summaryrefslogtreecommitdiff
path: root/gnomemusic/songliststore.py
diff options
context:
space:
mode:
authorMarinus Schraal <mschraal@gnome.org>2019-07-15 23:41:26 +0200
committerMarinus Schraal <mschraal@gnome.org>2019-07-16 01:05:47 +0200
commite626a26ad0912e2b322a09638ef1fa95bceb117d (patch)
treeb1c84321949d22480cdefcfc60758291d086f4b2 /gnomemusic/songliststore.py
parent2cebe931bfccb6ca07a20842ca6a78596aec3658 (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.py91
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