class Notifier(QObject): _conn = None _interface = None _notifications = None # a dict of notifyId: taskDict _completedTasksStat = None def __init__(self, parent): super().__init__(parent) self._conn = QDBusConnection("Xware Desktop").sessionBus() self._interface = QDBusInterface(_DBUS_NOTIFY_SERVICE, _DBUS_NOTIFY_PATH, _DBUS_NOTIFY_INTERFACE, self._conn) self._notifications = {} self._completedTasksStat = app.etmpy.completedTasksStat self._completedTasksStat.sigTaskCompleted.connect(self.notifyTask) successful = self._conn.connect(_DBUS_NOTIFY_SERVICE, _DBUS_NOTIFY_PATH, _DBUS_NOTIFY_INTERFACE, "ActionInvoked", self.slotActionInvoked) if not successful: logging.error("ActionInvoked connect failed.") self._qSound_complete = QSound(":/sound/download-complete.wav", self) @property def isConnected(self): return self._conn.isConnected() def notifyTask(self, taskId): task = self._completedTasksStat.getTask(taskId) if task.get("state", None) == 11: # see definitions in class TaskStatistic. if app.settings.getbool("frontend", "notifybysound"): self._qSound_complete.play() self._dbus_notify(task) else: # TODO: Also notify if errors occur pass def _dbus_notify(self, task): if not app.settings.getbool("frontend", "popnotifications"): return qdBusMsg = self._interface.call( "Notify", QDBusArgument("Xware Desktop", QMetaType.QString), # app_name QDBusArgument(0, QMetaType.UInt), # replace_id QDBusArgument("/opt/xware_desktop/frontend/thunder.ico", QMetaType.QString), # app_icon QDBusArgument("下载完成", QMetaType.QString), # summary QDBusArgument(task["name"], QMetaType.QString), # body QDBusArgument(["open", "打开", "openDir", "打开文件夹"], QMetaType.QStringList), # actions, { "category": "transfer.complete", }, # hints QDBusArgument(5000, QMetaType.Int), # timeout ) if qdBusMsg.errorName(): logging.error("DBus, notifyTask {}: {}".format(qdBusMsg.errorName(), qdBusMsg.errorMessage())) else: # add it to the dict self._notifications[qdBusMsg.arguments()[0]] = task @pyqtSlot(QDBusMessage) def slotActionInvoked(self, msg): notifyId, action = msg.arguments() task = self._notifications.get(notifyId, None) if not task: # other applications' notifications return name = task["name"] # filename path = task["path"] # location if action == "open": openPath = os.path.join(path, name) elif action == "openDir": openPath = path else: raise Exception("Unknown action from slotActionInvoked.") nativeOpenPath = app.mountsFaker.convertToNativePath(openPath) qUrl = QUrl.fromLocalFile(nativeOpenPath) QDesktopServices().openUrl(qUrl)
class Notifier(QObject): _conn = None _interface = None _notifications = None # a dict of notifyId: taskDict _capabilities = None _completedTasksStat = None def __init__(self, parent): super().__init__(parent) self._conn = QDBusConnection("Xware Desktop").sessionBus() self._interface = QDBusInterface(_DBUS_NOTIFY_SERVICE, _DBUS_NOTIFY_PATH, _DBUS_NOTIFY_INTERFACE, self._conn) self._notifications = {} self._completedTasksStat = app.etmpy.completedTasksStat self._completedTasksStat.sigTaskCompleted.connect(self.notifyTask) self._capabilities = self._getCapabilities() if "actions" in self._capabilities: successful = self._conn.connect(_DBUS_NOTIFY_SERVICE, _DBUS_NOTIFY_PATH, _DBUS_NOTIFY_INTERFACE, "ActionInvoked", self.slotActionInvoked) if not successful: logging.error("ActionInvoked connect failed.") self._qSound_complete = QSound(":/sound/download-complete.wav", self) @property def isConnected(self): return self._conn.isConnected() def notifyTask(self, taskId): task = self._completedTasksStat.getTask(taskId) if task.get("state", None) == 11: # see definitions in class TaskStatistic. if app.settings.getbool("frontend", "notifybysound"): self._qSound_complete.play() self._dbus_notify(task) else: # TODO: Also notify if errors occur pass def _getCapabilities(self): # get libnotify server caps and remember it. qdBusMsg = self._interface.call("GetCapabilities") if qdBusMsg.errorName(): logging.error( "cannot get org.freedesktop.Notifications.GetCapabilities") return [] else: return qdBusMsg.arguments()[0] def _dbus_notify(self, task): if not app.settings.getbool("frontend", "popnotifications"): return if "actions" in self._capabilities: actions = QDBusArgument(["open", "打开", "openDir", "打开文件夹"], QMetaType.QStringList) else: actions = QDBusArgument([], QMetaType.QStringList) qdBusMsg = self._interface.call( "Notify", QDBusArgument("Xware Desktop", QMetaType.QString), # app_name QDBusArgument(0, QMetaType.UInt), # replace_id # app_icon QDBusArgument(os.path.join(constants.FRONTEND_DIR, "thunder.ico"), QMetaType.QString), QDBusArgument("下载完成", QMetaType.QString), # summary QDBusArgument(task["name"], QMetaType.QString), # body actions, { "category": "transfer.complete", }, # hints QDBusArgument(5000, QMetaType.Int), # timeout ) if qdBusMsg.errorName(): logging.error("DBus, notifyTask {}: {}".format( qdBusMsg.errorName(), qdBusMsg.errorMessage())) else: # add it to the dict self._notifications[qdBusMsg.arguments()[0]] = task @pyqtSlot(QDBusMessage) def slotActionInvoked(self, msg): notifyId, action = msg.arguments() task = self._notifications.get(notifyId, None) if not task: # other applications' notifications return name = task["name"] # filename path = task["path"] # location if action == "open": openPath = os.path.join(path, name) elif action == "openDir": openPath = path elif action == "default": # Unity's notify osd always have a default action. return else: raise Exception( "Unknown action from slotActionInvoked: {}.".format(action)) nativeOpenPath = app.mountsFaker.convertToNativePath(openPath) qUrl = QUrl.fromLocalFile(nativeOpenPath) QDesktopServices().openUrl(qUrl)
class Notifier(QObject): def __init__(self, parent): super().__init__(parent) self._conn = QDBusConnection("Xware Desktop").sessionBus() self._interface = QDBusInterface(_DBUS_NOTIFY_SERVICE, _DBUS_NOTIFY_PATH, _DBUS_NOTIFY_INTERFACE, self._conn) self._notified = {} # a dict of notifyId: taskDict app.taskModel.taskCompleted.connect(self.notifyTaskCompleted, Qt.DirectConnection) self._capabilities = self._getCapabilities() if "actions" in self._capabilities: successful = self._conn.connect(_DBUS_NOTIFY_SERVICE, _DBUS_NOTIFY_PATH, _DBUS_NOTIFY_INTERFACE, "ActionInvoked", self.slotActionInvoked) if not successful: logging.error("ActionInvoked connect failed.") self._qSound_complete = QSound(":/sound/download-complete.wav", self) @property def isConnected(self): return self._conn.isConnected() @pyqtSlot("QObject", result = "void") def notifyTaskCompleted(self, taskItem): if app.settings.getbool("frontend", "notifybysound"): self._qSound_complete.play() if not app.settings.getbool("frontend", "popnotifications"): return self._dbus_notifyCompleted(taskItem) def _getCapabilities(self): # get libnotify server caps and remember it. qdBusMsg = self._interface.call( "GetCapabilities" ) if qdBusMsg.errorName(): logging.error("cannot get org.freedesktop.Notifications.GetCapabilities") return [] else: return qdBusMsg.arguments()[0] def _dbus_notifyCompleted(self, task: "TaskItem"): if "actions" in self._capabilities: actions = QDBusArgument(["open", "打开", "viewOneFile", "在文件夹中显示"], QMetaType.QStringList) else: actions = QDBusArgument([], QMetaType.QStringList) qdBusMsg = self._interface.call( "Notify", QDBusArgument("Xware Desktop", QMetaType.QString), # app_name QDBusArgument(0, QMetaType.UInt), # replace_id QDBusArgument("xware-desktop", QMetaType.QString), # app_icon QDBusArgument("下载完成", QMetaType.QString), # summary QDBusArgument(task.name, QMetaType.QString), # body actions, { "category": "transfer.complete", }, # hints QDBusArgument(5000, QMetaType.Int), # timeout ) if qdBusMsg.errorName(): logging.error("DBus, notifyTask {}: {}".format(qdBusMsg.errorName(), qdBusMsg.errorMessage())) else: # add it to the dict notificationId = qdBusMsg.arguments()[0] self._notified[notificationId] = task.id @pyqtSlot(QDBusMessage) def slotActionInvoked(self, msg): notifyId, action = msg.arguments() taskId = self._notified.get(notifyId, None) if not taskId: # other applications' notifications return taskItem = app.taskModel.taskManager.get(taskId, None) if not taskItem: logging.debug("taskItem cannot be found anymore in TaskModel.") return fullpath = taskItem.fullpath # path + name if action == "open": return systemOpen(fullpath) elif action == "viewOneFile": return viewOneFile(fullpath) elif action == "default": # Unity's notify osd always have a default action. return else: raise Exception("Unknown action from slotActionInvoked: {}.".format(action))
class Notifier(QObject): def __init__(self, *, taskModel, frontendSettings, parent): super().__init__(parent) self.__taskModel = taskModel self.__frontendSettings = frontendSettings self._conn = QDBusConnection("Xware Desktop").sessionBus() self._interface = QDBusInterface(_DBUS_NOTIFY_SERVICE, _DBUS_NOTIFY_PATH, _DBUS_NOTIFY_INTERFACE, self._conn) self._notified = {} # a dict of notifyId: taskDict self.__taskModel.taskCompleted.connect(self.notifyTaskCompleted, Qt.DirectConnection) self._capabilities = self._getCapabilities() if "actions" in self._capabilities: successful = self._conn.connect(_DBUS_NOTIFY_SERVICE, _DBUS_NOTIFY_PATH, _DBUS_NOTIFY_INTERFACE, "ActionInvoked", self.slotActionInvoked) if not successful: logging.error("ActionInvoked connect failed.") self._qSound_complete = QSound(":/sound/download-complete.wav", self) @property def isConnected(self): return self._conn.isConnected() @pyqtSlot("QObject", result="void") def notifyTaskCompleted(self, taskItem): if self.__frontendSettings.getbool("notifybysound"): self._qSound_complete.play() if not self.__frontendSettings.getbool("popnotifications"): return self._dbus_notifyCompleted(taskItem) def _getCapabilities(self): # get libnotify server caps and remember it. qdBusMsg = self._interface.call("GetCapabilities") if qdBusMsg.errorName(): logging.error( "cannot get org.freedesktop.Notifications.GetCapabilities") return [] else: return qdBusMsg.arguments()[0] def _dbus_notifyCompleted(self, task: "TaskItem"): if "actions" in self._capabilities: actions = QDBusArgument(["open", "打开", "viewOneFile", "在文件夹中显示"], QMetaType.QStringList) else: actions = QDBusArgument([], QMetaType.QStringList) qdBusMsg = self._interface.call( "Notify", QDBusArgument("Xware Desktop", QMetaType.QString), # app_name QDBusArgument(0, QMetaType.UInt), # replace_id QDBusArgument("xware-desktop", QMetaType.QString), # app_icon QDBusArgument("下载完成", QMetaType.QString), # summary QDBusArgument(task.name, QMetaType.QString), # body actions, { "category": "transfer.complete", }, # hints QDBusArgument(5000, QMetaType.Int), # timeout ) if qdBusMsg.errorName(): logging.error("DBus, notifyTask {}: {}".format( qdBusMsg.errorName(), qdBusMsg.errorMessage())) else: # add it to the dict notificationId = qdBusMsg.arguments()[0] self._notified[notificationId] = task.id @pyqtSlot(QDBusMessage) def slotActionInvoked(self, msg): notifyId, action = msg.arguments() taskId = self._notified.get(notifyId, None) if not taskId: # other applications' notifications return taskItem = self.__taskModel.adapterMap.get(taskId, None) if not taskItem: logging.debug("taskItem cannot be found anymore in TaskModel.") return fullpath = taskItem.fullpath # path + name if action == "open": return systemOpen(fullpath) elif action == "viewOneFile": return viewOneFile(fullpath) elif action == "default": # Unity's notify osd always have a default action. return else: raise Exception( "Unknown action from slotActionInvoked: {}.".format(action))