[gnome-music/wip/jfelder/core-playlists-view] playlistsview: Restore playlist deletion
- From: Jean Felder <jfelder src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-music/wip/jfelder/core-playlists-view] playlistsview: Restore playlist deletion
- Date: Tue, 9 Jul 2019 09:49:25 +0000 (UTC)
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]