[gnome-music/wip/jfelder/core-playlists-view] playlistsview: Restore playlist deletion



commit 9f34ae656ea8dea946e02b06a38fa83942edeee6
Author: Jean Felder <jfelder src gnome org>
Date:   Tue Jul 9 10:23:26 2019 +0200

    playlistsview: Restore playlist deletion

 gnomemusic/coremodel.py                         |  6 ++
 gnomemusic/grilowrappers/grltrackerplaylists.py | 86 +++++++++++++++++++++++--
 gnomemusic/views/playlistsview.py               | 31 +++++++--
 gnomemusic/widgets/notificationspopup.py        | 36 +++++++----
 4 files changed, 132 insertions(+), 27 deletions(-)
---
diff --git a/gnomemusic/coremodel.py b/gnomemusic/coremodel.py
index 48b01e97..e173439a 100644
--- a/gnomemusic/coremodel.py
+++ b/gnomemusic/coremodel.py
@@ -344,3 +344,9 @@ class CoreModel(GObject.GObject):
         flags=GObject.ParamFlags.READABLE)
     def playlists_sort(self):
         return self._playlists_model_sort
+
+    @GObject.Property(
+        type=Gfm.SortListModel, default=None,
+        flags=GObject.ParamFlags.READABLE)
+    def playlists_filter(self):
+        return self._playlists_model_filter
diff --git a/gnomemusic/grilowrappers/grltrackerplaylists.py b/gnomemusic/grilowrappers/grltrackerplaylists.py
index 62940d2e..96c12a23 100644
--- a/gnomemusic/grilowrappers/grltrackerplaylists.py
+++ b/gnomemusic/grilowrappers/grltrackerplaylists.py
@@ -41,6 +41,8 @@ class GrlTrackerPlaylists(GObject.GObject):
         self._grilo = grilo
         self._source = source
         self._model = self._coremodel.props.playlists
+        self._model_filter = self._coremodel.props.playlists_filter
+        self._pls_todelete = []
 
         self._fast_options = Grl.OperationOptions()
         self._fast_options.set_resolution_flags(
@@ -51,6 +53,7 @@ class GrlTrackerPlaylists(GObject.GObject):
     def _initial_playlists_fill(self):
         args = {
             "source": self._source,
+            "trackerplaylists": self,
             "coreselection": self._coreselection,
             "grilo": self._grilo
         }
@@ -100,11 +103,40 @@ class GrlTrackerPlaylists(GObject.GObject):
             return
 
         playlist = Playlist(
-            media=media, source=self._source, coremodel=self._coremodel,
+            media=media, source=self._source, trackerplaylists=self,
             coreselection=self._coreselection, grilo=self._grilo)
 
         self._model.append(playlist)
 
+    def _playlists_filter(self, playlist):
+        return playlist not in self._pls_todelete
+
+    def stage_playlist_deletion(self, playlist):
+        """Adds playlist to the list of playlists to delete
+
+        :param Playlist playlist: playlist
+        """
+        self._pls_todelete.append(playlist)
+        self._model_filter.set_filter_func(self._playlists_filter)
+
+    def finish_playlist_deletion(self, playlist, deleted=True):
+        """Removes playlist from the list of playlists to delete
+
+        :param Playlist playlist: playlist
+        :param bool deleted: indicates if the playlist has been deleted
+        """
+        self._pls_todelete.remove(playlist)
+        if deleted is False:
+            self._model_filter.set_filter_func(self._playlists_filter)
+            return
+
+        for idx, playlist_model in enumerate(self._model):
+            if playlist_model is playlist:
+                self._model.remove(idx)
+                break
+
+        self._model_filter.set_filter_func(self._playlists_filter)
+
 
 class Playlist(GObject.GObject):
     """ Base class of all playlists """
@@ -139,7 +171,7 @@ class Playlist(GObject.GObject):
 
     def __init__(
             self, media=None, query=None, tag_text=None, source=None,
-            coremodel=None, coreselection=None, grilo=None):
+            trackerplaylists=None, coreselection=None, grilo=None):
         super().__init__()
 
         if media:
@@ -150,8 +182,8 @@ class Playlist(GObject.GObject):
         self.props.query = query
         self.props.tag_text = tag_text
         self._model = None
+        self._trackerplaylists = trackerplaylists
         self._source = source
-        self._coremodel = coremodel
         self._coreselection = coreselection
         self._grilo = grilo
         self._tracker = TrackerWrapper().props.tracker
