SF.net SVN: fclient: [51] trunk/fclient/fclient_widgets/download_widget.py
Status: Pre-Alpha
Brought to you by:
jurner
From: <jU...@us...> - 2007-11-06 12:39:15
|
Revision: 51 http://fclient.svn.sourceforge.net/fclient/?rev=51&view=rev Author: jUrner Date: 2007-11-06 04:39:13 -0800 (Tue, 06 Nov 2007) Log Message: ----------- started implementing a download widget Added Paths: ----------- trunk/fclient/fclient_widgets/download_widget.py Added: trunk/fclient/fclient_widgets/download_widget.py =================================================================== --- trunk/fclient/fclient_widgets/download_widget.py (rev 0) +++ trunk/fclient/fclient_widgets/download_widget.py 2007-11-06 12:39:13 UTC (rev 51) @@ -0,0 +1,358 @@ +"""Sketch for a download widget + +""" + + +import os, sys + +#--> rel import hack +def parentdir(n, fpath): + fpath = os.path.abspath(fpath) + for i in xrange(n): + fpath = os.path.dirname(fpath) + return fpath +sys.path.insert(0, parentdir(2, __file__)) + +import config +from fclient_lib import fcp +#from fclient_dlgs import frdx_viewer +from fclient_lib.pyex import namespace, numbers +#from fclient_lib.qt4ex import settingsbase +#from fclient_lib.qt4ex.ctrls import progressbarwrap + +sys.path.pop(0) +del parentdir +#<-- rel import hack + + +import thread +from PyQt4 import QtCore, QtGui +#***************************************************************************** +# +#***************************************************************************** +class DownloadItem(QtGui.QTreeWidgetItem): + + # default indices + IndexName = 0 + IndexStatus = 1 + IndexProgress = 2 + IndexSize = 3 + IndexMimeType = 4 + IndexPriority = 5 + + ###################### + IndexLastProgress = 6 + IndexDuration = 7 + + + def __init__(self, parent, requestIdentifier, uri): + QtGui.QTreeWidgetItem.__init__(self, parent) + + self._requestIdentifier = requestIdentifier + self._uri = uri + + + def setRequestIdentifier(self, identifier): + self._requestIdentifier = identifier + + def requestIdentifier(self): + return self._requestIdentifier + + def setRequestMimeType(self, mimeType): + self.setText(self.IndexMimeType, mimeType) + + def requestMimeType(self): + return self.text(self.IndexMimeType) + + def setRequestName(self, name): + self.setText(self.IndexName, name) + + def requestName(self): + return self.text(self.IndexName) + + def setRequestPriority(self, priority): + self.setText(self.IndexPriority, priority) + + def requestPriority(self): + return self.text(self.IndexPriority) + + def setProgressWidget(self, tree, widget): + tree.setItemWidget(self, self.IndexProgress, widget) + + def progressWidget(self, tree): + return tree.itemWidget(self, self.IndexProgress) + + def setRequestStatus(self, status): + self.setText(self.IndexStatus, status) + + def requestStatus(self): + return self.text(self.IndexStatus) + + def setRequestSize(self, size): + self.setText(self.IndexSize, size) + + def requestSize(self): + return self.text(self.IndexSize) + + def setRequestUri(self, uri): + self._uri = uri + + def requestUri(self): + return self._uri + +#***************************************************************************** +# +#***************************************************************************** +class DownloadWidgetStrings(QtCore.QObject): + + + def __init__(self, parent): + QtCore.QObject.__init__(self, parent) + + + self.headerSections = [ + (DownloadItem.IndexName, self.trUtf8('Name')), + (DownloadItem.IndexStatus, self.trUtf8('Status')), + (DownloadItem.IndexProgress, self.trUtf8('Progress')), + (DownloadItem.IndexSize, self.trUtf8('Size')), + (DownloadItem.IndexMimeType, self.trUtf8('Content')), + (DownloadItem.IndexPriority, self.trUtf8('Priority')), + (DownloadItem.IndexLastProgress, self.trUtf8('Last Progress')), + (DownloadItem.IndexDuration, self.trUtf8('Duration')), + ] + self.headerSections.sort() + + +#**************************************************************************** +# +#**************************************************************************** +class DownloadWidget(QtGui.QTreeWidget): + + def __init__(self, + parent, + connectionName='', + directory=None, + uris=None, + maxQueuedItemsPerHop=200, + maxSimultaniousDownloads=2, + cfg=None + ): + """ + @param parent: (QWidget) parent or None + @param directory: (str) directory to sownload items to or None to use default directory + @param connectionName: name of the connection to the node + @param maxQueuedItemsPerHop: maximum number of items that can be e added in one hop + @param maxSimultaniousDownloads: maximim number of simultaneous downloads + @param cfg: (configConfig) instance or None + """ + + QtGui.QTreeWidget.__init__(self, parent) + + self._connectionName = connectionName + self._cfg = cfg if cfg is not None else config.Config(self) + self._directory = directory if directory is not None else self._cfg.defaultDownloadDir + self._downloads = { + 'Downloads': {}, # identifier --> item / items currently downloading + 'DownloadQueue': [], # (parent-item, uri) / items scheduled for download + 'DownloadDirectories': {}, # directory --> (parentItem, uris) / directories scheduled for testDDA + } + self._fcpClient = None + self._isCreated = False + self._lock = thread.allocate_lock() + self._maxQueuedItemsPerHop = maxQueuedItemsPerHop #TODO: move to settings + self._maxSimultaniousDownloads = maxSimultaniousDownloads #TODO: move to settings + self._strings = DownloadWidgetStrings(self) + + # timer to add scheduled downloads (add maxQueuedItemsPerHop / hop to avoid flooding of the tree) + self._timer = QtCore.QTimer(self) + self._timer.setInterval(300) # arbitrary delay + self.connect( + self._timer, + QtCore.SIGNAL('timeout()'), + self.addQueuedItems + ) + + # setup tree + self.setHeaderLabels([i[1] for i in self._strings.headerSections]) + #self.setColumnCount(len(self._strings.HeaderSections)) + self.setSelectionMode(self.ContiguousSelection) + + header = self.header() + header.setResizeMode(header.ResizeToContents) + header.setStretchLastSection(True) + + self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) + self.connect( + self, + QtCore.SIGNAL('customContextMenuRequested(const QPoint&)'), + self.handleContextMenu + ) + + # schedule initial uris + if uris is not None: + self._downloads['DownloadDirectories'][self._directory] = (self, uris) + + + def showEvent(self, event): + if not self._isCreated: + self._isCreated = True + self._fcpClient = self._cfg.fcpClientManager.newClient(self._connectionName, self.handleClientConnected) + + ############################################################# + ## + ## handlers for Qt events + ## + ############################################################# + def handleContextMenu(self): + pass + + + + ############################################################# + ## + ## handlers for Fcp events + ## + ############################################################# + def handleClientConnected(self, event, params): + """ + """ + self._fcpEvents = ( + (self._fcpClient.events.ClientDisconnected, self.handleClientDisconnected), + + (self._fcpClient.events.TestDDAComplete, self.handleTestDDAComplete), + ) + # take care not to connect twice + for event, observer in self._fcpEvents: + if not observer in event: + event += observer + + # register directories + for directory in self._downloads['DownloadDirectories']: + self._fcpClient.testDDA(directory, wantWriteDirectory=True) + + + def handleClientDisconnected(self, event, params): + """ + """ + + def handleTestDDAComplete(self, event, params): + """ + """ + directory = params['Directory'] + readAllowed = params.get('WriteDirectoryAllowed') + writeAllowed = params.get('WriteDirectoryAllowed') + + # check if there are items to be donloaded for the directory + downloads = None + self._lock.acquire(True) + try: + downloads = self._downloads['DownloadDirectories'].get(directory, None) + if downloads is not None: + del self._downloads['DownloadDirectories'][directory] # ??? + finally: + self._lock.release() + + if downloads: + if writeAllowed == self._fcpClient.FcpTrue: + parent, uris = downloads + for uri in uris: + self.download(uri, parent=parent) + + else: + pass + #TODO: write access denied, error + + ####################################################### + ## + ## methods + ## + ####################################################### + def addQueuedItems(self): + + self._timer.stop() + + self._lock.acquire(True) + try: + n = 0 + while self._downloads['DownloadQueue'] and n < self._maxQueuedItemsPerHop: + n += 1 + + parent, uri = self._downloads['DownloadQueue'].pop(0) + item = DownloadItem(parent, '', uri) + fcpUri = self._fcpClient.FcpUri(uri) + fileName = fcpUri.fileName() + fileName = namespace.unquote_uri(fileName) + + item.setRequestName(fileName) + + #... more here + + if self._downloads['DownloadQueue']: + self._timer.start() + + finally: + self._lock.release() + + + def download(self, uri, parent=None): + self._lock.acquire(True) + try: + self._downloads['DownloadQueue'].append( (parent, uri) ) + finally: + self._lock.release() + + if not self._timer.isActive(): + self._timer.start() + + + def retranslate(self): + pass + +#*************************************************************************************************** +# +#*************************************************************************************************** +if __name__ == '__main__': + import sys + + TestUris = '''CHK@sdNenKGj5mupxaSwo44jcW8dsX7vYTLww~BsRPtur0k,ZNRm9reMjtKEl9e-xFByKXbW6q4f6OQyfg~l9GRSAes,AAIC--8/snow_002%20%281%29.jpg +CHK@q4~2soHTd9SOINIoXmg~dn7LNUAOYzN1tHNHT3j4c9E,gcVRtoglEhgqN-DJolXPqJ4yX1f~1gBGh89HNWlFMWQ,AAIC--8/snow_002%20%2810%29.jpg +CHK@6tw-vrINDoNgSY9pTq-88n2sOAhREv1iFc3T0E18xHk,NxJxo9d7spLHCqGsMyY26XtXpUACPKTJq9v~WxVp3ic,AAIC--8/snow_002%20%2811%29.jpg +CHK@nOb-ZM4h1SNpoG3E0xcOPnNDydSf~y2DON~R80exAtU,2o6smJYijaftLzMz4iva24T1geEAnDFn~bIMKFkzU30,AAIC--8/snow_002%20%2812%29.jpg +CHK@XWyYvxoirEKiLWhnSVdKffSHT~nnKWsVZ5tJRKiFxBk,mK9-g5AeCvcNue1wYHRhc1Hdj3-yn77Vyu9Tq7XXJTM,AAIC--8/snow_002%20%2813%29.jpg +CHK@AbQOZRSJcgXnKOI16D2hF8qkjxp3cl1u72bkL2KS29E,jjQlvojCkJJgzI2WgWj5rMsmUd935zjGChiV-j937X0,AAIC--8/snow_002%20%2814%29.jpg +CHK@1ZW0fOpB7RmUFqSO2TtAOyfFm1uJ6~JcWuPESiYwtc4,aCDkI~JCr3Mb8s7rPBgmalPqzQEFdovlF~DgDRkGWuE,AAIC--8/snow_002%20%2815%29.jpg +CHK@a8jHCl0TkwVAcTdYOezd-FtIWTLIFhjrWeHXVcSjRPk,4rIwDZE~-Gp~B5tjDSAcSpn~tLgMmnMUFeikXP4f7y0,AAIC--8/snow_002%20%2816%29.jpg +CHK@Jg~F~~WbKu8AlBgmwkonWGQNzZFUholE2CkGnyt23kk,Gj7JtnR97EIRvabG8m6Xp1dUAqiP6qD4J5FJRN9waMQ,AAIC--8/snow_002%20%2836%29.jpg''' + TestUris = TestUris.split('\n') + + + + app = QtGui.QApplication(sys.argv) + w = QtGui.QMainWindow() + peers = DownloadWidget(None, + connectionName='TestDownloadWidget', + uris=TestUris + + ) + w.setCentralWidget(peers) + + #m = w.menuBar() + #m1 = m.addMenu('Peers') + #peers.populateMenu(m1) + + 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. |