diff options
author | mkaay <mkaay@mkaay.de> | 2009-12-22 17:07:35 +0100 |
---|---|---|
committer | mkaay <mkaay@mkaay.de> | 2009-12-22 17:07:35 +0100 |
commit | ed36dd5988907019cc9cc5b98265f00a52462c85 (patch) | |
tree | 855820996780a291b644d20d4424b5289b311e06 | |
parent | webserver for win (diff) | |
download | pyload-ed36dd5988907019cc9cc5b98265f00a52462c85.tar.xz |
more docstrings, small design changes
-rw-r--r-- | module/gui/Collector.py | 34 | ||||
-rw-r--r-- | module/gui/MainWindow.py | 107 | ||||
-rw-r--r-- | module/gui/Queue.py | 79 | ||||
-rw-r--r-- | module/gui/connector.py | 13 | ||||
-rwxr-xr-x | pyLoadGui.py | 111 |
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): |