add system tray module
This commit is contained in:
135
nwg_panel/modules/sni_system_tray/tray.py
Normal file
135
nwg_panel/modules/sni_system_tray/tray.py
Normal file
@@ -0,0 +1,135 @@
|
||||
import os
|
||||
import sys
|
||||
import gi
|
||||
|
||||
gi.require_version('Gtk', '3.0')
|
||||
|
||||
from gi.repository import Gtk, GLib, GdkPixbuf
|
||||
|
||||
from nwg_panel.tools import check_key, get_config_dir
|
||||
from .item import StatusNotifierItem
|
||||
|
||||
|
||||
def load_icon(image, icon_name, icon_size, icons_path=""):
|
||||
icon_theme = Gtk.IconTheme.get_default()
|
||||
search_path = icon_theme.get_search_path()
|
||||
if icons_path:
|
||||
search_path.append(icons_path)
|
||||
icon_theme.set_search_path(search_path)
|
||||
if icon_theme.has_icon(icon_name):
|
||||
pixbuf = icon_theme.load_icon(icon_name, icon_size, Gtk.IconLookupFlags.FORCE_SIZE)
|
||||
elif icon_theme.has_icon(icon_name.lower()):
|
||||
pixbuf = icon_theme.load_icon(icon_name.lower(), icon_size, Gtk.IconLookupFlags.FORCE_SIZE)
|
||||
else:
|
||||
try:
|
||||
pixbuf = icon_theme.load_icon(icon_name, icon_size, Gtk.IconLookupFlags.FORCE_SIZE)
|
||||
except GLib.GError:
|
||||
print(
|
||||
"tray.update_icon -> icon not found\n icon_name: {}\n search_path: {}".format(
|
||||
icon_name,
|
||||
search_path
|
||||
),
|
||||
file=sys.stderr
|
||||
)
|
||||
path = os.path.join(get_config_dir(), "icons_light/icon-missing.svg")
|
||||
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(path, icon_size, icon_size)
|
||||
# TODO: if image height is different to icon_size, resize to match, while maintaining
|
||||
# aspect ratio. Width can be ignored.
|
||||
image.set_from_pixbuf(pixbuf)
|
||||
|
||||
|
||||
def update_icon(image, item, icon_size, icon_path):
|
||||
if "IconThemePath" in item.properties:
|
||||
icon_path = item.properties["IconThemePath"]
|
||||
load_icon(image, item.properties["IconName"], icon_size, icon_path)
|
||||
|
||||
|
||||
def update_status(event_box, item):
|
||||
if "Status" in item.properties:
|
||||
status = item.properties["Status"].lower()
|
||||
event_box.set_visible(status != "passive")
|
||||
event_box_style = event_box.get_style_context()
|
||||
for class_name in event_box_style.list_classes():
|
||||
event_box_style.remove_class(class_name)
|
||||
if status == "needsattention":
|
||||
event_box_style.add_class("needs-attention")
|
||||
event_box_style.add_class(status)
|
||||
|
||||
|
||||
class Tray(Gtk.EventBox):
|
||||
def __init__(self, settings, icons_path=""):
|
||||
self.settings = settings
|
||||
self.icons_path = icons_path
|
||||
Gtk.EventBox.__init__(self)
|
||||
|
||||
check_key(settings, "icon-size", 16)
|
||||
check_key(settings, "root-css-name", "tray")
|
||||
|
||||
self.set_property("name", settings["root-css-name"])
|
||||
|
||||
self.icon_size = settings["icon-size"]
|
||||
|
||||
self.box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=0)
|
||||
self.add(self.box)
|
||||
|
||||
self.items = {}
|
||||
|
||||
def add_item(self, item: StatusNotifierItem):
|
||||
print("Tray -> add_item: {}".format(item.properties))
|
||||
full_service_name = "{}{}".format(item.service_name, item.object_path)
|
||||
if full_service_name not in self.items:
|
||||
event_box = Gtk.EventBox()
|
||||
image = Gtk.Image()
|
||||
|
||||
if "IconPixmap" in item.properties:
|
||||
# TODO: handle loading pixbuf from dbus
|
||||
pass
|
||||
else:
|
||||
update_icon(image, item, self.icon_size, self.icons_path)
|
||||
|
||||
if "Tooltip" in item.properties:
|
||||
# TODO: handle tooltip variant type
|
||||
pass
|
||||
|
||||
if "Title" in item.properties:
|
||||
image.set_tooltip_markup(item.properties["Title"])
|
||||
|
||||
update_status(event_box, item)
|
||||
|
||||
event_box.add(image)
|
||||
self.box.pack_start(event_box, False, False, 6)
|
||||
self.box.show_all()
|
||||
|
||||
self.items[full_service_name] = {
|
||||
"event_box": event_box,
|
||||
"image": image,
|
||||
"item": item
|
||||
}
|
||||
|
||||
def update_item(self, item: StatusNotifierItem, changed_properties: list[str]):
|
||||
full_service_name = "{}{}".format(item.service_name, item.object_path)
|
||||
event_box = self.items[full_service_name]["event_box"]
|
||||
image = self.items[full_service_name]["image"]
|
||||
|
||||
if "IconPixmap" in changed_properties:
|
||||
# TODO: handle loading pixbuf from dbus
|
||||
pass
|
||||
elif "IconThemePath" in changed_properties or "IconName" in changed_properties:
|
||||
update_icon(image, item, self.icon_size, self.icons_path)
|
||||
|
||||
if "Tooltip" in changed_properties:
|
||||
# handle tooltip variant type
|
||||
pass
|
||||
|
||||
if "Title" in changed_properties:
|
||||
image.set_tooltip_markup(item.properties["Title"])
|
||||
|
||||
update_status(event_box, item)
|
||||
|
||||
event_box.show_all()
|
||||
|
||||
def remove_item(self, item: StatusNotifierItem):
|
||||
full_service_name = "{}{}".format(item.service_name, item.object_path)
|
||||
self.box.remove(self.items[full_service_name]["event_box"])
|
||||
self.items.pop(full_service_name)
|
||||
self.box.show_all()
|
Reference in New Issue
Block a user