[gnome-music/wip/jfelder/songwidget-contextmenu: 7/8] playlistswidget: Move popup logic to PlaylistContextMenu




commit 70686793c495784e3a824f1d0cc80b68265e2c40
Author: Jean Felder <jfelder src gnome org>
Date:   Sun May 9 18:35:28 2021 +0200

    playlistswidget: Move popup logic to PlaylistContextMenu
    
    This will make it easier to associate the context menu with other
    views.

 gnomemusic/widgets/playlistcontextmenu.py | 78 +++++++++++++++++++++++++++----
 gnomemusic/widgets/playlistswidget.py     | 65 +++-----------------------
 2 files changed, 76 insertions(+), 67 deletions(-)
---
diff --git a/gnomemusic/widgets/playlistcontextmenu.py b/gnomemusic/widgets/playlistcontextmenu.py
index 5fa1e9492..622474ec2 100644
--- a/gnomemusic/widgets/playlistcontextmenu.py
+++ b/gnomemusic/widgets/playlistcontextmenu.py
@@ -23,10 +23,15 @@
 # delete this exception statement from your version.
 
 from __future__ import annotations
+from typing import Optional
 import typing
 
-from gi.repository import Gio, Gtk
+from gi.repository import Gio, GObject, Gtk
 
+from gnomemusic.coresong import CoreSong
+from gnomemusic.grilowrappers.grltrackerplaylists import Playlist
+from gnomemusic.widgets.notificationspopup import PlaylistNotification
+from gnomemusic.widgets.playlistdialog import PlaylistDialog
 if typing.TYPE_CHECKING:
     from gnomemusic.application import Application
 
@@ -36,6 +41,9 @@ class PlaylistContextMenu(Gtk.Popover):
 
     __gtype_name__ = 'PlaylistContextMenu'
 
+    coresong = GObject.Property(type=CoreSong, default=None)
+    song_position = GObject.Property(type=int, default=0)
+
     _song_menu = Gtk.Template.Child()
 
     def __init__(self, application: Application, view: Gtk.ListBox) -> None:
