Skip to content

Commit ad0df38

Browse files
ui: better system notifications
Try to use Desktop Environment notifications whenever possible, and fallback to Qt's notifications system if it fails. Related: #1464
1 parent ff05d94 commit ad0df38

File tree

2 files changed

+92
-45
lines changed

2 files changed

+92
-45
lines changed

ui/opensnitch/notifications.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,9 @@ def __init__(self):
7575
self.DOES_SUPPORT_ACTIONS = False
7676

7777
except Exception as e:
78-
print("DesktopNotifications not available (install python3-notify2):", e)
7978
self.IS_LIBNOTIFY_AVAILABLE = False
79+
print("[WARNING] DesktopNotifications not available. Try installing the package python3-notify2")
80+
print(e)
8081

8182
def is_available(self):
8283
return self.IS_LIBNOTIFY_AVAILABLE

ui/opensnitch/service.py

Lines changed: 90 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -248,10 +248,13 @@ def _on_switch_autostart(self):
248248
try:
249249
self._autostart.enable(self._menu_autostart.isChecked())
250250
except Exception as e:
251-
self._desktop_notifications.show(
252-
QC.translate("stats", "Warning"),
253-
QC.translate("stats", str(e))
254-
)
251+
has_ntfs, ntfs_type = self._has_desktop_notifications()
252+
if has_ntfs:
253+
self.show_systray_msg(
254+
QC.translate("stats", "Warning"),
255+
QC.translate("stats", "Error switching autostart: {0}".format(str(e))),
256+
mtype=ntfs_type
257+
)
255258

256259
def _on_show_menu(self):
257260
self._menu_autostart.setChecked(self._autostart.isEnabled())
@@ -269,24 +272,49 @@ def __show_gui():
269272

270273
QtCore.QTimer.singleShot(10000, __show_gui)
271274

