[gnome-music/wip/jfelder/coredisc-updates: 8/12] corealbum: Add a flattenlistmodel




commit 864ae6923ebd2caf8a2f8fdc32fe236e14e5e166
Author: Jean Felder <jfelder src gnome org>
Date:   Fri Nov 13 00:35:55 2020 +0100

    corealbum: Add a flattenlistmodel
    
    CoreAlbum contains a model which is a list of all the discs of the
    album. Then, each CoreDisc has a model wich contains all the songs of
    the disc. When playing an album a flattenlistmodel is created on the
    fly to have a list of all the songs of the album. This works reliably
    but it's impossible to update the player playlist when a CoreDisc is
    added because the playlist listens to the album model change instead
    of the flatten model changes.
    
    This issue is fixed by adding a new flatten model to CoreAlbum which
    contains all the songs of the album. This new model can directly be
    used to create a player playlist.
    
    CoreAlbum now contains 2 models:
    - model contains all the songs of the album
    - disc_model contains all the discs of the album

 gnomemusic/corealbum.py                 | 64 +++++++++++++++++++++++----------
 gnomemusic/coremodel.py                 | 11 ++----
 gnomemusic/widgets/albumwidget.py       |  4 +--
 gnomemusic/widgets/artistalbumwidget.py |  6 ++--
 4 files changed, 53 insertions(+), 32 deletions(-)
---
diff --git a/gnomemusic/corealbum.py b/gnomemusic/corealbum.py
index 86d49fd27..f73e64d95 100644
--- a/gnomemusic/corealbum.py
+++ b/gnomemusic/corealbum.py
@@ -22,6 +22,10 @@
 # code, but you are not obligated to do so.  If you do not wish to do so,
 # delete this exception statement from your version.
 
+from __future__ import annotations
+
+import typing
+
 import gi
 gi.require_versions({"Gfm": "0.1", "Grl": "0.3"})
 from gi.repository import Gfm, Gio, Grl, GObject
@@ -29,6 +33,9 @@ from gi.repository import Gfm, Gio, Grl, GObject
 import gnomemusic.utils as utils
 
 from gnomemusic.albumart import AlbumArt
+from gnomemusic.coresong import CoreSong
+if typing.TYPE_CHECKING:
+    from gnomemusic.coredisc import CoreDisc
 
 
 class CoreAlbum(GObject.GObject):
@@ -57,6 +64,14 @@ class CoreAlbum(GObject.GObject):
         self._selected = False
         self._thumbnail = None
 
+        self._disc_model_proxy = Gio.ListStore.new(Gio.ListModel)
+        self._disc_model = Gio.ListStore()
+        self._disc_model_sort = Gfm.SortListModel.new(
+            self._disc_model,
+            utils.wrap_list_store_sort_func(self._disc_order_sort))
+        self._disc_model_sort.connect(
+            "items-changed", self._on_core_items_changed)
+
         self.update(media)
 
     def update(self, media):
@@ -71,19 +86,14 @@ class CoreAlbum(GObject.GObject):
         self.props.url = media.get_url()
         self.props.year = utils.get_media_year(media)
 
-    def _get_album_model(self):
-        disc_model = Gio.ListStore()
-        disc_model_sort = Gfm.SortListModel.new(disc_model)
-
-        def _disc_order_sort(disc_a, disc_b):
-            return disc_a.props.disc_nr - disc_b.props.disc_nr
+    @staticmethod
+    def _disc_order_sort(disc_a: CoreDisc, disc_b: CoreDisc) -> int:
+        return disc_a.props.disc_nr - disc_b.props.disc_nr
 
-        disc_model_sort.set_sort_func(
-            utils.wrap_list_store_sort_func(_disc_order_sort))
-
-        self._coregrilo.get_album_discs(self.props.media, disc_model)
-
-        return disc_model_sort
+    def _load_album_model(self):
+        self._coregrilo.get_album_discs(self.props.media, self._disc_model)
+        self._model = Gfm.FlattenListModel.new(
+            CoreSong, self._disc_model_proxy)
 
     @GObject.Property(
         type=bool, default=False, flags=GObject.ParamFlags.READABLE)
@@ -96,16 +106,33 @@ class CoreAlbum(GObject.GObject):
         return self._model is not None
 
     @GObject.Property(
-        type=Gio.ListModel, default=None, flags=GObject.ParamFlags.READABLE)
+        type=Gfm.FlattenListModel, default=None,
+        flags=GObject.ParamFlags.READABLE)
     def model(self):
+        """Model which contains all the songs of an album.
+
+        :returns: songs model
+        :rtype: Gfm.FlattenListModel
+        """
         if not self.props.model_loaded:
-            self._model = self._get_album_model()
-            self._model.connect("items-changed", self._on_list_items_changed)
-            self._model.items_changed(0, 0, self._model.get_n_items())
+            self._load_album_model()
 
         return self._model
 
-    def _on_list_items_changed(self, model, position, removed, added):
+    @GObject.Property(
+        type=Gfm.SortListModel, flags=GObject.ParamFlags.READABLE)
+    def disc_model(self) -> Gfm.SortListModel:
+        """Model which contains all the discs of an album.
+
+        :returns: discs model
+        :rtype: Gfm.SortListModel
+        """
+        if not self.props.model_loaded:
+            self._load_album_model()
+
+        return self._disc_model_sort
+
+    def _on_core_items_changed(self, model, position, removed, added):
         with self.freeze_notify():
             for coredisc in model:
                 coredisc.props.selected = self.props.selected
@@ -113,13 +140,14 @@ class CoreAlbum(GObject.GObject):
             if added > 0:
                 for i in range(added):
                     coredisc = model[position + i]
+                    self._disc_model_proxy.append(coredisc.props.model)
                     coredisc.connect(
                         "notify::duration", self._on_duration_changed)
 
     def _on_duration_changed(self, coredisc, duration):
         duration = 0
 
-        for coredisc in self.props.model:
+        for coredisc in self._disc_model:
             duration += coredisc.props.duration
 
         self.props.duration = duration
diff --git a/gnomemusic/coremodel.py b/gnomemusic/coremodel.py
index 2a3f7967a..a75542de6 100644
--- a/gnomemusic/coremodel.py
+++ b/gnomemusic/coremodel.py
@@ -238,16 +238,9 @@ class CoreModel(GObject.GObject):
         songs_added = []
 
         if playlist_type == PlayerPlaylist.Type.ALBUM:
-            proxy_model = Gio.ListStore.new(Gio.ListModel)
-
-            for disc in model:
-                proxy_model.append(disc.props.model)
-
-            self._flatten_model = Gfm.FlattenListModel.new(
-                CoreSong, proxy_model)
-            self._current_playlist_model = self._flatten_model
+            self._current_playlist_model = model
 
-            for model_song in self._flatten_model:
+            for model_song in model:
                 song = CoreSong(self._application, model_song.props.media)
                 _bind_song_properties(model_song, song)
                 songs_added.append(song)
diff --git a/gnomemusic/widgets/albumwidget.py b/gnomemusic/widgets/albumwidget.py
index bdb11d754..3a8b1206c 100644
--- a/gnomemusic/widgets/albumwidget.py
+++ b/gnomemusic/widgets/albumwidget.py
@@ -84,7 +84,7 @@ class AlbumWidget(Gtk.EventBox):
         """
         if self._corealbum:
             self._corealbum.disconnect(self._duration_signal_id)
-            self._corealbum.props.model.disconnect(self._model_signal_id)
+            self._corealbum.props.disc_model.disconnect(self._model_signal_id)
 
         self._corealbum = corealbum
 
@@ -103,7 +103,7 @@ class AlbumWidget(Gtk.EventBox):
 
         self._set_composer_label(corealbum)
 
-        self._album_model = self._corealbum.props.model
+        self._album_model = self._corealbum.props.disc_model
         self._model_signal_id = self._album_model.connect_after(
             "items-changed", self._on_model_items_changed)
         self._disc_list_box.bind_model(self._album_model, self._create_widget)
diff --git a/gnomemusic/widgets/artistalbumwidget.py b/gnomemusic/widgets/artistalbumwidget.py
index 5993e7cb3..af21abed3 100644
--- a/gnomemusic/widgets/artistalbumwidget.py
+++ b/gnomemusic/widgets/artistalbumwidget.py
@@ -85,12 +85,12 @@ class ArtistAlbumWidget(Gtk.Box):
         if self._cover_size_group:
             self._cover_size_group.add_widget(self._art_stack)
 
-        corealbum.props.model.connect_after(
+        corealbum.props.disc_model.connect_after(
             "items-changed", self._on_model_items_changed)
         self._disc_list_box.bind_model(
-            corealbum.props.model, self._create_widget)
+            corealbum.props.disc_model, self._create_widget)
 
-        corealbum.props.model.items_changed(0, 0, 0)
+        corealbum.props.disc_model.items_changed(0, 0, 0)
 
     def _create_widget(self, disc):
         disc_box = DiscBox(disc)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]