diff --git a/blueman/bluez/Battery.py b/blueman/bluez/Battery.py index cc8521f32..e2340744d 100644 --- a/blueman/bluez/Battery.py +++ b/blueman/bluez/Battery.py @@ -1,5 +1,14 @@ +from blueman.bluez.AnyBase import AnyBase + from blueman.bluez.Base import Base +_INTERFACE = "org.bluez.Battery1" + class Battery(Base): - _interface_name = "org.bluez.Battery1" + _interface_name = _INTERFACE + + +class AnyBattery(AnyBase): + def __init__(self) -> None: + super().__init__(_INTERFACE) diff --git a/blueman/main/BatteryWatcher.py b/blueman/main/BatteryWatcher.py new file mode 100644 index 000000000..b809c89d9 --- /dev/null +++ b/blueman/main/BatteryWatcher.py @@ -0,0 +1,29 @@ +import weakref +from typing import Callable + +from blueman.bluez.Battery import Battery, AnyBattery +from blueman.bluez.Manager import Manager + + +class BatteryWatcher: + def __init__(self, callback: Callable[[str, int], None]) -> None: + super().__init__() + manager = Manager() + weakref.finalize( + self, + manager.disconnect_signal, + manager.connect_signal( + "battery-created", + lambda _manager, obj_path: callback(obj_path, Battery(obj_path=obj_path)["Percentage"]) + ) + ) + + any_battery = AnyBattery() + weakref.finalize( + self, + any_battery.disconnect_signal, + any_battery.connect_signal( + "property-changed", + lambda _any_battery, key, value, path: callback(path, value) if key == "Percentage" else None + ) + ) diff --git a/blueman/main/Makefile.am b/blueman/main/Makefile.am index 6fc56247d..986cb6a06 100644 --- a/blueman/main/Makefile.am +++ b/blueman/main/Makefile.am @@ -20,7 +20,8 @@ blueman_PYTHON = \ Services.py \ Tray.py \ DBusProxies.py \ - NetworkManager.py + NetworkManager.py \ + BatteryWatcher.py if HAVE_PULSEAUDIO blueman_PYTHON += PulseAudioUtils.py diff --git a/blueman/plugins/applet/ConnectionNotifier.py b/blueman/plugins/applet/ConnectionNotifier.py index 0a4aecf57..7e2b57639 100644 --- a/blueman/plugins/applet/ConnectionNotifier.py +++ b/blueman/plugins/applet/ConnectionNotifier.py @@ -2,11 +2,9 @@ from typing import Any, Dict, Union from blueman.bluez.Device import Device -from blueman.bluez.Battery import Battery -from blueman.bluez.Manager import Manager from blueman.gui.Notification import Notification, _NotificationBubble, _NotificationDialog +from blueman.main.BatteryWatcher import BatteryWatcher from blueman.plugins.AppletPlugin import AppletPlugin -from gi.repository import GLib class ConnectionNotifier(AppletPlugin): @@ -14,22 +12,17 @@ class ConnectionNotifier(AppletPlugin): __icon__ = "bluetooth-symbolic" __description__ = _("Shows desktop notifications when devices get connected or disconnected.") - _sig = None _notifications: Dict[str, Union[_NotificationBubble, _NotificationDialog]] = {} def on_load(self) -> None: - self._manager = Manager() - self._sig = self._manager.connect_signal("battery-created", self._on_battery_created) + self._battery_watcher = BatteryWatcher(self._on_battery_update) def on_unload(self) -> None: - if self._sig is not None: - self._manager.disconnect_signal(self._sig) + del self._battery_watcher def on_device_property_changed(self, path: str, key: str, value: Any) -> None: - device = Device(obj_path=path) - battery = Battery(obj_path=path) - if key == "Connected": + device = Device(obj_path=path) if value: self._notifications[path] = notification = Notification( device.display_name, @@ -37,23 +30,11 @@ def on_device_property_changed(self, path: str, key: str, value: Any) -> None: icon_name=device["Icon"] ) notification.show() - - sig = battery.connect_signal("property-changed", self._on_battery_property_changed) - - def disconnect_signal() -> bool: - battery.disconnect_signal(sig) - return False - GLib.timeout_add_seconds(5, disconnect_signal) else: Notification(device.display_name, _('Disconnected'), icon_name=device["Icon"]).show() - def _on_battery_created(self, _manager: Manager, obj_path: str) -> None: - battery = Battery(obj_path=obj_path) - self._on_battery_property_changed(battery, "Percentage", battery["Percentage"], obj_path) - - def _on_battery_property_changed(self, _battery: Battery, key: str, value: Any, path: str) -> None: - if key == "Percentage": - notification = self._notifications[path] - if notification: - notification.set_message(f"{_('Connected')} {value}%") - notification.set_notification_icon("battery") + def _on_battery_update(self, path: str, value: int) -> None: + notification = self._notifications[path] + if notification: + notification.set_message(f"{_('Connected')} {value}%") + notification.set_notification_icon("battery")