[gnome-music/wip/jfelder/core-playlists-view: 6/6] artistsview: Add support for live updates



commit 68662c5764824d4edaa75b2777b68cb537e10d30
Author: Jean Felder <jfelder src gnome org>
Date:   Thu Jul 11 11:45:44 2019 +0200

    artistsview: Add support for live updates

 gnomemusic/grilowrappers/grltrackersource.py | 50 +++++++++++++++++++++++
 gnomemusic/views/artistsview.py              | 60 +++++++++++++++++++++++-----
 2 files changed, 99 insertions(+), 11 deletions(-)
---
diff --git a/gnomemusic/grilowrappers/grltrackersource.py b/gnomemusic/grilowrappers/grltrackersource.py
index 5585d35f..bcb0a4f4 100644
--- a/gnomemusic/grilowrappers/grltrackersource.py
+++ b/gnomemusic/grilowrappers/grltrackersource.py
@@ -42,6 +42,7 @@ class GrlTrackerSource(GObject.GObject):
         self._albums_model = self._coremodel.props.albums
         self._album_ids = {}
         self._artists_model = self._coremodel.props.artists
+        self._artist_ids = {}
         self._hash = {}
         self._song_search_model = self._coremodel.props.songs_search
         self._album_search_model = self._coremodel.props.albums_search
@@ -71,6 +72,7 @@ class GrlTrackerSource(GObject.GObject):
                 print("ADDED", media.get_id())
                 self._add_media(media)
                 self._check_album_change(media)
+                self._check_artist_change(media)
             elif change_type == Grl.SourceChangeType.CHANGED:
                 print("CHANGED", media.get_id())
                 self._requery_media(media.get_id(), True)
@@ -78,6 +80,7 @@ class GrlTrackerSource(GObject.GObject):
                 print("REMOVED", media.get_id())
                 self._remove_media(media)
                 self._check_album_change(media)
+                self._check_artist_change(media)
 
     def _check_album_change(self, media):
         album_ids = {}
@@ -131,6 +134,52 @@ class GrlTrackerSource(GObject.GObject):
         self._source.query(
             query, self.METADATA_KEYS, options, check_album_cb)
 
+    def _check_artist_change(self, media):
+        artist_ids = {}
+
+        query = """
+        SELECT
+            rdf:type(?artist_class)
+            tracker:id(?artist_class) AS ?id
+            nmm:artistName(?artist_class) AS ?artist
+        {
+            ?artist_class a nmm:Artist .
+            ?song a nmm:MusicPiece;
+                    nmm:musicAlbum ?album;
+                    nmm:performer ?artist_class .
+        } GROUP BY ?artist_class
+        """.replace('\n', ' ').strip()
+
+        def check_artist_cb(source, op_id, media, user_data, error):
+            if error:
+                print("ERROR", error)
+                return
+
+            if not media:
+                changed_ids = set(
+                    artist_ids.keys()) ^ set(self._artist_ids.keys())
+                print("ARTISTS CHANGED", changed_ids)
+
+                for key in changed_ids:
+                    if key in artist_ids:
+                        self._artists_model.append(artist_ids[key])
+                    elif key in self._artist_ids:
+                        for idx, coreartist in enumerate(self._artists_model):
+                            if coreartist.media.get_id() == key:
+                                self._artists_model.remove(idx)
+                                break
+
+                self._artist_ids = artist_ids
+                return
+
+            artist = CoreArtist(media, self._coremodel)
+            artist_ids[media.get_id()] = artist
+
+        options = self._fast_options.copy()
+
+        self._source.query(
+            query, self.METADATA_KEYS, options, check_artist_cb)
+
     def _remove_media(self, media):
         try:
             coresong = self._hash.pop(media.get_id())
@@ -331,6 +380,7 @@ class GrlTrackerSource(GObject.GObject):
 
         artist = CoreArtist(media, self._coremodel)
         self._artists_model.append(artist)
+        self._artist_ids[media.get_id()] = artist
 
     def get_artist_albums(self, media, model):
         artist_id = media.get_id()
diff --git a/gnomemusic/views/artistsview.py b/gnomemusic/views/artistsview.py
index 85a56c35..a9f72b38 100644
--- a/gnomemusic/views/artistsview.py
+++ b/gnomemusic/views/artistsview.py
@@ -64,6 +64,9 @@ class ArtistsView(BaseView):
         self._window = window
         self._coremodel = window._app.props.coremodel
         self._model = self._coremodel.props.artists_sort
+
+        self._model.connect_after(
+            "items-changed", self._on_model_items_changed)
         self._sidebar.bind_model(self._model, self._create_widget)
         self._loaded_id = self._coremodel.connect(
             "artists-loaded", self._on_artists_loaded)
@@ -79,6 +82,7 @@ class ArtistsView(BaseView):
         self._ctrl.connect("released", self._on_sidebar_clicked)
 
         self._loaded_artists = []
+        self._loading_id = 0
 
         self.show_all()
 
@@ -90,6 +94,31 @@ class ArtistsView(BaseView):
 
         return row
 
+    def _on_model_items_changed(self, model, position, removed, added):
+        if removed == 0:
+            return
+
+        removed_artist = None
+        artists = [coreartist.props.artist for coreartist in model]
+        for artist in self._loaded_artists:
+            if artist not in artists:
+                removed_artist = artist
+                break
+
+        if removed_artist is None:
+            return
+
+        self._loaded_artists.remove(removed_artist)
+        if self._view.get_visible_child_name() == removed_artist:
+            row_next = (self._sidebar.get_row_at_index(position)
+                        or self._sidebar.get_row_at_index(position - 1))
+            if row_next:
+                self._sidebar.select_row(row_next)
+                row_next.emit("activate")
+
+        removed_frame = self._view.get_child_by_name(removed_artist)
+        self._view.remove(removed_frame)
+
     def _on_artists_loaded(self, klass):
         self._coremodel.disconnect(self._loaded_id)
         first_row = self._sidebar.get_row_at_index(0)
@@ -129,31 +158,40 @@ class ArtistsView(BaseView):
 
         # Prepare a new artist_albums_widget here
         coreartist = artist_tile.props.coreartist
-        if coreartist in self._loaded_artists:
+        if coreartist.props.artist in self._loaded_artists:
             scroll_vadjustment = self._view_container.props.vadjustment
             scroll_vadjustment.props.value = 0.
             self._view.set_visible_child_name(coreartist.props.artist)
             return
 
-        artist_albums = ArtistAlbumsWidget(
+        if self._loading_id > 0:
+            self._artist_albums.disconnect(self._loading_id)
+            self._loading_id = 0
+
+        self._artist_albums = ArtistAlbumsWidget(
             coreartist, self.player, self._window, False)
-        artist_albums.connect(
-            "ready", self._on_artist_albums_ready, coreartist)
+        self._loading_id = self._artist_albums.connect(
+            "ready", self._on_artist_albums_ready, coreartist.props.artist)
         self._view.set_visible_child_name("empty-frame")
         self._window.notifications_popup.push_loading()
         return
 
-    def _on_artist_albums_ready(self, klass, coreartist):
-        new_artist_albums_widget = Gtk.Frame(
+    def _on_artist_albums_ready(self, widget, artist):
+        artist_albums_frame = Gtk.Frame(
             shadow_type=Gtk.ShadowType.NONE, hexpand=True)
-        new_artist_albums_widget.add(klass)
-        new_artist_albums_widget.show()
-        self._view.add_named(new_artist_albums_widget, coreartist.props.artist)
+        artist_albums_frame.add(self._artist_albums)
+        artist_albums_frame.show()
+
+        self._view.add_named(artist_albums_frame, artist)
         scroll_vadjustment = self._view_container.props.vadjustment
         scroll_vadjustment.props.value = 0.
-        self._view.set_visible_child(new_artist_albums_widget)
+        self._view.set_visible_child(artist_albums_frame)
         self._window.notifications_popup.pop_loading()
-        self._loaded_artists.append(coreartist)
+        self._loaded_artists.append(artist)
+
+        self._artist_albums.disconnect(self._loading_id)
+        self._loading_id = 0
+        self._artist_albums = None
         return
 
     @log


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