summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar mkaay <mkaay@mkaay.de> 2009-12-22 17:07:35 +0100
committerGravatar mkaay <mkaay@mkaay.de> 2009-12-22 17:07:35 +0100
commited36dd5988907019cc9cc5b98265f00a52462c85 (patch)
tree855820996780a291b644d20d4424b5289b311e06
parentwebserver for win (diff)
downloadpyload-ed36dd5988907019cc9cc5b98265f00a52462c85.tar.xz
more docstrings, small design changes
-rw-r--r--module/gui/Collector.py34
-rw-r--r--module/gui/MainWindow.py107
-rw-r--r--module/gui/Queue.py79
-rw-r--r--module/gui/connector.py13
-rwxr-xr-xpyLoadGui.py111
5 files changed, 319 insertions, 25 deletions
diff --git a/module/gui/Collector.py b/module/gui/Collector.py
index 28cac097b..1d622b006 100644
--- a/module/gui/Collector.py
+++ b/module/gui/Collector.py
@@ -42,7 +42,9 @@ class PackageCollector(QThread):
def update(self):
locker = QMutexLocker(self.mutex)
packs = self.connector.getPackageCollector()
+ ids = []
for data in packs:
+ ids.append(data["id"])
pack = self.getPack(data["id"])
if not pack:
pack = self.PackageCollectorPack(self)
@@ -56,6 +58,8 @@ class PackageCollector(QThread):
child = self.PackageCollectorFile(self, pack)
child.setData(info)
pack.addChild(fid, child)
+ #pack.clear(files)
+ self.clear(ids)
def addPack(self, pid, newPack):
pos = None
@@ -83,6 +87,18 @@ class PackageCollector(QThread):
return pack
return None
+ def clear(self, ids):
+ toremove = []
+ for k, pack in enumerate(self.collector):
+ id = pack.getData()["id"]
+ if not id in ids:
+ toremove.append(k)
+ if not toremove:
+ return
+ self.collector = []
+ #self.view.clear()
+ self.view.emit(SIGNAL("clear"))
+
class PackageCollectorPack():
def __init__(self, collector):
self.collector = collector
@@ -111,6 +127,8 @@ class PackageCollector(QThread):
status = "%s (%s)" % (newChild.getData()["status_type"], newChild.getData()["plugin"])
item.setData(0, Qt.DisplayRole, QVariant(newChild.getData()["filename"]))
item.setData(0, Qt.UserRole, QVariant(cid))
+ flags = Qt.ItemIsEnabled
+ item.setFlags(flags)
def getChildren(self):
return self.children
@@ -129,6 +147,22 @@ class PackageCollector(QThread):
def getData(self):
return self.data
+
+ def clear(self, ids):
+ toremove = []
+ for k, file in enumerate(self.getChildren()):
+ id = file.getData()["id"]
+ if not id in ids:
+ toremove.append(k)
+ if not toremove:
+ return
+ ppos = self.collector.collector.index(self)
+ parent = self.collector.view.topLevelItem(ppos)
+ toremove.sort()
+ toremove.reverse()
+ for pos in toremove:
+ del self.children[k]
+ parent.takeChild(k)
class PackageCollectorFile():
def __init__(self, collector, pack):
diff --git a/module/gui/MainWindow.py b/module/gui/MainWindow.py
index 4f92f68a9..f72ad97de 100644
--- a/module/gui/MainWindow.py
+++ b/module/gui/MainWindow.py
@@ -31,7 +31,7 @@ class MainWindow(QMainWindow):
#window stuff
self.setWindowTitle("pyLoad Client")
self.setWindowIcon(QIcon("icons/logo.png"))
- self.resize(750,500)
+ self.resize(850,500)
#layout version
self.version = 1
@@ -85,13 +85,24 @@ class MainWindow(QMainWindow):
#init tabs
self.init_tabs()
+ #context menus
+ self.init_context()
+
#layout
self.masterlayout.addWidget(self.tabw)
+ #signals..
self.connect(self.mactions["manager"], SIGNAL("triggered()"), self.slotShowConnector)
self.connect(self.mactions["exit"], SIGNAL("triggered()"), self.close)
+
+ self.connect(self.tabs["queue"]["view"], SIGNAL('customContextMenuRequested(const QPoint &)'), self.slotQueueContextMenu)
+ self.connect(self.tabs["collector"]["package_view"], SIGNAL('customContextMenuRequested(const QPoint &)'), self.slotPackageCollectorContextMenu)
+ self.connect(self.tabs["collector"]["link_view"], SIGNAL('customContextMenuRequested(const QPoint &)'), self.slotLinkCollectorContextMenu)
def init_toolbar(self):
+ """
+ create toolbar
+ """
self.toolbar = self.addToolBar("Main Toolbar")
self.toolbar.setObjectName("Main Toolbar")
self.toolbar.setIconSize(QSize(40,40))
@@ -130,42 +141,102 @@ class MainWindow(QMainWindow):
groupLinks = QGroupBox("Links")
groupPackage.setLayout(QVBoxLayout())
groupLinks.setLayout(QVBoxLayout())
+ toQueue = QPushButton("Push selected packages to queue")
self.tabs["collector"]["l"] = QGridLayout()
self.tabs["collector"]["w"].setLayout(self.tabs["collector"]["l"])
self.tabs["collector"]["package_view"] = QTreeWidget()
+ self.connect(self.tabs["collector"]["package_view"], SIGNAL("clear"), self.tabs["collector"]["package_view"].clear)
self.tabs["collector"]["link_view"] = QTreeWidget()
groupPackage.layout().addWidget(self.tabs["collector"]["package_view"])
+ groupPackage.layout().addWidget(toQueue)
groupLinks.layout().addWidget(self.tabs["collector"]["link_view"])
self.tabs["collector"]["l"].addWidget(groupPackage, 0, 0)
self.tabs["collector"]["l"].addWidget(groupLinks, 0, 1)
+ self.connect(toQueue, SIGNAL("clicked()"), self.slotPushPackageToQueue)
+
+ def init_context(self):
+ """
+ create context menus
+ """
+ self.queueContext = QMenu()
+ self.queueContext.buttons = {}
+ self.queueContext.buttons["remove"] = QAction("Remove", self.queueContext)
+ self.queueContext.addAction(self.queueContext.buttons["remove"])
def slotToggleStatus(self, status):
+ """
+ pause/start toggle (toolbar)
+ """
self.emit(SIGNAL("setDownloadStatus"), status)
def slotStatusStop(self):
+ """
+ stop button (toolbar)
+
+ dummy
+ """
print "stop!"
def slotAdd(self):
+ """
+ add button (toolbar)
+ show context menu (choice: links/package)
+ """
self.addMenu.exec_(QCursor.pos())
def slotShowAddPackage(self):
+ """
+ action from add-menu
+ show new-package dock
+ """
self.tabw.setCurrentIndex(1)
self.newPackDock.show()
def slotShowAddLinks(self):
+ """
+ action from add-menu
+ show new-links dock
+ """
self.tabw.setCurrentIndex(1)
self.newLinkDock.show()
def slotShowConnector(self):
+ """
+ connectionmanager action triggered
+ let main to the stuff
+ """
self.emit(SIGNAL("connector"))
def slotAddLinks(self, links):
+ """
+ new links
+ let main to the stuff
+ """
self.emit(SIGNAL("addLinks"), links)
def slotAddPackage(self, name, ids):
+ """
+ new package
+ let main to the stuff
+ """
self.emit(SIGNAL("addPackage"), name, ids)
- def closeEvent(self, event):
+ def slotPushPackageToQueue(self):
+ """
+ push collector pack to queue
+ get child ids
+ let main to the rest
+ """
+ items = self.tabs["collector"]["package_view"].selectedItems()
+ for item in items:
+ id = item.data(0, Qt.UserRole).toPyObject()
+ self.emit(SIGNAL("pushPackageToQueue"), id)
+
+ def saveWindow(self):
+ """
+ get window state/geometry
+ pass data to main
+ """
state_raw = self.saveState(self.version)
geo_raw = self.saveGeometry()
@@ -173,9 +244,19 @@ class MainWindow(QMainWindow):
geo = str(geo_raw.toBase64())
self.emit(SIGNAL("saveMainWindow"), state, geo)
+
+ def closeEvent(self, event):
+ """
+ somebody wants to close me!
+ let me first save my state
+ """
+ self.saveWindow()
event.accept()
def restoreWindow(self, state, geo):
+ """
+ restore window state/geometry
+ """
state = QByteArray(state)
geo = QByteArray(geo)
@@ -184,4 +265,26 @@ class MainWindow(QMainWindow):
self.restoreState(state_raw, self.version)
self.restoreGeometry(geo_raw)
+
+ def slotQueueContextMenu(self, pos):
+ """
+ custom context menu in queue view requested
+ """
+ globalPos = self.tabs["queue"]["view"].mapToGlobal(pos)
+ i = self.tabs["queue"]["view"].itemAt(pos)
+ i.setSelected(True)
+ self.addFav.setData(QVariant(i))
+ self.showContext.exec_(globalPos)
+
+ def slotPackageCollectorContextMenu(self, pos):
+ """
+ custom context menu in package collector view requested
+ """
+ pass
+
+ def slotLinkCollectorContextMenu(self, pos):
+ """
+ custom context menu in link collector view requested
+ """
+ pass
diff --git a/module/gui/Queue.py b/module/gui/Queue.py
index 52f11fd8c..c9a3e858b 100644
--- a/module/gui/Queue.py
+++ b/module/gui/Queue.py
@@ -19,7 +19,7 @@
from PyQt4.QtCore import *
from PyQt4.QtGui import *
-from time import sleep
+from time import sleep, time
class Queue(QThread):
def __init__(self, view, connector):
@@ -37,8 +37,9 @@ class Queue(QThread):
}
self.statusMapReverse = dict((v,k) for k, v in self.statusMap.iteritems())
self.queue = []
- self.interval = 2
+ self.interval = 1
self.running = True
+ self.wait_dict = {}
self.mutex = QMutex()
def run(self):
@@ -54,7 +55,7 @@ class Queue(QThread):
packs = self.connector.getPackageQueue()
downloading_raw = self.connector.getDownloadQueue()
downloading = {}
- for d in downloading:
+ for d in downloading_raw:
did = d["id"]
del d["id"]
del d["name"]
@@ -73,7 +74,7 @@ class Queue(QThread):
if not child:
child = self.QueueFile(self, pack)
try:
- info["downloading"] = downloading[data["id"]]
+ info["downloading"] = downloading[info["id"]]
except:
info["downloading"] = None
child.setData(info)
@@ -98,13 +99,22 @@ class Queue(QThread):
self.view.insertTopLevelItem(pos, item)
item.setData(0, Qt.DisplayRole, QVariant(newPack.getData()["package_name"]))
status = -1
+ speed = self.getSpeed(newPack)
+ plugins = []
for child in newPack.getChildren():
if self.statusMap.has_key(child.data["status_type"]) and self.statusMap[child.data["status_type"]] > status:
status = self.statusMap[child.data["status_type"]]
+ if not child.data["plugin"] in plugins:
+ plugins.append(child.data["plugin"])
if status >= 0:
- item.setData(1, Qt.DisplayRole, QVariant(self.statusMapReverse[status]))
+ if speed == None:
+ statustxt = self.statusMapReverse[status]
+ else:
+ statustxt = "%s (%s KB/s)" % (self.statusMapReverse[status], speed)
+ item.setData(2, Qt.DisplayRole, QVariant(statustxt))
+ item.setData(1, Qt.DisplayRole, QVariant(", ".join(plugins)))
item.setData(0, Qt.UserRole, QVariant(pid))
- item.setData(2, Qt.UserRole, QVariant(newPack))
+ item.setData(3, Qt.UserRole, QVariant(newPack))
def getPack(self, pid):
for k, pack in enumerate(self.queue):
@@ -112,6 +122,27 @@ class Queue(QThread):
return pack
return None
+ def getWaitingProgress(self, q):
+ locker = QMutexLocker(self.mutex)
+ if isinstance(q, self.QueueFile):
+ data = q.getData()
+ if data["status_type"] == "waiting" and data["downloading"]:
+ until = float(data["downloading"]["wait_until"])
+ try:
+ since, until_old = self.wait_dict[data["id"]]
+ if not until == until_old:
+ raise Exception
+ except:
+ since = time()
+ self.wait_dict[data["id"]] = since, until
+ since = float(since)
+ max_wait = float(until-since)
+ rest = int(until-time())
+ res = 100/max_wait
+ perc = rest*res
+ return perc, rest
+ return None
+
def getProgress(self, q):
locker = QMutexLocker(self.mutex)
if isinstance(q, self.QueueFile):
@@ -142,7 +173,7 @@ class Queue(QThread):
return 0
def getSpeed(self, q):
- locker = QMutexLocker(self.mutex)
+ #locker = QMutexLocker(self.mutex)
if isinstance(q, self.QueueFile):
data = q.getData()
if data["downloading"]:
@@ -151,15 +182,18 @@ class Queue(QThread):
children = q.getChildren()
count = len(children)
speed_sum = 0
+ all_waiting = True
for child in children:
val = 0
data = child.getData()
running = False
if data["downloading"]:
+ if not data["status_type"] == "waiting":
+ all_waiting = False
val = int(data["downloading"]["speed"])
running = True
speed_sum += val
- if count == 0 or not running:
+ if count == 0 or not running or all_waiting:
return None
return speed_sum
return None
@@ -189,11 +223,16 @@ class Queue(QThread):
if not item:
item = QTreeWidgetItem()
parent.insertChild(pos, item)
- status = "%s (%s)" % (newChild.getData()["status_type"], newChild.getData()["plugin"])
+ speed = self.queue.getSpeed(newChild)
+ if speed == None:
+ status = newChild.getData()["status_type"]
+ else:
+ status = "%s (%s KB/s)" % (newChild.getData()["status_type"], speed)
item.setData(0, Qt.DisplayRole, QVariant(newChild.getData()["filename"]))
- item.setData(1, Qt.DisplayRole, QVariant(status))
+ item.setData(2, Qt.DisplayRole, QVariant(status))
+ item.setData(1, Qt.DisplayRole, QVariant(newChild.getData()["plugin"]))
item.setData(0, Qt.UserRole, QVariant(cid))
- item.setData(2, Qt.UserRole, QVariant(newChild))
+ item.setData(3, Qt.UserRole, QVariant(newChild))
def getChildren(self):
return self.children
@@ -217,6 +256,7 @@ class Queue(QThread):
def __init__(self, queue, pack):
self.queue = queue
self.pack = pack
+ self.wait_since = None
def getData(self):
return self.data
@@ -233,9 +273,15 @@ class QueueProgressBarDelegate(QItemDelegate):
self.queue = queue
def paint(self, painter, option, index):
- if index.column() == 2:
+ if index.column() == 3:
qe = index.data(Qt.UserRole).toPyObject()
- progress = self.queue.getProgress(qe)
+ w = self.queue.getWaitingProgress(qe)
+ wait = None
+ if w:
+ progress = w[0]
+ wait = w[1]
+ else:
+ progress = self.queue.getProgress(qe)
opts = QStyleOptionProgressBarV2()
opts.maximum = 100
opts.minimum = 0
@@ -245,11 +291,10 @@ class QueueProgressBarDelegate(QItemDelegate):
opts.rect.setHeight(option.rect.height()-1)
opts.textVisible = True
opts.textAlignment = Qt.AlignCenter
- speed = self.queue.getSpeed(qe)
- if speed == None:
- opts.text = QString.number(opts.progress) + "%"
+ if not wait == None:
+ opts.text = QString("waiting %d seconds" % (wait,))
else:
- opts.text = QString("%s kb/s - %s" % (speed, opts.progress)) + "%"
+ opts.text = QString.number(opts.progress) + "%"
QApplication.style().drawControl(QStyle.CE_ProgressBar, opts, painter)
return
QItemDelegate.paint(self, painter, option, index)
diff --git a/module/gui/connector.py b/module/gui/connector.py
index e7a151c5e..2a1ce511e 100644
--- a/module/gui/connector.py
+++ b/module/gui/connector.py
@@ -37,6 +37,9 @@ class connector(QThread):
self.addr = None
def setAddr(self, addr):
+ """
+ set new address
+ """
self.mutex.lock()
self.addr = addr
self.mutex.unlock()
@@ -197,3 +200,13 @@ class connector(QThread):
self.proxy.move_file_2_package(fileid, packid)
finally:
self.mutex.unlock()
+
+ def pushPackageToQueue(self, packid):
+ """
+ push a package to queue
+ """
+ self.mutex.lock()
+ try:
+ self.proxy.push_package_2_queue(packid)
+ finally:
+ self.mutex.unlock()
diff --git a/pyLoadGui.py b/pyLoadGui.py
index a21c27cb9..9ff070027 100755
--- a/pyLoadGui.py
+++ b/pyLoadGui.py
@@ -46,6 +46,9 @@ class main(QObject):
self.init()
def init(self):
+ """
+ set main things up
+ """
self.mainWindow = MainWindow()
self.pwWindow = PWInputWindow()
self.connWindow = ConnectionManager()
@@ -59,6 +62,9 @@ class main(QObject):
self.connWindow.show()
def startMain(self):
+ """
+ start all refresh threads and show main window
+ """
self.connector.start()
sleep(1)
self.restoreMainWindow()
@@ -69,13 +75,21 @@ class main(QObject):
self.mainloop.start()
def stopMain(self):
+ """
+ stop all refresh threads and hide main window
+ """
self.mainloop.stop()
self.connector.stop()
+ self.mainWindow.saveWindow()
self.mainWindow.hide()
self.queue.stop()
+ self.linkCollector.stop()
+ self.packageCollector.stop()
self.mainloop.wait()
self.connector.wait()
self.queue.wait()
+ self.linkCollector.wait()
+ self.packageCollector.wait()
def connectSignals(self):
"""
@@ -92,17 +106,26 @@ class main(QObject):
self.connect(self.mainWindow, SIGNAL("addPackage"), self.slotAddPackage)
self.connect(self.mainWindow, SIGNAL("setDownloadStatus"), self.slotSetDownloadStatus)
self.connect(self.mainWindow, SIGNAL("saveMainWindow"), self.slotSaveMainWindow)
+ self.connect(self.mainWindow, SIGNAL("pushPackageToQueue"), self.slotPushPackageToQueue)
def slotShowConnector(self):
+ """
+ emitted from main window (menu)
+ hide the main window and show connection manager
+ (to switch to other core)
+ """
self.stopMain()
self.init()
def quit(self):
+ """
+ quit gui
+ """
self.app.quit()
def loop(self):
"""
- start exec loop
+ start application loop
"""
sys.exit(self.app.exec_())
@@ -113,13 +136,27 @@ class main(QObject):
QMessageBox(QMessageBox.Warning, "Error", msg)
def initPackageCollector(self):
+ """
+ init the package collector view
+ * columns
+ * selection
+ * refresh thread
+ """
view = self.mainWindow.tabs["collector"]["package_view"]
view.setColumnCount(1)
view.setHeaderLabels(["Name"])
+ view.setSelectionMode(QAbstractItemView.ExtendedSelection)
self.packageCollector = PackageCollector(view, self.connector)
self.packageCollector.start()
def initLinkCollector(self):
+ """
+ init the link collector view
+ * columns
+ * selection
+ * drag'n'drop
+ * refresh thread
+ """
view = self.mainWindow.tabs["collector"]["link_view"]
view.setColumnCount(1)
view.setHeaderLabels(["Name"])
@@ -140,18 +177,28 @@ class main(QObject):
self.linkCollector.start()
def initQueue(self):
+ """
+ init the queue view
+ * columns
+ * refresh thread
+ * progressbar
+ """
view = self.mainWindow.tabs["queue"]["view"]
- view.setColumnCount(3)
- view.setHeaderLabels(["Name", "Status", "Fortschritt"])
+ view.setColumnCount(4)
+ view.setHeaderLabels(["Name", "Plugin", "Status", "Fortschritt"])
view.setColumnWidth(0, 300)
- view.setColumnWidth(1, 200)
- view.setColumnWidth(2, 100)
+ view.setColumnWidth(1, 100)
+ view.setColumnWidth(2, 200)
+ view.setColumnWidth(3, 100)
self.queue = Queue(view, self.connector)
delegate = QueueProgressBarDelegate(view, self.queue)
- view.setItemDelegateForColumn(2, delegate)
+ view.setItemDelegateForColumn(3, delegate)
self.queue.start()
def refreshServerStatus(self):
+ """
+ refresh server status and overall speed in the status bar
+ """
status = self.connector.getServerStatus()
if status["pause"]:
status["status"] = "Paused"
@@ -163,6 +210,9 @@ class main(QObject):
self.mainWindow.serverStatus.setText(text)
def getConnections(self):
+ """
+ parse all connections in the config file
+ """
connectionsNode = self.parser.xml.elementsByTagName("connections").item(0)
if connectionsNode.isNull():
raise Exception("null")
@@ -198,6 +248,9 @@ class main(QObject):
return ret
def slotSaveConnection(self, data):
+ """
+ save connection to config file
+ """
connectionsNode = self.parser.xml.elementsByTagName("connections").item(0)
if connectionsNode.isNull():
raise Exception("null")
@@ -232,6 +285,9 @@ class main(QObject):
self.refreshConnections()
def slotRemoveConnection(self, data):
+ """
+ remove connection from config file
+ """
connectionsNode = self.parser.xml.elementsByTagName("connections").item(0)
if connectionsNode.isNull():
raise Exception("null")
@@ -248,6 +304,10 @@ class main(QObject):
self.refreshConnections()
def slotConnect(self, data):
+ """
+ slot: connect button in connectionmanager
+ show password window if remote connection or start connecting
+ """
self.connWindow.hide()
self.connData = data
if data["type"] == "local":
@@ -256,6 +316,11 @@ class main(QObject):
self.pwWindow.show()
def slotPasswordTyped(self, pw):
+ """
+ connect to a core
+ if connection is local, parse the core config file for data
+ set up connector, show main window
+ """
data = self.connData
data["password"] = pw
if not data["type"] == "remote":
@@ -280,22 +345,39 @@ class main(QObject):
self.startMain()
def refreshConnections(self):
+ """
+ reload connetions and display them
+ """
self.parser.loadData()
conns = self.getConnections()
self.connWindow.emit(SIGNAL("setConnections(connections)"), conns)
def slotAddLinks(self, links):
+ """
+ emitted from main window
+ add urls to the collector
+ """
self.connector.addURLs(links)
def slotSetDownloadStatus(self, status):
+ """
+ toolbar start/pause slot
+ """
self.connector.setPause(not status)
def slotAddPackage(self, name, ids):
+ """
+ emitted from main window
+ add package to the collector
+ """
packid = self.connector.newPackage(str(name))
for fileid in ids:
self.connector.addFileToPackage(fileid, packid)
def slotSaveMainWindow(self, state, geo):
+ """
+ save the window geometry and toolbar/dock position to config file
+ """
mainWindowNode = self.parser.xml.elementsByTagName("mainWindow").item(0)
if mainWindowNode.isNull():
raise Exception("null")
@@ -312,6 +394,9 @@ class main(QObject):
self.parser.saveData()
def restoreMainWindow(self):
+ """
+ load and restore main window geometry and toolbar/dock position from config
+ """
mainWindowNode = self.parser.xml.elementsByTagName("mainWindow").item(0)
if mainWindowNode.isNull():
raise Exception("null")
@@ -322,7 +407,18 @@ class main(QObject):
self.mainWindow.restoreWindow(state, geo)
+ def slotPushPackageToQueue(self, id):
+ """
+ emitted from main window
+ push the collector package to queue
+ """
+ self.connector.pushPackageToQueue(id)
+
class Loop(QThread):
+ """
+ main loop (not application loop)
+ """
+
def __init__(self, parent):
QThread.__init__(self)
self.parent = parent
@@ -334,6 +430,9 @@ class main(QObject):
self.update()
def update(self):
+ """
+ methods to call
+ """
self.parent.refreshServerStatus()
def stop(self):