SF.net SVN: fclient: [66] trunk/fclient/fclient_widgets/download_widget.py
Status: Pre-Alpha
Brought to you by:
jurner
|
From: <jU...@us...> - 2007-11-10 11:30:23
|
Revision: 66
http://fclient.svn.sourceforge.net/fclient/?rev=66&view=rev
Author: jUrner
Date: 2007-11-10 03:30:27 -0800 (Sat, 10 Nov 2007)
Log Message:
-----------
implemented actual download of uris
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-10 11:28:52 UTC (rev 65)
+++ trunk/fclient/fclient_widgets/download_widget.py 2007-11-10 11:30:27 UTC (rev 66)
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+
"""Sketch for a download widget
"""
@@ -105,6 +107,8 @@
self._requestError = None
self._requestIdentifier = requestIdentifier
+ self._requestName = None
+ self._requestNamePostfix = None
self._requestStatus = self.StatusNone
self._requestInitTime = time.time()
self._uri = uri
@@ -144,20 +148,50 @@
self.setText(self.IndexMimeType, mimeType)
def requestMimeType(self):
- """Returns the mime type of the item"""
- return self.text(self.IndexMimeType)
+ """Returns the mime type of the item
+ @return: (unicode) request mime type
+ """
+ return unicode(self.text(self.IndexMimeType))
+
def setRequestName(self, name):
"""Sets the request name of the item
@param name: (str) name
+ @return: (unicode) name (including filename collision handling postfix)
+ @note: the name should not include the filename collision handling postfix
"""
+ self._requestName = name
+ if self._requestNamePostfix is not None:
+ name, exts = namespace.split_extensions(name)
+ name = '%s (%s)%s' % (name, self._requestNamePostfix, ''.join(exts))
self.setText(self.IndexName, name)
+ return name
- def requestName(self):
+
+ def increaseRequestNamePostfix(self):
+ """Increases the filename collision handling postfix by one
+ @return: (unicode) new request name
+ @note: use this to compose one of these 'filename (1).txt' filenames in case of
+ filename collisons
+ """
+ if self._requestNamePostfix is None:
+ self._requestNamePostfix = 1
+ else:
+ self._requestNamePostfix += 1
+ return self.setRequestName(self.requestName(includePostfix=False))
+
+
+ def requestName(self, includePostfix=True):
"""Returns the request name of the item
+ @param includePostfix: if True, returns the request name including file collision handling postfi,
+ if False the request name is returned without postfix
+ @return: (unicode) request name
"""
- return self.text(self.IndexName)
+ if includePostfix:
+ return unicode(self.text(self.IndexName))
+ return self._requestName
+
def setRequestPriority(self, priority):
"""Sets the request priority of the item
@param prority: (FcpClient.Priority)
@@ -165,8 +199,10 @@
self.setText(self.IndexPriority, priority)
def requestPriority(self):
- """Returns the request priority of the item"""
- return self.text(self.IndexPriority)
+ """Returns the request priority of the item
+ @return: (unicode) request priority
+ """
+ return unicode(self.text(self.IndexPriority))
def setProgressWidget(self, tree, widget):
"""Associates a progress widget to the item
@@ -200,8 +236,10 @@
self.setText(self.IndexSize, size)
def requestSize(self):
- """Returns the request size of the item"""
- return self.text(self.IndexSize)
+ """Returns the request size of the item
+ @return: (unicode) request size
+ """
+ return unicode(self.text(self.IndexSize))
def setRequestUri(self, uri):
"""Sets the request uri of the item
@@ -253,6 +291,9 @@
#****************************************************************************
#
#****************************************************************************
+
+#TODO: no idea if the node removes requests when complete or on error or
+# if RemovePersistentRequest has to be send explicitely
class DownloadWidget(QtGui.QTreeWidget):
def __init__(self,
@@ -341,9 +382,11 @@
(self._fcpClient.events.TestDDAComplete, self.handleFcpClientTestDDAComplete),
(self._fcpClient.events.ClientRequestInfo, self.handleFcpClientRequestInfo),
- (self._fcpClient.events.ClientRequestInfoProgress, self.handleFcpClientRequestInfoProgress),
+ (self._fcpClient.events.SimpleProgress, self.handleFcpClientSimpleProgress),
+ (self._fcpClient.events.DataFound, self.handleFcpClientDataFound),
(self._fcpClient.events.GetFailed, self.handleFcpClientGetFailed),
+ (self._fcpClient.events.IdentifierCollision, self.handleFcpClientIdentifierCollision),
(self._fcpClient.events.ProtocolError, self.handleFcpClientProtocolError),
)
# take care not to connect twice
@@ -356,17 +399,52 @@
self._fcpClient.testDDA(directory, wantWriteDirectory=True)
+ #TODO: not yet handled
def handleFcpClientDisconnected(self, event, params):
"""
"""
+ def handleFcpClientDataFound(self, event, params):
+ """
+ """
+ identifier = params['Identifier']
+ item = self._downloads['Downloads'].get(identifier, None)
+ if item is not None:
+ del self._downloads['Downloads'][identifier]
+
+ progress = item.progressWidget(self)
+ status = DownloadItem.StatusDownloadComplete
+
+ item.setRequestStatus(status, self._strings.itemStatus[status])
+ progress.setColors(
+ colorBar=self._userSettings['ColorProgressBarDownloadComplete'],
+ colorBg=self._userSettings['ColorProgressBgDownloadComplete']
+ )
+
+
#TODO: how to provide extra information to the user?
def handleFcpClientGetFailed(self, event, params):
identifier = params['Identifier']
item = self._downloads['Downloads'].get(identifier, None)
if item is not None:
del self._downloads['Downloads'][identifier]
+ code = params['Code']
+ # handle file name collision
+ if code == self._fcpClient.ProtocolError.DiskTargetExists:
+ if item.requestStatus() == DownloadItem.StatusDownloading:
+ filename = os.path.join(
+ self.downloadDirectoryFromItem(item),
+ item.increaseRequestNamePostfix()
+ )
+ identifier = self.uniqueDownloadsIdentifier(self._fcpClient.IdentifierPrefix.ClientGetFile)
+ uri = item.requestUri()
+
+ self._fcpClient.clientGetFile(uri, filename, identifier=identifier)
+ self._downloads['Downloads'][identifier] = item
+ return
+
+ # handle error
progress = item.progressWidget(self)
status = DownloadItem.StatusError
@@ -381,8 +459,14 @@
colorBar=self._userSettings['ColorProgressBarError'],
colorBg=self._userSettings['ColorProgressBgError']
)
+ #raise self._fcpClient.FetchError(params)
+ #TODO: not yet handled
+ def handleFcpClientIdentifierCollision(self, vent, params):
+ pass
+
+
def handleFcpClientIdle(self, event, params):
# check if there are sownloads queued
@@ -423,31 +507,49 @@
elif status & item.StatusRequestInfoComplete:
items[status].append(item)
- # start items with info requested
- itemsToBeStarted = self._userSettings['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
-
+ downloadsToBeStarted = self._userSettings['MaxSimultaniousDownloads'] - itemsBusy
- # start pending items
- if itemsToBeStarted > 0:
- pendingItems = items[DownloadItem.StatusPending]
- pendingItems.sort(cmp=sortf)
- while pendingItems:
- itemsToBeStarted -= 1
- if itemsToBeStarted < 0:
+ #TODO: sort by priority
+ def sortf(item1, item2):
+ return cmp(item1.requestInitTime(), item2.requestInitTime())
+
+ # start downloads with info requested complete
+ if downloadsToBeStarted > 0:
+ downloadsRequestInfoComplete = items[DownloadItem.StatusRequestInfoComplete]
+ downloadsRequestInfoComplete.sort(cmp=sortf)
+ while downloadsRequestInfoComplete:
+ downloadsToBeStarted -= 1
+ if downloadsToBeStarted < 0:
break
- item = pendingItems.pop(0)
+ item = downloadsRequestInfoComplete.pop(0)
+ filename = os.path.join( self.downloadDirectoryFromItem(item), item.requestName())
+ identifier = self.uniqueDownloadsIdentifier(self._fcpClient.IdentifierPrefix.ClientGetFile)
+ progress = item.progressWidget(self)
+ status = DownloadItem.StatusDownloading
+ uri = item.requestUri()
+
+ progress.setRange(0, 0)
+ progress.setValue(0)
+ progress.setColors(
+ colorBar=self._userSettings['ColorProgressBarDownloading'],
+ colorBg=self._userSettings['ColorProgressBgDownloading']
+ )
+ item.setRequestStatus(status, self._strings.itemStatus[status])
+ self._fcpClient.clientGetFile(uri, filename, identifier=identifier)
+ self._downloads['Downloads'][identifier] = item
+
+ # start pending downloads
+ if downloadsToBeStarted > 0:
+ downloadsPending = items[DownloadItem.StatusPending]
+ downloadsPending.sort(cmp=sortf)
+ while downloadsPending:
+ downloadsToBeStarted -= 1
+ if downloadsToBeStarted < 0:
+ break
+
+ identifier = self.uniqueDownloadsIdentifier(self._fcpClient.IdentifierPrefix.ClientRequestInfo)
+ item = downloadsPending.pop(0)
progress = progressbarwrap.ProgressBarEx(self)
status = DownloadItem.StatusRequestInfo
uri = item.requestUri()
@@ -460,11 +562,9 @@
)
item.setProgressWidget(self, progress)
item.setRequestStatus(status, self._strings.itemStatus[status])
-
- identifier = self._fcpClient.clientRequestInfo(uri)
+ self._fcpClient.clientRequestInfo(uri, identifier=identifier)
self._downloads['Downloads'][identifier] = item
-
-
+
def handleFcpClientProtocolError(self, event, params):
identifier = params.get('Identifier', None)
@@ -505,7 +605,7 @@
item.setRequestSize(dataLength)
- def handleFcpClientRequestInfoProgress(self, event, params):
+ def handleFcpClientSimpleProgress(self, event, params):
identifier = params['Identifier']
item = self._downloads['Downloads'].get(identifier, None)
@@ -558,6 +658,33 @@
#TODO: retranslate item status
+ def downloadDirectoryFromItem(self, item):
+ """Returns the dirctory an item should be downloaded to
+ @param item: (QTreeWidgetItem)
+ @return: (str) directory
+ """
+ out = []
+ parent = item.parent()
+ while parent is not None:
+ out.append(parent.requestName())
+ parent = parent.parent()
+
+ out.append(self._directory)
+ out.reverse()
+ return os.path.join(*out)
+
+
+ def uniqueDownloadsIdentifier(self, identifierPrefix):
+ """Creates a new identifier that is unique to the internal sownloads dict
+ @param identifierPrefix: FcpClient.IdentifierPrefix.*
+ @return: (str) identifier
+ """
+ while True:
+ identifier = identifierPrefix + self._fcpClient.newIdentifier()
+ if identifier not in self._downloads['Downloads']:
+ return identifier
+
+
#***************************************************************************************************
#
#***************************************************************************************************
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|