[gnome-music/wip/gbsneto/contained-playlists: 20/29] playlistview: Use a listbox in the sidebar
- From: Georges Basile Stavracas Neto <gbsneto src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-music/wip/gbsneto/contained-playlists: 20/29] playlistview: Use a listbox in the sidebar
- Date: Thu, 1 Dec 2016 23:27:15 +0000 (UTC)
commit dfbd91ae7b75d09f3d31f3e90232781180c3a31b
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date: Thu Dec 1 17:51:51 2016 -0200
playlistview: Use a listbox in the sidebar
Instead of using a treeview, use the listbox and let us
have a finer control of the sorting of the playlists.
Now they're sorted as follows:
* Static playlists always comes first
* All playlists are sorted by the title
* If the title is the same, sort by id
The CSS was adapted to keep the current work in pair with
the old style.
data/application.css | 13 +++
gnomemusic/views/playlistview.py | 197 +++++++++++++++++---------------------
gnomemusic/window.py | 1 +
3 files changed, 100 insertions(+), 111 deletions(-)
---
diff --git a/data/application.css b/data/application.css
index afd0850..b91fc5b 100644
--- a/data/application.css
+++ b/data/application.css
@@ -35,18 +35,31 @@ list, row {
border-width: 0 0 0 1px;
}
+list.side-panel,
.side-panel .view {
background-color: mix(@theme_fg_color, @theme_bg_color, 0.9);
}
+list.side-panel:dir(ltr),
.side-panel .view:dir(ltr) {
box-shadow: inset -10px 0 5px -10px alpha(black, 0.25);
}
+list.side-panel:dir(rtl),
.side-panel .view:dir(rtl) {
box-shadow: inset 10px 0 5px -10px alpha(black, 0.25);
}
+list.side-panel row label,
+list.side-panel row:hover label {
+ color: @theme_fg_color;
+}
+
+list.side-panel row:selected label {
+ color: @theme_selected_fg_color;
+}
+
+list.side-panel row:selected,
.side-panel .view:selected {
background-color: mix(@theme_fg_color, @theme_bg_color, 0.5);
}
diff --git a/gnomemusic/views/playlistview.py b/gnomemusic/views/playlistview.py
index 73692b0..85b33fc 100644
--- a/gnomemusic/views/playlistview.py
+++ b/gnomemusic/views/playlistview.py
@@ -35,6 +35,23 @@ import gnomemusic.utils as utils
playlists = Playlists.get_default()
+def playlist_listbox_sort_func(row1, row2, user_data):
+ """Compares two playlist rows by: static, title and id.
+
+ :return: 0 if they're equal, 1 if row1 comes before row2, -1 otherwise
+ :rtype: int
+ """
+ if row1.playlist.is_static != row2.playlist.is_static:
+ return row2.playlist.is_static - row1.playlist.is_static
+
+ retval = GLib.strcmp0(row1.playlist.title, row2.playlist.title)
+
+ if retval != 0:
+ return retval
+
+ return GLib.strcmp0(row1.playlist.id, row2.playlist.id)
+
+
class PlaylistView(BaseView):
__gsignals__ = {
'playlist-songs-loaded': (GObject.SignalFlags.RUN_FIRST, None, ()),
@@ -45,10 +62,17 @@ class PlaylistView(BaseView):
@log
def __init__(self, window, player):
- self.playlists_sidebar = Gd.MainView()
+ # The playlist sidebar is a GtkListBox, but we pass a scrolled window
+ # to the parent class
+ self.playlists_sidebar = Gtk.ListBox(selection_mode=Gtk.SelectionMode.SINGLE)
+ self.playlists_sidebar.set_sort_func(playlist_listbox_sort_func, self)
+
+ swin = Gtk.ScrolledWindow(hscrollbar_policy=Gtk.PolicyType.NEVER,
+ width_request=220)
+ swin.add(self.playlists_sidebar)
BaseView.__init__(self, 'playlists', _("Playlists"), window,
- Gd.MainViewType.LIST, True, self.playlists_sidebar)
+ Gd.MainViewType.LIST, True, swin)
self.view.get_generic_view().get_style_context()\
.add_class('songs-list')
@@ -70,39 +94,19 @@ class PlaylistView(BaseView):
self._grid.insert_row(0)
self._grid.attach(self.headerbar, 1, 0, 1, 1)
- self.playlists_model = Gtk.ListStore(
- GObject.TYPE_STRING,
- GObject.TYPE_STRING,
- GObject.TYPE_STRING,
- GObject.TYPE_STRING,
- GdkPixbuf.Pixbuf,
- GObject.TYPE_OBJECT,
- GObject.TYPE_BOOLEAN,
- GObject.TYPE_INT,
- GObject.TYPE_STRING,
- GObject.TYPE_INT,
- GObject.TYPE_BOOLEAN,
- GObject.TYPE_INT
- )
-
- self.playlists_sidebar.set_view_type(Gd.MainViewType.LIST)
- self.playlists_sidebar.set_model(self.playlists_model)
self.playlists_sidebar.set_hexpand(False)
self.playlists_sidebar.get_style_context().add_class('side-panel')
- self.playlists_sidebar.get_generic_view().get_selection().set_mode(
- Gtk.SelectionMode.SINGLE)
- self.playlists_sidebar.connect('item-activated', self._on_playlist_activated)
+ self.playlists_sidebar.connect('row-activated', self._on_playlist_activated)
self._grid.insert_column(0)
self._grid.child_set_property(self.stack, 'top-attach', 0)
self._grid.child_set_property(self.stack, 'height', 2)
- self._add_sidebar_renderers()
- self.playlists_sidebar.get_generic_view().get_style_context().remove_class('content-view')
self.iter_to_clean = None
self.iter_to_clean_model = None
self.current_playlist = None
self.current_playlist_index = None
self.pl_todelete = None
+ self.pl_todelete_row = None
self.pl_todelete_index = None
self.really_delete = True
self.songs_count = 0
@@ -189,25 +193,6 @@ class PlaylistView(BaseView):
list_widget.add_renderer(type_renderer,
self._on_list_widget_type_render, None)
- @log
- def _add_sidebar_renderers(self):
- list_widget = self.playlists_sidebar.get_generic_view()
-
- cols = list_widget.get_columns()
- cells = cols[0].get_cells()
- cells[1].set_visible(False)
- cells[2].set_visible(False)
- type_renderer = Gd.StyledTextRenderer(
- xpad=16,
- ypad=16,
- ellipsize=Pango.EllipsizeMode.END,
- xalign=0.0,
- width=220
- )
- list_widget.add_renderer(type_renderer, lambda *args: None, None)
- cols[0].clear_attributes(type_renderer)
- cols[0].add_attribute(type_renderer, "text", 2)
-
def _on_list_widget_title_render(self, col, cell, model, _iter, data):
pass
@@ -269,21 +254,6 @@ class PlaylistView(BaseView):
return False
@log
- def _add_playlist_to_model(self, playlist, index=None):
- if index is None:
- index = -1
- _iter = self.playlists_model.insert_with_valuesv(
- index,
- [2, 5],
- [playlist.title, playlist])
- if self.playlists_model.iter_n_children(None) == 1:
- _iter = self.playlists_model.get_iter_first()
- selection = self.playlists_sidebar.get_generic_view().get_selection()
- selection.select_iter(_iter)
- self.playlists_sidebar.emit('item-activated', '0',
- self.playlists_model.get_path(_iter))
-
- @log
def _on_item_activated(self, widget, id, path):
if self.star_handler.star_renderer_click:
self.star_handler.star_renderer_click = False
@@ -301,16 +271,13 @@ class PlaylistView(BaseView):
self.player.set_playing(True)
@log
- def on_playlist_update(self, widget, playlist):
- _iter = self.playlists_model.get_iter_first()
- while _iter:
- current_playlist = self.playlists_model.get_value(_iter, 5)
- if playlist == current_playlist and \
- self.current_playlist == current_playlist:
- path = self.playlists_model.get_path(_iter)
- GLib.idle_add(self._on_playlist_activated, None, None, path)
- break
- _iter = self.playlists_model.iter_next(_iter)
+ def on_playlist_update(self, playlists, playlist):
+ for row in self.playlists_listbox.get_children():
+ if playlist != row.playlist or self.current_playlist != row.playlist:
+ continue
+
+ self._on_playlist_activated(self.playlists_listbox, row)
+ pass
@log
def activate_playlist(self, playlist_id):
@@ -318,21 +285,22 @@ class PlaylistView(BaseView):
if not self._init:
return
- for playlist in self.playlists_model:
- if playlist[5].id == playlist_id:
- selection = self.playlists_sidebar.get_generic_view().get_selection()
- if selection.iter_is_selected(playlist.iter):
+ for row in self.playlists_listbox.get_children():
+ if row.playlist.id != playlist_id:
+ continue
+
+ selection = self.playlists_sidebar.get_selected_row()
+ if not selection:
+ self._on_play_activate(None)
+ else:
+ selection.select_iter(playlist.iter)
+ handler = 0
+ def songs_loaded_callback(view):
+ self.disconnect(handler)
self._on_play_activate(None)
- else:
- selection.select_iter(playlist.iter)
- handler = 0
- def songs_loaded_callback(view):
- self.disconnect(handler)
- self._on_play_activate(None)
-
- handler = self.connect('playlist-songs-loaded', songs_loaded_callback)
- self.playlists_sidebar.emit('item-activated', '0', playlist.path)
+ handler = self.connect('playlist-songs-loaded', songs_loaded_callback)
+ self.playlists_sidebar.emit('item-activated', '0', playlist.path)
@log
@@ -341,14 +309,12 @@ class PlaylistView(BaseView):
self._on_delete_activate(None)
@log
- def _on_playlist_activated(self, widget, item_id, path):
- _iter = self.playlists_model.get_iter(path)
- playlist_name = self.playlists_model.get_value(_iter, 2)
- playlist = self.playlists_model.get_value(_iter, 5)
+ def _on_playlist_activated(self, widget, row):
+ playlist = row.playlist
self.current_playlist = playlist
- self.name_label.set_text(playlist_name)
- self.current_playlist_index = int(path.to_string())
+ self.name_label.set_text(playlist.title)
+ self.current_playlist_index = int(row.get_index())
# if the active queue has been set by this playlist,
# use it as model, otherwise build the liststore
@@ -409,26 +375,26 @@ class PlaylistView(BaseView):
@log
def stage_playlist_for_deletion(self):
self.model.clear()
+
+ row = self.playlists_sidebar.get_selected_row()
+ next_row = self.playlists_sidebar.get_row_at_index(
+ self.current_playlist_index + 1)
self.pl_todelete_index = self.current_playlist_index
- _iter = self.playlists_sidebar.get_generic_view().get_selection().get_selected()[1]
- self.pl_todelete = self.playlists_model.get_value(_iter, 5)
+ self.pl_todelete_row = row
+ self.pl_todelete = row.playlist
- if not _iter:
+ if not self.pl_todelete:
return
- iter_next = self.playlists_model.iter_next(_iter)\
- or self.playlists_model.iter_previous(_iter)
- self.playlists_model.remove(_iter)
+ row.hide()
- if iter_next:
- selection = self.playlists_sidebar.get_generic_view().get_selection()
- selection.select_iter(iter_next)
- self.playlists_sidebar.emit('item-activated', '0',
- self.playlists_model.get_path(iter_next))
+ if next_row:
+ self.playlists_sidebar.select_row(next_row)
+ next_row.emit('activate')
@log
def undo_playlist_deletion(self):
- self._add_playlist_to_model(self.pl_todelete, self.pl_todelete_index)
+ self.pl_todelete_row.show()
@log
def _on_delete_activate(self, menuitem, data=None):
@@ -437,34 +403,43 @@ class PlaylistView(BaseView):
@log
def _on_playlist_added(self, playlists, playlist):
- self._add_playlist_to_model(playlist)
- if self.playlists_model.iter_n_children(None) == 1:
- _iter = self.playlists_model.get_iter_first()
- selection = self.playlists_sidebar.get_generic_view().get_selection()
- selection.select_iter(_iter)
- self.playlists_sidebar.emit('item-activated', '0',
- self.playlists_model.get_path(_iter))
+ label = Gtk.Label(label=playlist.title,
+ ellipsize=Pango.EllipsizeMode.MIDDLE,
+ xalign=0.0,
+ margin=18)
+
+ row = Gtk.ListBoxRow()
+ row.add(label)
+ row.show_all()
+
+ row.playlist = playlist
+
+ self.playlists_sidebar.add(row)
+
+ if not self.playlists_sidebar.get_selected_row():
+ self.playlists_sidebar.select_row(row)
+ row.emit('activate')
@log
def _on_song_added_to_playlist(self, playlists, playlist, item):
if self.current_playlist and \
- playlist.get_id() == self.current_playlist.id:
+ playlist.id == self.current_playlist.id:
self._add_item_to_model(item, self.model)
@log
def _on_song_removed_from_playlist(self, playlists, playlist, item):
if self.current_playlist and \
- playlist.get_id() == self.current_playlist.id:
+ playlist.id == self.current_playlist.id:
model = self.model
else:
return
update_playing_track = False
for row in model:
- if row[5].id == item.get_id():
+ if row[5].get_id() == item.get_id():
# Is the removed track now being played?
if self.current_playlist and \
- playlist.get_id() == self.current_playlist.id:
+ playlist.id == self.current_playlist.id:
if self.player.currentTrack is not None and self.player.currentTrack.valid():
currentTrackpath = self.player.currentTrack.get_path().to_string()
if row.path is not None and row.path.to_string() == currentTrackpath:
@@ -484,7 +459,7 @@ class PlaylistView(BaseView):
self.iter_to_clean = None
self.update_model(self.player, model, nextIter)
- self.player.set_playlist('Playlist', playlist.get_id(), model, nextIter, 5, 11)
+ self.player.set_playlist('Playlist', playlist.id, model, nextIter, 5, 11)
self.player.set_playing(True)
# Update songs count
diff --git a/gnomemusic/window.py b/gnomemusic/window.py
index 26772fc..0126473 100644
--- a/gnomemusic/window.py
+++ b/gnomemusic/window.py
@@ -375,6 +375,7 @@ class Window(Gtk.ApplicationWindow):
self.pl_todelete_notification = None
if self.views[3].really_delete:
playlist.delete_playlist(self.views[3].pl_todelete)
+ self.views[3].pl_todelete_row.destroy()
else:
self.views[3].really_delete = True
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]