@@ -46,16 +54,70 @@ class PlaylistContextMenu(Gtk.Popover):
         """
         super().__init__()
 
-        window = application.props.window
+        self._application = application
+        self._coremodel = application.props.coremodel
+        self._player = application.props.player
+        self._window = application.props.window
 
         self.props.relative_to = view
         self.bind_model(self._song_menu, None)
 
-        add_song = Gio.SimpleAction.new("add_song_to_playlist", None)
-        window.add_action(add_song)
+        add_song_action = Gio.SimpleAction.new("add_song_to_playlist", None)
+        add_song_action.connect("activate", self._add_song_to_playlist)
+        self._window.add_action(add_song_action)
+
+        play_song_action = Gio.SimpleAction.new("play_song", None)
+        play_song_action.connect("activate", self._play_song)
+        self._window.add_action(play_song_action)
+
+        self._remove_song_action = Gio.SimpleAction.new("remove_song", None)
+        self._window.add_action(self._remove_song_action)
+        self._remove_song_action.connect(
+            "activate", self._stage_song_for_deletion)
+
+    @GObject.Property(type=Playlist, default=None)
+    def playlist(self) -> Optional[Playlist]:
+        """Get the playlist associated with the menu
+
+        :returns: playlist or None if no playlist is set
+        :rtype: Playlist
+        """
+        return self._playlist
+
+    @playlist.setter  # type: ignore
+    def playlist(self, active_playlist: Optional[Playlist]) -> None:
+        """Set the playlist associated with the menu
+
+        :param Playlist active_playlist: playlist
+        """
+        self._playlist = active_playlist
+
+        self._remove_song_action.set_enabled(
+            self._playlist is not None
+            and not self._playlist.props.is_smart)
+
+    def _play_song(self, menuitem, data=None):
+        signal_id = 0
+
+        def _on_playlist_loaded(klass, playlist_type):
+            self._player.play(self.props.coresong)
+            self._coremodel.disconnect(signal_id)
+
+        signal_id = self._coremodel.connect(
+            "playlist-loaded", _on_playlist_loaded)
+        self._coremodel.props.active_core_object = self.props.playlist
+
+    def _add_song_to_playlist(self, menuitem, data=None):
+        playlist_dialog = PlaylistDialog(self._application)
+        playlist_dialog.props.transient_for = self._window
+        if playlist_dialog.run() == Gtk.ResponseType.ACCEPT:
+            playlist = playlist_dialog.props.selected_playlist
+            playlist.add_songs([self.props.coresong])
 
-        play_song = Gio.SimpleAction.new("play_song", None)
-        window.add_action(play_song)
+        playlist_dialog.destroy()
 
-        remove_song = Gio.SimpleAction.new("remove_song", None)
-        window.add_action(remove_song)
+    def _stage_song_for_deletion(self, menuitem, data=None):
+        notification = PlaylistNotification(  # noqa: F841
+            self._window.notifications_popup, self._application,
+            PlaylistNotification.Type.SONG, self.props.playlist,
+            self.props.song_position, self.props.coresong)
diff --git a/gnomemusic/widgets/playlistswidget.py b/gnomemusic/widgets/playlistswidget.py
index 30bceafc9..862721d8e 100644
--- a/gnomemusic/widgets/playlistswidget.py
+++ b/gnomemusic/widgets/playlistswidget.py
@@ -27,10 +27,8 @@ import typing
 
 from gi.repository import Gdk, GObject, Gtk
 
-from gnomemusic.widgets.notificationspopup import PlaylistNotification
 from gnomemusic.widgets.playlistcontextmenu import PlaylistContextMenu
 from gnomemusic.widgets.playlistcontrols import PlaylistControls  # noqa: F401
-from gnomemusic.widgets.playlistdialog import PlaylistDialog
 from gnomemusic.widgets.songwidget import SongWidget
 if typing.TYPE_CHECKING:
     from gnomemusic.application import Application
@@ -60,7 +58,6 @@ class PlaylistsWidget(Gtk.Box):
         super().__init__()
 
         self._application = application
-        self._window = application.props.window
         self._coremodel = application.props.coremodel
         self._player = application.props.player
         self._playlists_view = playlists_view
@@ -72,19 +69,6 @@ class PlaylistsWidget(Gtk.Box):
 
         self._song_popover = PlaylistContextMenu(application, self._songs_list)
 
-        play_song = self._window.lookup_action("play_song")
-        play_song.connect("activate", self._play_song)
-
-        add_song = self._window.lookup_action("add_song_to_playlist")
-        add_song.connect("activate", self._add_song_to_playlist)
-
-        self._remove_song_action = self._window.lookup_action("remove_song")
-        self._remove_song_action.connect(
-            "activate", self._stage_song_for_deletion)
-
-        playlist_play_action = self._window.lookup_action("playlist_play")
-        playlist_play_action.connect("activate", self._on_play_playlist)
-
         self._coremodel.connect(
             "smart-playlist-change", self._on_smart_playlist_change)
 
@@ -99,8 +83,6 @@ class PlaylistsWidget(Gtk.Box):
 
         self._pl_ctrls.props.playlist = playlist
 
-        self._remove_song_action.set_enabled(not playlist.props.is_smart)
-
     def _create_song_widget(
             self, coresong: CoreSong, playlist: Playlist) -> Gtk.ListBoxRow:
         can_dnd = not playlist.props.is_smart
@@ -116,12 +98,8 @@ class PlaylistsWidget(Gtk.Box):
     @Gtk.Template.Callback()
     def _on_song_activated(
             self, list_box: Gtk.ListBox, song_widget: SongWidget) -> bool:
+        signal_id = 0
         coresong = song_widget.props.coresong
-        self._play(coresong)
-        return True
-
-    def _play(self, coresong=None):
-        signal_id = None
 
         def _on_playlist_loaded(klass, playlist_type):
             self._player.play(coresong)
@@ -131,6 +109,7 @@ class PlaylistsWidget(Gtk.Box):
         signal_id = self._coremodel.connect(
             "playlist-loaded", _on_playlist_loaded)
         self._coremodel.props.active_core_object = current_playlist
+        return True
 
     def _on_song_widget_moved(self, target, source_position):
         target_position = target.get_index()
@@ -146,7 +125,6 @@ class PlaylistsWidget(Gtk.Box):
     @Gtk.Template.Callback()
     def _songs_list_right_click(self, gesture, n_press, x, y):
         requested_row = self._songs_list.get_row_at_y(y)
-        self._songs_list.select_row(requested_row)
 
         _, y0 = requested_row.translate_coordinates(self._songs_list, 0, 0)
         row_height = requested_row.get_allocated_height()
@@ -154,44 +132,13 @@ class PlaylistsWidget(Gtk.Box):
         rect.x = x
         rect.y = y0 + 0.5 * row_height
 
-        self._song_popover.props.relative_to = self._songs_list
+        current_playlist = self._playlists_view.props.current_playlist
+        self._song_popover.props.playlist = current_playlist
+        self._song_popover.props.coresong = requested_row.props.coresong
+        self._song_popover.props.song_position = requested_row.get_index()
         self._song_popover.props.pointing_to = rect
         self._song_popover.popup()
 
-    def _play_song(self, menuitem, data=None):
-        selected_row = self._songs_list.get_selected_row()
-        coresong = selected_row.props.coresong
-        self._songs_list.unselect_all()
-        self._play(coresong)
-
-    def _add_song_to_playlist(self, menuitem, data=None):
-        selected_row = self._songs_list.get_selected_row()
-        coresong = selected_row.props.coresong
-
-        playlist_dialog = PlaylistDialog(self._application)
-        playlist_dialog.props.transient_for = self._window
-        if playlist_dialog.run() == Gtk.ResponseType.ACCEPT:
-            playlist = playlist_dialog.props.selected_playlist
-            playlist.add_songs([coresong])
-
-        self._songs_list.unselect_all()
-        playlist_dialog.destroy()
-
-    def _stage_song_for_deletion(self, menuitem, data=None):
-        selected_row = self._songs_list.get_selected_row()
-        position = selected_row.get_index()
-        coresong = selected_row.props.coresong
-
-        current_playlist = self._playlists_view.props.current_playlist
-
-        notification = PlaylistNotification(  # noqa: F841
-            self._window.notifications_popup, self._application,
-            PlaylistNotification.Type.SONG, current_playlist, position,
-            coresong)
-
-    def _on_play_playlist(self, menuitem, data=None):
-        self._play()
-
     @GObject.Property(
         type=bool, default=False, flags=GObject.ParamFlags.READABLE)
     def rename_active(self):


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