diff --git a/lib/solaar/gtk.py b/lib/solaar/gtk.py index c34661f3..2ae9b694 100644 --- a/lib/solaar/gtk.py +++ b/lib/solaar/gtk.py @@ -40,41 +40,15 @@ def _parse_arguments(): def _run(args): - from logging import getLogger, DEBUG as _DEBUG - _log = getLogger(__name__) - del getLogger - import solaar.ui as ui - ui.notify.init() - - status_icon = ui.status_icon.create(ui.main_window.toggle_all, ui.main_window.popup) - assert status_icon - - # callback delivering status notifications from the receiver/devices to the UI - from logitech.unifying_receiver.status import ALERT - def status_changed(device, alert=ALERT.NONE, reason=None): - assert device is not None - if _log.isEnabledFor(_DEBUG): - _log.debug("status changed: %s, %s, %s", device, alert, reason) - - ui.async(ui.status_icon.update, status_icon, device) - if alert & ALERT.ATTENTION: - ui.async(ui.status_icon.attention, status_icon, reason) - - need_popup = alert & (ALERT.SHOW_WINDOW | ALERT.ATTENTION) - ui.async(ui.main_window.update, device, need_popup, status_icon) - - if alert & ALERT.NOTIFICATION: - ui.async(ui.notify.show, device, reason) + ui.init() import solaar.listener as listener - listener.start_scanner(status_changed, ui.error_dialog) + listener.start_scanner(ui.status_changed, ui.error_dialog) # main UI event loop ui.run_loop() - ui.status_icon.destroy(status_icon) - ui.notify.uninit() listener.stop_all() diff --git a/lib/solaar/listener.py b/lib/solaar/listener.py index 9a7f58ce..5be03f5f 100644 --- a/lib/solaar/listener.py +++ b/lib/solaar/listener.py @@ -65,6 +65,10 @@ class ReceiverListener(_listener.EventsListener): assert r is not None _log.info("%s: notifications listener has stopped", r) + # because udev is not notifying us about device removal, + # make sure to clean up in _all_listeners + _all_listeners.pop(r.path, None) + r.status = 'The receiver was unplugged.' if r: try: diff --git a/lib/solaar/ui/__init__.py b/lib/solaar/ui/__init__.py index 499f168e..85c2d406 100644 --- a/lib/solaar/ui/__init__.py +++ b/lib/solaar/ui/__init__.py @@ -5,13 +5,15 @@ from __future__ import absolute_import, division, print_function, unicode_literals +from logging import getLogger, DEBUG as _DEBUG +_log = getLogger(__name__) +del getLogger + from gi.repository import GLib, Gtk GLib.threads_init() -async = GLib.idle_add -run_loop = Gtk.main -def error_dialog(reason, object): +def _error_dialog(reason, object): if reason == 'permissions': title = 'Permissions error' text = ('Found a Logitech Receiver (%s), but did not have permission to open it.\n' @@ -21,13 +23,52 @@ def error_dialog(reason, object): else: raise Exception("ui.error_dialog: don't know how to handle (%s, %s)", reason, object) - def _show_dialog(d): - d.run() - d.destroy() - m = Gtk.MessageDialog(None, Gtk.DialogFlags.MODAL, Gtk.MessageType.ERROR, Gtk.ButtonsType.CLOSE, text) m.set_title(title) - async(_show_dialog, m) + m.run() + m.destroy() + +def error_dialog(reason, object): + GLib.idle_add(_error_dialog, reason, object) + +# +# +# + +_tray_icon = None + +def init(): + notify.init() + + global _tray_icon + _tray_icon = status_icon.create(main_window.toggle_all, main_window.popup) + assert _tray_icon + +def run_loop(): + global _tray_icon + Gtk.main() + t, _tray_icon = _tray_icon, None + status_icon.destroy(t) + notify.uninit() + +from logitech.unifying_receiver.status import ALERT +def _status_changed(device, alert, reason): + assert device is not None + if _log.isEnabledFor(_DEBUG): + _log.debug("status changed: %s, %s, %s", device, alert, reason) + + status_icon.update(_tray_icon, device) + if alert & ALERT.ATTENTION: + status_icon.attention(_tray_icon, reason) + + need_popup = alert & (ALERT.SHOW_WINDOW | ALERT.ATTENTION) + main_window.update(device, need_popup, _tray_icon) + + if alert & ALERT.NOTIFICATION: + notify.show(device, reason) + +def status_changed(device, alert=ALERT.NONE, reason=None): + GLib.idle_add(_status_changed, device, alert, reason) # # diff --git a/lib/solaar/ui/icons.py b/lib/solaar/ui/icons.py index 908d2f3d..9b6facad 100644 --- a/lib/solaar/ui/icons.py +++ b/lib/solaar/ui/icons.py @@ -4,9 +4,9 @@ from __future__ import absolute_import, division, print_function, unicode_literals -import logging -_DEBUG = logging.DEBUG -_log = logging.getLogger(__name__) +from logging import getLogger, DEBUG as _DEBUG +_log = getLogger(__name__) +del getLogger from gi.repository import Gtk