better battery icon in the systray
This commit is contained in:
parent
d6b18cd426
commit
932a015e49
|
@ -77,29 +77,39 @@ class ReceiverListener(_lur.listener.EventsListener):
|
|||
self.receiver.close()
|
||||
|
||||
self.receiver = None
|
||||
self._status_changed(DUMMY, _lur.status.ALERT.LOW)
|
||||
self._status_changed(None, alert=_lur.status.ALERT.LOW)
|
||||
|
||||
def tick(self, timestamp):
|
||||
if _log.isEnabledFor(_DEBUG):
|
||||
_log.debug("tick: polling status")
|
||||
|
||||
# read these in case they haven't been read already
|
||||
self.receiver.serial, self.receiver.firmware
|
||||
|
||||
if self.receiver.status.lock_open:
|
||||
# don't mess with stuff while pairing
|
||||
return
|
||||
|
||||
for dev in self.receiver:
|
||||
if dev.status:
|
||||
dev.serial, dev.firmware
|
||||
# read these in case they haven't been read already
|
||||
dev.wpid, dev.serial, dev.protocol, dev.firmware
|
||||
|
||||
if dev.status.get(_lur.status.BATTERY_LEVEL) is None:
|
||||
battery = _lur.hidpp20.get_battery(dev) or _lur.hidpp10.get_battery(dev)
|
||||
if battery:
|
||||
dev.status[_lur.status.BATTERY_LEVEL], dev.status[_lur.status.BATTERY_STATUS] = battery
|
||||
self._status_changed(dev)
|
||||
|
||||
elif len(dev.status) > 0 and timestamp - dev.status.updated > _DEVICE_TIMEOUT:
|
||||
dev.status.clear()
|
||||
self._status_changed(dev, _lur.status.ALERT.LOW)
|
||||
|
||||
def _status_changed(self, device, alert=_lur.status.ALERT.NONE, reason=None):
|
||||
assert device is not None
|
||||
if _log.isEnabledFor(_DEBUG):
|
||||
_log.debug("status_changed %s: %s (%X) %s", device, device.status, alert, reason or '')
|
||||
_log.debug("status_changed %s: %s (%X) %s", device, None if device is None else device.status, alert, reason or '')
|
||||
if self.status_changed_callback:
|
||||
if device is self.receiver:
|
||||
if device is None or device is self.receiver:
|
||||
self.status_changed_callback(self.receiver or DUMMY, None, alert, reason)
|
||||
else:
|
||||
self.status_changed_callback(self.receiver or DUMMY, device, alert, reason)
|
||||
|
@ -133,6 +143,7 @@ class ReceiverListener(_lur.listener.EventsListener):
|
|||
receiver = _lur.Receiver.open()
|
||||
if receiver:
|
||||
receiver.handle = _lur.listener.ThreadedHandle(receiver.handle, receiver.path)
|
||||
receiver.kind = 'applications-system'
|
||||
rl = ReceiverListener(receiver, status_changed_callback)
|
||||
rl.start()
|
||||
return rl
|
||||
|
|
|
@ -9,15 +9,17 @@ GObject.threads_init()
|
|||
from solaar import NAME
|
||||
_APP_ICONS = (NAME + '-init', NAME + '-fail', NAME)
|
||||
def appicon(receiver_status):
|
||||
return (_APP_ICONS[1] if type(receiver_status) == str else
|
||||
_APP_ICONS[2] if receiver_status else
|
||||
_APP_ICONS[0])
|
||||
return (_APP_ICONS[1] if type(receiver_status) == str
|
||||
else _APP_ICONS[2] if receiver_status
|
||||
else _APP_ICONS[0])
|
||||
|
||||
|
||||
_ICON_THEME = Gtk.IconTheme.get_default()
|
||||
|
||||
def get_icon(name, fallback):
|
||||
return name if name and _ICON_THEME.has_icon(name) else fallback
|
||||
def get_icon(name, *fallback):
|
||||
theme = Gtk.IconTheme.get_default()
|
||||
return (str(name) if name and theme.has_icon(str(name))
|
||||
else get_icon(*fallback) if fallback
|
||||
else None)
|
||||
|
||||
def get_battery_icon(level):
|
||||
if level < 0:
|
||||
|
@ -25,9 +27,9 @@ def get_battery_icon(level):
|
|||
return 'battery_%03d' % (10 * ((level + 5) // 10))
|
||||
|
||||
def icon_file(name):
|
||||
if name and _ICON_THEME.has_icon(name):
|
||||
return _ICON_THEME.lookup_icon(name, 0, 0).get_filename()
|
||||
return None
|
||||
theme = Gtk.IconTheme.get_default()
|
||||
return (theme.lookup_icon(str(name), 0, 0).get_filename() if name and theme.has_icon(str(name))
|
||||
else None)
|
||||
|
||||
|
||||
def error(window, title, text):
|
||||
|
|
|
@ -89,7 +89,7 @@ def _make_device_box(index):
|
|||
label.set_alignment(0, 0.5)
|
||||
label.set_padding(4, 4)
|
||||
|
||||
battery_icon = Gtk.Image.new_from_icon_name('battery_unknown', _STATUS_ICON_SIZE)
|
||||
battery_icon = Gtk.Image.new_from_icon_name(ui.get_battery_icon(-1), _STATUS_ICON_SIZE)
|
||||
|
||||
battery_label = Gtk.Label()
|
||||
battery_label.set_width_chars(6)
|
||||
|
@ -186,6 +186,7 @@ def create(title, name, max_devices, systray=False):
|
|||
vbox.set_visible(True)
|
||||
|
||||
window.add(vbox)
|
||||
window._vbox = vbox
|
||||
|
||||
geometry = Gdk.Geometry()
|
||||
geometry.min_width = 320
|
||||
|
@ -198,6 +199,10 @@ def create(title, name, max_devices, systray=False):
|
|||
|
||||
if systray:
|
||||
window.set_keep_above(True)
|
||||
# window.set_decorated(False)
|
||||
# window.set_type_hint(Gdk.WindowTypeHint.TOOLTIP)
|
||||
# window.set_skip_taskbar_hint(True)
|
||||
# window.set_skip_pager_hint(True)
|
||||
window.connect('delete-event', toggle)
|
||||
else:
|
||||
window.connect('delete-event', Gtk.main_quit)
|
||||
|
@ -248,14 +253,14 @@ def _update_device_info_label(label, dev):
|
|||
if firmware:
|
||||
items += [(f.kind, f.name + ' ' + f.version) for f in firmware]
|
||||
|
||||
label.set_markup('<small><tt>%s</tt></small>' % '\n'.join('%-12s: %s' % (item[0], str(item[1])) for item in items))
|
||||
label.set_markup('<small><tt>' + '\n'.join('%-12s: %s' % item for item in items) + '</tt></small>')
|
||||
|
||||
|
||||
def _update_receiver_info_label(label, dev):
|
||||
if label.get_visible() and '\n' not in label.get_text():
|
||||
items = [('Serial', dev.serial)] + \
|
||||
[(f.kind, f.version) for f in dev.firmware]
|
||||
label.set_markup('<small><tt>%s</tt></small>' % '\n'.join('%-10s: %s' % (item[0], str(item[1])) for item in items))
|
||||
label.set_markup('<small><tt>' + '\n'.join('%-10s: %s' % item for item in items) + '</tt></small>')
|
||||
|
||||
|
||||
def _toggle_info_box(action, label_widget, box_widget, frame, update_function):
|
||||
|
@ -319,7 +324,7 @@ def _update_device_box(frame, dev):
|
|||
|
||||
if battery_level is None:
|
||||
battery_icon.set_sensitive(False)
|
||||
battery_icon.set_from_icon_name('battery_unknown', _STATUS_ICON_SIZE)
|
||||
battery_icon.set_from_icon_name(ui.get_battery_icon(-1), _STATUS_ICON_SIZE)
|
||||
text = 'no status' if dev.protocol < 2.0 else 'waiting for status...'
|
||||
battery_label.set_markup('<small>%s</small>' % text)
|
||||
battery_label.set_sensitive(True)
|
||||
|
@ -355,8 +360,9 @@ def update(window, receiver, device=None):
|
|||
assert receiver is not None
|
||||
window.set_icon_name(ui.appicon(receiver.status))
|
||||
|
||||
vbox = window.get_child()
|
||||
vbox = window._vbox
|
||||
frames = list(vbox.get_children())
|
||||
assert len(frames) == 1 + receiver.max_devices, frames
|
||||
|
||||
if device is None:
|
||||
_update_receiver_box(frames[0], receiver)
|
||||
|
|
|
@ -58,7 +58,7 @@ try:
|
|||
|
||||
message = reason or ('unpaired' if dev.status is None else
|
||||
(str(dev.status) or ('connected' if dev.status else 'inactive')))
|
||||
n.update(summary, message, _icon(summary) or dev.kind)
|
||||
n.update(summary, message, _icon(summary) or str(dev.kind))
|
||||
urgency = Notify.Urgency.LOW if dev.status else Notify.Urgency.NORMAL
|
||||
n.set_urgency(urgency)
|
||||
|
||||
|
|
|
@ -2,18 +2,20 @@
|
|||
#
|
||||
#
|
||||
|
||||
from gi.repository import Gtk
|
||||
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(window.get_title())
|
||||
icon.set_name(window.get_title())
|
||||
icon.set_from_icon_name(ui.appicon(0))
|
||||
icon.set_title(name)
|
||||
icon.set_name(name)
|
||||
icon.set_from_icon_name(ui.appicon(False))
|
||||
|
||||
icon.set_tooltip_text(name)
|
||||
icon.connect('activate', window.toggle_visible)
|
||||
|
||||
menu = Gtk.Menu()
|
||||
|
@ -66,4 +68,15 @@ def update(icon, receiver, device=None):
|
|||
if battery_level is None:
|
||||
icon.set_from_icon_name(ui.appicon(receiver.status))
|
||||
else:
|
||||
icon.set_from_icon_name(ui.get_battery_icon(battery_level))
|
||||
appicon = ui.icon_file(ui.appicon(True) + '-mask')
|
||||
assert appicon
|
||||
pbuf = GdkPixbuf.Pixbuf.new_from_file(appicon)
|
||||
assert pbuf.get_width() == 128 and pbuf.get_height() == 128
|
||||
|
||||
baticon = ui.icon_file(ui.get_battery_icon(battery_level))
|
||||
assert baticon
|
||||
pbuf2 = GdkPixbuf.Pixbuf.new_from_file(baticon)
|
||||
assert pbuf2.get_width() == 128 and pbuf2.get_height() == 128
|
||||
|
||||
pbuf2.composite(pbuf, 0, 7, 80, 121, -32, 7, 1, 1, GdkPixbuf.InterpType.NEAREST, 255)
|
||||
icon.set_from_pixbuf(pbuf)
|
||||
|
|
|
@ -109,7 +109,7 @@ def close(handle):
|
|||
# _log.info("closed receiver handle %s", repr(handle))
|
||||
return True
|
||||
except:
|
||||
_log.exception("closing receiver handle %s", repr(handle))
|
||||
# _log.exception("closing receiver handle %s", repr(handle))
|
||||
pass
|
||||
|
||||
return False
|
||||
|
|
|
@ -129,7 +129,8 @@ class EventsListener(_threading.Thread):
|
|||
event = self._queued_events.get()
|
||||
|
||||
if event:
|
||||
_log.debug("processing event %s", event)
|
||||
# if _log.isEnabledFor(_DEBUG):
|
||||
# _log.debug("processing event %s", event)
|
||||
try:
|
||||
self._events_callback(event)
|
||||
except:
|
||||
|
@ -164,7 +165,7 @@ class EventsListener(_threading.Thread):
|
|||
def _events_hook(self, event):
|
||||
# only consider unhandled events that were sent from this thread,
|
||||
# i.e. triggered during a callback of a previous event
|
||||
if _threading.current_thread() == self:
|
||||
if self._active and _threading.current_thread() == self:
|
||||
_log.info("queueing unhandled event %s", event)
|
||||
self._queued_events.put(event)
|
||||
|
||||
|
|
|
@ -107,8 +107,8 @@ class DeviceStatus(dict):
|
|||
if self.updated == 0:
|
||||
alert |= ALERT.LOW
|
||||
self.updated = _timestamp()
|
||||
if _log.isEnabledFor(_DEBUG):
|
||||
_log.debug("device %d changed: active=%s %s", self._device.number, self._active, dict(self))
|
||||
# if _log.isEnabledFor(_DEBUG):
|
||||
# _log.debug("device %d changed: active=%s %s", self._device.number, self._active, dict(self))
|
||||
self._changed_callback(self._device, alert, reason)
|
||||
|
||||
# @property
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 803 B |
Loading…
Reference in New Issue