fclient-commit Mailing List for fclient (Page 3)
Status: Pre-Alpha
Brought to you by:
jurner
You can subscribe to this list here.
2007 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(23) |
Nov
(54) |
Dec
|
---|---|---|---|---|---|---|---|---|---|---|---|---|
2008 |
Jan
(17) |
Feb
(209) |
Mar
(63) |
Apr
(31) |
May
(7) |
Jun
(39) |
Jul
(390) |
Aug
(122) |
Sep
(6) |
Oct
|
Nov
|
Dec
|
From: <jU...@us...> - 2008-08-16 08:22:08
|
Revision: 920 http://fclient.svn.sourceforge.net/fclient/?rev=920&view=rev Author: jUrner Date: 2008-08-16 08:22:18 +0000 (Sat, 16 Aug 2008) Log Message: ----------- no longer needed Removed Paths: ------------- trunk/fclient/fclient/impl/tpls/ViewRequestsWidgetTpl.ui Deleted: trunk/fclient/fclient/impl/tpls/ViewRequestsWidgetTpl.ui =================================================================== --- trunk/fclient/fclient/impl/tpls/ViewRequestsWidgetTpl.ui 2008-08-16 08:21:59 UTC (rev 919) +++ trunk/fclient/fclient/impl/tpls/ViewRequestsWidgetTpl.ui 2008-08-16 08:22:18 UTC (rev 920) @@ -1,35 +0,0 @@ -<ui version="4.0" > - <class>ViewRequestsWidget</class> - <widget class="QWidget" name="ViewRequestsWidget" > - <property name="geometry" > - <rect> - <x>0</x> - <y>0</y> - <width>400</width> - <height>300</height> - </rect> - </property> - <property name="windowTitle" > - <string>Form</string> - </property> - <layout class="QGridLayout" name="gridLayout" > - <property name="margin" > - <number>0</number> - </property> - <property name="spacing" > - <number>0</number> - </property> - <item row="0" column="0" > - <widget class="QTreeWidget" name="tree" > - <column> - <property name="text" > - <string>1</string> - </property> - </column> - </widget> - </item> - </layout> - </widget> - <resources/> - <connections/> -</ui> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jU...@us...> - 2008-08-16 08:21:49
|
Revision: 919 http://fclient.svn.sourceforge.net/fclient/?rev=919&view=rev Author: jUrner Date: 2008-08-16 08:21:59 +0000 (Sat, 16 Aug 2008) Log Message: ----------- no longer needed Removed Paths: ------------- trunk/fclient/fclient/impl/tpls/Ui_ViewRequestsWidgetTpl.py Deleted: trunk/fclient/fclient/impl/tpls/Ui_ViewRequestsWidgetTpl.py =================================================================== --- trunk/fclient/fclient/impl/tpls/Ui_ViewRequestsWidgetTpl.py 2008-08-16 08:20:07 UTC (rev 918) +++ trunk/fclient/fclient/impl/tpls/Ui_ViewRequestsWidgetTpl.py 2008-08-16 08:21:59 UTC (rev 919) @@ -1,40 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file '/home/me/src/fclient/trunk/fclient/fclient/impl/tpls/ViewRequestsWidgetTpl.ui' -# -# Created: Mon Aug 11 19:50:32 2008 -# by: PyQt4 UI code generator 4.4.3-snapshot-20080705 -# -# WARNING! All changes made in this file will be lost! - -from PyQt4 import QtCore, QtGui - -class Ui_ViewRequestsWidget(object): - def setupUi(self, ViewRequestsWidget): - ViewRequestsWidget.setObjectName("ViewRequestsWidget") - ViewRequestsWidget.resize(400, 300) - self.gridLayout = QtGui.QGridLayout(ViewRequestsWidget) - self.gridLayout.setMargin(0) - self.gridLayout.setSpacing(0) - self.gridLayout.setObjectName("gridLayout") - self.tree = QtGui.QTreeWidget(ViewRequestsWidget) - self.tree.setObjectName("tree") - self.gridLayout.addWidget(self.tree, 0, 0, 1, 1) - - self.retranslateUi(ViewRequestsWidget) - QtCore.QMetaObject.connectSlotsByName(ViewRequestsWidget) - - def retranslateUi(self, ViewRequestsWidget): - ViewRequestsWidget.setWindowTitle(QtGui.QApplication.translate("ViewRequestsWidget", "Form", None, QtGui.QApplication.UnicodeUTF8)) - self.tree.headerItem().setText(0, QtGui.QApplication.translate("ViewRequestsWidget", "1", None, QtGui.QApplication.UnicodeUTF8)) - - -if __name__ == "__main__": - import sys - app = QtGui.QApplication(sys.argv) - ViewRequestsWidget = QtGui.QWidget() - ui = Ui_ViewRequestsWidget() - ui.setupUi(ViewRequestsWidget) - ViewRequestsWidget.show() - sys.exit(app.exec_()) - This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jU...@us...> - 2008-08-16 08:19:59
|
Revision: 918 http://fclient.svn.sourceforge.net/fclient/?rev=918&view=rev Author: jUrner Date: 2008-08-16 08:20:07 +0000 (Sat, 16 Aug 2008) Log Message: ----------- no longer needed Removed Paths: ------------- trunk/fclient/fclient/impl/DlgDownloadKeyToDisk.py Deleted: trunk/fclient/fclient/impl/DlgDownloadKeyToDisk.py =================================================================== --- trunk/fclient/fclient/impl/DlgDownloadKeyToDisk.py 2008-08-16 08:19:24 UTC (rev 917) +++ trunk/fclient/fclient/impl/DlgDownloadKeyToDisk.py 2008-08-16 08:20:07 UTC (rev 918) @@ -1,146 +0,0 @@ -#*************************************************************************************** -#TODO: -# x. have to inject (..whatebver) a checkbox into msg box invalid key warning <x don't show this message again> -# x. save dialog pos/size on exit -# -#************************************************************************************* - -from __future__ import absolute_import -if __name__ == '__main__': # see --> http://bugs.python.org/issue1510172 . works only current dir and below - import os; __path__ = [os.path.dirname(__file__)] - -import os -from PyQt4 import QtCore, QtGui - -from . import config -from .lib import fcp2 - -from .tpls.Ui_DlgDownloadKeyToDiskTpl import Ui_DlgDownloadKeyToDisk -#********************************************************************************** -# -#********************************************************************************** -class Settings(config.SettingsBase): - _key_ = 'DlgDownloadKeyToDisk' - _settings_ = ( - ('Geometry', 'ByteArray', QtCore.QByteArray()), - ) - - -#********************************************************************************** -# -#********************************************************************************** -class DlgDownloadKeyToDisk(QtGui.QDialog, Ui_DlgDownloadKeyToDisk): - - IdEdKey = 'edKey' - IdEdFileName = 'edFileName' - IdEdDirectory = 'edDirectory' - IdBtChooseDirectory = 'btChooseDirectory' - - - def __init__(self, parent=None, fcpKey=None): - QtGui.QDialog.__init__(self, parent) - - self.setupUi(self) - self.setWindowTitle(config.FcAppName + self.trUtf8(' - Download key..')) - self.fcSettings = Settings(self).restore() - - self._fileName = None - self._fcpKey = fcpKey - - # setup key editbox - ed = self.controlById(self.IdEdKey) - if fcpKey is not None: - ed.setText(fcpKey.toString()) - - # setup filename editbox - ed = self.controlById(self.IdEdFileName) - if fcpKey is not None: - # find out fileName to dl key to - fileName = config.guessFileNameFromKey(self._fcpKey) - if fileName is None: - fileName = self.trUtf8('UNKNOWN') - ed.setText(fileName) - - # setup directory editbox - ed = self.controlById(self.IdEdDirectory) - ed.setText(unicode(config.fcSettings.value('DownloadDir'))) - bt = self.controlById(self.IdBtChooseDirectory) - self.connect(bt, QtCore.SIGNAL('clicked()'), self.onChooseDirectory) - - - self.restoreGeometry(self.fcSettings.value('Geometry')) - - ############################## - ## methods - ############################## - def controlById(self, idControl): - return getattr(self, idControl) - - def fileName(self): - return self._fileName - - def fcpKey(self): - return self._fcpKey - - ############################## - ## overwritten methods - ############################## - def accept(self): - edKey = self.controlById(self.IdEdKey) - edFileName = self.controlById(self.IdEdFileName) - edDirectory = self.controlById(self.IdEdDirectory) - - key = unicode(edKey.text()) - if not key: - return QtGui.QMessageBox.warning(self, self.windowTitle(), 'Please enter a key to download') - try: - self._fcpKey = fcp2.Key(key) - except fcp2.ErrorKey: - return QtGui.QMessageBox.warning(self, self.windowTitle(), 'Looks like the key entered is not valid') - - fileName = edFileName.text() - if fileName.isEmpty(): - return QtGui.QMessageBox.warning(self, self.windowTitle(), 'Please enter a filename for the key') - - directory = edDirectory.text() - if directory.isEmpty(): - return QtGui.QMessageBox.warning(self, self.windowTitle(), 'Please enter a directory under wich to save the key') - - self._fileName = os.path.join(unicode(directory), unicode(fileName)) - self.done(self.Accepted) - - ############################## - ## overwritten events - ############################## - def hideEvent(self, event): - self.fcSettings.setValues(Geometry=self.saveGeometry()) - - ############################## - ## event handlers - ############################## - def onChooseDirectory(self): - edDirectory = self.controlById(self.IdEdDirectory) - directory = QtGui.QFileDialog.getExistingDirectory( - self, - config.FcAppName + self.trUtf8(' - Download key to..'), - edDirectory.text(), - ) - if directory: - edDirectory.setText(directory) - -#********************************************************************************** -# -#********************************************************************************** -if __name__ == '__main__': - import sys - - app = QtGui.QApplication(sys.argv) - w = DlgDownloadKeyToDisk( - #None, - fcpKey=fcp2.KeyKSK('foo.txt') - ) - w.show() - res = app.exec_() - sys.exit(res) - - This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jU...@us...> - 2008-08-16 08:19:16
|
Revision: 917 http://fclient.svn.sourceforge.net/fclient/?rev=917&view=rev Author: jUrner Date: 2008-08-16 08:19:24 +0000 (Sat, 16 Aug 2008) Log Message: ----------- isolated uploads view Modified Paths: -------------- trunk/fclient/fclient/fclient.py Added Paths: ----------- trunk/fclient/fclient/impl/ViewUploads/ trunk/fclient/fclient/impl/ViewUploads/ViewUploads.py trunk/fclient/fclient/impl/ViewUploads/__init__.py trunk/fclient/fclient/impl/ViewUploads/_fix_mexec.py Removed Paths: ------------- trunk/fclient/fclient/impl/ViewUploads.py Modified: trunk/fclient/fclient/fclient.py =================================================================== --- trunk/fclient/fclient/fclient.py 2008-08-16 08:13:58 UTC (rev 916) +++ trunk/fclient/fclient/fclient.py 2008-08-16 08:19:24 UTC (rev 917) @@ -18,7 +18,7 @@ from .impl.ViewConnection import ViewConnection from .impl.ViewDownloads import ViewDownloads from .impl.ViewLogger import ViewLogger -from .impl.ViewUploads import ViewUploadsWidget +from .impl.ViewUploads import ViewUploads from .impl.DlgSingleAppError import DlgSingleAppError #************************************************************* @@ -79,7 +79,7 @@ ViewConnection.ViewConnectionWidget(mainWindow), ViewBrowser.ViewBrowserWidget(mainWindow), ViewDownloads.ViewDownloadsWidget(mainWindow), - ViewUploadsWidget(mainWindow), + ViewUploads.ViewUploadsWidget(mainWindow), ) viewWidget.addBottomViews(ViewLogger.ViewLoggerWidget(mainWindow)) Added: trunk/fclient/fclient/impl/ViewUploads/ViewUploads.py =================================================================== --- trunk/fclient/fclient/impl/ViewUploads/ViewUploads.py (rev 0) +++ trunk/fclient/fclient/impl/ViewUploads/ViewUploads.py 2008-08-16 08:19:24 UTC (rev 917) @@ -0,0 +1,181 @@ + +"""""" + +# some fixes for relative imports +# see --> [http://bugs.python.org/issue1510172] absolute/rellative import not working (works only current dir and below) +# see --> [http://mail.python.org/pipermail/python-ideas/2007-February/000232.html] PEP for executing a module in a +# ...package containing relative imports +from __future__ import absolute_import +if __name__ == '__main__': + import os + __path__ = [os.path.dirname(__file__)] + from ._fix_mexec import fix_mexec + fix_mexec(__name__, __file__) + del fix_mexec + + +from PyQt4 import QtCore, QtGui + +from .. import config +from ..BaseRequestsWidget import BaseRequestsWidget +#************************************************************************************ +# +#************************************************************************************ +class UploadsWidgetGlobalFeedback(config.GlobalFeedbackBase): + """wrapper for global statusbar widgets, menus""" + + def __init__(self, parent, idGlobalFeedback): + config.GlobalFeedbackBase.__init__(self, parent, idGlobalFeedback) + + # menus + self.menus = [] + if self.menuBar is not None and hasattr(parent, 'fcViewObject'): + menu = QtGui.QMenu(parent.fcViewObject.displayName, self.menuBar) + parent.populateMenu(menu) + self.menus.append(menu) + self.menuBar.addViewMenu(menu) + + # status bar widgets + self.labelStatus = None + self.progress = None + self.labelFeedbackWrap = None + #if self.statusBar is not None: + # self.labelStatus = QtGui.QLabel(QtCore.QString(), self.statusBar) + # self.statusBar.addWidget(self.labelStatus) + # + # self.progress = QtGui.QProgressBar(self.statusBar) + # self.progress.setRange(0, Browser.MaxProgress) + # self.progress.setValue(0) + # self.statusBar.addWidget(self.progress) + # + # label = QtGui.QLabel(self.statusBar) + # label.setFrameStyle(QtGui.QLabel.Sunken | QtGui.QLabel.Box) + # self.labelFeedbackWrap = pathlabelwrap.PathLabelWrap( + # label, + # path_module=config.CompactPathFcpKeyModule, + # ) + # self.statusBar.addWidget(self.labelFeedbackWrap.label, 1) + + + def setVisible(self, flag): + if self.menuBar is not None: + for menu in self.menus: + menu.children()[0].setEnabled(flag) + #if self.statusBar is not None: + # self.progress.setVisible(flag) + # self.labelStatus.setVisible(flag) + # self.labelFeedbackWrap.label.setVisible(flag) + + #def setProgress(self, n): + # if self.progress is not None: + # self.progress.setValue(n) + + #def setStatusMessage(self, qString): + # if self.labelStatus is not None: + # self.labelStatus.setText(qString) + + #def setFeedback(self, qString): + # if self.labelFeedbackWrap is not None: + # self.labelFeedbackWrap.setPath(unicode(qString)) + + + +class DownloadsViewObject(config.ViewObject): + + def __init__(self, parent): + config.ViewObject. __init__(self, parent) + + self.name=parent.objectName() + self.displayName=self.trUtf8('Uploads') + self.icon=QtGui.QIcon() + + +class UploadsWidgetSettings(config.SettingsBase): + + + _key_ = config.IdViewUploadsWidget + _settings_ = ( + ) + + +class ViewUploadsWidget(BaseRequestsWidget.RequestsWidget): + + def __init__(self, parent, idGlobalFeedback=config.IdMainWindow): + + self.menuRemoveGroup = None + + BaseRequestsWidget.RequestsWidget.__init__(self, parent) + + self.setObjectName(config.IdViewUploadsWidget) + config.ObjectRegistry.register(self) + self.fcSettings = UploadsWidgetSettings(self).restore() + self.fcViewObject = DownloadsViewObject(self) + self.fcGlobalFeedback = UploadsWidgetGlobalFeedback(self, idGlobalFeedback) + + # setup menus + self.menuRemoveGroup = QtGui.QMenu(self) + self.menuRemoveGroup.setTitle(self.trUtf8('Remove group')) + for action in self.fcActions['GroupRemoveGroup'].actions(): + self.menuRemoveGroup.addAction(action) + + + ################################### + ## overwritten methods + ################################### + def hideEvent(self, event): + self.fcGlobalFeedback.setVisible(False) + BaseRequestsWidget.RequestsWidget.hideEvent(self, event) + + def showEvent(self, event): + self.fcGlobalFeedback.setVisible(True) + BaseRequestsWidget.RequestsWidget.showEvent(self, event) + + def retranslateUi(self, parent): + BaseRequestsWidget.RequestsWidget.retranslateUi(self, parent) + if self.menuRemoveGroup is not None: + self.menuRemoveGroup.setTitle(self.trUtf8('Remove group')) + + ################################### + ## methods + ################################### + + ################################### + ## event handlers + ################################### + def onTreeCustomContextMenuRequested(self, pt): + tree = self.controlById(self.IdTree) + pt = tree.viewport().mapToGlobal(pt) + + menu = QtGui.QMenu(self) + menu.addMenu(self.menuRemoveGroup) + menu.exec_(pt) + + def onTreeItemSelectionChanged(self): + tree = self.controlById(self.IdTree) + hasSelectedItems = tree.selectionModel().hasSelection() + +#********************************************************************************** +# +#********************************************************************************** +if __name__ == '__main__': + import sys + from .. import View + from ..ViewConnection import ViewConnection + from ..ViewLogger import ViewLogger + from ..MainWindow import MainWindow + + app = QtGui.QApplication(sys.argv) + + mainWindow = MainWindow.MainWindow() + viewWidget = View.ViewWidget(mainWindow) + mainWindow.setCentralWidget(viewWidget) + + viewWidget.addTopViews( + ViewConnection.ViewConnectionWidget(None), + ViewUploadsWidget(None), + ) + viewWidget.addBottomViews(ViewLogger.ViewLoggerWidget(None)) + + mainWindow.show() + res = app.exec_() + sys.exit(res) \ No newline at end of file Added: trunk/fclient/fclient/impl/ViewUploads/__init__.py =================================================================== --- trunk/fclient/fclient/impl/ViewUploads/__init__.py (rev 0) +++ trunk/fclient/fclient/impl/ViewUploads/__init__.py 2008-08-16 08:19:24 UTC (rev 917) @@ -0,0 +1 @@ + Added: trunk/fclient/fclient/impl/ViewUploads/_fix_mexec.py =================================================================== --- trunk/fclient/fclient/impl/ViewUploads/_fix_mexec.py (rev 0) +++ trunk/fclient/fclient/impl/ViewUploads/_fix_mexec.py 2008-08-16 08:19:24 UTC (rev 917) @@ -0,0 +1,93 @@ +'''python 2.5 relative impports are srsly broken ..fix this to make relative imports work +when executing a module as main (-m), including relative imports up to the root package + +see: [http://mail.python.org/pipermail/python-ideas/2007-February/000232.html] + +@note: root package is the highest available package in the package hirarchy. +don't look at __name__ too closely. it gets adjusted for a module to just "do the right +thing" in __name__ == '__main__' comparisons. + +usage:: + + # place this at the top a module, before doing any relative imports + from fix_mexec import fix_mexec + fix_mexec(__name__, __file__) + del fix_mexec + + from ...foo import bar + + + +##<-- copy and paste code, assuming _fix_mexec resides in the current dir.. + +# some fixes for relative imports +# see --> [http://bugs.python.org/issue1510172] absolute/rellative import not working (works only current dir and below) +# see --> [http://mail.python.org/pipermail/python-ideas/2007-February/000232.html] PEP for executing a module in a +# ...package containing relative imports +from __future__ import absolute_import +if __name__ == '__main__': + import os + __path__ = [os.path.dirname(__file__)] + from ._fix_mexec import fix_mexec + fix_mexec(__name__, __file__) + del fix_mexec + + +##--> copy and paste code +''' + +import imp, os, sys +#******************************************************************************** +# +#******************************************************************************** +class MainName(str): + def __eq__(self, other): + if other == '__main__': return True + return str.__eq__(self, other) + def __ne__(self, other): + if other == '__main__': return False + return str.__ne__(self, other) + + +def fix_mexec(_name_, _file_): + """bugfix for relative imports not working + @param _name_: __name__ of the module + @param _file_: __file__ of the module + + @note: not complete: relies on __init__.py, .pyo (...) is ignored currently + """ + if _name_ == '__main__': + out = [] + # find allparent packages + p = os.path.dirname(os.path.abspath(_file_)) + prev = p + while True: + pkg = os.path.join(p, '__init__.py') + if os.path.isfile(pkg): + out.append([pkg, os.path.basename(p)]) + else: + break + prev = p + p = os.path.dirname(p) + if p == prev: + break + out.reverse() + + # adjust sub package names an import parent modules + name = None + for n, (fpath, name) in enumerate(out): + if n > 0: + name = out[n][1] = out[n -1][1] + '.' + out[n][1] + m = imp.load_source(name, fpath) + m.__path__ = [os.path.dirname(fpath)] + + # adjust name of the __main__ module + if name is not None: + m = sys.modules.pop('__main__') + # 'foo.bar..__main__' does not work for some reason. 'foo.bar' seems to work as expected + ##m.__name__ = _Name_(name + '.' + '__main__') + m.__name__ = MainName(name) + sys.modules[m.__name__] = m + + + Deleted: trunk/fclient/fclient/impl/ViewUploads.py =================================================================== --- trunk/fclient/fclient/impl/ViewUploads.py 2008-08-16 08:13:58 UTC (rev 916) +++ trunk/fclient/fclient/impl/ViewUploads.py 2008-08-16 08:19:24 UTC (rev 917) @@ -1,173 +0,0 @@ - -"""""" - -from __future__ import absolute_import -if __name__ == '__main__': # see --> http://bugs.python.org/issue1510172 . works only current dir and below - import os; __path__ = [os.path.dirname(__file__)] - - -from PyQt4 import QtCore, QtGui - -from . import config -from .BaseRequestsWidget import RequestsWidget -#************************************************************************************ -# -#************************************************************************************ -class UploadsWidgetGlobalFeedback(config.GlobalFeedbackBase): - """wrapper for global statusbar widgets, menus""" - - def __init__(self, parent, idGlobalFeedback): - config.GlobalFeedbackBase.__init__(self, parent, idGlobalFeedback) - - # menus - self.menus = [] - if self.menuBar is not None and hasattr(parent, 'fcViewObject'): - menu = QtGui.QMenu(parent.fcViewObject.displayName, self.menuBar) - parent.populateMenu(menu) - self.menus.append(menu) - self.menuBar.addViewMenu(menu) - - # status bar widgets - self.labelStatus = None - self.progress = None - self.labelFeedbackWrap = None - #if self.statusBar is not None: - # self.labelStatus = QtGui.QLabel(QtCore.QString(), self.statusBar) - # self.statusBar.addWidget(self.labelStatus) - # - # self.progress = QtGui.QProgressBar(self.statusBar) - # self.progress.setRange(0, Browser.MaxProgress) - # self.progress.setValue(0) - # self.statusBar.addWidget(self.progress) - # - # label = QtGui.QLabel(self.statusBar) - # label.setFrameStyle(QtGui.QLabel.Sunken | QtGui.QLabel.Box) - # self.labelFeedbackWrap = pathlabelwrap.PathLabelWrap( - # label, - # path_module=config.CompactPathFcpKeyModule, - # ) - # self.statusBar.addWidget(self.labelFeedbackWrap.label, 1) - - - def setVisible(self, flag): - if self.menuBar is not None: - for menu in self.menus: - menu.children()[0].setEnabled(flag) - #if self.statusBar is not None: - # self.progress.setVisible(flag) - # self.labelStatus.setVisible(flag) - # self.labelFeedbackWrap.label.setVisible(flag) - - #def setProgress(self, n): - # if self.progress is not None: - # self.progress.setValue(n) - - #def setStatusMessage(self, qString): - # if self.labelStatus is not None: - # self.labelStatus.setText(qString) - - #def setFeedback(self, qString): - # if self.labelFeedbackWrap is not None: - # self.labelFeedbackWrap.setPath(unicode(qString)) - - - -class DownloadsViewObject(config.ViewObject): - - def __init__(self, parent): - config.ViewObject. __init__(self, parent) - - self.name=parent.objectName() - self.displayName=self.trUtf8('Uploads') - self.icon=QtGui.QIcon() - - -class UploadsWidgetSettings(config.SettingsBase): - - - _key_ = config.IdViewUploadsWidget - _settings_ = ( - ) - - -class ViewUploadsWidget(RequestsWidget): - - def __init__(self, parent, idGlobalFeedback=config.IdMainWindow): - - self.menuRemoveGroup = None - - RequestsWidget.__init__(self, parent) - - self.setObjectName(config.IdViewUploadsWidget) - config.ObjectRegistry.register(self) - self.fcSettings = UploadsWidgetSettings(self).restore() - self.fcViewObject = DownloadsViewObject(self) - self.fcGlobalFeedback = UploadsWidgetGlobalFeedback(self, idGlobalFeedback) - - # setup menus - self.menuRemoveGroup = QtGui.QMenu(self) - self.menuRemoveGroup.setTitle(self.trUtf8('Remove group')) - for action in self.fcActions['GroupRemoveGroup'].actions(): - self.menuRemoveGroup.addAction(action) - - - ################################### - ## overwritten methods - ################################### - def hideEvent(self, event): - self.fcGlobalFeedback.setVisible(False) - RequestsWidget.hideEvent(self, event) - - def showEvent(self, event): - self.fcGlobalFeedback.setVisible(True) - RequestsWidget.showEvent(self, event) - - def retranslateUi(self, parent): - RequestsWidget.retranslateUi(self, parent) - if self.menuRemoveGroup is not None: - self.menuRemoveGroup.setTitle(self.trUtf8('Remove group')) - - ################################### - ## methods - ################################### - - ################################### - ## event handlers - ################################### - def onTreeCustomContextMenuRequested(self, pt): - tree = self.controlById(self.IdTree) - pt = tree.viewport().mapToGlobal(pt) - - menu = QtGui.QMenu(self) - menu.addMenu(self.menuRemoveGroup) - menu.exec_(pt) - - def onTreeItemSelectionChanged(self): - tree = self.controlById(self.IdTree) - hasSelectedItems = tree.selectionModel().hasSelection() - -#********************************************************************************** -# -#********************************************************************************** -if __name__ == '__main__': - import sys - from . import View - from . import ViewConnection - from . import ViewLogger - from . import MainWindow - - app = QtGui.QApplication(sys.argv) - - mainWindow = MainWindow.MainWindow() - viewWidget = View.ViewWidget(mainWindow) - mainWindow.setCentralWidget(viewWidget) - - viewWidget.addTopViews( - ViewConnection.ViewConnectionWidget(None), - ViewUploadsWidget(None), - ) - viewWidget.addBottomViews(ViewLogger.ViewLoggerWidget(None)) - - mainWindow.show() - res = app.exec_() - sys.exit(res) \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jU...@us...> - 2008-08-16 08:13:49
|
Revision: 916 http://fclient.svn.sourceforge.net/fclient/?rev=916&view=rev Author: jUrner Date: 2008-08-16 08:13:58 +0000 (Sat, 16 Aug 2008) Log Message: ----------- fixes for downloads widget Modified Paths: -------------- trunk/fclient/fclient/impl/ViewDownloads/ViewDownloads.py Removed Paths: ------------- trunk/fclient/fclient/impl/BaseRequestsWidget.py Deleted: trunk/fclient/fclient/impl/BaseRequestsWidget.py =================================================================== --- trunk/fclient/fclient/impl/BaseRequestsWidget.py 2008-08-16 08:10:49 UTC (rev 915) +++ trunk/fclient/fclient/impl/BaseRequestsWidget.py 2008-08-16 08:13:58 UTC (rev 916) @@ -1,554 +0,0 @@ - -#************************************************************************************************************** -#TODO: -# -# x. prtty tricky to get dls right when the node or client may disconnect unexpectedly -# problem: dls that we send and that have not reached the node -# problem: what to do when the user wants to quit and we still have dls to push to the node -# -# solution would require keeping track of all requests -# a. keep identifiers of requests that reached the node (have to do it anyways) -# b. keep track of requests ahead of sending them to the node (feels not too good doubeling downloads.dat.gz) -# -# best idea seems to be to ignore the problem -# 1. wait till (if ever) freenet devels fdrop node keeping track of client requests -# -# 2. a box thrown to the user (x. do not show this message again) to inform him about pendings -# should be enough. maybe along with a separate widget or some separate color code for pendings -# -# x. performance -# start with a standard model and improve it over time. no need to set any hard -# limits. the user will find out by himself how many dls his machine can handle. -# have to be carefrul though when adding dls, like from a *.frdx to provide appropriate -# warnings -# x. it may take a while untill the final DataFound message arrives when a request is % completed. feedback would be nice -# x. DataFound for a request the file has been removed by the user. no idea what happens. have to test this -# x. when the node is about to start up, looks like persistents may arrive or not. check -# x. how to get early information about mimetype/size? maybe use FcpClient.getFileInfo() -# x. show/hide header izems -# x. sort by header -# x. indicate over all time / dl speed -# x. indicate status / remove items by status -# x. item properties -# x. how to handle inserting huge number of dls? -# idea: insert with lowest priority to get the node to know them, increase priority when a slot in -# MaxSimultaneousDls (if set) is free. atatch progressBar no sooner as priority > MinDlPriority -# x. how to handle huge numbers of dls. the node will flood us on startup with persistents. looks -# like the only way to control the flood is to have one connection/dl. maybe wait for freenet devels -# to realize that this is a serious problem... -# x. byte amount postfixes must be transllated ++ use Kib or Kb or let the user decide? -# x. sometimes groups of dls get not removed -#************************************************************************************************************** -from __future__ import absolute_import -if __name__ == '__main__': # see --> http://bugs.python.org/issue1510172 . works only current dir and below - import os; __path__ = [os.path.dirname(__file__)] - -import mimetypes -import os -from PyQt4 import QtCore, QtGui - -from . import config -from .lib import fcp2 -from .lib.fcp2.lib import pmstruct -from .lib.qt4ex import treewidgetwrap -from .lib import numbers - -from . import DlgDownloadKeyToDisk - -from .tpls.Ui_ViewRequestsWidgetTpl import Ui_ViewRequestsWidget -#********************************************************************************** -# -#********************************************************************************** -BLOCK_SIZE = 32768 # from CHKBlock.java - -#********************************************************************************** -# -#********************************************************************************** -class PersistentRequestData(pmstruct.PMStruct): - _fields_ = ( - ('ClientName', pmstruct.STRING), - ) - -#********************************************************************************** -# -#********************************************************************************** -class TreeItem(QtGui.QTreeWidgetItem): - - IndexName = 0 - IndexSize = 1 - IndexMimeType = 2 - IndexStatus = 3 - IndexProgress = 4 - IndexPriority = 5 - IndexElapsed = 6 - - ProgressBarName = 'downloadKey' - - StatusPending = 'pending' - StatusLoading = 'loading' - StatusComplete = 'complete' - StatusError = 'error' - StatusRemoved = 'removed' - StatusCompressing = 'compressing' - ##StatusCompressed = 'compressed' #TODO: no way to distinguish compressed an loading - - def __init__(self, fcpRequest, *params): - QtGui.QTreeWidgetItem.__init__(self, *params) - self.fcpRequest = fcpRequest - self.fcOldStatus = self.StatusPending - - def status(self): - if self.fcpRequest is None: - return self.StatusRemoved - elif self.fcpRequest['RequestStatus'] & fcp2.ConstRequestStatus.Success: - return self.StatusComplete - elif self.fcpRequest['RequestStatus'] & fcp2.ConstRequestStatus.Error: - return self.StatusError - - #TODO: more or less aguess ..have to check this in detail - elif self.fcpRequest['RequestStatus'] & fcp2.ConstRequestStatus.Started: - if self.fcpRequest['RequestStatus'] & fcp2.ConstRequestStatus.Compressing: - if self.fcpRequest['RequestStatus'] & fcp2.ConstRequestStatus.Compressed: - return self.StatusLoading - else: - return self.compressing - else: - return self.StatusLoading - else: - return self.StatusPending - -# exposes status property for stylesheets -class ProgressBar(QtGui.QProgressBar): - - def __init__(self, parent, item): - QtGui.QProgressBar.__init__(self, parent) - self.item = item - - def _get_status(self): - return self.item.status() - status= QtCore.pyqtProperty("QString", _get_status) - - -class RequestsWidgetActions(config.ActionsBase): - - def __init__(self, parent): - config.ActionsBase.__init__(self, parent) - - self.action( - name='ActionDownloadKeyToDisk', - text=self.trUtf8('Download &key...'), - trigger=parent.onDlgDownloadKey, - ) - self.action( - name='ActionRemoveSelectedDownloads', - text=self.trUtf8('Remove download'), - trigger=parent.onRemoveSelectedDownloads, - isEnabled=False, - ) - self.action( - name='ActionRestartSelectedDownloads', - text=self.trUtf8('Restart download'), - trigger=parent.onRestartSelectedDownloads, - isEnabled=False, - ) - - #TODO: enable/disable if items of that type are available? - group = self.group( - name='GroupRemoveGroup', - trigger=parent.onRemoveGroup, - ) - self.action( - name='ActionRemoveFailed', - group=group, - text=self.trUtf8('Failed'), - isEnabled=False, - ) - self.action( - name='ActionRemoveCompleted', - group=group, - text=self.trUtf8('Completed'), - isEnabled=False, - ) - -#********************************************************************************** -# -#********************************************************************************** -class RequestsWidget(QtGui.QWidget, Ui_ViewRequestsWidget): - - IdTree = 'tree' - - def __init__(self, parent, idGlobalFeedback=config.IdMainWindow): - QtGui.QWidget.__init__(self, parent) - self._isCreated = False - self.fcHeaderLabels = {} # fcpIdentifier --> treeItem - self.fcActions = RequestsWidgetActions(self) - self.fcpRequests = {} - self.fcRequestStatusNames = {} - self.menuRemoveGroup = QtGui.QMenu(self) - - self.setupUi(self) - self.fcpClientEvents = ( - (config.fcpClient.events.ClientConnected, self.onFcpClientConnected), - (config.fcpClient.events.ClientDisconnected, self.onFcpClientDisconnected), - (config.fcpClient.events.ConfigData, self.onFcpConfigData), - (config.fcpClient.events.RequestCompleted, self.onFcpClientRequestCompleted), - (config.fcpClient.events.RequestFailed, self.onFcpClientRequestFailed), - (config.fcpClient.events.RequestModified, self.onFcpClientRequestModified), - (config.fcpClient.events.RequestProgress, self.onFcpClientRequestProgress), - (config.fcpClient.events.RequestStarted, self.onFcpClientRequestStarted), - (config.fcpClient.events.RequestRemoved, self.onFcpClientRequestRemoved), - (config.fcpClient.events.RequestCompressionStarted, self.onFcpClientRequestCompressionStarted), - (config.fcpClient.events.RequestCompressionCompleted, self.onFcpClientRequestCompressionCompleted), - ) - config.fcpClient.events += self.fcpClientEvents - - - ############################ - ## private methods - ############################ - def _adjustItemStatus(self, item): - # to take Css styling into account we have to set a new statusBar for each state change - tree = self.controlById(self.IdTree) - oldProgressBar = progressBar = self.tree.itemWidget(item, TreeItem.IndexProgress) - itemStatus = item.status() - itemStatusChanged = itemStatus != item.fcOldStatus - if itemStatusChanged: - progressBar = ProgressBar(self.tree, item) - - # adjust statusBar and set a new one if necessary - # ..bit much work here, but necessary, cos Fcp might come up with - # ..a completed message without any prior progress notifications - if itemStatus == TreeItem.StatusPending: - progressBar.setRange(0, 0) - elif itemStatus == TreeItem.StatusLoading: - progressBar.setRange(0, item.fcpRequest['ProgressRequired']) - progressBar.setValue(item.fcpRequest['ProgressSucceeded']) - elif itemStatus == TreeItem.StatusComplete: - progressBar.setRange(0, 1) - progressBar.setValue(progressBar.maximum()) - elif itemStatus == TreeItem.StatusError: - progressBar.setMinimum(oldProgressBar.minimum()) - progressBar.setMaximum(oldProgressBar.maximum()) - progressBar.setValue(oldProgressBar.value()) - elif itemStatus == TreeItem.StatusRemoved: - pass - elif itemStatus == TreeItem.StatusCompressing: - progressBar.setRange(0, 0) - else: - raise ValueError('Unknown status: %r' % itemStatus) - if itemStatusChanged: - progressBar.setObjectName(TreeItem.ProgressBarName) - tree.setItemWidget(item, TreeItem.IndexProgress, progressBar) - item.setData( - TreeItem.IndexStatus, - QtCore.Qt.DisplayRole, - QtCore.QVariant(self.fcRequestStatusNames[itemStatus]), - ) - item.fcOldStatus = itemStatus - - ############################ - ## - ############################ - def retranslateUi(self, parent): - Ui_ViewRequestsWidget.retranslateUi(self, parent) - tree = self.controlById(self.IdTree) - root = tree.invisibleRootItem() - - # adjust header labels - self.fcHeaderLabels = { - TreeItem.IndexName: self.trUtf8('Name'), - TreeItem.IndexSize: self.trUtf8('Size'), - TreeItem.IndexMimeType: self.trUtf8('MimeType'), - TreeItem.IndexStatus: self.trUtf8('Status'), - TreeItem.IndexPriority: self.trUtf8('Priority'), - TreeItem.IndexProgress: self.trUtf8('Progress'), - TreeItem.IndexElapsed: self.trUtf8('Elapsed'), - } - tree.setHeaderLabels([i[1] for i in sorted(self.fcHeaderLabels.items())]) - - # adjust status names and retranslate all items - self.fcRequestStatusNames = { - TreeItem.StatusPending: self.trUtf8('Pending'), - TreeItem.StatusLoading: self.trUtf8('Loading'), - TreeItem.StatusComplete: self.trUtf8('Complete'), - TreeItem.StatusError: self.trUtf8('Error'), - TreeItem.StatusRemoved: self.trUtf8('Removed'), - TreeItem.StatusCompressing: self.trUtf8('Compressing'), - ##TreeItem.StatusCompressed: self.trUtf8('Compressed'), #TODO: no way to distinguish compressed an loading - } - for item in treewidgetwrap.walkItem(root): - fcpRequest = getattr(item, 'fcpRequest', None) - if hasattr(item, 'fcpRequest'): - item.setText(TreeItem.IndexStatus, self.fcRequestStatusNames[item.status()]) - - # others - self.menuRemoveGroup.setTitle(self.trUtf8('Remove group')) - - def closeEvent(self): - self.viewClose() - - def hideEvent(self, event): - self.fcGlobalFeedback.setVisible(False) - - def showEvent(self, event): - self.fcGlobalFeedback.setVisible(True) - if not self._isCreated: - self._isCreated = True - - # setup tree - tree = self.controlById(self.IdTree) - tree.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) - tree.setRootIsDecorated(False) - tree.setSelectionMode(tree.ExtendedSelection) - tree.setUniformRowHeights(True) - self.connect(tree, QtCore.SIGNAL('customContextMenuRequested(const QPoint &)'), self.onTreeCustomContextMenuRequested) - self.connect(tree, QtCore.SIGNAL('itemSelectionChanged() '), self.onTreeItemSelectionChanged) - - def viewClose(self): - config.fcpClient.events -= self.fcpClientEvents - - ######################################### - ## methods - ######################################### - #TODO: much... - def addFcpRequest(self, fcpRequest): - """ - @note: if you add a newly created request, make shure to set the requests PersistentUserData - to the result of the call to L{persistentFcpRequestData} - """ - tree = self.controlById(self.IdTree) - root = tree.invisibleRootItem() - item= TreeItem(fcpRequest, root) - progressBar = ProgressBar(self.tree, item) - - progressBar.setObjectName(TreeItem.ProgressBarName) - tree.setItemWidget(item, TreeItem.IndexProgress, progressBar) - fileName = fcpRequest['Filename'] - mimeType = mimetypes.guess_type(fileName)[0] - icon = config.fcResources.getIcon( - config.mimeTypeIconName(mimeType), - config.fcSettings.value('IconSize'), - config.fcSettings.value('IconTheme'), - ) - item.setIcon(0, icon) - item.setData( - TreeItem.IndexName, - QtCore.Qt.DisplayRole, - QtCore.QVariant(os.path.basename(fcpRequest['Filename'])) - ) - - #TODO: take a wild guess at the size. no other way to do it currently - estimatedSize = int((BLOCK_SIZE * fcpRequest['ProgressRequired']) + 1) - item.setData( - TreeItem.IndexSize, - QtCore.Qt.DisplayRole, - QtCore.QVariant(self.trUtf8('< ') + numbers.format_num_bytes(estimatedSize)), - ) - - self.fcpRequests[fcpRequest['Identifier']] = item - self._adjustItemStatus(item) - return item - - self.fcpRequests[fcpRequest['Identifier']] = item - self._adjustItemStatus(item) - return item - - - def controlById(idGlobalFeedback, idControl): - return getattr(idGlobalFeedback, idControl) - - # overwrite - def populateMenu(self, menu): - return menu - - def execDlgDownloadKey(self, fcpKey=None): - """pops up the dialog to allow the user to download a key to disk - @param fcpKey: key to initialize the key with or None - """ - dlg = DlgDownloadKeyToDisk.DlgDownloadKeyToDisk(self, fcpKey=fcpKey) - if dlg.exec_() == dlg.Accepted: - self.downloadFile( - dlg.fcpKey(), - dlg.fileName(), - persistence=fcp2.ConstPersistence.Forever, - handleFilenameCollision=True, - ) - - def persistentFcpRequestData(self): - return PersistentRequestData(ClientName=unicode(self.objectName())).dump() - - ######################################### - ## event handlers - ######################################### - def onDlgDownloadKey(self, action): - self.execDlgDownloadKey(fcpKey=None) - - def onRemoveSelectedDownloads(self, action): - tree = self.controlById(self.IdTree) - selectedItems = tree.selectedItems() - - # remove items - for item in selectedItems: - parent = item.parent() - if parent is None: - parent = tree.invisibleRootItem() - parent.removeChild(item) - - # cancel all requests - for item in selectedItems: - for tmp_item in treewidgetwrap.walkItem(item): - if tmp_item.fcpRequest is not None: # we may come across the same item multiple times - if tmp_item.fcpRequest['Identifier'] in self.fcpRequests: #TODO: should never be False?! check - del self.fcpRequests[tmp_item.fcpRequest['Identifier']] - config.fcpClient.removeRequest(tmp_item.fcpRequest) - tmp_item.fcpRequest = None - - def onRestartSelectedDownloads(self, action): - tree = self.controlById(self.IdTree) - for item in tree.selectedItems(): - if item.fcpRequest is None: - raise RuntimeError('fcpRequest is None. should not happen') - del self.fcpRequests[item.fcpRequest['Identifier']] - item.fcpRequest = config.fcpClient.resendRequest(item.fcpRequest) - self.fcpRequests[item.fcpRequest['Identifier']] = item - self._adjustItemStatus(item) - - def onRemoveGroup(self, action): - tree = self.controlById(self.IdTree) - root = tree.invisibleRootItem() - - if action == self.fcActions['ActionRemoveCompleted']: - flag = fcp2.ConstRequestStatus.Success - elif action == self.fcActions['ActionRemoveFailed']: - flag = fcp2.ConstRequestStatus.Error - else: - raise ValueError('Not implemented') - - for item in treewidgetwrap.walkItem(root, topdown=False): - fcpRequest = getattr(item, 'fcpRequest', None) - if fcpRequest is not None: - if fcpRequest['Identifier'] in self.fcpRequests: #TODO: should never be False?! check - del self.fcpRequests[fcpRequest['Identifier']] - - if fcpRequest['RequestStatus'] & fcp2.ConstRequestStatus.Removed: - pass - elif not fcpRequest['RequestStatus'] & flag: - continue - else: - item.fcpRequest = None - config.fcpClient.removeRequest(fcpRequest) - parent = item.parent() - if parent is None: - parent = root - parent.removeChild(item) - - - # overwrite - def onTreeCustomContextMenuRequested(self, pt): - pass - - # overwrite - def onTreeItemSelectionChanged(self): - pass - - ######################################### - ## fcp event handlers - ######################################### - def onFcpClientConnected(self, event, msg): - for action in self.fcActions: - action.setEnabled(True) - - - def onFcpClientDisconnected(self, event, msg): - for action in self.fcActions: - action.setEnabled(False) - - def onFcpConfigData(self, fcpEvent, fcpRequest): - pass - - - def onFcpClientRequestCompleted(self, fcpEvent, fcpRequest): - item = self.fcpRequests.get(fcpRequest['Identifier'], None) - if item is not None: - mimeType = fcpRequest['MetadataContentType'] - item.setData( - TreeItem.IndexSize, - QtCore.Qt.DisplayRole, - QtCore.QVariant(numbers.format_num_bytes(fcpRequest['MetadataSize'])) - ) - item.setData( - TreeItem.IndexMimeType, - QtCore.Qt.DisplayRole, - QtCore.QVariant(mimeType) - ) - icon = config.fcResources.getIcon( - config.mimeTypeIconName(mimeType), - config.fcSettings.value('IconSize'), - config.fcSettings.value('IconTheme'), - ) - item.setIcon(0, icon) - self._adjustItemStatus(item) - - def onFcpClientRequestCompressionStarted(self, fcpEvent, fcpRequest): - item = self.fcpRequests.get(fcpRequest['Identifier'], None) - if item is not None: - self._adjustItemStatus(item) - - def onFcpClientRequestCompressionCompleted(self, fcpEvent, fcpRequest): - item = self.fcpRequests.get(fcpRequest['Identifier'], None) - if item is not None: - self._adjustItemStatus(item) - - def onFcpClientRequestFailed(self, fcpEvent, fcpRequest): - item = self.fcpRequests.get(fcpRequest['Identifier'], None) - if item is not None: - self._adjustItemStatus(item) - - #TODO: not tested - def onFcpClientRequestModified(self, fcpEvent, fcpRequest): - - requestIdentifier = fcpRequest['Modified'].get(fcp2.ConstRequestModified.Identifier, None) - if requestIdentifier is None: - requestIdentifier = fcpRequest['Identifier'] - item = self.fcpRequests.get(requestIdentifier, None) - - if item is not None: - if fcp2.ConstRequestModified.Identifier in fcpRequest['Modified']: - newFcpIdentifier = fcpRequest['Identifier'] - del self.fcpRequests[requestIdentifier] - self.fcpRequests[newFcpIdentifier] = item - - if fcp2.ConstRequestModified.Filename in fcpRequest['Modified']: - item.setData( - TreeItem.IndexName, - QtCore.Qt.DisplayRole, - QtCore.QVariant(os.path.basename(fcpRequest['Filename'])) - ) - - - def onFcpClientRequestProgress(self, fcpEvent, fcpRequest): - item = self.fcpRequests.get(fcpRequest['Identifier'], None) - if item is not None: - self._adjustItemStatus(item) - - def onFcpClientRequestRemoved(self, fcpEvent, fcpRequest): - pass - - def onFcpClientRequestStarted(self, fcpEvent, fcpRequest): - if fcpRequest['RequestStatus'] & fcp2.ConstRequestStatus.Restored: - try: - requestData = PersistentRequestData.load(fcpRequest['PersistentUserData']) - except pmstruct.PMStructError: - pass - else: - if requestData.get('ClientName', None) == self.objectName(): - item = self.addFcpRequest(fcpRequest) - else: - item = self.fcpRequests.get(fcpRequest['Identifier'], None) - if item is not None: - self._adjustItemStatus(item) - - -#********************************************************************************** -# -#********************************************************************************** Modified: trunk/fclient/fclient/impl/ViewDownloads/ViewDownloads.py =================================================================== --- trunk/fclient/fclient/impl/ViewDownloads/ViewDownloads.py 2008-08-16 08:10:49 UTC (rev 915) +++ trunk/fclient/fclient/impl/ViewDownloads/ViewDownloads.py 2008-08-16 08:13:58 UTC (rev 916) @@ -16,7 +16,7 @@ from PyQt4 import QtCore, QtGui from .. import config -from ..BaseRequestsWidget import RequestsWidget +from ..BaseRequestsWidget import BaseRequestsWidget #************************************************************************************ # #************************************************************************************ @@ -98,13 +98,13 @@ ) -class ViewDownloadsWidget(RequestsWidget): +class ViewDownloadsWidget(BaseRequestsWidget.RequestsWidget): def __init__(self, parent, idGlobalFeedback=config.IdMainWindow): self.menuRemoveGroup = None - RequestsWidget.__init__(self, parent) + BaseRequestsWidget.RequestsWidget.__init__(self, parent) self.setObjectName(config.IdViewDownloadsWidget) config.ObjectRegistry.register(self) @@ -124,18 +124,18 @@ ################################### def hideEvent(self, event): self.fcGlobalFeedback.setVisible(False) - RequestsWidget.hideEvent(self, event) + BaseRequestsWidget.RequestsWidget.hideEvent(self, event) def showEvent(self, event): self.fcGlobalFeedback.setVisible(True) - RequestsWidget.showEvent(self, event) + BaseRequestsWidget.RequestsWidget.showEvent(self, event) def populateMenu(self, menu): menu.addAction(self.fcActions['ActionDownloadKeyToDisk']) return menu def retranslateUi(self, parent): - RequestsWidget.retranslateUi(self, parent) + BaseRequestsWidget.RequestsWidget.retranslateUi(self, parent) if self.menuRemoveGroup is not None: self.menuRemoveGroup.setTitle(self.trUtf8('Remove group')) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jU...@us...> - 2008-08-16 08:10:41
|
Revision: 915 http://fclient.svn.sourceforge.net/fclient/?rev=915&view=rev Author: jUrner Date: 2008-08-16 08:10:49 +0000 (Sat, 16 Aug 2008) Log Message: ----------- isolated downloads view Modified Paths: -------------- trunk/fclient/fclient/fclient.py Added Paths: ----------- trunk/fclient/fclient/impl/BaseRequestsWidget/ trunk/fclient/fclient/impl/BaseRequestsWidget/BaseRequestsWidget.py trunk/fclient/fclient/impl/BaseRequestsWidget/RequestsWidget.ui trunk/fclient/fclient/impl/BaseRequestsWidget/Ui_RequestsWidget.py trunk/fclient/fclient/impl/BaseRequestsWidget/__init__.py trunk/fclient/fclient/impl/BaseRequestsWidget/_fix_mexec.py trunk/fclient/fclient/impl/BaseRequestsWidget/dlgs/ trunk/fclient/fclient/impl/BaseRequestsWidget/dlgs/DlgDownloadKeyToDisk.py trunk/fclient/fclient/impl/BaseRequestsWidget/dlgs/DlgDownloadKeyToDiskTpl.ui trunk/fclient/fclient/impl/BaseRequestsWidget/dlgs/Ui_DlgDownloadKeyToDiskTpl.py trunk/fclient/fclient/impl/BaseRequestsWidget/dlgs/__init__.py trunk/fclient/fclient/impl/BaseRequestsWidget/dlgs/_fix_mexec.py trunk/fclient/fclient/impl/ViewDownloads/ trunk/fclient/fclient/impl/ViewDownloads/ViewDownloads.py trunk/fclient/fclient/impl/ViewDownloads/__init__.py trunk/fclient/fclient/impl/ViewDownloads/_fix_mexec.py Removed Paths: ------------- trunk/fclient/fclient/impl/ViewDownloads.py trunk/fclient/fclient/impl/tpls/DlgDownloadKeyToDiskTpl.ui trunk/fclient/fclient/impl/tpls/Ui_DlgDownloadKeyToDiskTpl.py trunk/fclient/fclient/impl/tpls/Ui_SideBarLoadDetailsTpl.py Modified: trunk/fclient/fclient/fclient.py =================================================================== --- trunk/fclient/fclient/fclient.py 2008-08-16 08:01:13 UTC (rev 914) +++ trunk/fclient/fclient/fclient.py 2008-08-16 08:10:49 UTC (rev 915) @@ -16,7 +16,7 @@ from .impl.View import ViewWidget from .impl.ViewBrowser import ViewBrowser from .impl.ViewConnection import ViewConnection -from .impl.ViewDownloads import ViewDownloadsWidget +from .impl.ViewDownloads import ViewDownloads from .impl.ViewLogger import ViewLogger from .impl.ViewUploads import ViewUploadsWidget @@ -78,7 +78,7 @@ viewWidget.addTopViews( ViewConnection.ViewConnectionWidget(mainWindow), ViewBrowser.ViewBrowserWidget(mainWindow), - ViewDownloadsWidget(mainWindow), + ViewDownloads.ViewDownloadsWidget(mainWindow), ViewUploadsWidget(mainWindow), ) viewWidget.addBottomViews(ViewLogger.ViewLoggerWidget(mainWindow)) Added: trunk/fclient/fclient/impl/BaseRequestsWidget/BaseRequestsWidget.py =================================================================== --- trunk/fclient/fclient/impl/BaseRequestsWidget/BaseRequestsWidget.py (rev 0) +++ trunk/fclient/fclient/impl/BaseRequestsWidget/BaseRequestsWidget.py 2008-08-16 08:10:49 UTC (rev 915) @@ -0,0 +1,561 @@ + +#************************************************************************************************************** +#TODO: +# +# x. prtty tricky to get dls right when the node or client may disconnect unexpectedly +# problem: dls that we send and that have not reached the node +# problem: what to do when the user wants to quit and we still have dls to push to the node +# +# solution would require keeping track of all requests +# a. keep identifiers of requests that reached the node (have to do it anyways) +# b. keep track of requests ahead of sending them to the node (feels not too good doubeling downloads.dat.gz) +# +# best idea seems to be to ignore the problem +# 1. wait till (if ever) freenet devels fdrop node keeping track of client requests +# +# 2. a box thrown to the user (x. do not show this message again) to inform him about pendings +# should be enough. maybe along with a separate widget or some separate color code for pendings +# +# x. performance +# start with a standard model and improve it over time. no need to set any hard +# limits. the user will find out by himself how many dls his machine can handle. +# have to be carefrul though when adding dls, like from a *.frdx to provide appropriate +# warnings +# x. it may take a while untill the final DataFound message arrives when a request is % completed. feedback would be nice +# x. DataFound for a request the file has been removed by the user. no idea what happens. have to test this +# x. when the node is about to start up, looks like persistents may arrive or not. check +# x. how to get early information about mimetype/size? maybe use FcpClient.getFileInfo() +# x. show/hide header izems +# x. sort by header +# x. indicate over all time / dl speed +# x. indicate status / remove items by status +# x. item properties +# x. how to handle inserting huge number of dls? +# idea: insert with lowest priority to get the node to know them, increase priority when a slot in +# MaxSimultaneousDls (if set) is free. atatch progressBar no sooner as priority > MinDlPriority +# x. how to handle huge numbers of dls. the node will flood us on startup with persistents. looks +# like the only way to control the flood is to have one connection/dl. maybe wait for freenet devels +# to realize that this is a serious problem... +# x. byte amount postfixes must be transllated ++ use Kib or Kb or let the user decide? +# x. sometimes groups of dls get not removed +#************************************************************************************************************** +# some fixes for relative imports +# see --> [http://bugs.python.org/issue1510172] absolute/rellative import not working (works only current dir and below) +# see --> [http://mail.python.org/pipermail/python-ideas/2007-February/000232.html] PEP for executing a module in a +# ...package containing relative imports +from __future__ import absolute_import +if __name__ == '__main__': + import os + __path__ = [os.path.dirname(__file__)] + from ._fix_mexec import fix_mexec + fix_mexec(__name__, __file__) + del fix_mexec +import mimetypes +import os +from PyQt4 import QtCore, QtGui + +from .. import config +from ..lib import fcp2 +from ..lib.fcp2.lib import pmstruct +from ..lib.qt4ex import treewidgetwrap +from ..lib import numbers + +from .dlgs import DlgDownloadKeyToDisk + +from .Ui_RequestsWidget import Ui_ViewRequestsWidget +#********************************************************************************** +# +#********************************************************************************** +BLOCK_SIZE = 32768 # from CHKBlock.java + +#********************************************************************************** +# +#********************************************************************************** +class PersistentRequestData(pmstruct.PMStruct): + _fields_ = ( + ('ClientName', pmstruct.STRING), + ) + +#********************************************************************************** +# +#********************************************************************************** +class TreeItem(QtGui.QTreeWidgetItem): + + IndexName = 0 + IndexSize = 1 + IndexMimeType = 2 + IndexStatus = 3 + IndexProgress = 4 + IndexPriority = 5 + IndexElapsed = 6 + + ProgressBarName = 'downloadKey' + + StatusPending = 'pending' + StatusLoading = 'loading' + StatusComplete = 'complete' + StatusError = 'error' + StatusRemoved = 'removed' + StatusCompressing = 'compressing' + ##StatusCompressed = 'compressed' #TODO: no way to distinguish compressed an loading + + def __init__(self, fcpRequest, *params): + QtGui.QTreeWidgetItem.__init__(self, *params) + self.fcpRequest = fcpRequest + self.fcOldStatus = self.StatusPending + + def status(self): + if self.fcpRequest is None: + return self.StatusRemoved + elif self.fcpRequest['RequestStatus'] & fcp2.ConstRequestStatus.Success: + return self.StatusComplete + elif self.fcpRequest['RequestStatus'] & fcp2.ConstRequestStatus.Error: + return self.StatusError + + #TODO: more or less aguess ..have to check this in detail + elif self.fcpRequest['RequestStatus'] & fcp2.ConstRequestStatus.Started: + if self.fcpRequest['RequestStatus'] & fcp2.ConstRequestStatus.Compressing: + if self.fcpRequest['RequestStatus'] & fcp2.ConstRequestStatus.Compressed: + return self.StatusLoading + else: + return self.compressing + else: + return self.StatusLoading + else: + return self.StatusPending + +# exposes status property for stylesheets +class ProgressBar(QtGui.QProgressBar): + + def __init__(self, parent, item): + QtGui.QProgressBar.__init__(self, parent) + self.item = item + + def _get_status(self): + return self.item.status() + status= QtCore.pyqtProperty("QString", _get_status) + + +class RequestsWidgetActions(config.ActionsBase): + + def __init__(self, parent): + config.ActionsBase.__init__(self, parent) + + self.action( + name='ActionDownloadKeyToDisk', + text=self.trUtf8('Download &key...'), + trigger=parent.onDlgDownloadKey, + ) + self.action( + name='ActionRemoveSelectedDownloads', + text=self.trUtf8('Remove download'), + trigger=parent.onRemoveSelectedDownloads, + isEnabled=False, + ) + self.action( + name='ActionRestartSelectedDownloads', + text=self.trUtf8('Restart download'), + trigger=parent.onRestartSelectedDownloads, + isEnabled=False, + ) + + #TODO: enable/disable if items of that type are available? + group = self.group( + name='GroupRemoveGroup', + trigger=parent.onRemoveGroup, + ) + self.action( + name='ActionRemoveFailed', + group=group, + text=self.trUtf8('Failed'), + isEnabled=False, + ) + self.action( + name='ActionRemoveCompleted', + group=group, + text=self.trUtf8('Completed'), + isEnabled=False, + ) + +#********************************************************************************** +# +#********************************************************************************** +class RequestsWidget(QtGui.QWidget, Ui_ViewRequestsWidget): + + IdTree = 'tree' + + def __init__(self, parent, idGlobalFeedback=config.IdMainWindow): + QtGui.QWidget.__init__(self, parent) + self._isCreated = False + self.fcHeaderLabels = {} # fcpIdentifier --> treeItem + self.fcActions = RequestsWidgetActions(self) + self.fcpRequests = {} + self.fcRequestStatusNames = {} + self.menuRemoveGroup = QtGui.QMenu(self) + + self.setupUi(self) + self.fcpClientEvents = ( + (config.fcpClient.events.ClientConnected, self.onFcpClientConnected), + (config.fcpClient.events.ClientDisconnected, self.onFcpClientDisconnected), + (config.fcpClient.events.ConfigData, self.onFcpConfigData), + (config.fcpClient.events.RequestCompleted, self.onFcpClientRequestCompleted), + (config.fcpClient.events.RequestFailed, self.onFcpClientRequestFailed), + (config.fcpClient.events.RequestModified, self.onFcpClientRequestModified), + (config.fcpClient.events.RequestProgress, self.onFcpClientRequestProgress), + (config.fcpClient.events.RequestStarted, self.onFcpClientRequestStarted), + (config.fcpClient.events.RequestRemoved, self.onFcpClientRequestRemoved), + (config.fcpClient.events.RequestCompressionStarted, self.onFcpClientRequestCompressionStarted), + (config.fcpClient.events.RequestCompressionCompleted, self.onFcpClientRequestCompressionCompleted), + ) + config.fcpClient.events += self.fcpClientEvents + + + ############################ + ## private methods + ############################ + def _adjustItemStatus(self, item): + # to take Css styling into account we have to set a new statusBar for each state change + tree = self.controlById(self.IdTree) + oldProgressBar = progressBar = self.tree.itemWidget(item, TreeItem.IndexProgress) + itemStatus = item.status() + itemStatusChanged = itemStatus != item.fcOldStatus + if itemStatusChanged: + progressBar = ProgressBar(self.tree, item) + + # adjust statusBar and set a new one if necessary + # ..bit much work here, but necessary, cos Fcp might come up with + # ..a completed message without any prior progress notifications + if itemStatus == TreeItem.StatusPending: + progressBar.setRange(0, 0) + elif itemStatus == TreeItem.StatusLoading: + progressBar.setRange(0, item.fcpRequest['ProgressRequired']) + progressBar.setValue(item.fcpRequest['ProgressSucceeded']) + elif itemStatus == TreeItem.StatusComplete: + progressBar.setRange(0, 1) + progressBar.setValue(progressBar.maximum()) + elif itemStatus == TreeItem.StatusError: + progressBar.setMinimum(oldProgressBar.minimum()) + progressBar.setMaximum(oldProgressBar.maximum()) + progressBar.setValue(oldProgressBar.value()) + elif itemStatus == TreeItem.StatusRemoved: + pass + elif itemStatus == TreeItem.StatusCompressing: + progressBar.setRange(0, 0) + else: + raise ValueError('Unknown status: %r' % itemStatus) + if itemStatusChanged: + progressBar.setObjectName(TreeItem.ProgressBarName) + tree.setItemWidget(item, TreeItem.IndexProgress, progressBar) + item.setData( + TreeItem.IndexStatus, + QtCore.Qt.DisplayRole, + QtCore.QVariant(self.fcRequestStatusNames[itemStatus]), + ) + item.fcOldStatus = itemStatus + + ############################ + ## + ############################ + def retranslateUi(self, parent): + Ui_ViewRequestsWidget.retranslateUi(self, parent) + tree = self.controlById(self.IdTree) + root = tree.invisibleRootItem() + + # adjust header labels + self.fcHeaderLabels = { + TreeItem.IndexName: self.trUtf8('Name'), + TreeItem.IndexSize: self.trUtf8('Size'), + TreeItem.IndexMimeType: self.trUtf8('MimeType'), + TreeItem.IndexStatus: self.trUtf8('Status'), + TreeItem.IndexPriority: self.trUtf8('Priority'), + TreeItem.IndexProgress: self.trUtf8('Progress'), + TreeItem.IndexElapsed: self.trUtf8('Elapsed'), + } + tree.setHeaderLabels([i[1] for i in sorted(self.fcHeaderLabels.items())]) + + # adjust status names and retranslate all items + self.fcRequestStatusNames = { + TreeItem.StatusPending: self.trUtf8('Pending'), + TreeItem.StatusLoading: self.trUtf8('Loading'), + TreeItem.StatusComplete: self.trUtf8('Complete'), + TreeItem.StatusError: self.trUtf8('Error'), + TreeItem.StatusRemoved: self.trUtf8('Removed'), + TreeItem.StatusCompressing: self.trUtf8('Compressing'), + ##TreeItem.StatusCompressed: self.trUtf8('Compressed'), #TODO: no way to distinguish compressed an loading + } + for item in treewidgetwrap.walkItem(root): + fcpRequest = getattr(item, 'fcpRequest', None) + if hasattr(item, 'fcpRequest'): + item.setText(TreeItem.IndexStatus, self.fcRequestStatusNames[item.status()]) + + # others + self.menuRemoveGroup.setTitle(self.trUtf8('Remove group')) + + def closeEvent(self): + self.viewClose() + + def hideEvent(self, event): + self.fcGlobalFeedback.setVisible(False) + + def showEvent(self, event): + self.fcGlobalFeedback.setVisible(True) + if not self._isCreated: + self._isCreated = True + + # setup tree + tree = self.controlById(self.IdTree) + tree.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) + tree.setRootIsDecorated(False) + tree.setSelectionMode(tree.ExtendedSelection) + tree.setUniformRowHeights(True) + self.connect(tree, QtCore.SIGNAL('customContextMenuRequested(const QPoint &)'), self.onTreeCustomContextMenuRequested) + self.connect(tree, QtCore.SIGNAL('itemSelectionChanged() '), self.onTreeItemSelectionChanged) + + def viewClose(self): + config.fcpClient.events -= self.fcpClientEvents + + ######################################### + ## methods + ######################################### + #TODO: much... + def addFcpRequest(self, fcpRequest): + """ + @note: if you add a newly created request, make shure to set the requests PersistentUserData + to the result of the call to L{persistentFcpRequestData} + """ + tree = self.controlById(self.IdTree) + root = tree.invisibleRootItem() + item= TreeItem(fcpRequest, root) + progressBar = ProgressBar(self.tree, item) + + progressBar.setObjectName(TreeItem.ProgressBarName) + tree.setItemWidget(item, TreeItem.IndexProgress, progressBar) + fileName = fcpRequest['Filename'] + mimeType = mimetypes.guess_type(fileName)[0] + icon = config.fcResources.getIcon( + config.mimeTypeIconName(mimeType), + config.fcSettings.value('IconSize'), + config.fcSettings.value('IconTheme'), + ) + item.setIcon(0, icon) + item.setData( + TreeItem.IndexName, + QtCore.Qt.DisplayRole, + QtCore.QVariant(os.path.basename(fcpRequest['Filename'])) + ) + + #TODO: take a wild guess at the size. no other way to do it currently + estimatedSize = int((BLOCK_SIZE * fcpRequest['ProgressRequired']) + 1) + item.setData( + TreeItem.IndexSize, + QtCore.Qt.DisplayRole, + QtCore.QVariant(self.trUtf8('< ') + numbers.format_num_bytes(estimatedSize)), + ) + + self.fcpRequests[fcpRequest['Identifier']] = item + self._adjustItemStatus(item) + return item + + self.fcpRequests[fcpRequest['Identifier']] = item + self._adjustItemStatus(item) + return item + + + def controlById(idGlobalFeedback, idControl): + return getattr(idGlobalFeedback, idControl) + + # overwrite + def populateMenu(self, menu): + return menu + + def execDlgDownloadKey(self, fcpKey=None): + """pops up the dialog to allow the user to download a key to disk + @param fcpKey: key to initialize the key with or None + """ + dlg = DlgDownloadKeyToDisk.DlgDownloadKeyToDisk(self, fcpKey=fcpKey) + if dlg.exec_() == dlg.Accepted: + self.downloadFile( + dlg.fcpKey(), + dlg.fileName(), + persistence=fcp2.ConstPersistence.Forever, + handleFilenameCollision=True, + ) + + def persistentFcpRequestData(self): + return PersistentRequestData(ClientName=unicode(self.objectName())).dump() + + ######################################### + ## event handlers + ######################################### + def onDlgDownloadKey(self, action): + self.execDlgDownloadKey(fcpKey=None) + + def onRemoveSelectedDownloads(self, action): + tree = self.controlById(self.IdTree) + selectedItems = tree.selectedItems() + + # remove items + for item in selectedItems: + parent = item.parent() + if parent is None: + parent = tree.invisibleRootItem() + parent.removeChild(item) + + # cancel all requests + for item in selectedItems: + for tmp_item in treewidgetwrap.walkItem(item): + if tmp_item.fcpRequest is not None: # we may come across the same item multiple times + if tmp_item.fcpRequest['Identifier'] in self.fcpRequests: #TODO: should never be False?! check + del self.fcpRequests[tmp_item.fcpRequest['Identifier']] + config.fcpClient.removeRequest(tmp_item.fcpRequest) + tmp_item.fcpRequest = None + + def onRestartSelectedDownloads(self, action): + tree = self.controlById(self.IdTree) + for item in tree.selectedItems(): + if item.fcpRequest is None: + raise RuntimeError('fcpRequest is None. should not happen') + del self.fcpRequests[item.fcpRequest['Identifier']] + item.fcpRequest = config.fcpClient.resendRequest(item.fcpRequest) + self.fcpRequests[item.fcpRequest['Identifier']] = item + self._adjustItemStatus(item) + + def onRemoveGroup(self, action): + tree = self.controlById(self.IdTree) + root = tree.invisibleRootItem() + + if action == self.fcActions['ActionRemoveCompleted']: + flag = fcp2.ConstRequestStatus.Success + elif action == self.fcActions['ActionRemoveFailed']: + flag = fcp2.ConstRequestStatus.Error + else: + raise ValueError('Not implemented') + + for item in treewidgetwrap.walkItem(root, topdown=False): + fcpRequest = getattr(item, 'fcpRequest', None) + if fcpRequest is not None: + if fcpRequest['Identifier'] in self.fcpRequests: #TODO: should never be False?! check + del self.fcpRequests[fcpRequest['Identifier']] + + if fcpRequest['RequestStatus'] & fcp2.ConstRequestStatus.Removed: + pass + elif not fcpRequest['RequestStatus'] & flag: + continue + else: + item.fcpRequest = None + config.fcpClient.removeRequest(fcpRequest) + parent = item.parent() + if parent is None: + parent = root + parent.removeChild(item) + + + # overwrite + def onTreeCustomContextMenuRequested(self, pt): + pass + + # overwrite + def onTreeItemSelectionChanged(self): + pass + + ######################################### + ## fcp event handlers + ######################################### + def onFcpClientConnected(self, event, msg): + for action in self.fcActions: + action.setEnabled(True) + + + def onFcpClientDisconnected(self, event, msg): + for action in self.fcActions: + action.setEnabled(False) + + def onFcpConfigData(self, fcpEvent, fcpRequest): + pass + + + def onFcpClientRequestCompleted(self, fcpEvent, fcpRequest): + item = self.fcpRequests.get(fcpRequest['Identifier'], None) + if item is not None: + mimeType = fcpRequest['MetadataContentType'] + item.setData( + TreeItem.IndexSize, + QtCore.Qt.DisplayRole, + QtCore.QVariant(numbers.format_num_bytes(fcpRequest['MetadataSize'])) + ) + item.setData( + TreeItem.IndexMimeType, + QtCore.Qt.DisplayRole, + QtCore.QVariant(mimeType) + ) + icon = config.fcResources.getIcon( + config.mimeTypeIconName(mimeType), + config.fcSettings.value('IconSize'), + config.fcSettings.value('IconTheme'), + ) + item.setIcon(0, icon) + self._adjustItemStatus(item) + + def onFcpClientRequestCompressionStarted(self, fcpEvent, fcpRequest): + item = self.fcpRequests.get(fcpRequest['Identifier'], None) + if item is not None: + self._adjustItemStatus(item) + + def onFcpClientRequestCompressionCompleted(self, fcpEvent, fcpRequest): + item = self.fcpRequests.get(fcpRequest['Identifier'], None) + if item is not None: + self._adjustItemStatus(item) + + def onFcpClientRequestFailed(self, fcpEvent, fcpRequest): + item = self.fcpRequests.get(fcpRequest['Identifier'], None) + if item is not None: + self._adjustItemStatus(item) + + #TODO: not tested + def onFcpClientRequestModified(self, fcpEvent, fcpRequest): + + requestIdentifier = fcpRequest['Modified'].get(fcp2.ConstRequestModified.Identifier, None) + if requestIdentifier is None: + requestIdentifier = fcpRequest['Identifier'] + item = self.fcpRequests.get(requestIdentifier, None) + + if item is not None: + if fcp2.ConstRequestModified.Identifier in fcpRequest['Modified']: + newFcpIdentifier = fcpRequest['Identifier'] + del self.fcpRequests[requestIdentifier] + self.fcpRequests[newFcpIdentifier] = item + + if fcp2.ConstRequestModified.Filename in fcpRequest['Modified']: + item.setData( + TreeItem.IndexName, + QtCore.Qt.DisplayRole, + QtCore.QVariant(os.path.basename(fcpRequest['Filename'])) + ) + + + def onFcpClientRequestProgress(self, fcpEvent, fcpRequest): + item = self.fcpRequests.get(fcpRequest['Identifier'], None) + if item is not None: + self._adjustItemStatus(item) + + def onFcpClientRequestRemoved(self, fcpEvent, fcpRequest): + pass + + def onFcpClientRequestStarted(self, fcpEvent, fcpRequest): + if fcpRequest['RequestStatus'] & fcp2.ConstRequestStatus.Restored: + try: + requestData = PersistentRequestData.load(fcpRequest['PersistentUserData']) + except pmstruct.PMStructError: + pass + else: + if requestData.get('ClientName', None) == self.objectName(): + item = self.addFcpRequest(fcpRequest) + else: + item = self.fcpRequests.get(fcpRequest['Identifier'], None) + if item is not None: + self._adjustItemStatus(item) + + +#********************************************************************************** +# +#********************************************************************************** Added: trunk/fclient/fclient/impl/BaseRequestsWidget/RequestsWidget.ui =================================================================== --- trunk/fclient/fclient/impl/BaseRequestsWidget/RequestsWidget.ui (rev 0) +++ trunk/fclient/fclient/impl/BaseRequestsWidget/RequestsWidget.ui 2008-08-16 08:10:49 UTC (rev 915) @@ -0,0 +1,35 @@ +<ui version="4.0" > + <class>ViewRequestsWidget</class> + <widget class="QWidget" name="ViewRequestsWidget" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>300</height> + </rect> + </property> + <property name="windowTitle" > + <string>Form</string> + </property> + <layout class="QGridLayout" name="gridLayout" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>0</number> + </property> + <item row="0" column="0" > + <widget class="QTreeWidget" name="tree" > + <column> + <property name="text" > + <string>1</string> + </property> + </column> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> Added: trunk/fclient/fclient/impl/BaseRequestsWidget/Ui_RequestsWidget.py =================================================================== --- trunk/fclient/fclient/impl/BaseRequestsWidget/Ui_RequestsWidget.py (rev 0) +++ trunk/fclient/fclient/impl/BaseRequestsWidget/Ui_RequestsWidget.py 2008-08-16 08:10:49 UTC (rev 915) @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file '/home/me/src/fclient/trunk/fclient/fclient/impl/XBaseRequestsWidget/RequestsWidget.ui' +# +# Created: Sat Aug 16 10:04:59 2008 +# by: PyQt4 UI code generator 4.4.3-snapshot-20080705 +# +# WARNING! All changes made in this file will be lost! + +from PyQt4 import QtCore, QtGui + +class Ui_ViewRequestsWidget(object): + def setupUi(self, ViewRequestsWidget): + ViewRequestsWidget.setObjectName("ViewRequestsWidget") + ViewRequestsWidget.resize(400, 300) + self.gridLayout = QtGui.QGridLayout(ViewRequestsWidget) + self.gridLayout.setMargin(0) + self.gridLayout.setSpacing(0) + self.gridLayout.setObjectName("gridLayout") + self.tree = QtGui.QTreeWidget(ViewRequestsWidget) + self.tree.setObjectName("tree") + self.gridLayout.addWidget(self.tree, 0, 0, 1, 1) + + self.retranslateUi(ViewRequestsWidget) + QtCore.QMetaObject.connectSlotsByName(ViewRequestsWidget) + + def retranslateUi(self, ViewRequestsWidget): + ViewRequestsWidget.setWindowTitle(QtGui.QApplication.translate("ViewRequestsWidget", "Form", None, QtGui.QApplication.UnicodeUTF8)) + self.tree.headerItem().setText(0, QtGui.QApplication.translate("ViewRequestsWidget", "1", None, QtGui.QApplication.UnicodeUTF8)) + + +if __name__ == "__main__": + import sys + app = QtGui.QApplication(sys.argv) + ViewRequestsWidget = QtGui.QWidget() + ui = Ui_ViewRequestsWidget() + ui.setupUi(ViewRequestsWidget) + ViewRequestsWidget.show() + sys.exit(app.exec_()) + Added: trunk/fclient/fclient/impl/BaseRequestsWidget/__init__.py =================================================================== --- trunk/fclient/fclient/impl/BaseRequestsWidget/__init__.py (rev 0) +++ trunk/fclient/fclient/impl/BaseRequestsWidget/__init__.py 2008-08-16 08:10:49 UTC (rev 915) @@ -0,0 +1 @@ + Added: trunk/fclient/fclient/impl/BaseRequestsWidget/_fix_mexec.py =================================================================== --- trunk/fclient/fclient/impl/BaseRequestsWidget/_fix_mexec.py (rev 0) +++ trunk/fclient/fclient/impl/BaseRequestsWidget/_fix_mexec.py 2008-08-16 08:10:49 UTC (rev 915) @@ -0,0 +1,99 @@ +'''in python 2.5 relative impports are srsly broken ..fix this to make relative imports work +when executing a module as main (-m), including relative imports up to the root package + +see: [http://mail.python.org/pipermail/python-ideas/2007-February/000232.html] + +@note: root package is the highest available package in the package hirarchy. +don't look at __name__ too closely. it gets adjusted for a module to just "do the right +thing" in __name__ == '__main__' comparisons +@note: this patch does not work if relative imports are done in __init__.py. no idea why +and to be honest, I don't wanna* know.. +@note: this is more or less a hack. so it may have unwanted side effects for example +when importing parent packages. use at your own risk. could improve this module +by adding a __main__.py to stop at this level or by fixing the __init__.py bug, but +I don't think its worth it. see what python2.6 or 3k brings.. + +usage:: + + # place this at the top a module, before doing any relative imports + from fix_mexec import fix_mexec + fix_mexec(__name__, __file__) + del fix_mexec + + from ...foo import bar + + + +##<-- copy and paste code, assuming _fix_mexec resides in the current dir.. + +# some fixes for relative imports +# see --> [http://bugs.python.org/issue1510172] absolute/rellative import not working (works only current dir and below) +# see --> [http://mail.python.org/pipermail/python-ideas/2007-February/000232.html] PEP for executing a module in a +# ...package containing relative imports +from __future__ import absolute_import +if __name__ == '__main__': + import os + __path__ = [os.path.dirname(__file__)] + from ._fix_mexec import fix_mexec + fix_mexec(__name__, __file__) + del fix_mexec + + +##--> copy and paste code +''' + +import imp, os, sys +#******************************************************************************** +# +#******************************************************************************** +class MainName(str): + def __eq__(self, other): + if other == '__main__': return True + return str.__eq__(self, other) + def __ne__(self, other): + if other == '__main__': return False + return str.__ne__(self, other) + + +def fix_mexec(_name_, _file_): + """bugfix for relative imports not working + @param _name_: __name__ of the module + @param _file_: __file__ of the module + + @note: not complete: relies on __init__.py, .pyo (...) is ignored currently + """ + if _name_ == '__main__': + out = [] + # find allparent packages + p = os.path.dirname(os.path.abspath(_file_)) + prev = p + while True: + pkg = os.path.join(p, '__init__.py') + if os.path.isfile(pkg): + out.append([pkg, os.path.basename(p)]) + else: + break + prev = p + p = os.path.dirname(p) + if p == prev: + break + out.reverse() + + # adjust sub package names an import parent modules + name = None + for n, (fpath, name) in enumerate(out): + if n > 0: + name = out[n][1] = out[n -1][1] + '.' + out[n][1] + m = imp.load_source(name, fpath) + m.__path__ = [os.path.dirname(fpath)] + + # adjust name of the __main__ module + if name is not None: + m = sys.modules.pop('__main__') + # 'foo.bar..__main__' does not work for some reason. 'foo.bar' seems to work as expected + ##m.__name__ = _Name_(name + '.' + '__main__') + m.__name__ = MainName(name) + sys.modules[m.__name__] = m + + + Added: trunk/fclient/fclient/impl/BaseRequestsWidget/dlgs/DlgDownloadKeyToDisk.py =================================================================== --- trunk/fclient/fclient/impl/BaseRequestsWidget/dlgs/DlgDownloadKeyToDisk.py (rev 0) +++ trunk/fclient/fclient/impl/BaseRequestsWidget/dlgs/DlgDownloadKeyToDisk.py 2008-08-16 08:10:49 UTC (rev 915) @@ -0,0 +1,153 @@ +#*************************************************************************************** +#TODO: +# x. have to inject (..whatebver) a checkbox into msg box invalid key warning <x don't show this message again> +# x. save dialog pos/size on exit +# +#************************************************************************************* +# some fixes for relative imports +# see --> [http://bugs.python.org/issue1510172] absolute/rellative import not working (works only current dir and below) +# see --> [http://mail.python.org/pipermail/python-ideas/2007-February/000232.html] PEP for executing a module in a +# ...package containing relative imports +from __future__ import absolute_import +if __name__ == '__main__': + import os + __path__ = [os.path.dirname(__file__)] + from ._fix_mexec import fix_mexec + fix_mexec(__name__, __file__) + del fix_mexec + +import os +from PyQt4 import QtCore, QtGui + +from ... import config +from ...lib import fcp2 + +from .Ui_DlgDownloadKeyToDiskTpl import Ui_DlgDownloadKeyToDisk +#********************************************************************************** +# +#********************************************************************************** +class Settings(config.SettingsBase): + _key_ = 'DlgDownloadKeyToDisk' + _settings_ = ( + ('Geometry', 'ByteArray', QtCore.QByteArray()), + ) + + +#********************************************************************************** +# +#********************************************************************************** +class DlgDownloadKeyToDisk(QtGui.QDialog, Ui_DlgDownloadKeyToDisk): + + IdEdKey = 'edKey' + IdEdFileName = 'edFileName' + IdEdDirectory = 'edDirectory' + IdBtChooseDirectory = 'btChooseDirectory' + + + def __init__(self, parent=None, fcpKey=None): + QtGui.QDialog.__init__(self, parent) + + self.setupUi(self) + self.setWindowTitle(config.FcAppName + self.trUtf8(' - Download key..')) + self.fcSettings = Settings(self).restore() + + self._fileName = None + self._fcpKey = fcpKey + + # setup key editbox + ed = self.controlById(self.IdEdKey) + if fcpKey is not None: + ed.setText(fcpKey.toString()) + + # setup filename editbox + ed = self.controlById(self.IdEdFileName) + if fcpKey is not None: + # find out fileName to dl key to + fileName = config.guessFileNameFromKey(self._fcpKey) + if fileName is None: + fileName = self.trUtf8('UNKNOWN') + ed.setText(fileName) + + # setup directory editbox + ed = self.controlById(self.IdEdDirectory) + ed.setText(unicode(config.fcSettings.value('DownloadDir'))) + bt = self.controlById(self.IdBtChooseDirectory) + self.connect(bt, QtCore.SIGNAL('clicked()'), self.onChooseDirectory) + + + self.restoreGeometry(self.fcSettings.value('Geometry')) + + ############################## + ## methods + ############################## + def controlById(self, idControl): + return getattr(self, idControl) + + def fileName(self): + return self._fileName + + def fcpKey(self): + return self._fcpKey + + ############################## + ## overwritten methods + ############################## + def accept(self): + edKey = self.controlById(self.IdEdKey) + edFileName = self.controlById(self.IdEdFileName) + edDirectory = self.controlById(self.IdEdDirectory) + + key = unicode(edKey.text()) + if not key: + return QtGui.QMessageBox.warning(self, self.windowTitle(), 'Please enter a key to download') + try: + self._fcpKey = fcp2.Key(key) + except fcp2.ErrorKey: + return QtGui.QMessageBox.warning(self, self.windowTitle(), 'Looks like the key entered is not valid') + + fileName = edFileName.text() + if fileName.isEmpty(): + return QtGui.QMessageBox.warning(self, self.windowTitle(), 'Please enter a filename for the key') + + directory = edDirectory.text() + if directory.isEmpty(): + return QtGui.QMessageBox.warning(self, self.windowTitle(), 'Please enter a directory under wich to save the key') + + self._fileName = os.path.join(unicode(directory), unicode(fileName)) + self.done(self.Accepted) + + ############################## + ## overwritten events + ############################## + def hideEvent(self, event): + self.fcSettings.setValues(Geometry=self.saveGeometry()) + + ############################## + ## event handlers + ############################## + def onChooseDirectory(self): + edDirectory = self.controlById(self.IdEdDirectory) + directory = QtGui.QFileDialog.getExistingDirectory( + self, + config.FcAppName + self.trUtf8(' - Download key to..'), + edDirectory.text(), + ) + if directory: + edDirectory.setText(directory) + +#********************************************************************************** +# +#********************************************************************************** +if __name__ == '__main__': + import sys + + app = QtGui.QApplication(sys.argv) + w = DlgDownloadKeyToDisk( + #None, + fcpKey=fcp2.KeyKSK('foo.txt') + ) + w.show() + res = app.exec_() + sys.exit(res) + + Added: trunk/fclient/fclient/impl/BaseRequestsWidget/dlgs/DlgDownloadKeyToDiskTpl.ui =================================================================== --- trunk/fclient/fclient/impl/BaseRequestsWidget/dlgs/DlgDownloadKeyToDiskTpl.ui (rev 0) +++ trunk/fclient/fclient/impl/BaseRequestsWidget/dlgs/DlgDownloadKeyToDiskTpl.ui 2008-08-16 08:10:49 UTC (rev 915) @@ -0,0 +1,136 @@ +<ui version="4.0" > + <class>DlgDownloadKeyToDisk</class> + <widget class="QDialog" name="DlgDownloadKeyToDisk" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>431</width> + <height>243</height> + </rect> + </property> + <property name="windowTitle" > + <string>Dialog</string> + </property> + <layout class="QGridLayout" name="gridLayout" > + <item row="0" column="0" > + <layout class="QVBoxLayout" name="verticalLayout" > + <item> + <widget class="QLabel" name="fieldHeader" > + <property name="text" > + <string>Key:</string> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="edKey" > + <property name="dragEnabled" > + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="fieldHeader_2" > + <property name="text" > + <string>File name:</string> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="edFileName" /> + </item> + <item> + <widget class="QLabel" name="fieldHeader_3" > + <property name="text" > + <string>Directory:</string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout" > + <item> + <widget class="QLineEdit" name="edDirectory" > + <property name="dragEnabled" > + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="btChooseDirectory" > + <property name="text" > + <string>...</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + <item row="1" column="0" > + <spacer name="verticalSpacer" > + <property name="orientation" > + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>20</width> + <height>15</height> + </size> + </property> + </spacer> + </item> + <item row="2" column="0" > + <widget class="Line" name="line" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="3" column="0" > + <widget class="QDialogButtonBox" name="buttonBox" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons" > + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>DlgDownloadKeyToDisk</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel" > + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel" > + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>DlgDownloadKeyToDisk</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel" > + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel" > + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> Added: trunk/fclient/fclient/impl/BaseRequestsWidget/dlgs/Ui_DlgDownloadKeyToDiskTpl.py =================================================================== --- trunk/fclient/fclient/impl/BaseRequestsWidget/dlgs/Ui_DlgDownloadKeyToDiskTpl.py (rev 0) +++ trunk/fclient/fclient/impl/BaseRequestsWidget/dlgs/Ui_DlgDownloadKeyToDiskTpl.py 2008-08-16 08:10:49 UTC (rev 915) @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file '/home/me/src/fclient/trunk/fclient/fclient/impl/XBaseRequestsWidget/dlgs/DlgDownloadKeyToDiskTpl.ui' +# +# Created: Sat Aug 16 10:03:40 2008 +# by: PyQt4 UI code generator 4.4.3-snapshot-20080705 +# +# WARNING! All changes made in this file will be lost! + +from PyQt4 import QtCore, QtGui + +class Ui_DlgDownloadKeyToDisk(object): + def setupUi(self, DlgDownloadKeyToDisk): + DlgDownloadKeyToDisk.setObjectName("DlgDownloadKeyToDisk") + DlgDownloadKeyToDisk.resize(431, 243) + self.gridLayout = QtGui.QGridLayout(DlgDownloadKeyToDisk) + self.gridLayout.setObjectName("gridLayout") + self.verticalLayout = QtGui.QVBoxLayout() + self.verticalLayout.setObjectName("verticalLayout") + self.fieldHeader = QtGui.QLabel(DlgDownloadKeyToDisk) + self.fieldHeader.setObjectName("fieldHeader") + self.verticalLayout.addWidget(self.fieldHeader) + self.edKey = QtGui.QLineEdit(DlgDownloadKeyToDisk) + self.edKey.setDragEnabled(True) + self.edKey.setObjectName("edKey") + self.verticalLayout.addWidget(self.edKey) + self.fieldHeader_2 = QtGui.QLabel(DlgDownloadKeyToDisk) + self.fieldHeader_2.setObjectName("fieldHeader_2") + self.verticalLayout.addWidget(self.fieldHeader_2) + self.edFileName = QtGui.QLineEdit(DlgDownloadKeyToDisk) + self.edFileName.setObjectName("edFileName") + self.verticalLayout.addWidget(self.edFileName) + self.fieldHeader_3 = QtGui.QLabel(DlgDownloadKeyToDisk) + self.fieldHeader_3.setObjectName("fieldHeader_3") + self.verticalLayout.addWidget(self.fieldHeader_3) + self.horizontalLayout = QtGui.QHBoxLayout() + self.horizontalLayout.setObjectName("horizontalLayout") + self.edDirectory = QtGui.QLineEdit(DlgDownloadKeyToDisk) + self.edDirectory.setDragEnabled(True) + self.edDirectory.setObjectName("edDirectory") + self.horizontalLayout.addWidget(self.edDirectory) + self.btChooseDirectory = QtGui.QPushButton(DlgDownloadKeyToDisk) + self.btChooseDirectory.setObjectName("btChooseDirectory") + self.horizontalLayout.addWidget(self.btChooseDirectory) + self.verticalLayout.addLayout(self.horizontalLayout) + self.gridLayout.addLayout(self.verticalLayout, 0, 0, 1, 1) + spacerItem = QtGui.QSpacerItem(20, 15, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.gridLayout.addItem(spacerItem, 1, 0, 1, 1) + self.line = QtGui.QFrame(DlgDownloadKeyToDisk) + self.line.setFrameShape(QtGui.QFrame.HLine) + self.line.setFrameShadow(QtGui.QFrame.Sunken) + self.line.setObjectName("line") + self.gridLayout.addWidget(self.line, 2, 0, 1, 1) + self.buttonBox = QtGui.QDialogButtonBox(DlgDownloadKeyToDisk) + self.buttonBox.setOrientation(QtCore.Qt.Horizontal) + self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok) + self.buttonBox.setObjectName("buttonBox") + self.gridLayout.addWidget(self.buttonBox, 3, 0, 1, 1) + + self.retranslateUi(DlgDownloadKeyToDisk) + QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("accepted()"), DlgDownloadKeyToDisk.accept) + QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("rejected()"), DlgDownloadKeyToDisk.reject) + QtCore.QMetaObject.connectSlotsByName(DlgDownloadKeyToDisk) + + def retranslateUi(self, DlgDownloadKeyToDisk): + DlgDownloadKeyToDisk.setWindowTitle(QtGui.QApplication.translate("DlgDownloadKeyToDisk", "Dialog", None, QtGui.QApplication.UnicodeUTF8)) + self.fieldHeader.setText(QtGui.QApplication.translate("DlgDownloadKeyToDisk", "Key:", None, QtGui.QApplication.UnicodeUTF8)) + self.fieldHeader_2.setText(QtGui.QApplication.translate("DlgDownloadKeyToDisk", "File name:", None, QtGui.QApplication.UnicodeUTF8)) + self.fieldHeader_3.setText(QtGui.QApplication.translate("DlgDownloadKeyToDisk", "Directory:", None, QtGui.QApplication.UnicodeUTF8)) + self.btChooseDirectory.setText(QtGui.QApplication.translate("DlgDownloadKeyToDisk", "...", None, QtGui.QApplication.UnicodeUTF8)) + + +if __name__ == "__main__": + import sys + app = QtGui.QApplication(sys.argv) + DlgDownloadKeyToDisk = QtGui.QDialog() + ui = Ui_DlgDownloadKeyToDisk() + ui.setupUi(DlgDownloadKeyToDisk) + DlgDownloadKeyToDisk.show() + sys.exit(app.exec_()) + Added: trunk/fclient/fclient/impl/BaseRequestsWidget/dlgs/__init__.py =================================================================== --- trunk/fclient/fclient/impl/BaseRequestsWidget/dlgs/__init__.py (rev 0) +++ trunk/fclient/fclient/impl/BaseRequestsWidget/dlgs/__init__.py 2008-08-16 08:10:49 UTC (rev 915) @@ -0,0 +1 @@ + Added: trunk/fclient/fclient/impl/BaseRequestsWidget/dlgs/_fix_mexec.py =================================================================== --- trunk/fclient/fclient/impl/BaseRequestsWidget/dlgs/_fix_mexec.py (rev 0) +++ trunk/fclient/fclient/impl/BaseRequestsWidget/dlgs/_fix_mexec.py 2008-08-16 08:10:49 UTC (rev 915) @@ -0,0 +1,99 @@ +'''in python 2.5 relative impports are srsly broken ..fix this to make relative imports work +when executing a module as main (-m), including relative imports up to the root package + +see: [http://mail.python.org/pipermail/python-ideas/2007-February/000232.html] + +@note: root package is the highest available package in the package hirarchy. +don't look at __name__ too closely. it gets adjusted for a module to just "do the right +thing" in __name__ == '__main__' comparisons +@note: this patch does not work if relative imports are done in __init__.py. no idea why +and to be honest, I don't wanna* know.. +@note: this is more or less a hack. so it may have unwanted side effects for example +when importing parent packages. use at your own risk. could improve this module +by adding a __main__.py to stop at this level or by fixing the __init__.py bug, but +I don't think its worth it. see what python2.6 or 3k brings.. + +usage:: + + # place this at the top a module, before doing any relative imports + from fix_mexec import fix_mexec + fix_mexec(__name__, __file__) + del fix_mexec + + from ...foo import bar + + + +##<-- copy and paste code, assuming _fix_mexec resides in the current dir.. + +# some fixes for relative imports +# see --> [http://bugs.python.org/issue1510172] absolute/rellative import not working (works only current dir and below) +# see --> [http://mail.python.org/pipermail/python-ideas/2007-February/000232.html] PEP for executing a module in a +# ...package containing relative imports +from __future__ import absolute_import +if __name__ == '__main__': + import os + __path__ = [os.path.dirname(__file__)] + from ._fix_mexec import fix_mexec + fix_mexec(__name__, __file__) + del fix_mexec + + +##--> copy and paste code +''' + +import imp, os, sys +#******************************************************************************** +# +#******************************************************************************** +class MainName(str): + def __eq__(self, other): + if other == '__main__': return True + return str.__eq__(self, other) + def __ne__(self, other): + if other == '__main__': return False + return str.__ne__(self, other) + + +def fix_mexec(_name_, _file_): + """bugfix for relative imports not working + @param _name_: __name__ of the module + @param _file_: __file__ of the module + + @note: not complete: relies on __init__.py, .pyo (...) is ignored currently + """ + if _name_ == '__main__': + out = [] + # find allparent packages + p = os.path.dirname(os.path.abspath(_file_)) + prev = p + while True: + pkg = os.path.join(p, '__init__.py') + if os.path.isfile(pkg): + out.append([pkg, os.path.basename(p)]) + else: + break + prev = p + p = os.path.dirname(p) + if p == prev: + break + out.reverse() + + # adjust sub package names an import parent modules + name = None + for n, (fpath, name) in enumerate(out): + if n > 0: + name = out[n][1] = out[n -1][1] + '.' + out[n][1] + m = imp.load_source(name, fpath) + m.__path__ = [os.path.dirname(fpath)] + + # adjust name of the __main__ module + if name is not None: + m = sys.modules.pop('__main__') + # 'foo.bar..__main__' does not work for some reason. 'foo.bar' seems to work as expected + ##m.__name__ = _Name_(name + '.' + '__main__') + m.__name__ = MainName(name) + sys.modules[m.__name__] = m + + + Added: trunk/fclient/fclient/impl/ViewDownloads/ViewDownloads.py =================================================================== --- trunk/fclient/fclient/impl/ViewDownloads/ViewDownloads.py (rev 0) +++ trunk/fclient/fclient/impl/ViewDownloads/ViewDownloads.py 2008-08-16 08:10:49 UTC (rev 915) @@ -0,0 +1,203 @@ +"""""" + +# some fixes for relative imports +# see --> [http://bugs.python.org/issue1510172] absolute/rellative import not working (works only current dir and below) +# see --> [http://mail.python.org/pipermail/python-ideas/2007-February/000232.html] PEP for executing a module in a +# ...package containing relative imports +from __future__ import absolute_import +if __name__ == '__main__': + import os + __path__ = [os.path.dirname(__file__)] + from ._fix_mexec import fix_mexec + fix_mexec(__name__, __file__) + del fix_mexec + + +from PyQt4 import QtCore, QtGui + +from .. import config +from ..BaseRequestsWidget import RequestsWidget +#************************************************************************************ +# +#************************************************************************************ +class DownloadsWidgetGlobalFeedback(config.GlobalFeedbackBase): + """wrapper for global statusbar widgets, menus""" + + def __init__(self, parent, idGlobalFeedback): + config.GlobalFeedbackBase.__init__(self, parent, idGlobalFeedback) + + # menus + self.menus = [] + if self.menuBar is not None and hasattr(parent, 'fcViewObject'): + menu = QtGui.QMenu(parent.fcViewObject.displayName, self.menuBar) + parent.populateMenu(menu) + self.menus.append(menu) + self.menuBar.addViewMenu(menu) + + # status bar widgets + self.labelStatus = None + self.progress = None + self.labelFeedbackWrap = None + #if self.statusBar is not None: + # self.labelStatus = QtGui.QLabel(QtCore.QString(), self.statusBar) + # self.statusBar.addWidget(self.labelStatus) + # + # self.progress = QtGui.QProgressBar(self.statusBar) + # self.progress.setRange(0, Browser.MaxProgress) + # self.progress.setValue(0) + # self.statusBar.addWidget(self.progress) + # + # label = QtGui.QLabel(self.statusBar) + # label.setFrameStyle(QtGui.QLabel.Sunken | QtGui.QLabel.Box) + # self.labelFeedbackWrap = pathlabelwrap.PathLabelWrap( + # label, + # path_module=config.CompactPathFcpKeyModule, + # ) + # self.statusBar.addWidget(self.labelFeedbackWrap.label, 1) + + + def setVisible(self, flag): + if self.menuBar is not None: + for menu in self.menus: + menu.children()[0].setEnabled(flag) + #if self.statusBar is not None: + # self.progress.setVisible(flag) + # self.labelStatus.setVisible(flag) + # self.labelFeedbackWrap.label.setVisible(flag) + + #def setProgress(self, n): + # if self.progress is not None: + # self.progress.setValue(n) + + #def setStatusMessage(self, qString): + # if self.labelStatus is not None: + # self.labelStatus.setText(qString) + + #def setFeedback(self, qString): + # if self.labelFeedbackWrap is not None: + # self.labelFeedbackWrap.setPath(unicode(qString)) + + + +class DownloadsViewObject(config.ViewObject): + + def __init__(self, parent): + config.ViewObject. __init__(self, parent) + + self.name=parent.objectName() + self.displayName=self.trUtf8('Downloads') + self.icon=QtGui.QIcon() + + +class DownloadsWidgetSettings(config.SettingsBase): + + + _key_ = config.IdViewDownloadsWidget + _settings_ = ( + ('MaxSimultaneousDownloads', 'UInt', 3), + ) + + +class ViewDownloadsWidget(RequestsWidget): + + def __init__(self, parent, idGlobalFeedback=config.IdMainWindow): + + self.menuRemoveGroup = None + + RequestsWidget.__init__(self, parent) + + self.setObjectName(config.IdViewDownloadsWidget) + config.ObjectRegistry.register(self) + self.fcSettings = DownloadsWidgetSettings(self).restore() + self.fcViewObject = DownloadsViewObject(self) + self.fcGlobalFeedback = DownloadsWidgetGlobalFeedback(self, idGlobalFeedback) + + # setup menus + self.menuRemoveGroup = QtGui.QMenu(self) + self.menuRemoveGroup.setTitle(self.trUtf8('Remove group')) + for action in self.fcActions['GroupRemoveGroup'].actions(): + self.menuRemoveGroup.addAction(action) + + + ################################### + ## overwritten methods + ################################### + def hideEvent(self, event): + self.fcGlobalFeedback.setVisible(False) + RequestsWidget.hideEvent(self, event) + + def showEvent(self, event): + self.fcGlobalFeedback.setVisible(True) + RequestsWidget.showEvent(self, event) + + def populateMenu(self, menu): + menu.addAction(self.fcActions['ActionDownloadKeyToDisk']) + return menu + + def retranslateUi(self, parent): + RequestsWidget.retranslateUi(self, parent) + if self.menuRemoveGroup is not None: + self.menuRemoveGroup.setTitle(self.trUtf8('Remove group')) + + ################################### + ## methods + ################################### + def downloadFile(self, fcpKey, fileName, **kws): + """""" + fileName = unicode(fileName) + fcpRequest = config.fcpClient.getFile( + fcpKey, + fileName, + persistentUserData = self.persistentFcpRequestData(), + #TODO: browser sets this. ok or not? + #handleFilenameCollision=True, + handlePermanentRedirect=True, + **kws + ) + item = self.addFcpRequest(fcpRequest) + + ################################### + ## event handlers + ################################### + def onTreeCustomContextMenuRequested(self, pt): + tree = self.controlById(self.IdTree) + pt = tree.viewport().mapToGlobal(pt) + + menu = QtGui.QMenu(self) + menu.addAction(self.fcActions['ActionRemoveSelectedDownloads']) + menu.addAction(self.fcActions['ActionRestartSelectedDownloads']) + menu.addMenu(self.menuRemoveGroup) + menu.exec_(pt) + + def onTreeItemSelectionChanged(self): + tree = self.controlById(self.IdTree) + hasSelectedItems = tree.selectionModel().hasSelection() + self.fcActions['ActionRemoveSelectedDownloads'].setEnabled(hasSelectedItems) + self.fcActions['ActionRestartSelectedDownloads'].setEnabled(hasSelectedItems) + + +#********************************************************************************** +# +#********************************************************************************** +if __name__ == '__main__': + import sys + from .. import View + from ..ViewConnection import ViewConnection + from ..ViewLogger import ViewLogger + from ..MainWindow import MainWindow + + app = QtGui.QApplication(sys.argv) + + mainWindow = MainWindow.MainWindow() + viewWidget = View.ViewWidget(mainWindow) + mainWindow.setCentralWidget(viewWidget) + + viewWidget.addTopViews( + ViewConnection.ViewConnectionWidget(None), + ViewDownloadsWidget(None), + ) + viewWidget.addBottomViews(ViewLogger.ViewLoggerWidget(None)) + + mainWindow.show() + res = app.exec_() + sys.exit(res) \ No newline at end of file Added: trunk/fclient/fclient/impl/ViewDownloads/__init__.py =================================================================== --- trunk/fclient/fclient/impl/ViewDownloads/__init__.py (rev 0) +++ trunk/fclient/fclient/impl/ViewDownloads/__init__.py 2008-08-16 08:10:49 UTC (rev 915) @@ -0,0 +1 @@ + Added: trunk/fclient/fclient/impl/ViewDownloads/_fix_mexec.py =================================================================== --- trunk/fclient/fclient/impl/ViewDownloads/_fix_mexec.py (rev 0) +++ trunk/fclient/fclient/impl/ViewDownloads/_fix_mexec.py 2008-08-16 08:10:49 UTC (rev 915) @@ -0,0 +1,93 @@ +'''python 2.5 relative impports are srsly broken ..fix this to make relative imports work +when executing a module as main (-m), including relative imports up to the root package + +see: [http://mail.python.org/pipermail/python-ideas/2007-February/000232.html] + +@note: root package is the highest available package in the package hirarchy. +don't look at __name__ too closely. it gets adjusted for a module to just "do the right +thing" in __name__ == '__main__' comparisons. + +usage:: + + # place this at the top a module, before doing any relative imports + from fix_mexec import fix_mexec + fix_mexec(__name__, __file__) + del fix_mexec + + from ...foo import bar + + + +##<-- copy and paste code, assuming _fix_mexec resides in the current dir.. + +# some fixes for relative imports +# see --> [http://bugs.python.org/issue1510172] absolute/rellative import not working (works only current dir and below) +# see --> [http://mail.python.org/pipermail/python-ideas/2007-February/000232.html] PEP for executing a module in a +# ...package containing relative imports +from __future__ import absolute_import +if __name__ == '__main__': + import os + __path__ = [os.path.dirname(__file__)] + from ._fix_mexec import fix_mexec + fix_mexec(__name__, __file__) + del fix_mexec + + +##--> copy and paste code +''' + +import imp, os, sys +#******************************************************************************** +# +#******************************************************************************** +class MainName(str): + def __eq__(self, other): + if other == '__main__': return True + return str.__eq__(self, other) + def __ne__(self, other): + if other == '__main__': return False + return str.__ne__(self, other) + + +def fix_mexec(_name_, _file_): + """bugfix for relative imports not working + @param _name_: __name__ of the module + @param _file_: __file__ of the module + + @note: not complete: relies on __init__.py, .pyo (...) is ignored currently + """ + if _name_ == '__main__': + out = [] + # find allparent packages + p = os.path.dirname(os.path.abspath(_file_)) + prev = p + while True: + pkg = os.path.join(p, '__init__.py') + if os.path.isfile(pkg): + out.append([pkg, os.path.basename(p)]) + else: + break + prev = p + p = os.path.dirname(p) + if p == prev: + break + out.reverse() + + # adjust sub package names an import parent modules + name = None + for n, (fpath, name) in enumerate(out): + if n > 0: + name = out[n][1] = out[n -1][1] + '.' + out[n][1] + m = imp.load_source(name, fpath) + m.__path__ = [os.path.dirname(fpath)] + + # adjust name of the __main__ module + if name is not None: + m = sys.modules.pop('__main__') + # 'foo.bar..__main__' does not work for some reason. 'foo.bar' seems to work as expected + ##m.__name__ = _Name_(name + '.' + '__main__') + m.__name__ = MainName(name) + sys.modules[m.__name__] = m + + + Deleted: trunk/fclient/fclient/impl/ViewDownloads.py =================================================================== --- trunk/fclient/fclient/impl/ViewDownloads.py 2008-08-16 08:01:13 UTC (rev 914) +++ trunk/fclient/fclient/impl/ViewDownloads.py 2008-08-16 08:10:49 UTC (rev 915) @@ -1,196 +0,0 @@ -"""""" - - -from __future__ import absolute_import -if __name__ == '__main__': # see --> http://bugs.python.org/issue1510172 . works only current dir and below - import os; __path__ = [os.path.dirname(__file__)] - - -from PyQt4 import QtCore, QtGui - -from . import config -from .BaseRequestsWidget import RequestsWidget -#************************************************************************************ -# -#***********************************************************************************... [truncated message content] |
From: <jU...@us...> - 2008-08-16 08:01:03
|
Revision: 914 http://fclient.svn.sourceforge.net/fclient/?rev=914&view=rev Author: jUrner Date: 2008-08-16 08:01:13 +0000 (Sat, 16 Aug 2008) Log Message: ----------- no longer needed Removed Paths: ------------- trunk/fclient/fclient/impl/ViewBrowser.py Deleted: trunk/fclient/fclient/impl/ViewBrowser.py =================================================================== --- trunk/fclient/fclient/impl/ViewBrowser.py 2008-08-16 08:00:12 UTC (rev 913) +++ trunk/fclient/fclient/impl/ViewBrowser.py 2008-08-16 08:01:13 UTC (rev 914) @@ -1,1381 +0,0 @@ -#****************************************************************************************** -#TODO: -# x. someday. maybe. reimpl to browse via fcp -# x. page history is cleared if we get an error on loading a page. reimpl page history? -# x. back-is-close like behaviour -# x. backand forward buttons suck somehow. sometimes fwd is enabled even if no fwd is available. reimpl page history? -# x. save page to disk -# x. download. idea is to add dls to global download widget and mark them (some color code) as new content. -# alt would be to to do it firefox like in a separate widget. maybe an option to adjust if browser dls should be -# persistent or not -# x. tool buttons do not adjust their size to icon size. maybe it is some global setting via qt-config -# x. fProxy is a bit tight-lipped when it comes to feedback. no idea -# x. give feedback on tabs about load / finisched / error. maybe some color code. wait for new QTabWidget features (qt4.5) -# x. close button on tabs. wait for new QTabWidget features (qt4.5) -# x. page actions: CopyImageToClipboard? -# x. when mouse pointer is over an opend image a magnifier cursor appears. no idea how this is handled -# x. open new tab on tab bar double click. IIRC looks like no way before qt4.5. tabBars are not stretched to fit in qt4.4 -# x. global feedback on statusbar flickers. reason: first label is holds arbitrary length text -# x. fproxy. "force browser to dl" should we dl it in downloads or store emidiately? no idea -# x. visiting plugins via fproxy does not work -# x. real toolbars -# x. remove host/port from urls? -# x. browser settings - QWebSettings -# x. shortcuts -# x. user staring gui for first time. maybe we should not connext untill the user connects explicitely -# x. looks like on error loading page reload does not work -# x. when loading a page, until fproxy reacts reload is enabled instead of stop. hitting reloading will trigger an error -# page, but reloads the current page as expected. no idea how to handle error page poping up. -# x. icons on find bar push button text tio the side. no idea so far -# x. on find action, give feedback when no matching text was found on page -# x. some shortcuts for actions are still missing -# x. rework to support dynamic retranslation -# x. tooltips for tabs showing truncated title -# x. reduce tab width when many tabs are open to allow for more tabs being visible -# x. tab context menu: "Close all tabs" is a bit of a trap. maybe remove or place it on the very bottom once we have -# more menu entries -# x. dropping. accept keys +1. what else to accept? -# x. option to upload content from browser? "upload current page" / image ..whatevs -# x. print contents -# x. a note on "save link". if it points to a html page, no media is saved, just the html -# x. close icon for ActionCloseSideBar -# x. peformance of QWebView sucks when it comes to rendering images -# x. on some pages images are not be loaded (no network error?!) while ff loads them without any problems -# -#******************************************************************************************* -#TODO: code -# -# x. isolate browser better. state data should be provided by browser -# x. when done, assign timers for tabProgressbars to browser as userData -# x. separate browser and sideBar controllers -# -#****************************************************************************************** -""" - -@newfield signal: signal, signals -""" -from __future__ import absolute_import -if __name__ == '__main__': # see --> http://bugs.python.org/issue1510172 . works only current dir and below - import os; __path__ = [os.path.dirname(__file__)] - -import os -from PyQt4 import QtCore, QtGui, QtWebKit - -from . import config - -from .lib import fcp2 -from .lib.qt4ex.lib import tools as qtools -from .lib.compactpath.qt4 import pathlabelwrap - -from . import DlgPropsBrowserObject -from . import SideBarLoadDetails - -from .tpls.Ui_ViewBrowserWidgetTpl import Ui_ViewBrowserWidget -#***************************************************************************************** -# -#***************************************************************************************** -class BrowserSideBar: - """template for sidebars""" - - def __init__(self, parent=None, closeAction=None): - """ - @param parent: parent widget - @param closeAction: (QAction) that should be triggered to close the sideBar - """ - def setCurrent(self, browserWidget, flag): - """ - @param browserWidget: browser widget the sideBar is attatched to - @param flag: (bool) True if the sideBar is the current sidebar now, False otherwise - """ - -#***************************************************************************************** -# -#***************************************************************************************** -# to browse via fcp... -from PyQt4 import QtNetwork -class NetworkAccessManager(QtNetwork.QNetworkAccessManager): - - def __init__(self, parent): - QtNetwork.QNetworkAccessManager.__init__(self, parent) - - def createRequest(self, operation, request, outgoingData): - reply = QtNetwork.QNetworkAccessManager.createRequest(self, operation, request, outgoingData) - self.emit(QtCore.SIGNAL('networkRequestCreated(QNetworkReply*)'), reply) - #print 'createRequest', reply.url() - #self.connect(reply, QtCore.SIGNAL('downloadProgress(qint64, qint64)'), self.foo) - return reply - - def foo(self, *args): - print args - - -class Page(QtWebKit.QWebPage): - def __init__(self, parent): - QtWebKit.QWebPage.__init__(self, parent) - - self.setNetworkAccessManager(NetworkAccessManager(self)) - #def acceptNavigationRequest(self, frame, request, typeRequest): - # return True - -#***************************************************************************************** -# -#***************************************************************************************** -class NetworkReplyData(QtCore.QObject): - def __init__(self, parent, url): - QtCore.QObject.__init__(self, parent) - self.url = url - self.bytesReceived = 0 - self.bytesTotal = 0 - self.finished = False - self.errorCode = None - - -class Browser(QtWebKit.QWebView): - """ browser customized for freenet - """ - - MaxProgress = 100 - - def __init__(self, parent=None, userData=None): - QtWebKit.QWebView.__init__(self, parent) - - page = Page(self) - self.setPage(page) - - #NOTE: we store last progress made to set busy cursor accordingly - self._lastProgress = 0 - self._userData = userData - self._networkGetReplies = [[], []] # (QNetworkReplies, urls) - self._networkReplySignals = ( - ('downloadProgress(qint64, qint64)', self.onNetworkReplyDownloadProgress), - ('error(QNetworkReply::NetworkError)', self.onNetworkReplyError), - ('finished()', self.onNetworkReplyFinished), - ) - - # connect actions - self.connect(self, QtCore.SIGNAL('loadStarted()'), self.onLoadStarted) - self.connect(self, QtCore.SIGNAL('loadProgress(int)'), self.onLoadProgress) - self.connect(self, QtCore.SIGNAL('loadFinished(bool)'), self.onLoadFinished) - self.connect(self.pageAction(QtWebKit.QWebPage.Stop), QtCore.SIGNAL('triggered()'), self.onActionStopTriggered) - - ################################ - ## methods - ################################ - #TODO: impl in BrowserWidget - def lastProgress(self): - """returns the last progress made by the browser - @return: (int) last progress - """ - return self._lastProgress - - def networkGetReplies(self): - return self._networkGetReplies[1] - - def networkGetReply(self, indexReply): - return self._networkGetReplies[1][indexReply] - - def setUserData(self, userData): - self._userData = userData - - def userData(self): - return self._userData - - ################################ - ## overwritten methods - ################################ - #def createWindow(self, typeWindow): - # pass - - def load(self, url): - self._lastProgress = 0 - return QtWebKit.QWebView.load(self, url) - - def setUrl(self, url): - return self.load(url) - - def setContents(self, *args): - """sets the contents of the browser without changing its url""" - self._lastProgress = 0 - return QtWebKit.QWebView.setContents(self, *args) - - def setHtml(self, *args): - """sets the contents of the browser without changing its url""" - self._lastProgress = 0 - return QtWebKit.QWebView.setHtm(self, *args) - - def setPage(self, page): - """""" - self._lastProgress = 0 - self.connect( - page.networkAccessManager(), - QtCore.SIGNAL('networkRequestCreated(QNetworkReply*)'), - self.onNetworkRequestCreated - ) - - self.emit(QtCore.SIGNAL('pageSet(QWebPage*)'), page) - return QtWebKit.QWebView.setPage(self, page) - - def mouseMoveEvent(self, event): - QtWebKit.QWebView.mouseMoveEvent(self, event) - if self._lastProgress < self.MaxProgress: - self.setCursor(QtCore.Qt.BusyCursor) - - ############################### - ## event handlers - ############################### - def onActionStopTriggered(self): - # check wich cursor to set cos we may have busy cursor set - pt = self.mapFromGlobal(self.cursor().pos()) #TODO: self.mapFromGlobal(self.viewPort().cursor().pos()) ?? - frame = self.page().currentFrame() - hitTest = frame.hitTestContent(pt) - #if not hitTest.isNull(): #TODO: looks like hitTest.isNull() alwas returns True - if hitTest.linkUrl().isValid(): - self.setCursor(QtCore.Qt.PointingHandCursor) - else: - self.setCursor(QtCore.Qt.ArrowCursor) - - def onLoadStarted(self): - self._lastProgress = 0 - self._networkGetReplies = [[], []] - - def onLoadProgress(self, n): - self._lastProgress = n - - def onLoadFinished(self, ok): - if ok: - self._lastProgress = self.MaxProgress - self.onActionStopTriggered() - - def onPageDownloadRequested(self, networkRequest): - self.emit(QtCore.SIGNAL('downloadRequested(const QNetworkRequest &)'), networkRequest) - - def onNetworkRequestCreated(self, reply): - if reply.operation() == NetworkAccessManager.GetOperation: - self._networkGetReplies[0].append(reply) - url = QtCore.QUrl(reply.url()) # copy url, qt nules it on return - networkReplyData = NetworkReplyData(self, url) - self._networkGetReplies[1].append(networkReplyData) - for signal, handler in self._networkReplySignals: - self.connect(reply, QtCore.SIGNAL(signal), handler) - self.emit(QtCore.SIGNAL('networkGetRequestCreated(int, QObject*)'), self._networkGetReplies[0].index(reply), networkReplyData) - - def onNetworkReplyDownloadProgress(self, bytesReceived, bytesTotal): - reply = self.sender() - i = self._networkGetReplies[0].index(reply) - networkReplyData = self._networkGetReplies[1][i] - networkReplyData.bytesReceived = bytesReceived - networkReplyData.bytesTotal = bytesTotal - self.emit(QtCore.SIGNAL('networkReplyProgress(int, QObject*)'), i, networkReplyData) - - def onNetworkReplyError(self, errorCode): - reply = self.sender() - i = self._networkGetReplies[0].index(reply) - networkReplyData = self._networkGetReplies[1][i] - networkReplyData.finished = True - networkReplyData.errorCode = errorCode - self.emit(QtCore.SIGNAL('networkReplyError(int, QObject*)'), i, networkReplyData) - #for signal, handler in self._networkReplySignals: - # self.disconnect(reply, QtCore.SIGNAL(signal), handler) - - def onNetworkReplyFinished(self): - reply = self.sender() - i = self._networkGetReplies[0].index(reply) - networkReplyData = self._networkGetReplies[1][i] - networkReplyData.finished = True - for signal, handler in self._networkReplySignals: - self.disconnect(reply, QtCore.SIGNAL(signal), handler) - self.emit(QtCore.SIGNAL('networkReplyFinished(int, QObject*)'), i, networkReplyData) - -#********************************************************************************** -# -#********************************************************************************** -class BrowserWidgetGlobalFeedback(config.GlobalFeedbackBase): - """wrapper for global statusbar widgets, menus""" - - def __init__(self, parent, idGlobalFeedback): - config.GlobalFeedbackBase.__init__(self, parent, idGlobalFeedback) - - # menus - self.menus = [] - if self.menuBar is not None and hasattr(parent, 'fcViewObject'): - menu = QtGui.QMenu(parent.fcViewObject.displayName, self.menuBar) - parent.populateMenu(menu) - self.menus.append(menu) - self.menuBar.addViewMenu(menu) - - # status bar widgets - self.labelStatus = None - self.progress = None - self.labelFeedbackWrap = None - if self.statusBar is not None: - label = QtGui.QLabel(self.statusBar) - label.setFrameStyle(QtGui.QLabel.Sunken | QtGui.QLabel.Box) - self.labelFeedbackWrap = pathlabelwrap.PathLabelWrap( - label, - path_module=config.CompactPathFcpKeyModule, - ) - self.statusBar.addWidget(self.labelFeedbackWrap.label, 10) - - def setVisible(self, flag): - if self.menuBar is not None: - for menu in self.menus: - menu.children()[0].setEnabled(flag) - if self.statusBar is not None: - self.labelFeedbackWrap.label.setVisible(flag) - - def setFeedback(self, qString): - if self.labelFeedbackWrap is not None: - self.labelFeedbackWrap.setPath(unicode(qString)) - - -class BrowserWidgetViewObject(config.ViewObject): - - def __init__(self, parent): - config.ViewObject. __init__(self, parent) - - self.name=parent.objectName() - self.displayName=self.trUtf8('Browser') - self.icon=QtGui.QIcon() - - -class BrowserWidgetSettings(config.SettingsBase): - _key_ = config.IdViewBrowserWidget - _settings_ = ( - ('OpenLinksInNewTab', 'Bool', False), - ('OpenAddressBarInNewTab', 'Bool', False), - ('OpenBookmarksInNewTab', 'Bool', False), - ('OpenHomePageOnNewTabCreated', 'Bool', False), - ('BackIsClose', 'Bool', False), #TODO: not implemented - ('HomePage', 'String', QtCore.QString()), - ('AutoLoadImages', 'Bool', True), #TODO: not yet implemented - ('MaxTabText', 'UInt', 15), #NOTE: make shure Max >= Min and Max and Min > 0 - ('MinTabText', 'UInt', 15), - - ('TabProgressBarColor', 'QColor', QtGui.QColor('blue')), - ('TabProgressBarAlpha', 'UInt', 55), - - ('SplitterPos', 'ByteArray', QtCore.QByteArray()), - ('LastSideBarAction', 'String', QtCore.QString('')), - - ) - - def setValues(self, **kws): - config.SettingsBase.setValues(self, **kws) - if not self.parent().isCreated: - return - - autoLoadImages = kws.get('AutoLoadImages', None) - if autoLoadImages is not None: - browserWidget = self.parent() - tabWidget = browserWidget.controlById(browserWidget.IdTabBrowsers) - for i in xrange(tabWidget.count()): - browser = tabWidget.widget(i) - if hasattr(browser, 'settings'): # QTabWidget may return a Null QWidget - settings = browser.settings() - settings.setAttribute(settings.AutoLoadImages, autoLoadImages) - - if kws.get('TabProgressBarColor', None) is not None or kws.get('TabProgressBarAlpha', None) is not None: - tabWidget = browserWidget.controlById(browserWidget.IdTabBrowsers) - tabWidget.tabBar().repaint() - - - #backIsClose = kws.get('BackIsClose', None) - #if backIsClose is not None: - # self.parent()._adjustBackIsClose() - - - -class BrowserWidgetActions(config.ActionsBase): - - def __init__(self, parent): - config.ActionsBase.__init__(self, parent) - - iconSize = config.fcSettings.value('IconSize') - iconTheme = config.fcSettings.value('IconTheme') - - #TODO: shortcut - self.action( - name='ActionCloseCurrentTab', - text=self.trUtf8('Close ¤t tab'), - trigger=parent.onCloseCurrentTab, - ) - #TODO: shortcut - self.action( # context menu only - name='ActionCloseBrowserUnderMouse', - text=self.trUtf8('&Close tab'), - trigger=None, - ) - self.action( - name='ActionCloseAllTabs', - text=self.trUtf8('Close &all tabs'), - trigger=parent.onCloseAllTabs, - ) - #TODO: shortcut - self.action( - name='ActionCreateNewTab', - text=self.trUtf8('Create &new tab'), - trigger=parent.onCreateNewTab, - ) - #TODO: shortcut - self.action( - name='ActionDuplicateTab', - text=self.trUtf8('&Duplicate tab'), - trigger=parent.onDuplicateTab, - ) - - #TODO: shortcut - self.action( - name='ActionGoToFProxy', - text=self.trUtf8('Go to f&Proxy homepage'), - trigger=parent.onGoToFProxy, - ) - self.action( - name='ActionGoToHomePage', - text=self.trUtf8('Go to &homepage'), - shortcut=QtGui.QKeySequence(self.trUtf8('Alt+Home')), - trigger=parent.onGoToHomePage, - ) - #TODO: shortcut - self.action( - name='ActionObjectProperties', - text=self.trUtf8('Properties..'), - trigger=None, - ) - self.action( - name='ActionZoomIn', - text=self.trUtf8('Zoom in'), - shortcut=QtGui.QKeySequence(QtGui.QKeySequence.ZoomIn), - trigger=parent.onZoomIn, - ) - self.action( - name='ActionZoomOut', - text=self.trUtf8('Zoom out'), - shortcut=QtGui.QKeySequence(QtGui.QKeySequence.ZoomOut), - trigger=parent.onZoomOut, - ) - - # default browser actions - self.action( - name='ActionBack', - text=self.trUtf8('Back'), - trigger=None, - isEnabled=False, - shortcut=QtGui.QKeySequence(QtGui.QKeySequence.Back), - icon=config.fcResources.getIcon('back', iconSize, iconTheme=iconTheme), - userData=(None, None), - ) - self.action( - name='ActionForward', - text=self.trUtf8('Forward'), - trigger=None, - isEnabled=False, - shortcut=QtGui.QKeySequence(QtGui.QKeySequence.Forward), - icon=config.fcResources.getIcon('forward', iconSize, iconTheme=iconTheme), - userData=(None, None), - ) - self.action( - name='ActionReload', - text=self.trUtf8('Reload'), - #EXPERIMENTAL: we handle it, cos page.url() is empty if fproxy did not respond. - # for some reason QWebView has "Reload" enabled in this case. we keep track of - # the last known url and reload it manually. hope we don't get into trouble with - # this. NOTE: we may have to do this for other actions aswell - trigger=parent.onBrowserReloadTriggered, - isEnabled=False, - #TODO: how to assign QKeySequence.Refresh and* F5 ? - shortcut=QtGui.QKeySequence(QtGui.QKeySequence.Refresh), - icon=config.fcResources.getIcon('reload_page', iconSize, iconTheme=iconTheme), - userData=(None, None), - ) - self.action( - name='ActionStop', - text=self.trUtf8('Stop'), - trigger=None, - isEnabled=False, - shortcut=QtGui.QKeySequence(self.trUtf8('Esc')), - icon=config.fcResources.getIcon('stop', iconSize, iconTheme=iconTheme), - userData=(None, None), - ) - self.action( - name='ActionBackIsClose', - text=self.trUtf8('Back is close'), - icon=config.fcResources.getIcon('button_cancel', iconSize, iconTheme=iconTheme), - trigger=None, - ) - - # find actions - self.action( - name='ActionFind', - text=self.trUtf8('Find'), - shortcut=QtGui.QKeySequence(QtGui.QKeySequence.Find), - trigger=parent.onFind, - ) - self.action( - name='ActionFindNext', - text=self.trUtf8('Find next'), - isEnabled=False, - shortcut=QtGui.QKeySequence(QtGui.QKeySequence.FindNext), - trigger=parent.onFindNext, - ) - self.action( - name='ActionFindPrevious', - text=self.trUtf8('Find previous'), - isEnabled=False, - shortcut=QtGui.QKeySequence(QtGui.QKeySequence.FindPrevious), - trigger=parent.onFindPrevious, - ) - self.action( - name='ActionSavePage', - text=self.trUtf8('Save page..'), - isEnabled=True, - ##shortcut=QtGui.QKeySequence(QtGui.QKeySequence.FindPrevious), - trigger=parent.onSavePage, - ) - - # sideBars - group = self.group( - name='GroupSideBars', - isExclusive=True, - trigger=parent.onShowSidebar, - ) - self.action( - name='ActionShowSideBarLoadDetails', - group=group, - text=self.trUtf8('Load details'), - isEnabled=True, - isCheckable=True, - ) - - self.action( - name='ActionCloseCurrentSideBar', - text=self.trUtf8('Close sidebar'), - isEnabled=True, - trigger=parent.onCloseCurrentSideBar, - ) - - - def intertwineBrowserActions(self, browser=None): - """intertwines Browser actions with BrowserWidget actions - @note: call everytime the current browser changes - """ - actions = ( - ('ActionBack', QtWebKit.QWebPage.Back), - ('ActionForward', QtWebKit.QWebPage.Forward), - ('ActionReload', QtWebKit.QWebPage.Reload), - ('ActionStop', QtWebKit.QWebPage.Stop), - ) - for actionName, pageAction in actions: - myPageAction = self[actionName] - newPageAction = None if browser is None else browser.pageAction(pageAction) - oldPageAction, cb = myPageAction.userData() - - if oldPageAction is not None: - myPageAction.disconnect(oldPageAction, QtCore.SIGNAL('changed()'), cb) - oldPageAction.disconnect(myPageAction, QtCore.SIGNAL('triggered()'), oldPageAction.trigger) - - if newPageAction is None: - myPageAction.setUserData((None, None)) - myPageAction.setEnabled(False) - else: - def onActionChanged(browser=browser, myPageAction=myPageAction, browserPageAction=newPageAction): - myPageAction.setEnabled(browserPageAction.isEnabled()) - - myPageAction.setEnabled(newPageAction.isEnabled()) - myPageAction.setUserData((newPageAction, onActionChanged)) - myPageAction.connect(newPageAction, QtCore.SIGNAL('changed()'), onActionChanged) - newPageAction.connect(myPageAction, QtCore.SIGNAL('triggered()'), newPageAction.trigger) - - -class LastBrowserState(object): - """records the last known state browser""" - - StateNone = 0x0 - StateLoading = 0x1 - StateComplete = 0x2 - StateError = 0x4 - StateHideProgressBar = 0x100 - - - __slots__ = ('clearProgressBarTimers', 'icon', 'progress', 'state', 'statusMessage', 'title', 'url') - - def __init__(self, icon=None, progress=0, statusMessage=None, state=StateNone, title=None, url=None): - self.clearProgressBarTimers = [] # timers scheduled for hiding progressBar - self.progress = 0 - self.icon = tCore.QIcon() if icon is None else icon - self.state = state - self.statusMessage = QtCore.QString() if statusMessage is None else statusMessage - self.title = QtCore.QString() if title is None else title - #NOTE: opening a browser in a new tab may take a while to load. - # self.url() will return '' untill the page is found, so we handle - # it ourself and keep track of the last known url in self._lastUrl - # to give feedback to the user on the navbar. downside is we have - # to reimplement contextMenuEvent() :-( - self.url = QtCore.QUrl() if url is None else url - - -class BrowserTabBar(QtGui.QTabBar): - """customized tabBar to show progress indicstor on tabs""" - - #EXPERIMENTAL: to show progressBar at 100% use a timer to clear it after - # a short delay. current implementation may pile up timers, not doing any - # harm to the progressBar though. we'd have to remove all obsolete timers - # (user hitting links like crazy), but no idea if we may run into strange race - # conditions - # - #NOTE: excessive link hitting will trigger a Qt unhandled sooner or later: - # >>> QAbstractSocket::connectToHost() called when already connecting/connected - # ...looks like we're not alone when it comes to race conditions :-) - class ClearProgressbarTimer(QtCore.QTimer): - - def __init__(self, parent, lastBrowserState): - QtCore.QTimer.__init__(self, parent) - self.lastBrowserState = lastBrowserState - self.setSingleShot(True) - self.start(500) - self.connect(self, QtCore.SIGNAL('timeout()'), self.onTimeout) - - def onTimeout(self): - self.lastBrowserState.clearProgressBarTimers.remove(self) - if not self.lastBrowserState.clearProgressBarTimers: - if not self.lastBrowserState.state & self.lastBrowserState.StateHideProgressBar: - self.lastBrowserState.state |= self.lastBrowserState.StateHideProgressBar - self.parent().repaint() - - def __init__(self, parent, fcSettings): - QtGui.QTabBar.__init__(self, parent) - self.fcSettings = fcSettings - - def paintEvent(self, event): - # let QTabBar do the dirty work and draw over with a big brush - QtGui.QTabBar.paintEvent(self, event) - - application = QtGui.QApplication.instance() - painter = QtGui.QPainter(self) - for i in xrange(self.count()): - browser = self.parent().widget(i) - lastBrowserState = browser.userData() - if lastBrowserState.state & lastBrowserState.StateHideProgressBar: - continue - if lastBrowserState.state & (lastBrowserState.StateComplete | lastBrowserState.StateError): - timer = self.ClearProgressbarTimer(self, lastBrowserState) - lastBrowserState.clearProgressBarTimers.append(timer) - color = QtGui.QColor(self.fcSettings.value('TabProgressBarColor')) - color.setAlpha(self.fcSettings.value('TabProgressBarAlpha')) - brush = QtGui.QBrush(color) - rc = self.tabRect(i) - rc.adjust(4, 4, -4, -4) - w = int(rc.width() * (float(lastBrowserState.progress) / 100)) - painter.setClipRect(rc.left(), rc.top(), w, rc.height()) - painter.fillRect(rc, brush) - -#********************************************************************************** -# -#********************************************************************************** -#TODO: strip host:port on address bar? -#TODO: rename home page to start page -class ViewBrowserWidget(QtGui.QWidget, Ui_ViewBrowserWidget): - - IdTabBrowsers = 'tabBrowsers' - IdFrameTools = 'frameTools' - IdFrameAddressBar = 'frameAddressBar' - IdEdAddressBar = 'edAddressBar' - - IdTabSideBar = 'tabSideBar' - IdSplitter = 'splitter' - - IdBtBack = 'btBack' - IdBtForward = 'btForward' - IdBtReload = 'btReload' - IdBtStop = 'btStop' - - IdFrameFind = 'frameFind' - IdEdFind = 'edFind' - IdBtFindPrevious = 'btFindPrevious' - IdBtFindNext= 'btFindNext' - IdCkFindCaseSensitive = 'ckFindCaseSensitive' - - ForcedMinBrowserTabText = 5 # forced minimum number of chars on browser tabBar - - def __init__(self, parent, idGlobalFeedback=config.IdMainWindow): - QtGui.QWidget.__init__(self, parent) - - self.menuSideBars = QtGui.QMenu(self.trUtf8('Side bars')) #TODO: retranslate - - self.setupUi(self) - config.ObjectRegistry.register(self) - - self.isCreated = False - self._initialConfigDataArrived = False - - self.fcSettings = BrowserWidgetSettings(self).restore() - self.fcActions = BrowserWidgetActions(self) - self.fcViewObject = BrowserWidgetViewObject(self) - self.fcGlobalFeedback = BrowserWidgetGlobalFeedback(self, idGlobalFeedback) - - # setup - iconSize = config.fcSettings.value('IconSize') - iconTheme = config.fcSettings.value('IconTheme') - - # setup tab bar - tabWidget = self.controlById(self.IdTabBrowsers) - tabWidget.clear() # clear, setTabBar() seems to take over alreeady present tabs (qt-designer!) - tabWidget.setTabBar(BrowserTabBar(tabWidget, self.fcSettings)) - tabWidget.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) - self.connect(tabWidget, QtCore.SIGNAL('currentChanged(int)'), self.onTabCurrentChanged) - self.connect(tabWidget, QtCore.SIGNAL('customContextMenuRequested(const QPoint &)'), self.onTabContextMenuEvent) - - # setup sideBar - tabWidget = self.controlById(self.IdTabSideBar) - tabWidget.clear() # clear, setTabBar() seems to take over alreeady present tabs (qt-designer!) - tabWidget.setVisible(False) - tabWidget.tabBar().setVisible(False) - - # add sideBars - for action in self.fcActions['GroupSideBars'].actions(): - self.menuSideBars.addAction(action) - self.sideBarLoadDetails = SideBarLoadDetails.SideBarLoadDetails(tabWidget, closeAction=self.fcActions['ActionCloseCurrentSideBar']) - tabWidget.addTab(self.sideBarLoadDetails, self.trUtf8('Load details')) - - # setup splitter - splitter = self.controlById(self.IdSplitter) - splitter.restoreState(self.fcSettings.value('SplitterPos')) - self.connect(splitter, QtCore.SIGNAL('splitterMoved(int, int)'), self.onSplitterMoved) - - # setup addressBar - addressbar = self.controlById(self.IdEdAddressBar) - self.connect(addressbar, QtCore.SIGNAL('returnPressed()'), self.onNavBarReturnPressed) - - # setup tool buttons - self.controlById(self.IdBtBack).setDefaultAction(self.fcActions['ActionBack']) - self.controlById(self.IdBtForward).setDefaultAction(self.fcActions['ActionForward']) - self.controlById(self.IdBtReload).setDefaultAction(self.fcActions['ActionReload']) - self.controlById(self.IdBtStop).setDefaultAction(self.fcActions['ActionStop']) - - # setupp search bar - bt = self.controlById(self.IdBtFindPrevious) - self.connect(bt, QtCore.SIGNAL('clicked()'), self.fcActions['ActionFindPrevious'].trigger) - bt.setIcon(config.fcResources.getIcon('arrow_up',iconSize, iconTheme=iconTheme)) - bt = self.controlById(self.IdBtFindNext) - bt.setIcon(config.fcResources.getIcon('arrow_down', iconSize, iconTheme=iconTheme)) - self.connect(bt, QtCore.SIGNAL('clicked()'), self.fcActions['ActionFindNext'].trigger) - ed = self.controlById(self.IdEdFind) - self.connect(ed, QtCore.SIGNAL('returnPressed()'), self.fcActions['ActionFindNext'].trigger) - self.connect(ed, QtCore.SIGNAL('textChanged(const QString &)'), self.onEdFindTextChanged) - frameFind = self.controlById(self.IdFrameFind) - frameFind.setVisible(False) - - # finally - #TODO: hopefuly the user will not play around with this setting - actionName = self.fcSettings.value('LastSideBarAction') - action = self.fcActions.get(actionName, None) - if action is not None: - action.trigger() - - ######################################### - ## private methods - ######################################### - def _adjustCurrentBrowserDependendStuff(self): - self.fcActions.intertwineBrowserActions(self.currentBrowser()) - if self.sideBarLoadDetails.isVisible(): - self.sideBarLoadDetails.setBrowser(self.currentBrowser()) - - #NOTE: to reduce flicker set min size to max size - def _adjustTabText(self, qString): - maxTabText = self.fcSettings.value('MaxTabText') - minTabText = self.fcSettings.value('MinTabText') - ellipsis = self.trUtf8('..') - - if minTabText < self.ForcedMinBrowserTabText: - minTabText = self.ForcedMinBrowserTabText - self.fcSettings.setValues(MinTabText=minTabText) - if maxTabText < self.ForcedMinBrowserTabText: - maxTabText = self.ForcedMinBrowserTabText - self.fcSettings.setValues(MaxTabText=maxTabText) - if minTabText > maxTabText: - minTabText = maxTabText - self.fcSettings.setValues(MinTabText=maxTabText) - - if qString.count() < minTabText: - qString = qString.append('\x20' * (minTabText - qString.count())) - else: - if maxTabText < self.ForcedMinBrowserTabText: - maxTabText = sminTabText - qString = qtools.truncateString(maxTabText, qString, ellipsis) - return qString - - def _downloadImageToDisk(self, hitTestResult): - px = hitTestResult.pixmap() - if px.isNull(): - return False - - key = config.qStringToFcpKey(hitTestResult.imageUrl().toString()) - if key is None: - return False - - # thow a dialog box at the user to select a filename - # ..qt seems to place the filename part as suggestion into the filename box. so try it - caption = config.FcAppName + self.trUtf8(' - Save Image To..') - directory = unicode(config.fcSettings.value('DownloadDir')) - fileName = unicode(config.guessFileNameFromKey(key, default=QtCore.QString(''))) - - if directory and fileName: - directory = os.path.join(directory, fileName) - elif not directory: - directory = fileName - filePath = QtGui.QFileDialog.getSaveFileName(self, caption, directory) - - if filePath: - filePath= unicode(filePath) - if os.path.exists(filePath): - try: - os.remove(filePath) - except Exception, details: - QtGui.QMessageBox.critical( - self, - caption, - self.trUtf8('Could not remove file'), #NOTE: no details please, may contain arbitrary lenght filepath - ) - return False - px.save(filePath) - return True - - def _downloadKeyToDisk(self, qUrl): - """ - @return: (bool) False if the key in the url is invalid, True otherwise - """ - fcpKey = config.qStringToFcpKey(QtCore.QString(qUrl.encodedPath())) - if fcpKey is None: - QtGui.QMessageBox.critical( - self, - config.FcAppName + self.trUtf8(' - Browser error'), - self.trUtf8('Can not download key (key is invalid)') - ) - return False - downloadsWidget = config.ObjectRegistry.get(config.IdViewDownloadsWidget, None) - if downloadsWidget is None: - raise ValueError('no downloads widget found') - downloadsWidget.execDlgDownloadKey(fcpKey=fcpKey) - return True - - ######################################### - ## methods - ######################################### - def controlById(self, idControl): - return getattr(self, idControl) - - def currentBrowser(self): - """returns the current browser or None""" - tabWidget = self.controlById(self.IdTabBrowsers) - widget = tabWidget.currentWidget() - if isinstance(widget, Browser): - return widget - - def load(self, url, force=False, browser=None): - """loads an url in the current browser. if there is no current browser, a new browser is created - @param force: (bool) if True, a new browser is opend if there is no browser available - @param browser: browser to load the url in or None to use the current browser - @return: (bool) - """ - browser = self.currentBrowser() if browser is None else browser - tabWidget = self.controlById(self.IdTabBrowsers) - addressBar = self.controlById(self.IdEdAddressBar) - url = QtCore.QUrl(url) - - # check if we have a browser at hand - if force and browser is None: - browser = self.newBrowser() - if browser is None: - return False - - connectionWidget = config.ObjectRegistry.get(config.IdViewConnectionWidget, None) - if connectionWidget is None: - raise ValueError('No connection widget found') - - # load url - url.setScheme('http') - url.setHost(connectionWidget.fcSettings.value('FproxyConnectionHost')) - url.setPort(connectionWidget.fcSettings.value('FproxyConnectionPort')) - tabWidget.setTabText(tabWidget.indexOf(browser), self._adjustTabText(self.trUtf8('Loading'))) - addressBar.setText(url.toString()) - lastBrowserState = browser.userData() - lastBrowserState.state = lastBrowserState.StateLoading - lastBrowserState.url = url - browser.load(url) - return True - - def newBrowser(self, title=''): - """opens a browser in a new tab""" - tabWidget = self.controlById(self.IdTabBrowsers) - browser = Browser(self) - page = browser.page() - settings = browser.settings() - title = QtCore.QString(title) - - # attatch browser state information - lastBrowserState = LastBrowserState( - icon=browser.icon(), - statusMessage=self.trUtf8('Waiting'), - ) - browser.setUserData(lastBrowserState) - - # customize browser - browser.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) - settings.setAttribute(settings.DeveloperExtrasEnabled, False) - settings.setAttribute(settings.JavaEnabled, False) - settings.setAttribute(settings.JavascriptEnabled, False) - settings.setAttribute(settings.JavascriptCanOpenWindows, False) - settings.setAttribute(settings.JavascriptCanAccessClipboard, False) - settings.setAttribute(settings.PluginsEnabled, False) - settings.setAttribute(settings.AutoLoadImages, self.fcSettings.value('AutoLoadImages')) - - # connect browser signals - self.connect(browser, QtCore.SIGNAL('loadStarted()'), self.onBrowserLoadStarted) - self.connect(browser, QtCore.SIGNAL('loadProgress(int)'), self.onBrowserLoadProgress) - self.connect(browser, QtCore.SIGNAL('loadFinished(bool)'), self.onBrowserLoadFinished) - self.connect(browser, QtCore.SIGNAL('iconChanged()'), self.onBrowserIconChanged) - self.connect(browser, QtCore.SIGNAL('statusBarMessage(const QString &)'), self.onBrowserStatusBarMessage) - self.connect(browser, QtCore.SIGNAL('titleChanged(const QString &)'), self.onBrowserTitleChanged) - self.connect(browser, QtCore.SIGNAL('urlChanged(const QUrl &)'), self.onBrowserUrlChanged) - self.connect(browser, QtCore.SIGNAL('customContextMenuRequested(const QPoint &)'), self.onBrowserCustomContextMenuRequested) - self.connect(browser, QtCore.SIGNAL('linkClicked(const QUrl &)'), self.onBrowserLinkClicked) - - # adjust browser actions - act = browser.pageAction(page.OpenLinkInNewWindow) - act.setText(self.trUtf8('Open page in new tab')) - act = browser.pageAction(page.OpenImageInNewWindow) - act.setText(self.trUtf8('Open image in new tab')) - act = browser.pageAction(page.OpenFrameInNewWindow) - act.setText(self.trUtf8('Open frame in new tab')) - - - # customize page - page.setLinkDelegationPolicy(page.DelegateAllLinks) - - # connect page signals - self.connect(page, QtCore.SIGNAL('linkHovered(const QString &, const QString &, const QString &)'), self.onPageLinkHovered) - - tabWidget.addTab(browser, self._adjustTabText(title)) - self._adjustCurrentBrowserDependendStuff() - return browser - - #TODO: rework. we need more then one menu - def populateMenu(self, menu): - menu.addAction(self.fcActions['ActionBack']) - menu.addAction(self.fcActions['ActionForward']) - menu.addAction(self.fcActions['ActionReload']) - menu.addAction(self.fcActions['ActionStop']) - menu.addAction(self.fcActions['ActionGoToFProxy']) - menu.addAction(self.fcActions['ActionGoToHomePage']) - menu.addAction(self.fcActions['ActionCloseCurrentTab']) - menu.addAction(self.fcActions['ActionCloseAllTabs']) - menu.addAction(self.fcActions['ActionCreateNewTab']) - menu.addAction(self.fcActions['ActionZoomIn']) - menu.addAction(self.fcActions['ActionZoomOut']) - menu.addAction(self.fcActions['ActionFind']) - menu.addAction(self.fcActions['ActionFindNext']) - menu.addAction(self.fcActions['ActionFindPrevious']) - - menu.addMenu(self.menuSideBars) - return menu - - ######################################### - ## overwritten methods - ######################################### - #TODO: retranslate adjusted browser actions for all browsers - #TODO: retranslate all tab texts we inserted. mabe a flag tabHasCustomText - def retranslateUi(self, me): - Ui_ViewBrowserWidget.retranslateUi(self, me) - - ######################################### - ## overwritten events - ######################################### - def closeEvent(self): - self.viewClose() - - def hideEvent(self, event): - self.fcGlobalFeedback.setVisible(False) - - def showEvent(self, event): - self.fcGlobalFeedback.setVisible(True) - if not self.isCreated: - self.isCreated = True - # fire up a new broser to make a start - #TODO: find a better time to fire up the browser. how do we know when the gui is up and running? - QtGui.QApplication.instance().processEvents() - self.newBrowser(title=self.trUtf8('Waiting for fproxy')) - QtGui.QApplication.instance().processEvents() - self.fcActions['ActionGoToHomePage'].trigger() - - def viewClose(self): - pass - - ######################################### - ## event handlers - ######################################### - #TODO: actions need some comb over - def onBrowserCustomContextMenuRequested(self, pt): - browser = self.sender() - frame = browser.page().currentFrame() - page = browser.page() - hitTestResult = frame.hitTestContent(pt) - pt = browser.mapToGlobal(pt) - - #if not hitTest.isNull(): #TODO: looks like hitTest.isNull() alwas returns True - - menu = QtGui.QMenu() - - menu.addAction(browser.pageAction(page.OpenLink)) - menu.addAction(browser.pageAction(page.OpenLinkInNewWindow)) - menu.addAction(browser.pageAction(page.CopyLinkToClipboard)) - menu.addAction(browser.pageAction(page.DownloadLinkToDisk)) - - menu.addSeparator() - menu.addAction(browser.pageAction(page.OpenImageInNewWindow)) - menu.addAction(browser.pageAction(page.CopyImageToClipboard)) - menu.addAction(browser.pageAction(page.DownloadImageToDisk)) - - menu.addSeparator() - menu.addAction(browser.pageAction(page.OpenFrameInNewWindow)) - - menu.addSeparator() - menu.addAction(browser.pageAction(page.Copy)) - menu.addAction(self.fcActions['ActionObjectProperties']) - - #TODO: QwebView assumes we can download queries - we can't - browser.pageAction(page.DownloadLinkToDisk).setEnabled(config.fcpClient.isConnected()) - if browser.pageAction(page.DownloadLinkToDisk).isEnabled(): - result = config.qStringToFcpKey(hitTestResult.linkUrl().toString()) - if result is None: - browser.pageAction(page.DownloadLinkToDisk).setEnabled(False) - - action = menu.exec_(pt) - - if action == browser.pageAction(page.OpenLinkInNewWindow): - browser = self.newBrowser(title=self.trUtf8('Loading')) - self.load(hitTestResult.linkUrl(), browser=browser) - elif action == browser.pageAction(page.OpenImageInNewWindow): - browser = self.newBrowser(title=self.trUtf8('Loading')) - self.load(hitTestResult.imageUrl(), browser=browser) - elif action == browser.pageAction(page.OpenFrameInNewWindow): - browser = self.newBrowser(title=self.trUtf8('Loading')) - self.load(hitTestResult.frame().url(), browser=browser) - elif action == browser.pageAction(page.DownloadImageToDisk): - self._downloadImageToDisk(hitTestResult) - elif action == browser.pageAction(page.DownloadLinkToDisk): - self._downloadKeyToDisk(hitTestResult.linkUrl()) - elif action == self.fcActions['ActionObjectProperties']: - dlg = DlgPropsBrowserObject.DlgPropsBrowserObject(self, hitTestResult=hitTestResult) - if dlg.exec_() == dlg.Accepted: - pass - - #TODO: nav buttons seem to get confused on error - def onBrowserLoadFinished(self, ok): - browser = self.sender() - lastBrowserState = browser.userData() - tabWidget = self.controlById(self.IdTabBrowsers) - - lastBrowserState.progress = Browser.MaxProgress - if ok: - lastBrowserState.state = lastBrowserState.StateComplete - lastBrowserState.statusMessage = self.trUtf8('Complete') - title = self.trUtf8('Complete') if lastBrowserState.title.isEmpty() else lastBrowserState.title - tabWidget.setTabText(tabWidget.indexOf(browser), self._adjustTabText(title)) - else: - # something went wrong. most likely fProxy can not be reached - lastBrowserState.state = lastBrowserState.StateError - lastBrowserState.statusMessage = self.trUtf8('Error') - tabWidget.setTabText(tabWidget.indexOf(browser), self._adjustTabText(self.trUtf8('Error'))) - #TODO: or maybe NOTE: we can not give any feedback to the user here, like - # injecting some html via JavaScript. Browser crashes when navigating to another - # page. looks like we should not interrupt the java code. maybe there is a way by intercepting - # the network request.. - - def onBrowserIconChanged(self, qIcon): - browser = self.sender() - qIcon = QtCore.QIcon(qIcon) # copy it - qt nukes it on return - - lastBrowserState = browser.userData() - if not qIcon.isNull(): - lastBrowserState = qIcon - self.tabWidget.setTabIcon(i, lastBrowserState.icon) - - def onBrowserLoadProgress(self, n): - browser = self.sender() - lastBrowserState = browser.userData() - lastBrowserState.state = lastBrowserState.StateLoading - - lastBrowserState.progress = n - - def onBrowserLinkClicked(self, qUrl): - browser = self.sender() - qUrl = QtCore.QUrl(qUrl) - query = unicode(qUrl.encodedQuery()) - - if query.lower() == 'forcedownload': - if not self._downloadKeyToDisk(qUrl): - self.fcGlobalFeedback.setFeedback(self.trUtf8('Invalid key!')) - else: # assume fproxy is doing the right thing - if self.fcSettings.value('OpenLinksInNewTab'): - browser = self.newBrowser(title=self.trUtf8('Loading')) - self.load(qUrl, browser=browser) - - def onBrowserLoadStarted(self): - browser = self.sender() - lastBrowserState = browser.userData() - tabWidget = self.controlById(self.IdTabBrowsers) - - lastBrowserState.statusMessage = self.trUtf8('Loading') - tabWidget.setTabText(tabWidget.indexOf(browser), self._adjustTabText(self.trUtf8('Loading'))) - - def onBrowserReloadTriggered(self, action): - browser = self.currentBrowser() - if browser is not None: - if browser.url().toString().isEmpty(): - url = browser.userData().url - self.load(url, browser=browser) - - - def onBrowserStatusBarMessage(self, qString): - browser = self.sender() - qString = QtCore.QString(qString) # copy it - qt nukes it on return - - lastBrowserState = browser.userData() - if not qString.isEmpty(): - lastBrowserState.statusMessage = qString - - def onBrowserTitleChanged(self, qString): - browser = self.sender() - qString = QtCore.QString(qString) # copy it - qt nukes it on return - maxTabText = self.fcSettings.value('MaxTabText') - tabWidget = self.controlById(self.IdTabBrowsers) - lastBrowserState = browser.userData() - if not qString.isEmpty(): - lastBrowserState.title = qString - tabWidget.setTabText(tabWidget.indexOf(browser), self._adjustTabText( lastBrowserState.title)) - - def onBrowserUrlChanged(self, qUrl): - browser = self.sender() - qUrl = QtCore.QUrl(qUrl) # copy it - qt nukes it on return - - lastBrowserState = browser.userData() - if qUrl.isValid(): - lastBrowserState.url = qUrl - addressbar = self.controlById(self.IdEdAddressBar) - addressbar.setText(lastBrowserState.url.toString()) - - def onCloseAllTabs(self, action): - # have to do it by hand to reset [BackIsClose] - tabWidget = self.controlById(self.IdTabBrowsers) - tabWidget.clear() - self._adjustCurrentBrowserDependendStuff() - - def onCloseCurrentTab(self, action): - tabWidget = self.controlById(self.IdTabBrowsers) - i = tabWidget.currentIndex() - if i > -1: - tabWidget.removeTab(i) - self._adjustCurrentBrowserDependendStuff() - - def onCloseCurrentSideBar(self, action): - tabWidget = self.controlById(self.IdTabSideBar) - sideBar = tabWidget.currentWidget() - sideBar.setCurrent(self, False) - tabWidget.setVisible(False) - checkedAction = self.fcActions['GroupSideBars'].checkedAction() - if checkedAction is not None: - checkedAction.setChecked(False) - self.fcSettings.setValues(LastSideBarAction=QtCore.QString('')) - - def onDuplicateTab(self, action): - tabWidget = self.controlById(self.IdTabBrowsers) - browser = self.currentBrowser() - print browser - lastBrowserState = browser.userData() - self.fcActions['ActionCreateNewTab'].trigger() - browser = tabWidget.widget(tabWidget.count() -1) - self.load(lastBrowserState.url, browser=browser) - - def onEdFindTextChanged(self, text): - self.fcActions['ActionFindNext'].setEnabled(bool(text)) - self.fcActions['ActionFindPrevious'].setEnabled(bool(text)) - - def onFind(self, action): - frameFind = self.controlById(self.IdFrameFind) - ed = self.controlById(self.IdEdFind) - #ed.setText('fooBar') - - frameFind.setVisible(not frameFind.isVisible()) - #self.fcActions['ActionFindNext'].setEnabled() - #self.fcActions['ActionFindPrevious'].setEnabled() - if frameFind.isVisible(): - ed.setFocus(QtCore.Qt.OtherFocusReason) - ed.selectAll() - - #TODO: give feedback when no matching text was found - def onFindNext(self): - browser = self.currentBrowser() - if browser is not None: - page = browser.page() - ed = self.controlById(self.IdEdFind) - ck = self.controlById(self.IdCkFindCaseSensitive) - flags = page.FindWrapsAroundDocument - if ck.checkState() == QtCore.Qt.Checked: - flags |= page.FindCaseSensitively - if not browser.findText(ed.text(), flags): - pass - - def onFindPrevious(self): - browser = self.currentBrowser() - if browser is not None: - page = browser.page() - ed = self.controlById(self.IdEdFind) - ck = self.controlById(self.IdCkFindCaseSensitive) - flags = page.FindWrapsAroundDocument | page.FindBackward - if ck.checkState() == QtCore.Qt.Checked: - flags |= page.FindCaseSensitively - browser.findText(ed.text(), flags) - - #TODO: open in new tab option? - def onGoToFProxy(self, action): - url = QtCore.QUrl() - self.load(url, force=True) - - #TODO: open in new tab option? - def onGoToHomePage(self, action): - home = self.fcSettings.value('HomePage') - qUrl = QtCore.QUrl(home) - self.load(qUrl, force=True) - - def onNavBarReturnPressed(self): - text = self.controlById(self.IdEdAddressBar).text() - if text.isEmpty(): - return - qUrl = QtCore.QUrl(text) - browser = self.currentBrowser() - if browser is None or self.fcSettings.value('OpenAddressBarInNewTab'): - browser = self.newBrowser(title=self.trUtf8('Loading')) - self.load(qUrl, browser=browser) - - #TODO: we get no load progress feedback here? - #TODO: more choices for page to load - #TODO: we load fproxy in new page. this is because we enforce fproxy host/port on urls - # ...no way to distinguish in onDuplicateTab() between an empty page and fproxy page - # ...cos it relies on lastBrowserState.url - def onCreateNewTab(self, action): - browser = self.newBrowser(title=self.trUtf8('Empty')) - if self.fcSettings.value('OpenHomePageOnNewTabCreated'): - homePage = self.fcSettings.value('HomePage') - self.load(QtCore.QUrl(homePage), browser=browser) - else: - self.load(QtCore.QUrl(), browser=browser) - - def onPageLinkHovered(self, link, title, textContent): - self.fcGlobalFeedback.setFeedback(QtCore.QString(link)) - - def onPageActionBackChanged(self): - act = self.sender() - browser = self.currentBrowser() - if browser is not None and act is browser.pageAction(browser.page().Back): - self._adjustBackIsClose() - - def onSavePage(self, action): - # we have to cheat a bit here and reload the page to make shure the page has - # all QNetWorkReplies present - browser = self.currentBrowser() - - def onShowSidebar(self, action): - tabWidget = self.controlById(self.IdTabSideBar) - if action == self.fcActions['ActionShowSideBarLoadDetails']: - index = tabWidget.indexOf(self.sideBarLoadDetails) - self.sideBarLoadDetails.setCurrent(self, True) - else: - raise ValueError('No such sideBar') - self.fcSettings.setValues(LastSideBarAction=action.objectName()) - tabWidget.setCurrentIndex(index) - tabWidget.setVisible(True) - - def onSplitterMoved(self, pos, index): - splitter = self.controlById(self.IdSplitter) - self.fcSettings.setValues(SplitterPos=splitter.saveState()) - - def onTabContextMenuEvent(self, pt): - menu = QtGui.QMenu() - browser = self.currentBrowser() - tabWidget = self.controlById(self.IdTabBrowsers) - pt = tabWidget.mapToGlobal(pt) - pt2 = tabWidget.tabBar().mapFromGlobal(pt) - index = tabWidget.tabBar().tabAt(pt2) - - # setup actions - self.fcActions['ActionCloseBrowserUnderMouse'].setEnabled(index >-1) - self.fcActions['ActionDuplicateTab'].setEnabled(index >-1) - - # setup menu - menu.addAction(self.fcActions['ActionCloseBrowserUnderMouse']) - menu.addAction(self.fcActions['ActionCreateNewTab']) - menu.addAction(self.fcActions['ActionDuplicateTab']) - menu.addAction(self.fcActions['ActionCloseAllTabs']) - act = menu.exec_(pt) - if act == self.fcActions['ActionCloseBrowserUnderMouse']: - tabWidget.removeTab(i) - self._adjustCurrentBrowserDependendStuff() - - def onTabCurrentChanged(self, i): - tabWidget = self.controlById(self.IdTabBrowsers) - browser = tabWidget.widget(i) - self._adjustCurrentBrowserDependendStuff() - if browser is not None: - lastBrowserState = browser.userData() - addressBar = self.controlById(self.IdEdAddressBar) - - # update status info - addressBar.setText(lastBrowserState.url.toString()) - - #TODO: enable/disable, but no view gives non feedback on max/min zoom - def onZoomIn(self, action): - browser = self.currentBrowser() - if browser is not None: - oldMultiplier = browser.textSizeMultiplier() - browser.setTextSizeMultiplier(browser.textSizeMultiplier() + 0.2) - if browser.textSizeMultiplier() <= oldMultiplier: - menu.addAction(self.fcActions['ActionZoomIn']).setEnabled(False) - - def onZoomOut(self, action): - browser = self.currentBrowser() - if browser is not None: - oldMultiplier = browser.textSizeMultiplier() - browser.setTextSizeMultiplier(browser.textSizeMultiplier() - 0.2) - if browser.textSizeMultiplier() >= oldMultiplier: - menu.addAction(self.fcActions['ActionZoomOut']).setEnabled(False) - -#********************************************************************************** -# -#********************************************************************************** -if __name__ == '__main__': - import sys - from .ViewLogger import ViewLoggerWidget - from .MainWindow import MainWindow - from .View import ViewWidget - from .ViewConnection import ViewConnectionWidget - from .ViewDownloads import ViewDownloadsWidget - - app = QtGui.QApplication(sys.argv) - - mainWindow = MainWindow() - viewWidget = ViewWidget(mainWindow) - mainWindow.setCentralWidget(viewWidget) - - browserWidget = ViewBrowserWidget(mainWindow) - viewWidget.addTopViews( - ViewConnectionWidget(mainWindow), - browserWidget, - ViewDownloadsWidget(mainWindow), - ) - viewWidget.addBottomViews( - ViewLoggerWidget(mainWindow), - ) - - mainWindow.show() - res = app.exec_() - sys.exit(res) - This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jU...@us...> - 2008-08-16 08:00:03
|
Revision: 913 http://fclient.svn.sourceforge.net/fclient/?rev=913&view=rev Author: jUrner Date: 2008-08-16 08:00:12 +0000 (Sat, 16 Aug 2008) Log Message: ----------- no longer needed Removed Paths: ------------- trunk/fclient/fclient/impl/SideBarLoadDetails.py Deleted: trunk/fclient/fclient/impl/SideBarLoadDetails.py =================================================================== --- trunk/fclient/fclient/impl/SideBarLoadDetails.py 2008-08-16 07:59:09 UTC (rev 912) +++ trunk/fclient/fclient/impl/SideBarLoadDetails.py 2008-08-16 08:00:12 UTC (rev 913) @@ -1,270 +0,0 @@ -"""sideBar for the browser to show detailed information on page load""" -#******************************************************************************** -#TODO: -# -# x. how to adjust item colors via stylesheet? -# x. limit number of requests we keep track off (performance)? -# x. context menu actions for items like ...load in browser ..download key (...) -# x. save column widths -# -#******************************************************************************** -from __future__ import absolute_import -if __name__ == '__main__': # see --> http://bugs.python.org/issue1510172 . works only current dir and below - import os; __path__ = [os.path.dirname(__file__)] - -import posixpath -from PyQt4 import QtCore, QtGui - -from . import config -from .tpls.Ui_SideBarLoadDetailsTpl import Ui_SideBarLoadDetails -#********************************************************************************** -# -#********************************************************************************** -class SideBarLoadDetailsSettings(config.SettingsBase): - _key_ = config.IdSideBarLoadDetails - _settings_ = ( - ('ColorFgItem', 'QColor', QtGui.QColor('black')), - ('ColorBgItem', 'QColor', QtGui.QColor('white')), - ('ColorFgItemError', 'QColor', QtGui.QColor('red')), - ('ColorBgItemError', 'QColor', QtGui.QColor('white')), - ('ColorFgItemComplete', 'QColor', QtGui.QColor('green')), - ('ColorBgItemComplete', 'QColor', QtGui.QColor('white')), - ) - - -class TreeItem(QtGui.QTreeWidgetItem): - - StatusNone = 0 - StatusLoading = 1 - StatusComplete = 2 - StatusError = 3 - def __init__(self, *args): - QtGui.QTreeWidgetItem.__init__(self, *args) - self.status = self.StatusNone - self.url = None - - - -class SideBarLoadDetails(QtGui.QWidget, Ui_SideBarLoadDetails): - - IdTree = 'tree' - IdBtClose = 'btClose' - - IndexProgress = 0 - IndexStatus = 1 - IndexName = 2 - - - def __init__(self, parent=None, closeAction=None): - QtGui.QWidget.__init__(self, parent) - self.statusNames = {} # TreeItem.Status* --> displayName - - self.setupUi(self) - - config.ObjectRegistry.register(self) - self.fcSettings = SideBarLoadDetailsSettings(self).restore() - self.baseKey = None # base key of the page - - # setup tree - tree = self.controlById(self.IdTree) - tree.setUniformRowHeights(True) - tree.setRootIsDecorated(False) - - # setup close button - if closeAction is not None: - bt = self.controlById(self.IdBtClose) - bt.setDefaultAction(closeAction) - - ############################## - ## private methods - ############################## - def _splitBaseKey(self, url): - baseKey = '' - fileName = tmp_fileName = unicode(url.path()) - if tmp_fileName: - tmp_fileName = tmp_fileName.lstrip('/') - if tmp_fileName: - # prep fileName to extract freenetKey - T = tmp_fileName.split('/', 1) - if len(T) == 2: - tmp_baseKey, tmp_fileName = T - else: - tmp_baseKey, tmp_fileName = T[0], '' - # check if baseKey is a freenet key - if config.qStringToFcpKey(tmp_baseKey) is not None: - baseKey = tmp_baseKey - fileName = tmp_fileName - else: - fileName = fileName.lstrip('/') - return baseKey, fileName - - ############################## - ## methods - ############################## - def addNetworkReply(self, indexReply, networkReplyData): - #TODO: better extraction of filename part - tree = self.controlById(self.IdTree) - n = tree.topLevelItemCount() - if indexReply < n: - return - - if indexReply == 0: - self.baseKey, fileName = self._splitBaseKey(networkReplyData.url) - else: - #problem: index page may point somewhere deep into a container - # ..so we can not assume all following requests of are lokated deeper - # ..in the age hirarchy. anyways. links to external resources are - # ..always displayed as absolute urls - baseKey, fileName = self._splitBaseKey(networkReplyData.url) - if baseKey != self.baseKey: - fileName = unicode(networkReplyData.url.toString()) - if not fileName: - fileName = '/' - - item = TreeItem(tree) - item.url = networkReplyData.url - # set progress - if networkReplyData.bytesTotal < 1: - progress = '0%' - else: - progress = str(int((float(networkReplyData.bytesReceived) / networkReplyData.bytesTotal * 100))) + '%' - item.setData( - self.IndexProgress, - QtCore.Qt.DisplayRole, - QtCore.QVariant(progress), - ) - # set status - if networkReplyData.bytesReceived: - item.status = TreeItem.StatusLoading - if networkReplyData.errorCode is not None: - item.status = TreeItem.StatusError - if networkReplyData.finished: - item.status = TreeItem.StatusComplete - item.setData( - self.IndexStatus, - QtCore.Qt.DisplayRole, - QtCore.QVariant(self.statusNames[item.status]), - ) - # set fileName - item.setData( - self.IndexName, - QtCore.Qt.DisplayRole, - QtCore.QVariant(fileName), - ) - # set vcolors - item.setForeground(self.IndexStatus, self.fcSettings.value('ColorFgItem')) - item.setBackground(self.IndexStatus, self.fcSettings.value('ColorBgItem')) - - - def controlById(self, idControl): - return getattr(self, idControl) - - def setCurrent(self, browserWidget, flag): - if flag: - self.setBrowser(browserWidget.currentBrowser()) - else: - tree = self.controlById(self.IdTree) - tree.clear() - self.baseUrl = None - - def setBrowser(self, browser): - tree = self.controlById(self.IdTree) - tree.clear() - self.baseUrl = None - # setup browser - if browser is not None: - self.connect(browser, QtCore.SIGNAL('networkGetRequestCreated(int, QObject*)'), self.addNetworkReply) - self.connect(browser, QtCore.SIGNAL('networkReplyProgress(int, QObject*)'), self.onBrowserNetworkReplyProgress) - self.connect(browser, QtCore.SIGNAL('networkReplyError(int, QObject*)'), self.onBrowserNetworkReplyError) - self.connect(browser, QtCore.SIGNAL('networkReplyFinished(int, QObject*)'), self.onBrowserNetworkReplyFinished) - self.connect(browser, QtCore.SIGNAL('loadStarted()'), self.onBrowserLoadStarted) - for indexReply, networkReplyData in enumerate(browser.networkGetReplies()): - self.addNetworkReply(indexReply, networkReplyData) - - ########################### - ## overwritten methods - ########################### - def retranslateUi(self, this): - Ui_SideBarLoadDetails.retranslateUi(self, this) - tree = self.controlById(self.IdTree) - headerLabels = [ - (self.IndexProgress, self.trUtf8('Progress')), - (self.IndexStatus, self.trUtf8('Status')), - (self.IndexName, self.trUtf8('Name')), - ] - headerLabels.sort() - tree.setHeaderLabels([i[1] for i in headerLabels]) - self.statusNames = { - TreeItem.StatusNone: self.trUtf8('waiting'), - TreeItem.StatusLoading: self.trUtf8('loading'), - TreeItem.StatusComplete: self.trUtf8('complete'), - TreeItem.StatusError: self.trUtf8('error'), - } - root = tree.invisibleRootItem() - for i in xrange(root.childCount()): - item = root.child(i) - item.setData( - self.IndexStatus, - QtCore.Qt.DisplayRole, - QtCore.QVariant(self.statusNames[item.status]), - ) - ############################## - ## event handlers - ############################## - def onBrowserLoadStarted(self): - tree = self.controlById(self.IdTree) - tree.clear() - - def onBrowserNetworkReplyProgress(self, indexReply, networkReplyData): - tree = self.controlById(self.IdTree) - item = tree.invisibleRootItem().child(indexReply) - if item is None: - return - if item.status != TreeItem.StatusError: - item.status = item.StatusLoading - if networkReplyData.bytesTotal < 1: - progress = '0%' - else: - progress = str(int((float(networkReplyData.bytesReceived) / networkReplyData.bytesTotal * 100))) + '%' - - item.setData( - self.IndexProgress, - QtCore.Qt.DisplayRole, - QtCore.QVariant(progress), - ) - item.setData( - self.IndexStatus, - QtCore.Qt.DisplayRole, - QtCore.QVariant(self.statusNames[item.status]), - ) - - def onBrowserNetworkReplyError(self, indexReply, networkReplyData): - tree = self.controlById(self.IdTree) - item = tree.invisibleRootItem().child(indexReply) - if item is None: - return - item.setForeground(self.IndexStatus, self.fcSettings.value('ColorFgItemError')) - item.setBackground(self.IndexStatus, self.fcSettings.value('ColorBgItemError')) - item.status = item.StatusError - item.setData( - self.IndexStatus, - QtCore.Qt.DisplayRole, - QtCore.QVariant(self.statusNames[item.status]), - ) - - def onBrowserNetworkReplyFinished(self, indexReply, networkReplyData): - tree = self.controlById(self.IdTree) - item = tree.invisibleRootItem().child(indexReply) - if item is None: - return - if item.status != TreeItem.StatusError: - item.status = item.StatusComplete - item.setData( - self.IndexStatus, - QtCore.Qt.DisplayRole, - QtCore.QVariant(self.statusNames[item.status]), - ) - item.setForeground(self.IndexStatus, self.fcSettings.value('ColorFgItemComplete')) - item.setBackground(self.IndexStatus, self.fcSettings.value('ColorBgItemComplete')) - - This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jU...@us...> - 2008-08-16 07:59:01
|
Revision: 912 http://fclient.svn.sourceforge.net/fclient/?rev=912&view=rev Author: jUrner Date: 2008-08-16 07:59:09 +0000 (Sat, 16 Aug 2008) Log Message: ----------- isolated logger view Modified Paths: -------------- trunk/fclient/fclient/fclient.py Added Paths: ----------- trunk/fclient/fclient/impl/ViewLogger/ trunk/fclient/fclient/impl/ViewLogger/LoggerWidget.ui trunk/fclient/fclient/impl/ViewLogger/Ui_LoggerWidget.py trunk/fclient/fclient/impl/ViewLogger/ViewLogger.py trunk/fclient/fclient/impl/ViewLogger/__init__.py trunk/fclient/fclient/impl/ViewLogger/_fix_mexec.py Removed Paths: ------------- trunk/fclient/fclient/impl/ViewLogger.py trunk/fclient/fclient/impl/tpls/SideBarLoadDetailsTpl.ui trunk/fclient/fclient/impl/tpls/Ui_ViewLoggerWidgetTpl.py trunk/fclient/fclient/impl/tpls/ViewLoggerWidgetTpl.ui Modified: trunk/fclient/fclient/fclient.py =================================================================== --- trunk/fclient/fclient/fclient.py 2008-08-16 07:54:39 UTC (rev 911) +++ trunk/fclient/fclient/fclient.py 2008-08-16 07:59:09 UTC (rev 912) @@ -17,7 +17,7 @@ from .impl.ViewBrowser import ViewBrowser from .impl.ViewConnection import ViewConnection from .impl.ViewDownloads import ViewDownloadsWidget -from .impl.ViewLogger import ViewLoggerWidget +from .impl.ViewLogger import ViewLogger from .impl.ViewUploads import ViewUploadsWidget from .impl.DlgSingleAppError import DlgSingleAppError @@ -81,7 +81,7 @@ ViewDownloadsWidget(mainWindow), ViewUploadsWidget(mainWindow), ) - viewWidget.addBottomViews(ViewLoggerWidget(mainWindow)) + viewWidget.addBottomViews(ViewLogger.ViewLoggerWidget(mainWindow)) mainWindow.show() res = app.exec_() Added: trunk/fclient/fclient/impl/ViewLogger/LoggerWidget.ui =================================================================== --- trunk/fclient/fclient/impl/ViewLogger/LoggerWidget.ui (rev 0) +++ trunk/fclient/fclient/impl/ViewLogger/LoggerWidget.ui 2008-08-16 07:59:09 UTC (rev 912) @@ -0,0 +1,30 @@ +<ui version="4.0" > + <class>ViewLoggerWidget</class> + <widget class="QWidget" name="ViewLoggerWidget" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>550</width> + <height>471</height> + </rect> + </property> + <property name="windowTitle" > + <string>Form</string> + </property> + <layout class="QGridLayout" name="gridLayout" > + <item row="0" column="0" > + <widget class="QPlainTextEdit" name="edLogger" > + <property name="lineWrapMode" > + <enum>QPlainTextEdit::NoWrap</enum> + </property> + <property name="readOnly" > + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> Added: trunk/fclient/fclient/impl/ViewLogger/Ui_LoggerWidget.py =================================================================== --- trunk/fclient/fclient/impl/ViewLogger/Ui_LoggerWidget.py (rev 0) +++ trunk/fclient/fclient/impl/ViewLogger/Ui_LoggerWidget.py 2008-08-16 07:59:09 UTC (rev 912) @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file '/home/me/src/fclient/trunk/fclient/fclient/impl/ViewLogger/LoggerWidget.ui' +# +# Created: Sat Aug 16 09:56:26 2008 +# by: PyQt4 UI code generator 4.4.3-snapshot-20080705 +# +# WARNING! All changes made in this file will be lost! + +from PyQt4 import QtCore, QtGui + +class Ui_ViewLoggerWidget(object): + def setupUi(self, ViewLoggerWidget): + ViewLoggerWidget.setObjectName("ViewLoggerWidget") + ViewLoggerWidget.resize(550, 471) + self.gridLayout = QtGui.QGridLayout(ViewLoggerWidget) + self.gridLayout.setObjectName("gridLayout") + self.edLogger = QtGui.QPlainTextEdit(ViewLoggerWidget) + self.edLogger.setLineWrapMode(QtGui.QPlainTextEdit.NoWrap) + self.edLogger.setReadOnly(True) + self.edLogger.setObjectName("edLogger") + self.gridLayout.addWidget(self.edLogger, 0, 0, 1, 1) + + self.retranslateUi(ViewLoggerWidget) + QtCore.QMetaObject.connectSlotsByName(ViewLoggerWidget) + + def retranslateUi(self, ViewLoggerWidget): + ViewLoggerWidget.setWindowTitle(QtGui.QApplication.translate("ViewLoggerWidget", "Form", None, QtGui.QApplication.UnicodeUTF8)) + + +if __name__ == "__main__": + import sys + app = QtGui.QApplication(sys.argv) + ViewLoggerWidget = QtGui.QWidget() + ui = Ui_ViewLoggerWidget() + ui.setupUi(ViewLoggerWidget) + ViewLoggerWidget.show() + sys.exit(app.exec_()) + Added: trunk/fclient/fclient/impl/ViewLogger/ViewLogger.py =================================================================== --- trunk/fclient/fclient/impl/ViewLogger/ViewLogger.py (rev 0) +++ trunk/fclient/fclient/impl/ViewLogger/ViewLogger.py 2008-08-16 07:59:09 UTC (rev 912) @@ -0,0 +1,276 @@ + +# some fixes for relative imports +# see --> [http://bugs.python.org/issue1510172] absolute/rellative import not working (works only current dir and below) +# see --> [http://mail.python.org/pipermail/python-ideas/2007-February/000232.html] PEP for executing a module in a +# ...package containing relative imports +from __future__ import absolute_import +if __name__ == '__main__': + import os + __path__ = [os.path.dirname(__file__)] + from ._fix_mexec import fix_mexec + fix_mexec(__name__, __file__) + del fix_mexec + +import sys +import logging + +from PyQt4 import QtCore, QtGui + +from .. import config +from ..lib import fcp2 + +from .Ui_LoggerWidget import Ui_ViewLoggerWidget +#********************************************************************************** +# +#********************************************************************************** +class Actions(config.ActionsBase): + + PrefixVerbosity = 'ActionVerbosity' + + def __init__(self, parent): + config.ActionsBase.__init__(self, parent) + + # for ease of use verbosities are mapped to verbosity actions like this: PrefixVerbosity + Verbosity + self.action( + name='ActionLoggerClear', + text=self.trUtf8('C&lear'), + trigger=parent.onActionLoggerClear, + ) + + groupVerbosity = self.group( + name='GroupVerbosity', + trigger=parent.onGroupVerbosityTriggered, + isExclusive=True, + ) + self.action( + name='ActionVerbosityInfo', + text=self.trUtf8('Info'), + group=groupVerbosity, + trigger=None, + isCheckable=True, + userData=fcp2.ConstDebugVerbosity.Info, + ) + self.action( + name='ActionVerbosityMessage', + text=self.trUtf8('Message'), + group=groupVerbosity, + trigger=None, + isCheckable=True, + userData=fcp2.ConstDebugVerbosity.Message, + ) + self.action( + name='ActionVerbosityDebug', + text=self.trUtf8('Debug'), + group=groupVerbosity, + trigger=None, + isCheckable=True, + userData=fcp2.ConstDebugVerbosity.Debug, + ) + self.action( + name='ActionVerbosityChatty', + text=self.trUtf8('Chatty'), + group=groupVerbosity, + trigger=None, + isCheckable=True, + userData=fcp2.ConstDebugVerbosity.Chatty, + ) + + +class GlobalFeedback(config.GlobalFeedbackBase): + """wrapper for global statusbar widgets, menus""" + + def __init__(self, parent, idGlobalFeedback): + config.GlobalFeedbackBase.__init__(self, parent, idGlobalFeedback) + + # menus + self.menus = [] + if self.menuBar is not None and hasattr(parent, 'fcViewObject'): + menu = QtGui.QMenu(parent.fcViewObject.displayName, self.menuBar) + parent.populateMenu(menu) + self.menus.append(menu) + self.menuBar.addViewMenu(menu) + + # status bar widgets + self.label1 = None + #if self.statusBar is not None: + # self.label1 = QtGui.QLabel('foo here', self.statusBar) + + def setVisible(self, flag): + for menu in self.menus: + menu.children()[0].setVisible(flag) + if self.label1 is not None: + self.label1.setVisible(flag) + + +class Settings(config.SettingsBase): + + PrefixVerbosityColorFg = 'ColorFgVerbosity' + + _key_ = config.IdViewLoggerWidget + _settings_ = ( + ('MaxLines', 'UInt', 1000), + ('Verbosity', 'PyString', 'Info'), + + #TODO: Chatty does not seem to work. check in fcp2.client + ('ColorFgVerbosityCRITICAL', 'QColor', QtGui.QColor('red')), + ('ColorFgVerbosityERROR', 'QColor', QtGui.QColor('red')), + ('ColorFgVerbosityWARNING', 'QColor', QtGui.QColor('red')), + ('ColorFgVerbosityINFO', 'QColor', QtGui.QColor('black')), + ('ColorFgVerbosityMESSAGE', 'QColor', QtGui.QColor('blue')), + ('ColorFgVerbosityDEBUG', 'QColor', QtGui.QColor('slategray')), + ('ColorFgVerbosityCHATTY', 'QColor', QtGui.QColor('lightslategray')), + ) + + +class LoggerViewObject(config.ViewObject): + + def __init__(self, parent): + config.ViewObject. __init__(self, parent) + + self.name=parent.objectName() + self.displayName=self.trUtf8('Logger') + self.icon=QtGui.QIcon() + + +#*********************************************************************** +# +#*********************************************************************** +class MyLoggingHandler(logging.Handler): + + def __init__(self, cb, *args, **kwargs): + logging.Handler.__init__(self, *args, **kwargs) + self.cb = cb + + def emit(self, record): + self.cb(record) + +#*********************************************************************** +# +#*********************************************************************** +class ViewLoggerWidget(QtGui.QWidget, Ui_ViewLoggerWidget): + + IdEdLogger = 'edLogger' + + + def __init__(self, parent, idGlobalFeedback=config.IdMainWindow): + QtGui.QWidget.__init__(self, parent) + self._isCreated = False + self._mainWindowMenus = {} #TODO: wrap along with toolbars to a handy class MainWindowStuff + + self.setupUi(self) + config.ObjectRegistry.register(self) + + self.fcActions = Actions(self) + self.fcSettings = Settings(self).restore() + self.fcViewObject = LoggerViewObject(self) + self.fcGlobalFeedback = GlobalFeedback(self, idGlobalFeedback) + + + # setup editbox + #NOTE: do not move to showEvent(). we want to be up and alive as soon as possible to catch logs + ed = self.controlById(self.IdEdLogger) + ed.document().setMaximumBlockCount(self.fcSettings.value('MaxLines')) + ed.contextMenuEvent = self.loggerContextMenuEvent + self.connect(ed, QtCore.SIGNAL('textChanged()'), self.onLoggerTextChanged) + + # setup logger + self.loggingHandler = MyLoggingHandler(self.addRecord) + logging.getLogger('').addHandler(self.loggingHandler) + + # setup actions + verbosity = self.fcSettings.value('Verbosity').title() + action = self.fcActions.get(self.fcActions.PrefixVerbosity + verbosity, None) + if action is None: + verbosity = self.fcSettings.restoreDefaults('Verbosity')['Verbosity'] + action = self.fcActions.get(self.fcActions.PrefixVerbosity + verbosity, None) + if action is None: + raise ValueError('default verbosity action "%s" not found. WTF?' % self.actions.PrefixVerbosity + verbosity) + action.trigger() + + ######################################### + ## methods + ######################################### + def addRecord(self, record): + """adds a logging record""" + ed = self.controlById(self.IdEdLogger) + fmt = ed.currentCharFormat() + colorFg = self.fcSettings.value(self.fcSettings.PrefixVerbosityColorFg + record.levelname) + fmt.setForeground(QtGui.QBrush(colorFg)) + ed.setCurrentCharFormat(fmt) + + text = '%s:%s:%s' % (record.levelname, record.name, record.getMessage()) + ed.appendPlainText(text) + + def controlById(self, idControl): + return getattr(self, idControl) + + def populateMenu(self, menu): + menu.addAction(self.fcActions['ActionLoggerClear']) + subMenu = menu.addMenu(self.trUtf8('Verbosity')) + subMenu.addActions(self.fcActions['GroupVerbosity'].actions()) + return menu + + ######################################### + ##view methods + ######################################### + def viewClose(self): + pass + + def viewDisplayName(self): + return self.trUtf8('Logger') + + def viewIcon(self): + return QtGui.QIcon() + + def viewName(self): + return self.objectName() + + ######################################### + ## overwritten events + ######################################### + def loggerContextMenuEvent(self, event): + """customize context menu of the logger QTextEdit""" + ed = self.controlById(self.IdEdLogger) + menu = ed.createStandardContextMenu() + self.populateMenu(menu) + menu.exec_(event.globalPos()) + + def hideEvent(self, event): + self.fcGlobalFeedback.setVisible(False) + + def showEvent(self, event): + self.fcGlobalFeedback.setVisible(True) + if self._isCreated: + return + self._isCreated = True + + ######################################### + ## event onrs + ######################################### + def onActionLoggerClear(self, action): + self.controlById(self.IdEdLogger).clear() + + def onGroupVerbosityTriggered(self, action): + nameVerbosity = action.objectName()[len(self.fcActions.PrefixVerbosity):] + self.fcSettings.setValues(Verbosity=nameVerbosity) + logging.getLogger().setLevel(action.userData()) + + def onLoggerTextChanged(self): + ed = self.controlById(self.IdEdLogger) + self.fcActions['ActionLoggerClear'].setEnabled(not ed.document().isEmpty()) + +#********************************************************************************** +# +#********************************************************************************** +if __name__ == '__main__': + import sys + + app = QtGui.QApplication(sys.argv) + w = ViewLoggerWidget(None) + + w.show() + res = app.exec_() + sys.exit(res) + + + Added: trunk/fclient/fclient/impl/ViewLogger/__init__.py =================================================================== --- trunk/fclient/fclient/impl/ViewLogger/__init__.py (rev 0) +++ trunk/fclient/fclient/impl/ViewLogger/__init__.py 2008-08-16 07:59:09 UTC (rev 912) @@ -0,0 +1 @@ + Added: trunk/fclient/fclient/impl/ViewLogger/_fix_mexec.py =================================================================== --- trunk/fclient/fclient/impl/ViewLogger/_fix_mexec.py (rev 0) +++ trunk/fclient/fclient/impl/ViewLogger/_fix_mexec.py 2008-08-16 07:59:09 UTC (rev 912) @@ -0,0 +1,99 @@ +'''in python 2.5 relative impports are srsly broken ..fix this to make relative imports work +when executing a module as main (-m), including relative imports up to the root package + +see: [http://mail.python.org/pipermail/python-ideas/2007-February/000232.html] + +@note: root package is the highest available package in the package hirarchy. +don't look at __name__ too closely. it gets adjusted for a module to just "do the right +thing" in __name__ == '__main__' comparisons +@note: this patch does not work if relative imports are done in __init__.py. no idea why +and to be honest, I don't wanna* know.. +@note: this is more or less a hack. so it may have unwanted side effects for example +when importing parent packages. use at your own risk. could improve this module +by adding a __main__.py to stop at this level or by fixing the __init__.py bug, but +I don't think its worth it. see what python2.6 or 3k brings.. + +usage:: + + # place this at the top a module, before doing any relative imports + from fix_mexec import fix_mexec + fix_mexec(__name__, __file__) + del fix_mexec + + from ...foo import bar + + + +##<-- copy and paste code, assuming _fix_mexec resides in the current dir.. + +# some fixes for relative imports +# see --> [http://bugs.python.org/issue1510172] absolute/rellative import not working (works only current dir and below) +# see --> [http://mail.python.org/pipermail/python-ideas/2007-February/000232.html] PEP for executing a module in a +# ...package containing relative imports +from __future__ import absolute_import +if __name__ == '__main__': + import os + __path__ = [os.path.dirname(__file__)] + from ._fix_mexec import fix_mexec + fix_mexec(__name__, __file__) + del fix_mexec + + +##--> copy and paste code +''' + +import imp, os, sys +#******************************************************************************** +# +#******************************************************************************** +class MainName(str): + def __eq__(self, other): + if other == '__main__': return True + return str.__eq__(self, other) + def __ne__(self, other): + if other == '__main__': return False + return str.__ne__(self, other) + + +def fix_mexec(_name_, _file_): + """bugfix for relative imports not working + @param _name_: __name__ of the module + @param _file_: __file__ of the module + + @note: not complete: relies on __init__.py, .pyo (...) is ignored currently + """ + if _name_ == '__main__': + out = [] + # find allparent packages + p = os.path.dirname(os.path.abspath(_file_)) + prev = p + while True: + pkg = os.path.join(p, '__init__.py') + if os.path.isfile(pkg): + out.append([pkg, os.path.basename(p)]) + else: + break + prev = p + p = os.path.dirname(p) + if p == prev: + break + out.reverse() + + # adjust sub package names an import parent modules + name = None + for n, (fpath, name) in enumerate(out): + if n > 0: + name = out[n][1] = out[n -1][1] + '.' + out[n][1] + m = imp.load_source(name, fpath) + m.__path__ = [os.path.dirname(fpath)] + + # adjust name of the __main__ module + if name is not None: + m = sys.modules.pop('__main__') + # 'foo.bar..__main__' does not work for some reason. 'foo.bar' seems to work as expected + ##m.__name__ = _Name_(name + '.' + '__main__') + m.__name__ = MainName(name) + sys.modules[m.__name__] = m + + + Deleted: trunk/fclient/fclient/impl/ViewLogger.py =================================================================== --- trunk/fclient/fclient/impl/ViewLogger.py 2008-08-16 07:54:39 UTC (rev 911) +++ trunk/fclient/fclient/impl/ViewLogger.py 2008-08-16 07:59:09 UTC (rev 912) @@ -1,269 +0,0 @@ - -from __future__ import absolute_import -if __name__ == '__main__': # see --> http://bugs.python.org/issue1510172 . works only current dir and below - import os; __path__ = [os.path.dirname(__file__)] - -import sys -import logging - -from PyQt4 import QtCore, QtGui - -from . import config -from .lib import fcp2 - -from .tpls.Ui_ViewLoggerWidgetTpl import Ui_ViewLoggerWidget -#********************************************************************************** -# -#********************************************************************************** -class Actions(config.ActionsBase): - - PrefixVerbosity = 'ActionVerbosity' - - def __init__(self, parent): - config.ActionsBase.__init__(self, parent) - - # for ease of use verbosities are mapped to verbosity actions like this: PrefixVerbosity + Verbosity - self.action( - name='ActionLoggerClear', - text=self.trUtf8('C&lear'), - trigger=parent.onActionLoggerClear, - ) - - groupVerbosity = self.group( - name='GroupVerbosity', - trigger=parent.onGroupVerbosityTriggered, - isExclusive=True, - ) - self.action( - name='ActionVerbosityInfo', - text=self.trUtf8('Info'), - group=groupVerbosity, - trigger=None, - isCheckable=True, - userData=fcp2.ConstDebugVerbosity.Info, - ) - self.action( - name='ActionVerbosityMessage', - text=self.trUtf8('Message'), - group=groupVerbosity, - trigger=None, - isCheckable=True, - userData=fcp2.ConstDebugVerbosity.Message, - ) - self.action( - name='ActionVerbosityDebug', - text=self.trUtf8('Debug'), - group=groupVerbosity, - trigger=None, - isCheckable=True, - userData=fcp2.ConstDebugVerbosity.Debug, - ) - self.action( - name='ActionVerbosityChatty', - text=self.trUtf8('Chatty'), - group=groupVerbosity, - trigger=None, - isCheckable=True, - userData=fcp2.ConstDebugVerbosity.Chatty, - ) - - -class GlobalFeedback(config.GlobalFeedbackBase): - """wrapper for global statusbar widgets, menus""" - - def __init__(self, parent, idGlobalFeedback): - config.GlobalFeedbackBase.__init__(self, parent, idGlobalFeedback) - - # menus - self.menus = [] - if self.menuBar is not None and hasattr(parent, 'fcViewObject'): - menu = QtGui.QMenu(parent.fcViewObject.displayName, self.menuBar) - parent.populateMenu(menu) - self.menus.append(menu) - self.menuBar.addViewMenu(menu) - - # status bar widgets - self.label1 = None - #if self.statusBar is not None: - # self.label1 = QtGui.QLabel('foo here', self.statusBar) - - def setVisible(self, flag): - for menu in self.menus: - menu.children()[0].setVisible(flag) - if self.label1 is not None: - self.label1.setVisible(flag) - - -class Settings(config.SettingsBase): - - PrefixVerbosityColorFg = 'ColorFgVerbosity' - - _key_ = config.IdViewLoggerWidget - _settings_ = ( - ('MaxLines', 'UInt', 1000), - ('Verbosity', 'PyString', 'Info'), - - #TODO: Chatty does not seem to work. check in fcp2.client - ('ColorFgVerbosityCRITICAL', 'QColor', QtGui.QColor('red')), - ('ColorFgVerbosityERROR', 'QColor', QtGui.QColor('red')), - ('ColorFgVerbosityWARNING', 'QColor', QtGui.QColor('red')), - ('ColorFgVerbosityINFO', 'QColor', QtGui.QColor('black')), - ('ColorFgVerbosityMESSAGE', 'QColor', QtGui.QColor('blue')), - ('ColorFgVerbosityDEBUG', 'QColor', QtGui.QColor('slategray')), - ('ColorFgVerbosityCHATTY', 'QColor', QtGui.QColor('lightslategray')), - ) - - -class LoggerViewObject(config.ViewObject): - - def __init__(self, parent): - config.ViewObject. __init__(self, parent) - - self.name=parent.objectName() - self.displayName=self.trUtf8('Logger') - self.icon=QtGui.QIcon() - - -#*********************************************************************** -# -#*********************************************************************** -class MyLoggingHandler(logging.Handler): - - def __init__(self, cb, *args, **kwargs): - logging.Handler.__init__(self, *args, **kwargs) - self.cb = cb - - def emit(self, record): - self.cb(record) - -#*********************************************************************** -# -#*********************************************************************** -class ViewLoggerWidget(QtGui.QWidget, Ui_ViewLoggerWidget): - - IdEdLogger = 'edLogger' - - - def __init__(self, parent, idGlobalFeedback=config.IdMainWindow): - QtGui.QWidget.__init__(self, parent) - self._isCreated = False - self._mainWindowMenus = {} #TODO: wrap along with toolbars to a handy class MainWindowStuff - - self.setupUi(self) - config.ObjectRegistry.register(self) - - self.fcActions = Actions(self) - self.fcSettings = Settings(self).restore() - self.fcViewObject = LoggerViewObject(self) - self.fcGlobalFeedback = GlobalFeedback(self, idGlobalFeedback) - - - # setup editbox - #NOTE: do not move to showEvent(). we want to be up and alive as soon as possible to catch logs - ed = self.controlById(self.IdEdLogger) - ed.document().setMaximumBlockCount(self.fcSettings.value('MaxLines')) - ed.contextMenuEvent = self.loggerContextMenuEvent - self.connect(ed, QtCore.SIGNAL('textChanged()'), self.onLoggerTextChanged) - - # setup logger - self.loggingHandler = MyLoggingHandler(self.addRecord) - logging.getLogger('').addHandler(self.loggingHandler) - - # setup actions - verbosity = self.fcSettings.value('Verbosity').title() - action = self.fcActions.get(self.fcActions.PrefixVerbosity + verbosity, None) - if action is None: - verbosity = self.fcSettings.restoreDefaults('Verbosity')['Verbosity'] - action = self.fcActions.get(self.fcActions.PrefixVerbosity + verbosity, None) - if action is None: - raise ValueError('default verbosity action "%s" not found. WTF?' % self.actions.PrefixVerbosity + verbosity) - action.trigger() - - ######################################### - ## methods - ######################################### - def addRecord(self, record): - """adds a logging record""" - ed = self.controlById(self.IdEdLogger) - fmt = ed.currentCharFormat() - colorFg = self.fcSettings.value(self.fcSettings.PrefixVerbosityColorFg + record.levelname) - fmt.setForeground(QtGui.QBrush(colorFg)) - ed.setCurrentCharFormat(fmt) - - text = '%s:%s:%s' % (record.levelname, record.name, record.getMessage()) - ed.appendPlainText(text) - - def controlById(self, idControl): - return getattr(self, idControl) - - def populateMenu(self, menu): - menu.addAction(self.fcActions['ActionLoggerClear']) - subMenu = menu.addMenu(self.trUtf8('Verbosity')) - subMenu.addActions(self.fcActions['GroupVerbosity'].actions()) - return menu - - ######################################### - ##view methods - ######################################### - def viewClose(self): - pass - - def viewDisplayName(self): - return self.trUtf8('Logger') - - def viewIcon(self): - return QtGui.QIcon() - - def viewName(self): - return self.objectName() - - ######################################### - ## overwritten events - ######################################### - def loggerContextMenuEvent(self, event): - """customize context menu of the logger QTextEdit""" - ed = self.controlById(self.IdEdLogger) - menu = ed.createStandardContextMenu() - self.populateMenu(menu) - menu.exec_(event.globalPos()) - - def hideEvent(self, event): - self.fcGlobalFeedback.setVisible(False) - - def showEvent(self, event): - self.fcGlobalFeedback.setVisible(True) - if self._isCreated: - return - self._isCreated = True - - ######################################### - ## event onrs - ######################################### - def onActionLoggerClear(self, action): - self.controlById(self.IdEdLogger).clear() - - def onGroupVerbosityTriggered(self, action): - nameVerbosity = action.objectName()[len(self.fcActions.PrefixVerbosity):] - self.fcSettings.setValues(Verbosity=nameVerbosity) - logging.getLogger().setLevel(action.userData()) - - def onLoggerTextChanged(self): - ed = self.controlById(self.IdEdLogger) - self.fcActions['ActionLoggerClear'].setEnabled(not ed.document().isEmpty()) - -#********************************************************************************** -# -#********************************************************************************** -if __name__ == '__main__': - import sys - from . import Ui_ViewLogger - - app = QtGui.QApplication(sys.argv) - w = ViewLoggerWidget(None) - - w.show() - res = app.exec_() - sys.exit(res) - - - Deleted: trunk/fclient/fclient/impl/tpls/SideBarLoadDetailsTpl.ui =================================================================== --- trunk/fclient/fclient/impl/tpls/SideBarLoadDetailsTpl.ui 2008-08-16 07:54:39 UTC (rev 911) +++ trunk/fclient/fclient/impl/tpls/SideBarLoadDetailsTpl.ui 2008-08-16 07:59:09 UTC (rev 912) @@ -1,47 +0,0 @@ -<ui version="4.0" > - <class>SideBarLoadDetails</class> - <widget class="QWidget" name="SideBarLoadDetails" > - <property name="geometry" > - <rect> - <x>0</x> - <y>0</y> - <width>497</width> - <height>488</height> - </rect> - </property> - <property name="windowTitle" > - <string>Form</string> - </property> - <layout class="QGridLayout" name="gridLayout" > - <item row="0" column="0" > - <layout class="QHBoxLayout" name="horizontalLayout" > - <item> - <widget class="QLabel" name="header" > - <property name="text" > - <string>Load details</string> - </property> - </widget> - </item> - <item> - <widget class="QToolButton" name="btClose" > - <property name="text" > - <string>...</string> - </property> - </widget> - </item> - </layout> - </item> - <item row="1" column="0" > - <widget class="QTreeWidget" name="tree" > - <column> - <property name="text" > - <string>1</string> - </property> - </column> - </widget> - </item> - </layout> - </widget> - <resources/> - <connections/> -</ui> Deleted: trunk/fclient/fclient/impl/tpls/Ui_ViewLoggerWidgetTpl.py =================================================================== --- trunk/fclient/fclient/impl/tpls/Ui_ViewLoggerWidgetTpl.py 2008-08-16 07:54:39 UTC (rev 911) +++ trunk/fclient/fclient/impl/tpls/Ui_ViewLoggerWidgetTpl.py 2008-08-16 07:59:09 UTC (rev 912) @@ -1,39 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file '/home/me/src/proj/fclient/trunk/fclient/src/fclient/tpls/ViewLoggerWidgetTpl.ui' -# -# Created: Tue Jul 15 16:03:24 2008 -# by: PyQt4 UI code generator 4.4.3-snapshot-20080705 -# -# WARNING! All changes made in this file will be lost! - -from PyQt4 import QtCore, QtGui - -class Ui_ViewLoggerWidget(object): - def setupUi(self, ViewLoggerWidget): - ViewLoggerWidget.setObjectName("ViewLoggerWidget") - ViewLoggerWidget.resize(550, 471) - self.gridLayout = QtGui.QGridLayout(ViewLoggerWidget) - self.gridLayout.setObjectName("gridLayout") - self.edLogger = QtGui.QPlainTextEdit(ViewLoggerWidget) - self.edLogger.setLineWrapMode(QtGui.QPlainTextEdit.NoWrap) - self.edLogger.setReadOnly(True) - self.edLogger.setObjectName("edLogger") - self.gridLayout.addWidget(self.edLogger, 0, 0, 1, 1) - - self.retranslateUi(ViewLoggerWidget) - QtCore.QMetaObject.connectSlotsByName(ViewLoggerWidget) - - def retranslateUi(self, ViewLoggerWidget): - ViewLoggerWidget.setWindowTitle(QtGui.QApplication.translate("ViewLoggerWidget", "Form", None, QtGui.QApplication.UnicodeUTF8)) - - -if __name__ == "__main__": - import sys - app = QtGui.QApplication(sys.argv) - ViewLoggerWidget = QtGui.QWidget() - ui = Ui_ViewLoggerWidget() - ui.setupUi(ViewLoggerWidget) - ViewLoggerWidget.show() - sys.exit(app.exec_()) - Deleted: trunk/fclient/fclient/impl/tpls/ViewLoggerWidgetTpl.ui =================================================================== --- trunk/fclient/fclient/impl/tpls/ViewLoggerWidgetTpl.ui 2008-08-16 07:54:39 UTC (rev 911) +++ trunk/fclient/fclient/impl/tpls/ViewLoggerWidgetTpl.ui 2008-08-16 07:59:09 UTC (rev 912) @@ -1,30 +0,0 @@ -<ui version="4.0" > - <class>ViewLoggerWidget</class> - <widget class="QWidget" name="ViewLoggerWidget" > - <property name="geometry" > - <rect> - <x>0</x> - <y>0</y> - <width>550</width> - <height>471</height> - </rect> - </property> - <property name="windowTitle" > - <string>Form</string> - </property> - <layout class="QGridLayout" name="gridLayout" > - <item row="0" column="0" > - <widget class="QPlainTextEdit" name="edLogger" > - <property name="lineWrapMode" > - <enum>QPlainTextEdit::NoWrap</enum> - </property> - <property name="readOnly" > - <bool>true</bool> - </property> - </widget> - </item> - </layout> - </widget> - <resources/> - <connections/> -</ui> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jU...@us...> - 2008-08-16 07:54:30
|
Revision: 911 http://fclient.svn.sourceforge.net/fclient/?rev=911&view=rev Author: jUrner Date: 2008-08-16 07:54:39 +0000 (Sat, 16 Aug 2008) Log Message: ----------- isolated connection view Modified Paths: -------------- trunk/fclient/fclient/fclient.py trunk/fclient/fclient/impl/Prefs.py Added Paths: ----------- trunk/fclient/fclient/impl/ViewConnection/ trunk/fclient/fclient/impl/ViewConnection/ConnectionWidgetTpl.ui trunk/fclient/fclient/impl/ViewConnection/Ui_ConnectionWidgetTpl.py trunk/fclient/fclient/impl/ViewConnection/ViewConnection.py trunk/fclient/fclient/impl/ViewConnection/__init__.py trunk/fclient/fclient/impl/ViewConnection/_fix_mexec.py trunk/fclient/fclient/impl/ViewConnection/prefs/ trunk/fclient/fclient/impl/ViewConnection/prefs/PrefsConnectionExpertSettings.ui trunk/fclient/fclient/impl/ViewConnection/prefs/PrefsConnectionWidget.py trunk/fclient/fclient/impl/ViewConnection/prefs/Ui_PrefsConnectionExpertSettings.py trunk/fclient/fclient/impl/ViewConnection/prefs/__init__.py trunk/fclient/fclient/impl/ViewConnection/prefs/_fix_mexec.py Removed Paths: ------------- trunk/fclient/fclient/impl/PrefsConnectionWidget.py trunk/fclient/fclient/impl/ViewConnection.py trunk/fclient/fclient/impl/tpls/PrefsConnectionExpertSettingsTpl.ui trunk/fclient/fclient/impl/tpls/Ui_PrefsConnectionExpertSettingsTpl.py trunk/fclient/fclient/impl/tpls/Ui_ViewConnectionWidgetTpl.py trunk/fclient/fclient/impl/tpls/ViewConnectionWidgetTpl.ui Modified: trunk/fclient/fclient/fclient.py =================================================================== --- trunk/fclient/fclient/fclient.py 2008-08-16 07:43:18 UTC (rev 910) +++ trunk/fclient/fclient/fclient.py 2008-08-16 07:54:39 UTC (rev 911) @@ -15,7 +15,7 @@ from .impl.MainWindow import MainWindow from .impl.View import ViewWidget from .impl.ViewBrowser import ViewBrowser -from .impl.ViewConnection import ViewConnectionWidget +from .impl.ViewConnection import ViewConnection from .impl.ViewDownloads import ViewDownloadsWidget from .impl.ViewLogger import ViewLoggerWidget from .impl.ViewUploads import ViewUploadsWidget @@ -76,7 +76,7 @@ viewWidget = ViewWidget(mainWindow) mainWindow.setCentralWidget(viewWidget) viewWidget.addTopViews( - ViewConnectionWidget(mainWindow), + ViewConnection.ViewConnectionWidget(mainWindow), ViewBrowser.ViewBrowserWidget(mainWindow), ViewDownloadsWidget(mainWindow), ViewUploadsWidget(mainWindow), Modified: trunk/fclient/fclient/impl/Prefs.py =================================================================== --- trunk/fclient/fclient/impl/Prefs.py 2008-08-16 07:43:18 UTC (rev 910) +++ trunk/fclient/fclient/impl/Prefs.py 2008-08-16 07:54:39 UTC (rev 911) @@ -9,7 +9,7 @@ from .lib.qt4ex import dlgpreferences from .PrefsGlobal import PrefsPageGlobal from .ViewBrowser.prefs import PrefsBrowserWidget -from .PrefsConnectionWidget import PrefsPageConnectionExpertSettings +from .ViewConnection.prefs.PrefsConnectionWidget import PrefsPageConnectionExpertSettings from .PrefsSingleApp import PrefsPageSingleApp #********************************************************************************** # Deleted: trunk/fclient/fclient/impl/PrefsConnectionWidget.py =================================================================== --- trunk/fclient/fclient/impl/PrefsConnectionWidget.py 2008-08-16 07:43:18 UTC (rev 910) +++ trunk/fclient/fclient/impl/PrefsConnectionWidget.py 2008-08-16 07:54:39 UTC (rev 911) @@ -1,128 +0,0 @@ -""" -""" -#******************************************************************************* -#TODO: -# -# x. should we reconnect when the user changes the fcp connection name? -# -# -#****************************************************************************** - -from __future__ import absolute_import -if __name__ == '__main__': # see --> http://bugs.Fc.org/issue1510172 . works only current dir and below - import os; __path__ = [os.path.dirname(__file__)] - - -from PyQt4 import QtCore, QtGui - -from . import config -from .lib.qt4ex import dlgpreferences -from .lib.qt4ex.lib import settings - -from .tpls.Ui_PrefsConnectionExpertSettingsTpl import Ui_PrefsConnectionExpertSettings -#********************************************************************************** -# -#********************************************************************************** -class PrefsConnectionExpertSettingsWidget(QtGui.QWidget, Ui_PrefsConnectionExpertSettings): - - IdEdFcpConnectionName = 'edFcpConnectionName' - IdSpinFcpConnectionTimerMaxDuration = 'spinFcpConnectionTimerMaxDuration' - IdSpinConnectionTimerTimeout = 'spinConnectionTimerTimeout' - IdSpinFcpPollTimerTimeout = 'spinFcpPollTimerTimeout' - - - def __init__(self, parent=None, page=None): - QtGui.QWidget.__init__(self, parent) - - self.setupUi(self) - self.setWindowTitle(config.FcAppName + self.trUtf8(' - Connection expert settings')) - self.fcSettingsControler = None - - # - connectionWidget = config.ObjectRegistry.get(config.IdViewConnectionWidget, None) - if connectionWidget is None: - self.setEnabled(False) - else: - self.fcSettingsControler = settings.SettingsControler(connectionWidget.fcSettings, parent=self) - if page is not None: - page.connect(self.fcSettingsControler, QtCore.SIGNAL('isDirty(bool)'), page.setDirty) - self.fcSettingsControler.addLineEdit( - self.controlById(self.IdEdFcpConnectionName), - 'FcpConnectionName', - ) - self.fcSettingsControler.addSpinBox( - self.controlById(self.IdSpinFcpConnectionTimerMaxDuration), - 'FcpConnectionTimerMaxDuration', - ) - self.fcSettingsControler.addSpinBox( - self.controlById(self.IdSpinConnectionTimerTimeout), - 'FcpConnectionTimerTimeout', - ) - self.fcSettingsControler.addSpinBox( - self.controlById(self.IdSpinFcpPollTimerTimeout), - 'FcpPollTimerTimeout', - ) - - def controlById(self, idControl): - return getattr(self, idControl) - - def doApply(self): - if self.fcSettingsControler is not None: - return self.fcSettingsControler.apply() - return False - - def doRestoreDefaults(self): - if self.fcSettingsControler is not None: - return self.fcSettingsControler.restoreDefaults() - return False - -#*********************************************************************** -# -#*********************************************************************** -class PrefsPageConnectionExpertSettings(dlgpreferences.Page): - - UUID = '{{98c7efcb-5636-4bf5-8192-10e7ccb09314}' - - def __init__(self): - dlgpreferences.Page.__init__(self, self.UUID) - self._widget = None - - def displayName(self): - return self.trUtf8('Connection') - - def canApply(self): return True - def canHelp(self): return False - def canRestoreDefaults(self): return True - - def doApply(self): - self._widget.doApply() - return True - - def doRestoreDefaults(self): - self._widget.doRestoreDefaults() - return True - - def setVisible(self, parent, flag): - createdNew = False - if flag and self._widget is None: - createdNew = True - self._widget = PrefsConnectionExpertSettingsWidget(parent, page=self) - self.connect(self._widget, QtCore.SIGNAL('setDirty(bool)'), self.setDirty) - self._widget.setVisible(flag) - return (createdNew, self._widget) - - - -#*********************************************************************** -# -#*********************************************************************** -if __name__ == '__main__': - from PyQt4 import QtGui - import sys - - app = QtGui.QApplication(sys.argv) - w = PrefsConnectionExpertSettingsWidget(None) - w.show() - res = app.exec_() - sys.exit(res) - Added: trunk/fclient/fclient/impl/ViewConnection/ConnectionWidgetTpl.ui =================================================================== --- trunk/fclient/fclient/impl/ViewConnection/ConnectionWidgetTpl.ui (rev 0) +++ trunk/fclient/fclient/impl/ViewConnection/ConnectionWidgetTpl.ui 2008-08-16 07:54:39 UTC (rev 911) @@ -0,0 +1,170 @@ +<ui version="4.0" > + <class>ViewConnectionWidget</class> + <widget class="QWidget" name="ViewConnectionWidget" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>421</width> + <height>558</height> + </rect> + </property> + <property name="windowTitle" > + <string>Form</string> + </property> + <layout class="QGridLayout" name="gridLayout" > + <item row="0" column="0" > + <widget class="QLabel" name="fieldHeader" > + <property name="text" > + <string>Fcp connection:</string> + </property> + </widget> + </item> + <item row="1" column="0" > + <layout class="QHBoxLayout" name="horizontalLayout" > + <item> + <layout class="QVBoxLayout" name="verticalLayout" > + <item> + <widget class="QLabel" name="fieldName" > + <property name="text" > + <string>Host:</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="fieldName_2" > + <property name="text" > + <string>Port:</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QVBoxLayout" > + <item> + <widget class="QLineEdit" name="edFcpConnectionHost" > + <property name="dragEnabled" > + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="spinFcpConnectionPort" /> + </item> + </layout> + </item> + </layout> + </item> + <item rowspan="5" row="1" column="1" > + <widget class="Line" name="line" > + <property name="orientation" > + <enum>Qt::Vertical</enum> + </property> + </widget> + </item> + <item row="1" column="2" > + <spacer name="horizontalSpacer" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>229</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="2" column="0" > + <widget class="QCheckBox" name="ckFcpAutoConnect" > + <property name="text" > + <string>Auto Connect</string> + </property> + </widget> + </item> + <item row="3" column="0" > + <widget class="Line" name="line_2" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="4" column="0" > + <widget class="QLabel" name="fieldHeader_2" > + <property name="text" > + <string>Fproxy connection:</string> + </property> + </widget> + </item> + <item row="5" column="0" > + <layout class="QVBoxLayout" name="verticalLayout_5" > + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2" > + <item> + <layout class="QVBoxLayout" name="verticalLayout_3" > + <item> + <widget class="QLabel" name="fieldName_3" > + <property name="text" > + <string>Host:</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="fieldName_4" > + <property name="text" > + <string>Port:</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout_2" > + <item> + <widget class="QLineEdit" name="edFproxyConnectionHost" > + <property name="dragEnabled" > + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="spinFproxyConnectionPort" /> + </item> + </layout> + </item> + </layout> + </item> + </layout> + </item> + <item row="6" column="0" > + <spacer name="verticalSpacer" > + <property name="orientation" > + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>20</width> + <height>97</height> + </size> + </property> + </spacer> + </item> + <item row="7" column="0" colspan="3" > + <widget class="QPushButton" name="btConnect" > + <property name="text" > + <string>Connect</string> + </property> + <property name="checkable" > + <bool>true</bool> + </property> + <property name="autoExclusive" > + <bool>false</bool> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> Added: trunk/fclient/fclient/impl/ViewConnection/Ui_ConnectionWidgetTpl.py =================================================================== --- trunk/fclient/fclient/impl/ViewConnection/Ui_ConnectionWidgetTpl.py (rev 0) +++ trunk/fclient/fclient/impl/ViewConnection/Ui_ConnectionWidgetTpl.py 2008-08-16 07:54:39 UTC (rev 911) @@ -0,0 +1,117 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file '/home/me/src/fclient/trunk/fclient/fclient/impl/ViewConnection/ConnectionWidgetTpl.ui' +# +# Created: Sat Aug 16 09:44:39 2008 +# by: PyQt4 UI code generator 4.4.3-snapshot-20080705 +# +# WARNING! All changes made in this file will be lost! + +from PyQt4 import QtCore, QtGui + +class Ui_ViewConnectionWidget(object): + def setupUi(self, ViewConnectionWidget): + ViewConnectionWidget.setObjectName("ViewConnectionWidget") + ViewConnectionWidget.resize(421, 558) + self.gridLayout = QtGui.QGridLayout(ViewConnectionWidget) + self.gridLayout.setObjectName("gridLayout") + self.fieldHeader = QtGui.QLabel(ViewConnectionWidget) + self.fieldHeader.setObjectName("fieldHeader") + self.gridLayout.addWidget(self.fieldHeader, 0, 0, 1, 1) + self.horizontalLayout = QtGui.QHBoxLayout() + self.horizontalLayout.setObjectName("horizontalLayout") + self.verticalLayout = QtGui.QVBoxLayout() + self.verticalLayout.setObjectName("verticalLayout") + self.fieldName = QtGui.QLabel(ViewConnectionWidget) + self.fieldName.setObjectName("fieldName") + self.verticalLayout.addWidget(self.fieldName) + self.fieldName_2 = QtGui.QLabel(ViewConnectionWidget) + self.fieldName_2.setObjectName("fieldName_2") + self.verticalLayout.addWidget(self.fieldName_2) + self.horizontalLayout.addLayout(self.verticalLayout) + self.vboxlayout = QtGui.QVBoxLayout() + self.vboxlayout.setObjectName("vboxlayout") + self.edFcpConnectionHost = QtGui.QLineEdit(ViewConnectionWidget) + self.edFcpConnectionHost.setDragEnabled(True) + self.edFcpConnectionHost.setObjectName("edFcpConnectionHost") + self.vboxlayout.addWidget(self.edFcpConnectionHost) + self.spinFcpConnectionPort = QtGui.QSpinBox(ViewConnectionWidget) + self.spinFcpConnectionPort.setObjectName("spinFcpConnectionPort") + self.vboxlayout.addWidget(self.spinFcpConnectionPort) + self.horizontalLayout.addLayout(self.vboxlayout) + self.gridLayout.addLayout(self.horizontalLayout, 1, 0, 1, 1) + self.line = QtGui.QFrame(ViewConnectionWidget) + self.line.setFrameShape(QtGui.QFrame.VLine) + self.line.setFrameShadow(QtGui.QFrame.Sunken) + self.line.setObjectName("line") + self.gridLayout.addWidget(self.line, 1, 1, 5, 1) + spacerItem = QtGui.QSpacerItem(229, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.gridLayout.addItem(spacerItem, 1, 2, 1, 1) + self.ckFcpAutoConnect = QtGui.QCheckBox(ViewConnectionWidget) + self.ckFcpAutoConnect.setObjectName("ckFcpAutoConnect") + self.gridLayout.addWidget(self.ckFcpAutoConnect, 2, 0, 1, 1) + self.line_2 = QtGui.QFrame(ViewConnectionWidget) + self.line_2.setFrameShape(QtGui.QFrame.HLine) + self.line_2.setFrameShadow(QtGui.QFrame.Sunken) + self.line_2.setObjectName("line_2") + self.gridLayout.addWidget(self.line_2, 3, 0, 1, 1) + self.fieldHeader_2 = QtGui.QLabel(ViewConnectionWidget) + self.fieldHeader_2.setObjectName("fieldHeader_2") + self.gridLayout.addWidget(self.fieldHeader_2, 4, 0, 1, 1) + self.verticalLayout_5 = QtGui.QVBoxLayout() + self.verticalLayout_5.setObjectName("verticalLayout_5") + self.horizontalLayout_2 = QtGui.QHBoxLayout() + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.verticalLayout_3 = QtGui.QVBoxLayout() + self.verticalLayout_3.setObjectName("verticalLayout_3") + self.fieldName_3 = QtGui.QLabel(ViewConnectionWidget) + self.fieldName_3.setObjectName("fieldName_3") + self.verticalLayout_3.addWidget(self.fieldName_3) + self.fieldName_4 = QtGui.QLabel(ViewConnectionWidget) + self.fieldName_4.setObjectName("fieldName_4") + self.verticalLayout_3.addWidget(self.fieldName_4) + self.horizontalLayout_2.addLayout(self.verticalLayout_3) + self.verticalLayout_2 = QtGui.QVBoxLayout() + self.verticalLayout_2.setObjectName("verticalLayout_2") + self.edFproxyConnectionHost = QtGui.QLineEdit(ViewConnectionWidget) + self.edFproxyConnectionHost.setDragEnabled(True) + self.edFproxyConnectionHost.setObjectName("edFproxyConnectionHost") + self.verticalLayout_2.addWidget(self.edFproxyConnectionHost) + self.spinFproxyConnectionPort = QtGui.QSpinBox(ViewConnectionWidget) + self.spinFproxyConnectionPort.setObjectName("spinFproxyConnectionPort") + self.verticalLayout_2.addWidget(self.spinFproxyConnectionPort) + self.horizontalLayout_2.addLayout(self.verticalLayout_2) + self.verticalLayout_5.addLayout(self.horizontalLayout_2) + self.gridLayout.addLayout(self.verticalLayout_5, 5, 0, 1, 1) + spacerItem1 = QtGui.QSpacerItem(20, 97, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.gridLayout.addItem(spacerItem1, 6, 0, 1, 1) + self.btConnect = QtGui.QPushButton(ViewConnectionWidget) + self.btConnect.setCheckable(True) + self.btConnect.setAutoExclusive(False) + self.btConnect.setObjectName("btConnect") + self.gridLayout.addWidget(self.btConnect, 7, 0, 1, 3) + + self.retranslateUi(ViewConnectionWidget) + QtCore.QMetaObject.connectSlotsByName(ViewConnectionWidget) + + def retranslateUi(self, ViewConnectionWidget): + ViewConnectionWidget.setWindowTitle(QtGui.QApplication.translate("ViewConnectionWidget", "Form", None, QtGui.QApplication.UnicodeUTF8)) + self.fieldHeader.setText(QtGui.QApplication.translate("ViewConnectionWidget", "Fcp connection:", None, QtGui.QApplication.UnicodeUTF8)) + self.fieldName.setText(QtGui.QApplication.translate("ViewConnectionWidget", "Host:", None, QtGui.QApplication.UnicodeUTF8)) + self.fieldName_2.setText(QtGui.QApplication.translate("ViewConnectionWidget", "Port:", None, QtGui.QApplication.UnicodeUTF8)) + self.ckFcpAutoConnect.setText(QtGui.QApplication.translate("ViewConnectionWidget", "Auto Connect", None, QtGui.QApplication.UnicodeUTF8)) + self.fieldHeader_2.setText(QtGui.QApplication.translate("ViewConnectionWidget", "Fproxy connection:", None, QtGui.QApplication.UnicodeUTF8)) + self.fieldName_3.setText(QtGui.QApplication.translate("ViewConnectionWidget", "Host:", None, QtGui.QApplication.UnicodeUTF8)) + self.fieldName_4.setText(QtGui.QApplication.translate("ViewConnectionWidget", "Port:", None, QtGui.QApplication.UnicodeUTF8)) + self.btConnect.setText(QtGui.QApplication.translate("ViewConnectionWidget", "Connect", None, QtGui.QApplication.UnicodeUTF8)) + + +if __name__ == "__main__": + import sys + app = QtGui.QApplication(sys.argv) + ViewConnectionWidget = QtGui.QWidget() + ui = Ui_ViewConnectionWidget() + ui.setupUi(ViewConnectionWidget) + ViewConnectionWidget.show() + sys.exit(app.exec_()) + Added: trunk/fclient/fclient/impl/ViewConnection/ViewConnection.py =================================================================== --- trunk/fclient/fclient/impl/ViewConnection/ViewConnection.py (rev 0) +++ trunk/fclient/fclient/impl/ViewConnection/ViewConnection.py 2008-08-16 07:54:39 UTC (rev 911) @@ -0,0 +1,324 @@ +#********************************************************************* +#TODO: +# x. setting fcp/fproxy connection params currently won't reset connection. how to handle? +# +# +#********************************************************************* +# some fixes for relative imports +# see --> [http://bugs.python.org/issue1510172] absolute/rellative import not working (works only current dir and below) +# see --> [http://mail.python.org/pipermail/python-ideas/2007-February/000232.html] PEP for executing a module in a +# ...package containing relative imports +from __future__ import absolute_import +if __name__ == '__main__': + import os + __path__ = [os.path.dirname(__file__)] + from ._fix_mexec import fix_mexec + fix_mexec(__name__, __file__) + del fix_mexec +from PyQt4 import QtCore, QtGui + +from .. import config +from ..lib import fcp2 + +from .Ui_ConnectionWidgetTpl import Ui_ViewConnectionWidget +#********************************************************************************** +# +#********************************************************************************** +class Actions(config.ActionsBase): + pass + + +class GlobalFeedback(config.GlobalFeedbackBase): + """wrapper for global statusbar widgets, menus""" + + def __init__(self, parent,idGlobalFeedback): + config.GlobalFeedbackBase.__init__(self, parent,idGlobalFeedback) + + # menus + self.menus = [] + if self.menuBar is not None and hasattr(parent, 'fcViewObject'): + menu = QtGui.QMenu(parent.fcViewObject.displayName, self.menuBar) + parent.populateMenu(menu) + self.menus.append(menu) + self.menuBar.addViewMenu(menu) + + # status bar widgets + self.label1 = None + #if self.statusBar is not None: + # self.label1 = QtGui.QLabel('foo here', self.statusBar) + + def setVisible(self, flag): + for menu in self.menus: + menu.children()[0].setEnabled(flag) + if self.label1 is not None: + self.label1.setVisible(flag) + + +class Settings(config.SettingsBase): + _key_ = config.IdViewConnectionWidget + _settings_ = ( + ('FcpAutoConnect', 'Bool', True), + ('FcpConnectionName', 'String', config.FcConnectionName), + ('FcpConnectionHost', 'String', fcp2.Client.DefaultFcpHost), + ('FcpConnectionPort', 'UInt', fcp2.Client.DefaultFcpPort), + ('FcpConnectionTimerTimeout', 'UInt', 500), + ('FcpConnectionTimerMaxDuration', 'UInt', 20), + ('FcpPollTimerTimeout', 'UInt', 200), + + ('FproxyConnectionHost', 'String','127.0.0.1'), + ('FproxyConnectionPort', 'UInt', 8888), + ) + + def setValues(self, **kws): + config.SettingsBase.setValues(self, **kws) + parent = self.parent() + + # set fcp connection params + if 'FcpConnectionHost' in kws: + edHost = parent.controlById(parent.IdEdFcpConnectionHost) + edHost.setText(self.value('FcpConnectionHost')) + + if 'FcpConnectionPort' in kws: + spinPort = parent.controlById(parent.IdFcpSpinFcpConnectionPort) + spinPort.setValue(self.value('FcpConnectionPort')) + + if 'FcpAutoConnect' in kws: + ck = parent.controlById(parent.IdCkFcpAutoConnect) + ck.setChecked(self.value('FcpAutoConnect')) + + # set fproxy connection params + if 'FproxyConnectionHost' in kws: + edHost = parent.controlById(parent.IdEdFproxyConnectionHost) + edHost.setText(self.value('FproxyConnectionHost')) + + if 'FproxyConnectionPort' in kws: + spinPort = parent.controlById(parent.IdFproxySpinConnectionPort) + spinPort.setValue(self.value('FproxyConnectionPort')) + + +class ConnectionViewObject(config.ViewObject): + + def __init__(self, parent): + config.ViewObject. __init__(self, parent) + + self.name=parent.objectName() + self.displayName=self.trUtf8('Connection') + self.icon=QtGui.QIcon() + + +#********************************************************************************** +# +#********************************************************************************** +class ConnectionTimer(QtCore.QTimer): + + def __init__(self,parent): + QtCore.QTimer.__init__(self, parent) + self.fcpIterConnect = None + self.connect(self, QtCore.SIGNAL('timeout()'), self.onNext) + + def start(self, settings): + config.fcpClient.setConnectionName(settings.value('FcpConnectionName')) + self.fcpIterConnect = config.fcpClient.iterConnect( + host=settings.value('FcpConnectionHost'), + port=settings.value('FcpConnectionPort'), + duration=settings.value('FcpConnectionTimerMaxDuration'), + timeout=0 + ) + if not self.onNext(): + QtCore.QTimer.start(self, settings.value('FcpConnectionTimerTimeout')) + + def onNext(self): + try: + result = self.fcpIterConnect.next() + except StopIteration: + self.stop() + else: + if result is not None: + self.stop() + return True + return False + + +class PollTimer(QtCore.QTimer): + + def __init__(self,parent): + QtCore.QTimer.__init__(self, parent) + self.connect(self, QtCore.SIGNAL('timeout()'), self.onNext) + + def start(self, settings): + QtCore.QTimer.start(self, settings.value('FcpPollTimerTimeout')) + + def onNext(self): + if config.fcpClient.isConnected(): + result = config.fcpClient.next() + +#*********************************************************************** +# +#*********************************************************************** +class ViewConnectionWidget(QtGui.QWidget, Ui_ViewConnectionWidget): + + IdBtConnect = 'btConnect' + IdEdFcpConnectionHost = 'edFcpConnectionHost' + IdFcpSpinFcpConnectionPort = 'spinFcpConnectionPort' + IdCkFcpAutoConnect = 'ckFcpAutoConnect' + + IdEdFproxyConnectionHost = 'edFproxyConnectionHost' + IdFproxySpinConnectionPort = 'spinFproxyConnectionPort' + + + def __init__(self, parent, idGlobalFeedback=config.IdMainWindow): + QtGui.QWidget.__init__(self, parent) + self.setupUi(self) + + # adjust spin box ranges + spinPort = self.controlById(self.IdFcpSpinFcpConnectionPort) + spinPort.setRange(0, 0xFFFF) #TODO: no idea if port range (0, 0xFFFF) this is reasonable + spinPort = self.controlById(self.IdFproxySpinConnectionPort) + spinPort.setRange(0, 0xFFFF) #TODO: no idea if port range (0, 0xFFFF) this is reasonable + + self._isCreated = False + config.ObjectRegistry.register(self) + self.fcSettings = Settings(self).restore() + self.fcActions = Actions(self) + self.fcViewObject = ConnectionViewObject(self) + self.fcGlobalFeedback = GlobalFeedback(self,idGlobalFeedback) + + self._connectionTimer = ConnectionTimer(self) + self._pollTimer = PollTimer(self) + self._fcpEventonrs = ( + (config.fcpClient.events.ClientConnected, self.onFcpClientConected), + (config.fcpClient.events.ClientDisconnected, self.onFcpClientDisconected), + ) + config.fcpClient.events += self._fcpEventonrs + self._mainWindowMenus = () + + ######################################### + ## methods + ######################################### + def connected(self): + return self.controlById(self.IdBtConnect).isChecked() + + def controlById(self, idControl): + return getattr(self, idControl) + + def populateMenu(self, menu): + return menu + + def setConnected(self, flag): + bt = self.controlById(self.IdBtConnect) + if (bt.isChecked() and not flag) or (not bt.isChecked() and flag): + bt.click() + return True + return False + + ######################################### + ## view methods + ######################################### + def viewClose(self): + config.fcpClient.events -= self._fcpEventonrs + + ######################################### + ## overwritten events + ######################################### + def closeEvent(self, event): + self.viewClose() + + def hideEvent(self, event): + self.fcGlobalFeedback.setVisible(False) + + def showEvent(self, event): + self.fcGlobalFeedback.setVisible(True) + if self._isCreated: + return + self._isCreated = True + + doAutoConnect = self.fcSettings.value('FcpAutoConnect') + ck = self.controlById(self.IdCkFcpAutoConnect) + ck.setChecked(doAutoConnect) + self.connect(ck, QtCore.SIGNAL('stateChanged(int)'), self.onCkFcpAutoConnectStateChanged) + + spinPort = self.controlById(self.IdFcpSpinFcpConnectionPort) + self.connect(spinPort, QtCore.SIGNAL('valueChanged(int)'), self.onSpinFcpConnectionPortChanged) + + spinPort = self.controlById(self.IdFproxySpinConnectionPort) + self.connect(spinPort, QtCore.SIGNAL('valueChanged(int)'), self.onSpinFproxyConnectionPortChanged) + + # setup fproxy host / port + edHost = self.controlById(self.IdEdFproxyConnectionHost) + self.connect(edHost, QtCore.SIGNAL('textChanged(const QString &)'), self.onEdFproxyConnectionHostChanged) + + bt = self.controlById(self.IdBtConnect) + self.connect(bt, QtCore.SIGNAL('clicked(bool)'), self.onBtConnectClicked) + if doAutoConnect: + self.controlById(self.IdBtConnect).click() + + ######################################## + ## overwritten methods + ######################################### + def retranslateUi(self, w): + Ui_ViewConnectionWidget.retranslateUi(self, w) + bt = self.controlById(self.IdBtConnect) + bt.setText(self.trUtf8('Disconnect') if self.connected() else self.trUtf8('Connect')) + + + ######################################### + ## event onrs + ######################################### + def onBtConnectClicked(self, isChecked): + bt = self.controlById(self.IdBtConnect) + bt.setText(self.trUtf8('Disconnect') if isChecked else self.trUtf8('Connect')) + if isChecked: + if config.fcpClient.isConnected(): + config.fcpClient.close() + self._connectionTimer.start(self.fcSettings) + else: + self._connectionTimer.stop() + if config.fcpClient.isConnected(): + self._pollTimer.stop() + config.fcpClient.close() + + + def onCkFcpAutoConnectStateChanged(self, state): + self.fcSettings.setValues(FcpAutoConnect=state == QtCore.Qt.Checked) + + def onEdFcpConnectionHostChanged(self, text): + self.fcSettings.setValues(FcpConnectionHost=text) + + def onSpinFcpConnectionPortChanged(self, value): + self.fcSettings.setValues(FcpConnectionPort=value) + + def onEdFproxyConnectionHostChanged(self, text): + self.fcSettings.setValues(FproxyConnectionHost=text) + + def onSpinFproxyConnectionPortChanged(self, value): + self.fcSettings.setValues(FproxyConnectionPort=value) + + ######################################### + ## fcp event onrs + ######################################### + def onFcpClientDisconected(self, event, msg): + bt = self.controlById(self.IdBtConnect) + if bt.isChecked(): + bt.click() + + def onFcpClientConected(self, event, msg): + self._pollTimer.start(self.fcSettings) + +#********************************************************************************** +# +#********************************************************************************** +if __name__ == '__main__': + import sys + from .. import View, ViewLogger + + app = QtGui.QApplication(sys.argv) + w = View.ViewWidget(None) + w.addTopViews(ViewConnectionWidget(None)) + w.addBottomViews(ViewLogger.ViewLoggerWidget(None)) + + w.show() + res = app.exec_() + sys.exit(res) + + + Added: trunk/fclient/fclient/impl/ViewConnection/__init__.py =================================================================== --- trunk/fclient/fclient/impl/ViewConnection/__init__.py (rev 0) +++ trunk/fclient/fclient/impl/ViewConnection/__init__.py 2008-08-16 07:54:39 UTC (rev 911) @@ -0,0 +1 @@ + Added: trunk/fclient/fclient/impl/ViewConnection/_fix_mexec.py =================================================================== --- trunk/fclient/fclient/impl/ViewConnection/_fix_mexec.py (rev 0) +++ trunk/fclient/fclient/impl/ViewConnection/_fix_mexec.py 2008-08-16 07:54:39 UTC (rev 911) @@ -0,0 +1,99 @@ +'''in python 2.5 relative impports are srsly broken ..fix this to make relative imports work +when executing a module as main (-m), including relative imports up to the root package + +see: [http://mail.python.org/pipermail/python-ideas/2007-February/000232.html] + +@note: root package is the highest available package in the package hirarchy. +don't look at __name__ too closely. it gets adjusted for a module to just "do the right +thing" in __name__ == '__main__' comparisons +@note: this patch does not work if relative imports are done in __init__.py. no idea why +and to be honest, I don't wanna* know.. +@note: this is more or less a hack. so it may have unwanted side effects for example +when importing parent packages. use at your own risk. could improve this module +by adding a __main__.py to stop at this level or by fixing the __init__.py bug, but +I don't think its worth it. see what python2.6 or 3k brings.. + +usage:: + + # place this at the top a module, before doing any relative imports + from fix_mexec import fix_mexec + fix_mexec(__name__, __file__) + del fix_mexec + + from ...foo import bar + + + +##<-- copy and paste code, assuming _fix_mexec resides in the current dir.. + +# some fixes for relative imports +# see --> [http://bugs.python.org/issue1510172] absolute/rellative import not working (works only current dir and below) +# see --> [http://mail.python.org/pipermail/python-ideas/2007-February/000232.html] PEP for executing a module in a +# ...package containing relative imports +from __future__ import absolute_import +if __name__ == '__main__': + import os + __path__ = [os.path.dirname(__file__)] + from ._fix_mexec import fix_mexec + fix_mexec(__name__, __file__) + del fix_mexec + + +##--> copy and paste code +''' + +import imp, os, sys +#******************************************************************************** +# +#******************************************************************************** +class MainName(str): + def __eq__(self, other): + if other == '__main__': return True + return str.__eq__(self, other) + def __ne__(self, other): + if other == '__main__': return False + return str.__ne__(self, other) + + +def fix_mexec(_name_, _file_): + """bugfix for relative imports not working + @param _name_: __name__ of the module + @param _file_: __file__ of the module + + @note: not complete: relies on __init__.py, .pyo (...) is ignored currently + """ + if _name_ == '__main__': + out = [] + # find allparent packages + p = os.path.dirname(os.path.abspath(_file_)) + prev = p + while True: + pkg = os.path.join(p, '__init__.py') + if os.path.isfile(pkg): + out.append([pkg, os.path.basename(p)]) + else: + break + prev = p + p = os.path.dirname(p) + if p == prev: + break + out.reverse() + + # adjust sub package names an import parent modules + name = None + for n, (fpath, name) in enumerate(out): + if n > 0: + name = out[n][1] = out[n -1][1] + '.' + out[n][1] + m = imp.load_source(name, fpath) + m.__path__ = [os.path.dirname(fpath)] + + # adjust name of the __main__ module + if name is not None: + m = sys.modules.pop('__main__') + # 'foo.bar..__main__' does not work for some reason. 'foo.bar' seems to work as expected + ##m.__name__ = _Name_(name + '.' + '__main__') + m.__name__ = MainName(name) + sys.modules[m.__name__] = m + + + Added: trunk/fclient/fclient/impl/ViewConnection/prefs/PrefsConnectionExpertSettings.ui =================================================================== --- trunk/fclient/fclient/impl/ViewConnection/prefs/PrefsConnectionExpertSettings.ui (rev 0) +++ trunk/fclient/fclient/impl/ViewConnection/prefs/PrefsConnectionExpertSettings.ui 2008-08-16 07:54:39 UTC (rev 911) @@ -0,0 +1,235 @@ +<ui version="4.0" > + <class>PrefsConnectionExpertSettings</class> + <widget class="QWidget" name="PrefsConnectionExpertSettings" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>520</width> + <height>502</height> + </rect> + </property> + <property name="windowTitle" > + <string>Form</string> + </property> + <layout class="QGridLayout" name="gridLayout" > + <item row="0" column="0" > + <layout class="QVBoxLayout" name="verticalLayout_3" > + <item> + <widget class="QLabel" name="fieldHeader" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Fixed" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" > + <string>Connection name:</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_5" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Preferred" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" > + <string>Adjusts the name the client uses to connect to the node. Use this for example to adjust the connection name in case the name is already in use by other clients. WARNING: changing this will loose your current qequests untill you connect under that name again</string> + </property> + <property name="alignment" > + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> + </property> + <property name="wordWrap" > + <bool>true</bool> + </property> + <property name="textInteractionFlags" > + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard</set> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="edFcpConnectionName" /> + </item> + <item> + <widget class="QLabel" name="fieldHeader_2" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Fixed" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" > + <string>Connect duration and timeout:</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_6" > + <property name="text" > + <string>How long should the client try to connect to the node before finally giving up? How long should he wait before retrying to establish a connection? WARNING: setting timeout to low values may cause the gui to slow down</string> + </property> + <property name="wordWrap" > + <bool>true</bool> + </property> + <property name="textInteractionFlags" > + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard</set> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout" > + <item> + <layout class="QVBoxLayout" name="verticalLayout" > + <item> + <widget class="QLabel" name="fieldName" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Preferred" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" > + <string>Duration: </string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="fieldName_2" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Preferred" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" > + <string>Timeout:</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout_2" > + <item> + <widget class="QSpinBox" name="spinFcpConnectionTimerMaxDuration" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Expanding" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="suffix" > + <string> seconds</string> + </property> + <property name="maximum" > + <number>999</number> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="spinConnectionTimerTimeout" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Expanding" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="suffix" > + <string> miliseconds</string> + </property> + <property name="maximum" > + <number>99999</number> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + <item> + <widget class="QLabel" name="fieldHeader_3" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Fixed" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" > + <string>Poll frequency: </string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_7" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Preferred" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" > + <string>How long should the client wait before polling the node for a the next message? Warning: setting this to high values will make messages come in more slowly. Setting it to low values may cause the gui to slow down.</string> + </property> + <property name="wordWrap" > + <bool>true</bool> + </property> + <property name="textInteractionFlags" > + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard</set> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="spinFcpPollTimerTimeout" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Expanding" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="suffix" > + <string> miliseconds</string> + </property> + <property name="maximum" > + <number>99999</number> + </property> + </widget> + </item> + </layout> + </item> + <item row="1" column="0" > + <spacer name="verticalSpacer" > + <property name="orientation" > + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>20</width> + <height>87</height> + </size> + </property> + </spacer> + </item> + </layout> + <zorder>tabWidget</zorder> + <zorder>label</zorder> + <zorder>fieldHeader</zorder> + <zorder>label_5</zorder> + <zorder>edFcpConnectionName</zorder> + <zorder>fieldHeader_2</zorder> + <zorder>label_6</zorder> + <zorder>fieldName</zorder> + <zorder>spinFcpConnectionTimerMaxDuration</zorder> + <zorder>fieldName_2</zorder> + <zorder>spinConnectionTimerTimeout</zorder> + <zorder>label_7</zorder> + <zorder>spinFcpPollTimerTimeout</zorder> + <zorder>fieldHeader_3</zorder> + <zorder>verticalSpacer</zorder> + <zorder></zorder> + </widget> + <resources/> + <connections/> +</ui> Added: trunk/fclient/fclient/impl/ViewConnection/prefs/PrefsConnectionWidget.py =================================================================== --- trunk/fclient/fclient/impl/ViewConnection/prefs/PrefsConnectionWidget.py (rev 0) +++ trunk/fclient/fclient/impl/ViewConnection/prefs/PrefsConnectionWidget.py 2008-08-16 07:54:39 UTC (rev 911) @@ -0,0 +1,135 @@ +""" +""" +#******************************************************************************* +#TODO: +# +# x. should we reconnect when the user changes the fcp connection name? +# +# +#****************************************************************************** +# some fixes for relative imports +# see --> [http://bugs.python.org/issue1510172] absolute/rellative import not working (works only current dir and below) +# see --> [http://mail.python.org/pipermail/python-ideas/2007-February/000232.html] PEP for executing a module in a +# ...package containing relative imports +from __future__ import absolute_import +if __name__ == '__main__': + import os + __path__ = [os.path.dirname(__file__)] + from ._fix_mexec import fix_mexec + fix_mexec(__name__, __file__) + del fix_mexec + + +from PyQt4 import QtCore, QtGui + +from ... import config +from ...lib.qt4ex import dlgpreferences +from ...lib.qt4ex.lib import settings + +from .Ui_PrefsConnectionExpertSettings import Ui_PrefsConnectionExpertSettings +#********************************************************************************** +# +#********************************************************************************** +class PrefsConnectionExpertSettingsWidget(QtGui.QWidget, Ui_PrefsConnectionExpertSettings): + + IdEdFcpConnectionName = 'edFcpConnectionName' + IdSpinFcpConnectionTimerMaxDuration = 'spinFcpConnectionTimerMaxDuration' + IdSpinConnectionTimerTimeout = 'spinConnectionTimerTimeout' + IdSpinFcpPollTimerTimeout = 'spinFcpPollTimerTimeout' + + + def __init__(self, parent=None, page=None): + QtGui.QWidget.__init__(self, parent) + + self.setupUi(self) + self.setWindowTitle(config.FcAppName + self.trUtf8(' - Connection expert settings')) + self.fcSettingsControler = None + + # + connectionWidget = config.ObjectRegistry.get(config.IdViewConnectionWidget, None) + if connectionWidget is None: + self.setEnabled(False) + else: + self.fcSettingsControler = settings.SettingsControler(connectionWidget.fcSettings, parent=self) + if page is not None: + page.connect(self.fcSettingsControler, QtCore.SIGNAL('isDirty(bool)'), page.setDirty) + self.fcSettingsControler.addLineEdit( + self.controlById(self.IdEdFcpConnectionName), + 'FcpConnectionName', + ) + self.fcSettingsControler.addSpinBox( + self.controlById(self.IdSpinFcpConnectionTimerMaxDuration), + 'FcpConnectionTimerMaxDuration', + ) + self.fcSettingsControler.addSpinBox( + self.controlById(self.IdSpinConnectionTimerTimeout), + 'FcpConnectionTimerTimeout', + ) + self.fcSettingsControler.addSpinBox( + self.controlById(self.IdSpinFcpPollTimerTimeout), + 'FcpPollTimerTimeout', + ) + + def controlById(self, idControl): + return getattr(self, idControl) + + def doApply(self): + if self.fcSettingsControler is not None: + return self.fcSettingsControler.apply() + return False + + def doRestoreDefaults(self): + if self.fcSettingsControler is not None: + return self.fcSettingsControler.restoreDefaults() + return False + +#*********************************************************************** +# +#*********************************************************************** +class PrefsPageConnectionExpertSettings(dlgpreferences.Page): + + UUID = '{{98c7efcb-5636-4bf5-8192-10e7ccb09314}' + + def __init__(self): + dlgpreferences.Page.__init__(self, self.UUID) + self._widget = None + + def displayName(self): + return self.trUtf8('Connection') + + def canApply(self): return True + def canHelp(self): return False + def canRestoreDefaults(self): return True + + def doApply(self): + self._widget.doApply() + return True + + def doRestoreDefaults(self): + self._widget.doRestoreDefaults() + return True + + def setVisible(self, parent, flag): + createdNew = False + if flag and self._widget is None: + createdNew = True + self._widget = PrefsConnectionExpertSettingsWidget(parent, page=self) + self.connect(self._widget, QtCore.SIGNAL('setDirty(bool)'), self.setDirty) + self._widget.setVisible(flag) + return (createdNew, self._widget) + + + +#*********************************************************************** +# +#*********************************************************************** +if __name__ == '__main__': + from PyQt4 import QtGui + import sys + + app = QtGui.QApplication(sys.argv) + w = PrefsConnectionExpertSettingsWidget(None) + w.show() + res = app.exec_() + sys.exit(res) + Added: trunk/fclient/fclient/impl/ViewConnection/prefs/Ui_PrefsConnectionExpertSettings.py =================================================================== --- trunk/fclient/fclient/impl/ViewConnection/prefs/Ui_PrefsConnectionExpertSettings.py (rev 0) +++ trunk/fclient/fclient/impl/ViewConnection/prefs/Ui_PrefsConnectionExpertSettings.py 2008-08-16 07:54:39 UTC (rev 911) @@ -0,0 +1,155 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file '/home/me/src/fclient/trunk/fclient/fclient/impl/ViewConnection/prefs/PrefsConnectionExpertSettings.ui' +# +# Created: Sat Aug 16 09:47:48 2008 +# by: PyQt4 UI code generator 4.4.3-snapshot-20080705 +# +# WARNING! All changes made in this file will be lost! + +from PyQt4 import QtCore, QtGui + +class Ui_PrefsConnectionExpertSettings(object): + def setupUi(self, PrefsConnectionExpertSettings): + PrefsConnectionExpertSettings.setObjectName("PrefsConnectionExpertSettings") + PrefsConnectionExpertSettings.resize(520, 502) + self.gridLayout = QtGui.QGridLayout(PrefsConnectionExpertSettings) + self.gridLayout.setObjectName("gridLayout") + self.verticalLayout_3 = QtGui.QVBoxLayout() + self.verticalLayout_3.setObjectName("verticalLayout_3") + self.fieldHeader = QtGui.QLabel(PrefsConnectionExpertSettings) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.fieldHeader.sizePolicy().hasHeightForWidth()) + self.fieldHeader.setSizePolicy(sizePolicy) + self.fieldHeader.setObjectName("fieldHeader") + self.verticalLayout_3.addWidget(self.fieldHeader) + self.label_5 = QtGui.QLabel(PrefsConnectionExpertSettings) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.label_5.sizePolicy().hasHeightForWidth()) + self.label_5.setSizePolicy(sizePolicy) + self.label_5.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop) + self.label_5.setWordWrap(True) + self.label_5.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse|QtCore.Qt.TextSelectableByKeyboard) + self.label_5.setObjectName("label_5") + self.verticalLayout_3.addWidget(self.label_5) + self.edFcpConnectionName = QtGui.QLineEdit(PrefsConnectionExpertSettings) + self.edFcpConnectionName.setObjectName("edFcpConnectionName") + self.verticalLayout_3.addWidget(self.edFcpConnectionName) + self.fieldHeader_2 = QtGui.QLabel(PrefsConnectionExpertSettings) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.fieldHeader_2.sizePolicy().hasHeightForWidth()) + self.fieldHeader_2.setSizePolicy(sizePolicy) + self.fieldHeader_2.setObjectName("fieldHeader_2") + self.verticalLayout_3.addWidget(self.fieldHeader_2) + self.label_6 = QtGui.QLabel(PrefsConnectionExpertSettings) + self.label_6.setWordWrap(True) + self.label_6.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse|QtCore.Qt.TextSelectableByKeyboard) + self.label_6.setObjectName("label_6") + self.verticalLayout_3.addWidget(self.label_6) + self.horizontalLayout = QtGui.QHBoxLayout() + self.horizontalLayout.setObjectName("horizontalLayout") + self.verticalLayout = QtGui.QVBoxLayout() + self.verticalLayout.setObjectName("verticalLayout") + self.fieldName = QtGui.QLabel(PrefsConnectionExpertSettings) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.fieldName.sizePolicy().hasHeightForWidth()) + self.fieldName.setSizePolicy(sizePolicy) + self.fieldName.setObjectName("fieldName") + self.verticalLayout.addWidget(self.fieldName) + self.fieldName_2 = QtGui.QLabel(PrefsConnectionExpertSettings) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.fieldName_2.sizePolicy().hasHeightForWidth()) + self.fieldName_2.setSizePolicy(sizePolicy) + self.fieldName_2.setObjectName("fieldName_2") + self.verticalLayout.addWidget(self.fieldName_2) + self.horizontalLayout.addLayout(self.verticalLayout) + self.verticalLayout_2 = QtGui.QVBoxLayout() + self.verticalLayout_2.setObjectName("verticalLayout_2") + self.spinFcpConnectionTimerMaxDuration = QtGui.QSpinBox(PrefsConnectionExpertSettings) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.spinFcpConnectionTimerMaxDuration.sizePolicy().hasHeightForWidth()) + self.spinFcpConnectionTimerMaxDuration.setSizePolicy(sizePolicy) + self.spinFcpConnectionTimerMaxDuration.setMaximum(999) + self.spinFcpConnectionTimerMaxDuration.setObjectName("spinFcpConnectionTimerMaxDuration") + self.verticalLayout_2.addWidget(self.spinFcpConnectionTimerMaxDuration) + self.spinConnectionTimerTimeout = QtGui.QSpinBox(PrefsConnectionExpertSettings) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.spinConnectionTimerTimeout.sizePolicy().hasHeightForWidth()) + self.spinConnectionTimerTimeout.setSizePolicy(sizePolicy) + self.spinConnectionTimerTimeout.setMaximum(99999) + self.spinConnectionTimerTimeout.setObjectName("spinConnectionTimerTimeout") + self.verticalLayout_2.addWidget(self.spinConnectionTimerTimeout) + self.horizontalLayout.addLayout(self.verticalLayout_2) + self.verticalLayout_3.addLayout(self.horizontalLayout) + self.fieldHeader_3 = QtGui.QLabel(PrefsConnectionExpertSettings) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.fieldHeader_3.sizePolicy().hasHeightForWidth()) + self.fieldHeader_3.setSizePolicy(sizePolicy) + self.fieldHeader_3.setObjectName("fieldHeader_3") + self.verticalLayout_3.addWidget(self.fieldHeader_3) + self.label_7 = QtGui.QLabel(PrefsConnectionExpertSettings) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.label_7.sizePolicy().hasHeightForWidth()) + self.label_7.setSizePolicy(sizePolicy) + self.label_7.setWordWrap(True) + self.label_7.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse|QtCore.Qt.TextSelectableByKeyboard) + self.label_7.setObjectName("label_7") + self.verticalLayout_3.addWidget(self.label_7) + self.spinFcpPollTimerTimeout = QtGui.QSpinBox(PrefsConnectionExpertSettings) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.spinFcpPollTimerTimeout.sizePolicy().hasHeightForWidth()) + self.spinFcpPollTimerTimeout.setSizePolicy(sizePolicy) + self.spinFcpPollTimerTimeout.setMaximum(99999) + self.spinFcpPollTimerTimeout.setObjectName("spinFcpPollTimerTimeout") + self.verticalLayout_3.addWidget(self.spinFcpPollTimerTimeout) + self.gridLayout.addLayout(self.verticalLayout_3, 0, 0, 1, 1) + spacerItem = QtGui.QSpacerItem(20, 87, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.gridLayout.addItem(spacerItem, 1, 0, 1, 1) + + self.retranslateUi(PrefsConnectionExpertSettings) + QtCore.QMetaObject.connectSlotsByName(PrefsConnectionExpertSettings) + + def retranslateUi(self, PrefsConnectionExpertSettings): + PrefsConnectionExpertSettings.setWindowTitle(QtGui.QApplication.translate("PrefsConnectionExpertSettings", "Form", None, QtGui.QApplication.UnicodeUTF8)) + self.fieldHeader.setText(QtGui.QApplication.translate("PrefsConnectionExpertSettings", "Connection name:", None, QtGui.QApplication.UnicodeUTF8)) + self.label_5.setText(QtGui.QApplication.translate("PrefsConnectionExpertSettings", "Adjusts the name the client uses to connect to the node. Use this for example to adjust the connection name in case the name is already in use by other clients. WARNING: changing this will loose your current qequests untill you connect under that name again", None, QtGui.QApplication.UnicodeUTF8)) + self.fieldHeader_2.setText(QtGui.QApplication.translate("PrefsConnectionExpertSettings", "Connect duration and timeout:", None, QtGui.QApplication.UnicodeUTF8)) + self.label_6.setText(QtGui.QApplication.translate("PrefsConnectionExpertSettings", "How long should the client try to connect to the node before finally giving up? How long should he wait before retrying to establish a connection? WARNING: setting timeout to low values may cause the gui to slow down", None, QtGui.QApplication.UnicodeUTF8)) + self.fieldName.setText(QtGui.QApplication.translate("PrefsConnectionExpertSettings", "Duration: ", None, QtGui.QApplication.UnicodeUTF8)) + self.fieldName_2.setText(QtGui.QApplication.translate("PrefsConnectionExpertSettings", "Timeout:", None, QtGui.QApplication.UnicodeUTF8)) + self.spinFcpConnectionTimerMaxDuration.setSuffix(QtGui.QApplication.translate("PrefsConnectionExpertSettings", " seconds", None, QtGui.QApplication.UnicodeUTF8)) + self.spinConnectionTimerTimeout.setSuffix(QtGui.QApplication.translate("PrefsConnectionExpertSettings", " miliseconds", None, QtGui.QApplication.UnicodeUTF8)) + self.fieldHeader_3.setText(QtGui.QApplication.translate("PrefsConnectionExpertSettings", "Poll frequency: ", None, QtGui.QApplication.UnicodeUTF8)) + self.label_7.setText(QtGui.QApplication.translate("PrefsConnectionExpertSettings", "How long should the client wait before polling the node for a the next message? Warning: setting this to high values will make messages come in more slowly. Setting it to low values may cause the gui to slow down.", None, QtGui.QApplication.UnicodeUTF8)) + self.spinFcpPollTimerTimeout.setSuffix(QtGui.QApplication.translate("PrefsConnectionExpertSettings", " miliseconds", None, QtGui.QApplication.UnicodeUTF8)) + + +if __name__ == "__main__": + import sys + app = QtGui.QApplication(sys.argv) + PrefsConnectionExpertSettings = QtGui.QWidget() + ui = Ui_PrefsConnectionExpertSettings() + ui.setupUi(PrefsConnectionExpertSettings) + PrefsConnectionExpertSettings.show() + sys.exit(app.exec_()) + Added: trunk/fclient/fclient/impl/ViewConnection/prefs/__init__.py =================================================================== -... [truncated message content] |
From: <jU...@us...> - 2008-08-16 07:43:10
|
Revision: 910 http://fclient.svn.sourceforge.net/fclient/?rev=910&view=rev Author: jUrner Date: 2008-08-16 07:43:18 +0000 (Sat, 16 Aug 2008) Log Message: ----------- isolated browser view Modified Paths: -------------- trunk/fclient/fclient/fclient.py trunk/fclient/fclient/impl/Prefs.py Added Paths: ----------- trunk/fclient/fclient/impl/ViewBrowser/ trunk/fclient/fclient/impl/ViewBrowser/Actions.py trunk/fclient/fclient/impl/ViewBrowser/Browser.py trunk/fclient/fclient/impl/ViewBrowser/BrowserWidget.ui trunk/fclient/fclient/impl/ViewBrowser/GlobalFeedback.py trunk/fclient/fclient/impl/ViewBrowser/NetworkAccessManager.py trunk/fclient/fclient/impl/ViewBrowser/Page.py trunk/fclient/fclient/impl/ViewBrowser/Settings.py trunk/fclient/fclient/impl/ViewBrowser/SideBar.py trunk/fclient/fclient/impl/ViewBrowser/SideBars/ trunk/fclient/fclient/impl/ViewBrowser/SideBars/SideBarLoadDetails.py trunk/fclient/fclient/impl/ViewBrowser/SideBars/SideBarLoadDetailsTpl.ui trunk/fclient/fclient/impl/ViewBrowser/SideBars/Ui_SideBarLoadDetailsTpl.py trunk/fclient/fclient/impl/ViewBrowser/SideBars/__init__.py trunk/fclient/fclient/impl/ViewBrowser/SideBars/_fix_mexec.py trunk/fclient/fclient/impl/ViewBrowser/TabBar.py trunk/fclient/fclient/impl/ViewBrowser/Ui_BrowserWidget.py trunk/fclient/fclient/impl/ViewBrowser/ViewBrowser.py trunk/fclient/fclient/impl/ViewBrowser/__init__.py trunk/fclient/fclient/impl/ViewBrowser/_fix_mexec.py trunk/fclient/fclient/impl/ViewBrowser/dlgs/ trunk/fclient/fclient/impl/ViewBrowser/dlgs/DlgPropsBrowserObject.py trunk/fclient/fclient/impl/ViewBrowser/dlgs/DlgPropsBrowserObjectTpl.ui trunk/fclient/fclient/impl/ViewBrowser/dlgs/Ui_DlgPropsBrowserObjectTpl.py trunk/fclient/fclient/impl/ViewBrowser/dlgs/__init__.py trunk/fclient/fclient/impl/ViewBrowser/dlgs/_fix_mexec.py trunk/fclient/fclient/impl/ViewBrowser/prefs/ trunk/fclient/fclient/impl/ViewBrowser/prefs/PrefsBrowserWidget.py trunk/fclient/fclient/impl/ViewBrowser/prefs/PrefsBrowserWidgetTpl.ui trunk/fclient/fclient/impl/ViewBrowser/prefs/Ui_PrefsBrowserWidgetTpl.py trunk/fclient/fclient/impl/ViewBrowser/prefs/__init__.py trunk/fclient/fclient/impl/ViewBrowser/prefs/_fix_mexec.py Removed Paths: ------------- trunk/fclient/fclient/impl/DlgPropsBrowserObject.py trunk/fclient/fclient/impl/PrefsBrowserWidget.py trunk/fclient/fclient/impl/tpls/DlgPropsBrowserObjectTpl.ui trunk/fclient/fclient/impl/tpls/PrefsBrowserWidgetTpl.ui trunk/fclient/fclient/impl/tpls/Ui_DlgPropsBrowserObjectTpl.py trunk/fclient/fclient/impl/tpls/Ui_PrefsBrowserWidgetTpl.py trunk/fclient/fclient/impl/tpls/Ui_ViewBrowserWidgetTpl.py trunk/fclient/fclient/impl/tpls/ViewBrowserWidgetTpl.ui Modified: trunk/fclient/fclient/fclient.py =================================================================== --- trunk/fclient/fclient/fclient.py 2008-08-16 06:51:24 UTC (rev 909) +++ trunk/fclient/fclient/fclient.py 2008-08-16 07:43:18 UTC (rev 910) @@ -14,7 +14,7 @@ from .impl.MainWindow import MainWindow from .impl.View import ViewWidget -from .impl.ViewBrowser import ViewBrowserWidget +from .impl.ViewBrowser import ViewBrowser from .impl.ViewConnection import ViewConnectionWidget from .impl.ViewDownloads import ViewDownloadsWidget from .impl.ViewLogger import ViewLoggerWidget @@ -77,7 +77,7 @@ mainWindow.setCentralWidget(viewWidget) viewWidget.addTopViews( ViewConnectionWidget(mainWindow), - ViewBrowserWidget(mainWindow), + ViewBrowser.ViewBrowserWidget(mainWindow), ViewDownloadsWidget(mainWindow), ViewUploadsWidget(mainWindow), ) Deleted: trunk/fclient/fclient/impl/DlgPropsBrowserObject.py =================================================================== --- trunk/fclient/fclient/impl/DlgPropsBrowserObject.py 2008-08-16 06:51:24 UTC (rev 909) +++ trunk/fclient/fclient/impl/DlgPropsBrowserObject.py 2008-08-16 07:43:18 UTC (rev 910) @@ -1,69 +0,0 @@ -#********************************************************************* -#TODO: -# just a sketch so far -# -# x. link and image url are not selectable -# -# -#********************************************************************** -from __future__ import absolute_import -if __name__ == '__main__': # see --> http://bugs.python.org/issue1510172 . works only current dir and below - import os; __path__ = [os.path.dirname(__file__)] - -import posixpath -from PyQt4 import QtGui - -from . import config -from .lib.compactpath.qt4 import pathlabelwrap -from .lib.qt4ex.lib import tools as qtools - -from .tpls.Ui_DlgPropsBrowserObjectTpl import Ui_DlgPropsBrowserObject -#********************************************************************************** -# -#********************************************************************************** -class DlgPropsBrowserObject(QtGui.QDialog, Ui_DlgPropsBrowserObject): - - IdLabelType = 'labelType' - IdLabelTitle = 'labelTitle' - IdLabelName = 'labelName' - IdLabelLinkUrl = 'labelLinkUrl' - IdLabelImageUrl = 'labelImageUrl' - - MaxText = 80 - - def __init__(self, parent, browser=None, hitTestResult=None): - QtGui.QDialog.__init__(self, parent) - - self.setupUi(self) - self.setWindowTitle(config.FcAppName + self.trUtf8(' - Properties')) - - if hitTestResult is not None: - - if not hitTestResult.linkUrl().isEmpty(): - labelLinkUrl = self.controlById(self.IdLabelLinkUrl) - self.wrapLinkUrl = pathlabelwrap.PathLabelWrap(labelLinkUrl, path_module=config.CompactPathFcpKeyModule) - self.wrapLinkUrl.setPath(unicode(hitTestResult.linkUrl().toString())) - if not hitTestResult.imageUrl().isEmpty(): - labelImageUrl = self.controlById(self.IdLabelImageUrl) - self.wrapImageUrl = pathlabelwrap.PathLabelWrap(labelImageUrl, path_module=config.CompactPathFcpKeyModule) - self.wrapImageUrl.setPath(unicode(hitTestResult.imageUrl().toString())) - - ellipsis = self.trUtf8('..') - self.labelTitle.setText(qtools.truncateString(self.MaxText, hitTestResult.linkTitle().toString(), ellipsis)) - self.labelTitle.setText(qtools.truncateString(self.MaxText, hitTestResult.linkText(), ellipsis)) - - def controlById(self, idControl): - return getattr(self, idControl) - -#********************************************************************************** -# -#********************************************************************************** -if __name__ == '__main__': - import sys - - app = QtGui.QApplication(sys.argv) - w = PropsBrowserObjectDlg(None) - w.show() - res = app.exec_() - sys.exit(res) - Modified: trunk/fclient/fclient/impl/Prefs.py =================================================================== --- trunk/fclient/fclient/impl/Prefs.py 2008-08-16 06:51:24 UTC (rev 909) +++ trunk/fclient/fclient/impl/Prefs.py 2008-08-16 07:43:18 UTC (rev 910) @@ -8,7 +8,7 @@ from . import config from .lib.qt4ex import dlgpreferences from .PrefsGlobal import PrefsPageGlobal -from .PrefsBrowserWidget import PrefsPageBrowser +from .ViewBrowser.prefs import PrefsBrowserWidget from .PrefsConnectionWidget import PrefsPageConnectionExpertSettings from .PrefsSingleApp import PrefsPageSingleApp #********************************************************************************** @@ -59,7 +59,7 @@ ( PrefsPageSingleApp(), ), - PrefsPageBrowser(), + PrefsBrowserWidget.PrefsPageBrowser(), ) dlgpreferences.DlgPreferencesFlatTree.__init__(self, parent, Deleted: trunk/fclient/fclient/impl/PrefsBrowserWidget.py =================================================================== --- trunk/fclient/fclient/impl/PrefsBrowserWidget.py 2008-08-16 06:51:24 UTC (rev 909) +++ trunk/fclient/fclient/impl/PrefsBrowserWidget.py 2008-08-16 07:43:18 UTC (rev 910) @@ -1,131 +0,0 @@ - -from __future__ import absolute_import -if __name__ == '__main__': # see --> http://bugs.python.org/issue1510172 . works only current dir and below - import os; __path__ = [os.path.dirname(__file__)] - - -from PyQt4 import QtCore, QtGui - -from . import config -from .lib.qt4ex import dlgpreferences -from .lib.qt4ex.lib import settings - - -from .tpls.Ui_PrefsBrowserWidgetTpl import Ui_PrefsBrowserWidget -#********************************************************************************** -# -#********************************************************************************** -class PrefsBrowserWidget(QtGui.QWidget, Ui_PrefsBrowserWidget): - - IdEdHomePage = 'edHomePage' - IdCkOpenAddressBarInNewTab = 'ckOpenAddressBarInNewTab' - IdCkOpenBookmarksInNewTab = 'ckOpenBookmarksInNewTab' - IdCkOpenLinksInNewTab = 'ckOpenLinksInNewTab' - IdCkOpenHomePageOnNewTabCreated = 'ckOpenHomePageOnNewTabCreated' - IdCkBackIsClose = 'ckBackIsClose' - IdCkAutoLoadImages = 'ckAutoLoadImages' - - def __init__(self, parent=None, page=None): - QtGui.QWidget.__init__(self, parent) - - self.setupUi(self) - - browserWidget = config.ObjectRegistry.get(config.IdViewBrowserWidget, None) - if browserWidget is None: - self.setEnabled(False) - else: - self.fcSettingsControler = settings.SettingsControler(browserWidget.fcSettings, parent=self) - if page is not None: - page.connect(self.fcSettingsControler, QtCore.SIGNAL('isDirty(bool)'), page.setDirty) - - self.fcSettingsControler.addLineEdit( - self.controlById(self.IdEdHomePage), - 'HomePage', - ) - self.fcSettingsControler.addCheckBox( - self.controlById(self.IdCkOpenAddressBarInNewTab), - 'OpenAddressBarInNewTab', - ) - self.fcSettingsControler.addCheckBox( - self.controlById(self.IdCkOpenBookmarksInNewTab), - 'OpenBookmarksInNewTab', - ) - self.fcSettingsControler.addCheckBox( - self.controlById(self.IdCkOpenLinksInNewTab), - 'OpenLinksInNewTab', - ) - self.fcSettingsControler.addCheckBox( - self.controlById(self.IdCkOpenHomePageOnNewTabCreated), - 'OpenHomePageOnNewTabCreated', - ) - self.fcSettingsControler.addCheckBox( - self.controlById(self.IdCkBackIsClose), - 'BackIsClose', - ) - self.fcSettingsControler.addCheckBox( - self.controlById(self.IdCkAutoLoadImages), - 'AutoLoadImages', - ) - - def controlById(self, idControl): - return getattr(self, idControl) - - def doApply(self): - if self.fcSettingsControler is not None: - return self.fcSettingsControler.apply() - return False - - def doRestoreDefaults(self): - if self.fcSettingsControler is not None: - return self.fcSettingsControler.restoreDefaults() - return False - -#*********************************************************************** -# -#*********************************************************************** -class PrefsPageBrowser(dlgpreferences.Page): - - UUID = '{c85e63a8-6806-435a-81ce-f4b46872246f}' - - def __init__(self): - dlgpreferences.Page.__init__(self, self.UUID) - self._widget = None - - def displayName(self): - return self.trUtf8('Browser') - - def canApply(self): return True - def canHelp(self): return False - def canRestoreDefaults(self): return True - - def setVisible(self, parent, flag): - createdNew = False - if flag and self._widget is None: - createdNew = True - self._widget = PrefsBrowserWidget(parent=parent, page=self) - self._widget.setVisible(flag) - return (createdNew, self._widget) - - - def doApply(self): - self._widget.doApply() - return True - - def doRestoreDefaults(self): - self._widget.doRestoreDefaults() - return True - - -#*********************************************************************** -# -#*********************************************************************** -if __name__ == '__main__': - from PyQt4 import QtGui - import sys - - app = QtGui.QApplication(sys.argv) - w = PrefsBrowserWidget(None) - w.show() - res = app.exec_() - sys.exit(res) - Added: trunk/fclient/fclient/impl/ViewBrowser/Actions.py =================================================================== --- trunk/fclient/fclient/impl/ViewBrowser/Actions.py (rev 0) +++ trunk/fclient/fclient/impl/ViewBrowser/Actions.py 2008-08-16 07:43:18 UTC (rev 910) @@ -0,0 +1,220 @@ +# some fixes for relative imports +# see --> [http://bugs.python.org/issue1510172] absolute/rellative import not working (works only current dir and below) +# see --> [http://mail.python.org/pipermail/python-ideas/2007-February/000232.html] PEP for executing a module in a +# ...package containing relative imports +from __future__ import absolute_import +if __name__ == '__main__': + import os + __path__ = [os.path.dirname(__file__)] + from ._fix_mexec import fix_mexec + fix_mexec(__name__, __file__) + del fix_mexec + + +from PyQt4 import QtCore, QtGui, QtWebKit + +from .. import config + +from PyQt4 import QtCore, QtGui +#********************************************************************************** +# +#********************************************************************************** +class Actions(config.ActionsBase): + + def __init__(self, parent): + config.ActionsBase.__init__(self, parent) + + iconSize = config.fcSettings.value('IconSize') + iconTheme = config.fcSettings.value('IconTheme') + + #TODO: shortcut + self.action( + name='ActionCloseCurrentTab', + text=self.trUtf8('Close ¤t tab'), + trigger=parent.onCloseCurrentTab, + ) + #TODO: shortcut + self.action( # context menu only + name='ActionCloseBrowserUnderMouse', + text=self.trUtf8('&Close tab'), + trigger=None, + ) + self.action( + name='ActionCloseAllTabs', + text=self.trUtf8('Close &all tabs'), + trigger=parent.onCloseAllTabs, + ) + #TODO: shortcut + self.action( + name='ActionCreateNewTab', + text=self.trUtf8('Create &new tab'), + trigger=parent.onCreateNewTab, + ) + #TODO: shortcut + self.action( + name='ActionDuplicateTab', + text=self.trUtf8('&Duplicate tab'), + trigger=parent.onDuplicateTab, + ) + + #TODO: shortcut + self.action( + name='ActionGoToFProxy', + text=self.trUtf8('Go to f&Proxy homepage'), + trigger=parent.onGoToFProxy, + ) + self.action( + name='ActionGoToHomePage', + text=self.trUtf8('Go to &homepage'), + shortcut=QtGui.QKeySequence(self.trUtf8('Alt+Home')), + trigger=parent.onGoToHomePage, + ) + #TODO: shortcut + self.action( + name='ActionObjectProperties', + text=self.trUtf8('Properties..'), + trigger=None, + ) + self.action( + name='ActionZoomIn', + text=self.trUtf8('Zoom in'), + shortcut=QtGui.QKeySequence(QtGui.QKeySequence.ZoomIn), + trigger=parent.onZoomIn, + ) + self.action( + name='ActionZoomOut', + text=self.trUtf8('Zoom out'), + shortcut=QtGui.QKeySequence(QtGui.QKeySequence.ZoomOut), + trigger=parent.onZoomOut, + ) + + # default browser actions + self.action( + name='ActionBack', + text=self.trUtf8('Back'), + trigger=None, + isEnabled=False, + shortcut=QtGui.QKeySequence(QtGui.QKeySequence.Back), + icon=config.fcResources.getIcon('back', iconSize, iconTheme=iconTheme), + userData=(None, None), + ) + self.action( + name='ActionForward', + text=self.trUtf8('Forward'), + trigger=None, + isEnabled=False, + shortcut=QtGui.QKeySequence(QtGui.QKeySequence.Forward), + icon=config.fcResources.getIcon('forward', iconSize, iconTheme=iconTheme), + userData=(None, None), + ) + self.action( + name='ActionReload', + text=self.trUtf8('Reload'), + #EXPERIMENTAL: we handle it, cos page.url() is empty if fproxy did not respond. + # for some reason QWebView has "Reload" enabled in this case. we keep track of + # the last known url and reload it manually. hope we don't get into trouble with + # this. NOTE: we may have to do this for other actions aswell + trigger=parent.onBrowserReloadTriggered, + isEnabled=False, + #TODO: how to assign QKeySequence.Refresh and* F5 ? + shortcut=QtGui.QKeySequence(QtGui.QKeySequence.Refresh), + icon=config.fcResources.getIcon('reload_page', iconSize, iconTheme=iconTheme), + userData=(None, None), + ) + self.action( + name='ActionStop', + text=self.trUtf8('Stop'), + trigger=None, + isEnabled=False, + shortcut=QtGui.QKeySequence(self.trUtf8('Esc')), + icon=config.fcResources.getIcon('stop', iconSize, iconTheme=iconTheme), + userData=(None, None), + ) + self.action( + name='ActionBackIsClose', + text=self.trUtf8('Back is close'), + icon=config.fcResources.getIcon('button_cancel', iconSize, iconTheme=iconTheme), + trigger=None, + ) + + # find actions + self.action( + name='ActionFind', + text=self.trUtf8('Find'), + shortcut=QtGui.QKeySequence(QtGui.QKeySequence.Find), + trigger=parent.onFind, + ) + self.action( + name='ActionFindNext', + text=self.trUtf8('Find next'), + isEnabled=False, + shortcut=QtGui.QKeySequence(QtGui.QKeySequence.FindNext), + trigger=parent.onFindNext, + ) + self.action( + name='ActionFindPrevious', + text=self.trUtf8('Find previous'), + isEnabled=False, + shortcut=QtGui.QKeySequence(QtGui.QKeySequence.FindPrevious), + trigger=parent.onFindPrevious, + ) + self.action( + name='ActionSavePage', + text=self.trUtf8('Save page..'), + isEnabled=True, + ##shortcut=QtGui.QKeySequence(QtGui.QKeySequence.FindPrevious), + trigger=parent.onSavePage, + ) + + # sideBars + group = self.group( + name='GroupSideBars', + isExclusive=True, + trigger=parent.onShowSidebar, + ) + self.action( + name='ActionShowSideBarLoadDetails', + group=group, + text=self.trUtf8('Load details'), + isEnabled=True, + isCheckable=True, + ) + + self.action( + name='ActionCloseCurrentSideBar', + text=self.trUtf8('Close sidebar'), + isEnabled=True, + trigger=parent.onCloseCurrentSideBar, + ) + + + def intertwineBrowserActions(self, browser=None): + """intertwines Browser actions with BrowserWidget actions + @note: call everytime the current browser changes + """ + actions = ( + ('ActionBack', QtWebKit.QWebPage.Back), + ('ActionForward', QtWebKit.QWebPage.Forward), + ('ActionReload', QtWebKit.QWebPage.Reload), + ('ActionStop', QtWebKit.QWebPage.Stop), + ) + for actionName, pageAction in actions: + myPageAction = self[actionName] + newPageAction = None if browser is None else browser.pageAction(pageAction) + oldPageAction, cb = myPageAction.userData() + + if oldPageAction is not None: + myPageAction.disconnect(oldPageAction, QtCore.SIGNAL('changed()'), cb) + oldPageAction.disconnect(myPageAction, QtCore.SIGNAL('triggered()'), oldPageAction.trigger) + + if newPageAction is None: + myPageAction.setUserData((None, None)) + myPageAction.setEnabled(False) + else: + def onActionChanged(browser=browser, myPageAction=myPageAction, browserPageAction=newPageAction): + myPageAction.setEnabled(browserPageAction.isEnabled()) + + myPageAction.setEnabled(newPageAction.isEnabled()) + myPageAction.setUserData((newPageAction, onActionChanged)) + myPageAction.connect(newPageAction, QtCore.SIGNAL('changed()'), onActionChanged) + newPageAction.connect(myPageAction, QtCore.SIGNAL('triggered()'), newPageAction.trigger) Added: trunk/fclient/fclient/impl/ViewBrowser/Browser.py =================================================================== --- trunk/fclient/fclient/impl/ViewBrowser/Browser.py (rev 0) +++ trunk/fclient/fclient/impl/ViewBrowser/Browser.py 2008-08-16 07:43:18 UTC (rev 910) @@ -0,0 +1,216 @@ +# some fixes for relative imports +# see --> [http://bugs.python.org/issue1510172] absolute/rellative import not working (works only current dir and below) +# see --> [http://mail.python.org/pipermail/python-ideas/2007-February/000232.html] PEP for executing a module in a +# ...package containing relative imports +from __future__ import absolute_import +if __name__ == '__main__': + import os + __path__ = [os.path.dirname(__file__)] + from ._fix_mexec import fix_mexec + fix_mexec(__name__, __file__) + del fix_mexec + +from . import Page + +from PyQt4 import QtCore, QtGui, QtWebKit, QtNetwork + +#***************************************************************************************** +# +#***************************************************************************************** +class NetworkReplyData(QtCore.QObject): + def __init__(self, parent, url): + QtCore.QObject.__init__(self, parent) + self.url = url + self.bytesReceived = 0 + self.bytesTotal = 0 + self.finished = False + self.errorCode = None + +#***************************************************************************************** +# +#***************************************************************************************** +#TODO: impl functionality in browser +class LastBrowserState(object): + """records the last known state browser""" + + StateNone = 0x0 + StateLoading = 0x1 + StateComplete = 0x2 + StateError = 0x4 + StateHideProgressBar = 0x100 + + + __slots__ = ('clearProgressBarTimers', 'icon', 'progress', 'state', 'statusMessage', 'title', 'url') + + def __init__(self, icon=None, progress=0, statusMessage=None, state=StateNone, title=None, url=None): + self.clearProgressBarTimers = [] # timers scheduled for hiding progressBar + self.progress = 0 + self.icon = tCore.QIcon() if icon is None else icon + self.state = state + self.statusMessage = QtCore.QString() if statusMessage is None else statusMessage + self.title = QtCore.QString() if title is None else title + #NOTE: opening a browser in a new tab may take a while to load. + # self.url() will return '' untill the page is found, so we handle + # it ourself and keep track of the last known url in self._lastUrl + # to give feedback to the user on the navbar. downside is we have + # to reimplement contextMenuEvent() :-( + self.url = QtCore.QUrl() if url is None else url + +#***************************************************************************************** +# +#***************************************************************************************** +class Browser(QtWebKit.QWebView): + """ browser customized for freenet + """ + + MaxProgress = 100 + + def __init__(self, parent=None, userData=None): + QtWebKit.QWebView.__init__(self, parent) + + page = Page.Page(self) + self.setPage(page) + + #NOTE: we store last progress made to set busy cursor accordingly + self._lastProgress = 0 + self._userData = userData + self._networkGetReplies = [[], []] # (QNetworkReplies, urls) + self._networkReplySignals = ( + ('downloadProgress(qint64, qint64)', self.onNetworkReplyDownloadProgress), + ('error(QNetworkReply::NetworkError)', self.onNetworkReplyError), + ('finished()', self.onNetworkReplyFinished), + ) + + # connect actions + self.connect(self, QtCore.SIGNAL('loadStarted()'), self.onLoadStarted) + self.connect(self, QtCore.SIGNAL('loadProgress(int)'), self.onLoadProgress) + self.connect(self, QtCore.SIGNAL('loadFinished(bool)'), self.onLoadFinished) + self.connect(self.pageAction(QtWebKit.QWebPage.Stop), QtCore.SIGNAL('triggered()'), self.onActionStopTriggered) + + ################################ + ## methods + ################################ + #TODO: impl in BrowserWidget + def lastProgress(self): + """returns the last progress made by the browser + @return: (int) last progress + """ + return self._lastProgress + + def networkGetReplies(self): + return self._networkGetReplies[1] + + def networkGetReply(self, indexReply): + return self._networkGetReplies[1][indexReply] + + def setUserData(self, userData): + self._userData = userData + + def userData(self): + return self._userData + + ################################ + ## overwritten methods + ################################ + #def createWindow(self, typeWindow): + # pass + + def load(self, url): + self._lastProgress = 0 + return QtWebKit.QWebView.load(self, url) + + def setUrl(self, url): + return self.load(url) + + def setContents(self, *args): + """sets the contents of the browser without changing its url""" + self._lastProgress = 0 + return QtWebKit.QWebView.setContents(self, *args) + + def setHtml(self, *args): + """sets the contents of the browser without changing its url""" + self._lastProgress = 0 + return QtWebKit.QWebView.setHtm(self, *args) + + def setPage(self, page): + """""" + self._lastProgress = 0 + self.connect( + page.networkAccessManager(), + QtCore.SIGNAL('networkRequestCreated(QNetworkReply*)'), + self.onNetworkRequestCreated + ) + + self.emit(QtCore.SIGNAL('pageSet(QWebPage*)'), page) + return QtWebKit.QWebView.setPage(self, page) + + def mouseMoveEvent(self, event): + QtWebKit.QWebView.mouseMoveEvent(self, event) + if self._lastProgress < self.MaxProgress: + self.setCursor(QtCore.Qt.BusyCursor) + + ############################### + ## event handlers + ############################### + def onActionStopTriggered(self): + # check wich cursor to set cos we may have busy cursor set + pt = self.mapFromGlobal(self.cursor().pos()) #TODO: self.mapFromGlobal(self.viewPort().cursor().pos()) ?? + frame = self.page().currentFrame() + hitTest = frame.hitTestContent(pt) + #if not hitTest.isNull(): #TODO: looks like hitTest.isNull() alwas returns True + if hitTest.linkUrl().isValid(): + self.setCursor(QtCore.Qt.PointingHandCursor) + else: + self.setCursor(QtCore.Qt.ArrowCursor) + + def onLoadStarted(self): + self._lastProgress = 0 + self._networkGetReplies = [[], []] + + def onLoadProgress(self, n): + self._lastProgress = n + + def onLoadFinished(self, ok): + if ok: + self._lastProgress = self.MaxProgress + self.onActionStopTriggered() + + def onPageDownloadRequested(self, networkRequest): + self.emit(QtCore.SIGNAL('downloadRequested(const QNetworkRequest &)'), networkRequest) + + def onNetworkRequestCreated(self, reply): + if reply.operation() == QtNetwork.QNetworkAccessManager.GetOperation: + self._networkGetReplies[0].append(reply) + url = QtCore.QUrl(reply.url()) # copy url, qt nules it on return + networkReplyData = NetworkReplyData(self, url) + self._networkGetReplies[1].append(networkReplyData) + for signal, handler in self._networkReplySignals: + self.connect(reply, QtCore.SIGNAL(signal), handler) + self.emit(QtCore.SIGNAL('networkGetRequestCreated(int, QObject*)'), self._networkGetReplies[0].index(reply), networkReplyData) + + def onNetworkReplyDownloadProgress(self, bytesReceived, bytesTotal): + reply = self.sender() + i = self._networkGetReplies[0].index(reply) + networkReplyData = self._networkGetReplies[1][i] + networkReplyData.bytesReceived = bytesReceived + networkReplyData.bytesTotal = bytesTotal + self.emit(QtCore.SIGNAL('networkReplyProgress(int, QObject*)'), i, networkReplyData) + + def onNetworkReplyError(self, errorCode): + reply = self.sender() + i = self._networkGetReplies[0].index(reply) + networkReplyData = self._networkGetReplies[1][i] + networkReplyData.finished = True + networkReplyData.errorCode = errorCode + self.emit(QtCore.SIGNAL('networkReplyError(int, QObject*)'), i, networkReplyData) + #for signal, handler in self._networkReplySignals: + # self.disconnect(reply, QtCore.SIGNAL(signal), handler) + + def onNetworkReplyFinished(self): + reply = self.sender() + i = self._networkGetReplies[0].index(reply) + networkReplyData = self._networkGetReplies[1][i] + networkReplyData.finished = True + for signal, handler in self._networkReplySignals: + self.disconnect(reply, QtCore.SIGNAL(signal), handler) + self.emit(QtCore.SIGNAL('networkReplyFinished(int, QObject*)'), i, networkReplyData) \ No newline at end of file Added: trunk/fclient/fclient/impl/ViewBrowser/BrowserWidget.ui =================================================================== --- trunk/fclient/fclient/impl/ViewBrowser/BrowserWidget.ui (rev 0) +++ trunk/fclient/fclient/impl/ViewBrowser/BrowserWidget.ui 2008-08-16 07:43:18 UTC (rev 910) @@ -0,0 +1,267 @@ +<ui version="4.0" > + <class>ViewBrowserWidget</class> + <widget class="QWidget" name="ViewBrowserWidget" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>710</width> + <height>794</height> + </rect> + </property> + <property name="windowTitle" > + <string>Form</string> + </property> + <layout class="QGridLayout" name="gridLayout_4" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>0</number> + </property> + <item row="0" column="0" > + <layout class="QHBoxLayout" name="horizontalLayout" > + <property name="spacing" > + <number>0</number> + </property> + <item> + <layout class="QHBoxLayout" > + <item> + <widget class="QFrame" name="frameTools" > + <property name="frameShape" > + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow" > + <enum>QFrame::Raised</enum> + </property> + <layout class="QGridLayout" name="gridLayout_2" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>0</number> + </property> + <item row="0" column="0" > + <widget class="QToolButton" name="btBack" > + <property name="text" > + <string>Back</string> + </property> + </widget> + </item> + <item row="0" column="1" > + <widget class="QToolButton" name="btForward" > + <property name="text" > + <string>Forward</string> + </property> + </widget> + </item> + <item row="0" column="3" > + <widget class="QToolButton" name="btReload" > + <property name="text" > + <string>Reload</string> + </property> + </widget> + </item> + <item row="0" column="4" > + <widget class="QToolButton" name="btStop" > + <property name="text" > + <string>Stop</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QFrame" name="frameAddressBar" > + <property name="minimumSize" > + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="frameShape" > + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow" > + <enum>QFrame::Plain</enum> + </property> + <property name="lineWidth" > + <number>0</number> + </property> + <layout class="QGridLayout" name="gridLayout" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>0</number> + </property> + <item row="0" column="0" > + <widget class="QLineEdit" name="edAddressBar" > + <property name="dragEnabled" > + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </item> + <item row="1" column="0" > + <widget class="QSplitter" name="splitter" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Expanding" hsizetype="Expanding" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <widget class="QTabWidget" name="tabSideBar" > + <widget class="QWidget" name="tab_2" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>137</width> + <height>736</height> + </rect> + </property> + <attribute name="title" > + <string>Tab 1</string> + </attribute> + </widget> + <widget class="QWidget" name="tab_3" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>150</width> + <height>712</height> + </rect> + </property> + <attribute name="title" > + <string>Tab 2</string> + </attribute> + </widget> + </widget> + <widget class="QWidget" name="layoutWidget" > + <layout class="QVBoxLayout" name="verticalLayout" > + <property name="spacing" > + <number>0</number> + </property> + <property name="margin" > + <number>0</number> + </property> + <item> + <widget class="QTabWidget" name="tabBrowsers" > + <property name="currentIndex" > + <number>0</number> + </property> + <widget class="QWidget" name="tab" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>557</width> + <height>700</height> + </rect> + </property> + <attribute name="title" > + <string>Tab 1</string> + </attribute> + </widget> + </widget> + </item> + <item> + <widget class="QFrame" name="frameFind" > + <property name="frameShape" > + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow" > + <enum>QFrame::Raised</enum> + </property> + <layout class="QGridLayout" name="gridLayout_3" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>0</number> + </property> + <item row="0" column="0" > + <layout class="QHBoxLayout" name="horizontalLayout_2" > + <property name="spacing" > + <number>6</number> + </property> + <item> + <widget class="QLabel" name="label" > + <property name="text" > + <string>Find:</string> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="edFind" > + <property name="dragEnabled" > + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="btFindNext" > + <property name="text" > + <string>Next</string> + </property> + <property name="flat" > + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="btFindPrevious" > + <property name="text" > + <string>Previous</string> + </property> + <property name="flat" > + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="ckFindCaseSensitive" > + <property name="text" > + <string>Case sensitive</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>48</width> + <height>25</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> Added: trunk/fclient/fclient/impl/ViewBrowser/GlobalFeedback.py =================================================================== --- trunk/fclient/fclient/impl/ViewBrowser/GlobalFeedback.py (rev 0) +++ trunk/fclient/fclient/impl/ViewBrowser/GlobalFeedback.py 2008-08-16 07:43:18 UTC (rev 910) @@ -0,0 +1,58 @@ +# some fixes for relative imports +# see --> [http://bugs.python.org/issue1510172] absolute/rellative import not working (works only current dir and below) +# see --> [http://mail.python.org/pipermail/python-ideas/2007-February/000232.html] PEP for executing a module in a +# ...package containing relative imports +from __future__ import absolute_import +if __name__ == '__main__': + import os + __path__ = [os.path.dirname(__file__)] + from ._fix_mexec import fix_mexec + fix_mexec(__name__, __file__) + del fix_mexec + +from .. import config +from ..lib.compactpath.qt4 import pathlabelwrap + + + +from PyQt4 import QtCore, QtGui +#********************************************************************************** +# +#********************************************************************************** +class GlobalFeedback(config.GlobalFeedbackBase): + """wrapper for global statusbar widgets, menus""" + + def __init__(self, parent, idGlobalFeedback): + config.GlobalFeedbackBase.__init__(self, parent, idGlobalFeedback) + + # menus + self.menus = [] + if self.menuBar is not None and hasattr(parent, 'fcViewObject'): + menu = QtGui.QMenu(parent.fcViewObject.displayName, self.menuBar) + parent.populateMenu(menu) + self.menus.append(menu) + self.menuBar.addViewMenu(menu) + + # status bar widgets + self.labelStatus = None + self.progress = None + self.labelFeedbackWrap = None + if self.statusBar is not None: + label = QtGui.QLabel(self.statusBar) + label.setFrameStyle(QtGui.QLabel.Sunken | QtGui.QLabel.Box) + self.labelFeedbackWrap = pathlabelwrap.PathLabelWrap( + label, + path_module=config.CompactPathFcpKeyModule, + ) + self.statusBar.addWidget(self.labelFeedbackWrap.label, 10) + + def setVisible(self, flag): + if self.menuBar is not None: + for menu in self.menus: + menu.children()[0].setEnabled(flag) + if self.statusBar is not None: + self.labelFeedbackWrap.label.setVisible(flag) + + def setFeedback(self, qString): + if self.labelFeedbackWrap is not None: + self.labelFeedbackWrap.setPath(unicode(qString)) \ No newline at end of file Added: trunk/fclient/fclient/impl/ViewBrowser/NetworkAccessManager.py =================================================================== --- trunk/fclient/fclient/impl/ViewBrowser/NetworkAccessManager.py (rev 0) +++ trunk/fclient/fclient/impl/ViewBrowser/NetworkAccessManager.py 2008-08-16 07:43:18 UTC (rev 910) @@ -0,0 +1,19 @@ + +from PyQt4 import QtCore, QtNetwork +#***************************************************************************************** +# +#***************************************************************************************** +class NetworkAccessManager(QtNetwork.QNetworkAccessManager): + + def __init__(self, parent): + QtNetwork.QNetworkAccessManager.__init__(self, parent) + + def createRequest(self, operation, request, outgoingData): + reply = QtNetwork.QNetworkAccessManager.createRequest(self, operation, request, outgoingData) + self.emit(QtCore.SIGNAL('networkRequestCreated(QNetworkReply*)'), reply) + #print 'createRequest', reply.url() + #self.connect(reply, QtCore.SIGNAL('downloadProgress(qint64, qint64)'), self.foo) + return reply + + def foo(self, *args): + print args Added: trunk/fclient/fclient/impl/ViewBrowser/Page.py =================================================================== --- trunk/fclient/fclient/impl/ViewBrowser/Page.py (rev 0) +++ trunk/fclient/fclient/impl/ViewBrowser/Page.py 2008-08-16 07:43:18 UTC (rev 910) @@ -0,0 +1,25 @@ +# some fixes for relative imports +# see --> [http://bugs.python.org/issue1510172] absolute/rellative import not working (works only current dir and below) +# see --> [http://mail.python.org/pipermail/python-ideas/2007-February/000232.html] PEP for executing a module in a +# ...package containing relative imports +from __future__ import absolute_import +if __name__ == '__main__': + import os + __path__ = [os.path.dirname(__file__)] + from ._fix_mexec import fix_mexec + fix_mexec(__name__, __file__) + del fix_mexec + +from PyQt4 import QtCore, QtGui, QtWebKit + +from . import NetworkAccessManager +#***************************************************************************************** +# +#***************************************************************************************** +class Page(QtWebKit.QWebPage): + def __init__(self, parent): + QtWebKit.QWebPage.__init__(self, parent) + + self.setNetworkAccessManager(NetworkAccessManager.NetworkAccessManager(self)) + #def acceptNavigationRequest(self, frame, request, typeRequest): + # return True Added: trunk/fclient/fclient/impl/ViewBrowser/Settings.py =================================================================== --- trunk/fclient/fclient/impl/ViewBrowser/Settings.py (rev 0) +++ trunk/fclient/fclient/impl/ViewBrowser/Settings.py 2008-08-16 07:43:18 UTC (rev 910) @@ -0,0 +1,63 @@ +# some fixes for relative imports +# see --> [http://bugs.python.org/issue1510172] absolute/rellative import not working (works only current dir and below) +# see --> [http://mail.python.org/pipermail/python-ideas/2007-February/000232.html] PEP for executing a module in a +# ...package containing relative imports +from __future__ import absolute_import +if __name__ == '__main__': + import os + __path__ = [os.path.dirname(__file__)] + from ._fix_mexec import fix_mexec + fix_mexec(__name__, __file__) + del fix_mexec + +from .. import config + +from PyQt4 import QtCore, QtGui +#********************************************************************************** +# +#********************************************************************************** +class Settings(config.SettingsBase): + _key_ = config.IdViewBrowserWidget + _settings_ = ( + ('OpenLinksInNewTab', 'Bool', False), + ('OpenAddressBarInNewTab', 'Bool', False), + ('OpenBookmarksInNewTab', 'Bool', False), + ('OpenHomePageOnNewTabCreated', 'Bool', False), + ('BackIsClose', 'Bool', False), #TODO: not implemented + ('HomePage', 'String', QtCore.QString()), + ('AutoLoadImages', 'Bool', True), #TODO: not yet implemented + ('MaxTabText', 'UInt', 15), #NOTE: make shure Max >= Min and Max and Min > 0 + ('MinTabText', 'UInt', 15), + + ('TabProgressBarColor', 'QColor', QtGui.QColor('blue')), + ('TabProgressBarAlpha', 'UInt', 55), + + ('SplitterPos', 'ByteArray', QtCore.QByteArray()), + ('LastSideBarAction', 'String', QtCore.QString('')), + + ) + + def setValues(self, **kws): + config.SettingsBase.setValues(self, **kws) + if not self.parent().isCreated: + return + + autoLoadImages = kws.get('AutoLoadImages', None) + if autoLoadImages is not None: + browserWidget = self.parent() + tabWidget = browserWidget.controlById(browserWidget.IdTabBrowsers) + for i in xrange(tabWidget.count()): + browser = tabWidget.widget(i) + if hasattr(browser, 'settings'): # QTabWidget may return a Null QWidget + settings = browser.settings() + settings.setAttribute(settings.AutoLoadImages, autoLoadImages) + + if kws.get('TabProgressBarColor', None) is not None or kws.get('TabProgressBarAlpha', None) is not None: + tabWidget = browserWidget.controlById(browserWidget.IdTabBrowsers) + tabWidget.tabBar().repaint() + + + #backIsClose = kws.get('BackIsClose', None) + #if backIsClose is not None: + # self.parent()._adjustBackIsClose() + \ No newline at end of file Added: trunk/fclient/fclient/impl/ViewBrowser/SideBar.py =================================================================== --- trunk/fclient/fclient/impl/ViewBrowser/SideBar.py (rev 0) +++ trunk/fclient/fclient/impl/ViewBrowser/SideBar.py 2008-08-16 07:43:18 UTC (rev 910) @@ -0,0 +1 @@ + Added: trunk/fclient/fclient/impl/ViewBrowser/SideBars/SideBarLoadDetails.py =================================================================== --- trunk/fclient/fclient/impl/ViewBrowser/SideBars/SideBarLoadDetails.py (rev 0) +++ trunk/fclient/fclient/impl/ViewBrowser/SideBars/SideBarLoadDetails.py 2008-08-16 07:43:18 UTC (rev 910) @@ -0,0 +1,278 @@ +"""sideBar for the browser to show detailed information on page load""" +#******************************************************************************** +#TODO: +# +# x. how to adjust item colors via stylesheet? +# x. limit number of requests we keep track off (performance)? +# x. context menu actions for items like ...load in browser ..download key (...) +# x. save column widths +# +#******************************************************************************** +# some fixes for relative imports +# see --> [http://bugs.python.org/issue1510172] absolute/rellative import not working (works only current dir and below) +# see --> [http://mail.python.org/pipermail/python-ideas/2007-February/000232.html] PEP for executing a module in a +# ...package containing relative imports +from __future__ import absolute_import +if __name__ == '__main__': + import os + __path__ = [os.path.dirname(__file__)] + from ._fix_mexec import fix_mexec + fix_mexec(__name__, __file__) + del fix_mexec + +import posixpath +from PyQt4 import QtCore, QtGui + +from ... import config +from .Ui_SideBarLoadDetailsTpl import Ui_SideBarLoadDetails +#********************************************************************************** +# +#********************************************************************************** +class SideBarLoadDetailsSettings(config.SettingsBase): + _key_ = config.IdSideBarLoadDetails + _settings_ = ( + ('ColorFgItem', 'QColor', QtGui.QColor('black')), + ('ColorBgItem', 'QColor', QtGui.QColor('white')), + ('ColorFgItemError', 'QColor', QtGui.QColor('red')), + ('ColorBgItemError', 'QColor', QtGui.QColor('white')), + ('ColorFgItemComplete', 'QColor', QtGui.QColor('green')), + ('ColorBgItemComplete', 'QColor', QtGui.QColor('white')), + ) + + +class TreeItem(QtGui.QTreeWidgetItem): + + StatusNone = 0 + StatusLoading = 1 + StatusComplete = 2 + StatusError = 3 + def __init__(self, *args): + QtGui.QTreeWidgetItem.__init__(self, *args) + self.status = self.StatusNone + self.url = None + + + +class SideBarLoadDetails(QtGui.QWidget, Ui_SideBarLoadDetails): + + IdTree = 'tree' + IdBtClose = 'btClose' + + IndexProgress = 0 + IndexStatus = 1 + IndexName = 2 + + + def __init__(self, parent=None, closeAction=None): + QtGui.QWidget.__init__(self, parent) + self.statusNames = {} # TreeItem.Status* --> displayName + + self.setupUi(self) + + config.ObjectRegistry.register(self) + self.fcSettings = SideBarLoadDetailsSettings(self).restore() + self.baseKey = None # base key of the page + + # setup tree + tree = self.controlById(self.IdTree) + tree.setUniformRowHeights(True) + tree.setRootIsDecorated(False) + + # setup close button + if closeAction is not None: + bt = self.controlById(self.IdBtClose) + bt.setDefaultAction(closeAction) + + ############################## + ## private methods + ############################## + def _splitBaseKey(self, url): + baseKey = '' + fileName = tmp_fileName = unicode(url.path()) + if tmp_fileName: + tmp_fileName = tmp_fileName.lstrip('/') + if tmp_fileName: + # prep fileName to extract freenetKey + T = tmp_fileName.split('/', 1) + if len(T) == 2: + tmp_baseKey, tmp_fileName = T + else: + tmp_baseKey, tmp_fileName = T[0], '' + # check if baseKey is a freenet key + if config.qStringToFcpKey(tmp_baseKey) is not None: + baseKey = tmp_baseKey + fileName = tmp_fileName + else: + fileName = fileName.lstrip('/') + return baseKey, fileName + + ############################## + ## methods + ############################## + def addNetworkReply(self, indexReply, networkReplyData): + #TODO: better extraction of filename part + tree = self.controlById(self.IdTree) + n = tree.topLevelItemCount() + if indexReply < n: + return + + if indexReply == 0: + self.baseKey, fileName = self._splitBaseKey(networkReplyData.url) + else: + #problem: index page may point somewhere deep into a container + # ..so we can not assume all following requests of are lokated deeper + # ..in the age hirarchy. anyways. links to external resources are + # ..always displayed as absolute urls + baseKey, fileName = self._splitBaseKey(networkReplyData.url) + if baseKey != self.baseKey: + fileName = unicode(networkReplyData.url.toString()) + if not fileName: + fileName = '/' + + item = TreeItem(tree) + item.url = networkReplyData.url + # set progress + if networkReplyData.bytesTotal < 1: + progress = '0%' + else: + progress = str(int((float(networkReplyData.bytesReceived) / networkReplyData.bytesTotal * 100))) + '%' + item.setData( + self.IndexProgress, + QtCore.Qt.DisplayRole, + QtCore.QVariant(progress), + ) + # set status + if networkReplyData.bytesReceived: + item.status = TreeItem.StatusLoading + if networkReplyData.errorCode is not None: + item.status = TreeItem.StatusError + if networkReplyData.finished: + item.status = TreeItem.StatusComplete + item.setData( + self.IndexStatus, + QtCore.Qt.DisplayRole, + QtCore.QVariant(self.statusNames[item.status]), + ) + # set fileName + item.setData( + self.IndexName, + QtCore.Qt.DisplayRole, + QtCore.QVariant(fileName), + ) + # set vcolors + item.setForeground(self.IndexStatus, self.fcSettings.value('ColorFgItem')) + item.setBackground(self.IndexStatus, self.fcSettings.value('ColorBgItem')) + + + def controlById(self, idControl): + return getattr(self, idControl) + + def setCurrent(self, browserWidget, flag): + if flag: + self.setBrowser(browserWidget.currentBrowser()) + else: + tree = self.controlById(self.IdTree) + tree.clear() + self.baseUrl = None + + def setBrowser(self, browser): + tree = self.controlById(self.IdTree) + tree.clear() + self.baseUrl = None + # setup browser + if browser is not None: + self.connect(browser, QtCore.SIGNAL('networkGetRequestCreated(int, QObject*)'), self.addNetworkReply) + self.connect(browser, QtCore.SIGNAL('networkReplyProgress(int, QObject*)'), self.onBrowserNetworkReplyProgress) + self.connect(browser, QtCore.SIGNAL('networkReplyError(int, QObject*)'), self.onBrowserNetworkReplyError) + self.connect(browser, QtCore.SIGNAL('networkReplyFinished(int, QObject*)'), self.onBrowserNetworkReplyFinished) + self.connect(browser, QtCore.SIGNAL('loadStarted()'), self.onBrowserLoadStarted) + for indexReply, networkReplyData in enumerate(browser.networkGetReplies()): + self.addNetworkReply(indexReply, networkReplyData) + + ########################### + ## overwritten methods + ########################### + def retranslateUi(self, this): + Ui_SideBarLoadDetails.retranslateUi(self, this) + tree = self.controlById(self.IdTree) + headerLabels = [ + (self.IndexProgress, self.trUtf8('Progress')), + (self.IndexStatus, self.trUtf8('Status')), + (self.IndexName, self.trUtf8('Name')), + ] + headerLabels.sort() + tree.setHeaderLabels([i[1] for i in headerLabels]) + self.statusNames = { + TreeItem.StatusNone: self.trUtf8('waiting'), + TreeItem.StatusLoading: self.trUtf8('loading'), + TreeItem.StatusComplete: self.trUtf8('complete'), + TreeItem.StatusError: self.trUtf8('error'), + } + root = tree.invisibleRootItem() + for i in xrange(root.childCount()): + item = root.child(i) + item.setData( + self.IndexStatus, + QtCore.Qt.DisplayRole, + QtCore.QVariant(self.statusNames[item.status]), + ) + ############################## + ## event handlers + ############################## + def onBrowserLoadStarted(self): + tree = self.controlById(self.IdTree) + tree.clear() + + def onBrowserNetworkReplyProgress(self, indexReply, networkReplyData): + tree = self.controlById(self.IdTree) + item = tree.invisibleRootItem().child(indexReply) + if item is None: + return + if item.status != TreeItem.StatusError: + item.status = item.StatusLoading + if networkReplyData.bytesTotal < 1: + progress = '0%' + else: + progress = str(int((float(networkReplyData.bytesReceived) / networkReplyData.bytesTotal * 100))) + '%' + + item.setData( + self.IndexProgress, + QtCore.Qt.DisplayRole, + QtCore.QVariant(progress), + ) + item.setData( + self.IndexStatus, + QtCore.Qt.DisplayRole, + QtCore.QVariant(self.statusNames[item.status]), + ) + + def onBrowserNetworkReplyError(self, indexReply, networkReplyData): + tree = self.controlById(self.IdTree) + item = tree.invisibleRootItem().child(indexReply) + if item is None: + return + item.setForeground(self.IndexStatus, self.fcSettings.value('ColorFgItemError')) + item.setBackground(self.IndexStatus, self.fcSettings.value('ColorBgItemError')) + item.status = item.StatusError + item.setData( + self.IndexStatus, + QtCore.Qt.DisplayRole, + QtCore.QVariant(self.statusNames[item.status]), + ) + + def onBrowserNetworkReplyFinished(self, indexReply, networkReplyData): + tree = self.controlById(self.IdTree) + item = tree.invisibleRootItem().child(indexReply) + if item is None: + return + if item.status != TreeItem.StatusError: + item.status = item.StatusComplete + item.setData( + self.IndexStatus, + QtCore.Qt.DisplayRole, + QtCore.QVariant(self.statusNames[item.status]), + ) + item.setForeground(self.IndexStatus, self.fcSettings.value('ColorFgItemComplete')) + item.setBackground(self.IndexStatus, self.fcSettings.value('ColorBgItemComplete')) + + Added: trunk/fclient/fclient/impl/ViewBrowser/SideBars/SideBarLoadDetailsTpl.ui =================================================================== --- trunk/fclient/fclient/impl/ViewBrowser/SideBars/SideBarLoadDetailsTpl.ui (rev 0) +++ trunk/fclient/fclient/impl/ViewBrowser/SideBars/SideBarLoadDetailsTpl.ui 2008-08-16 07:43:18 UTC (rev 910) @@ -0,0 +1,47 @@ +<ui version="4.0" > + <class>SideBarLoadDetails</class> + <widget class="QWidget" name="SideBarLoadDetails" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>497</width> + <height>488</height> + </rect> + </property> + <property name="windowTitle" > + <string>Form</string> + </property> + <layout class="QGridLayout" name="gridLayout" > + <item row="0" column="0" > + <layout class="QHBoxLayout" name="horizontalLayout" > + <item> + <widget class="QLabel" name="header" > + <property name="text" > + <string>Load details</string> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="btClose" > + <property name="text" > + <string>...</string> + </property> + </widget> + </item> + </layout> + </item> + <item row="1" column="0" > + <widget class="QTreeWidget" name="tree" > + <column> + <property name="text" > + <string>1</string> + </property> + </column> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> Added: trunk/fclient/fclient/impl/ViewBrowser/SideBars/Ui_SideBarLoadDetailsTpl.py =================================================================== --- trunk/fclient/fclient/impl/ViewBrowser/SideBars/Ui_SideBarLoadDetailsTpl.py (rev 0) +++ trunk/fclient/fclient/impl/ViewBrowser/SideBars/Ui_SideBarLoadDetailsTpl.py 2008-08-16 07:43:18 UTC (rev 910) @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file '/home/me/src/fclient/trunk/fclient/fclient/impl/ViewBrowser/SideBars/SideBarLoadDetailsTpl.ui' +# +# Created: Sat Aug 16 09:12:46 2008 +# by: PyQt4 UI code generator 4.4.3-snapshot-20080705 +# +# WARNING! All changes made in this file will be lost! + +from PyQt4 import QtCore, QtGui + +class Ui_SideBarLoadDetails(object): + def setupUi(self, SideBarLoadDetails): + SideBarLoadDetails.setObjectName("SideBarLoadDetails") + SideBarLoadDetails.resize(497, 488) + self.gridLayout = QtGui.QGridLayout(SideBarLoadDetails) + self.gridLayout.setObjectName("gridLayout") + self.horizontalLayout = QtGui.QHBoxLayout() + self.horizontalLayout.setObjectName("horizontalLayout") + self.header = QtGui.QLabel(SideBarLoadDetails) + self.header.setObjectName("header") + self.horizontalLayout.addWidget(self.header) + self.btClose = QtGui.QToolButton(SideBarLoadDetails) + self.btClose.setObjectName("btClose") + self.horizontalLayout.addWidget(self.btClose) + self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 1) + self.tree = QtGui.QTreeWidget(SideBarLoadDetails) + self.tree.setObjectName("tree") + self.gridLayout.addWidget(self.tree, 1, 0, 1, 1) + + self.retranslateUi(SideBarLoadDetails) + QtCore.QMetaObject.connectSlotsByName(SideBarLoadDetails) + + def retranslateUi(self, SideBarLoadDetails): + SideBarLoadDetails.setWindowTitle(QtGui.QApplication.translate("SideBarLoadDetails", "Form", None, QtGui.QApplication.UnicodeUTF8)) + self.header.setText(QtGui.QApplication.translate("SideBarLoadDetails", "Load details", None, QtGui.QApplication.UnicodeUTF8)) + self.btClose.setText(QtGui.QApplication.translate("SideBarLoadDetails", "...", None, QtGui.QApplication.UnicodeUTF8)) + self.tree.headerItem().setText(0, QtGui.QApplication.translate("SideBarLoadDetails", "1", None, QtGui.QApplication.UnicodeUTF8)) + + +if __name__ == "__main__": + import sys + app = QtGui.QApplication(sys.argv) + SideBarLoadDetails = QtGui.QWidget() + ui = Ui_SideBarLoadDetails() + ui.setupUi(SideBarLoadDetails) + SideBarLoadDetails.show() + sys.exit(app.exec_()) + Added: trunk/fclient/fclient/impl/ViewBrowser/SideBars/__init__.py =================================================================== --- trunk/fclient/fclient/impl/ViewBrowser/SideBars/__init__.py (rev 0) +++ trunk/fclient/fclient/impl/ViewBrowser/SideBars/__init__.py 2008-08-16 07:43:18 UTC (rev 910) @@ -0,0 +1,14 @@ + +class BrowserSideBar: + """template for sidebars""" + + def __init__(self, parent=None, closeAction=None): + """ + @param parent: parent widget + @param closeAction: (QAction) that should be triggered to close the sideBar + """ + def setCurrent(self, browserWidget, flag): + """ + @param browserWidget: browser widget the sideBar is attatched to + @param flag: (bool) True if the sideBar is the current sidebar now, False otherwise + """ \ No newline at end of file Added: trunk/fclient/fclient/impl/ViewBrowser/SideBars/_fix_mexec.py =================================================================== --- trunk/fclient/fclient/impl/ViewBrowser/SideBars/_fix_mexec.py (rev 0) +++ trunk/fclient/fclient/impl/ViewBrowser/SideBars/_fix_mexec.py 2008-08-16 07:43:18 UTC (rev 910) @@ -0,0 +1,99 @@ +'''in python 2.5 relative impports are srsly broken ..fix this to make relative imports work +when executing a module as main (-m), including relative imports up to the root package + +see: [http://mail.python.org/pipermail/python-ideas/2007-February/000232.html] + +@note: root package is the highest available package in the package hirarchy. +don't look at __name__ too closely. it gets adjusted for a module to just "do the right +thing" in __name__ == '__main__' comparisons +@note: this patch does not work if relative imports are done in __init__.py. no idea why +and to be honest, I don't wanna* know.. +@note: this is more or less a hack. so it may have unwanted side effects for example +when importing parent packages. use at your own risk. could improve this module +by adding a __main__.py to stop at this level or by fixing the __init__.py bug, but +I don't think its worth it. see what python2.6 or 3k brings.. + +usage:: + + # place this at the top a module, before doing any relative imports + from fix_mexec import fix_mexec + fi... [truncated message content] |
From: <jU...@us...> - 2008-08-16 06:51:14
|
Revision: 909 http://fclient.svn.sourceforge.net/fclient/?rev=909&view=rev Author: jUrner Date: 2008-08-16 06:51:24 +0000 (Sat, 16 Aug 2008) Log Message: ----------- playing around with styles Modified Paths: -------------- trunk/fclient/fclient/impl/res/stylesheets/default.css Modified: trunk/fclient/fclient/impl/res/stylesheets/default.css =================================================================== --- trunk/fclient/fclient/impl/res/stylesheets/default.css 2008-08-16 06:50:50 UTC (rev 908) +++ trunk/fclient/fclient/impl/res/stylesheets/default.css 2008-08-16 06:51:24 UTC (rev 909) @@ -72,22 +72,23 @@ /* downloadWidget progressBars (omitted [status="removed"]) */ QProgressBar#downloadKey[status="pending"]::chunk{ -background: qlineargradient(x1: 0, y1: 0.5, x2: 1, y2: 0.5, stop: 0 gray, stop: 1 lightgray); +background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 gray, stop: 0.5 lightgray, stop: 1 gray); } QProgressBar#downloadKey[status="loading"]::chunk{ -background: qlineargradient(x1: 0, y1: 0.5, x2: 1, y2: 0.5, stop: 0 blue, stop: 1 aqua); +background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 blue, stop: 0.5 aqua, stop: 1 blue); } QProgressBar#downloadKey[status="complete"]::chunk{ -background: qlineargradient(x1: 0, y1: 0.5, x2: 1, y2: 0.5, stop: 0 green, stop: 1 limegreen); +background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 green, stop: 0.5 limegreen, stop: 1 green); } + QProgressBar#downloadKey[status="error"]::chunk{ background: qlineargradient(x1: 0, y1: 0.5, x2: 1, y2: 0.5, stop: 0 red, stop: 1 pink); } QProgressBar#downloadKey[status="compressing"]::chunk{ -background: qlineargradient(x1: 0, y1: 0.5, x2: 1, y2: 0.5, stop: 0 orange, stop: 1 yellow); +background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 orange, stop: 0.5 yellow, stop: 1 orange); } /* label indicating connected status on statusBar */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jU...@us...> - 2008-08-16 06:50:41
|
Revision: 908 http://fclient.svn.sourceforge.net/fclient/?rev=908&view=rev Author: jUrner Date: 2008-08-16 06:50:50 +0000 (Sat, 16 Aug 2008) Log Message: ----------- whitespace Modified Paths: -------------- trunk/fclient/fclient/impl/DlgSingleAppError.py Modified: trunk/fclient/fclient/impl/DlgSingleAppError.py =================================================================== --- trunk/fclient/fclient/impl/DlgSingleAppError.py 2008-08-16 06:49:45 UTC (rev 907) +++ trunk/fclient/fclient/impl/DlgSingleAppError.py 2008-08-16 06:50:50 UTC (rev 908) @@ -3,7 +3,6 @@ # x. error icon # #************************************************************************************* - from __future__ import absolute_import if __name__ == '__main__': # see --> http://bugs.python.org/issue1510172 . works only current dir and below import os; __path__ = [os.path.dirname(__file__)] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jU...@us...> - 2008-08-16 06:49:37
|
Revision: 907 http://fclient.svn.sourceforge.net/fclient/?rev=907&view=rev Author: jUrner Date: 2008-08-16 06:49:45 +0000 (Sat, 16 Aug 2008) Log Message: ----------- another package redesign. finally found a way to separate components while leaving relative imports intact for testing Modified Paths: -------------- trunk/fclient/fclient/fclient.py Added Paths: ----------- trunk/fclient/fclient/impl/MainWindow/ trunk/fclient/fclient/impl/MainWindow/Actions.py trunk/fclient/fclient/impl/MainWindow/MainWindow.py trunk/fclient/fclient/impl/MainWindow/MainWindow.ui trunk/fclient/fclient/impl/MainWindow/MenuBar.py trunk/fclient/fclient/impl/MainWindow/Settings.py trunk/fclient/fclient/impl/MainWindow/StatusBar.py trunk/fclient/fclient/impl/MainWindow/TitleBar.py trunk/fclient/fclient/impl/MainWindow/Ui_MainWindow.py trunk/fclient/fclient/impl/MainWindow/__init__.py trunk/fclient/fclient/impl/MainWindow/_fix_mexec.py Removed Paths: ------------- trunk/fclient/fclient/impl/MainWindow.py trunk/fclient/fclient/impl/tpls/MainWindowTpl.ui trunk/fclient/fclient/impl/tpls/Ui_MainWindowTpl.py Modified: trunk/fclient/fclient/fclient.py =================================================================== --- trunk/fclient/fclient/fclient.py 2008-08-12 08:44:19 UTC (rev 906) +++ trunk/fclient/fclient/fclient.py 2008-08-16 06:49:45 UTC (rev 907) @@ -70,7 +70,7 @@ else: # everything went well. start gui app = QtGui.QApplication(sys.argv) - mainWindow = MainWindow() + mainWindow = MainWindow.MainWindow() singleApp.userData = mainWindow viewWidget = ViewWidget(mainWindow) Added: trunk/fclient/fclient/impl/MainWindow/Actions.py =================================================================== --- trunk/fclient/fclient/impl/MainWindow/Actions.py (rev 0) +++ trunk/fclient/fclient/impl/MainWindow/Actions.py 2008-08-16 06:49:45 UTC (rev 907) @@ -0,0 +1,45 @@ + +# some fixes for relative imports +# see --> [http://bugs.python.org/issue1510172] absolute/rellative import not working (works only current dir and below) +# see --> [http://mail.python.org/pipermail/python-ideas/2007-February/000232.html] PEP for executing a module in a +# ...package containing relative imports +from __future__ import absolute_import +if __name__ == '__main__': + import os + __path__ = [os.path.dirname(__file__)] + from ._fix_mexec import fix_mexec + fix_mexec(__name__, __file__) + del fix_mexec + +from .. import config + +from PyQt4 import QtCore, QtGui +#********************************************************************************** +# +#********************************************************************************** +class Actions(config.ActionsBase): + + def __init__(self, parent): + config.ActionsBase.__init__(self, parent) + + self.action( + name='ActionPreferences', + text=self.trUtf8('&Preferences...'), + trigger=parent.onActPreferencesTriggered, + ) + self.action( + name='ActionExit', + text=self.trUtf8('E&xit'), + trigger=parent.onActExitTriggered, + ) + self.action( + name='ActionAbout', + text=self.trUtf8('A&bout...'), + trigger=parent.onActAboutTriggered, + ) + self.action( + name='ActionHelp', + text=self.trUtf8('&Help...'), + trigger=parent.onActHelpTriggered, + ) + \ No newline at end of file Added: trunk/fclient/fclient/impl/MainWindow/MainWindow.py =================================================================== --- trunk/fclient/fclient/impl/MainWindow/MainWindow.py (rev 0) +++ trunk/fclient/fclient/impl/MainWindow/MainWindow.py 2008-08-16 06:49:45 UTC (rev 907) @@ -0,0 +1,103 @@ + +# some fixes for relative imports +# see --> [http://bugs.python.org/issue1510172] absolute/rellative import not working (works only current dir and below) +# see --> [http://mail.python.org/pipermail/python-ideas/2007-February/000232.html] PEP for executing a module in a +# ...package containing relative imports +from __future__ import absolute_import +if __name__ == '__main__': + import os + __path__ = [os.path.dirname(__file__)] + from ._fix_mexec import fix_mexec + fix_mexec(__name__, __file__) + del fix_mexec + +from PyQt4 import QtCore, QtGui + +from .. import config +from .. import Prefs +from ..lib.qt4ex import dlgabout + +from . import Actions +from . import MenuBar +from . import Settings +from . import StatusBar +from . import TitleBar +from . import Ui_MainWindow +#********************************************************************************** +# +#********************************************************************************** +class MainWindow(QtGui.QMainWindow, Ui_MainWindow.Ui_MainWindow): + + def __init__(self, parent=None): + QtGui.QMainWindow.__init__(self, parent) + self._isCreated = False + + self.setupUi(self) + config.ObjectRegistry.register(self) + + self.fcSettings = Settings.Settings().restore() + self.fcActions = Actions.Actions(self) + self.setMenuBar(MenuBar.MenuBar(self)) + self.setStatusBar(StatusBar.StatusBar(self)) + self.fcTitleBar = TitleBar.TitleBar(self) + + self.setWindowIcon(config.fcResources.getIcon('fclient', 32, iconTheme='application', ext='.svg')) + self.restoreGeometry(self.fcSettings.value('Geometry')) + + ################################## + ## methods + ################################## + def titleBar(self): + return self.fcTitleBar + + ################################## + ## events + ################################## + def closeEvent(self, event): + self.fcSettings.setValues(Geometry=self.saveGeometry()) + + def showEvent(self, event): + if self._isCreated: + return + self._isCreated = True + + ################################### + ## event onrs + ################################### + def onActPreferencesTriggered(self): + dlg = Prefs.PrefsDlg(self) + if dlg.exec_() == dlg.Accepted: + pass + + def onActExitTriggered(self): + self.close() + + def onActHelpTriggered(self): + pass + + def onActAboutTriggered(self): + dlg = dlgabout.DlgAbout( + self, + ##state=self.guiSettings['DlgAboutState'], + caption=config.FcAppName + ' - ' + self.trUtf8('About'), + appName=config.FcAppName, + description=self.trUtf8('a freenet client written in Fc and Qt4'), + version=config.FcVersion, + author=config.FcAuthor, + licence=config.FcLicence, + copyright=config.FcCopyright, + homepage=config.FcHomepage + ) + dlg.exec_() + #self.guiSettings['DlgAboutState'] = dlg.saveState() + +#********************************************************************************** +# +#********************************************************************************** +if __name__ == '__main__': + import sys + app = QtGui.QApplication(sys.argv) + w = MainWindow(None) + w.show() + res = app.exec_() + sys.exit(res) Added: trunk/fclient/fclient/impl/MainWindow/MainWindow.ui =================================================================== --- trunk/fclient/fclient/impl/MainWindow/MainWindow.ui (rev 0) +++ trunk/fclient/fclient/impl/MainWindow/MainWindow.ui 2008-08-16 06:49:45 UTC (rev 907) @@ -0,0 +1,70 @@ +<ui version="4.0" > + <class>MainWindow</class> + <widget class="QMainWindow" name="MainWindow" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>774</width> + <height>591</height> + </rect> + </property> + <property name="windowTitle" > + <string>MainWindow</string> + </property> + <widget class="QWidget" name="centralwidget" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>774</width> + <height>568</height> + </rect> + </property> + <zorder>frame</zorder> + </widget> + <widget class="QStatusBar" name="statusbar" > + <property name="geometry" > + <rect> + <x>0</x> + <y>568</y> + <width>774</width> + <height>23</height> + </rect> + </property> + </widget> + <action name="action_Preferences" > + <property name="text" > + <string>_Preferences</string> + </property> + </action> + <action name="actPreferences" > + <property name="text" > + <string>&Preferences..</string> + </property> + </action> + <action name="actExit" > + <property name="text" > + <string>E&xit</string> + </property> + </action> + <action name="actHelp" > + <property name="text" > + <string>&Help..</string> + </property> + <property name="toolTip" > + <string>Help</string> + </property> + </action> + <action name="actAbout" > + <property name="text" > + <string>A&bout..</string> + </property> + <property name="iconText" > + <string>About</string> + </property> + </action> + </widget> + <resources/> + <connections/> +</ui> Added: trunk/fclient/fclient/impl/MainWindow/MenuBar.py =================================================================== --- trunk/fclient/fclient/impl/MainWindow/MenuBar.py (rev 0) +++ trunk/fclient/fclient/impl/MainWindow/MenuBar.py 2008-08-16 06:49:45 UTC (rev 907) @@ -0,0 +1,26 @@ + +from PyQt4 import QtGui +#********************************************************************************** +# +#********************************************************************************** +class MenuBar(QtGui.QMenuBar): + + def __init__(self, parent): + QtGui.QMenuBar.__init__(self, parent) + self.setObjectName('MenuBar') + #config.ObjectRegistry.register(self) + + self.menuApplication = QtGui.QMenu(self.trUtf8('&Application'), self) + self.addMenu(self.menuApplication) + self.menuApplication.addAction(parent.fcActions['ActionPreferences']) + self.menuApplication.addAction(parent.fcActions['ActionExit']) + + self.menuHelp = QtGui.QMenu(self.trUtf8('&Help'), self) + self.addMenu(self.menuHelp) + self.menuHelp.addAction(parent.fcActions['ActionAbout']) + self.menuHelp.addAction(parent.fcActions['ActionHelp']) + + + def addViewMenu(self, menu): + self.insertMenu(self.menuHelp.children()[0], menu) + return menu \ No newline at end of file Added: trunk/fclient/fclient/impl/MainWindow/Settings.py =================================================================== --- trunk/fclient/fclient/impl/MainWindow/Settings.py (rev 0) +++ trunk/fclient/fclient/impl/MainWindow/Settings.py 2008-08-16 06:49:45 UTC (rev 907) @@ -0,0 +1,26 @@ +# some fixes for relative imports +# see --> [http://bugs.python.org/issue1510172] absolute/rellative import not working (works only current dir and below) +# see --> [http://mail.python.org/pipermail/python-ideas/2007-February/000232.html] PEP for executing a module in a +# ...package containing relative imports +from __future__ import absolute_import +if __name__ == '__main__': + import os + __path__ = [os.path.dirname(__file__)] + from ._fix_mexec import fix_mexec + fix_mexec(__name__, __file__) + del fix_mexec + +from .. import config + +from PyQt4 import QtCore, QtGui +#********************************************************************************** +# +#********************************************************************************** +class Settings(config.SettingsBase): + + _key_ = config.IdMainWindow + _settings_ = ( + ('Geometry', 'ByteArray', QtCore.QByteArray()), + ('ConnectionLabelFlashRate', 'UInt', 800), + ) + Added: trunk/fclient/fclient/impl/MainWindow/StatusBar.py =================================================================== --- trunk/fclient/fclient/impl/MainWindow/StatusBar.py (rev 0) +++ trunk/fclient/fclient/impl/MainWindow/StatusBar.py 2008-08-16 06:49:45 UTC (rev 907) @@ -0,0 +1,90 @@ + +# some fixes for relative imports +# see --> [http://bugs.python.org/issue1510172] absolute/rellative import not working (works only current dir and below) +# see --> [http://mail.python.org/pipermail/python-ideas/2007-February/000232.html] PEP for executing a module in a +# ...package containing relative imports +from __future__ import absolute_import +if __name__ == '__main__': + import os + __path__ = [os.path.dirname(__file__)] + from ._fix_mexec import fix_mexec + fix_mexec(__name__, __file__) + del fix_mexec + +from .. import config + +from PyQt4 import QtCore, QtGui +#********************************************************************************** +# +#********************************************************************************** +class StatusBar(QtGui.QStatusBar): + + + class DisconnectTimer(QtCore.QTimer): + + def __init__(self,statusBar): + QtCore.QTimer.__init__(self, statusBar) + self.connect(self, QtCore.SIGNAL('timeout()'), self.onNext) + + def start(self, n): + QtCore.QTimer.start(self, n) + + def onNext(self): + statusBar = self.parent() + if statusBar.connectionLabels['LabelConnectionConnected'].isVisible(): + self.stop() + else: + statusBar.connectionLabels['LabelConnectionDisonnectedOn'].setVisible( + not statusBar.connectionLabels['LabelConnectionDisonnectedOn'].isVisible() + ) + statusBar.connectionLabels['LabelConnectionDisonnectedOff'].setVisible( + not statusBar.connectionLabels['LabelConnectionDisonnectedOff'].isVisible() + ) + + def __init__(self, mainWindow): + QtGui.QStatusBar.__init__(self, mainWindow) + self.setObjectName('StatusBar') + #config.ObjectRegistry.register(self) + mainWindow.setStatusBar(self) + + self._disconnectTimer = self.DisconnectTimer(self) + + # setup connection labels + self.fcpEvents = ( + (config.fcpClient.events.ClientConnected, self.onFcpClientConnected), + (config.fcpClient.events.ClientDisconnected, self.onFcpClientDisconnected), + ) + config.fcpClient.events += self.fcpEvents + self.connectionLabels = { + 'LabelConnectionConnected': QtGui.QLabel(self), + 'LabelConnectionDisonnectedOn': QtGui.QLabel(self), + 'LabelConnectionDisonnectedOff': QtGui.QLabel(self), + } + for objectName, label in self.connectionLabels.items(): + label.setObjectName(objectName) + label.setVisible(False) + self.addWidget(label, 0) + if config.fcpClient.isConnected(): + self.connectionLabels['LabelConnectionConnected'].show() + else : + self.connectionLabels['LabelConnectionDisonnectedOn'].show() + + self.retranslateUi(self) + + + def retranslateUi(self, this): + self.connectionLabels['LabelConnectionConnected'].setText(self.trUtf8('CONNECTED')) + self.connectionLabels['LabelConnectionDisonnectedOn'].setText(self.trUtf8('DISCONNECTED')) + self.connectionLabels['LabelConnectionDisonnectedOff'].setText(self.trUtf8('DISCONNECTED')) + + def onFcpClientConnected(self, event, msg): + self._disconnectTimer.stop() + for label in self.connectionLabels.values(): + label.hide() + self.connectionLabels['LabelConnectionConnected'].show() + + def onFcpClientDisconnected(self, event, msg): + for label in self.connectionLabels.values(): + label.hide() + self.connectionLabels['LabelConnectionDisonnectedOn'].show() + self._disconnectTimer.start(self.parent().fcSettings.value('ConnectionLabelFlashRate')) Added: trunk/fclient/fclient/impl/MainWindow/TitleBar.py =================================================================== --- trunk/fclient/fclient/impl/MainWindow/TitleBar.py (rev 0) +++ trunk/fclient/fclient/impl/MainWindow/TitleBar.py 2008-08-16 06:49:45 UTC (rev 907) @@ -0,0 +1,32 @@ + +# some fixes for relative imports +# see --> [http://bugs.python.org/issue1510172] absolute/rellative import not working (works only current dir and below) +# see --> [http://mail.python.org/pipermail/python-ideas/2007-February/000232.html] PEP for executing a module in a +# ...package containing relative imports +from __future__ import absolute_import +if __name__ == '__main__': + import os + __path__ = [os.path.dirname(__file__)] + from ._fix_mexec import fix_mexec + fix_mexec(__name__, __file__) + del fix_mexec + +from .. import config + + +from PyQt4 import QtCore +#********************************************************************************** +# +#********************************************************************************** +class TitleBar(QtCore.QObject): + + def __init__(self, parent): + QtCore.QObject.__init__(self, parent) + self.setInfo('') + + def setInfo(self, text): + if text: + title = config.FcAppName + ' - [%s]' % text + else: + title = config.FcAppName + self.parent().setWindowTitle(title) Added: trunk/fclient/fclient/impl/MainWindow/Ui_MainWindow.py =================================================================== --- trunk/fclient/fclient/impl/MainWindow/Ui_MainWindow.py (rev 0) +++ trunk/fclient/fclient/impl/MainWindow/Ui_MainWindow.py 2008-08-16 06:49:45 UTC (rev 907) @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file '/home/me/src/fclient/trunk/fclient/fclient/impl/MainWindow/MainWindow.ui' +# +# Created: Thu Aug 14 13:55:41 2008 +# by: PyQt4 UI code generator 4.4.3-snapshot-20080705 +# +# WARNING! All changes made in this file will be lost! + +from PyQt4 import QtCore, QtGui + +class Ui_MainWindow(object): + def setupUi(self, MainWindow): + MainWindow.setObjectName("MainWindow") + MainWindow.resize(774, 591) + self.centralwidget = QtGui.QWidget(MainWindow) + self.centralwidget.setGeometry(QtCore.QRect(0, 0, 774, 568)) + self.centralwidget.setObjectName("centralwidget") + MainWindow.setCentralWidget(self.centralwidget) + self.statusbar = QtGui.QStatusBar(MainWindow) + self.statusbar.setGeometry(QtCore.QRect(0, 568, 774, 23)) + self.statusbar.setObjectName("statusbar") + MainWindow.setStatusBar(self.statusbar) + self.action_Preferences = QtGui.QAction(MainWindow) + self.action_Preferences.setObjectName("action_Preferences") + self.actPreferences = QtGui.QAction(MainWindow) + self.actPreferences.setObjectName("actPreferences") + self.actExit = QtGui.QAction(MainWindow) + self.actExit.setObjectName("actExit") + self.actHelp = QtGui.QAction(MainWindow) + self.actHelp.setObjectName("actHelp") + self.actAbout = QtGui.QAction(MainWindow) + self.actAbout.setObjectName("actAbout") + + self.retranslateUi(MainWindow) + QtCore.QMetaObject.connectSlotsByName(MainWindow) + + def retranslateUi(self, MainWindow): + MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8)) + self.action_Preferences.setText(QtGui.QApplication.translate("MainWindow", "_Preferences", None, QtGui.QApplication.UnicodeUTF8)) + self.actPreferences.setText(QtGui.QApplication.translate("MainWindow", "&Preferences..", None, QtGui.QApplication.UnicodeUTF8)) + self.actExit.setText(QtGui.QApplication.translate("MainWindow", "E&xit", None, QtGui.QApplication.UnicodeUTF8)) + self.actHelp.setText(QtGui.QApplication.translate("MainWindow", "&Help..", None, QtGui.QApplication.UnicodeUTF8)) + self.actHelp.setToolTip(QtGui.QApplication.translate("MainWindow", "Help", None, QtGui.QApplication.UnicodeUTF8)) + self.actAbout.setText(QtGui.QApplication.translate("MainWindow", "A&bout..", None, QtGui.QApplication.UnicodeUTF8)) + self.actAbout.setIconText(QtGui.QApplication.translate("MainWindow", "About", None, QtGui.QApplication.UnicodeUTF8)) + + +if __name__ == "__main__": + import sys + app = QtGui.QApplication(sys.argv) + MainWindow = QtGui.QMainWindow() + ui = Ui_MainWindow() + ui.setupUi(MainWindow) + MainWindow.show() + sys.exit(app.exec_()) + Added: trunk/fclient/fclient/impl/MainWindow/__init__.py =================================================================== --- trunk/fclient/fclient/impl/MainWindow/__init__.py (rev 0) +++ trunk/fclient/fclient/impl/MainWindow/__init__.py 2008-08-16 06:49:45 UTC (rev 907) @@ -0,0 +1 @@ + Added: trunk/fclient/fclient/impl/MainWindow/_fix_mexec.py =================================================================== --- trunk/fclient/fclient/impl/MainWindow/_fix_mexec.py (rev 0) +++ trunk/fclient/fclient/impl/MainWindow/_fix_mexec.py 2008-08-16 06:49:45 UTC (rev 907) @@ -0,0 +1,99 @@ +'''in python 2.5 relative impports are srsly broken ..fix this to make relative imports work +when executing a module as main (-m), including relative imports up to the root package + +see: [http://mail.python.org/pipermail/python-ideas/2007-February/000232.html] + +@note: root package is the highest available package in the package hirarchy. +don't look at __name__ too closely. it gets adjusted for a module to just "do the right +thing" in __name__ == '__main__' comparisons +@note: this patch does not work if relative imports are done in __init__.py. no idea why +and to be honest, I don't wanna* know.. +@note: this is more or less a hack. so it may have unwanted side effects for example +when importing parent packages. use at your own risk. could improve this module +by adding a __main__.py to stop at this level or by fixing the __init__.py bug, but +I don't think its worth it. see what python2.6 or 3k brings.. + +usage:: + + # place this at the top a module, before doing any relative imports + from fix_mexec import fix_mexec + fix_mexec(__name__, __file__) + del fix_mexec + + from ...foo import bar + + + +##<-- copy and paste code, assuming _fix_mexec resides in the current dir.. + +# some fixes for relative imports +# see --> [http://bugs.python.org/issue1510172] absolute/rellative import not working (works only current dir and below) +# see --> [http://mail.python.org/pipermail/python-ideas/2007-February/000232.html] PEP for executing a module in a +# ...package containing relative imports +from __future__ import absolute_import +if __name__ == '__main__': + import os + __path__ = [os.path.dirname(__file__)] + from ._fix_mexec import fix_mexec + fix_mexec(__name__, __file__) + del fix_mexec + + +##--> copy and paste code +''' + +import imp, os, sys +#******************************************************************************** +# +#******************************************************************************** +class MainName(str): + def __eq__(self, other): + if other == '__main__': return True + return str.__eq__(self, other) + def __ne__(self, other): + if other == '__main__': return False + return str.__ne__(self, other) + + +def fix_mexec(_name_, _file_): + """bugfix for relative imports not working + @param _name_: __name__ of the module + @param _file_: __file__ of the module + + @note: not complete: relies on __init__.py, .pyo (...) is ignored currently + """ + if _name_ == '__main__': + out = [] + # find allparent packages + p = os.path.dirname(os.path.abspath(_file_)) + prev = p + while True: + pkg = os.path.join(p, '__init__.py') + if os.path.isfile(pkg): + out.append([pkg, os.path.basename(p)]) + else: + break + prev = p + p = os.path.dirname(p) + if p == prev: + break + out.reverse() + + # adjust sub package names an import parent modules + name = None + for n, (fpath, name) in enumerate(out): + if n > 0: + name = out[n][1] = out[n -1][1] + '.' + out[n][1] + m = imp.load_source(name, fpath) + m.__path__ = [os.path.dirname(fpath)] + + # adjust name of the __main__ module + if name is not None: + m = sys.modules.pop('__main__') + # 'foo.bar..__main__' does not work for some reason. 'foo.bar' seems to work as expected + ##m.__name__ = _Name_(name + '.' + '__main__') + m.__name__ = MainName(name) + sys.modules[m.__name__] = m + + + Deleted: trunk/fclient/fclient/impl/MainWindow.py =================================================================== --- trunk/fclient/fclient/impl/MainWindow.py 2008-08-12 08:44:19 UTC (rev 906) +++ trunk/fclient/fclient/impl/MainWindow.py 2008-08-16 06:49:45 UTC (rev 907) @@ -1,246 +0,0 @@ -from __future__ import absolute_import -if __name__ == '__main__': # see --> http://bugs.Fc.org/issue1510172 . works only current dir and below - import os; __path__ = [os.path.dirname(__file__)] - -import logging -import sys -logging.basicConfig(stream=sys.stdout, level=logging.DEBUG) - -from PyQt4 import QtCore, QtGui - -from . import config -from . import Prefs -from .lib.qt4ex import dlgabout - -from .tpls.Ui_MainWindowTpl import Ui_MainWindow -#********************************************************************************** -# -#********************************************************************************** -class Settings(config.SettingsBase): - - _key_ = config.IdMainWindow - _settings_ = ( - ('Geometry', 'ByteArray', QtCore.QByteArray()), - ('ConnectionLabelFlashRate', 'UInt', 800), - ) - - -class Actions(config.ActionsBase): - - def __init__(self, parent): - config.ActionsBase.__init__(self, parent) - - self.action( - name='ActionPreferences', - text=self.trUtf8('&Preferences...'), - trigger=parent.onActPreferencesTriggered, - ) - self.action( - name='ActionExit', - text=self.trUtf8('E&xit'), - trigger=parent.onActExitTriggered, - ) - self.action( - name='ActionAbout', - text=self.trUtf8('A&bout...'), - trigger=parent.onActAboutTriggered, - ) - self.action( - name='ActionHelp', - text=self.trUtf8('&Help...'), - trigger=parent.onActHelpTriggered, - ) - -#********************************************************************************** -# -#********************************************************************************** -class MenuBar(QtGui.QMenuBar): - - def __init__(self, parent): - QtGui.QMenuBar.__init__(self, parent) - self.setObjectName('MenuBar') - #config.ObjectRegistry.register(self) - - self.menuApplication = QtGui.QMenu(self.trUtf8('&Application'), self) - self.addMenu(self.menuApplication) - self.menuApplication.addAction(parent.fcActions['ActionPreferences']) - self.menuApplication.addAction(parent.fcActions['ActionExit']) - - self.menuHelp = QtGui.QMenu(self.trUtf8('&Help'), self) - self.addMenu(self.menuHelp) - self.menuHelp.addAction(parent.fcActions['ActionAbout']) - self.menuHelp.addAction(parent.fcActions['ActionHelp']) - - - def addViewMenu(self, menu): - self.insertMenu(self.menuHelp.children()[0], menu) - return menu - - -class StatusBar(QtGui.QStatusBar): - - - class DisconnectTimer(QtCore.QTimer): - - def __init__(self,statusBar): - QtCore.QTimer.__init__(self, statusBar) - self.connect(self, QtCore.SIGNAL('timeout()'), self.onNext) - - def start(self, n): - QtCore.QTimer.start(self, n) - - def onNext(self): - statusBar = self.parent() - if statusBar.connectionLabels['LabelConnectionConnected'].isVisible(): - self.stop() - else: - statusBar.connectionLabels['LabelConnectionDisonnectedOn'].setVisible( - not statusBar.connectionLabels['LabelConnectionDisonnectedOn'].isVisible() - ) - statusBar.connectionLabels['LabelConnectionDisonnectedOff'].setVisible( - not statusBar.connectionLabels['LabelConnectionDisonnectedOff'].isVisible() - ) - - def __init__(self, mainWindow): - QtGui.QStatusBar.__init__(self, mainWindow) - self.setObjectName('StatusBar') - #config.ObjectRegistry.register(self) - mainWindow.setStatusBar(self) - - self._disconnectTimer = self.DisconnectTimer(self) - - # setup connection labels - self.fcpEvents = ( - (config.fcpClient.events.ClientConnected, self.onFcpClientConnected), - (config.fcpClient.events.ClientDisconnected, self.onFcpClientDisconnected), - ) - config.fcpClient.events += self.fcpEvents - self.connectionLabels = { - 'LabelConnectionConnected': QtGui.QLabel(self), - 'LabelConnectionDisonnectedOn': QtGui.QLabel(self), - 'LabelConnectionDisonnectedOff': QtGui.QLabel(self), - } - for objectName, label in self.connectionLabels.items(): - label.setObjectName(objectName) - label.setVisible(False) - self.addWidget(label, 0) - if config.fcpClient.isConnected(): - self.connectionLabels['LabelConnectionConnected'].show() - else : - self.connectionLabels['LabelConnectionDisonnectedOn'].show() - - self.retranslateUi(self) - - - def retranslateUi(self, this): - self.connectionLabels['LabelConnectionConnected'].setText(self.trUtf8('CONNECTED')) - self.connectionLabels['LabelConnectionDisonnectedOn'].setText(self.trUtf8('DISCONNECTED')) - self.connectionLabels['LabelConnectionDisonnectedOff'].setText(self.trUtf8('DISCONNECTED')) - - def onFcpClientConnected(self, event, msg): - self._disconnectTimer.stop() - for label in self.connectionLabels.values(): - label.hide() - self.connectionLabels['LabelConnectionConnected'].show() - - def onFcpClientDisconnected(self, event, msg): - for label in self.connectionLabels.values(): - label.hide() - self.connectionLabels['LabelConnectionDisonnectedOn'].show() - self._disconnectTimer.start(self.parent().fcSettings.value('ConnectionLabelFlashRate')) - - - -class TitleBar(QtCore.QObject): - - def __init__(self, parent): - QtCore.QObject.__init__(self, parent) - self.setInfo('') - - def setInfo(self, text): - if text: - title = config.FcAppName + ' - [%s]' % text - else: - title = config.FcAppName - self.parent().setWindowTitle(title) - -#********************************************************************************** -# -#********************************************************************************** -class MainWindow(QtGui.QMainWindow, Ui_MainWindow): - - def __init__(self, parent=None): - QtGui.QMainWindow.__init__(self, parent) - self._isCreated = False - - self.setupUi(self) - config.ObjectRegistry.register(self) - - self.fcSettings = Settings().restore() - self.fcActions = Actions(self) - self.setMenuBar(MenuBar(self)) - self.setStatusBar(StatusBar(self)) - self.fcTitleBar = TitleBar(self) - - self.setWindowIcon(config.fcResources.getIcon('fclient', 32, iconTheme='application', ext='.svg')) - self.restoreGeometry(self.fcSettings.value('Geometry')) - - ################################## - ## methods - ################################## - def titleBar(self): - return self.fcTitleBar - - - ################################## - ## events - ################################## - def closeEvent(self, event): - self.fcSettings.setValues(Geometry=self.saveGeometry()) - - def showEvent(self, event): - if self._isCreated: - return - self._isCreated = True - - ################################### - ## event onrs - ################################### - def onActPreferencesTriggered(self): - dlg = Prefs.PrefsDlg(self) - if dlg.exec_() == dlg.Accepted: - pass - - def onActExitTriggered(self): - self.close() - - def onActHelpTriggered(self): - pass - - def onActAboutTriggered(self): - dlg = dlgabout.DlgAbout( - self, - ##state=self.guiSettings['DlgAboutState'], - caption=config.FcAppName + ' - ' + self.trUtf8('About'), - appName=config.FcAppName, - description=self.trUtf8('a freenet client written in Fc and Qt4'), - version=config.FcVersion, - author=config.FcAuthor, - licence=config.FcLicence, - copyright=config.FcCopyright, - homepage=config.FcHomepage - ) - dlg.exec_() - #self.guiSettings['DlgAboutState'] = dlg.saveState() - -#********************************************************************************** -# -#********************************************************************************** -if __name__ == '__main__': - import sys - - app = QtGui.QApplication(sys.argv) - w = MainWindow(None) - w.show() - res = app.exec_() - sys.exit(res) \ No newline at end of file Deleted: trunk/fclient/fclient/impl/tpls/MainWindowTpl.ui =================================================================== --- trunk/fclient/fclient/impl/tpls/MainWindowTpl.ui 2008-08-12 08:44:19 UTC (rev 906) +++ trunk/fclient/fclient/impl/tpls/MainWindowTpl.ui 2008-08-16 06:49:45 UTC (rev 907) @@ -1,70 +0,0 @@ -<ui version="4.0" > - <class>MainWindow</class> - <widget class="QMainWindow" name="MainWindow" > - <property name="geometry" > - <rect> - <x>0</x> - <y>0</y> - <width>774</width> - <height>591</height> - </rect> - </property> - <property name="windowTitle" > - <string>MainWindow</string> - </property> - <widget class="QWidget" name="centralwidget" > - <property name="geometry" > - <rect> - <x>0</x> - <y>0</y> - <width>774</width> - <height>568</height> - </rect> - </property> - <zorder>frame</zorder> - </widget> - <widget class="QStatusBar" name="statusbar" > - <property name="geometry" > - <rect> - <x>0</x> - <y>568</y> - <width>774</width> - <height>23</height> - </rect> - </property> - </widget> - <action name="action_Preferences" > - <property name="text" > - <string>_Preferences</string> - </property> - </action> - <action name="actPreferences" > - <property name="text" > - <string>&Preferences..</string> - </property> - </action> - <action name="actExit" > - <property name="text" > - <string>E&xit</string> - </property> - </action> - <action name="actHelp" > - <property name="text" > - <string>&Help..</string> - </property> - <property name="toolTip" > - <string>Help</string> - </property> - </action> - <action name="actAbout" > - <property name="text" > - <string>A&bout..</string> - </property> - <property name="iconText" > - <string>About</string> - </property> - </action> - </widget> - <resources/> - <connections/> -</ui> Deleted: trunk/fclient/fclient/impl/tpls/Ui_MainWindowTpl.py =================================================================== --- trunk/fclient/fclient/impl/tpls/Ui_MainWindowTpl.py 2008-08-12 08:44:19 UTC (rev 906) +++ trunk/fclient/fclient/impl/tpls/Ui_MainWindowTpl.py 2008-08-16 06:49:45 UTC (rev 907) @@ -1,57 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file '/home/me/src/fclient/trunk/fclient/fclient/impl/tpls/MainWindowTpl.ui' -# -# Created: Sat Aug 2 01:50:59 2008 -# by: PyQt4 UI code generator 4.4.3-snapshot-20080705 -# -# WARNING! All changes made in this file will be lost! - -from PyQt4 import QtCore, QtGui - -class Ui_MainWindow(object): - def setupUi(self, MainWindow): - MainWindow.setObjectName("MainWindow") - MainWindow.resize(774, 591) - self.centralwidget = QtGui.QWidget(MainWindow) - self.centralwidget.setGeometry(QtCore.QRect(0, 0, 774, 568)) - self.centralwidget.setObjectName("centralwidget") - MainWindow.setCentralWidget(self.centralwidget) - self.statusbar = QtGui.QStatusBar(MainWindow) - self.statusbar.setGeometry(QtCore.QRect(0, 568, 774, 23)) - self.statusbar.setObjectName("statusbar") - MainWindow.setStatusBar(self.statusbar) - self.action_Preferences = QtGui.QAction(MainWindow) - self.action_Preferences.setObjectName("action_Preferences") - self.actPreferences = QtGui.QAction(MainWindow) - self.actPreferences.setObjectName("actPreferences") - self.actExit = QtGui.QAction(MainWindow) - self.actExit.setObjectName("actExit") - self.actHelp = QtGui.QAction(MainWindow) - self.actHelp.setObjectName("actHelp") - self.actAbout = QtGui.QAction(MainWindow) - self.actAbout.setObjectName("actAbout") - - self.retranslateUi(MainWindow) - QtCore.QMetaObject.connectSlotsByName(MainWindow) - - def retranslateUi(self, MainWindow): - MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8)) - self.action_Preferences.setText(QtGui.QApplication.translate("MainWindow", "_Preferences", None, QtGui.QApplication.UnicodeUTF8)) - self.actPreferences.setText(QtGui.QApplication.translate("MainWindow", "&Preferences..", None, QtGui.QApplication.UnicodeUTF8)) - self.actExit.setText(QtGui.QApplication.translate("MainWindow", "E&xit", None, QtGui.QApplication.UnicodeUTF8)) - self.actHelp.setText(QtGui.QApplication.translate("MainWindow", "&Help..", None, QtGui.QApplication.UnicodeUTF8)) - self.actHelp.setToolTip(QtGui.QApplication.translate("MainWindow", "Help", None, QtGui.QApplication.UnicodeUTF8)) - self.actAbout.setText(QtGui.QApplication.translate("MainWindow", "A&bout..", None, QtGui.QApplication.UnicodeUTF8)) - self.actAbout.setIconText(QtGui.QApplication.translate("MainWindow", "About", None, QtGui.QApplication.UnicodeUTF8)) - - -if __name__ == "__main__": - import sys - app = QtGui.QApplication(sys.argv) - MainWindow = QtGui.QMainWindow() - ui = Ui_MainWindow() - ui.setupUi(MainWindow) - MainWindow.show() - sys.exit(app.exec_()) - This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jU...@us...> - 2008-08-12 08:44:11
|
Revision: 906 http://fclient.svn.sourceforge.net/fclient/?rev=906&view=rev Author: jUrner Date: 2008-08-12 08:44:19 +0000 (Tue, 12 Aug 2008) Log Message: ----------- more css Modified Paths: -------------- trunk/fclient/fclient/impl/res/stylesheets/default.css Modified: trunk/fclient/fclient/impl/res/stylesheets/default.css =================================================================== --- trunk/fclient/fclient/impl/res/stylesheets/default.css 2008-08-12 08:43:51 UTC (rev 905) +++ trunk/fclient/fclient/impl/res/stylesheets/default.css 2008-08-12 08:44:19 UTC (rev 906) @@ -86,8 +86,10 @@ QProgressBar#downloadKey[status="error"]::chunk{ background: qlineargradient(x1: 0, y1: 0.5, x2: 1, y2: 0.5, stop: 0 red, stop: 1 pink); } +QProgressBar#downloadKey[status="compressing"]::chunk{ +background: qlineargradient(x1: 0, y1: 0.5, x2: 1, y2: 0.5, stop: 0 orange, stop: 1 yellow); +} - /* label indicating connected status on statusBar */ QLabel#LabelConnectionConnected{ color: green; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jU...@us...> - 2008-08-12 08:43:44
|
Revision: 905 http://fclient.svn.sourceforge.net/fclient/?rev=905&view=rev Author: jUrner Date: 2008-08-12 08:43:51 +0000 (Tue, 12 Aug 2008) Log Message: ----------- add an uploads widget to play around with Modified Paths: -------------- trunk/fclient/fclient/fclient.py trunk/fclient/fclient/impl/config.py Added Paths: ----------- trunk/fclient/fclient/impl/ViewUploads.py Modified: trunk/fclient/fclient/fclient.py =================================================================== --- trunk/fclient/fclient/fclient.py 2008-08-12 08:42:46 UTC (rev 904) +++ trunk/fclient/fclient/fclient.py 2008-08-12 08:43:51 UTC (rev 905) @@ -18,6 +18,7 @@ from .impl.ViewConnection import ViewConnectionWidget from .impl.ViewDownloads import ViewDownloadsWidget from .impl.ViewLogger import ViewLoggerWidget +from .impl.ViewUploads import ViewUploadsWidget from .impl.DlgSingleAppError import DlgSingleAppError #************************************************************* @@ -78,6 +79,7 @@ ViewConnectionWidget(mainWindow), ViewBrowserWidget(mainWindow), ViewDownloadsWidget(mainWindow), + ViewUploadsWidget(mainWindow), ) viewWidget.addBottomViews(ViewLoggerWidget(mainWindow)) Added: trunk/fclient/fclient/impl/ViewUploads.py =================================================================== --- trunk/fclient/fclient/impl/ViewUploads.py (rev 0) +++ trunk/fclient/fclient/impl/ViewUploads.py 2008-08-12 08:43:51 UTC (rev 905) @@ -0,0 +1,173 @@ + +"""""" + +from __future__ import absolute_import +if __name__ == '__main__': # see --> http://bugs.python.org/issue1510172 . works only current dir and below + import os; __path__ = [os.path.dirname(__file__)] + + +from PyQt4 import QtCore, QtGui + +from . import config +from .BaseRequestsWidget import RequestsWidget +#************************************************************************************ +# +#************************************************************************************ +class UploadsWidgetGlobalFeedback(config.GlobalFeedbackBase): + """wrapper for global statusbar widgets, menus""" + + def __init__(self, parent, idGlobalFeedback): + config.GlobalFeedbackBase.__init__(self, parent, idGlobalFeedback) + + # menus + self.menus = [] + if self.menuBar is not None and hasattr(parent, 'fcViewObject'): + menu = QtGui.QMenu(parent.fcViewObject.displayName, self.menuBar) + parent.populateMenu(menu) + self.menus.append(menu) + self.menuBar.addViewMenu(menu) + + # status bar widgets + self.labelStatus = None + self.progress = None + self.labelFeedbackWrap = None + #if self.statusBar is not None: + # self.labelStatus = QtGui.QLabel(QtCore.QString(), self.statusBar) + # self.statusBar.addWidget(self.labelStatus) + # + # self.progress = QtGui.QProgressBar(self.statusBar) + # self.progress.setRange(0, Browser.MaxProgress) + # self.progress.setValue(0) + # self.statusBar.addWidget(self.progress) + # + # label = QtGui.QLabel(self.statusBar) + # label.setFrameStyle(QtGui.QLabel.Sunken | QtGui.QLabel.Box) + # self.labelFeedbackWrap = pathlabelwrap.PathLabelWrap( + # label, + # path_module=config.CompactPathFcpKeyModule, + # ) + # self.statusBar.addWidget(self.labelFeedbackWrap.label, 1) + + + def setVisible(self, flag): + if self.menuBar is not None: + for menu in self.menus: + menu.children()[0].setEnabled(flag) + #if self.statusBar is not None: + # self.progress.setVisible(flag) + # self.labelStatus.setVisible(flag) + # self.labelFeedbackWrap.label.setVisible(flag) + + #def setProgress(self, n): + # if self.progress is not None: + # self.progress.setValue(n) + + #def setStatusMessage(self, qString): + # if self.labelStatus is not None: + # self.labelStatus.setText(qString) + + #def setFeedback(self, qString): + # if self.labelFeedbackWrap is not None: + # self.labelFeedbackWrap.setPath(unicode(qString)) + + + +class DownloadsViewObject(config.ViewObject): + + def __init__(self, parent): + config.ViewObject. __init__(self, parent) + + self.name=parent.objectName() + self.displayName=self.trUtf8('Uploads') + self.icon=QtGui.QIcon() + + +class UploadsWidgetSettings(config.SettingsBase): + + + _key_ = config.IdViewUploadsWidget + _settings_ = ( + ) + + +class ViewUploadsWidget(RequestsWidget): + + def __init__(self, parent, idGlobalFeedback=config.IdMainWindow): + + self.menuRemoveGroup = None + + RequestsWidget.__init__(self, parent) + + self.setObjectName(config.IdViewUploadsWidget) + config.ObjectRegistry.register(self) + self.fcSettings = UploadsWidgetSettings(self).restore() + self.fcViewObject = DownloadsViewObject(self) + self.fcGlobalFeedback = UploadsWidgetGlobalFeedback(self, idGlobalFeedback) + + # setup menus + self.menuRemoveGroup = QtGui.QMenu(self) + self.menuRemoveGroup.setTitle(self.trUtf8('Remove group')) + for action in self.fcActions['GroupRemoveGroup'].actions(): + self.menuRemoveGroup.addAction(action) + + + ################################### + ## overwritten methods + ################################### + def hideEvent(self, event): + self.fcGlobalFeedback.setVisible(False) + RequestsWidget.hideEvent(self, event) + + def showEvent(self, event): + self.fcGlobalFeedback.setVisible(True) + RequestsWidget.showEvent(self, event) + + def retranslateUi(self, parent): + RequestsWidget.retranslateUi(self, parent) + if self.menuRemoveGroup is not None: + self.menuRemoveGroup.setTitle(self.trUtf8('Remove group')) + + ################################### + ## methods + ################################### + + ################################### + ## event handlers + ################################### + def onTreeCustomContextMenuRequested(self, pt): + tree = self.controlById(self.IdTree) + pt = tree.viewport().mapToGlobal(pt) + + menu = QtGui.QMenu(self) + menu.addMenu(self.menuRemoveGroup) + menu.exec_(pt) + + def onTreeItemSelectionChanged(self): + tree = self.controlById(self.IdTree) + hasSelectedItems = tree.selectionModel().hasSelection() + +#********************************************************************************** +# +#********************************************************************************** +if __name__ == '__main__': + import sys + from . import View + from . import ViewConnection + from . import ViewLogger + from . import MainWindow + + app = QtGui.QApplication(sys.argv) + + mainWindow = MainWindow.MainWindow() + viewWidget = View.ViewWidget(mainWindow) + mainWindow.setCentralWidget(viewWidget) + + viewWidget.addTopViews( + ViewConnection.ViewConnectionWidget(None), + ViewUploadsWidget(None), + ) + viewWidget.addBottomViews(ViewLogger.ViewLoggerWidget(None)) + + mainWindow.show() + res = app.exec_() + sys.exit(res) \ No newline at end of file Modified: trunk/fclient/fclient/impl/config.py =================================================================== --- trunk/fclient/fclient/impl/config.py 2008-08-12 08:42:46 UTC (rev 904) +++ trunk/fclient/fclient/impl/config.py 2008-08-12 08:43:51 UTC (rev 905) @@ -45,6 +45,7 @@ IdViewDownloadsWidget = 'ViewDownloadsWidget' IdViewLoggerWidget = 'ViewDownloadsWidget' IdViewLoggerWidget = 'ViewLoggerWidget' +IdViewUploadsWidget = 'ViewUploadsWidget' IdDlgPrefs = 'DlgPrefs' IdSideBarLoadDetails = 'SideBarLoadDetails' This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jU...@us...> - 2008-08-12 08:42:40
|
Revision: 904 http://fclient.svn.sourceforge.net/fclient/?rev=904&view=rev Author: jUrner Date: 2008-08-12 08:42:46 +0000 (Tue, 12 Aug 2008) Log Message: ----------- bit more work to impl a genaral purpose requests widget Modified Paths: -------------- trunk/fclient/fclient/impl/BaseRequestsWidget.py trunk/fclient/fclient/impl/ViewDownloads.py Modified: trunk/fclient/fclient/impl/BaseRequestsWidget.py =================================================================== --- trunk/fclient/fclient/impl/BaseRequestsWidget.py 2008-08-12 08:41:55 UTC (rev 903) +++ trunk/fclient/fclient/impl/BaseRequestsWidget.py 2008-08-12 08:42:46 UTC (rev 904) @@ -89,6 +89,8 @@ StatusComplete = 'complete' StatusError = 'error' StatusRemoved = 'removed' + StatusCompressing = 'compressing' + ##StatusCompressed = 'compressed' #TODO: no way to distinguish compressed an loading def __init__(self, fcpRequest, *params): QtGui.QTreeWidgetItem.__init__(self, *params) @@ -102,8 +104,16 @@ return self.StatusComplete elif self.fcpRequest['RequestStatus'] & fcp2.ConstRequestStatus.Error: return self.StatusError + + #TODO: more or less aguess ..have to check this in detail elif self.fcpRequest['RequestStatus'] & fcp2.ConstRequestStatus.Started: - return self.StatusLoading + if self.fcpRequest['RequestStatus'] & fcp2.ConstRequestStatus.Compressing: + if self.fcpRequest['RequestStatus'] & fcp2.ConstRequestStatus.Compressed: + return self.StatusLoading + else: + return self.compressing + else: + return self.StatusLoading else: return self.StatusPending @@ -187,6 +197,8 @@ (config.fcpClient.events.RequestProgress, self.onFcpClientRequestProgress), (config.fcpClient.events.RequestStarted, self.onFcpClientRequestStarted), (config.fcpClient.events.RequestRemoved, self.onFcpClientRequestRemoved), + (config.fcpClient.events.RequestCompressionStarted, self.onFcpClientRequestCompressionStarted), + (config.fcpClient.events.RequestCompressionCompleted, self.onFcpClientRequestCompressionCompleted), ) config.fcpClient.events += self.fcpClientEvents @@ -220,6 +232,8 @@ progressBar.setValue(oldProgressBar.value()) elif itemStatus == TreeItem.StatusRemoved: pass + elif itemStatus == TreeItem.StatusCompressing: + progressBar.setRange(0, 0) else: raise ValueError('Unknown status: %r' % itemStatus) if itemStatusChanged: @@ -232,40 +246,6 @@ ) item.fcOldStatus = itemStatus - def _createItemFromFcpRequest(self, fcpRequest): - tree = self.controlById(self.IdTree) - root = tree.invisibleRootItem() - item= TreeItem(fcpRequest, root) - progressBar = ProgressBar(self.tree, item) - - progressBar.setObjectName(TreeItem.ProgressBarName) - tree.setItemWidget(item, TreeItem.IndexProgress, progressBar) - fileName = fcpRequest['Filename'] - mimeType = mimetypes.guess_type(fileName)[0] - icon = config.fcResources.getIcon( - config.mimeTypeIconName(mimeType), - config.fcSettings.value('IconSize'), - config.fcSettings.value('IconTheme'), - ) - item.setIcon(0, icon) - item.setData( - TreeItem.IndexName, - QtCore.Qt.DisplayRole, - QtCore.QVariant(os.path.basename(fcpRequest['Filename'])) - ) - - #TODO: take a wild guess at the size. no other way to do it currently - estimatedSize = int((BLOCK_SIZE * fcpRequest['ProgressRequired']) + 1) - item.setData( - TreeItem.IndexSize, - QtCore.Qt.DisplayRole, - QtCore.QVariant(self.trUtf8('< ') + numbers.format_num_bytes(estimatedSize)), - ) - - self.fcpRequests[fcpRequest['Identifier']] = item - self._adjustItemStatus(item) - return item - ############################ ## ############################ @@ -293,6 +273,8 @@ TreeItem.StatusComplete: self.trUtf8('Complete'), TreeItem.StatusError: self.trUtf8('Error'), TreeItem.StatusRemoved: self.trUtf8('Removed'), + TreeItem.StatusCompressing: self.trUtf8('Compressing'), + ##TreeItem.StatusCompressed: self.trUtf8('Compressed'), #TODO: no way to distinguish compressed an loading } for item in treewidgetwrap.walkItem(root): fcpRequest = getattr(item, 'fcpRequest', None) @@ -328,28 +310,57 @@ ######################################### ## methods ######################################### + #TODO: much... + def addFcpRequest(self, fcpRequest): + """ + @note: if you add a newly created request, make shure to set the requests PersistentUserData + to the result of the call to L{persistentFcpRequestData} + """ + tree = self.controlById(self.IdTree) + root = tree.invisibleRootItem() + item= TreeItem(fcpRequest, root) + progressBar = ProgressBar(self.tree, item) + + progressBar.setObjectName(TreeItem.ProgressBarName) + tree.setItemWidget(item, TreeItem.IndexProgress, progressBar) + fileName = fcpRequest['Filename'] + mimeType = mimetypes.guess_type(fileName)[0] + icon = config.fcResources.getIcon( + config.mimeTypeIconName(mimeType), + config.fcSettings.value('IconSize'), + config.fcSettings.value('IconTheme'), + ) + item.setIcon(0, icon) + item.setData( + TreeItem.IndexName, + QtCore.Qt.DisplayRole, + QtCore.QVariant(os.path.basename(fcpRequest['Filename'])) + ) + + #TODO: take a wild guess at the size. no other way to do it currently + estimatedSize = int((BLOCK_SIZE * fcpRequest['ProgressRequired']) + 1) + item.setData( + TreeItem.IndexSize, + QtCore.Qt.DisplayRole, + QtCore.QVariant(self.trUtf8('< ') + numbers.format_num_bytes(estimatedSize)), + ) + + self.fcpRequests[fcpRequest['Identifier']] = item + self._adjustItemStatus(item) + return item + + self.fcpRequests[fcpRequest['Identifier']] = item + self._adjustItemStatus(item) + return item + + def controlById(idGlobalFeedback, idControl): return getattr(idGlobalFeedback, idControl) - def downloadFile(self, fcpKey, fileName, **kws): - """""" - fileName = unicode(fileName) - fcpRequest = config.fcpClient.getFile( - fcpKey, - fileName, - persistentUserData=PersistentRequestData(ClientName=unicode(self.objectName())).dump(), - #TODO: browser sets this. ok or not? - #handleFilenameCollision=True, - handlePermanentRedirect=True, - **kws - ) - item = self._createItemFromFcpRequest(fcpRequest) - + # overwrite def populateMenu(self, menu): - menu.addAction(self.fcActions['ActionDownloadKeyToDisk']) return menu - def execDlgDownloadKey(self, fcpKey=None): """pops up the dialog to allow the user to download a key to disk @param fcpKey: key to initialize the key with or None @@ -363,6 +374,9 @@ handleFilenameCollision=True, ) + def persistentFcpRequestData(self): + return PersistentRequestData(ClientName=unicode(self.objectName())).dump() + ######################################### ## event handlers ######################################### @@ -456,6 +470,7 @@ def onFcpClientRequestCompleted(self, fcpEvent, fcpRequest): item = self.fcpRequests.get(fcpRequest['Identifier'], None) if item is not None: + mimeType = fcpRequest['MetadataContentType'] item.setData( TreeItem.IndexSize, QtCore.Qt.DisplayRole, @@ -464,10 +479,26 @@ item.setData( TreeItem.IndexMimeType, QtCore.Qt.DisplayRole, - QtCore.QVariant(fcpRequest['MetadataContentType']) + QtCore.QVariant(mimeType) ) + icon = config.fcResources.getIcon( + config.mimeTypeIconName(mimeType), + config.fcSettings.value('IconSize'), + config.fcSettings.value('IconTheme'), + ) + item.setIcon(0, icon) self._adjustItemStatus(item) + def onFcpClientRequestCompressionStarted(self, fcpEvent, fcpRequest): + item = self.fcpRequests.get(fcpRequest['Identifier'], None) + if item is not None: + self._adjustItemStatus(item) + + def onFcpClientRequestCompressionCompleted(self, fcpEvent, fcpRequest): + item = self.fcpRequests.get(fcpRequest['Identifier'], None) + if item is not None: + self._adjustItemStatus(item) + def onFcpClientRequestFailed(self, fcpEvent, fcpRequest): item = self.fcpRequests.get(fcpRequest['Identifier'], None) if item is not None: @@ -511,7 +542,7 @@ pass else: if requestData.get('ClientName', None) == self.objectName(): - item = self._createItemFromFcpRequest(fcpRequest) + item = self.addFcpRequest(fcpRequest) else: item = self.fcpRequests.get(fcpRequest['Identifier'], None) if item is not None: Modified: trunk/fclient/fclient/impl/ViewDownloads.py =================================================================== --- trunk/fclient/fclient/impl/ViewDownloads.py 2008-08-12 08:41:55 UTC (rev 903) +++ trunk/fclient/fclient/impl/ViewDownloads.py 2008-08-12 08:42:46 UTC (rev 904) @@ -8,6 +8,7 @@ from PyQt4 import QtCore, QtGui +from . import config from .BaseRequestsWidget import RequestsWidget #************************************************************************************ # @@ -111,6 +112,9 @@ self.menuRemoveGroup.addAction(action) + ################################### + ## overwritten methods + ################################### def hideEvent(self, event): self.fcGlobalFeedback.setVisible(False) RequestsWidget.hideEvent(self, event) @@ -119,11 +123,35 @@ self.fcGlobalFeedback.setVisible(True) RequestsWidget.showEvent(self, event) + def populateMenu(self, menu): + menu.addAction(self.fcActions['ActionDownloadKeyToDisk']) + return menu + def retranslateUi(self, parent): RequestsWidget.retranslateUi(self, parent) if self.menuRemoveGroup is not None: self.menuRemoveGroup.setTitle(self.trUtf8('Remove group')) + ################################### + ## methods + ################################### + def downloadFile(self, fcpKey, fileName, **kws): + """""" + fileName = unicode(fileName) + fcpRequest = config.fcpClient.getFile( + fcpKey, + fileName, + persistentUserData = self.persistentFcpRequestData(), + #TODO: browser sets this. ok or not? + #handleFilenameCollision=True, + handlePermanentRedirect=True, + **kws + ) + item = self.addFcpRequest(fcpRequest) + + ################################### + ## event handlers + ################################### def onTreeCustomContextMenuRequested(self, pt): tree = self.controlById(self.IdTree) pt = tree.viewport().mapToGlobal(pt) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jU...@us...> - 2008-08-12 08:41:49
|
Revision: 903 http://fclient.svn.sourceforge.net/fclient/?rev=903&view=rev Author: jUrner Date: 2008-08-12 08:41:55 +0000 (Tue, 12 Aug 2008) Log Message: ----------- fix: tell GET and POST requests apart Modified Paths: -------------- trunk/fclient/fclient/impl/SideBarLoadDetails.py trunk/fclient/fclient/impl/ViewBrowser.py Modified: trunk/fclient/fclient/impl/SideBarLoadDetails.py =================================================================== --- trunk/fclient/fclient/impl/SideBarLoadDetails.py 2008-08-11 18:14:30 UTC (rev 902) +++ trunk/fclient/fclient/impl/SideBarLoadDetails.py 2008-08-12 08:41:55 UTC (rev 903) @@ -173,7 +173,7 @@ self.baseUrl = None # setup browser if browser is not None: - self.connect(browser, QtCore.SIGNAL('networkRequestCreated(int, QObject*)'), self.addNetworkReply) + self.connect(browser, QtCore.SIGNAL('networkGetRequestCreated(int, QObject*)'), self.addNetworkReply) self.connect(browser, QtCore.SIGNAL('networkReplyProgress(int, QObject*)'), self.onBrowserNetworkReplyProgress) self.connect(browser, QtCore.SIGNAL('networkReplyError(int, QObject*)'), self.onBrowserNetworkReplyError) self.connect(browser, QtCore.SIGNAL('networkReplyFinished(int, QObject*)'), self.onBrowserNetworkReplyFinished) Modified: trunk/fclient/fclient/impl/ViewBrowser.py =================================================================== --- trunk/fclient/fclient/impl/ViewBrowser.py 2008-08-11 18:14:30 UTC (rev 902) +++ trunk/fclient/fclient/impl/ViewBrowser.py 2008-08-12 08:41:55 UTC (rev 903) @@ -257,7 +257,7 @@ self._networkGetReplies[1].append(networkReplyData) for signal, handler in self._networkReplySignals: self.connect(reply, QtCore.SIGNAL(signal), handler) - self.emit(QtCore.SIGNAL('networkRequestCreated(int, QObject*)'), self._networkGetReplies[0].index(reply), networkReplyData) + self.emit(QtCore.SIGNAL('networkGetRequestCreated(int, QObject*)'), self._networkGetReplies[0].index(reply), networkReplyData) def onNetworkReplyDownloadProgress(self, bytesReceived, bytesTotal): reply = self.sender() @@ -1003,6 +1003,7 @@ #TODO: find a better time to fire up the browser. how do we know when the gui is up and running? QtGui.QApplication.instance().processEvents() self.newBrowser(title=self.trUtf8('Waiting for fproxy')) + QtGui.QApplication.instance().processEvents() self.fcActions['ActionGoToHomePage'].trigger() def viewClose(self): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jU...@us...> - 2008-08-11 18:14:31
|
Revision: 902 http://fclient.svn.sourceforge.net/fclient/?rev=902&view=rev Author: jUrner Date: 2008-08-11 18:14:30 +0000 (Mon, 11 Aug 2008) Log Message: ----------- isolating requests widget pt2 Modified Paths: -------------- trunk/fclient/fclient/impl/ViewDownloads.py Added Paths: ----------- trunk/fclient/fclient/impl/BaseRequestsWidget.py Added: trunk/fclient/fclient/impl/BaseRequestsWidget.py =================================================================== --- trunk/fclient/fclient/impl/BaseRequestsWidget.py (rev 0) +++ trunk/fclient/fclient/impl/BaseRequestsWidget.py 2008-08-11 18:14:30 UTC (rev 902) @@ -0,0 +1,523 @@ + +#************************************************************************************************************** +#TODO: +# +# x. prtty tricky to get dls right when the node or client may disconnect unexpectedly +# problem: dls that we send and that have not reached the node +# problem: what to do when the user wants to quit and we still have dls to push to the node +# +# solution would require keeping track of all requests +# a. keep identifiers of requests that reached the node (have to do it anyways) +# b. keep track of requests ahead of sending them to the node (feels not too good doubeling downloads.dat.gz) +# +# best idea seems to be to ignore the problem +# 1. wait till (if ever) freenet devels fdrop node keeping track of client requests +# +# 2. a box thrown to the user (x. do not show this message again) to inform him about pendings +# should be enough. maybe along with a separate widget or some separate color code for pendings +# +# x. performance +# start with a standard model and improve it over time. no need to set any hard +# limits. the user will find out by himself how many dls his machine can handle. +# have to be carefrul though when adding dls, like from a *.frdx to provide appropriate +# warnings +# x. it may take a while untill the final DataFound message arrives when a request is % completed. feedback would be nice +# x. DataFound for a request the file has been removed by the user. no idea what happens. have to test this +# x. when the node is about to start up, looks like persistents may arrive or not. check +# x. how to get early information about mimetype/size? maybe use FcpClient.getFileInfo() +# x. show/hide header izems +# x. sort by header +# x. indicate over all time / dl speed +# x. indicate status / remove items by status +# x. item properties +# x. how to handle inserting huge number of dls? +# idea: insert with lowest priority to get the node to know them, increase priority when a slot in +# MaxSimultaneousDls (if set) is free. atatch progressBar no sooner as priority > MinDlPriority +# x. how to handle huge numbers of dls. the node will flood us on startup with persistents. looks +# like the only way to control the flood is to have one connection/dl. maybe wait for freenet devels +# to realize that this is a serious problem... +# x. byte amount postfixes must be transllated ++ use Kib or Kb or let the user decide? +# x. sometimes groups of dls get not removed +#************************************************************************************************************** +from __future__ import absolute_import +if __name__ == '__main__': # see --> http://bugs.python.org/issue1510172 . works only current dir and below + import os; __path__ = [os.path.dirname(__file__)] + +import mimetypes +import os +from PyQt4 import QtCore, QtGui + +from . import config +from .lib import fcp2 +from .lib.fcp2.lib import pmstruct +from .lib.qt4ex import treewidgetwrap +from .lib import numbers + +from . import DlgDownloadKeyToDisk + +from .tpls.Ui_ViewRequestsWidgetTpl import Ui_ViewRequestsWidget +#********************************************************************************** +# +#********************************************************************************** +BLOCK_SIZE = 32768 # from CHKBlock.java + +#********************************************************************************** +# +#********************************************************************************** +class PersistentRequestData(pmstruct.PMStruct): + _fields_ = ( + ('ClientName', pmstruct.STRING), + ) + +#********************************************************************************** +# +#********************************************************************************** +class TreeItem(QtGui.QTreeWidgetItem): + + IndexName = 0 + IndexSize = 1 + IndexMimeType = 2 + IndexStatus = 3 + IndexProgress = 4 + IndexPriority = 5 + IndexElapsed = 6 + + ProgressBarName = 'downloadKey' + + StatusPending = 'pending' + StatusLoading = 'loading' + StatusComplete = 'complete' + StatusError = 'error' + StatusRemoved = 'removed' + + def __init__(self, fcpRequest, *params): + QtGui.QTreeWidgetItem.__init__(self, *params) + self.fcpRequest = fcpRequest + self.fcOldStatus = self.StatusPending + + def status(self): + if self.fcpRequest is None: + return self.StatusRemoved + elif self.fcpRequest['RequestStatus'] & fcp2.ConstRequestStatus.Success: + return self.StatusComplete + elif self.fcpRequest['RequestStatus'] & fcp2.ConstRequestStatus.Error: + return self.StatusError + elif self.fcpRequest['RequestStatus'] & fcp2.ConstRequestStatus.Started: + return self.StatusLoading + else: + return self.StatusPending + +# exposes status property for stylesheets +class ProgressBar(QtGui.QProgressBar): + + def __init__(self, parent, item): + QtGui.QProgressBar.__init__(self, parent) + self.item = item + + def _get_status(self): + return self.item.status() + status= QtCore.pyqtProperty("QString", _get_status) + + +class RequestsWidgetActions(config.ActionsBase): + + def __init__(self, parent): + config.ActionsBase.__init__(self, parent) + + self.action( + name='ActionDownloadKeyToDisk', + text=self.trUtf8('Download &key...'), + trigger=parent.onDlgDownloadKey, + ) + self.action( + name='ActionRemoveSelectedDownloads', + text=self.trUtf8('Remove download'), + trigger=parent.onRemoveSelectedDownloads, + isEnabled=False, + ) + self.action( + name='ActionRestartSelectedDownloads', + text=self.trUtf8('Restart download'), + trigger=parent.onRestartSelectedDownloads, + isEnabled=False, + ) + + #TODO: enable/disable if items of that type are available? + group = self.group( + name='GroupRemoveGroup', + trigger=parent.onRemoveGroup, + ) + self.action( + name='ActionRemoveFailed', + group=group, + text=self.trUtf8('Failed'), + isEnabled=False, + ) + self.action( + name='ActionRemoveCompleted', + group=group, + text=self.trUtf8('Completed'), + isEnabled=False, + ) + +#********************************************************************************** +# +#********************************************************************************** +class RequestsWidget(QtGui.QWidget, Ui_ViewRequestsWidget): + + IdTree = 'tree' + + def __init__(self, parent, idGlobalFeedback=config.IdMainWindow): + QtGui.QWidget.__init__(self, parent) + self._isCreated = False + self.fcHeaderLabels = {} # fcpIdentifier --> treeItem + self.fcActions = RequestsWidgetActions(self) + self.fcpRequests = {} + self.fcRequestStatusNames = {} + self.menuRemoveGroup = QtGui.QMenu(self) + + self.setupUi(self) + self.fcpClientEvents = ( + (config.fcpClient.events.ClientConnected, self.onFcpClientConnected), + (config.fcpClient.events.ClientDisconnected, self.onFcpClientDisconnected), + (config.fcpClient.events.ConfigData, self.onFcpConfigData), + (config.fcpClient.events.RequestCompleted, self.onFcpClientRequestCompleted), + (config.fcpClient.events.RequestFailed, self.onFcpClientRequestFailed), + (config.fcpClient.events.RequestModified, self.onFcpClientRequestModified), + (config.fcpClient.events.RequestProgress, self.onFcpClientRequestProgress), + (config.fcpClient.events.RequestStarted, self.onFcpClientRequestStarted), + (config.fcpClient.events.RequestRemoved, self.onFcpClientRequestRemoved), + ) + config.fcpClient.events += self.fcpClientEvents + + + ############################ + ## private methods + ############################ + def _adjustItemStatus(self, item): + # to take Css styling into account we have to set a new statusBar for each state change + tree = self.controlById(self.IdTree) + oldProgressBar = progressBar = self.tree.itemWidget(item, TreeItem.IndexProgress) + itemStatus = item.status() + itemStatusChanged = itemStatus != item.fcOldStatus + if itemStatusChanged: + progressBar = ProgressBar(self.tree, item) + + # adjust statusBar and set a new one if necessary + # ..bit much work here, but necessary, cos Fcp might come up with + # ..a completed message without any prior progress notifications + if itemStatus == TreeItem.StatusPending: + progressBar.setRange(0, 0) + elif itemStatus == TreeItem.StatusLoading: + progressBar.setRange(0, item.fcpRequest['ProgressRequired']) + progressBar.setValue(item.fcpRequest['ProgressSucceeded']) + elif itemStatus == TreeItem.StatusComplete: + progressBar.setRange(0, 1) + progressBar.setValue(progressBar.maximum()) + elif itemStatus == TreeItem.StatusError: + progressBar.setMinimum(oldProgressBar.minimum()) + progressBar.setMaximum(oldProgressBar.maximum()) + progressBar.setValue(oldProgressBar.value()) + elif itemStatus == TreeItem.StatusRemoved: + pass + else: + raise ValueError('Unknown status: %r' % itemStatus) + if itemStatusChanged: + progressBar.setObjectName(TreeItem.ProgressBarName) + tree.setItemWidget(item, TreeItem.IndexProgress, progressBar) + item.setData( + TreeItem.IndexStatus, + QtCore.Qt.DisplayRole, + QtCore.QVariant(self.fcRequestStatusNames[itemStatus]), + ) + item.fcOldStatus = itemStatus + + def _createItemFromFcpRequest(self, fcpRequest): + tree = self.controlById(self.IdTree) + root = tree.invisibleRootItem() + item= TreeItem(fcpRequest, root) + progressBar = ProgressBar(self.tree, item) + + progressBar.setObjectName(TreeItem.ProgressBarName) + tree.setItemWidget(item, TreeItem.IndexProgress, progressBar) + fileName = fcpRequest['Filename'] + mimeType = mimetypes.guess_type(fileName)[0] + icon = config.fcResources.getIcon( + config.mimeTypeIconName(mimeType), + config.fcSettings.value('IconSize'), + config.fcSettings.value('IconTheme'), + ) + item.setIcon(0, icon) + item.setData( + TreeItem.IndexName, + QtCore.Qt.DisplayRole, + QtCore.QVariant(os.path.basename(fcpRequest['Filename'])) + ) + + #TODO: take a wild guess at the size. no other way to do it currently + estimatedSize = int((BLOCK_SIZE * fcpRequest['ProgressRequired']) + 1) + item.setData( + TreeItem.IndexSize, + QtCore.Qt.DisplayRole, + QtCore.QVariant(self.trUtf8('< ') + numbers.format_num_bytes(estimatedSize)), + ) + + self.fcpRequests[fcpRequest['Identifier']] = item + self._adjustItemStatus(item) + return item + + ############################ + ## + ############################ + def retranslateUi(self, parent): + Ui_ViewRequestsWidget.retranslateUi(self, parent) + tree = self.controlById(self.IdTree) + root = tree.invisibleRootItem() + + # adjust header labels + self.fcHeaderLabels = { + TreeItem.IndexName: self.trUtf8('Name'), + TreeItem.IndexSize: self.trUtf8('Size'), + TreeItem.IndexMimeType: self.trUtf8('MimeType'), + TreeItem.IndexStatus: self.trUtf8('Status'), + TreeItem.IndexPriority: self.trUtf8('Priority'), + TreeItem.IndexProgress: self.trUtf8('Progress'), + TreeItem.IndexElapsed: self.trUtf8('Elapsed'), + } + tree.setHeaderLabels([i[1] for i in sorted(self.fcHeaderLabels.items())]) + + # adjust status names and retranslate all items + self.fcRequestStatusNames = { + TreeItem.StatusPending: self.trUtf8('Pending'), + TreeItem.StatusLoading: self.trUtf8('Loading'), + TreeItem.StatusComplete: self.trUtf8('Complete'), + TreeItem.StatusError: self.trUtf8('Error'), + TreeItem.StatusRemoved: self.trUtf8('Removed'), + } + for item in treewidgetwrap.walkItem(root): + fcpRequest = getattr(item, 'fcpRequest', None) + if hasattr(item, 'fcpRequest'): + item.setText(TreeItem.IndexStatus, self.fcRequestStatusNames[item.status()]) + + # others + self.menuRemoveGroup.setTitle(self.trUtf8('Remove group')) + + def closeEvent(self): + self.viewClose() + + def hideEvent(self, event): + self.fcGlobalFeedback.setVisible(False) + + def showEvent(self, event): + self.fcGlobalFeedback.setVisible(True) + if not self._isCreated: + self._isCreated = True + + # setup tree + tree = self.controlById(self.IdTree) + tree.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) + tree.setRootIsDecorated(False) + tree.setSelectionMode(tree.ExtendedSelection) + tree.setUniformRowHeights(True) + self.connect(tree, QtCore.SIGNAL('customContextMenuRequested(const QPoint &)'), self.onTreeCustomContextMenuRequested) + self.connect(tree, QtCore.SIGNAL('itemSelectionChanged() '), self.onTreeItemSelectionChanged) + + def viewClose(self): + config.fcpClient.events -= self.fcpClientEvents + + ######################################### + ## methods + ######################################### + def controlById(idGlobalFeedback, idControl): + return getattr(idGlobalFeedback, idControl) + + def downloadFile(self, fcpKey, fileName, **kws): + """""" + fileName = unicode(fileName) + fcpRequest = config.fcpClient.getFile( + fcpKey, + fileName, + persistentUserData=PersistentRequestData(ClientName=unicode(self.objectName())).dump(), + #TODO: browser sets this. ok or not? + #handleFilenameCollision=True, + handlePermanentRedirect=True, + **kws + ) + item = self._createItemFromFcpRequest(fcpRequest) + + def populateMenu(self, menu): + menu.addAction(self.fcActions['ActionDownloadKeyToDisk']) + return menu + + + def execDlgDownloadKey(self, fcpKey=None): + """pops up the dialog to allow the user to download a key to disk + @param fcpKey: key to initialize the key with or None + """ + dlg = DlgDownloadKeyToDisk.DlgDownloadKeyToDisk(self, fcpKey=fcpKey) + if dlg.exec_() == dlg.Accepted: + self.downloadFile( + dlg.fcpKey(), + dlg.fileName(), + persistence=fcp2.ConstPersistence.Forever, + handleFilenameCollision=True, + ) + + ######################################### + ## event handlers + ######################################### + def onDlgDownloadKey(self, action): + self.execDlgDownloadKey(fcpKey=None) + + def onRemoveSelectedDownloads(self, action): + tree = self.controlById(self.IdTree) + selectedItems = tree.selectedItems() + + # remove items + for item in selectedItems: + parent = item.parent() + if parent is None: + parent = tree.invisibleRootItem() + parent.removeChild(item) + + # cancel all requests + for item in selectedItems: + for tmp_item in treewidgetwrap.walkItem(item): + if tmp_item.fcpRequest is not None: # we may come across the same item multiple times + if tmp_item.fcpRequest['Identifier'] in self.fcpRequests: #TODO: should never be False?! check + del self.fcpRequests[tmp_item.fcpRequest['Identifier']] + config.fcpClient.removeRequest(tmp_item.fcpRequest) + tmp_item.fcpRequest = None + + def onRestartSelectedDownloads(self, action): + tree = self.controlById(self.IdTree) + for item in tree.selectedItems(): + if item.fcpRequest is None: + raise RuntimeError('fcpRequest is None. should not happen') + del self.fcpRequests[item.fcpRequest['Identifier']] + item.fcpRequest = config.fcpClient.resendRequest(item.fcpRequest) + self.fcpRequests[item.fcpRequest['Identifier']] = item + self._adjustItemStatus(item) + + def onRemoveGroup(self, action): + tree = self.controlById(self.IdTree) + root = tree.invisibleRootItem() + + if action == self.fcActions['ActionRemoveCompleted']: + flag = fcp2.ConstRequestStatus.Success + elif action == self.fcActions['ActionRemoveFailed']: + flag = fcp2.ConstRequestStatus.Error + else: + raise ValueError('Not implemented') + + for item in treewidgetwrap.walkItem(root, topdown=False): + fcpRequest = getattr(item, 'fcpRequest', None) + if fcpRequest is not None: + if fcpRequest['Identifier'] in self.fcpRequests: #TODO: should never be False?! check + del self.fcpRequests[fcpRequest['Identifier']] + + if fcpRequest['RequestStatus'] & fcp2.ConstRequestStatus.Removed: + pass + elif not fcpRequest['RequestStatus'] & flag: + continue + else: + item.fcpRequest = None + config.fcpClient.removeRequest(fcpRequest) + parent = item.parent() + if parent is None: + parent = root + parent.removeChild(item) + + + # overwrite + def onTreeCustomContextMenuRequested(self, pt): + pass + + # overwrite + def onTreeItemSelectionChanged(self): + pass + + ######################################### + ## fcp event handlers + ######################################### + def onFcpClientConnected(self, event, msg): + for action in self.fcActions: + action.setEnabled(True) + + + def onFcpClientDisconnected(self, event, msg): + for action in self.fcActions: + action.setEnabled(False) + + def onFcpConfigData(self, fcpEvent, fcpRequest): + pass + + + def onFcpClientRequestCompleted(self, fcpEvent, fcpRequest): + item = self.fcpRequests.get(fcpRequest['Identifier'], None) + if item is not None: + item.setData( + TreeItem.IndexSize, + QtCore.Qt.DisplayRole, + QtCore.QVariant(numbers.format_num_bytes(fcpRequest['MetadataSize'])) + ) + item.setData( + TreeItem.IndexMimeType, + QtCore.Qt.DisplayRole, + QtCore.QVariant(fcpRequest['MetadataContentType']) + ) + self._adjustItemStatus(item) + + def onFcpClientRequestFailed(self, fcpEvent, fcpRequest): + item = self.fcpRequests.get(fcpRequest['Identifier'], None) + if item is not None: + self._adjustItemStatus(item) + + #TODO: not tested + def onFcpClientRequestModified(self, fcpEvent, fcpRequest): + + requestIdentifier = fcpRequest['Modified'].get(fcp2.ConstRequestModified.Identifier, None) + if requestIdentifier is None: + requestIdentifier = fcpRequest['Identifier'] + item = self.fcpRequests.get(requestIdentifier, None) + + if item is not None: + if fcp2.ConstRequestModified.Identifier in fcpRequest['Modified']: + newFcpIdentifier = fcpRequest['Identifier'] + del self.fcpRequests[requestIdentifier] + self.fcpRequests[newFcpIdentifier] = item + + if fcp2.ConstRequestModified.Filename in fcpRequest['Modified']: + item.setData( + TreeItem.IndexName, + QtCore.Qt.DisplayRole, + QtCore.QVariant(os.path.basename(fcpRequest['Filename'])) + ) + + + def onFcpClientRequestProgress(self, fcpEvent, fcpRequest): + item = self.fcpRequests.get(fcpRequest['Identifier'], None) + if item is not None: + self._adjustItemStatus(item) + + def onFcpClientRequestRemoved(self, fcpEvent, fcpRequest): + pass + + def onFcpClientRequestStarted(self, fcpEvent, fcpRequest): + if fcpRequest['RequestStatus'] & fcp2.ConstRequestStatus.Restored: + try: + requestData = PersistentRequestData.load(fcpRequest['PersistentUserData']) + except pmstruct.PMStructError: + pass + else: + if requestData.get('ClientName', None) == self.objectName(): + item = self._createItemFromFcpRequest(fcpRequest) + else: + item = self.fcpRequests.get(fcpRequest['Identifier'], None) + if item is not None: + self._adjustItemStatus(item) + + +#********************************************************************************** +# +#********************************************************************************** Modified: trunk/fclient/fclient/impl/ViewDownloads.py =================================================================== --- trunk/fclient/fclient/impl/ViewDownloads.py 2008-08-11 17:59:02 UTC (rev 901) +++ trunk/fclient/fclient/impl/ViewDownloads.py 2008-08-11 18:14:30 UTC (rev 902) @@ -1,527 +1,17 @@ """""" -#************************************************************************************************************** -#TODO: -# -# x. prtty tricky to get dls right when the node or client may disconnect unexpectedly -# problem: dls that we send and that have not reached the node -# problem: what to do when the user wants to quit and we still have dls to push to the node -# -# solution would require keeping track of all requests -# a. keep identifiers of requests that reached the node (have to do it anyways) -# b. keep track of requests ahead of sending them to the node (feels not too good doubeling downloads.dat.gz) -# -# best idea seems to be to ignore the problem -# 1. wait till (if ever) freenet devels fdrop node keeping track of client requests -# -# 2. a box thrown to the user (x. do not show this message again) to inform him about pendings -# should be enough. maybe along with a separate widget or some separate color code for pendings -# -# x. performance -# start with a standard model and improve it over time. no need to set any hard -# limits. the user will find out by himself how many dls his machine can handle. -# have to be carefrul though when adding dls, like from a *.frdx to provide appropriate -# warnings -# x. it may take a while untill the final DataFound message arrives when a request is % completed. feedback would be nice -# x. DataFound for a request the file has been removed by the user. no idea what happens. have to test this -# x. when the node is about to start up, looks like persistents may arrive or not. check -# x. how to get early information about mimetype/size? maybe use FcpClient.getFileInfo() -# x. show/hide header izems -# x. sort by header -# x. indicate over all time / dl speed -# x. indicate status / remove items by status -# x. item properties -# x. how to handle inserting huge number of dls? -# idea: insert with lowest priority to get the node to know them, increase priority when a slot in -# MaxSimultaneousDls (if set) is free. atatch progressBar no sooner as priority > MinDlPriority -# x. how to handle huge numbers of dls. the node will flood us on startup with persistents. looks -# like the only way to control the flood is to have one connection/dl. maybe wait for freenet devels -# to realize that this is a serious problem... -# x. byte amount postfixes must be transllated ++ use Kib or Kb or let the user decide? -# x. sometimes groups of dls get not removed -#************************************************************************************************************** + from __future__ import absolute_import if __name__ == '__main__': # see --> http://bugs.python.org/issue1510172 . works only current dir and below import os; __path__ = [os.path.dirname(__file__)] + -import mimetypes -import os from PyQt4 import QtCore, QtGui -from . import config -from .lib import fcp2 -from .lib.fcp2.lib import pmstruct -from .lib.qt4ex import treewidgetwrap -from .lib import numbers - -from . import DlgDownloadKeyToDisk - -from .tpls.Ui_ViewRequestsWidgetTpl import Ui_ViewRequestsWidget -#********************************************************************************** +from .BaseRequestsWidget import RequestsWidget +#************************************************************************************ # -#********************************************************************************** -BLOCK_SIZE = 32768 # from CHKBlock.java - -#********************************************************************************** -# -#********************************************************************************** -class PersistentRequestData(pmstruct.PMStruct): - _fields_ = ( - ('ClientName', pmstruct.STRING), - ) - -#********************************************************************************** -# -#********************************************************************************** -class TreeItem(QtGui.QTreeWidgetItem): - - IndexName = 0 - IndexSize = 1 - IndexMimeType = 2 - IndexStatus = 3 - IndexProgress = 4 - IndexPriority = 5 - IndexElapsed = 6 - - ProgressBarName = 'downloadKey' - - StatusPending = 'pending' - StatusLoading = 'loading' - StatusComplete = 'complete' - StatusError = 'error' - StatusRemoved = 'removed' - - def __init__(self, fcpRequest, *params): - QtGui.QTreeWidgetItem.__init__(self, *params) - self.fcpRequest = fcpRequest - self.fcOldStatus = self.StatusPending - - def status(self): - if self.fcpRequest is None: - return self.StatusRemoved - elif self.fcpRequest['RequestStatus'] & fcp2.ConstRequestStatus.Success: - return self.StatusComplete - elif self.fcpRequest['RequestStatus'] & fcp2.ConstRequestStatus.Error: - return self.StatusError - elif self.fcpRequest['RequestStatus'] & fcp2.ConstRequestStatus.Started: - return self.StatusLoading - else: - return self.StatusPending - -# exposes status property for stylesheets -class ProgressBar(QtGui.QProgressBar): - - def __init__(self, parent, item): - QtGui.QProgressBar.__init__(self, parent) - self.item = item - - def _get_status(self): - return self.item.status() - status= QtCore.pyqtProperty("QString", _get_status) - - -class RequestsWidgetActions(config.ActionsBase): - - def __init__(self, parent): - config.ActionsBase.__init__(self, parent) - - self.action( - name='ActionDownloadKeyToDisk', - text=self.trUtf8('Download &key...'), - trigger=parent.onDlgDownloadKey, - ) - self.action( - name='ActionRemoveSelectedDownloads', - text=self.trUtf8('Remove download'), - trigger=parent.onRemoveSelectedDownloads, - isEnabled=False, - ) - self.action( - name='ActionRestartSelectedDownloads', - text=self.trUtf8('Restart download'), - trigger=parent.onRestartSelectedDownloads, - isEnabled=False, - ) - - #TODO: enable/disable if items of that type are available? - group = self.group( - name='GroupRemoveGroup', - trigger=parent.onRemoveGroup, - ) - self.action( - name='ActionRemoveFailed', - group=group, - text=self.trUtf8('Failed'), - isEnabled=False, - ) - self.action( - name='ActionRemoveCompleted', - group=group, - text=self.trUtf8('Completed'), - isEnabled=False, - ) - -#********************************************************************************** -# -#********************************************************************************** -class RequestsWidget(QtGui.QWidget, Ui_ViewRequestsWidget): - - IdTree = 'tree' - - def __init__(self, parent, idGlobalFeedback=config.IdMainWindow): - QtGui.QWidget.__init__(self, parent) - self._isCreated = False - self.fcHeaderLabels = {} # fcpIdentifier --> treeItem - self.fcActions = RequestsWidgetActions(self) - self.fcpRequests = {} - self.fcRequestStatusNames = {} - self.menuRemoveGroup = QtGui.QMenu(self) - - self.setupUi(self) - self.fcpClientEvents = ( - (config.fcpClient.events.ClientConnected, self.onFcpClientConnected), - (config.fcpClient.events.ClientDisconnected, self.onFcpClientDisconnected), - (config.fcpClient.events.ConfigData, self.onFcpConfigData), - (config.fcpClient.events.RequestCompleted, self.onFcpClientRequestCompleted), - (config.fcpClient.events.RequestFailed, self.onFcpClientRequestFailed), - (config.fcpClient.events.RequestModified, self.onFcpClientRequestModified), - (config.fcpClient.events.RequestProgress, self.onFcpClientRequestProgress), - (config.fcpClient.events.RequestStarted, self.onFcpClientRequestStarted), - (config.fcpClient.events.RequestRemoved, self.onFcpClientRequestRemoved), - ) - config.fcpClient.events += self.fcpClientEvents - - - ############################ - ## private methods - ############################ - def _adjustItemStatus(self, item): - # to take Css styling into account we have to set a new statusBar for each state change - tree = self.controlById(self.IdTree) - oldProgressBar = progressBar = self.tree.itemWidget(item, TreeItem.IndexProgress) - itemStatus = item.status() - itemStatusChanged = itemStatus != item.fcOldStatus - if itemStatusChanged: - progressBar = ProgressBar(self.tree, item) - - # adjust statusBar and set a new one if necessary - # ..bit much work here, but necessary, cos Fcp might come up with - # ..a completed message without any prior progress notifications - if itemStatus == TreeItem.StatusPending: - progressBar.setRange(0, 0) - elif itemStatus == TreeItem.StatusLoading: - progressBar.setRange(0, item.fcpRequest['ProgressRequired']) - progressBar.setValue(item.fcpRequest['ProgressSucceeded']) - elif itemStatus == TreeItem.StatusComplete: - progressBar.setRange(0, 1) - progressBar.setValue(progressBar.maximum()) - elif itemStatus == TreeItem.StatusError: - progressBar.setMinimum(oldProgressBar.minimum()) - progressBar.setMaximum(oldProgressBar.maximum()) - progressBar.setValue(oldProgressBar.value()) - elif itemStatus == TreeItem.StatusRemoved: - pass - else: - raise ValueError('Unknown status: %r' % itemStatus) - if itemStatusChanged: - progressBar.setObjectName(TreeItem.ProgressBarName) - tree.setItemWidget(item, TreeItem.IndexProgress, progressBar) - item.setData( - TreeItem.IndexStatus, - QtCore.Qt.DisplayRole, - QtCore.QVariant(self.fcRequestStatusNames[itemStatus]), - ) - item.fcOldStatus = itemStatus - - def _createItemFromFcpRequest(self, fcpRequest): - tree = self.controlById(self.IdTree) - root = tree.invisibleRootItem() - item= TreeItem(fcpRequest, root) - progressBar = ProgressBar(self.tree, item) - - progressBar.setObjectName(TreeItem.ProgressBarName) - tree.setItemWidget(item, TreeItem.IndexProgress, progressBar) - fileName = fcpRequest['Filename'] - mimeType = mimetypes.guess_type(fileName)[0] - icon = config.fcResources.getIcon( - config.mimeTypeIconName(mimeType), - config.fcSettings.value('IconSize'), - config.fcSettings.value('IconTheme'), - ) - item.setIcon(0, icon) - item.setData( - TreeItem.IndexName, - QtCore.Qt.DisplayRole, - QtCore.QVariant(os.path.basename(fcpRequest['Filename'])) - ) - - #TODO: take a wild guess at the size. no other way to do it currently - estimatedSize = int((BLOCK_SIZE * fcpRequest['ProgressRequired']) + 1) - item.setData( - TreeItem.IndexSize, - QtCore.Qt.DisplayRole, - QtCore.QVariant(self.trUtf8('< ') + numbers.format_num_bytes(estimatedSize)), - ) - - self.fcpRequests[fcpRequest['Identifier']] = item - self._adjustItemStatus(item) - return item - - ############################ - ## - ############################ - def retranslateUi(self, parent): - Ui_ViewRequestsWidget.retranslateUi(self, parent) - tree = self.controlById(self.IdTree) - root = tree.invisibleRootItem() - - # adjust header labels - self.fcHeaderLabels = { - TreeItem.IndexName: self.trUtf8('Name'), - TreeItem.IndexSize: self.trUtf8('Size'), - TreeItem.IndexMimeType: self.trUtf8('MimeType'), - TreeItem.IndexStatus: self.trUtf8('Status'), - TreeItem.IndexPriority: self.trUtf8('Priority'), - TreeItem.IndexProgress: self.trUtf8('Progress'), - TreeItem.IndexElapsed: self.trUtf8('Elapsed'), - } - tree.setHeaderLabels([i[1] for i in sorted(self.fcHeaderLabels.items())]) - - # adjust status names and retranslate all items - self.fcRequestStatusNames = { - TreeItem.StatusPending: self.trUtf8('Pending'), - TreeItem.StatusLoading: self.trUtf8('Loading'), - TreeItem.StatusComplete: self.trUtf8('Complete'), - TreeItem.StatusError: self.trUtf8('Error'), - TreeItem.StatusRemoved: self.trUtf8('Removed'), - } - for item in treewidgetwrap.walkItem(root): - fcpRequest = getattr(item, 'fcpRequest', None) - if hasattr(item, 'fcpRequest'): - item.setText(TreeItem.IndexStatus, self.fcRequestStatusNames[item.status()]) - - # others - self.menuRemoveGroup.setTitle(self.trUtf8('Remove group')) - - def closeEvent(self): - self.viewClose() - - def hideEvent(self, event): - self.fcGlobalFeedback.setVisible(False) - - def showEvent(self, event): - self.fcGlobalFeedback.setVisible(True) - if not self._isCreated: - self._isCreated = True - - # setup tree - tree = self.controlById(self.IdTree) - tree.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) - tree.setRootIsDecorated(False) - tree.setSelectionMode(tree.ExtendedSelection) - tree.setUniformRowHeights(True) - self.connect(tree, QtCore.SIGNAL('customContextMenuRequested(const QPoint &)'), self.onTreeCustomContextMenuRequested) - self.connect(tree, QtCore.SIGNAL('itemSelectionChanged() '), self.onTreeItemSelectionChanged) - - def viewClose(self): - config.fcpClient.events -= self.fcpClientEvents - - ######################################### - ## methods - ######################################### - def controlById(idGlobalFeedback, idControl): - return getattr(idGlobalFeedback, idControl) - - def downloadFile(self, fcpKey, fileName, **kws): - """""" - fileName = unicode(fileName) - fcpRequest = config.fcpClient.getFile( - fcpKey, - fileName, - persistentUserData=PersistentRequestData(ClientName=unicode(self.objectName())).dump(), - #TODO: browser sets this. ok or not? - #handleFilenameCollision=True, - handlePermanentRedirect=True, - **kws - ) - item = self._createItemFromFcpRequest(fcpRequest) - - def populateMenu(self, menu): - menu.addAction(self.fcActions['ActionDownloadKeyToDisk']) - return menu - - - def execDlgDownloadKey(self, fcpKey=None): - """pops up the dialog to allow the user to download a key to disk - @param fcpKey: key to initialize the key with or None - """ - dlg = DlgDownloadKeyToDisk.DlgDownloadKeyToDisk(self, fcpKey=fcpKey) - if dlg.exec_() == dlg.Accepted: - self.downloadFile( - dlg.fcpKey(), - dlg.fileName(), - persistence=fcp2.ConstPersistence.Forever, - handleFilenameCollision=True, - ) - - ######################################### - ## event handlers - ######################################### - def onDlgDownloadKey(self, action): - self.execDlgDownloadKey(fcpKey=None) - - def onRemoveSelectedDownloads(self, action): - tree = self.controlById(self.IdTree) - selectedItems = tree.selectedItems() - - # remove items - for item in selectedItems: - parent = item.parent() - if parent is None: - parent = tree.invisibleRootItem() - parent.removeChild(item) - - # cancel all requests - for item in selectedItems: - for tmp_item in treewidgetwrap.walkItem(item): - if tmp_item.fcpRequest is not None: # we may come across the same item multiple times - if tmp_item.fcpRequest['Identifier'] in self.fcpRequests: #TODO: should never be False?! check - del self.fcpRequests[tmp_item.fcpRequest['Identifier']] - config.fcpClient.removeRequest(tmp_item.fcpRequest) - tmp_item.fcpRequest = None - - def onRestartSelectedDownloads(self, action): - tree = self.controlById(self.IdTree) - for item in tree.selectedItems(): - if item.fcpRequest is None: - raise RuntimeError('fcpRequest is None. should not happen') - del self.fcpRequests[item.fcpRequest['Identifier']] - item.fcpRequest = config.fcpClient.resendRequest(item.fcpRequest) - self.fcpRequests[item.fcpRequest['Identifier']] = item - self._adjustItemStatus(item) - - def onRemoveGroup(self, action): - tree = self.controlById(self.IdTree) - root = tree.invisibleRootItem() - - if action == self.fcActions['ActionRemoveCompleted']: - flag = fcp2.ConstRequestStatus.Success - elif action == self.fcActions['ActionRemoveFailed']: - flag = fcp2.ConstRequestStatus.Error - else: - raise ValueError('Not implemented') - - for item in treewidgetwrap.walkItem(root, topdown=False): - fcpRequest = getattr(item, 'fcpRequest', None) - if fcpRequest is not None: - if fcpRequest['Identifier'] in self.fcpRequests: #TODO: should never be False?! check - del self.fcpRequests[fcpRequest['Identifier']] - - if fcpRequest['RequestStatus'] & fcp2.ConstRequestStatus.Removed: - pass - elif not fcpRequest['RequestStatus'] & flag: - continue - else: - item.fcpRequest = None - config.fcpClient.removeRequest(fcpRequest) - parent = item.parent() - if parent is None: - parent = root - parent.removeChild(item) - - - # overwrite - def onTreeCustomContextMenuRequested(self, pt): - pass - - # overwrite - def onTreeItemSelectionChanged(self): - pass - - ######################################### - ## fcp event handlers - ######################################### - def onFcpClientConnected(self, event, msg): - for action in self.fcActions: - action.setEnabled(True) - - - def onFcpClientDisconnected(self, event, msg): - for action in self.fcActions: - action.setEnabled(False) - - def onFcpConfigData(self, fcpEvent, fcpRequest): - pass - - - def onFcpClientRequestCompleted(self, fcpEvent, fcpRequest): - item = self.fcpRequests.get(fcpRequest['Identifier'], None) - if item is not None: - item.setData( - TreeItem.IndexSize, - QtCore.Qt.DisplayRole, - QtCore.QVariant(numbers.format_num_bytes(fcpRequest['MetadataSize'])) - ) - item.setData( - TreeItem.IndexMimeType, - QtCore.Qt.DisplayRole, - QtCore.QVariant(fcpRequest['MetadataContentType']) - ) - self._adjustItemStatus(item) - - def onFcpClientRequestFailed(self, fcpEvent, fcpRequest): - item = self.fcpRequests.get(fcpRequest['Identifier'], None) - if item is not None: - self._adjustItemStatus(item) - - #TODO: not tested - def onFcpClientRequestModified(self, fcpEvent, fcpRequest): - - requestIdentifier = fcpRequest['Modified'].get(fcp2.ConstRequestModified.Identifier, None) - if requestIdentifier is None: - requestIdentifier = fcpRequest['Identifier'] - item = self.fcpRequests.get(requestIdentifier, None) - - if item is not None: - if fcp2.ConstRequestModified.Identifier in fcpRequest['Modified']: - newFcpIdentifier = fcpRequest['Identifier'] - del self.fcpRequests[requestIdentifier] - self.fcpRequests[newFcpIdentifier] = item - - if fcp2.ConstRequestModified.Filename in fcpRequest['Modified']: - item.setData( - TreeItem.IndexName, - QtCore.Qt.DisplayRole, - QtCore.QVariant(os.path.basename(fcpRequest['Filename'])) - ) - - - def onFcpClientRequestProgress(self, fcpEvent, fcpRequest): - item = self.fcpRequests.get(fcpRequest['Identifier'], None) - if item is not None: - self._adjustItemStatus(item) - - def onFcpClientRequestRemoved(self, fcpEvent, fcpRequest): - pass - - def onFcpClientRequestStarted(self, fcpEvent, fcpRequest): - if fcpRequest['RequestStatus'] & fcp2.ConstRequestStatus.Restored: - try: - requestData = PersistentRequestData.load(fcpRequest['PersistentUserData']) - except pmstruct.PMStructError: - pass - else: - if requestData.get('ClientName', None) == self.objectName(): - item = self._createItemFromFcpRequest(fcpRequest) - else: - item = self.fcpRequests.get(fcpRequest['Identifier'], None) - if item is not None: - self._adjustItemStatus(item) - - -#********************************************************************************** -# -#********************************************************************************** +#************************************************************************************ class DownloadsWidgetGlobalFeedback(config.GlobalFeedbackBase): """wrapper for global statusbar widgets, menus""" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jU...@us...> - 2008-08-11 17:58:56
|
Revision: 901 http://fclient.svn.sourceforge.net/fclient/?rev=901&view=rev Author: jUrner Date: 2008-08-11 17:59:02 +0000 (Mon, 11 Aug 2008) Log Message: ----------- no longer needed Removed Paths: ------------- trunk/fclient/fclient/impl/tpls/Ui_ViewDownloadsWidgetTpl.py trunk/fclient/fclient/impl/tpls/ViewDownloadsWidgetTpl.ui Deleted: trunk/fclient/fclient/impl/tpls/Ui_ViewDownloadsWidgetTpl.py =================================================================== --- trunk/fclient/fclient/impl/tpls/Ui_ViewDownloadsWidgetTpl.py 2008-08-11 17:57:50 UTC (rev 900) +++ trunk/fclient/fclient/impl/tpls/Ui_ViewDownloadsWidgetTpl.py 2008-08-11 17:59:02 UTC (rev 901) @@ -1,40 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file '/home/me/src/proj/fclient/trunk/fclient/src/fclient/tpls/ViewDownloadsWidgetTpl.ui' -# -# Created: Mon Jul 21 14:55:28 2008 -# by: PyQt4 UI code generator 4.4.3-snapshot-20080705 -# -# WARNING! All changes made in this file will be lost! - -from PyQt4 import QtCore, QtGui - -class Ui_ViewDownloadsWidget(object): - def setupUi(self, ViewDownloadsWidget): - ViewDownloadsWidget.setObjectName("ViewDownloadsWidget") - ViewDownloadsWidget.resize(400, 300) - self.gridLayout = QtGui.QGridLayout(ViewDownloadsWidget) - self.gridLayout.setMargin(0) - self.gridLayout.setSpacing(0) - self.gridLayout.setObjectName("gridLayout") - self.tree = QtGui.QTreeWidget(ViewDownloadsWidget) - self.tree.setObjectName("tree") - self.gridLayout.addWidget(self.tree, 0, 0, 1, 1) - - self.retranslateUi(ViewDownloadsWidget) - QtCore.QMetaObject.connectSlotsByName(ViewDownloadsWidget) - - def retranslateUi(self, ViewDownloadsWidget): - ViewDownloadsWidget.setWindowTitle(QtGui.QApplication.translate("ViewDownloadsWidget", "Form", None, QtGui.QApplication.UnicodeUTF8)) - self.tree.headerItem().setText(0, QtGui.QApplication.translate("ViewDownloadsWidget", "1", None, QtGui.QApplication.UnicodeUTF8)) - - -if __name__ == "__main__": - import sys - app = QtGui.QApplication(sys.argv) - ViewDownloadsWidget = QtGui.QWidget() - ui = Ui_ViewDownloadsWidget() - ui.setupUi(ViewDownloadsWidget) - ViewDownloadsWidget.show() - sys.exit(app.exec_()) - Deleted: trunk/fclient/fclient/impl/tpls/ViewDownloadsWidgetTpl.ui =================================================================== --- trunk/fclient/fclient/impl/tpls/ViewDownloadsWidgetTpl.ui 2008-08-11 17:57:50 UTC (rev 900) +++ trunk/fclient/fclient/impl/tpls/ViewDownloadsWidgetTpl.ui 2008-08-11 17:59:02 UTC (rev 901) @@ -1,35 +0,0 @@ -<ui version="4.0" > - <class>ViewDownloadsWidget</class> - <widget class="QWidget" name="ViewDownloadsWidget" > - <property name="geometry" > - <rect> - <x>0</x> - <y>0</y> - <width>400</width> - <height>300</height> - </rect> - </property> - <property name="windowTitle" > - <string>Form</string> - </property> - <layout class="QGridLayout" name="gridLayout" > - <property name="margin" > - <number>0</number> - </property> - <property name="spacing" > - <number>0</number> - </property> - <item row="0" column="0" > - <widget class="QTreeWidget" name="tree" > - <column> - <property name="text" > - <string>1</string> - </property> - </column> - </widget> - </item> - </layout> - </widget> - <resources/> - <connections/> -</ui> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jU...@us...> - 2008-08-11 17:57:43
|
Revision: 900 http://fclient.svn.sourceforge.net/fclient/?rev=900&view=rev Author: jUrner Date: 2008-08-11 17:57:50 +0000 (Mon, 11 Aug 2008) Log Message: ----------- spped up browser pane on first access Modified Paths: -------------- trunk/fclient/fclient/impl/ViewBrowser.py Modified: trunk/fclient/fclient/impl/ViewBrowser.py =================================================================== --- trunk/fclient/fclient/impl/ViewBrowser.py 2008-08-11 17:56:50 UTC (rev 899) +++ trunk/fclient/fclient/impl/ViewBrowser.py 2008-08-11 17:57:50 UTC (rev 900) @@ -1001,8 +1001,8 @@ self.isCreated = True # fire up a new broser to make a start #TODO: find a better time to fire up the browser. how do we know when the gui is up and running? + QtGui.QApplication.instance().processEvents() self.newBrowser(title=self.trUtf8('Waiting for fproxy')) - QtGui.QApplication.instance().processEvents() self.fcActions['ActionGoToHomePage'].trigger() def viewClose(self): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jU...@us...> - 2008-08-11 17:56:46
|
Revision: 899 http://fclient.svn.sourceforge.net/fclient/?rev=899&view=rev Author: jUrner Date: 2008-08-11 17:56:50 +0000 (Mon, 11 Aug 2008) Log Message: ----------- started rewriting downloadsWidget to a more gemeral purpose requests widget Modified Paths: -------------- trunk/fclient/fclient/impl/ViewDownloads.py Added Paths: ----------- trunk/fclient/fclient/impl/tpls/Ui_ViewRequestsWidgetTpl.py trunk/fclient/fclient/impl/tpls/ViewRequestsWidgetTpl.ui Modified: trunk/fclient/fclient/impl/ViewDownloads.py =================================================================== --- trunk/fclient/fclient/impl/ViewDownloads.py 2008-08-11 10:42:48 UTC (rev 898) +++ trunk/fclient/fclient/impl/ViewDownloads.py 2008-08-11 17:56:50 UTC (rev 899) @@ -56,7 +56,7 @@ from . import DlgDownloadKeyToDisk -from .tpls.Ui_ViewDownloadsWidgetTpl import Ui_ViewDownloadsWidget +from .tpls.Ui_ViewRequestsWidgetTpl import Ui_ViewRequestsWidget #********************************************************************************** # #********************************************************************************** @@ -65,126 +65,6 @@ #********************************************************************************** # #********************************************************************************** -class DownloadsViewObject(config.ViewObject): - - def __init__(self, parent): - config.ViewObject. __init__(self, parent) - - self.name=parent.objectName() - self.displayName=self.trUtf8('Downloads') - self.icon=QtGui.QIcon() - -#********************************************************************************** -# -#********************************************************************************** -class DownloadsWidgetGlobalFeedback(config.GlobalFeedbackBase): - """wrapper for global statusbar widgets, menus""" - - def __init__(self, parent, idGlobalFeedback): - config.GlobalFeedbackBase.__init__(self, parent, idGlobalFeedback) - - # menus - self.menus = [] - if self.menuBar is not None and hasattr(parent, 'fcViewObject'): - menu = QtGui.QMenu(parent.fcViewObject.displayName, self.menuBar) - parent.populateMenu(menu) - self.menus.append(menu) - self.menuBar.addViewMenu(menu) - - # status bar widgets - self.labelStatus = None - self.progress = None - self.labelFeedbackWrap = None - #if self.statusBar is not None: - # self.labelStatus = QtGui.QLabel(QtCore.QString(), self.statusBar) - # self.statusBar.addWidget(self.labelStatus) - # - # self.progress = QtGui.QProgressBar(self.statusBar) - # self.progress.setRange(0, Browser.MaxProgress) - # self.progress.setValue(0) - # self.statusBar.addWidget(self.progress) - # - # label = QtGui.QLabel(self.statusBar) - # label.setFrameStyle(QtGui.QLabel.Sunken | QtGui.QLabel.Box) - # self.labelFeedbackWrap = pathlabelwrap.PathLabelWrap( - # label, - # path_module=config.CompactPathFcpKeyModule, - # ) - # self.statusBar.addWidget(self.labelFeedbackWrap.label, 1) - - - def setVisible(self, flag): - if self.menuBar is not None: - for menu in self.menus: - menu.children()[0].setEnabled(flag) - #if self.statusBar is not None: - # self.progress.setVisible(flag) - # self.labelStatus.setVisible(flag) - # self.labelFeedbackWrap.label.setVisible(flag) - - #def setProgress(self, n): - # if self.progress is not None: - # self.progress.setValue(n) - - #def setStatusMessage(self, qString): - # if self.labelStatus is not None: - # self.labelStatus.setText(qString) - - #def setFeedback(self, qString): - # if self.labelFeedbackWrap is not None: - # self.labelFeedbackWrap.setPath(unicode(qString)) - -class DownloadsWidgetActions(config.ActionsBase): - - def __init__(self, parent): - config.ActionsBase.__init__(self, parent) - - self.action( - name='ActionDownloadKeyToDisk', - text=self.trUtf8('Download &key...'), - trigger=parent.onDlgDownloadKey, - ) - self.action( - name='ActionRemoveSelectedDownloads', - text=self.trUtf8('Remove download'), - trigger=parent.onRemoveSelectedDownloads, - isEnabled=False, - ) - self.action( - name='ActionRestartSelectedDownloads', - text=self.trUtf8('Restart download'), - trigger=parent.onRestartSelectedDownloads, - isEnabled=False, - ) - - #TODO: enable/disable if items of that type are available? - group = self.group( - name='GroupRemoveGroup', - trigger=parent.onRemoveGroup, - ) - self.action( - name='ActionRemoveFailed', - group=group, - text=self.trUtf8('Failed'), - isEnabled=False, - ) - self.action( - name='ActionRemoveCompleted', - group=group, - text=self.trUtf8('Completed'), - isEnabled=False, - ) - -class DownloadsWidgetSettings(config.SettingsBase): - - - _key_ = config.IdViewDownloadsWidget - _settings_ = ( - ('MaxSimultaneousDownloads', 'UInt', 3), - ) -#********************************************************************************** -# -#********************************************************************************** class PersistentRequestData(pmstruct.PMStruct): _fields_ = ( ('ClientName', pmstruct.STRING), @@ -239,10 +119,52 @@ return self.item.status() status= QtCore.pyqtProperty("QString", _get_status) + +class RequestsWidgetActions(config.ActionsBase): + + def __init__(self, parent): + config.ActionsBase.__init__(self, parent) + + self.action( + name='ActionDownloadKeyToDisk', + text=self.trUtf8('Download &key...'), + trigger=parent.onDlgDownloadKey, + ) + self.action( + name='ActionRemoveSelectedDownloads', + text=self.trUtf8('Remove download'), + trigger=parent.onRemoveSelectedDownloads, + isEnabled=False, + ) + self.action( + name='ActionRestartSelectedDownloads', + text=self.trUtf8('Restart download'), + trigger=parent.onRestartSelectedDownloads, + isEnabled=False, + ) + + #TODO: enable/disable if items of that type are available? + group = self.group( + name='GroupRemoveGroup', + trigger=parent.onRemoveGroup, + ) + self.action( + name='ActionRemoveFailed', + group=group, + text=self.trUtf8('Failed'), + isEnabled=False, + ) + self.action( + name='ActionRemoveCompleted', + group=group, + text=self.trUtf8('Completed'), + isEnabled=False, + ) + #********************************************************************************** # #********************************************************************************** -class ViewDownloadsWidget(QtGui.QWidget, Ui_ViewDownloadsWidget): +class RequestsWidget(QtGui.QWidget, Ui_ViewRequestsWidget): IdTree = 'tree' @@ -250,17 +172,12 @@ QtGui.QWidget.__init__(self, parent) self._isCreated = False self.fcHeaderLabels = {} # fcpIdentifier --> treeItem + self.fcActions = RequestsWidgetActions(self) self.fcpRequests = {} self.fcRequestStatusNames = {} self.menuRemoveGroup = QtGui.QMenu(self) self.setupUi(self) - - config.ObjectRegistry.register(self) - self.fcSettings = DownloadsWidgetSettings(self).restore() - self.fcActions = DownloadsWidgetActions(self) - self.fcViewObject = DownloadsViewObject(self) - self.fcGlobalFeedback = DownloadsWidgetGlobalFeedback(self, idGlobalFeedback) self.fcpClientEvents = ( (config.fcpClient.events.ClientConnected, self.onFcpClientConnected), (config.fcpClient.events.ClientDisconnected, self.onFcpClientDisconnected), @@ -274,9 +191,6 @@ ) config.fcpClient.events += self.fcpClientEvents - # setup menus - for action in self.fcActions['GroupRemoveGroup'].actions(): - self.menuRemoveGroup.addAction(action) ############################ ## private methods @@ -357,7 +271,7 @@ ## ############################ def retranslateUi(self, parent): - Ui_ViewDownloadsWidget.retranslateUi(self, parent) + Ui_ViewRequestsWidget.retranslateUi(self, parent) tree = self.controlById(self.IdTree) root = tree.invisibleRootItem() @@ -515,21 +429,14 @@ parent = root parent.removeChild(item) + + # overwrite def onTreeCustomContextMenuRequested(self, pt): - tree = self.controlById(self.IdTree) - pt = tree.viewport().mapToGlobal(pt) + pass - menu = QtGui.QMenu(self) - menu.addAction(self.fcActions['ActionRemoveSelectedDownloads']) - menu.addAction(self.fcActions['ActionRestartSelectedDownloads']) - menu.addMenu(self.menuRemoveGroup) - menu.exec_(pt) - + # overwrite def onTreeItemSelectionChanged(self): - tree = self.controlById(self.IdTree) - hasSelectedItems = tree.selectionModel().hasSelection() - self.fcActions['ActionRemoveSelectedDownloads'].setEnabled(hasSelectedItems) - self.fcActions['ActionRestartSelectedDownloads'].setEnabled(hasSelectedItems) + pass ######################################### ## fcp event handlers @@ -611,9 +518,142 @@ if item is not None: self._adjustItemStatus(item) + #********************************************************************************** # #********************************************************************************** +class DownloadsWidgetGlobalFeedback(config.GlobalFeedbackBase): + """wrapper for global statusbar widgets, menus""" + + def __init__(self, parent, idGlobalFeedback): + config.GlobalFeedbackBase.__init__(self, parent, idGlobalFeedback) + + # menus + self.menus = [] + if self.menuBar is not None and hasattr(parent, 'fcViewObject'): + menu = QtGui.QMenu(parent.fcViewObject.displayName, self.menuBar) + parent.populateMenu(menu) + self.menus.append(menu) + self.menuBar.addViewMenu(menu) + + # status bar widgets + self.labelStatus = None + self.progress = None + self.labelFeedbackWrap = None + #if self.statusBar is not None: + # self.labelStatus = QtGui.QLabel(QtCore.QString(), self.statusBar) + # self.statusBar.addWidget(self.labelStatus) + # + # self.progress = QtGui.QProgressBar(self.statusBar) + # self.progress.setRange(0, Browser.MaxProgress) + # self.progress.setValue(0) + # self.statusBar.addWidget(self.progress) + # + # label = QtGui.QLabel(self.statusBar) + # label.setFrameStyle(QtGui.QLabel.Sunken | QtGui.QLabel.Box) + # self.labelFeedbackWrap = pathlabelwrap.PathLabelWrap( + # label, + # path_module=config.CompactPathFcpKeyModule, + # ) + # self.statusBar.addWidget(self.labelFeedbackWrap.label, 1) + + + def setVisible(self, flag): + if self.menuBar is not None: + for menu in self.menus: + menu.children()[0].setEnabled(flag) + #if self.statusBar is not None: + # self.progress.setVisible(flag) + # self.labelStatus.setVisible(flag) + # self.labelFeedbackWrap.label.setVisible(flag) + + #def setProgress(self, n): + # if self.progress is not None: + # self.progress.setValue(n) + + #def setStatusMessage(self, qString): + # if self.labelStatus is not None: + # self.labelStatus.setText(qString) + + #def setFeedback(self, qString): + # if self.labelFeedbackWrap is not None: + # self.labelFeedbackWrap.setPath(unicode(qString)) + + + +class DownloadsViewObject(config.ViewObject): + + def __init__(self, parent): + config.ViewObject. __init__(self, parent) + + self.name=parent.objectName() + self.displayName=self.trUtf8('Downloads') + self.icon=QtGui.QIcon() + + +class DownloadsWidgetSettings(config.SettingsBase): + + + _key_ = config.IdViewDownloadsWidget + _settings_ = ( + ('MaxSimultaneousDownloads', 'UInt', 3), + ) + + +class ViewDownloadsWidget(RequestsWidget): + + def __init__(self, parent, idGlobalFeedback=config.IdMainWindow): + + self.menuRemoveGroup = None + + RequestsWidget.__init__(self, parent) + + self.setObjectName(config.IdViewDownloadsWidget) + config.ObjectRegistry.register(self) + self.fcSettings = DownloadsWidgetSettings(self).restore() + self.fcViewObject = DownloadsViewObject(self) + self.fcGlobalFeedback = DownloadsWidgetGlobalFeedback(self, idGlobalFeedback) + + # setup menus + self.menuRemoveGroup = QtGui.QMenu(self) + self.menuRemoveGroup.setTitle(self.trUtf8('Remove group')) + for action in self.fcActions['GroupRemoveGroup'].actions(): + self.menuRemoveGroup.addAction(action) + + + def hideEvent(self, event): + self.fcGlobalFeedback.setVisible(False) + RequestsWidget.hideEvent(self, event) + + def showEvent(self, event): + self.fcGlobalFeedback.setVisible(True) + RequestsWidget.showEvent(self, event) + + def retranslateUi(self, parent): + RequestsWidget.retranslateUi(self, parent) + if self.menuRemoveGroup is not None: + self.menuRemoveGroup.setTitle(self.trUtf8('Remove group')) + + def onTreeCustomContextMenuRequested(self, pt): + tree = self.controlById(self.IdTree) + pt = tree.viewport().mapToGlobal(pt) + + menu = QtGui.QMenu(self) + menu.addAction(self.fcActions['ActionRemoveSelectedDownloads']) + menu.addAction(self.fcActions['ActionRestartSelectedDownloads']) + menu.addMenu(self.menuRemoveGroup) + menu.exec_(pt) + + def onTreeItemSelectionChanged(self): + tree = self.controlById(self.IdTree) + hasSelectedItems = tree.selectionModel().hasSelection() + self.fcActions['ActionRemoveSelectedDownloads'].setEnabled(hasSelectedItems) + self.fcActions['ActionRestartSelectedDownloads'].setEnabled(hasSelectedItems) + + +#********************************************************************************** +# +#********************************************************************************** if __name__ == '__main__': import sys from . import View Added: trunk/fclient/fclient/impl/tpls/Ui_ViewRequestsWidgetTpl.py =================================================================== --- trunk/fclient/fclient/impl/tpls/Ui_ViewRequestsWidgetTpl.py (rev 0) +++ trunk/fclient/fclient/impl/tpls/Ui_ViewRequestsWidgetTpl.py 2008-08-11 17:56:50 UTC (rev 899) @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file '/home/me/src/fclient/trunk/fclient/fclient/impl/tpls/ViewRequestsWidgetTpl.ui' +# +# Created: Mon Aug 11 19:50:32 2008 +# by: PyQt4 UI code generator 4.4.3-snapshot-20080705 +# +# WARNING! All changes made in this file will be lost! + +from PyQt4 import QtCore, QtGui + +class Ui_ViewRequestsWidget(object): + def setupUi(self, ViewRequestsWidget): + ViewRequestsWidget.setObjectName("ViewRequestsWidget") + ViewRequestsWidget.resize(400, 300) + self.gridLayout = QtGui.QGridLayout(ViewRequestsWidget) + self.gridLayout.setMargin(0) + self.gridLayout.setSpacing(0) + self.gridLayout.setObjectName("gridLayout") + self.tree = QtGui.QTreeWidget(ViewRequestsWidget) + self.tree.setObjectName("tree") + self.gridLayout.addWidget(self.tree, 0, 0, 1, 1) + + self.retranslateUi(ViewRequestsWidget) + QtCore.QMetaObject.connectSlotsByName(ViewRequestsWidget) + + def retranslateUi(self, ViewRequestsWidget): + ViewRequestsWidget.setWindowTitle(QtGui.QApplication.translate("ViewRequestsWidget", "Form", None, QtGui.QApplication.UnicodeUTF8)) + self.tree.headerItem().setText(0, QtGui.QApplication.translate("ViewRequestsWidget", "1", None, QtGui.QApplication.UnicodeUTF8)) + + +if __name__ == "__main__": + import sys + app = QtGui.QApplication(sys.argv) + ViewRequestsWidget = QtGui.QWidget() + ui = Ui_ViewRequestsWidget() + ui.setupUi(ViewRequestsWidget) + ViewRequestsWidget.show() + sys.exit(app.exec_()) + Added: trunk/fclient/fclient/impl/tpls/ViewRequestsWidgetTpl.ui =================================================================== --- trunk/fclient/fclient/impl/tpls/ViewRequestsWidgetTpl.ui (rev 0) +++ trunk/fclient/fclient/impl/tpls/ViewRequestsWidgetTpl.ui 2008-08-11 17:56:50 UTC (rev 899) @@ -0,0 +1,35 @@ +<ui version="4.0" > + <class>ViewRequestsWidget</class> + <widget class="QWidget" name="ViewRequestsWidget" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>300</height> + </rect> + </property> + <property name="windowTitle" > + <string>Form</string> + </property> + <layout class="QGridLayout" name="gridLayout" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>0</number> + </property> + <item row="0" column="0" > + <widget class="QTreeWidget" name="tree" > + <column> + <property name="text" > + <string>1</string> + </property> + </column> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jU...@us...> - 2008-08-11 10:42:39
|
Revision: 898 http://fclient.svn.sourceforge.net/fclient/?rev=898&view=rev Author: jUrner Date: 2008-08-11 10:42:48 +0000 (Mon, 11 Aug 2008) Log Message: ----------- new versionno Modified Paths: -------------- trunk/fclient/fclient/impl/config.py Modified: trunk/fclient/fclient/impl/config.py =================================================================== --- trunk/fclient/fclient/impl/config.py 2008-08-11 10:42:29 UTC (rev 897) +++ trunk/fclient/fclient/impl/config.py 2008-08-11 10:42:48 UTC (rev 898) @@ -16,7 +16,7 @@ #********************************************************************************** FcOrgName = 'fclient' FcAppName = 'fclient' -FcVersion = '0.0.1' +FcVersion = '0.0.2' FcAuthor = 'Juergen Urner' FcLicence = 'MIT' FcCopyright = '(c) 2008 Juergen Urner' This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jU...@us...> - 2008-08-11 10:42:21
|
Revision: 897 http://fclient.svn.sourceforge.net/fclient/?rev=897&view=rev Author: jUrner Date: 2008-08-11 10:42:29 +0000 (Mon, 11 Aug 2008) Log Message: ----------- adapt to recent Modified Paths: -------------- trunk/fclient/fclient/README Modified: trunk/fclient/fclient/README =================================================================== --- trunk/fclient/fclient/README 2008-08-11 10:42:15 UTC (rev 896) +++ trunk/fclient/fclient/README 2008-08-11 10:42:29 UTC (rev 897) @@ -5,7 +5,22 @@ Version history: + ******************************************************************* +0.0.2 - (???) +******************************************************************* +second pre-alpha release + +news: + + x. downloads can now be removed groupwise + +bugfixes: + + x. many + + +******************************************************************* 0.0.1 - (08.10.08) ******************************************************************* first pre-alpha release This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jU...@us...> - 2008-08-11 10:42:09
|
Revision: 896 http://fclient.svn.sourceforge.net/fclient/?rev=896&view=rev Author: jUrner Date: 2008-08-11 10:42:15 +0000 (Mon, 11 Aug 2008) Log Message: ----------- more css Modified Paths: -------------- trunk/fclient/fclient/impl/res/stylesheets/default.css Modified: trunk/fclient/fclient/impl/res/stylesheets/default.css =================================================================== --- trunk/fclient/fclient/impl/res/stylesheets/default.css 2008-08-11 10:42:00 UTC (rev 895) +++ trunk/fclient/fclient/impl/res/stylesheets/default.css 2008-08-11 10:42:15 UTC (rev 896) @@ -69,34 +69,26 @@ background: qlineargradient(x1: 0, y1: 0.5, x2: 1, y2: 0.5, stop: 0 green, stop: 1 white); } -/* -QProgressBar{ - color: white; - border: 0px solid black; - background: gray; - margin: 0px; - padding: 0px; - text-align: center vcenter; + +/* downloadWidget progressBars (omitted [status="removed"]) */ +QProgressBar#downloadKey[status="pending"]::chunk{ +background: qlineargradient(x1: 0, y1: 0.5, x2: 1, y2: 0.5, stop: 0 gray, stop: 1 lightgray); } -QProgressBar::chunk{ - background: #377FFF; - border-radius: 5px; - border: 1px solid darkgrey; - } - QProgressBar#downloadKey[status="loading"]::chunk{ - background:#0000FF; - } +background: qlineargradient(x1: 0, y1: 0.5, x2: 1, y2: 0.5, stop: 0 blue, stop: 1 aqua); +} + QProgressBar#downloadKey[status="complete"]::chunk{ - background:#009600; - } +background: qlineargradient(x1: 0, y1: 0.5, x2: 1, y2: 0.5, stop: 0 green, stop: 1 limegreen); +} + QProgressBar#downloadKey[status="error"]::chunk{ - background:red; - } -*/ +background: qlineargradient(x1: 0, y1: 0.5, x2: 1, y2: 0.5, stop: 0 red, stop: 1 pink); +} +/* label indicating connected status on statusBar */ QLabel#LabelConnectionConnected{ color: green; font: bold; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |