better battery icon in the systray

This commit is contained in:
Daniel Pavel 2012-11-29 20:13:25 +02:00
parent d6b18cd426
commit 932a015e49
9 changed files with 63 additions and 30 deletions

View File

@ -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

View File

@ -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):

View File

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

View File

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

View File

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

View File

@ -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

View File

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

View File

@ -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