add system tray module
This commit is contained in:
128
nwg_panel/modules/sni_system_tray/host.py
Normal file
128
nwg_panel/modules/sni_system_tray/host.py
Normal file
@@ -0,0 +1,128 @@
|
||||
import typing
|
||||
import os
|
||||
|
||||
from dasbus.connection import SessionMessageBus
|
||||
from dasbus.loop import EventLoop
|
||||
from dasbus.client.observer import DBusObserver
|
||||
from dasbus.client.proxy import disconnect_proxy
|
||||
|
||||
from .watcher import WATCHER_SERVICE_NAME, WATCHER_OBJECT_PATH
|
||||
from .tray import Tray
|
||||
from .item import StatusNotifierItem
|
||||
|
||||
HOST_SERVICE_NAME_TEMPLATE = "org.kde.StatusNotifierHost-{}-{}"
|
||||
HOST_OBJECT_PATH_TEMPLATE = "/StatusNotifierHost/{}"
|
||||
|
||||
dasbus_event_loop: typing.Union[EventLoop, None] = None
|
||||
|
||||
|
||||
def get_service_name_and_object_path(service: str) -> (str, str):
|
||||
index = service.find("/")
|
||||
if index != len(service):
|
||||
return service[0:index], service[index:]
|
||||
return service, "/StatusNotifierItem"
|
||||
|
||||
|
||||
class StatusNotifierHostInterface(object):
|
||||
def __init__(self, host_id, trays: typing.List[Tray]):
|
||||
self.host_id = host_id
|
||||
self.trays = trays
|
||||
|
||||
self._statusNotifierItems = []
|
||||
self.watcher_proxy = None
|
||||
self.session_bus = SessionMessageBus()
|
||||
|
||||
self.host_service_name = HOST_SERVICE_NAME_TEMPLATE.format(os.getpid(), self.host_id)
|
||||
self.host_object_path = HOST_OBJECT_PATH_TEMPLATE.format(self.host_id)
|
||||
self.session_bus.register_service(self.host_service_name)
|
||||
|
||||
self.watcher_service_observer = DBusObserver(
|
||||
message_bus=self.session_bus,
|
||||
service_name=WATCHER_SERVICE_NAME
|
||||
)
|
||||
self.watcher_service_observer.service_available.connect(
|
||||
self.watcher_available_handler
|
||||
)
|
||||
self.watcher_service_observer.service_unavailable.connect(
|
||||
self.watcher_unavailable_handler
|
||||
)
|
||||
self.watcher_service_observer.connect_once_available()
|
||||
|
||||
def __del__(self):
|
||||
if self.watcher_proxy is not None:
|
||||
disconnect_proxy(self.watcher_proxy)
|
||||
self.watcher_service_observer.disconnect()
|
||||
self.session_bus.disconnect()
|
||||
|
||||
def watcher_available_handler(self, _observer):
|
||||
print("StatusNotifierHostInterface -> watcher_available_handler")
|
||||
self.watcher_proxy = self.session_bus.get_proxy(WATCHER_SERVICE_NAME, WATCHER_OBJECT_PATH)
|
||||
self.watcher_proxy.StatusNotifierItemRegistered.connect(self.item_registered_handler)
|
||||
self.watcher_proxy.StatusNotifierItemUnregistered.connect(self.item_unregistered_handler)
|
||||
self.watcher_proxy.RegisterStatusNotifierHost(self.host_object_path, callback=lambda _: None)
|
||||
|
||||
def watcher_unavailable_handler(self, _observer):
|
||||
print("StatusNotifierHostInterface -> watcher_unavailable_handler")
|
||||
self._statusNotifierItems.clear()
|
||||
disconnect_proxy(self.watcher_proxy)
|
||||
self.watcher_proxy = None
|
||||
|
||||
def item_registered_handler(self, full_service_service):
|
||||
print(
|
||||
"StatusNotifierHostInterface -> item_registered_handler\n full_service_name: {}".format(
|
||||
full_service_service
|
||||
)
|
||||
)
|
||||
service_name, object_path = get_service_name_and_object_path(full_service_service)
|
||||
if self.find_item(service_name, object_path) is None:
|
||||
item = StatusNotifierItem(service_name, object_path)
|
||||
item.set_on_loaded_callback(self.item_loaded_handler)
|
||||
item.set_on_updated_callback(self.item_updated_handler)
|
||||
self._statusNotifierItems.append(item)
|
||||
|
||||
def item_unregistered_handler(self, full_service_service):
|
||||
print(
|
||||
"StatusNotifierHostInterface -> item_unregistered_handler\n full_service_name: {}".format(
|
||||
full_service_service
|
||||
)
|
||||
)
|
||||
service_name, object_path = get_service_name_and_object_path(full_service_service)
|
||||
item = self.find_item(service_name, object_path)
|
||||
if item is not None:
|
||||
self._statusNotifierItems.remove(item)
|
||||
for tray in self.trays:
|
||||
tray.remove_item(item)
|
||||
|
||||
def find_item(self, service_name, object_path) -> typing.Union[StatusNotifierItem, None]:
|
||||
for item in self._statusNotifierItems:
|
||||
if item.service_name == service_name and item.object_path == object_path:
|
||||
return item
|
||||
else:
|
||||
return None
|
||||
|
||||
def item_loaded_handler(self, item):
|
||||
for tray in self.trays:
|
||||
tray.add_item(item)
|
||||
|
||||
def item_updated_handler(self, item, changed_properties):
|
||||
for tray in self.trays:
|
||||
tray.update_item(item, changed_properties)
|
||||
|
||||
|
||||
def init(host_id, trays: typing.List[Tray]):
|
||||
_status_notifier_host_interface = StatusNotifierHostInterface(host_id, trays)
|
||||
|
||||
global dasbus_event_loop
|
||||
if dasbus_event_loop is None:
|
||||
print("host.init(): running dasbus.EventLoop")
|
||||
dasbus_event_loop = EventLoop()
|
||||
dasbus_event_loop.run()
|
||||
|
||||
|
||||
def deinit():
|
||||
global dasbus_event_loop
|
||||
if dasbus_event_loop is not None:
|
||||
print("host.deinit(): quitting dasbus.EventLoop")
|
||||
dasbus_event_loop.quit()
|
||||
if dasbus_event_loop is not None:
|
||||
dasbus_event_loop = None
|
Reference in New Issue
Block a user