136 lines
4.8 KiB
Python
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()
|