@@ -265,7 +297,7 @@ class Playlist(GObject.GObject):
         self._tracker.update_async(
             query, GLib.PRIORITY_LOW, None, update_cb, None)
 
-    def stage_deletion(self, coresong, index):
+    def stage_song_deletion(self, coresong, index):
         """Adds a song to the list of songs to delete
 
         :param CoreSong coresong: song to delete
@@ -275,8 +307,8 @@ class Playlist(GObject.GObject):
         self._model.remove(index)
         self.props.count -= 1
 
-    def undo_pending_deletion(self, coresong, position):
-        """Adds a song to the list of songs to delete
+    def undo_pending_song_deletion(self, coresong, position):
+        """Removes song from the list of songs to delete
 
         :param CoreSong coresong: song to delete
         :param int position: Song position in the playlist
@@ -285,7 +317,7 @@ class Playlist(GObject.GObject):
         self._model.insert(position, coresong)
         self.props.count += 1
 
-    def finish_deletion(self, coresong):
+    def finish_song_deletion(self, coresong):
         """Removes a song from the playlist
 
         :param CoreSong coresong: song to remove
@@ -448,6 +480,46 @@ class Playlist(GObject.GObject):
             self._tracker.update_blank_async(
                 query, GLib.PRIORITY_LOW, None, _requery_media, coresong)
 
+    def stage_deletion(self):
+        """Adds playlist to the list of playlists to delete"""
+        self._trackerplaylists.stage_playlist_deletion(self)
+
+    def undo_pending_deletion(self):
+        """Undo pending playlist deletion
+
+        :param int position: Song position in the playlist
+        """
+        self._trackerplaylists.finish_playlist_deletion(self, False)
+
+    def finish_deletion(self):
+        """Deletes the playlists."""
+        def _update_cb(conn, res, data):
+            # FIXME: Check for failure.
+            self._trackerplaylists.finish_playlist_deletion(self)
+            conn.update_finish(res)
+
+        query = """
+        DELETE {
+            ?playlist a rdfs:Resource .
+            ?entry a rdfs:Resource .
+
+        }
+        WHERE {
+            ?playlist a nmm:Playlist ;
+                      a nfo:MediaList .
+            OPTIONAL {
+                ?playlist nfo:hasMediaFileListEntry ?entry .
+            }
+            FILTER (
+            tracker:id(?playlist) = %(playlist_id)s
+            )
+        }
+        """.replace("\n", " ").strip() % {
+            'playlist_id': self.props.pl_id
+        }
+        self._tracker.update_async(
+            query, GLib.PRIORITY_LOW, None, _update_cb, None)
+
 
 class SmartPlaylist(Playlist):
     """Base class for smart playlists"""
diff --git a/gnomemusic/views/playlistsview.py b/gnomemusic/views/playlistsview.py
index 083a9302..b0305111 100644
--- a/gnomemusic/views/playlistsview.py
+++ b/gnomemusic/views/playlistsview.py
@@ -90,11 +90,12 @@ class PlaylistsView(BaseView):
             'activate', self._on_play_playlist)
         self._window.add_action(playlist_play_action)
 
-        # self._playlist_delete_action = Gio.SimpleAction.new(
-        #     'playlist_delete', None)
-        # self._playlist_delete_action.connect(
-        #     'activate', self._stage_playlist_for_deletion)
-        # self._window.add_action(self._playlist_delete_action)
+        self._playlist_delete_action = Gio.SimpleAction.new(
+            'playlist_delete', None)
+        self._playlist_delete_action.connect(
+            'activate', self._stage_playlist_for_deletion)
+        self._window.add_action(self._playlist_delete_action)
+
         self._playlist_rename_action = Gio.SimpleAction.new(
             'playlist_rename', None)
         self._playlist_rename_action.connect(
@@ -208,7 +209,7 @@ class PlaylistsView(BaseView):
 
         notification = PlaylistNotification(  # noqa: F841
             self._window.notifications_popup, PlaylistNotification.Type.SONG,
-            selected_playlist, coresong, position)
+            selected_playlist, position, coresong)
 
     @log
     def _on_playlist_activated(self, sidebar, row, data=None):
@@ -227,6 +228,7 @@ class PlaylistsView(BaseView):
         playlist.connect("notify::count", self._on_song_count_changed)
 
         self._playlist_rename_action.set_enabled(not playlist.props.is_smart)
