diff options
| author | 2009-12-22 17:07:35 +0100 | |
|---|---|---|
| committer | 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): | 
