From 92870512d97af3674e1dfed9639fed528058f373 Mon Sep 17 00:00:00 2001 From: Alexander Schlarb Date: Wed, 28 Oct 2020 17:11:51 +0100 Subject: [PATCH 1/2] Drop `org.kde.VisualNotifications` notifier as it has long since been supplanted by the equivalent FreeDesktop facility and doesn't even exist in KDE 5 anymore --- src/calibre/gui2/notify.py | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/src/calibre/gui2/notify.py b/src/calibre/gui2/notify.py index 0973bf5db5..671dd2192e 100644 --- a/src/calibre/gui2/notify.py +++ b/src/calibre/gui2/notify.py @@ -49,24 +49,6 @@ class DBUSNotifier(Notifier): prints(server, 'found' if self.ok else 'not found', 'in', '%.1f' % (time.time() - start), 'seconds') -class KDENotifier(DBUSNotifier): - - SERVICE = 'org.kde.VisualNotifications', '/VisualNotifications', 'org.kde.VisualNotifications' - - def __call__(self, body, summary=None, replaces_id=None, timeout=0): - if replaces_id is None: - replaces_id = self.dbus.UInt32() - event_id = '' - timeout, body, summary = self.get_msg_parms(timeout, body, summary) - try: - self._notify.Notify('calibre', replaces_id, event_id, self.ICON, summary, body, - self.dbus.Array(signature='s'), self.dbus.Dictionary(signature='sv'), - timeout) - except: - import traceback - traceback.print_exc() - - class FDONotifier(DBUSNotifier): SERVICE = 'org.freedesktop.Notifications', '/org/freedesktop/Notifications', 'org.freedesktop.Notifications' @@ -88,7 +70,7 @@ def get_dbus_notifier(): import dbus session_bus = dbus.SessionBus() names = frozenset(session_bus.list_names()) - for srv in KDENotifier, FDONotifier: + for srv in (FDONotifier,): if srv.SERVICE[0] in names: ans = srv(session_bus) if ans.ok: From 59818ed377e5780c3ba6fcdaaeded6df4b180343 Mon Sep 17 00:00:00 2001 From: Alexander Schlarb Date: Thu, 29 Oct 2020 00:46:10 +0100 Subject: [PATCH 2/2] Add xdg-desktop-portal based notifier backend that works without special priviledges in Linux sandbox contexts --- src/calibre/gui2/notify.py | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/calibre/gui2/notify.py b/src/calibre/gui2/notify.py index 671dd2192e..d127822d14 100644 --- a/src/calibre/gui2/notify.py +++ b/src/calibre/gui2/notify.py @@ -30,7 +30,13 @@ class Notifier(object): class DBUSNotifier(Notifier): + #XXX: Really, this should instead just send the themable icon name + # + # Doing that however, requires Calibre to first be converted to use + # its AppID everywhere and then we still need a fallback for portable + # installations. ICON = I('lt.png') + ICON_DATA = I('lt.png', data=True) def __init__(self, session_bus): self.ok, self.err = True, None @@ -66,11 +72,38 @@ class FDONotifier(DBUSNotifier): traceback.print_exc() +class XDPNotifier(DBUSNotifier): + + SERVICE = 'org.freedesktop.portal.Desktop', '/org/freedesktop/portal/desktop', 'org.freedesktop.portal.Notification' + + def __call__(self, body, summary=None, replaces_id=None, timeout=0): + if replaces_id is None: + replaces_id = self.dbus.UInt32() + _, body, summary = self.get_msg_parms(timeout, body, summary) + # Note: This backend does not natively support the notion of timeouts + # + # While the effect may be emulated by manually withdrawing the notifi- + # cation from the Calibre side, this resulted in a less than optimal + # User Experience. Based on this, KG decided it to be better to not + # support timeouts at all for this backend. + # + # See discussion at https://github.com/kovidgoyal/calibre/pull/1268. + try: + self._notify.AddNotification(str(replaces_id), self.dbus.Dictionary({ + "title": self.dbus.String(summary), + "body": self.dbus.String(body), + "icon": self.dbus.Struct(("bytes", self.dbus.ByteArray(self.ICON_DATA, variant_level=1)), signature='sv'), + }, signature='sv')) + except: + import traceback + traceback.print_exc() + + def get_dbus_notifier(): import dbus session_bus = dbus.SessionBus() names = frozenset(session_bus.list_names()) - for srv in (FDONotifier,): + for srv in (FDONotifier, XDPNotifier): if srv.SERVICE[0] in names: ans = srv(session_bus) if ans.ok: