Files
nwg-panel/nwg_panel/modules/sni_system_tray/tray.py
2022-02-01 08:49:50 +11:00

136 lines
4.8 KiB
Python

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()