From 73e35821ed87a5942e192e3689b2f1c6641a67ce Mon Sep 17 00:00:00 2001 From: coderkun Date: Sat, 4 Jun 2016 13:22:58 +0200 Subject: [PATCH 01/14] move volume button to left toolbar --- data/gtk.glade | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/data/gtk.glade b/data/gtk.glade index 1a0c375..032f24a 100644 --- a/data/gtk.glade +++ b/data/gtk.glade @@ -695,26 +695,6 @@ True - - - - 1 - - - - - True - False - panelstack - - - - - True - False - False True @@ -764,6 +744,26 @@ + + 1 + + + + + True + False + panelstack + + + + + True + False + False + + end 1 From c9f01de84b5850a0da0c4e873e620bd49d3a479e Mon Sep 17 00:00:00 2001 From: coderkun Date: Sat, 4 Jun 2016 14:11:42 +0200 Subject: [PATCH 02/14] use right toolbar to show panel-specific toolbar and migrate toolbar of playlist panel --- data/gtk.glade | 161 +++++++++++++++++++++++++++++++------------------ mcg/mcgGtk.py | 34 ++++++++++- 2 files changed, 133 insertions(+), 62 deletions(-) diff --git a/data/gtk.glade b/data/gtk.glade index 032f24a..d366e74 100644 --- a/data/gtk.glade +++ b/data/gtk.glade @@ -332,73 +332,36 @@ - + + + + True - False - vertical + True - - True - False - False - - - True - False - True - edit-clear - - - - False - True - - - - - - False - True - 0 - - - - + True True - - - True - True - 0 - horizontal - 3 - 0 - 0 - 1 - 5 - - - + 6 + horizontal + 3 + 0 + 0 + 1 + 5 - - True - True - 1 - + playlist Playlist - 2 + 3 @@ -579,7 +542,7 @@ library Library - 3 + 4 @@ -756,13 +719,91 @@ - + True False - False - + + + True + False + + + + server + Server + + + + + True + False + + + + cover + Cover + 1 + + + + + True + False + False + + + True + False + True + edit-clear + + + + False + True + + + + + + playlist + Playlist + 2 + + + + + True + False + False + + + True + False + True + gtk-refresh + + + False + True + + + + + + library + Library + 3 + + end diff --git a/mcg/mcgGtk.py b/mcg/mcgGtk.py index 0084c19..e6e1927 100755 --- a/mcg/mcgGtk.py +++ b/mcg/mcgGtk.py @@ -151,6 +151,8 @@ class Window(): self._stack = builder.get_object('panelstack') # Header self._header_bar = HeaderBar(builder) + # Toolbar stack + self._toolbar_stack = builder.get_object('toolbarstack') # Properties self._header_bar.set_sensitive(False, False) @@ -233,6 +235,7 @@ class Window(): # HeaderBar callbacks def on_header_bar_stack_switched(self, widget): + self._set_visible_toolbar() self._save_visible_panel() @@ -418,6 +421,13 @@ class Window(): self._settings.set_int(Application.SETTING_PANEL, panel_index_selected) + def _set_visible_toolbar(self): + panels = [panel.get() for panel in self._panels] + panel_index_selected = panels.index(self._stack.get_visible_child()) + toolbar = self._panels[panel_index_selected].get_toolbar() + self._toolbar_stack.set_visible_child(toolbar) + + def _show_error(self, message): self._infobar.show_error(message) @@ -605,6 +615,7 @@ class ConnectionPanel(mcg.Base): # Widgets self._panel = builder.get_object('server-panel') + self._toolbar = builder.get_object('server-toolbar') # Zeroconf self._zeroconf_list = builder.get_object('server-zeroconf-list') self._zeroconf_list.set_model(self._services) @@ -629,6 +640,10 @@ class ConnectionPanel(mcg.Base): return self._panel + def get_toolbar(self): + return self._toolbar + + def get_signal_handlers(self): return { 'on_server-zeroconf-list-selection_changed': self.on_service_selected, @@ -731,6 +746,7 @@ class CoverPanel(mcg.Base): # Widgets self._panel = builder.get_object('cover-panel') + self._toolbar = builder.get_object('cover-toolbar') # Cover self._cover_scroll = builder.get_object('cover-scroll') self._cover_image = builder.get_object('cover-image') @@ -747,6 +763,10 @@ class CoverPanel(mcg.Base): return self._panel + def get_toolbar(self): + return self._toolbar + + def get_signal_handlers(self): return { 'on_cover-box_button_press_event': self.on_cover_box_pressed, @@ -949,8 +969,9 @@ class PlaylistPanel(mcg.Base): # Widgets self._panel = builder.get_object('playlist-panel') + self._toolbar = builder.get_object('playlist-toolbar') # Clear button - self._playlist_clear_button = builder.get_object('playlist-clear') + self._playlist_clear_button = builder.get_object('playlist-toolbar-clear') # Playlist Grid: Model self._playlist_grid_model = Gtk.ListStore(GdkPixbuf.Pixbuf, str, str) # Playlist Grid @@ -965,9 +986,13 @@ class PlaylistPanel(mcg.Base): return self._panel + def get_toolbar(self): + return self._toolbar + + def get_signal_handlers(self): return { - 'on_playlist-clear_clicked': self._callback_from_widget + 'on_playlist-toolbar-clear_clicked': self._callback_from_widget } @@ -1068,6 +1093,7 @@ class LibraryPanel(mcg.Base): # Widgets self._panel = builder.get_object('library-panel') + self._toolbar = builder.get_object('library-toolbar') # Progress Bar self._progress_revealer = builder.get_object('library-progress-revealer') self._progress_bar = builder.get_object('library-progress') @@ -1109,6 +1135,10 @@ class LibraryPanel(mcg.Base): return self._panel + def get_toolbar(self): + return self._toolbar + + def get_signal_handlers(self): return { 'on_library-update_clicked': self.on_update_clicked, From 6b75674031b43f7a7c2603dae78d1d6d1e472294 Mon Sep 17 00:00:00 2001 From: coderkun Date: Sun, 5 Jun 2016 12:42:39 +0200 Subject: [PATCH 03/14] migrate toolbar of library panel --- data/gtk.glade | 331 ++++++++++++++++++++++++++++++------------------- mcg/mcgGtk.py | 119 +++++++++--------- 2 files changed, 266 insertions(+), 184 deletions(-) diff --git a/data/gtk.glade b/data/gtk.glade index d366e74..08392d6 100644 --- a/data/gtk.glade +++ b/data/gtk.glade @@ -9,6 +9,150 @@ 1 10 + + False + + + True + False + vertical + + + True + True + library-scale-adjustment + 0 + False + False + + + + + False + True + 0 + + + + + gtk-refresh + True + True + True + none + True + + + + False + True + 1 + + + + + True + False + vertical + + + True + False + vertical + + + False + True + 0 + + + + + True + False + Sort + + + False + True + 1 + + + + + sort by artist + True + True + False + True + library-toolbar-sort-year + + + + False + True + 2 + + + + + sort by title + True + True + False + True + library-toolbar-sort-year + + + + False + True + 3 + + + + + sort by year + True + True + False + True + True + + + + False + True + 4 + + + + + gtk-sort-descending + True + True + False + True + True + True + + + + False + True + 5 + + + + + False + True + 2 + + + + + 1024 9999 @@ -331,9 +475,6 @@ 1 - - - True @@ -361,7 +502,7 @@ playlist Playlist - 3 + 2 @@ -369,6 +510,30 @@ True False vertical + + + True + True + False + + + + True + True + edit-find-symbolic + False + False + search library + + + + + + False + True + 0 + + True @@ -382,125 +547,6 @@ - - False - True - 0 - - - - - True - False - 0 - - - True - False - - - True - False - True - view-refresh - - - - False - True - - - - - - - - True - True - edit-find-symbolic - False - False - search library - - - - - - True - False - - - True - False - - - 100 - True - True - library-scale-adjustment - off - off - False - 0 - 0 - False - - - - - - - False - True - - - - - True - False - - - True - False - - - - - - False - True - - - - - True - False - True - view-sort-descending - True - - - - False - True - - - - - - end - 1 - - - - False True @@ -542,7 +588,7 @@ library Library - 4 + 3 @@ -726,6 +772,7 @@ True False + end @@ -739,6 +786,7 @@ True False + end @@ -753,6 +801,7 @@ True False + end False @@ -781,17 +830,45 @@ True False + end False - + True False True - gtk-refresh + edit-find-symbolic + False - True + False + + + + + True + False + + + True + True + True + none + library-toolbar-popover + + + True + False + open-menu-symbolic + + + + + + + False + False + True + + 1 + + + True + False + + + 2 + + + + + True + True + True + + + + True + False + media-playback-start + + + + + 3 + + + + + True + True + False + True + none + vertical + audio-volume-muted + audio-volume-high + audio-volume-low + audio-volume-medium + + + + + + True + True + center + center + none + + + + + True + True + center + center + none + + + + + 4 + + + + + True @@ -769,56 +746,63 @@ True False - + True False - end - - - - server - Server - - - - - True - False - end - + 6 + end + + + cover Cover + + + + + True + False + 6 + end + + + + + + server + Server 1 - + True False - end - False + 6 + end - + True - False - True - edit-clear + True + True + + + True + False + edit-clear + + False - True + False + 0 + True - playlist @@ -827,53 +811,53 @@ - + True False - end - False + 6 + end - + True - False - True - edit-find-symbolic + True + True - - - False - False - - - - - True - False - + True - True - True - none - library-toolbar-popover - - - True - False - open-menu-symbolic - - + False + system-search-symbolic False - False + False + 0 + True + + + + + True + True + True + library-toolbar-popover + + + True + False + open-menu-symbolic + + + + + False + False + 1 + True - library @@ -884,7 +868,7 @@ end - 1 + 5 From 48b2bcd05dae22094336fc0ead411f84caf78863 Mon Sep 17 00:00:00 2001 From: coderkun Date: Sat, 11 Jun 2016 12:25:27 +0200 Subject: [PATCH 05/14] add standalone mode to library panel --- data/gtk.glade | 243 ++++++++++++++++++++++++++++++++++++++----------- data/mcg.css | 4 + mcg/mcgGtk.py | 166 ++++++++++++++++++++++++--------- 3 files changed, 318 insertions(+), 95 deletions(-) diff --git a/data/gtk.glade b/data/gtk.glade index 3d9690d..d4d248b 100644 --- a/data/gtk.glade +++ b/data/gtk.glade @@ -2,6 +2,62 @@ + + True + False + + + True + True + True + + + + True + False + go-previous-symbolic + + + + + + + True + False + vertical + + + True + False + Title + True + + + + + + + False + True + 0 + + + + + True + False + Artist + True + + + False + True + 1 + + + + + 100 1000 @@ -364,6 +420,7 @@ True False False + True @@ -506,82 +563,164 @@ - + True False - vertical + slide-left-right - + True - True False - + vertical - + True - True - edit-find-symbolic - False - False - search library - + True + False + + + + True + True + edit-find-symbolic + False + False + search library + + + + + False + True + 0 + - - - False - True - 0 - - - - - True - False - none - + True False - 0.5 + none + + + True + False + 0.5 + + + + False + True + 1 + - - - False - True - 1 - - - - - True - True - + True True - 0 - horizontal - 0 - 0 - 1 - 5 - + + + True + True + 6 + none + horizontal + 0 + 0 + 1 + 5 + True + + + + + + True + True + 2 + - - True - True - end - 2 + page0 + page0 + + + + + True + False + vertical + + + True + False + + + True + False + + + standalone-spinne + + + + + True + True + False + False + + + + True + False + + + True + False + gtk-missing-image + 6 + + + + + + + standalone-scroll + 1 + + + + + True + True + 0 + + + + + True + False + + + False + True + 1 + + + + + page1 + page1 + 1 diff --git a/data/mcg.css b/data/mcg.css index 37178f3..df42fb1 100644 --- a/data/mcg.css +++ b/data/mcg.css @@ -21,3 +21,7 @@ GtkIconView.cell:selected:focus { iconview.view:hover { -gtk-icon-effect:highlight; } + +actionbar { + background-color:@theme_unfocused_bg_color; +} diff --git a/mcg/mcgGtk.py b/mcg/mcgGtk.py index 512b38f..c602a3f 100755 --- a/mcg/mcgGtk.py +++ b/mcg/mcgGtk.py @@ -77,6 +77,27 @@ class Application(Gtk.Application): ) + def load_cover(url): + if not url: + return None + if url.startswith('/'): + try: + return GdkPixbuf.Pixbuf.new_from_file(url) + except Exception as e: + print(e) + return None + else: + try: + response = urllib.request.urlopen(url) + loader = GdkPixbuf.PixbufLoader() + loader.write(response.read()) + loader.close() + return loader.get_pixbuf() + except Exception as e: + print(e) + return None + + def load_thumbnail(cache, album, size): cache_url = cache.create_filename(album) pixbuf = None @@ -88,26 +109,12 @@ class Application(Gtk.Application): print(e) else: url = album.get_cover() - if url is not None: - if url.startswith('/'): - try: - pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(url, size, size) - except Exception as e: - print(e) - else: - try: - response = urllib.request.urlopen(url) - loader = GdkPixbuf.PixbufLoader() - loader.write(response.read()) - loader.close() - pixbuf = loader.get_pixbuf().scale_simple(size, size, GdkPixbuf.InterpType.HYPER) - except Exception as e: - print(e) - if pixbuf is not None: - filetype = os.path.splitext(url)[1][1:] - if filetype == 'jpg': - filetype = 'jpeg' - pixbuf.savev(cache.create_filename(album), filetype, [], []) + pixbuf = Application.load_cover(url) + if pixbuf is not None: + filetype = os.path.splitext(url)[1][1:] + if filetype == 'jpg': + filetype = 'jpeg' + pixbuf.savev(cache.create_filename(album), filetype, [], []) return pixbuf @@ -872,7 +879,7 @@ class CoverPanel(mcg.Base): url = album.get_cover() if url is not None and url is not "": # Load image and draw it - self._cover_pixbuf = self._load_cover(url) + self._cover_pixbuf = Application.load_cover(url) self._resize_image() else: # Reset image @@ -906,25 +913,6 @@ class CoverPanel(mcg.Base): return True - def _load_cover(self, url): - if url.startswith('/'): - try: - return GdkPixbuf.Pixbuf.new_from_file(url) - except Exception as e: - print(e) - return None - else: - try: - response = urllib.request.urlopen(url) - loader = GdkPixbuf.PixbufLoader() - loader.write(response.read()) - loader.close() - return loader.get_pixbuf() - except Exception as e: - print(e) - return None - - def _resize_image(self): """Diese Methode skaliert das geladene Bild aus dem Pixelpuffer auf die Größe des Fensters unter Beibehalt der Seitenverhältnisse @@ -1090,10 +1078,18 @@ class LibraryPanel(mcg.Base): self._library_lock = threading.Lock() self._library_stop = threading.Event() self._icon_theme = Gtk.IconTheme.get_default() + self._standalone_pixbuf = None + self._selected_albums = [] # Widgets + self._appwindow = builder.get_object('appwindow') self._panel = builder.get_object('library-panel') self._toolbar = builder.get_object('library-toolbar') + self._headerbar = builder.get_object('headerbar') + self._headerbar_standalone = builder.get_object('headerbar-library-standalone') + self._panel_normal = builder.get_object('library-panel-normal') + self._panel_standalone = builder.get_object('library-panel-standalone') + # Filter/search bar self._filter_bar = builder.get_object('library-filter-bar') self._filter_entry = builder.get_object('library-filter') @@ -1122,6 +1118,19 @@ class LibraryPanel(mcg.Base): self._library_grid.set_pixbuf_column(0) self._library_grid.set_text_column(-1) self._library_grid.set_tooltip_column(1) + # Standalon labels + self._standalone_title = builder.get_object('headerbar-library-standalone-title') + self._standalone_artist = builder.get_object('headerbar-library-standalone-artist') + # Standalone Image + self._standalone_stack = builder.get_object('library-standalone-stack') + self._standalone_spinner = builder.get_object('library-standalone-spinner') + self._standalone_scroll = builder.get_object('library-standalone-scroll') + self._standalone_image = builder.get_object('library-standalone-image') + # Action bar + action_bar = builder.get_object('library-standalone-actionbar') + play_button = Gtk.Button('play') + play_button.connect('clicked', self.on_standalone_play_clicked) + action_bar.pack_end(play_button) def get(self): @@ -1142,7 +1151,9 @@ class LibraryPanel(mcg.Base): 'on_library-toolbar-sort-order_toggled': self.on_sort_order_toggled, 'on_library-filter-bar_notify': self.on_filter_bar_notify, 'on_library-filter_search_changed': self.on_filter_entry_changed, - 'on_library-iconview_item_activated': self.on_library_grid_clicked + 'on_library-iconview_item_activated': self.on_library_grid_clicked, + 'on_library-standalone-scroll_size_allocate': self.on_standalone_scroll_size_allocate, + 'on_headerbar-library-standalone-close_clicked': self.on_standalone_close_clicked } @@ -1199,9 +1210,23 @@ class LibraryPanel(mcg.Base): def on_library_grid_clicked(self, widget, path): + # Get selected album path = self._library_grid_filter.convert_path_to_child_path(path) iter = self._library_grid_model.get_iter(path) - self._callback(LibraryPanel.SIGNAL_PLAY, self._library_grid_model.get_value(iter, 2)) + hash = self._library_grid_model.get_value(iter, 2) + album = self._albums[hash] + self._selected_albums = [album] + + # Set labels + self._standalone_title.set_text(album.get_title()) + self._standalone_artist.set_text(", ".join(album.get_artists())) + + # Show panel + self._panel.set_visible_child(self._panel_standalone) + self._appwindow.set_titlebar(self._headerbar_standalone) + + # Load cover + threading.Thread(target=self._show_standalone_image, args=(album,)).start() def on_filter_visible(self, model, iter, data): @@ -1212,6 +1237,19 @@ class LibraryPanel(mcg.Base): return album.filter(self._filter_string) + def on_standalone_scroll_size_allocate(self, widget, allocation): + self._resize_standalone_image() + + + def on_standalone_play_clicked(self, widget): + self._callback(LibraryPanel.SIGNAL_PLAY, self._selected_albums[0].get_hash()) + + + def on_standalone_close_clicked(self, widget): + self._panel.set_visible_child(self._panel.get_children()[0]) + self._appwindow.set_titlebar(self._headerbar) + + def set_item_size(self, item_size): if self._item_size != item_size: self._item_size = item_size @@ -1282,7 +1320,7 @@ class LibraryPanel(mcg.Base): self._library_lock.acquire() self._library_stop.clear() self._albums = albums - self._progress_revealer.set_reveal_child(True) + GObject.idle_add(self._progress_revealer.set_reveal_child, True) GObject.idle_add(self._progress_bar.set_fraction, 0.0) self._library_grid.set_model(None) self._library_grid.freeze_child_notify() @@ -1386,6 +1424,48 @@ class LibraryPanel(mcg.Base): self.set_albums(self._host, self._albums) + def _show_standalone_image(self, album): + self._standalone_stack.set_visible_child(self._standalone_spinner) + self._standalone_spinner.start() + url = album.get_cover() + if url is not None and url is not "": + # Load image and draw it + self._standalone_pixbuf = Application.load_cover(url) + self._resize_standalone_image() + else: + # Reset image + self._standalone_image.clear() + self._standalone_stack.set_visible_child(self._standalone_scroll) + self._standalone_spinner.stop() + + + def _resize_standalone_image(self): + """Diese Methode skaliert das geladene Bild aus dem Pixelpuffer + auf die Größe des Fensters unter Beibehalt der Seitenverhältnisse + """ + pixbuf = self._standalone_pixbuf + size = self._standalone_scroll.get_allocation() + # Check pixelbuffer + if pixbuf is None: + return + + # Skalierungswert für Breite und Höhe ermitteln + ratioW = float(size.width) / float(pixbuf.get_width()) + ratioH = float(size.height) / float(pixbuf.get_height()) + # Kleineren beider Skalierungswerte nehmen, nicht Hochskalieren + ratio = min(ratioW, ratioH) + ratio = min(ratio, 1) + # Neue Breite und Höhe berechnen + width = int(math.floor(pixbuf.get_width()*ratio)) + height = int(math.floor(pixbuf.get_height()*ratio)) + if width <= 0 or height <= 0: + return + # Pixelpuffer auf Oberfläche zeichnen + self._standalone_image.set_allocation(self._standalone_scroll.get_allocation()) + self._standalone_image.set_from_pixbuf(pixbuf.scale_simple(width, height, GdkPixbuf.InterpType.HYPER)) + self._standalone_image.show() + + class StackSwitcher(mcg.Base): From 898f59bd42cce82cf646bffffb99e529667153f0 Mon Sep 17 00:00:00 2001 From: coderkun Date: Sat, 11 Jun 2016 12:38:21 +0200 Subject: [PATCH 06/14] load image for cover panel in its own thread and display spinner icon during loading --- data/gtk.glade | 37 ++++++++++++++++++++++++++++--------- mcg/mcgGtk.py | 36 +++++++++++++++++++++++------------- 2 files changed, 51 insertions(+), 22 deletions(-) diff --git a/data/gtk.glade b/data/gtk.glade index d4d248b..562f483 100644 --- a/data/gtk.glade +++ b/data/gtk.glade @@ -415,30 +415,49 @@ False True - + True - True - False - False - + False - + True False + + + cover-spinner + + + + + True + True + False + False + - + True False - + True False - gtk-missing-image + + + True + False + gtk-missing-image + + + + cover-scroll + 1 + diff --git a/mcg/mcgGtk.py b/mcg/mcgGtk.py index c602a3f..7f74b20 100755 --- a/mcg/mcgGtk.py +++ b/mcg/mcgGtk.py @@ -755,6 +755,8 @@ class CoverPanel(mcg.Base): self._panel = builder.get_object('cover-panel') self._toolbar = builder.get_object('cover-toolbar') # Cover + self._cover_stack = builder.get_object('cover-stack') + self._cover_spinner = builder.get_object('cover-spinner') self._cover_scroll = builder.get_object('cover-scroll') self._cover_image = builder.get_object('cover-image') # Songs @@ -813,6 +815,7 @@ class CoverPanel(mcg.Base): def set_album(self, album): + # Set labels self._album_title_label.set_markup( "{}".format( GObject.markup_escape_text( @@ -834,9 +837,13 @@ class CoverPanel(mcg.Base): ) ) ) - self._set_cover(album) + + # Set tracks self._set_tracks(album) + # Load cover + threading.Thread(target=self._set_cover, args=(album,)).start() + def set_play(self, pos, time): if self._timer is not None: @@ -873,18 +880,21 @@ class CoverPanel(mcg.Base): def _set_cover(self, album): - if self._current_album is not None and album.get_hash() == self._current_album.get_hash(): - return - self._current_album = album - url = album.get_cover() - if url is not None and url is not "": - # Load image and draw it - self._cover_pixbuf = Application.load_cover(url) - self._resize_image() - else: - # Reset image - self._cover_pixbuf = None - self._cover_image.clear() + self._cover_stack.set_visible_child(self._cover_spinner) + self._cover_spinner.start() + if self._current_album is None or album.get_hash() != self._current_album.get_hash(): + self._current_album = album + url = album.get_cover() + if url is not None and url is not "": + # Load image and draw it + self._cover_pixbuf = Application.load_cover(url) + self._resize_image() + else: + # Reset image + self._cover_pixbuf = None + self._cover_image.clear() + self._cover_stack.set_visible_child(self._cover_scroll) + self._cover_spinner.stop() def _set_tracks(self, album): From c0316303792fbcb8ae97855b9cc008d929bec995 Mon Sep 17 00:00:00 2001 From: coderkun Date: Sat, 11 Jun 2016 13:15:20 +0200 Subject: [PATCH 07/14] move labels on cover panel to the right and use CSS for styling --- data/gtk.glade | 168 ++++++++++++++++++++++++------------------------- data/mcg.css | 7 +++ mcg/mcgGtk.py | 20 +++--- 3 files changed, 98 insertions(+), 97 deletions(-) diff --git a/data/gtk.glade b/data/gtk.glade index 562f483..fcbd62d 100644 --- a/data/gtk.glade +++ b/data/gtk.glade @@ -408,60 +408,112 @@ True False - vertical + True - + True False - True - + True False + + + cover-spinner + + + + + True + True + False + False + - + True False - - - cover-spinner - - - - - True - True - False - False - - + True False - + True False - - - True - False - gtk-missing-image - - + gtk-missing-image - - cover-scroll - 1 - - True + cover-scroll + 1 + + + + + True + True + 0 + + + + + True + False + vertical + + + True + False + 5 + 5 + 5 + True + True + + + True + False + Album + + + 0 + 0 + + + + + True + False + Date + + + 0 + 1 + + + + + True + False + Artist + + + 0 + 2 + + + + + + False True 10 0 @@ -473,7 +525,6 @@ True start vertical - 1 False @@ -481,66 +532,15 @@ True True - 10 - end 1 - - True - True - 10 - 0 - - - - - True - False - 5 - 5 - 5 - True - True - - - True - False - Album - - - 0 - 0 - - - - - True - False - Date - - - 0 - 1 - - - - - True - False - Artist - - - 0 - 2 - - - False True 10 + end 1 diff --git a/data/mcg.css b/data/mcg.css index df42fb1..13d4fa8 100644 --- a/data/mcg.css +++ b/data/mcg.css @@ -11,6 +11,13 @@ border:none; } +.cover-labels label { + font-size:larger; +} +.cover-labels label:first-child { + font-weight:bold; +} + iconview.view:selected, iconview.view:selected:focus, GtkIconView.cell:selected, diff --git a/mcg/mcgGtk.py b/mcg/mcgGtk.py index 7f74b20..acc9155 100755 --- a/mcg/mcgGtk.py +++ b/mcg/mcgGtk.py @@ -816,25 +816,19 @@ class CoverPanel(mcg.Base): def set_album(self, album): # Set labels - self._album_title_label.set_markup( - "{}".format( - GObject.markup_escape_text( - album.get_title() - ) + self._album_title_label.set_label( + GObject.markup_escape_text( + album.get_title() ) ) self._album_date_label.set_markup( - "{}".format( - GObject.markup_escape_text( - ', '.join(album.get_dates()) - ) + GObject.markup_escape_text( + ', '.join(album.get_dates()) ) ) self._album_artist_label.set_markup( - "{}".format( - GObject.markup_escape_text( - ', '.join(album.get_artists()) - ) + GObject.markup_escape_text( + ', '.join(album.get_artists()) ) ) From 02ee75de4d0c0694019ec9ff578b4820f20b9659 Mon Sep 17 00:00:00 2001 From: coderkun Date: Sat, 11 Jun 2016 13:29:07 +0200 Subject: [PATCH 08/14] fix fullscreen with new widgets --- data/gtk.glade | 5 +++-- mcg/mcgGtk.py | 27 +++++++++++++-------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/data/gtk.glade b/data/gtk.glade index fcbd62d..7d9ecde 100644 --- a/data/gtk.glade +++ b/data/gtk.glade @@ -434,9 +434,10 @@ True False - + True False + True @@ -462,7 +463,7 @@ - + True False vertical diff --git a/mcg/mcgGtk.py b/mcg/mcgGtk.py index acc9155..7d6f3af 100755 --- a/mcg/mcgGtk.py +++ b/mcg/mcgGtk.py @@ -46,7 +46,7 @@ class Application(Gtk.Application): def __init__(self): - Gtk.Application.__init__(self, application_id="de.coderkun.mcg", flags=Gio.ApplicationFlags.FLAGS_NONE) + Gtk.Application.__init__(self, application_id="de.coderkun.mcg-dev", flags=Gio.ApplicationFlags.FLAGS_NONE) self._window = None @@ -279,9 +279,9 @@ class Window(): def on_cover_panel_toggle_fullscreen(self): if not self._fullscreened: - self.fullscreen() + self._appwindow.fullscreen() else: - self.unfullscreen() + self._appwindow.unfullscreen() def on_cover_panel_set_song(self, pos, time): @@ -414,10 +414,10 @@ class Window(): if fullscreened_new != self._fullscreened: self._fullscreened = fullscreened_new if self._fullscreened: - self._header_bar.hide() + self._header_bar.get().hide() self._panels[Window._PANEL_INDEX_COVER].set_fullscreen(True) else: - self._header_bar.show() + self._header_bar.get().show() self._panels[Window._PANEL_INDEX_COVER].set_fullscreen(False) @@ -758,14 +758,16 @@ class CoverPanel(mcg.Base): self._cover_stack = builder.get_object('cover-stack') self._cover_spinner = builder.get_object('cover-spinner') self._cover_scroll = builder.get_object('cover-scroll') + self._cover_box = builder.get_object('cover-box') self._cover_image = builder.get_object('cover-image') - # Songs - self._songs_scale = builder.get_object('cover-songs') - self._songs_scale.override_color(Gtk.StateFlags.NORMAL, Gdk.RGBA(0, 0, 0, 1)) # Album Infos + self._info_box = builder.get_object('cover-info-box') self._album_title_label = builder.get_object('cover-album') self._album_date_label = builder.get_object('cover-date') self._album_artist_label = builder.get_object('cover-artist') + # Songs + self._songs_scale = builder.get_object('cover-songs') + self._songs_scale.override_color(Gtk.StateFlags.NORMAL, Gdk.RGBA(0, 0, 0, 1)) def get(self): @@ -860,15 +862,12 @@ class CoverPanel(mcg.Base): def set_fullscreen(self, active): if active: self._songs_scale.hide() - self._info_grid.hide() - self.child_set_property(self._current_box, 'padding', 0) - self._current_box.child_set_property(self._cover_scroll, 'padding', 0) + self._info_box.hide() self._cover_box.override_background_color(Gtk.StateFlags.NORMAL, Gdk.RGBA(0, 0, 0, 1)) + GObject.idle_add(self._resize_image) else: self._songs_scale.show() - self._info_grid.show() - self.child_set_property(self._current_box, 'padding', 10) - self._current_box.child_set_property(self._cover_scroll, 'padding', 10) + self._info_box.show() self._cover_box.override_background_color(Gtk.StateFlags.NORMAL, Gdk.RGBA(0, 0, 0, 0)) GObject.idle_add(self._resize_image) From 1001f38a67a39214e0827c9386b5936ad2e09e72 Mon Sep 17 00:00:00 2001 From: coderkun Date: Sat, 11 Jun 2016 13:34:16 +0200 Subject: [PATCH 09/14] add button for fullscreen action to toolbar of cover panel --- data/gtk.glade | 20 +++++++++++++++++++- mcg/mcgGtk.py | 5 +++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/data/gtk.glade b/data/gtk.glade index 7d9ecde..82c6753 100644 --- a/data/gtk.glade +++ b/data/gtk.glade @@ -911,7 +911,25 @@ 6 end - + + True + True + True + + + + True + False + view-fullscreen-symbolic + + + + + False + False + 0 + True + diff --git a/mcg/mcgGtk.py b/mcg/mcgGtk.py index 7d6f3af..646fbf4 100755 --- a/mcg/mcgGtk.py +++ b/mcg/mcgGtk.py @@ -780,6 +780,7 @@ class CoverPanel(mcg.Base): def get_signal_handlers(self): return { + 'on_cover-toolbar-fullscreen_clicked': self.on_fullscreen_clicked, 'on_cover-box_button_press_event': self.on_cover_box_pressed, 'on_cover-scroll_size_allocate': self.on_cover_size_allocate, 'on_cover-songs_button_press_event': self.on_songs_start_change, @@ -787,6 +788,10 @@ class CoverPanel(mcg.Base): } + def on_fullscreen_clicked(self, widget): + self._callback(self.SIGNAL_TOGGLE_FULLSCREEN) + + def on_cover_box_pressed(self, widget, event): if event.type == Gdk.EventType._2BUTTON_PRESS: self._callback(self.SIGNAL_TOGGLE_FULLSCREEN) From be3037bc03cbab03ea685d2b714d7419e7f22c1e Mon Sep 17 00:00:00 2001 From: coderkun Date: Sat, 11 Jun 2016 13:51:59 +0200 Subject: [PATCH 10/14] fix resizing of thumbnails (for iconviews) --- mcg/mcgGtk.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mcg/mcgGtk.py b/mcg/mcgGtk.py index 646fbf4..eb6ea7d 100755 --- a/mcg/mcgGtk.py +++ b/mcg/mcgGtk.py @@ -111,6 +111,7 @@ class Application(Gtk.Application): url = album.get_cover() pixbuf = Application.load_cover(url) if pixbuf is not None: + pixbuf = pixbuf.scale_simple(size, size, GdkPixbuf.InterpType.HYPER) filetype = os.path.splitext(url)[1][1:] if filetype == 'jpg': filetype = 'jpeg' From c8dd5f7a83dd68afb49e309fca00ffb0f7feed68 Mon Sep 17 00:00:00 2001 From: coderkun Date: Sat, 11 Jun 2016 14:06:06 +0200 Subject: [PATCH 11/14] set item padding of iconviews based on item size --- data/gtk.glade | 8 ++++---- mcg/mcgGtk.py | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/data/gtk.glade b/data/gtk.glade index 82c6753..ace5bd7 100644 --- a/data/gtk.glade +++ b/data/gtk.glade @@ -560,13 +560,13 @@ True True - 6 + 0 horizontal 3 0 0 1 - 5 + 0 @@ -643,13 +643,13 @@ True True - 6 + 0 none horizontal 0 0 1 - 5 + 0 True + + + + page0 + page0 + + + + + True + False + vertical + + + True + False + + + True + False + + + standalone-spinne + + + + + True + True + False + False + + + True + False + + + True + False + gtk-missing-image + 6 + + + + + + + standalone-scroll + 1 + + + + + True + True + 0 + + + + + True + False + + + False + True + 1 + + + + + page1 + page1 + 1 + - playlist diff --git a/mcg/mcgGtk.py b/mcg/mcgGtk.py index d7dcc00..53f05f2 100755 --- a/mcg/mcgGtk.py +++ b/mcg/mcgGtk.py @@ -969,13 +969,22 @@ class PlaylistPanel(mcg.Base): self._host = None self._item_size = 150 self._playlist = None + self._playlist_albums = None self._playlist_lock = threading.Lock() self._playlist_stop = threading.Event() self._icon_theme = Gtk.IconTheme.get_default() + self._standalone_pixbuf = None + self._selected_albums = [] # Widgets + self._appwindow = builder.get_object('appwindow') self._panel = builder.get_object('playlist-panel') self._toolbar = builder.get_object('playlist-toolbar') + self._headerbar = builder.get_object('headerbar') + self._headerbar_standalone = builder.get_object('headerbar-playlist-standalone') + self._panel_normal = builder.get_object('playlist-panel-normal') + self._panel_standalone = builder.get_object('playlist-panel-standalone') + # Clear button self._playlist_clear_button = builder.get_object('playlist-toolbar-clear') # Playlist Grid: Model @@ -987,6 +996,17 @@ class PlaylistPanel(mcg.Base): self._playlist_grid.set_text_column(-1) self._playlist_grid.set_tooltip_column(1) + # Standalone labels + self._standalone_title = builder.get_object('headerbar-playlist-standalone-title') + self._standalone_artist = builder.get_object('headerbar-playlist-standalone-artist') + # Standalone Image + self._standalone_stack = builder.get_object('playlist-standalone-stack') + self._standalone_spinner = builder.get_object('playlist-standalone-spinner') + self._standalone_scroll = builder.get_object('playlist-standalone-scroll') + self._standalone_image = builder.get_object('playlist-standalone-image') + # Action bar + action_bar = builder.get_object('playlist-standalone-actionbar') + def get(self): return self._panel @@ -998,10 +1018,41 @@ class PlaylistPanel(mcg.Base): def get_signal_handlers(self): return { - 'on_playlist-toolbar-clear_clicked': self._callback_from_widget + 'on_playlist-toolbar-clear_clicked': self._callback_from_widget, + 'on_playlist-iconview_item_activated': self.on_playlist_grid_clicked, + 'on_playlist-standalone-scroll_size_allocate': self.on_standalone_scroll_size_allocate, + 'on_headerbar-playlist-standalone-close_clicked': self.on_standalone_close_clicked } + def on_playlist_grid_clicked(self, widget, path): + # Get selected album + iter = self._playlist_grid_model.get_iter(path) + hash = self._playlist_grid_model.get_value(iter, 2) + album = self._playlist_albums[hash] + self._selected_albums = [album] + + # Set labels + self._standalone_title.set_text(album.get_title()) + self._standalone_artist.set_text(", ".join(album.get_artists())) + + # Show panel + self._panel.set_visible_child(self._panel_standalone) + self._appwindow.set_titlebar(self._headerbar_standalone) + + # Load cover + threading.Thread(target=self._show_standalone_image, args=(album,)).start() + + + def on_standalone_scroll_size_allocate(self, widget, allocation): + self._resize_standalone_image() + + + def on_standalone_close_clicked(self, widget): + self._panel.set_visible_child(self._panel.get_children()[0]) + self._appwindow.set_titlebar(self._headerbar) + + def set_item_size(self, item_size): if self._item_size != item_size: self._item_size = item_size @@ -1026,6 +1077,9 @@ class PlaylistPanel(mcg.Base): self._playlist_lock.acquire() self._playlist_stop.clear() self._playlist = playlist + self._playlist_albums = {} + for album in playlist: + self._playlist_albums[album.get_hash()] = album self._playlist_grid.set_model(None) self._playlist_grid.freeze_child_notify() self._playlist_grid_model.clear() @@ -1068,6 +1122,48 @@ class PlaylistPanel(mcg.Base): self.set_playlist(self._host, self._playlist) + def _show_standalone_image(self, album): + self._standalone_stack.set_visible_child(self._standalone_spinner) + self._standalone_spinner.start() + url = album.get_cover() + if url is not None and url is not "": + # Load image and draw it + self._standalone_pixbuf = Application.load_cover(url) + self._resize_standalone_image() + else: + # Reset image + self._standalone_image.clear() + self._standalone_stack.set_visible_child(self._standalone_scroll) + self._standalone_spinner.stop() + + + def _resize_standalone_image(self): + """Diese Methode skaliert das geladene Bild aus dem Pixelpuffer + auf die Größe des Fensters unter Beibehalt der Seitenverhältnisse + """ + pixbuf = self._standalone_pixbuf + size = self._standalone_scroll.get_allocation() + # Check pixelbuffer + if pixbuf is None: + return + + # Skalierungswert für Breite und Höhe ermitteln + ratioW = float(size.width) / float(pixbuf.get_width()) + ratioH = float(size.height) / float(pixbuf.get_height()) + # Kleineren beider Skalierungswerte nehmen, nicht Hochskalieren + ratio = min(ratioW, ratioH) + ratio = min(ratio, 1) + # Neue Breite und Höhe berechnen + width = int(math.floor(pixbuf.get_width()*ratio)) + height = int(math.floor(pixbuf.get_height()*ratio)) + if width <= 0 or height <= 0: + return + # Pixelpuffer auf Oberfläche zeichnen + self._standalone_image.set_allocation(self._standalone_scroll.get_allocation()) + self._standalone_image.set_from_pixbuf(pixbuf.scale_simple(width, height, GdkPixbuf.InterpType.HYPER)) + self._standalone_image.show() + + def _callback_from_widget(self, widget): if widget is self._playlist_clear_button: self._callback(PlaylistPanel.SIGNAL_CLEAR_PLAYLIST) From ed29006f10bb55c74b667026ebb22442a5d7917f Mon Sep 17 00:00:00 2001 From: coderkun Date: Mon, 1 Aug 2016 10:36:13 +0200 Subject: [PATCH 14/14] add options for different tracklist sizes on cover panel --- data/de.coderkun.MCG.gschema.xml | 10 ++ data/gschemas.compiled | Bin 812 -> 928 bytes data/gtk.glade | 245 ++++++++++++++++++++++--------- mcg/mcgGtk.py | 71 ++++++++- 4 files changed, 255 insertions(+), 71 deletions(-) diff --git a/data/de.coderkun.MCG.gschema.xml b/data/de.coderkun.MCG.gschema.xml index c532da1..057448c 100644 --- a/data/de.coderkun.MCG.gschema.xml +++ b/data/de.coderkun.MCG.gschema.xml @@ -37,6 +37,16 @@ Last selected panel The index of the last selected panel. + + 'large' + + + + + + Size of tracklist on cover panel + The size of the tracklist on the cover panel. + 150 diff --git a/data/gschemas.compiled b/data/gschemas.compiled index ec3c06730c5d165c7804c268dd1b309b298427b5..4c938fdd692119bba04b888cca36dd09950f0b7a 100644 GIT binary patch literal 928 zcmYjQziSjh82zHR(OfiMVL-cd*+uTIO`(ESf>;SkO6PXRyCM6F-N}!WMA8T%+N#AB z{sG#Ef<;8jXquFQ+FJ@DT6w-VyB9L>_Pu%E%s1ceH@kdW6-K32>Tvi^WB~pK!vh&;+6*B0jFxr zfSbo~2KwsF%OA)*Z%#JkC%A*+HhPOK`qWMMOZ0%(U+4eOr*6T22z~;5+_^u?TB$ww z&%rN&y}5?VLp=lk9r!(PU5&Pxhq?iOAAAVB{k-7TQ!~#O@Gs!}@7Y-*mcfcty=>au+kb~I= zTc~g?Hl=Ns=ALFuBvwVAGITTat}@1)j>|;Fu~d3sqDZICo)*9KhiW|t%B-;MtUzCf zS``c)nt?MrGJ2)6!BaF^)lHV+rjK^*q#1JQSqP`@!&}> z{SS&DqPI|bY!$(aAc)|xmmWn=#`h*0=m&4#%bRcB{L1Zhom-tcDQgMbn`$*zdKK`& z&kv_$j$M~KvIRbd5i~_6D0K;j+!OLD5Svbv#U_8aopzFFlY{CizbNJ~n^TAd;7W-q zxK@Jw<7@K`j&rT5?8sN}H{ki(mwo!wb@;!)=fL|P%|G<18}PYM0NnWfw4hJToCdfF z96x?i=l-b!_$}}nF#h~th5gj*zX{#|X6L2mdGCXt0UtlL{649f^9poT3^xH&lns#h+8mb68L+$v$sBUb!vxn^BA-h=8 zI+OTtjK2mrjag?{OO#b3Wo;OSIM?)DX$Qb%pbqeTS=<($NrpN#0~#p)W*(XIF63=x zg_A)R>48_=Xq2U?iJU(P&fza3%kj69kXza8< + + False + + + True + False + vertical + + + True + False + vertical + + + True + False + Tracklist + + + False + True + 0 + + + + + large tracklist + True + True + False + True + True + + + + False + True + 1 + + + + + small tracklist + True + True + False + True + True + cover-toolbar-tracklist-large + + + + False + True + 2 + + + + + hide tracklist + True + True + False + True + True + cover-toolbar-tracklist-large + + + + False + True + 3 + + + + + False + True + 2 + + + + + True False @@ -519,85 +603,91 @@ - + True False - vertical + slide-right + True - + True False - 5 - 5 - 5 - True - True - - - True - False - Album - - - 0 - 0 - - - - - True - False - Date - - - 0 - 1 - - - - - True - False - Artist - - - 0 - 2 - - - - - - False - True - 10 - 0 - - - - - True - True - start vertical - False - - + + + True + False + 5 + 5 + 5 + True + True + + + True + False + Album + + + 0 + 0 + + + + + True + False + Date + + + 0 + 1 + + + + + True + False + Artist + + + 0 + 2 + + + + + + False + True + 10 + 0 + + + + + True + True + start + vertical + False + + + + + True + True + 1 + + - - True - True - 1 - False True - 10 - end 1 @@ -1068,6 +1158,27 @@ True + + + True + True + True + cover-toolbar-popover + + + True + False + open-menu-symbolic + + + + + False + False + 1 + True + + cover diff --git a/mcg/mcgGtk.py b/mcg/mcgGtk.py index 53f05f2..bca4d7f 100755 --- a/mcg/mcgGtk.py +++ b/mcg/mcgGtk.py @@ -38,6 +38,7 @@ class Application(Gtk.Application): SETTING_WINDOW_SIZE = 'window-size' SETTING_WINDOW_MAXIMIZED = 'window-maximized' SETTING_PANEL = 'panel' + SETTING_TRACKLIST_SIZE = 'tracklist-size' SETTING_ITEM_SIZE = 'item-size' SETTING_SORT_ORDER = 'sort-order' SETTING_SORT_TYPE = 'sort-type' @@ -169,6 +170,7 @@ class Window(): if use_keyring: self._panels[Window._PANEL_INDEX_CONNECTION].set_password(keyring.get_password(Application.KEYRING_SYSTEM, Application.KEYRING_USERNAME)) self._panels[Window._PANEL_INDEX_CONNECTION].set_image_dir(self._settings.get_string(Application.SETTING_IMAGE_DIR)) + self._panels[Window._PANEL_INDEX_COVER].set_tracklist_size(self._settings.get_string(Application.SETTING_TRACKLIST_SIZE)) self._panels[Window._PANEL_INDEX_PLAYLIST].set_item_size(self._settings.get_int(Application.SETTING_ITEM_SIZE)) self._panels[Window._PANEL_INDEX_LIBRARY].set_item_size(self._settings.get_int(Application.SETTING_ITEM_SIZE)) self._panels[Window._PANEL_INDEX_LIBRARY].set_sort_order(self._settings.get_string(Application.SETTING_SORT_ORDER)) @@ -181,6 +183,7 @@ class Window(): self._header_bar.connect_signal(HeaderBar.SIGNAL_SET_VOLUME, self.on_header_bar_set_volume) self._panels[Window._PANEL_INDEX_CONNECTION].connect_signal(ConnectionPanel.SIGNAL_CONNECTION_CHANGED, self.on_connection_panel_connection_changed) self._panels[Window._PANEL_INDEX_COVER].connect_signal(CoverPanel.SIGNAL_TOGGLE_FULLSCREEN, self.on_cover_panel_toggle_fullscreen) + self._panels[Window._PANEL_INDEX_COVER].connect_signal(CoverPanel.SIGNAL_TRACKLIST_SIZE_CHANGED, self.on_cover_panel_tracklist_size_changed) self._panels[Window._PANEL_INDEX_COVER].connect_signal(CoverPanel.SIGNAL_SET_SONG, self.on_cover_panel_set_song) self._panels[Window._PANEL_INDEX_PLAYLIST].connect_signal(PlaylistPanel.SIGNAL_CLEAR_PLAYLIST, self.on_playlist_panel_clear_playlist) self._panels[Window._PANEL_INDEX_LIBRARY].connect_signal(LibraryPanel.SIGNAL_UPDATE, self.on_library_panel_update) @@ -194,6 +197,7 @@ class Window(): self._mcg.connect_signal(mcg.Client.SIGNAL_LOAD_ALBUMS, self.on_mcg_load_albums) self._mcg.connect_signal(mcg.Client.SIGNAL_ERROR, self.on_mcg_error) self._settings.connect('changed::'+Application.SETTING_PANEL, self.on_settings_panel_changed) + self._settings.connect('changed::'+Application.SETTING_TRACKLIST_SIZE, self.on_settings_tracklist_size_changed) self._settings.connect('changed::'+Application.SETTING_ITEM_SIZE, self.on_settings_item_size_changed) self._settings.connect('changed::'+Application.SETTING_SORT_ORDER, self.on_settings_sort_order_changed) self._settings.connect('changed::'+Application.SETTING_SORT_TYPE, self.on_settings_sort_type_changed) @@ -285,6 +289,10 @@ class Window(): self._appwindow.unfullscreen() + def on_cover_panel_tracklist_size_changed(self, size): + self._settings.set_string(Application.SETTING_TRACKLIST_SIZE, size) + + def on_cover_panel_set_song(self, pos, time): self._mcg.seek(pos, time) @@ -361,6 +369,11 @@ class Window(): self._stack.set_visible_child(self._panels[panel_index].get()) + def on_settings_tracklist_size_changed(self, settings, key): + size = settings.get_string(key) + self._panels[Window._PANEL_INDEX_COVER].set_tracklist_size(size) + + def on_settings_item_size_changed(self, settings, key): size = settings.get_int(key) self._panels[Window._PANEL_INDEX_PLAYLIST].set_item_size(size) @@ -741,7 +754,11 @@ class ConnectionPanel(mcg.Base): class CoverPanel(mcg.Base): SIGNAL_TOGGLE_FULLSCREEN = 'toggle-fullscreen' + SIGNAL_TRACKLIST_SIZE_CHANGED = 'tracklist-size-changed' SIGNAL_SET_SONG = 'set-song' + TRACKLIST_SIZE_LARGE = 'large' + TRACKLIST_SIZE_SMALL = 'small' + TRACKLIST_SIZE_HIDDEN = 'hidden' def __init__(self, builder): @@ -751,11 +768,18 @@ class CoverPanel(mcg.Base): self._cover_pixbuf = None self._timer = None self._properties = {} + self._tracklist_size = CoverPanel.TRACKLIST_SIZE_LARGE # Widgets self._appwindow = builder.get_object('appwindow') self._panel = builder.get_object('cover-panel') self._toolbar = builder.get_object('cover-toolbar') + # Toolbar menu + self._toolbar_tracklist_buttons = { + CoverPanel.TRACKLIST_SIZE_LARGE: builder.get_object('cover-toolbar-tracklist-large'), + CoverPanel.TRACKLIST_SIZE_SMALL: builder.get_object('cover-toolbar-tracklist-small'), + CoverPanel.TRACKLIST_SIZE_HIDDEN: builder.get_object('cover-toolbar-tracklist-hidden') + } # Cover self._cover_stack = builder.get_object('cover-stack') self._cover_spinner = builder.get_object('cover-spinner') @@ -763,6 +787,7 @@ class CoverPanel(mcg.Base): self._cover_box = builder.get_object('cover-box') self._cover_image = builder.get_object('cover-image') # Album Infos + self._info_revealer = builder.get_object('cover-info-revealer') self._info_box = builder.get_object('cover-info-box') self._album_title_label = builder.get_object('cover-album') self._album_date_label = builder.get_object('cover-date') @@ -783,6 +808,7 @@ class CoverPanel(mcg.Base): def get_signal_handlers(self): return { 'on_cover-toolbar-fullscreen_clicked': self.on_fullscreen_clicked, + 'on_cover-toolbar-tracklist_toggled': self.on_tracklist_togged, 'on_cover-box_button_press_event': self.on_cover_box_pressed, 'on_cover-scroll_size_allocate': self.on_cover_size_allocate, 'on_cover-songs_button_press_event': self.on_songs_start_change, @@ -794,6 +820,12 @@ class CoverPanel(mcg.Base): self._callback(self.SIGNAL_TOGGLE_FULLSCREEN) + def on_tracklist_togged(self, widget): + if widget.get_active(): + size = [key for key, value in self._toolbar_tracklist_buttons.items() if value is widget][0] + self._change_tracklist_size(size) + + def on_cover_box_pressed(self, widget, event): if event.type == Gdk.EventType._2BUTTON_PRESS: self._callback(self.SIGNAL_TOGGLE_FULLSCREEN) @@ -823,6 +855,18 @@ class CoverPanel(mcg.Base): self._callback(self.SIGNAL_SET_SONG, pos, time) + def set_tracklist_size(self, size): + if self._tracklist_size != size: + button = self._toolbar_tracklist_buttons[size] + if button and not button.get_active(): + button.set_active(True) + self._change_tracklist_size(size, False) + + + def get_tracklist_size(self): + return self._tracklist_size + + def set_album(self, album): # Set labels self._album_title_label.set_label( @@ -868,8 +912,7 @@ class CoverPanel(mcg.Base): def set_fullscreen(self, active): if active: - self._songs_scale.hide() - self._info_box.hide() + self._change_tracklist_size(CoverPanel.TRACKLIST_SIZE_HIDDEN, False, False) self._cover_box.override_background_color(Gtk.StateFlags.NORMAL, Gdk.RGBA(0, 0, 0, 1)) GObject.idle_add(self._resize_image) # Hide curser @@ -877,8 +920,7 @@ class CoverPanel(mcg.Base): Gdk.Cursor.new_from_name(Gdk.Display.get_default(), "none") ) else: - self._songs_scale.show() - self._info_box.show() + self._change_tracklist_size(self._tracklist_size, False, False) self._cover_box.override_background_color(Gtk.StateFlags.NORMAL, Gdk.RGBA(0, 0, 0, 0)) GObject.idle_add(self._resize_image) # Reset cursor @@ -924,6 +966,27 @@ class CoverPanel(mcg.Base): self._songs_scale.add_mark(length, Gtk.PositionType.RIGHT, "{0[0]:02d}:{0[1]:02d} minutes".format(divmod(length, 60))) + def _change_tracklist_size(self, size, notify=True, store=True): + # Set tracklist size + if size == CoverPanel.TRACKLIST_SIZE_LARGE: + self._panel.set_homogeneous(True) + self._info_revealer.set_reveal_child(True) + elif size == CoverPanel.TRACKLIST_SIZE_SMALL: + self._panel.set_homogeneous(False) + self._info_revealer.set_reveal_child(True) + else: + self._panel.set_homogeneous(False) + self._info_revealer.set_reveal_child(False) + # Store size + if store: + self._tracklist_size = size + # Notify signals + if notify: + self._callback(CoverPanel.SIGNAL_TRACKLIST_SIZE_CHANGED, size) + # Resize image + self._resize_image() + + def _playing(self): value = self._songs_scale.get_value() + 1 self._songs_scale.set_value(value)