SF.net SVN: fclient: [57] trunk/fclient/fclient_widgets/download_widget.py
Status: Pre-Alpha
Brought to you by:
jurner
|
From: <jU...@us...> - 2007-11-07 17:35:29
|
Revision: 57
http://fclient.svn.sourceforge.net/fclient/?rev=57&view=rev
Author: jUrner
Date: 2007-11-07 09:35:34 -0800 (Wed, 07 Nov 2007)
Log Message:
-----------
continued working on downloads widget
Modified Paths:
--------------
trunk/fclient/fclient_widgets/download_widget.py
Modified: trunk/fclient/fclient_widgets/download_widget.py
===================================================================
--- trunk/fclient/fclient_widgets/download_widget.py 2007-11-07 17:35:00 UTC (rev 56)
+++ trunk/fclient/fclient_widgets/download_widget.py 2007-11-07 17:35:34 UTC (rev 57)
@@ -17,15 +17,21 @@
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
+from fclient_lib.qt4ex.ctrls import progressbarwrap
+from fclient_lib.qt4ex.ctrls import treewidgetwrap
+
+
sys.path.pop(0)
del parentdir
#<-- rel import hack
import thread
+import time
from PyQt4 import QtCore, QtGui
#*****************************************************************************
#
@@ -40,15 +46,31 @@
IndexMimeType = 4
IndexPriority = 5
- ######################
+ #TODO: implement or not ???
IndexLastProgress = 6
IndexDuration = 7
+ StatusNone = 0x0
+ StatusPending = 0x1
+ StatusRequestInfo = 0x2
+ StatusRequestInfoComplete = 0x4
+ StatusDownloading = 0x8
+ StatusDownloadComplete = 0x10
+
+ StatusError = 0x10000
+
+ StatusMaskBusy = StatusRequestInfo | StatusDownloading
+
+
+
+
def __init__(self, parent, requestIdentifier, uri):
QtGui.QTreeWidgetItem.__init__(self, parent)
self._requestIdentifier = requestIdentifier
+ self._requestStatus = self.StatusNone
+ self._requestInitTime = time.time()
self._uri = uri
@@ -58,6 +80,9 @@
def requestIdentifier(self):
return self._requestIdentifier
+ def requestInitTime(self):
+ return self._requestInitTime
+
def setRequestMimeType(self, mimeType):
self.setText(self.IndexMimeType, mimeType)
@@ -82,12 +107,13 @@
def progressWidget(self, tree):
return tree.itemWidget(self, self.IndexProgress)
- def setRequestStatus(self, status):
- self.setText(self.IndexStatus, status)
+ def setRequestStatus(self, status, text=''):
+ self._requestStatus = status
+ self.setText(self.IndexStatus, text)
def requestStatus(self):
- return self.text(self.IndexStatus)
-
+ return self._requestStatus
+
def setRequestSize(self, size):
self.setText(self.IndexSize, size)
@@ -122,6 +148,19 @@
]
self.headerSections.sort()
+ self.itemStatus = {
+ DownloadItem.StatusPending: self.trUtf8('Pending'),
+ DownloadItem.StatusRequestInfo: self.trUtf8('Requesting'),
+ DownloadItem.StatusRequestInfoComplete: self.trUtf8('Found'),
+ DownloadItem.StatusDownloading: self.trUtf8('Loading'),
+ DownloadItem.StatusDownloadComplete: self.trUtf8('Complete'),
+
+ DownloadItem.StatusError: self.trUtf8('Error'),
+ }
+
+
+ self.unknown = self.trUtf8('Unknown')
+
#****************************************************************************
#
@@ -161,24 +200,12 @@
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
- )
-
+ self._strings = None
+
# 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.setResizeMode(header.ResizeToContents)
header.setStretchLastSection(True)
self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
@@ -188,7 +215,11 @@
self.handleContextMenu
)
- # schedule initial uris
+
+ self.retranslate()
+
+
+ # schedule initial uris for download
if uris is not None:
self._downloads['DownloadDirectories'][self._directory] = (self, uris)
@@ -217,9 +248,12 @@
"""
"""
self._fcpEvents = (
+ (self._fcpClient.events.Idle, self.handleClientIdle),
(self._fcpClient.events.ClientDisconnected, self.handleClientDisconnected),
(self._fcpClient.events.TestDDAComplete, self.handleTestDDAComplete),
+ (self._fcpClient.events.ClientGetInfo, self.handleClientGetInfo),
+ (self._fcpClient.events.ClientGetInfoProgress, self.handleClientGetInfoProgress),
)
# take care not to connect twice
for event, observer in self._fcpEvents:
@@ -230,7 +264,82 @@
for directory in self._downloads['DownloadDirectories']:
self._fcpClient.testDDA(directory, wantWriteDirectory=True)
+
+
+ def handleClientIdle(self, event, msg):
+
+ # check if there are sownloads queued
+ 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)
+ status = DownloadItem.StatusPending
+
+ item.setRequestName(fileName)
+ item.setRequestStatus(status, self._strings.itemStatus[status])
+
+ #... more here
+
+ # check how many downloads are currently running
+ items = {
+ DownloadItem.StatusPending: [],
+ DownloadItem.StatusRequestInfoComplete: [],
+ }
+ itemsBusy = 0
+ enum = treewidgetwrap.TreeWidgetIterator(self)
+ for item in enum:
+ status = item.requestStatus()
+ if status & item.StatusMaskBusy:
+ itemsBusy += 1
+ elif status & item.StatusPending:
+ items[status].append(item)
+ elif status & item.StatusRequestInfoComplete:
+ items[status].append(item)
+
+ # start items with info requested
+ itemsToBeStarted = self._maxSimultaniousDownloads - itemsBusy
+ if itemsToBeStarted > 0:
+ def sortf(item1, item2):
+ return cmp(item1.requestInitTime(), item2.requestInitTime())
+
+ infoCompleteItems = items[DownloadItem.StatusRequestInfoComplete]
+ infoCompleteItems.sort(cmp=sortf)
+ while infoCompleteItems:
+
+ #TODO: not yet implemented
+ break
+ itemsToBeStarted -= 1
+
+
+ # start pending items
+ if itemsToBeStarted > 0:
+ pendingItems = items[DownloadItem.StatusPending]
+ pendingItems.sort(cmp=sortf)
+ while pendingItems:
+ itemsToBeStarted -= 1
+ if itemsToBeStarted < 0:
+ break
+
+ item = pendingItems.pop(0)
+ progress = progressbarwrap.ProgressBarEx(self)
+ uri = item.requestUri()
+
+
+ progress.setRange(0, 0)
+ progress.setValue(0)
+ item.setProgressWidget(self, progress)
+
+ identifier = self._fcpClient.clientGetInfo(uri)
+ self._downloads['Downloads'][identifier] = item
+
+
+
def handleClientDisconnected(self, event, params):
"""
"""
@@ -243,14 +352,9 @@
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()
+ downloads = self._downloads['DownloadDirectories'].get(directory, None)
+ if downloads is not None:
+ del self._downloads['DownloadDirectories'][directory] # ???
if downloads:
if writeAllowed == self._fcpClient.FcpTrue:
@@ -261,52 +365,60 @@
else:
pass
#TODO: write access denied, error
-
+
+
+ def handleClientGetInfo(self, event, params):
+
+ identifier = params['Identifier']
+ item = self._downloads['Downloads'].get(identifier, None)
+ if item is not None:
+ del self._downloads['Downloads'][identifier]
+
+ status = DownloadItem.StatusRequestInfoComplete
+ mimeType = params.get('Metadata.ContentType', self._strings.unknown)
+ dataLength = params.get('DataLength', '')
+ try:
+ dataLength = int(dataLength)
+ except ValueError:
+ dataLength = self._strings.unknown
+ else:
+ dataLength = numbers.format_num_bytes(dataLength)
+
+ item.setRequestStatus(status, self._strings.itemStatus[status])
+ item.setRequestMimeType(mimeType)
+ item.setRequestSize(dataLength)
+
+
+
+ def handleClientGetInfoProgress(self, event, params):
+
+ identifier = params['Identifier']
+ item = self._downloads['Downloads'].get(identifier, None)
+ if item is not None:
+ progress = item.progressWidget(self)
+ required=int(params['Required'])
+ succeeded=int(params['Succeeded'])
+
+ if required != progress.maximum():
+ progress.setRange(0, required)
+ progress.setValue(succeeded)
+
#######################################################
##
## 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()
+ self._downloads['DownloadQueue'].append( (parent, uri) )
+ #TODO: adjust priority?
- if not self._timer.isActive():
- self._timer.start()
-
-
+
def retranslate(self):
- pass
+ self._strings = DownloadWidgetStrings(self)
+ self.setHeaderLabels([i[1] for i in self._strings.headerSections])
+
+ #TODO: retranslate item status
+
#***************************************************************************************************
#
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|