275+
def show_systray_msg(self, title, body, icon=None, callback=None, user_args=None, mtype=Config.NOTIFICATION_TYPE_QT, timeout=10):
276+
try:
277+
if mtype == Config.NOTIFICATION_TYPE_QT:
278+
if not isinstance(icon, QtWidgets.QSystemTrayIcon.MessageIcon):
279+
icon = QtWidgets.QSystemTrayIcon.MessageIcon.Information
280+
self._tray.showMessage(title, body, icon, timeout * 1000)
281+
else:
282+
if icon is None:
283+
icon = "dialog-information"
284+
self._desktop_notifications.show(
285+
title,
286+
body,
287+
icon,
288+
callback=callback
289+
)
290+
except Exception as e:
291+
print("[service] error showing notification:", e)
292+
print(title, body)
293+
272294
def _show_systray_msg_error(self):
273-
print("")
274-
print("WARNING: system tray not available. On GNOME you need the extension gnome-shell-extension-appindicator.")
275-
print("\tRead more:", Config.HELP_SYSTRAY_WARN)
276-
print("\tIf you want to start OpenSnitch GUI in background even if tray not available, use --background argument.")
277-
print("")
278-
279-
hide_msg = self._cfg.getBool(Config.DEFAULT_HIDE_SYSTRAY_WARN)
280-
if hide_msg:
281-
return
282-
self._desktop_notifications.show(
283-
QC.translate("stats", "WARNING"),
284-
QC.translate("stats", """System tray not available. Read more:
295+
try:
296+
print("")
297+
print("WARNING: system tray not available. On GNOME you need the extension gnome-shell-extension-appindicator.")
298+
print("\tRead more:", Config.HELP_SYSTRAY_WARN)
299+
print("\tIf you want to start OpenSnitch GUI in background even if tray not available, use --background argument.")
300+
print("")
301+
302+
hide_msg = self._cfg.getBool(Config.DEFAULT_HIDE_SYSTRAY_WARN)
303+
if hide_msg:
304+
return
305+
has_ntfs, ntf_type = self._has_desktop_notifications()
306+
if has_ntfs:
307+
self.show_systray_msg(
308+
QC.translate("stats", "WARNING"),
309+
QC.translate("stats", """System tray not available. Read more:
285310
{0}
286311
""".format(Config.HELP_SYSTRAY_WARN)),
287-
os.path.join(self._path, "res/icon-white.svg")
288-
)
289-
self._cfg.setSettings(Config.DEFAULT_HIDE_SYSTRAY_WARN, True)
312+
icon=os.path.join(self._path, "res/icon-white.svg"),
313+
mtype=ntf_type
314+
)
315+
self._cfg.setSettings(Config.DEFAULT_HIDE_SYSTRAY_WARN, True)
316+
except Exception as e:
317+
print("[service] exception showing systray msg error:", e)
290318

291319
def _on_tray_icon_activated(self, reason):
292320
if reason == QtWidgets.QSystemTrayIcon.ActivationReason.Trigger or reason == QtWidgets.QSystemTrayIcon.ActivationReason.MiddleClick:
@@ -421,12 +449,17 @@ def _on_stats_dialog_shown(self):
421449
@QtCore.pyqtSlot(str, ui_pb2.NotificationReply)
422450
def _on_notification_reply(self, addr, reply):
423451
if reply.code == ui_pb2.ERROR:
424-
self._tray.showMessage(
425-
"Error",
426-
reply.data,
427-
QtWidgets.QSystemTrayIcon.MessageIcon.Information,
428-
5000
429-
)
452+
has_ntfs, ntf_type = self._has_desktop_notifications()
453+
if has_ntfs:
454+
self.show_systray_msg(
455+
"Error",
456+
reply.data,
457+
icon=os.path.join(self._path, "res/icon-white.svg"),
458+
mtype=ntf_type,
459+
timeout=5000
460+
)
461+
else:
462+
print("[service] notification reply error:", addr, reply.data)
430463

431464
def _on_remote_stats_menu(self, address):
432465
self._remote_stats[address]['dialog'].show()
@@ -439,21 +472,22 @@ def callback_open_clicked(notifObject, action):
439472
#self._stats_dialog.raise()
440473
self._stats_dialog.activateWindow()
441474

442-
if self._desktop_notifications.are_enabled():
475+
has_ntfs, ntf_type = self._has_desktop_notifications()
476+
if has_ntfs:
443477
timeout = self._cfg.getInt(Config.DEFAULT_TIMEOUT_KEY, 15)
444-
445-
if self._desktop_notifications.is_available() and self._cfg.getInt(Config.NOTIFICATIONS_TYPE, 1) == Config.NOTIFICATION_TYPE_SYSTEM:
446-
try:
447-
self._desktop_notifications.show(
448-
title,
449-
body,
450-
os.path.join(self._path, "res/icon-white.svg"),
451-
callback=callback_open_clicked
452-
)
453-
except:
454-
self._tray.showMessage(title, body, icon, timeout * 1000)
455-
else:
478+
try:
479+
self.show_systray_msg(
480+
title,
481+
body,
482+
icon=os.path.join(self._path, "res/icon-white.svg"),
483+
callback=callback_open_clicked,
484+
mtype=ntf_type,
485+
timeout=timeout
486+
)
487+
except:
456488
self._tray.showMessage(title, body, icon, timeout * 1000)
489+
else:
490+
self._tray.showMessage(title, body, icon, timeout * 1000)
457491

458492
if icon == QtWidgets.QSystemTrayIcon.MessageIcon.NoIcon:
459493
self._tray.setIcon(self.alert_icon)
@@ -474,6 +508,13 @@ def _on_settings_saved(self):
474508
if theme_idx > 0:
475509
self._themes.load_theme(self._app)
476510

511+
def _has_desktop_notifications(self):
512+
desk_ntfs_available = self._desktop_notifications.is_available() and self._desktop_notifications.are_enabled()
513+
if desk_ntfs_available:
514+
ntf_type = Config.NOTIFICATION_TYPE_SYSTEM
515+
ntf_type = self._cfg.getInt(Config.NOTIFICATIONS_TYPE, ntf_type)
516+
return self._tray.isSystemTrayAvailable() or desk_ntfs_available, ntf_type
517+
477518
def _init_translation(self):
478519
if self.translator:
479520
self._app.removeTranslator(self.translator)
@@ -547,12 +588,17 @@ def _enable_interception(self, enable):
547588
if self._connected == False:
548589
return
549590
if self._nodes.count() == 0:
550-
self._tray.showMessage(
551-
QC.translated("stats", "No nodes connected"),
552-
"",
553-
QtWidgets.QSystemTrayIcon.MessageIcon.Information,
554-
5000
555-
)
591+
has_ntfs, ntfs_type = self._has_desktop_notifications()
592+
if has_ntfs:
593+
self.show_systray_msg(
594+
QC.translated("stats", "No nodes connected"),
595+
"",
596+
icon=QtWidgets.QSystemTrayIcon.MessageIcon.Information,
597+
mtype=ntfs_type,
598+
timeout=5000
599+
)
600+
else:
601+
print("[service] enable_interception: no nodes connected")
556602
return
557603
if self._nodes.count() > 1:
558604
print("enable interception for all nodes not supported yet")

0 commit comments

Comments
 (0)