diff options
author | Marinus Schraal <mschraal@gnome.org> | 2019-07-15 23:41:26 +0200 |
---|---|---|
committer | Marinus Schraal <mschraal@gnome.org> | 2019-07-16 01:05:47 +0200 |
commit | e626a26ad0912e2b322a09638ef1fa95bceb117d (patch) | |
tree | b1c84321949d22480cdefcfc60758291d086f4b2 /gnomemusic/songliststore.py | |
parent | 2cebe931bfccb6ca07a20842ca6a78596aec3658 (diff) |
Complete rewrite of the core of Music
Use persistent list models throughout Music to hold the state of a
users music collected through Grilo and Tracker.
The extent of the rework did not allow for a gradual approach, so this
commit marks a hard break from the old approach. It is not yet on-par
with the old codebase.
This rework is partially based on the work of
Jean Felder <jfelder@src.gnome.org>.
Related: #299.
Diffstat (limited to 'gnomemusic/songliststore.py')
-rw-r--r-- | gnomemusic/songliststore.py | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/gnomemusic/songliststore.py b/gnomemusic/songliststore.py new file mode 100644 index 00000000..b923943e --- /dev/null +++ b/gnomemusic/songliststore.py @@ -0,0 +1,91 @@ +from gi.repository import Gfm, Gio, GObject, Gtk +from gi._gi import pygobject_new_full + +import gnomemusic.utils as utils + + +class SongListStore(Gtk.ListStore): + + def __init__(self, model): + super().__init__() + + self._model = Gfm.SortListModel.new(model) + self._model.set_sort_func( + self._wrap_list_store_sort_func(self._songs_sort)) + + self.set_column_types([ + GObject.TYPE_STRING, # play or invalid icon + GObject.TYPE_BOOLEAN, # selected + GObject.TYPE_STRING, # title + GObject.TYPE_STRING, # artist + GObject.TYPE_STRING, # album + GObject.TYPE_STRING, # duration + GObject.TYPE_INT, # favorite + GObject.TYPE_OBJECT, # coresong + GObject.TYPE_INT, # validation + GObject.TYPE_BOOLEAN, # iter_to_clean + ]) + + self._model.connect("items-changed", self._on_items_changed) + + def _wrap_list_store_sort_func(self, func): + + def wrap(a, b, *user_data): + a = pygobject_new_full(a, False) + b = pygobject_new_full(b, False) + return func(a, b, *user_data) + + return wrap + + def _songs_sort(self, song_a, song_b): + title_a = song_a.props.title.casefold() + title_b = song_b.props.title.casefold() + song_cmp = title_a == title_b + if not song_cmp: + return title_a > title_b + + artist_a = song_a.props.artist.casefold() + artist_b = song_b.props.artist.casefold() + artist_cmp = artist_a == artist_b + if not artist_cmp: + return artist_a > artist_b + + return song_a.props.album.casefold() > song_b.props.album.casefold() + + def _on_items_changed(self, model, position, removed, added): + if removed > 0: + for i in list(range(removed)): + path = Gtk.TreePath.new_from_string("{}".format(position)) + iter_ = self.get_iter(path) + self.remove(iter_) + + if added > 0: + for i in list(range(added)): + coresong = model[position] + time = utils.seconds_to_string(coresong.props.duration) + self.insert_with_valuesv( + position, [2, 3, 4, 5, 6, 7], + [coresong.props.title, coresong.props.artist, + coresong.props.album, time, + int(coresong.props.favorite), coresong]) + coresong.connect( + "notify::favorite", self._on_favorite_changed) + coresong.connect( + "notify::state", self._on_state_changed) + + def _on_favorite_changed(self, coresong, value): + for row in self: + if coresong == row[7]: + row[6] = coresong.props.favorite + break + + def _on_state_changed(self, coresong, value): + for row in self: + if coresong == row[7]: + row[8] = coresong.props.validation + break + + @GObject.Property( + type=Gio.ListStore, default=None, flags=GObject.ParamFlags.READABLE) + def model(self): + return self._model |