From 3f12eedf966ce94fbf398323caf2e87061a71cb5 Mon Sep 17 00:00:00 2001 From: coderkun Date: Sun, 4 Nov 2018 19:09:18 +0100 Subject: [PATCH] Visually indicate changes of playlist and library (close #42) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Set the GTK “needs-attention” property of the header bar stack switcher for the playlist and the library panel when their content changes. --- mcg/client.py | 11 ++++++++++ mcg/widgets.py | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/mcg/client.py b/mcg/client.py index 40d3141..bb105d8 100644 --- a/mcg/client.py +++ b/mcg/client.py @@ -115,6 +115,8 @@ class Client(Base): SIGNAL_LOAD_PLAYLIST = 'load-playlist' # Signal: load audio output devices SIGNAL_LOAD_OUTPUT_DEVICES = 'load-output-devices' + # Signal: custom (dummy) event to trigger callback + SIGNAL_CUSTOM = 'custom' # Signal: error SIGNAL_ERROR = 'error' @@ -275,6 +277,11 @@ class Client(Base): self._add_action(self._set_volume, volume) + def get_custom(self, name): + self._logger.info("get custom \"%s\"", name) + self._add_action(self._get_custom, name) + + # Private methods def _connect(self, host, port, password): @@ -604,6 +611,10 @@ class Client(Base): self._call('setvol', volume) + def _get_custom(self, name): + self._callback(Client.SIGNAL_CUSTOM, name) + + def _start_worker(self): """Start the worker thread which waits for action to be performed.""" self._logger.debug("start worker") diff --git a/mcg/widgets.py b/mcg/widgets.py index 9d9754d..c4c084c 100644 --- a/mcg/widgets.py +++ b/mcg/widgets.py @@ -110,6 +110,7 @@ class Window(): _PANEL_INDEX_PLAYLIST = 2 _PANEL_INDEX_LIBRARY = 3 _CSS_SELECTION = 'selection' + _CUSTOM_STARTUP_COMPLETE = 'startup-complete' def __init__(self, app, builder, title, settings): @@ -179,6 +180,7 @@ class Window(): self._mcg.connect_signal(client.Client.SIGNAL_LOAD_OUTPUT_DEVICES, self.on_mcg_load_output_devices) self._mcg.connect_signal(client.Client.SIGNAL_LOAD_PLAYLIST, self.on_mcg_load_playlist) self._mcg.connect_signal(client.Client.SIGNAL_LOAD_ALBUMS, self.on_mcg_load_albums) + self._mcg.connect_signal(client.Client.SIGNAL_CUSTOM, self.on_mcg_custom) self._mcg.connect_signal(client.Client.SIGNAL_ERROR, self.on_mcg_error) self._settings.connect('changed::'+Window.SETTING_PANEL, self.on_settings_panel_changed) self._settings.connect('changed::'+Window.SETTING_ITEM_SIZE, self.on_settings_item_size_changed) @@ -271,6 +273,14 @@ class Window(): self._set_visible_toolbar() self._save_visible_panel() self._set_menu_visible_panel() + for panel in self._panels: + panel.set_selected(panel.get() == self._stack.get_visible_child()) + GObject.idle_add( + self._stack.child_set_property, + self._stack.get_visible_child(), + 'needs-attention', + False + ) def on_header_bar_connect(self, widget): @@ -367,6 +377,7 @@ class Window(): GObject.idle_add(self._connect_connected) self._mcg.load_playlist() self._mcg.load_albums() + self._mcg.get_custom(Window._CUSTOM_STARTUP_COMPLETE) self._mcg.get_status() self._mcg.get_stats() self._mcg.get_output_devices() @@ -423,6 +434,17 @@ class Window(): self._panels[self._PANEL_INDEX_LIBRARY].set_albums(self._connection_panel.get_host(), albums) + def on_mcg_custom(self, name): + if name == Window._CUSTOM_STARTUP_COMPLETE: + for panel in self._panels: + GObject.idle_add( + self._stack.child_set_property, + panel.get(), + 'needs-attention', + False + ) + + def on_mcg_error(self, error): GObject.idle_add(self._show_error, str(error)) @@ -829,6 +851,7 @@ class ServerPanel(GObject.GObject): GObject.GObject.__init__(self) self._none_label = "" self._output_buttons = {} + self._is_selected = False # Widgets self._panel = builder.get_object('server-panel') @@ -858,6 +881,10 @@ class ServerPanel(GObject.GObject): return self._panel + def set_selected(self, selected): + self._is_selected = selected + + def get_toolbar(self): return self._toolbar @@ -947,6 +974,7 @@ class CoverPanel(GObject.GObject): self._properties = {} self._icon_theme = Gtk.IconTheme.get_default() self._fullscreened = False + self._is_selected = False # Widgets self._appwindow = builder.get_object('appwindow') @@ -979,6 +1007,10 @@ class CoverPanel(GObject.GObject): return self._panel + def set_selected(self, selected): + self._is_selected = selected + + def get_toolbar(self): return self._toolbar @@ -1197,6 +1229,7 @@ class PlaylistPanel(GObject.GObject): self._icon_theme = Gtk.IconTheme.get_default() self._standalone_pixbuf = None self._selected_albums = [] + self._is_selected = False # Widgets self._appwindow = builder.get_object('appwindow') @@ -1251,6 +1284,10 @@ class PlaylistPanel(GObject.GObject): return self._panel + def set_selected(self, selected): + self._is_selected = selected + + def get_toolbar(self): return self._toolbar @@ -1358,6 +1395,13 @@ class PlaylistPanel(GObject.GObject): def _set_playlist(self, host, playlist, size): + if not self._is_selected and self._playlist != playlist: + GObject.idle_add( + self.get().get_parent().child_set_property, + self.get(), + 'needs-attention', + True + ) self._playlist_lock.acquire() self._playlist_stop.clear() self._playlist = playlist @@ -1493,6 +1537,7 @@ class LibraryPanel(GObject.GObject): self._standalone_pixbuf = None self._selected_albums = [] self._allocation = (0, 0) + self._is_selected = False # Widgets self._appwindow = builder.get_object('appwindow') @@ -1573,6 +1618,10 @@ class LibraryPanel(GObject.GObject): return self._panel + def set_selected(self, selected): + self._is_selected = selected + + def get_toolbar(self): return self._toolbar @@ -1817,6 +1866,13 @@ class LibraryPanel(GObject.GObject): def _set_albums(self, host, albums, size): + if not self._is_selected and albums != self._albums: + GObject.idle_add( + self.get().get_parent().child_set_property, + self.get(), + 'needs-attention', + True + ) self._library_lock.acquire() self._library_stop.clear() self._albums = albums