summaryrefslogtreecommitdiffstats
path: root/pyLoadGui.py
diff options
context:
space:
mode:
authorGravatar RaNaN <Mast3rRaNaN@hotmail.de> 2010-08-29 18:42:09 +0200
committerGravatar RaNaN <Mast3rRaNaN@hotmail.de> 2010-08-29 18:42:09 +0200
commitfe017986229a92a29541329650b25e1b326dc87f (patch)
treeafb4b74c4ce62e8d1b8940eff723e1a9094f9f17 /pyLoadGui.py
parentplugin updater (diff)
downloadpyload-fe017986229a92a29541329650b25e1b326dc87f.tar.xz
moved interfaces
Diffstat (limited to 'pyLoadGui.py')
-rwxr-xr-xpyLoadGui.py698
1 files changed, 698 insertions, 0 deletions
diff --git a/pyLoadGui.py b/pyLoadGui.py
new file mode 100755
index 000000000..570b2e779
--- /dev/null
+++ b/pyLoadGui.py
@@ -0,0 +1,698 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License,
+ or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+ @author: mkaay
+ @version: v0.4.0
+"""
+
+import sys
+
+from time import sleep
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from uuid import uuid4 as uuid
+import re
+import gettext
+from xmlrpclib import Binary
+from os.path import join
+from os.path import abspath
+from os.path import dirname
+
+
+from module import InitHomeDir
+from module.gui.ConnectionManager import *
+from module.gui.connector import Connector
+from module.gui.MainWindow import *
+from module.gui.Queue import *
+from module.gui.Collector import *
+from module.gui.XMLParser import *
+from module.gui.CoreConfigParser import ConfigParser
+
+from os.path import expanduser
+from os.path import join
+from os.path import basename
+from os.path import dirname
+from os import chdir
+from os import makedirs
+from os import name as platform
+
+try:
+ import pynotify
+except ImportError:
+ pass
+
+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()
+
+ translation = gettext.translation("pyLoadGui", join(pypath, "locale"), languages=[str(lang)])
+ 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
+
+ if True:
+ 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.app.quit)
+ 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.canConnect():
+ self.init()
+ return
+ self.connector.start()
+ self.connect(self.connector, SIGNAL("connectionLost"), sys.exit)
+ sleep(1)
+ 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"), sys.exit)
+ self.mainloop.stop()
+ self.connector.stop()
+ self.mainWindow.saveWindow()
+ self.mainWindow.hide()
+ self.queue.stop()
+ self.connector.wait()
+
+ def connectSignals(self):
+ """
+ signal and slot stuff, yay!
+ """
+ self.connect(self.connector, SIGNAL("error_box"), 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("setPriority"), self.slotSetPriority)
+ self.connect(self.mainWindow, SIGNAL("reloadAccounts"), self.slotReloadAccounts)
+
+ self.connect(self.mainWindow, SIGNAL("quit"), self.quit)
+ 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.stopMain()
+ self.init()
+
+ def quit(self):
+ """
+ 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.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")
+ else:
+ status["status"] = _("Running")
+ status["speed"] = int(status["speed"])
+ text = _("Status: %(status)s | Speed: %(speed)s kb/s") % status
+ self.mainWindow.actions["toggle_status"].setChecked(not status["pause"])
+ self.mainWindow.serverStatus.setText(text)
+
+ 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["ssl"] = subs["server"].attribute("ssl", "False")
+ if data["ssl"] == "True":
+ data["ssl"] = True
+ else:
+ data["ssl"] = False
+ 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("ssl", data["ssl"])
+ 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
+ set up connector, show main window
+ """
+ self.connWindow.hide()
+ if not data["type"] == "remote":
+
+ coreparser = ConfigParser(self.configdir)
+ if not coreparser.config:
+ raise Exception
+ #except:
+ # data["port"] = 7227
+ # data["user"] = "admin"
+ # data["password"] = "pwhere"
+ # data["host"] = "127.0.0.1"
+ # data["ssl"] = False
+
+ data["port"] = coreparser.get("remote","port")
+ data["user"] = coreparser.get("remote","username")
+ data["password"] = coreparser.get("remote","password")
+ data["host"] = "127.0.0.1"
+ data["ssl"] = coreparser.get("ssl","activated")
+ data["ssl"] = "s" if data["ssl"] else ""
+ server_url = "http%(ssl)s://%(user)s:%(password)s@%(host)s:%(port)s/" % data
+ self.connector.setAddr(str(server_url))
+ self.startMain()
+
+ 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
+ """
+ self.connector.setPause(not status)
+
+ def slotAddPackage(self, name, links):
+ """
+ emitted from main window
+ add package to the collector
+ """
+ self.connector.proxy.add_package(name, links)
+
+ def slotAddFileToPackage(self, pid, fid):
+ """
+ emitted from collector view after a drop action
+ """
+ self.connector.addFileToPackage(fid, pid)
+
+ 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.proxy.upload_container(filename, Binary(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.proxy.push_package_to_queue(id)
+
+ def slotRestartDownload(self, id, isPack):
+ """
+ emitted from main window
+ restart download
+ """
+ if isPack:
+ self.connector.restartPackage(id)
+ else:
+ self.connector.restartFile(id)
+
+ def slotRemoveDownload(self, id, isPack):
+ """
+ emitted from main window
+ remove download
+ """
+ if isPack:
+ self.connector.removePackage(id)
+ else:
+ self.connector.removeFile(id)
+
+ def slotAbortDownload(self, id, isPack):
+ """
+ emitted from main window
+ remove download
+ """
+ if isPack:
+ data = self.connector.proxy.get_package_data(id)
+ self.connector.proxy.abort_files(data["links"].keys())
+ else:
+ self.connector.proxy.abort_files([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)://[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?/.*)?")
+ matches = pattern.finditer(text)
+ for match in matches:
+ self.slotAddLinks([str(match.group(0))])
+
+ 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.proxy.pull_out_package(pid)
+
+ def slotSetPriority(self, pid, level):
+ """
+ set package priority
+ """
+ self.connector.proxy.set_priority(pid, level)
+
+ def checkCaptcha(self):
+ if self.connector.captchaWaiting() and self.mainWindow.captchaDock.isFree():
+ cid, img, imgType = self.connector.getCaptcha()
+ self.mainWindow.captchaDock.emit(SIGNAL("setTask"), cid, str(img), imgType)
+ self.mainWindow.show()
+ elif not self.mainWindow.captchaDock.isFree():
+ status = self.connector.getCaptchaStatus(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(str(cid), str(result))
+
+ def pullEvents(self):
+ events = self.connector.getEvents()
+ for event in events:
+ if event[1] == "queue":
+ self.queue.addEvent(event)
+ try:
+ if event[0] == "update" and event[2] == "file":
+ info = self.connector.getLinkInfo(event[3])
+ if info["status_type"] == "finished":
+ self.emit(SIGNAL("showMessage"), _("Finished downloading of '%s'") % info["status_filename"])
+ elif info["status_type"] == "downloading":
+ self.emit(SIGNAL("showMessage"), _("Started downloading '%s'") % info["status_filename"])
+ elif info["status_type"] == "failed":
+ self.emit(SIGNAL("showMessage"), _("Failed downloading '%s'!") % info["status_filename"])
+ if event[0] == "insert" and event[2] == "file":
+ info = self.connector.getLinkInfo(event[3])
+ self.emit(SIGNAL("showMessage"), _("Added '%s' to queue") % info["status_filename"])
+ except:
+ pass
+ elif event[1] == "collector":
+ self.packageCollector.addEvent(event)
+
+ def slotReloadAccounts(self):
+ self.mainWindow.tabs["accounts"]["view"].model().reloadData()
+
+ class Loop():
+ def __init__(self, parent):
+ self.parent = parent
+ self.timer = QTimer()
+ self.timer.connect(self.timer, SIGNAL("timeout()"), self.update)
+
+ def start(self):
+ self.update()
+ self.timer.start(1000)
+
+ def update(self):
+ """
+ methods to call
+ """
+ self.parent.refreshServerStatus()
+ self.parent.refreshLog()
+ self.parent.checkCaptcha()
+ self.parent.pullEvents()
+
+ def stop(self):
+ self.timer.stop()
+
+
+class TrayIcon(QSystemTrayIcon):
+ def __init__(self):
+ QSystemTrayIcon.__init__(self, QIcon(join(pypath, "icons", "logo.png")))
+ self.contextMenu = QMenu()
+ self.showAction = QAction(_("Show"), self.contextMenu)
+ self.showAction.setCheckable(True)
+ self.showAction.setChecked(True)
+ self.showAction.setDisabled(True)
+ self.contextMenu.addAction(self.showAction)
+ self.exitAction = QAction(QIcon(join(pypath, "icons", "close.png")), _("Exit"), self.contextMenu)
+ self.contextMenu.addAction(self.exitAction)
+ self.setContextMenu(self.contextMenu)
+
+ self.connect(self, SIGNAL("activated(QSystemTrayIcon::ActivationReason)"), self.doubleClicked)
+
+ def mainWindowHidden(self):
+ self.showAction.setChecked(False)
+
+ def doubleClicked(self, reason):
+ if self.showAction.isEnabled():
+ if reason == QSystemTrayIcon.DoubleClick:
+ self.showAction.toggle()
+
+class Notification(QObject):
+ def __init__(self, tray):
+ QObject.__init__(self)
+ self.tray = tray
+ self.usePynotify = False
+
+ try:
+ self.usePynotify = pynotify.init("icon-summary-body")
+ except:
+ pass
+
+ def showMessage(self, body):
+ if self.usePynotify:
+ n = pynotify.Notification("pyload", body, join(pypath, "icons", "logo.png"))
+ try:
+ n.set_hint_string("x-canonical-append", "")
+ except:
+ pass
+ n.show()
+ else:
+ self.tray.showMessage("pyload", body)
+
+if __name__ == "__main__":
+ app = main()
+ app.loop()
+