From 5347f41d73cdba8fd5ee51fdf470cac9c77466c5 Mon Sep 17 00:00:00 2001 From: Daniel Pavel Date: Sat, 13 Oct 2012 18:12:16 +0300 Subject: [PATCH] redesigned the window UI --- app/solaar.py | 2 + app/ui/window.py | 226 +++++++++++++++++++++++------------------------ app/watcher.py | 15 ++-- 3 files changed, 123 insertions(+), 120 deletions(-) diff --git a/app/solaar.py b/app/solaar.py index cb2e51e5..8966d82c 100644 --- a/app/solaar.py +++ b/app/solaar.py @@ -61,6 +61,8 @@ if __name__ == '__main__': if args.systray: tray_icon = ui.icon.create(APP_TITLE, (ui.window.toggle, window)) tray_icon.set_from_icon_name(APP_TITLE + '-fail') + else: + window.present() Gtk.main() diff --git a/app/ui/window.py b/app/ui/window.py index 505ab2ad..a788e5f0 100644 --- a/app/ui/window.py +++ b/app/ui/window.py @@ -7,8 +7,8 @@ from gi.repository import (Gtk, Gdk) from logitech.devices import constants as C -_DEVICE_ICON_SIZE = Gtk.IconSize.DND -_STATUS_ICON_SIZE = Gtk.IconSize.DIALOG +_DEVICE_ICON_SIZE = Gtk.IconSize.DIALOG +_STATUS_ICON_SIZE = Gtk.IconSize.DND _PLACEHOLDER = '~' @@ -36,10 +36,10 @@ def _find_children(container, *child_names): return result if count > 1 else result[0] -def _update_receiver_box(box, receiver): - label, buttons_box = _find_children(box, 'receiver-status', 'receiver-buttons') - label.set_text(receiver.text or '') - buttons_box.set_visible(receiver.code >= C.STATUS.CONNECTED) +def _update_receiver_box(box, rstatus): + label, buttons_box = _find_children(box, 'label', 'buttons') + label.set_text(rstatus.text or '') + buttons_box.set_visible(rstatus.code >= C.STATUS.CONNECTED) def _update_device_box(frame, devstatus): @@ -48,147 +48,133 @@ def _update_device_box(frame, devstatus): frame.set_name(_PLACEHOLDER) return + icon, label = _find_children(frame, 'icon', 'label') + frame.set_visible(True) if frame.get_name() != devstatus.name: frame.set_name(devstatus.name) - icon = _find_children(frame, 'device-icon') icon.set_from_icon_name(devstatus.name, _DEVICE_ICON_SIZE) icon.set_tooltip_text(devstatus.name) + label.set_markup('' + devstatus.name + '') - expander = _find_children(frame, 'device-expander') + status = _find_children(frame, 'status') if devstatus.code < C.STATUS.CONNECTED: - expander.set_sensitive(False) - expander.set_expanded(False) - expander.set_label('%s\n%s' % (devstatus.name, devstatus.text)) + icon.set_sensitive(False) + label.set_sensitive(False) + status.set_visible(False) return - expander.set_sensitive(True) - status_icons = expander.get_child().get_children() + icon.set_sensitive(True) + label.set_sensitive(True) + status.set_visible(True) + status_icons = status.get_children() - texts = [] - - light_icon = status_icons[-2] - light_level = getattr(devstatus, C.PROPS.LIGHT_LEVEL, None) - if light_level is None: - light_icon.set_visible(False) - else: - light_icon.set_visible(True) - icon_name = 'light_%02d' % (20 * ((light_level + 50) // 100)) - light_icon.set_from_icon_name(icon_name, _STATUS_ICON_SIZE) - tooltip = 'Light: %d lux' % light_level - light_icon.set_tooltip_text(tooltip) - texts.append(tooltip) - - battery_icon = status_icons[-1] + battery_icon, battery_label = status_icons[0:2] battery_level = getattr(devstatus, C.PROPS.BATTERY_LEVEL, None) if battery_level is None: battery_icon.set_sensitive(False) battery_icon.set_from_icon_name('battery_unknown', _STATUS_ICON_SIZE) - battery_icon.set_tooltip_text('Battery: unknown') + battery_label.set_sensitive(False) + battery_label.set_text('') else: battery_icon.set_sensitive(True) icon_name = 'battery_%02d' % (20 * ((battery_level + 10) // 20)) battery_icon.set_from_icon_name(icon_name, _STATUS_ICON_SIZE) - tooltip = 'Battery: %d%%' % battery_level - battery_icon.set_tooltip_text(tooltip) - texts.append(tooltip) + battery_label.set_sensitive(True) + battery_label.set_text('%d%%' % battery_level) battery_status = getattr(devstatus, C.PROPS.BATTERY_STATUS, None) - if battery_status is not None: - texts.append(battery_status) - battery_icon.set_tooltip_text(battery_icon.get_tooltip_text() + '\n' + battery_status) - - if texts: - expander.set_label('%s\n%s' % (devstatus.name, ', '.join(texts))) + if battery_status is None: + battery_icon.set_tooltip_text('') else: - expander.set_label('%s\n%s' % (devstatus.name, devstatus.text)) + battery_icon.set_tooltip_text(battery_status) + + light_icon, light_label = status_icons[2:4] + light_level = getattr(devstatus, C.PROPS.LIGHT_LEVEL, None) + if light_level is None: + light_icon.set_visible(False) + light_label.set_visible(False) + else: + light_icon.set_visible(True) + icon_name = 'light_%02d' % (20 * ((light_level + 50) // 100)) + light_icon.set_from_icon_name(icon_name, _STATUS_ICON_SIZE) + light_label.set_visible(True) + light_label.set_text('%d lux' % light_level) -def update(window, receiver, devices, icon_name=None): +def update(window, rstatus, devices, icon_name=None): if window and window.get_child(): if icon_name is not None: window.set_icon_name(icon_name) vbox = window.get_child().get_child() controls = list(vbox.get_children()) - _update_receiver_box(controls[0], receiver) + _update_receiver_box(controls[0], rstatus) for index in range(1, len(controls)): _update_device_box(controls[index], devices.get(index)) -def _receiver_box(rstatus): - box = Gtk.HBox(homogeneous=False, spacing=8) - box.set_border_width(4) - - icon = Gtk.Image.new_from_icon_name(rstatus.name, _DEVICE_ICON_SIZE) - icon.set_alignment(0.5, 0) - icon.set_tooltip_text(rstatus.name) - box.pack_start(icon, False, False, 0) - - label = Gtk.Label('Initializing...') - label.set_alignment(0, 0.5) - label.set_name('receiver-status') - box.pack_start(label, True, True, 0) - - toolbar = Gtk.Toolbar() - toolbar.set_style(Gtk.ToolbarStyle.ICONS) - toolbar.set_name('receiver-buttons') - toolbar.set_show_arrow(False) - toolbar.set_icon_size(Gtk.IconSize.BUTTON) - box.pack_end(toolbar, False, False, 0) - - def _action(button, function, params): - button.set_sensitive(False) - function(button, *params) - button.set_sensitive(True) - - def _add_button(name, icon, action): - button = Gtk.ToolButton() - button.set_icon_name(icon) - button.set_tooltip_text(name) - if action: - function = action[0] - params = action[1:] - button.connect('clicked', _action, function, params) - else: - button.set_sensitive(False) - toolbar.insert(button, -1) - - _add_button('Scan for devices', 'reload', rstatus.refresh) - _add_button('Pair new device', 'add', rstatus.pair) - - box.show_all() - toolbar.set_visible(False) - return box - - -def _device_box(): - box = Gtk.HBox(homogeneous=False, spacing=8) +def _device_box(name=None, has_status_icons=True, has_frame=True): + box = Gtk.HBox(homogeneous=False, spacing=10) box.set_border_width(4) icon = Gtk.Image() + if name: + icon.set_from_icon_name(name, _DEVICE_ICON_SIZE) + icon.set_tooltip_text(name) + else: + icon.set_from_icon_name('dialog-question', _DEVICE_ICON_SIZE) icon.set_alignment(0.5, 0) - icon.set_name('device-icon') + icon.set_name('icon') box.pack_start(icon, False, False, 0) - expander = Gtk.Expander() - expander.set_use_markup(True) - expander.set_spacing(4) - expander.set_name('device-expander') - box.pack_start(expander, True, True, 1) + vbox = Gtk.VBox(homogeneous=False, spacing=8) + box.pack_start(vbox, True, True, 0) - ebox = Gtk.HBox(False, 8) - battery_icon = Gtk.Image.new_from_icon_name('battery_unknown', _STATUS_ICON_SIZE) - ebox.pack_end(battery_icon, False, True, 0) - light_icon = Gtk.Image.new_from_icon_name('light_unknown', _STATUS_ICON_SIZE) - ebox.pack_end(light_icon, False, True, 0) - expander.add(ebox) + label = Gtk.Label('...') + label.set_alignment(0, 0.5) + label.set_name('label') - frame = Gtk.Frame() - frame.add(box) - frame.show_all() - frame.set_visible(False) - return frame + status_box = Gtk.HBox(homogeneous=False, spacing=0) + status_box.set_name('status') + + if has_status_icons: + vbox.pack_start(label, True, True, 0) + + battery_icon = Gtk.Image.new_from_icon_name('battery_unknown', _STATUS_ICON_SIZE) + status_box.pack_start(battery_icon, False, True, 0) + battery_label = Gtk.Label() + battery_label.set_width_chars(6) + battery_label.set_alignment(0, 0.5) + status_box.pack_start(battery_label, False, True, 0) + + light_icon = Gtk.Image.new_from_icon_name('light_unknown', _STATUS_ICON_SIZE) + status_box.pack_start(light_icon, False, True, 0) + light_label = Gtk.Label() + light_label.set_alignment(0, 0.5) + light_label.set_width_chars(8) + status_box.pack_start(light_label, False, True, 0) + else: + status_box.pack_start(label, True, True, 0) + + toolbar = Gtk.Toolbar() + toolbar.set_style(Gtk.ToolbarStyle.ICONS) + toolbar.set_icon_size(Gtk.IconSize.MENU) + toolbar.set_name('buttons') + toolbar.set_show_arrow(False) + status_box.pack_end(toolbar, False, False, 0) + + vbox.pack_start(status_box, True, True, 0) + + box.show_all() + + if has_frame: + frame = Gtk.Frame() + frame.add(box) + return frame + else: + toolbar.set_visible(False) + return box def create(title, rstatus, systray=False): @@ -199,9 +185,11 @@ def create(title, rstatus, systray=False): vbox = Gtk.VBox(homogeneous=False, spacing=4) vbox.set_border_width(4) - vbox.add(_receiver_box(rstatus)) + rbox = _device_box(rstatus.name, False, False) + vbox.add(rbox) for i in range(1, 1 + rstatus.max_devices): - vbox.add(_device_box()) + dbox = _device_box() + vbox.add(dbox) vbox.set_visible(True) frame = Gtk.Frame() @@ -211,7 +199,7 @@ def create(title, rstatus, systray=False): window.add(frame) geometry = Gdk.Geometry() - geometry.min_width = 300 + geometry.min_width = 260 geometry.min_height = 40 window.set_geometry_hints(frame, geometry, Gdk.WindowHints.MIN_SIZE) @@ -219,23 +207,35 @@ def create(title, rstatus, systray=False): window.set_default_size(geometry.min_width, geometry.min_height) if systray: + def _state_event(window, event): + if event.new_window_state & Gdk.WindowState.ICONIFIED: + # position = window.get_position() + window.hide() + window.deiconify() + # window.move(*position) + return True + window.set_keep_above(True) - window.set_deletable(False) - window.set_decorated(False) + # window.set_deletable(False) + # window.set_decorated(False) window.set_position(Gtk.WindowPosition.MOUSE) - window.set_type_hint(Gdk.WindowTypeHint.MENU) + # window.set_type_hint(Gdk.WindowTypeHint.MENU) window.set_skip_taskbar_hint(True) window.set_skip_pager_hint(True) + + window.connect('window-state-event', _state_event) + window.connect('delete-event', lambda w, e: toggle(None, window) or True) else: window.set_position(Gtk.WindowPosition.CENTER) window.connect('delete-event', Gtk.main_quit) - window.present() return window def toggle(_, window): if window.get_visible(): + # position = window.get_position() window.hide() + # window.move(*position) else: window.present() diff --git a/app/watcher.py b/app/watcher.py index 71f04d01..cf2594c0 100644 --- a/app/watcher.py +++ b/app/watcher.py @@ -43,7 +43,7 @@ class Watcher(Thread): def __init__(self, status_changed_callback, notify_callback=None): super(Watcher, self).__init__(group='Solaar', name='Watcher') self.daemon = True - self.active = False + self._active = False self.notify = notify_callback self.status_text = None @@ -59,9 +59,9 @@ class Watcher(Thread): self.devices = {} def run(self): - self.active = True + self._active = True - while self.active: + while self._active: if self.listener is None: self._update_status_text() @@ -97,7 +97,7 @@ class Watcher(Thread): self._update_status_text() for i in range(0, int(_THREAD_SLEEP / _SLEEP_QUANT)): - if self.active: + if self._active: time.sleep(_SLEEP_QUANT) else: break @@ -107,8 +107,9 @@ class Watcher(Thread): self.listener = None def stop(self): - self.active = False - self.join() + if self._active: + self._active = False + self.join() def _request_status(self, devstatus): if self.listener and devstatus: @@ -127,7 +128,7 @@ class Watcher(Thread): return updated def _new_device(self, dev): - if not self.active: + if not self._active: return None if type(dev) == int: