[gnome-music/wip/mschraal/playlists-fixes: 4/6] grltrackerplaylists: Bind playlists songs to main coresong



commit 29405eea01968c3bffebfb2aef36c09d8f5525d1
Author: Marinus Schraal <mschraal gnome org>
Date:   Fri Feb 21 12:18:09 2020 +0100

    grltrackerplaylists: Bind playlists songs to main coresong
    
    Playlist songs do not receive change notifications as they are created
    as separate CoreSong's from the main song model.
    
    To fix this, create a binding for all properties between the main
    CoreSong and the Playlist equivalent.

 gnomemusic/coremodel.py                         | 11 ++++-----
 gnomemusic/grilowrappers/grltrackerplaylists.py | 30 +++++++++++++++++++++----
 gnomemusic/grilowrappers/grltrackerwrapper.py   | 13 ++++++++---
 3 files changed, 42 insertions(+), 12 deletions(-)
---
diff --git a/gnomemusic/coremodel.py b/gnomemusic/coremodel.py
index be395d07..c4033421 100644
--- a/gnomemusic/coremodel.py
+++ b/gnomemusic/coremodel.py
@@ -240,8 +240,8 @@ class CoreModel(GObject.GObject):
                         coresong.props.media, self._coreselection,
                         self.props.grilo)
 
-                    song.bind_property(
-                        "state", coresong, "state",
+                    coresong.bind_property(
+                        "state", song, "state",
                         GObject.BindingFlags.SYNC_CREATE)
                     coresong.bind_property(
                         "validation", song, "validation",
@@ -284,9 +284,10 @@ class CoreModel(GObject.GObject):
                     self.props.grilo)
 
                 songs_added.append(song)
-                song.bind_property(
-                    "state", model_song, "state",
-                    GObject.BindingFlags.SYNC_CREATE)
+                model_song.bind_property(
+                    "state", song, "state",
+                    GObject.BindingFlags.BIDIRECTIONAL
+                    | GObject.BindingFlags.SYNC_CREATE)
                 model_song.bind_property(
                     "validation", song, "validation",
                     GObject.BindingFlags.BIDIRECTIONAL
diff --git a/gnomemusic/grilowrappers/grltrackerplaylists.py b/gnomemusic/grilowrappers/grltrackerplaylists.py
index f164c853..0573a6cd 100644
--- a/gnomemusic/grilowrappers/grltrackerplaylists.py
+++ b/gnomemusic/grilowrappers/grltrackerplaylists.py
@@ -55,7 +55,8 @@ class GrlTrackerPlaylists(GObject.GObject):
     ]
 
     def __init__(
-            self, source, coremodel, application, grilo, tracker_wrapper):
+            self, source, coremodel, application, grilo, tracker_wrapper,
+            songs_hash):
         """Initialize GrlTrackerPlaylists.
 
         :param Grl.TrackerSource source: The Tracker source to wrap
@@ -78,6 +79,7 @@ class GrlTrackerPlaylists(GObject.GObject):
         self._model_filter = self._coremodel.props.playlists_filter
         self._user_model_filter = self._coremodel.props.user_playlists_filter
         self._pls_todelete = []
+        self._songs_hash = songs_hash
         self._tracker = tracker_wrapper.props.tracker
         self._tracker_wrapper = tracker_wrapper
         self._window = application.props.window
@@ -95,7 +97,8 @@ class GrlTrackerPlaylists(GObject.GObject):
             "source": self._source,
             "application": self._application,
             "grilo": self._grilo,
-            "tracker_wrapper": self._tracker_wrapper
+            "tracker_wrapper": self._tracker_wrapper,
+            "songs_hash": self._songs_hash
         }
 
         smart_playlists = {
@@ -149,7 +152,7 @@ class GrlTrackerPlaylists(GObject.GObject):
         playlist = Playlist(
             media=media, source=self._source, coremodel=self._coremodel,
             application=self._application, grilo=self._grilo,
-            tracker_wrapper=self._tracker_wrapper)
+            tracker_wrapper=self._tracker_wrapper, songs_hash=self._songs_hash)
 
         self._model.append(playlist)
         callback = data
@@ -306,7 +309,7 @@ class Playlist(GObject.GObject):
     def __init__(
             self, media=None, query=None, tag_text=None, source=None,
             coremodel=None, application=None, grilo=None,
-            tracker_wrapper=None):
+            tracker_wrapper=None, songs_hash=None):
 
         super().__init__()
         """Initialize a playlist
@@ -338,6 +341,7 @@ class Playlist(GObject.GObject):
         self._coreselection = application.props.coreselection
         self._grilo = grilo
         self._log = application.props.log
+        self._songs_hash = songs_hash
         self._tracker = tracker_wrapper.props.tracker
         self._tracker_wrapper = tracker_wrapper
         self._window = application.props.window
@@ -412,6 +416,7 @@ class Playlist(GObject.GObject):
                 return
 
             coresong = CoreSong(media, self._coreselection, self._grilo)
+            self._bind_to_main_song(coresong)
             if coresong not in self._songs_todelete:
                 self._model.append(coresong)
 
@@ -422,6 +427,20 @@ class Playlist(GObject.GObject):
         self._source.query(
             query, self.METADATA_KEYS, options, _add_to_playlist_cb, None)
 
+    def _bind_to_main_song(self, coresong):
+        main_coresong = self._songs_hash[coresong.props.media.get_id()]
+
+        properties = [
+            "album", "album_disc_number", "artist", "duration", "media",
+            "grlid", "play_count", "state", "title", "track_number", "url",
+            "validation", "favorite", "selected"]
+
+        for prop in properties:
+            main_coresong.bind_property(
+                prop, coresong, prop,
+                GObject.BindingFlags.BIDIRECTIONAL
+                | GObject.BindingFlags.SYNC_CREATE)
+
     @GObject.Property(type=str, default=None)
     def title(self):
         """Playlist title
@@ -584,6 +603,7 @@ class Playlist(GObject.GObject):
                 return
 
             coresong = CoreSong(media, self._coreselection, self._grilo)
+            self._bind_to_main_song(coresong)
             if coresong not in self._songs_todelete:
                 self._model.append(coresong)
 
@@ -734,6 +754,7 @@ class SmartPlaylist(Playlist):
                     return
 
                 coresong = CoreSong(media, self._coreselection, self._grilo)
+                self._bind_to_main_song(coresong)
                 self._model.append(coresong)
 
             options = self._fast_options.copy()
@@ -785,6 +806,7 @@ class SmartPlaylist(Playlist):
         for idx, media in enumerate(new_model_medias):
             if media.get_id() not in current_models_ids:
                 coresong = CoreSong(media, self._coreselection, self._grilo)
+                self._bind_to_main_song(coresong)
                 self._model.append(coresong)
                 self.props.count += 1
 
diff --git a/gnomemusic/grilowrappers/grltrackerwrapper.py b/gnomemusic/grilowrappers/grltrackerwrapper.py
index 0e3b559a..22e7796f 100644
--- a/gnomemusic/grilowrappers/grltrackerwrapper.py
+++ b/gnomemusic/grilowrappers/grltrackerwrapper.py
@@ -74,6 +74,7 @@ class GrlTrackerWrapper(GObject.GObject):
         """
         super().__init__()
 
+        self._application = application
         self._coremodel = coremodel
         self._coreselection = application.props.coreselection
         self._grilo = grilo
@@ -90,6 +91,7 @@ class GrlTrackerWrapper(GObject.GObject):
         self._artist_search_model = self._coremodel.props.artists_search
         self._batch_changed_media_ids = {}
         self._content_changed_timeout = None
+        self._tracker_playlists = None
         self._tracker_wrapper = tracker_wrapper
         self._window = application.props.window
 
@@ -108,9 +110,6 @@ class GrlTrackerWrapper(GObject.GObject):
         self._initial_albums_fill(self.props.source)
         self._initial_artists_fill(self.props.source)
 
-        self._tracker_playlists = GrlTrackerPlaylists(
-            source, coremodel, application, grilo, tracker_wrapper)
-
     @GObject.Property(type=Grl.Source, default=None)
     def source(self):
         return self._source
@@ -383,6 +382,14 @@ class GrlTrackerWrapper(GObject.GObject):
             if not media:
                 self._model.splice(self._model.get_n_items(), 0, songs_added)
                 self._window.notifications_popup.pop_loading()
+
+                # Initialize the playlists subwrapper after the initial
+                # songs model fill, the playlists expect a filled songs
+                # hashtable.
+                self._tracker_playlists = GrlTrackerPlaylists(
+                    self.props.source, self._coremodel, self._application,
+                    self._grilo, self._tracker_wrapper, self._hash)
+
                 return
 
             song = CoreSong(media, self._coreselection, self._grilo)


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