# # # from __future__ import absolute_import, division, print_function, unicode_literals from gi.repository import Gtk, GdkPixbuf import ui from logitech.unifying_receiver import status as _status # # # def create(window, menu_actions=None): name = window.get_title() icon = Gtk.StatusIcon() icon.set_title(name) icon.set_name(name) icon.set_from_icon_name(ui.appicon(False)) icon._devices = {} icon.set_tooltip_text(name) icon.connect('activate', window.toggle_visible) menu = Gtk.Menu() for action in menu_actions or (): if action: menu.append(action.create_menu_item()) menu.append(ui.action.quit.create_menu_item()) menu.show_all() icon.connect('popup_menu', lambda icon, button, time, menu: menu.popup(None, None, icon.position_menu, icon, button, time), menu) return icon _PIXMAPS = {} def _icon_with_battery(s): battery_icon = ui.get_battery_icon(s[_status.BATTERY_LEVEL]) name = '%s-%s' % (battery_icon, bool(s)) if name not in _PIXMAPS: mask = ui.icon_file(ui.appicon(True) + '-mask', 128) assert mask mask = GdkPixbuf.Pixbuf.new_from_file(mask) assert mask.get_width() == 128 and mask.get_height() == 128 mask.saturate_and_pixelate(mask, 0.7, False) battery = ui.icon_file(battery_icon, 128) assert battery battery = GdkPixbuf.Pixbuf.new_from_file(battery) assert battery.get_width() == 128 and battery.get_height() == 128 if not s: battery.saturate_and_pixelate(battery, 0, True) # TODO can the masking be done at runtime? battery.composite(mask, 0, 7, 80, 121, -32, 7, 1, 1, GdkPixbuf.InterpType.NEAREST, 255) _PIXMAPS[name] = mask return _PIXMAPS[name] def update(icon, receiver, device=None): # print ("icon update", receiver, receiver.status, len(receiver), device) battery_status = None if device: icon._devices[device.number] = None if device.status is None else device lines = [ui.NAME + ': ' + str(receiver.status), ''] if receiver: for k in range(1, 1 + receiver.max_devices): dev = icon._devices.get(k) if dev is None: continue lines.append('' + dev.name + '') assert hasattr(dev, 'status') and dev.status is not None p = str(dev.status) if p: if not dev.status: p += ' (inactive)' else: if dev.status: if dev.protocol < 2.0: p = 'no status' else: p = 'waiting for status...' else: p = '(inactive)' lines.append('\t' + p) lines.append('') if battery_status is None and dev.status.get(_status.BATTERY_LEVEL): battery_status = dev.status else: icon._devices.clear() icon.set_tooltip_markup('\n'.join(lines).rstrip('\n')) if battery_status is None: icon.set_from_icon_name(ui.appicon(receiver.status)) else: icon.set_from_pixbuf(_icon_with_battery(battery_status))