re-work the status icon updating
This commit is contained in:
parent
c20b279362
commit
5f46c820e6
|
@ -103,6 +103,7 @@ def _run(args):
|
|||
def _startup_check_receiver():
|
||||
if not listeners:
|
||||
ui.notify.alert('No receiver found.')
|
||||
ui.status_icon.update(status_icon)
|
||||
GLib.timeout_add(1000, _startup_check_receiver)
|
||||
|
||||
from logitech.unifying_receiver import base as _base
|
||||
|
|
|
@ -17,13 +17,13 @@ from logitech.unifying_receiver import (Receiver,
|
|||
#
|
||||
|
||||
from collections import namedtuple
|
||||
_GHOST_DEVICE = namedtuple('_GHOST_DEVICE', ['receiver', 'number', 'name', 'kind', 'status'])
|
||||
_GHOST_DEVICE = namedtuple('_GHOST_DEVICE', ['receiver', 'number', 'name', 'kind', 'serial', 'status'])
|
||||
_GHOST_DEVICE.__bool__ = lambda self: False
|
||||
_GHOST_DEVICE.__nonzero__ = _GHOST_DEVICE.__bool__
|
||||
del namedtuple
|
||||
|
||||
def _ghost(device):
|
||||
return _GHOST_DEVICE(receiver=device.receiver, number=device.number, name=device.name, kind=device.kind, status=None)
|
||||
return _GHOST_DEVICE(receiver=device.receiver, number=device.number, name=device.name, kind=device.kind, serial=device.serial, status=None)
|
||||
|
||||
#
|
||||
#
|
||||
|
|
|
@ -14,9 +14,6 @@ from logitech.unifying_receiver import status as _status
|
|||
#
|
||||
#
|
||||
|
||||
_NO_DEVICES = [None] * 6
|
||||
|
||||
|
||||
def create(activate_callback):
|
||||
assert activate_callback
|
||||
|
||||
|
@ -24,23 +21,22 @@ def create(activate_callback):
|
|||
icon.set_title(NAME)
|
||||
icon.set_name(NAME)
|
||||
icon.set_from_icon_name(_icons.APP_ICON[0])
|
||||
icon._devices = list(_NO_DEVICES)
|
||||
icon._devices_info = []
|
||||
icon._receivers = set()
|
||||
|
||||
icon.set_tooltip_text(NAME)
|
||||
icon.connect('activate', activate_callback)
|
||||
|
||||
menu = Gtk.Menu()
|
||||
|
||||
menu.append(Gtk.SeparatorMenuItem.new())
|
||||
# per-device menu entries will be generated as-needed
|
||||
|
||||
menu.append(Gtk.SeparatorMenuItem.new())
|
||||
menu.append(_action.about.create_menu_item())
|
||||
menu.append(_action.make('application-exit', 'Quit', Gtk.main_quit).create_menu_item())
|
||||
menu.show_all()
|
||||
|
||||
for x in _NO_DEVICES:
|
||||
m = Gtk.ImageMenuItem()
|
||||
m.set_sensitive(False)
|
||||
menu.insert(m, 0)
|
||||
icon._menu = menu
|
||||
|
||||
icon.connect('popup_menu',
|
||||
lambda icon, button, time, menu:
|
||||
|
@ -48,6 +44,30 @@ def create(activate_callback):
|
|||
menu)
|
||||
return icon
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
def _generate_tooltip_lines(icon):
|
||||
yield '<b>%s</b>' % NAME
|
||||
yield ''
|
||||
|
||||
for _, serial, name, status in icon._devices_info:
|
||||
yield '<b>%s</b>' % name
|
||||
|
||||
p = str(status)
|
||||
if p: # does it have any properties to print?
|
||||
if status:
|
||||
yield '\t%s' % p
|
||||
else:
|
||||
yield '\t%s <small>(inactive)</small>' % p
|
||||
else:
|
||||
if status:
|
||||
yield '\t<small>no status</small>'
|
||||
else:
|
||||
yield '\t<small>(inactive)</small>'
|
||||
yield ''
|
||||
|
||||
|
||||
_PIXMAPS = {}
|
||||
def _icon_with_battery(level, active):
|
||||
|
@ -73,57 +93,105 @@ def _icon_with_battery(level, active):
|
|||
|
||||
return _PIXMAPS[name]
|
||||
|
||||
def update(icon, device):
|
||||
assert device is not None
|
||||
# print ("icon update", device)
|
||||
|
||||
if device.kind is None:
|
||||
receiver = device
|
||||
if not device:
|
||||
icon._devices[:] = _NO_DEVICES
|
||||
else:
|
||||
icon._devices[device.number] = None if device.status is None else device
|
||||
receiver = device.receiver
|
||||
|
||||
if not icon.is_embedded():
|
||||
def _update_image(icon):
|
||||
if not icon._receivers:
|
||||
icon.set_from_icon_name(_icons.APP_ICON[-1])
|
||||
return
|
||||
|
||||
def _lines(r, devices):
|
||||
yield '<b>%s</b>: %s' % (NAME, r.status)
|
||||
yield ''
|
||||
|
||||
for dev in devices:
|
||||
if dev is None:
|
||||
continue
|
||||
|
||||
yield '<b>%s</b>' % dev.name
|
||||
|
||||
assert hasattr(dev, 'status') and dev.status is not None
|
||||
p = str(dev.status)
|
||||
if p: # does it have any properties to print?
|
||||
if dev.status:
|
||||
yield '\t%s' % p
|
||||
else:
|
||||
yield '\t%s <small>(inactive)</small>' % p
|
||||
else:
|
||||
if dev.status:
|
||||
yield '\t<small>no status</small>'
|
||||
else:
|
||||
yield '\t<small>(inactive)</small>'
|
||||
yield ''
|
||||
|
||||
icon.set_tooltip_markup('\n'.join(_lines(receiver, icon._devices)).rstrip('\n'))
|
||||
|
||||
battery_status = None
|
||||
battery_level = 1000
|
||||
for dev in icon._devices:
|
||||
if dev is not None:
|
||||
level = dev.status.get(_status.BATTERY_LEVEL)
|
||||
if level is not None and level < battery_level:
|
||||
battery_status = dev.status
|
||||
battery_level = level
|
||||
|
||||
for _, serial, name, status in icon._devices_info:
|
||||
level = status.get(_status.BATTERY_LEVEL)
|
||||
if level is not None and level < battery_level:
|
||||
battery_status = status
|
||||
battery_level = level
|
||||
|
||||
if battery_status is None:
|
||||
icon.set_from_icon_name(_icons.APP_ICON[1 if receiver else -1])
|
||||
icon.set_from_icon_name(_icons.APP_ICON[1])
|
||||
else:
|
||||
icon.set_from_pixbuf(_icon_with_battery(battery_level, bool(battery_status)))
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
def _device_index(icon, device):
|
||||
if device.receiver.serial in icon._receivers:
|
||||
for index, (rserial, serial, name, _) in enumerate(icon._devices_info):
|
||||
if rserial == device.receiver.serial and serial == device.serial:
|
||||
return index
|
||||
|
||||
|
||||
def _add_device(icon, device):
|
||||
index = len(icon._devices_info)
|
||||
device_info = (device.receiver.serial, device.serial, device.name, device.status)
|
||||
icon._devices_info.append(device_info)
|
||||
|
||||
menu_item = Gtk.ImageMenuItem.new_with_label(device.name)
|
||||
icon._menu.insert(menu_item, index)
|
||||
menu_item.set_image(Gtk.Image())
|
||||
menu_item.show_all()
|
||||
|
||||
return index
|
||||
|
||||
|
||||
def _remove_device(icon, index):
|
||||
# print ("remove device", index)
|
||||
assert index is not None
|
||||
del icon._devices_info[index]
|
||||
menu_items = icon._menu.get_children()
|
||||
icon._menu.remove(menu_items[index])
|
||||
|
||||
|
||||
def _remove_receiver(icon, receiver):
|
||||
icon._receivers.remove(receiver.serial)
|
||||
index = 0
|
||||
while index < len(icon._devices_info):
|
||||
rserial, _, _, _ = icon._devices_info[index]
|
||||
# print ("remove receiver", index, rserial)
|
||||
if rserial == receiver.serial:
|
||||
_remove_device(icon, index)
|
||||
else:
|
||||
index += 1
|
||||
|
||||
|
||||
def _update_menu_item(icon, index, device_status):
|
||||
menu_items = icon._menu.get_children()
|
||||
menu_item = menu_items[index]
|
||||
|
||||
image = menu_item.get_image()
|
||||
battery_level = device_status.get(_status.BATTERY_LEVEL) if device_status else None
|
||||
image.set_from_icon_name(_icons.battery(battery_level), Gtk.IconSize.MENU)
|
||||
image.set_sensitive(battery_level is not None)
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
def update(icon, device=None):
|
||||
# print ("icon update", device)
|
||||
|
||||
if device is not None:
|
||||
if device.kind is None:
|
||||
# receiver
|
||||
receiver = device
|
||||
if receiver:
|
||||
icon._receivers.add(receiver.serial)
|
||||
else:
|
||||
_remove_receiver(icon, receiver)
|
||||
else:
|
||||
# peripheral
|
||||
index = _device_index(icon, device)
|
||||
if device.status is None:
|
||||
# was just unpaired
|
||||
assert index is not None
|
||||
_remove_device(icon, index)
|
||||
else:
|
||||
if index is None:
|
||||
index = _add_device(icon, device)
|
||||
_update_menu_item(icon, index, device.status)
|
||||
|
||||
tooltip_lines = _generate_tooltip_lines(icon)
|
||||
icon.set_tooltip_markup('\n'.join(tooltip_lines).rstrip('\n'))
|
||||
_update_image(icon)
|
||||
|
|
Loading…
Reference in New Issue