def init(self, first=False): """ set main things up """ self.parser = XMLParser( join(self.configdir, "gui.xml"), join(self.path, "module", "config", "gui_default.xml")) lang = self.parser.xml.elementsByTagName("language").item( 0).toElement().text() if not lang: parser = XMLParser( join(self.path, "module", "config", "gui_default.xml")) lang = parser.xml.elementsByTagName("language").item( 0).toElement().text() gettext.setpaths( [join(os.sep, "usr", "share", "pyload", "locale"), None]) translation = gettext.translation( "pyLoadGui", join(pypath, "locale"), languages=[str(lang), "en"], fallback=True, ) install_translation(translation) self.connector = Connector() self.mainWindow = MainWindow(self.connector) self.connWindow = ConnectionManager() self.mainloop = self.Loop(self) self.connectSignals() self.checkClipboard = False default = self.refreshConnections() self.connData = None self.captchaProcessing = False self.serverStatus = {"freespace": 0} self.core = None # pyLoadCore if started self.connectionLost = False if True: # when used if first, minimizing not working correctly.. self.tray = TrayIcon() self.tray.show() self.notification = Notification(self.tray) self.connect(self, SIGNAL("showMessage"), self.notification.showMessage) self.connect(self.tray.exitAction, SIGNAL("triggered()"), self.slotQuit) self.connect(self.tray.showAction, SIGNAL("toggled(bool)"), self.mainWindow.setVisible) self.connect(self.mainWindow, SIGNAL("hidden"), self.tray.mainWindowHidden) if not first: self.connWindow.show() else: self.connWindow.edit.setData(default) data = self.connWindow.edit.getData() self.slotConnect(data)
def init(self, first=False): """ set main things up """ self.parser = XMLParser(join(self.configdir, "gui.xml"), join(self.path, "module", "config", "gui_default.xml")) lang = self.parser.xml.elementsByTagName("language").item(0).toElement().text() if not lang: parser = XMLParser(join(self.path, "module", "config", "gui_default.xml")) lang = parser.xml.elementsByTagName("language").item(0).toElement().text() gettext.setpaths([join(os.sep, "usr", "share", "pyload", "locale"), None]) translation = gettext.translation("pyLoadGui", join(pypath, "locale"), languages=[str(lang), "en"], fallback=True) try: translation.install(unicode=(True if sys.stdout.encoding.lower().startswith("utf") else False)) except: translation.install(unicode=False) self.connector = Connector() self.mainWindow = MainWindow(self.connector) self.connWindow = ConnectionManager() self.mainloop = self.Loop(self) self.connectSignals() self.checkClipboard = False default = self.refreshConnections() self.connData = None self.captchaProcessing = False self.serverStatus = {"freespace":0} self.core = None # pyLoadCore if started self.connectionLost = False if True: # when used if first, minimizing not working correctly.. self.tray = TrayIcon() self.tray.show() self.notification = Notification(self.tray) self.connect(self, SIGNAL("showMessage"), self.notification.showMessage) self.connect(self.tray.exitAction, SIGNAL("triggered()"), self.slotQuit) self.connect(self.tray.showAction, SIGNAL("toggled(bool)"), self.mainWindow.setVisible) self.connect(self.mainWindow, SIGNAL("hidden"), self.tray.mainWindowHidden) if not first: self.connWindow.show() else: self.connWindow.edit.setData(default) data = self.connWindow.edit.getData() self.slotConnect(data)
class main(QObject): def __init__(self): """ main setup """ QObject.__init__(self) self.app = QApplication(sys.argv) self.path = pypath self.homedir = abspath("") self.configdir = "" self.init(True) def init(self, first=False): """ set main things up """ self.parser = XMLParser( join(self.configdir, "gui.xml"), join(self.path, "module", "config", "gui_default.xml")) lang = self.parser.xml.elementsByTagName("language").item( 0).toElement().text() if not lang: parser = XMLParser( join(self.path, "module", "config", "gui_default.xml")) lang = parser.xml.elementsByTagName("language").item( 0).toElement().text() gettext.setpaths( [join(os.sep, "usr", "share", "pyload", "locale"), None]) translation = gettext.translation( "pyLoadGui", join(pypath, "locale"), languages=[str(lang), "en"], fallback=True, ) install_translation(translation) self.connector = Connector() self.mainWindow = MainWindow(self.connector) self.connWindow = ConnectionManager() self.mainloop = self.Loop(self) self.connectSignals() self.checkClipboard = False default = self.refreshConnections() self.connData = None self.captchaProcessing = False self.serverStatus = {"freespace": 0} self.core = None # pyLoadCore if started self.connectionLost = False if True: # when used if first, minimizing not working correctly.. self.tray = TrayIcon() self.tray.show() self.notification = Notification(self.tray) self.connect(self, SIGNAL("showMessage"), self.notification.showMessage) self.connect(self.tray.exitAction, SIGNAL("triggered()"), self.slotQuit) self.connect(self.tray.showAction, SIGNAL("toggled(bool)"), self.mainWindow.setVisible) self.connect(self.mainWindow, SIGNAL("hidden"), self.tray.mainWindowHidden) if not first: self.connWindow.show() else: self.connWindow.edit.setData(default) data = self.connWindow.edit.getData() self.slotConnect(data) def startMain(self): """ start all refresh threads and show main window """ if not self.connector.connectProxy(): self.init() return self.connect(self.connector, SIGNAL("connectionLost"), self.slotConnectionLost) self.restoreMainWindow() self.mainWindow.show() self.initQueue() self.initPackageCollector() self.mainloop.start() self.clipboard = self.app.clipboard() self.connect(self.clipboard, SIGNAL('dataChanged()'), self.slotClipboardChange) self.mainWindow.actions["clipboard"].setChecked(self.checkClipboard) self.mainWindow.tabs["settings"]["w"].setConnector(self.connector) self.mainWindow.tabs["settings"]["w"].loadConfig() self.tray.showAction.setDisabled(False) def stopMain(self): """ stop all refresh threads and hide main window """ self.tray.showAction.setDisabled(True) self.disconnect(self.clipboard, SIGNAL('dataChanged()'), self.slotClipboardChange) self.disconnect(self.connector, SIGNAL("connectionLost"), self.slotConnectionLost) self.mainloop.stop() self.mainWindow.saveWindow() self.mainWindow.hide() self.queue.stop() def connectSignals(self): """ signal and slot stuff, yay! """ self.connect(self.connector, SIGNAL("errorBox"), self.slotErrorBox) self.connect(self.connWindow, SIGNAL("saveConnection"), self.slotSaveConnection) self.connect(self.connWindow, SIGNAL("removeConnection"), self.slotRemoveConnection) self.connect(self.connWindow, SIGNAL("connect"), self.slotConnect) self.connect(self.mainWindow, SIGNAL("connector"), self.slotShowConnector) 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) self.connect(self.mainWindow, SIGNAL("restartDownload"), self.slotRestartDownload) self.connect(self.mainWindow, SIGNAL("removeDownload"), self.slotRemoveDownload) self.connect(self.mainWindow, SIGNAL("abortDownload"), self.slotAbortDownload) self.connect(self.mainWindow, SIGNAL("addContainer"), self.slotAddContainer) self.connect(self.mainWindow, SIGNAL("stopAllDownloads"), self.slotStopAllDownloads) self.connect(self.mainWindow, SIGNAL("setClipboardStatus"), self.slotSetClipboardStatus) self.connect(self.mainWindow, SIGNAL("changePackageName"), self.slotChangePackageName) self.connect(self.mainWindow, SIGNAL("pullOutPackage"), self.slotPullOutPackage) self.connect(self.mainWindow, SIGNAL("refreshStatus"), self.slotRefreshStatus) self.connect(self.mainWindow, SIGNAL("reloadAccounts"), self.slotReloadAccounts) self.connect(self.mainWindow, SIGNAL("Quit"), self.slotQuit) self.connect(self.mainWindow.mactions["exit"], SIGNAL("triggered()"), self.slotQuit) self.connect(self.mainWindow.captchaDock, SIGNAL("done"), self.slotCaptchaDone) def slotShowConnector(self): """ emitted from main window (menu) hide the main window and show connection manager (to switch to other core) """ self.quitInternal() self.stopMain() self.init() #def quit(self): #not used anymore? # """ # quit gui # """ # self.app.quit() def loop(self): """ start application loop """ sys.exit(self.app.exec_()) def slotErrorBox(self, msg): """ display a nice error box """ msgb = QMessageBox(QMessageBox.Warning, "Error", msg) msgb.exec_() def initPackageCollector(self): """ init the package collector view * columns * selection * refresh thread * drag'n'drop """ view = self.mainWindow.tabs["collector"]["package_view"] view.setSelectionBehavior(QAbstractItemView.SelectRows) view.setSelectionMode(QAbstractItemView.ExtendedSelection) def dropEvent(klass, event): event.setDropAction(Qt.CopyAction) event.accept() view = event.source() if view == klass: items = view.selectedItems() for item in items: if not hasattr(item.parent(), "getPackData"): continue target = view.itemAt(event.pos()) if not hasattr(target, "getPackData"): target = target.parent() klass.emit(SIGNAL("droppedToPack"), target.getPackData()["id"], item.getFileData()["id"]) event.ignore() return items = view.selectedItems() for item in items: row = view.indexOfTopLevelItem(item) view.takeTopLevelItem(row) def dragEvent(klass, event): #view = event.source() #dragOkay = False #items = view.selectedItems() #for item in items: # if hasattr(item, "_data"): # if item._data["id"] == "fixed" or item.parent()._data["id"] == "fixed": # dragOkay = True # else: # dragOkay = True #if dragOkay: event.accept() #else: # event.ignore() view.dropEvent = dropEvent view.dragEnterEvent = dragEvent view.setDragEnabled(True) view.setDragDropMode(QAbstractItemView.DragDrop) view.setDropIndicatorShown(True) view.setDragDropOverwriteMode(True) view.connect(view, SIGNAL("droppedToPack"), self.slotAddFileToPackage) #self.packageCollector = PackageCollector(view, self.connector) self.packageCollector = view.model() def initQueue(self): """ init the queue view * columns * progressbar """ view = self.mainWindow.tabs["queue"]["view"] view.setSelectionBehavior(QAbstractItemView.SelectRows) view.setSelectionMode(QAbstractItemView.ExtendedSelection) self.queue = view.model() self.connect(self.queue, SIGNAL("updateCount"), self.slotUpdateCount) overview = self.mainWindow.tabs["overview"]["view"].model() overview.queue = self.queue self.connect(self.queue, SIGNAL("updateCount"), overview.queueChanged) self.queue.start() def slotUpdateCount(self, pc, fc): self.mainWindow.packageCount.setText("%i" % pc) self.mainWindow.fileCount.setText("%i" % fc) def refreshServerStatus(self): """ refresh server status and overall speed in the status bar """ s = self.connector.statusServer() if s.pause: self.mainWindow.status.setText(_("paused")) else: self.mainWindow.status.setText(_("running")) self.mainWindow.speed.setText(formatSpeed(s.speed)) self.mainWindow.space.setText( formatSize(self.serverStatus["freespace"])) self.mainWindow.actions["toggle_status"].setChecked(not s.pause) def refreshLog(self): """ update log window """ offset = self.mainWindow.tabs["log"]["text"].logOffset lines = self.connector.getLog(offset) if not lines: return self.mainWindow.tabs["log"]["text"].logOffset += len(lines) for line in lines: self.mainWindow.tabs["log"]["text"].emit(SIGNAL("append(QString)"), line.strip("\n")) cursor = self.mainWindow.tabs["log"]["text"].textCursor() cursor.movePosition(QTextCursor.End, QTextCursor.MoveAnchor) self.mainWindow.tabs["log"]["text"].setTextCursor(cursor) def getConnections(self): """ parse all connections in the config file """ connectionsNode = self.parser.xml.elementsByTagName( "connections").item(0) if connectionsNode.isNull(): raise Exception("null") connections = self.parser.parseNode(connectionsNode) ret = [] for conn in connections: data = {} data["type"] = conn.attribute("type", "remote") data["default"] = conn.attribute("default", "False") data["id"] = conn.attribute("id", uuid().hex) if data["default"] == "True": data["default"] = True else: data["default"] = False subs = self.parser.parseNode(conn, "dict") if "name" not in subs: data["name"] = _("Unnamed") else: data["name"] = subs["name"].text() if data["type"] == "remote": if "server" not in subs: continue else: data["host"] = subs["server"].text() data["user"] = subs["server"].attribute("user", "admin") data["port"] = int(subs["server"].attribute( "port", "7227")) data["password"] = subs["server"].attribute("password", "") ret.append(data) 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") connections = self.parser.parseNode(connectionsNode) connNode = self.parser.xml.createElement("connection") connNode.setAttribute("default", str(data["default"])) connNode.setAttribute("type", data["type"]) connNode.setAttribute("id", data["id"]) nameNode = self.parser.xml.createElement("name") nameText = self.parser.xml.createTextNode(data["name"]) nameNode.appendChild(nameText) connNode.appendChild(nameNode) if data["type"] == "remote": serverNode = self.parser.xml.createElement("server") serverNode.setAttribute("user", data["user"]) serverNode.setAttribute("port", data["port"]) serverNode.setAttribute("password", data["password"]) hostText = self.parser.xml.createTextNode(data["host"]) serverNode.appendChild(hostText) connNode.appendChild(serverNode) found = False for c in connections: cid = c.attribute("id", "None") if str(cid) == str(data["id"]): found = c break if found: connectionsNode.replaceChild(connNode, found) else: connectionsNode.appendChild(connNode) self.parser.saveData() 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") connections = self.parser.parseNode(connectionsNode) found = False for c in connections: cid = c.attribute("id", "None") if str(cid) == str(data["id"]): found = c break if found: connectionsNode.removeChild(found) self.parser.saveData() self.refreshConnections() def slotConnect(self, data): """ connect to a core if connection is local, parse the core config file for data if internal, start pyLoadCore set up connector, show main window """ self.connWindow.hide() if data["type"] not in ("remote", "internal"): coreparser = ConfigParser(self.configdir) if not coreparser.config: self.connector.setConnectionData("127.0.0.1", 7227, "anonymous", "anonymous", False) else: self.connector.setConnectionData( "127.0.0.1", coreparser.get("remote", "port"), "anonymous", "anonymous") elif data["type"] == "remote": self.connector.setConnectionData(data["host"], data["port"], data["user"], data["password"]) elif data["type"] == "internal": from pyLoadCore import Core from module.ConfigParser import ConfigParser as CoreConfig if not self.core: config = CoreConfig( ) #create so at least default config exists self.core = Core() self.core.startedInGui = True thread.start_new_thread(self.core.start, (False, False)) while not self.core.running: sleep(0.5) self.connector.proxy = self.core.api self.connector.internal = True #self.connector.setConnectionData("127.0.0.1", config.get("remote","port"), "anonymous", "anonymous") self.startMain() # try: # host = data["host"] # except: # host = "127.0.0.1" def refreshConnections(self): """ reload connetions and display them """ self.parser.loadData() conns = self.getConnections() self.connWindow.emit(SIGNAL("setConnections"), conns) for conn in conns: if conn["default"]: return conn return None def slotSetDownloadStatus(self, status): """ toolbar start/pause slot """ if status: self.connector.unpauseServer() else: self.connector.pauseServer() def slotAddPackage(self, name, links, password=None): """ emitted from main window add package to the collector """ pack = self.connector.addPackage(name, links, Destination.Collector) if password: data = {"password": password} self.connector.setPackageData(pack, data) def slotAddFileToPackage(self, pid, fid): #TODO deprecated? gets called """ emitted from collector view after a drop action """ #self.connector.addFileToPackage(fid, pid) pass def slotAddContainer(self, path): """ emitted from main window add container """ filename = basename(path) #type = "".join(filename.split(".")[-1]) fh = open(path, "r") content = fh.read() fh.close() self.connector.uploadContainer(filename, content) 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(): mainWindowNode = self.parser.xml.createElement("mainWindow") self.parser.root.appendChild(mainWindowNode) stateNode = mainWindowNode.toElement().elementsByTagName("state").item( 0) geoNode = mainWindowNode.toElement().elementsByTagName( "geometry").item(0) newStateNode = self.parser.xml.createTextNode(state) newGeoNode = self.parser.xml.createTextNode(geo) stateNode.removeChild(stateNode.firstChild()) geoNode.removeChild(geoNode.firstChild()) stateNode.appendChild(newStateNode) geoNode.appendChild(newGeoNode) 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(): return nodes = self.parser.parseNode(mainWindowNode, "dict") state = str(nodes["state"].text()) geo = str(nodes["geometry"].text()) self.mainWindow.restoreWindow(state, geo) self.mainWindow.captchaDock.hide() def slotPushPackageToQueue(self, id): """ emitted from main window push the collector package to queue """ self.connector.pushToQueue(id) def slotRestartDownload(self, id, isPack): """ emitted from main window restart download """ if isPack: self.connector.restartPackage(id) else: self.connector.restartFile(id) def slotRefreshStatus(self, id): """ emitted from main window refresh download status """ self.connector.recheckPackage(id) def slotRemoveDownload(self, id, isPack): """ emitted from main window remove download """ if isPack: self.connector.deletePackages([id]) else: self.connector.deleteFiles([id]) def slotAbortDownload(self, id, isPack): """ emitted from main window remove download """ if isPack: data = self.connector.getFileOrder(id) #less data to transmit self.connector.stopDownloads(data.values()) else: self.connector.stopDownloads([id]) def slotStopAllDownloads(self): """ emitted from main window stop all running downloads """ self.connector.stopAllDownloads() def slotClipboardChange(self): """ called if clipboard changes """ if self.checkClipboard: text = self.clipboard.text() pattern = re.compile( r"(http|https|ftp)://[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?/.*)?" ) matches = pattern.finditer(text) # thanks to: jmansour //#139 links = [str(match.group(0)) for match in matches] if len(links) == 0: return filenames = [link.rpartition("/")[2] for link in links] packagename = commonprefix(filenames) if len(packagename) == 0: packagename = filenames[0] self.slotAddPackage(packagename, links) def slotSetClipboardStatus(self, status): """ set clipboard checking """ self.checkClipboard = status def slotChangePackageName(self, pid, name): """ package name edit finished """ self.connector.setPackageName(pid, str(name)) def slotPullOutPackage(self, pid): """ pull package out of the queue """ self.connector.pullFromQueue(pid) def checkCaptcha(self): if self.connector.isCaptchaWaiting( ) and self.mainWindow.captchaDock.isFree(): t = self.connector.getCaptchaTask(False) self.mainWindow.show() self.mainWindow.raise_() self.mainWindow.activateWindow() self.mainWindow.captchaDock.emit(SIGNAL("setTask"), t.tid, b64decode(t.data), t.type) elif not self.mainWindow.captchaDock.isFree(): status = self.connector.getCaptchaTaskStatus( self.mainWindow.captchaDock.currentID) if not (status == "user" or status == "shared-user"): self.mainWindow.captchaDock.hide() self.mainWindow.captchaDock.processing = False self.mainWindow.captchaDock.currentID = None def slotCaptchaDone(self, cid, result): self.connector.setCaptchaResult(cid, str(result)) def pullEvents(self): events = self.connector.getEvents(self.connector.connectionID) if not events: return for event in events: if event.eventname == "account": self.mainWindow.emit(SIGNAL("reloadAccounts"), False) elif event.eventname == "config": pass elif event.destination == Destination.Queue: self.queue.addEvent(event) try: if event.eventname == "update" and event.type == ElementType.File: info = self.connector.getFileData(event.id) if info.statusmsg == "finished": self.emit( SIGNAL("showMessage"), _("Finished downloading of '%s'") % info.name) elif info.statusmsg == "failed": self.emit( SIGNAL("showMessage"), _("Failed downloading '%s'!") % info.name) if event.event == "insert" and event.type == ElementType.File: info = self.connector.getLinkInfo(event[3]) self.emit(SIGNAL("showMessage"), _("Added '%s' to queue") % info.name) except: print("can't send notification") elif event.destination == Destination.Collector: self.packageCollector.addEvent(event) def slotReloadAccounts(self, force=False): self.mainWindow.tabs["accounts"]["view"].model().reloadData(force) def slotQuit(self): self.tray.hide() self.quitInternal() self.app.quit() def quitInternal(self): if self.core: self.core.api.kill() for i in range(10): if self.core.shuttedDown: break sleep(0.5) def slotConnectionLost(self): if not self.connectionLost: self.connectionLost = True m = QMessageBox(QMessageBox.Critical, _("Connection lost"), _("Lost connection to the core!"), QMessageBox.Ok) m.exec_() self.slotQuit() class Loop(): def __init__(self, parent): self.parent = parent self.timer = QTimer() self.timer.connect(self.timer, SIGNAL("timeout()"), self.update) self.lastSpaceCheck = 0 def start(self): self.update() self.timer.start(1000) def update(self): """ methods to call """ self.parent.refreshServerStatus() if self.lastSpaceCheck + 5 < time(): self.lastSpaceCheck = time() self.parent.serverStatus[ "freespace"] = self.parent.connector.freeSpace() self.parent.refreshLog() self.parent.checkCaptcha() self.parent.pullEvents() def stop(self): self.timer.stop()
class main(QObject): def __init__(self): """ main setup """ QObject.__init__(self) self.app = QApplication(sys.argv) self.path = pypath self.homedir = abspath("") self.configdir = "" self.init(True) def init(self, first=False): """ set main things up """ self.parser = XMLParser(join(self.configdir, "gui.xml"), join(self.path, "module", "config", "gui_default.xml")) lang = self.parser.xml.elementsByTagName("language").item(0).toElement().text() if not lang: parser = XMLParser(join(self.path, "module", "config", "gui_default.xml")) lang = parser.xml.elementsByTagName("language").item(0).toElement().text() gettext.setpaths([join(os.sep, "usr", "share", "pyload", "locale"), None]) translation = gettext.translation("pyLoadGui", join(pypath, "locale"), languages=[str(lang), "en"], fallback=True) try: translation.install(unicode=(True if sys.stdout.encoding.lower().startswith("utf") else False)) except: translation.install(unicode=False) self.connector = Connector() self.mainWindow = MainWindow(self.connector) self.connWindow = ConnectionManager() self.mainloop = self.Loop(self) self.connectSignals() self.checkClipboard = False default = self.refreshConnections() self.connData = None self.captchaProcessing = False self.serverStatus = {"freespace":0} self.core = None # pyLoadCore if started self.connectionLost = False if True: # when used if first, minimizing not working correctly.. self.tray = TrayIcon() self.tray.show() self.notification = Notification(self.tray) self.connect(self, SIGNAL("showMessage"), self.notification.showMessage) self.connect(self.tray.exitAction, SIGNAL("triggered()"), self.slotQuit) self.connect(self.tray.showAction, SIGNAL("toggled(bool)"), self.mainWindow.setVisible) self.connect(self.mainWindow, SIGNAL("hidden"), self.tray.mainWindowHidden) if not first: self.connWindow.show() else: self.connWindow.edit.setData(default) data = self.connWindow.edit.getData() self.slotConnect(data) def startMain(self): """ start all refresh threads and show main window """ if not self.connector.connectProxy(): self.init() return self.connect(self.connector, SIGNAL("connectionLost"), self.slotConnectionLost) self.restoreMainWindow() self.mainWindow.show() self.initQueue() self.initPackageCollector() self.mainloop.start() self.clipboard = self.app.clipboard() self.connect(self.clipboard, SIGNAL('dataChanged()'), self.slotClipboardChange) self.mainWindow.actions["clipboard"].setChecked(self.checkClipboard) self.mainWindow.tabs["settings"]["w"].setConnector(self.connector) self.mainWindow.tabs["settings"]["w"].loadConfig() self.tray.showAction.setDisabled(False) def stopMain(self): """ stop all refresh threads and hide main window """ self.tray.showAction.setDisabled(True) self.disconnect(self.clipboard, SIGNAL('dataChanged()'), self.slotClipboardChange) self.disconnect(self.connector, SIGNAL("connectionLost"), self.slotConnectionLost) self.mainloop.stop() self.mainWindow.saveWindow() self.mainWindow.hide() self.queue.stop() def connectSignals(self): """ signal and slot stuff, yay! """ self.connect(self.connector, SIGNAL("errorBox"), self.slotErrorBox) self.connect(self.connWindow, SIGNAL("saveConnection"), self.slotSaveConnection) self.connect(self.connWindow, SIGNAL("removeConnection"), self.slotRemoveConnection) self.connect(self.connWindow, SIGNAL("connect"), self.slotConnect) self.connect(self.mainWindow, SIGNAL("connector"), self.slotShowConnector) 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) self.connect(self.mainWindow, SIGNAL("restartDownload"), self.slotRestartDownload) self.connect(self.mainWindow, SIGNAL("removeDownload"), self.slotRemoveDownload) self.connect(self.mainWindow, SIGNAL("abortDownload"), self.slotAbortDownload) self.connect(self.mainWindow, SIGNAL("addContainer"), self.slotAddContainer) self.connect(self.mainWindow, SIGNAL("stopAllDownloads"), self.slotStopAllDownloads) self.connect(self.mainWindow, SIGNAL("setClipboardStatus"), self.slotSetClipboardStatus) self.connect(self.mainWindow, SIGNAL("changePackageName"), self.slotChangePackageName) self.connect(self.mainWindow, SIGNAL("pullOutPackage"), self.slotPullOutPackage) self.connect(self.mainWindow, SIGNAL("refreshStatus"), self.slotRefreshStatus) self.connect(self.mainWindow, SIGNAL("reloadAccounts"), self.slotReloadAccounts) self.connect(self.mainWindow, SIGNAL("Quit"), self.slotQuit) self.connect(self.mainWindow.mactions["exit"], SIGNAL("triggered()"), self.slotQuit) self.connect(self.mainWindow.captchaDock, SIGNAL("done"), self.slotCaptchaDone) def slotShowConnector(self): """ emitted from main window (menu) hide the main window and show connection manager (to switch to other core) """ self.quitInternal() self.stopMain() self.init() #def quit(self): #not used anymore? # """ # quit gui # """ # self.app.quit() def loop(self): """ start application loop """ sys.exit(self.app.exec_()) def slotErrorBox(self, msg): """ display a nice error box """ msgb = QMessageBox(QMessageBox.Warning, "Error", msg) msgb.exec_() def initPackageCollector(self): """ init the package collector view * columns * selection * refresh thread * drag'n'drop """ view = self.mainWindow.tabs["collector"]["package_view"] view.setSelectionBehavior(QAbstractItemView.SelectRows) view.setSelectionMode(QAbstractItemView.ExtendedSelection) def dropEvent(klass, event): event.setDropAction(Qt.CopyAction) event.accept() view = event.source() if view == klass: items = view.selectedItems() for item in items: if not hasattr(item.parent(), "getPackData"): continue target = view.itemAt(event.pos()) if not hasattr(target, "getPackData"): target = target.parent() klass.emit(SIGNAL("droppedToPack"), target.getPackData()["id"], item.getFileData()["id"]) event.ignore() return items = view.selectedItems() for item in items: row = view.indexOfTopLevelItem(item) view.takeTopLevelItem(row) def dragEvent(klass, event): #view = event.source() #dragOkay = False #items = view.selectedItems() #for item in items: # if hasattr(item, "_data"): # if item._data["id"] == "fixed" or item.parent()._data["id"] == "fixed": # dragOkay = True # else: # dragOkay = True #if dragOkay: event.accept() #else: # event.ignore() view.dropEvent = dropEvent view.dragEnterEvent = dragEvent view.setDragEnabled(True) view.setDragDropMode(QAbstractItemView.DragDrop) view.setDropIndicatorShown(True) view.setDragDropOverwriteMode(True) view.connect(view, SIGNAL("droppedToPack"), self.slotAddFileToPackage) #self.packageCollector = PackageCollector(view, self.connector) self.packageCollector = view.model() def initQueue(self): """ init the queue view * columns * progressbar """ view = self.mainWindow.tabs["queue"]["view"] view.setSelectionBehavior(QAbstractItemView.SelectRows) view.setSelectionMode(QAbstractItemView.ExtendedSelection) self.queue = view.model() self.connect(self.queue, SIGNAL("updateCount"), self.slotUpdateCount) overview = self.mainWindow.tabs["overview"]["view"].model() overview.queue = self.queue self.connect(self.queue, SIGNAL("updateCount"), overview.queueChanged) self.queue.start() def slotUpdateCount(self, pc, fc): self.mainWindow.packageCount.setText("%i" % pc) self.mainWindow.fileCount.setText("%i" % fc) def refreshServerStatus(self): """ refresh server status and overall speed in the status bar """ s = self.connector.statusServer() if s.pause: self.mainWindow.status.setText(_("paused")) else: self.mainWindow.status.setText(_("running")) self.mainWindow.speed.setText(formatSpeed(s.speed)) self.mainWindow.space.setText(formatSize(self.serverStatus["freespace"])) self.mainWindow.actions["toggle_status"].setChecked(not s.pause) def refreshLog(self): """ update log window """ offset = self.mainWindow.tabs["log"]["text"].logOffset lines = self.connector.getLog(offset) if not lines: return self.mainWindow.tabs["log"]["text"].logOffset += len(lines) for line in lines: self.mainWindow.tabs["log"]["text"].emit(SIGNAL("append(QString)"), line.strip("\n")) cursor = self.mainWindow.tabs["log"]["text"].textCursor() cursor.movePosition(QTextCursor.End, QTextCursor.MoveAnchor) self.mainWindow.tabs["log"]["text"].setTextCursor(cursor) def getConnections(self): """ parse all connections in the config file """ connectionsNode = self.parser.xml.elementsByTagName("connections").item(0) if connectionsNode.isNull(): raise Exception("null") connections = self.parser.parseNode(connectionsNode) ret = [] for conn in connections: data = {} data["type"] = conn.attribute("type", "remote") data["default"] = conn.attribute("default", "False") data["id"] = conn.attribute("id", uuid().hex) if data["default"] == "True": data["default"] = True else: data["default"] = False subs = self.parser.parseNode(conn, "dict") if not subs.has_key("name"): data["name"] = _("Unnamed") else: data["name"] = subs["name"].text() if data["type"] == "remote": if not subs.has_key("server"): continue else: data["host"] = subs["server"].text() data["user"] = subs["server"].attribute("user", "admin") data["port"] = int(subs["server"].attribute("port", "7227")) data["password"] = subs["server"].attribute("password", "") ret.append(data) 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") connections = self.parser.parseNode(connectionsNode) connNode = self.parser.xml.createElement("connection") connNode.setAttribute("default", str(data["default"])) connNode.setAttribute("type", data["type"]) connNode.setAttribute("id", data["id"]) nameNode = self.parser.xml.createElement("name") nameText = self.parser.xml.createTextNode(data["name"]) nameNode.appendChild(nameText) connNode.appendChild(nameNode) if data["type"] == "remote": serverNode = self.parser.xml.createElement("server") serverNode.setAttribute("user", data["user"]) serverNode.setAttribute("port", data["port"]) serverNode.setAttribute("password", data["password"]) hostText = self.parser.xml.createTextNode(data["host"]) serverNode.appendChild(hostText) connNode.appendChild(serverNode) found = False for c in connections: cid = c.attribute("id", "None") if str(cid) == str(data["id"]): found = c break if found: connectionsNode.replaceChild(connNode, found) else: connectionsNode.appendChild(connNode) self.parser.saveData() 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") connections = self.parser.parseNode(connectionsNode) found = False for c in connections: cid = c.attribute("id", "None") if str(cid) == str(data["id"]): found = c break if found: connectionsNode.removeChild(found) self.parser.saveData() self.refreshConnections() def slotConnect(self, data): """ connect to a core if connection is local, parse the core config file for data if internal, start pyLoadCore set up connector, show main window """ self.connWindow.hide() if data["type"] not in ("remote","internal"): coreparser = ConfigParser(self.configdir) if not coreparser.config: self.connector.setConnectionData("127.0.0.1", 7227, "anonymous", "anonymous", False) else: self.connector.setConnectionData("127.0.0.1", coreparser.get("remote","port"), "anonymous", "anonymous") elif data["type"] == "remote": self.connector.setConnectionData(data["host"], data["port"], data["user"], data["password"]) elif data["type"] == "internal": from pyLoadCore import Core from module.ConfigParser import ConfigParser as CoreConfig import thread if not self.core: config = CoreConfig() #create so at least default config exists self.core = Core() self.core.startedInGui = True thread.start_new_thread(self.core.start, (False, False)) while not self.core.running: sleep(0.5) self.connector.proxy = self.core.api self.connector.internal = True #self.connector.setConnectionData("127.0.0.1", config.get("remote","port"), "anonymous", "anonymous") self.startMain() # try: # host = data["host"] # except: # host = "127.0.0.1" def refreshConnections(self): """ reload connetions and display them """ self.parser.loadData() conns = self.getConnections() self.connWindow.emit(SIGNAL("setConnections"), conns) for conn in conns: if conn["default"]: return conn return None def slotSetDownloadStatus(self, status): """ toolbar start/pause slot """ if status: self.connector.unpauseServer() else: self.connector.pauseServer() def slotAddPackage(self, name, links, password=None): """ emitted from main window add package to the collector """ pack = self.connector.addPackage(name, links, Destination.Collector) if password: data = {"password": password} self.connector.setPackageData(pack, data) def slotAddFileToPackage(self, pid, fid): #TODO deprecated? gets called """ emitted from collector view after a drop action """ #self.connector.addFileToPackage(fid, pid) pass def slotAddContainer(self, path): """ emitted from main window add container """ filename = basename(path) #type = "".join(filename.split(".")[-1]) fh = open(path, "r") content = fh.read() fh.close() self.connector.uploadContainer(filename, content) 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(): mainWindowNode = self.parser.xml.createElement("mainWindow") self.parser.root.appendChild(mainWindowNode) stateNode = mainWindowNode.toElement().elementsByTagName("state").item(0) geoNode = mainWindowNode.toElement().elementsByTagName("geometry").item(0) newStateNode = self.parser.xml.createTextNode(state) newGeoNode = self.parser.xml.createTextNode(geo) stateNode.removeChild(stateNode.firstChild()) geoNode.removeChild(geoNode.firstChild()) stateNode.appendChild(newStateNode) geoNode.appendChild(newGeoNode) 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(): return nodes = self.parser.parseNode(mainWindowNode, "dict") state = str(nodes["state"].text()) geo = str(nodes["geometry"].text()) self.mainWindow.restoreWindow(state, geo) self.mainWindow.captchaDock.hide() def slotPushPackageToQueue(self, id): """ emitted from main window push the collector package to queue """ self.connector.pushToQueue(id) def slotRestartDownload(self, id, isPack): """ emitted from main window restart download """ if isPack: self.connector.restartPackage(id) else: self.connector.restartFile(id) def slotRefreshStatus(self, id): """ emitted from main window refresh download status """ self.connector.recheckPackage(id) def slotRemoveDownload(self, id, isPack): """ emitted from main window remove download """ if isPack: self.connector.deletePackages([id]) else: self.connector.deleteFiles([id]) def slotAbortDownload(self, id, isPack): """ emitted from main window remove download """ if isPack: data = self.connector.getFileOrder(id) #less data to transmit self.connector.stopDownloads(data.values()) else: self.connector.stopDownloads([id]) def slotStopAllDownloads(self): """ emitted from main window stop all running downloads """ self.connector.stopAllDownloads() def slotClipboardChange(self): """ called if clipboard changes """ if self.checkClipboard: text = self.clipboard.text() pattern = re.compile(r"(http|https|ftp)://[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?/.*)?") matches = pattern.finditer(text) # thanks to: jmansour //#139 links = [str(match.group(0)) for match in matches] if len(links) == 0: return filenames = [link.rpartition("/")[2] for link in links] packagename = commonprefix(filenames) if len(packagename) == 0: packagename = filenames[0] self.slotAddPackage(packagename, links) def slotSetClipboardStatus(self, status): """ set clipboard checking """ self.checkClipboard = status def slotChangePackageName(self, pid, name): """ package name edit finished """ self.connector.setPackageName(pid, str(name)) def slotPullOutPackage(self, pid): """ pull package out of the queue """ self.connector.pullFromQueue(pid) def checkCaptcha(self): if self.connector.isCaptchaWaiting() and self.mainWindow.captchaDock.isFree(): t = self.connector.getCaptchaTask(False) self.mainWindow.show() self.mainWindow.raise_() self.mainWindow.activateWindow() self.mainWindow.captchaDock.emit(SIGNAL("setTask"), t.tid, b64decode(t.data), t.type) elif not self.mainWindow.captchaDock.isFree(): status = self.connector.getCaptchaTaskStatus(self.mainWindow.captchaDock.currentID) if not (status == "user" or status == "shared-user"): self.mainWindow.captchaDock.hide() self.mainWindow.captchaDock.processing = False self.mainWindow.captchaDock.currentID = None def slotCaptchaDone(self, cid, result): self.connector.setCaptchaResult(cid, str(result)) def pullEvents(self): events = self.connector.getEvents(self.connector.connectionID) if not events: return for event in events: if event.eventname == "account": self.mainWindow.emit(SIGNAL("reloadAccounts"), False) elif event.eventname == "config": pass elif event.destination == Destination.Queue: self.queue.addEvent(event) try: if event.eventname == "update" and event.type == ElementType.File: info = self.connector.getFileData(event.id) if info.statusmsg == "finished": self.emit(SIGNAL("showMessage"), _("Finished downloading of '%s'") % info.name) elif info.statusmsg == "failed": self.emit(SIGNAL("showMessage"), _("Failed downloading '%s'!") % info.name) if event.event == "insert" and event.type == ElementType.File: info = self.connector.getLinkInfo(event[3]) self.emit(SIGNAL("showMessage"), _("Added '%s' to queue") % info.name) except: print "can't send notification" elif event.destination == Destination.Collector: self.packageCollector.addEvent(event) def slotReloadAccounts(self, force=False): self.mainWindow.tabs["accounts"]["view"].model().reloadData(force) def slotQuit(self): self.tray.hide() self.quitInternal() self.app.quit() def quitInternal(self): if self.core: self.core.api.kill() for i in range(10): if self.core.shuttedDown: break sleep(0.5) def slotConnectionLost(self): if not self.connectionLost: self.connectionLost = True m = QMessageBox(QMessageBox.Critical, _("Connection lost"), _("Lost connection to the core!"), QMessageBox.Ok) m.exec_() self.slotQuit() class Loop(): def __init__(self, parent): self.parent = parent self.timer = QTimer() self.timer.connect(self.timer, SIGNAL("timeout()"), self.update) self.lastSpaceCheck = 0 def start(self): self.update() self.timer.start(1000) def update(self): """ methods to call """ self.parent.refreshServerStatus() if self.lastSpaceCheck + 5 < time(): self.lastSpaceCheck = time() self.parent.serverStatus["freespace"] = self.parent.connector.freeSpace() self.parent.refreshLog() self.parent.checkCaptcha() self.parent.pullEvents() def stop(self): self.timer.stop()