+        self._playlist_delete_action.set_enabled(not playlist.props.is_smart)
 
     def _on_song_count_changed(self, playlist, value):
         self._update_songs_count(playlist.props.count)
@@ -271,6 +273,23 @@ class PlaylistsView(BaseView):
         pl_torename = selection.playlist
         pl_torename.rename(new_name)
 
+    @log
+    def _stage_playlist_for_deletion(self, menutime, data=None):
+        selected_row = self._sidebar.get_selected_row()
+        position = selected_row.get_index()
+        selected_playlist = selected_row.playlist
+
+        notification = PlaylistNotification(  # noqa: F841
+            self._window.notifications_popup,
+            PlaylistNotification.Type.PLAYLIST, selected_playlist, position)
+
+        # FIXME: Should Check that the playlist is not playing
+        # playlist_id = selection.playlist.props.pl_id
+        # if self.player.playing_playlist(
+        #         PlayerPlaylist.Type.PLAYLIST, playlist_id):
+        #     self.player.stop()
+        #     self._window.set_player_visible(False)
+
     @log
     def _populate(self, data=None):
         """Populate sidebar.
diff --git a/gnomemusic/widgets/notificationspopup.py b/gnomemusic/widgets/notificationspopup.py
index 061a811e..b20a468e 100644
--- a/gnomemusic/widgets/notificationspopup.py
+++ b/gnomemusic/widgets/notificationspopup.py
@@ -213,21 +213,23 @@ class PlaylistNotification(Gtk.Grid):
         return '<PlaylistNotification>'
 
     @log
-    def __init__(self, notifications_popup, type_, playlist, data, position):
+    def __init__(
+            self, notifications_popup, type_, playlist, position=None,
+            coresong=None):
         """Creates a playlist deletion notification popup (song or playlist)
 
         :param GtkRevealer notifications_popup: the popup object
         :param type_: NotificationType (song or playlist)
         :param Playlist playlist: playlist
-        :param object data: Data associated with the deletion
         :param int position: position of the object to delete
+        :param object coresong: CoreSong for song deletion
         """
         super().__init__(column_spacing=18)
         self._notifications_popup = notifications_popup
         self.type_ = type_
         self._playlist = playlist
-        self.data = data
         self._position = position
+        self._coresong = coresong
 
         message = self._create_notification_message()
         self._label = Gtk.Label(
@@ -239,25 +241,24 @@ class PlaylistNotification(Gtk.Grid):
         self.add(undo_button)
         self.show_all()
 
-        if self.type_ == PlaylistNotification.Type.SONG:
-            playlist.stage_deletion(self.data, position)
+        if self.type_ == PlaylistNotification.Type.PLAYLIST:
+            playlist.stage_deletion()
+        else:
+            playlist.stage_song_deletion(self._coresong, position)
 
         self._timeout_id = GLib.timeout_add_seconds(5, self._finish_deletion)
         self._notifications_popup.add_notification(self)
 
     def _create_notification_message(self):
         if self.type_ == PlaylistNotification.Type.PLAYLIST:
-            return None
-            # pl_todelete = data
-            # msg = _("Playlist {} removed".format(pl_todelete.props.title))
-
+            msg = _("Playlist {} removed".format(self._playlist.props.title))
         else:
             playlist_title = self._playlist.props.title
-            coresong = self.data
-            song_title = coresong.props.title
+            song_title = self._coresong.props.title
             msg = _("{} removed from {}".format(
                 song_title, playlist_title))
-            return msg
+
+        return msg
 
     @log
     def _undo_deletion(self, widget_):
@@ -267,8 +268,15 @@ class PlaylistNotification(Gtk.Grid):
             self._timeout_id = 0
 
         self._notifications_popup.remove_notification(self)
-        self._playlist.undo_pending_deletion(self.data, self._position)
+        if self.type_ == PlaylistNotification.Type.PLAYLIST:
+            self._playlist.undo_pending_deletion()
+        else:
+            self._playlist.undo_pending_song_deletion(
+                self._coresong, self._position)
 
     def _finish_deletion(self):
         self._notifications_popup.remove_notification(self)
-        self._playlist.finish_deletion(self.data)
+        if self.type_ == PlaylistNotification.Type.PLAYLIST:
+            self._playlist.finish_deletion()
+        else:
+            self._playlist.finish_song_deletion(self._coresong)


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