[gnome-music/wip/jfelder/playlistsview-dnd] playlistsview: Restore drag and drop operation



commit c9931735873e17d3ee6a9b8d80829bdcc32a9dd6
Author: Jean Felder <jfelder src gnome org>
Date:   Tue Jul 9 21:16:41 2019 +0200

    playlistsview: Restore drag and drop operation

 data/ui/SongWidget.ui                   | 18 ++++++++++
 gnomemusic/views/playlistsview.py       |  9 ++++-
 gnomemusic/widgets/disclistboxwidget.py |  2 --
 gnomemusic/widgets/songwidget.py        | 60 ++++++++++++++++++++++++++++++++-
 4 files changed, 85 insertions(+), 4 deletions(-)
---
diff --git a/data/ui/SongWidget.ui b/data/ui/SongWidget.ui
index 28f4675a..a3e157ad 100644
--- a/data/ui/SongWidget.ui
+++ b/data/ui/SongWidget.ui
@@ -6,6 +6,7 @@
     <property name="visible">True</property>
     <property name="can_focus">False</property>
     <signal name="notify::selected" handler="_on_selection_changed"/>
+    <signal name="drag_data_received" handler="_on_drag_data_received"/>
     <child>
       <object class="GtkBox" id="box1">
         <property name="visible">True</property>
@@ -130,6 +131,23 @@
             <property name="position">2</property>
           </packing>
         </child>
+        <child>
+          <object class="GtkEventBox" id="_dnd_eventbox">
+            <property name="visible">False</property>
+            <signal name="drag-begin" handler="_on_drag_begin"/>
+            <signal name="drag-end" handler="_on_drag_end"/>
+            <signal name="drag_data_get" handler="_on_drag_data_get"/>
+            <child>
+              <object class="GtkImage">
+                <property name="visible">True</property>
+                <property name="icon-name">open-menu-symbolic</property>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="position">3</property>
+          </packing>
+        </child>
         <child>
           <placeholder/>
         </child>
diff --git a/gnomemusic/views/playlistsview.py b/gnomemusic/views/playlistsview.py
index 0d423188..bdbeacd5 100644
--- a/gnomemusic/views/playlistsview.py
+++ b/gnomemusic/views/playlistsview.py
@@ -244,9 +244,10 @@ class PlaylistsView(BaseView):
         self._update_songs_count(playlist.props.count)
 
     def _create_song_widget(self, coresong):
-        song_widget = SongWidget(coresong)
+        song_widget = SongWidget(coresong, True)
 
         song_widget.connect('button-release-event', self._song_activated)
+        song_widget.connect("widget_moved", self._on_song_widget_moved)
 
         return song_widget
 
@@ -299,6 +300,12 @@ class PlaylistsView(BaseView):
         #     self.player.stop()
         #     self._window.set_player_visible(False)
 
+    def _on_song_widget_moved(self, target, source_position):
+        source_row = self._view.get_row_at_index(source_position)
+        target_position = target.get_parent().get_index()
+        self._view.remove(source_row)
+        self._view.insert(source_row, target_position)
+
     @log
     def _populate(self, data=None):
         """Populate sidebar.
diff --git a/gnomemusic/widgets/disclistboxwidget.py b/gnomemusic/widgets/disclistboxwidget.py
index 02c3c1a6..7de001d4 100644
--- a/gnomemusic/widgets/disclistboxwidget.py
+++ b/gnomemusic/widgets/disclistboxwidget.py
@@ -139,8 +139,6 @@ class DiscBox(Gtk.Box):
 
         song_widget.connect('button-release-event', self._song_activated)
 
-        song_widget.show_all()
-
         return song_widget
 
     @log
diff --git a/gnomemusic/widgets/songwidget.py b/gnomemusic/widgets/songwidget.py
index 35b59fa8..4e59a503 100644
--- a/gnomemusic/widgets/songwidget.py
+++ b/gnomemusic/widgets/songwidget.py
@@ -53,6 +53,7 @@ class SongWidget(Gtk.EventBox):
 
     __gsignals__ = {
         'selection-changed': (GObject.SignalFlags.RUN_FIRST, None, ()),
+        "widget-moved": (GObject.SignalFlags.RUN_FIRST, None, (int,))
     }
 
     coresong = GObject.Property(type=CoreSong, default=None)
@@ -63,6 +64,7 @@ class SongWidget(Gtk.EventBox):
 
     _playlists = Playlists.get_default()
 
+    _dnd_eventbox = Gtk.Template.Child()
     _select_button = Gtk.Template.Child()
     _number_label = Gtk.Template.Child()
     _title_label = Gtk.Template.Child()
@@ -82,7 +84,12 @@ class SongWidget(Gtk.EventBox):
         return '<SongWidget>'
 
     @log
-    def __init__(self, coresong):
+    def __init__(self, coresong, can_dnd=False):
+        """Instanciates a SongWidget
+
+        :param Corsong coresong: song associated with the widget
+        :param bool can_dnd: allow drag and drop operations
+        """
         super().__init__()
 
         self.props.coresong = coresong
@@ -134,11 +141,62 @@ class SongWidget(Gtk.EventBox):
 
         self._number_label.props.no_show_all = True
 
+        if can_dnd is True:
+            self._dnd_eventbox.props.visible = True
+            self._drag_widget = None
+            entries = [
+                Gtk.TargetEntry.new(
+                    "GTK_EVENT_BOX", Gtk.TargetFlags.SAME_APP, 0)
+            ]
+            self._dnd_eventbox.drag_source_set(
+                Gdk.ModifierType.BUTTON1_MASK, entries,
+                Gdk.DragAction.MOVE)
+            self.drag_dest_set(
+                Gtk.DestDefaults.ALL, entries, Gdk.DragAction.MOVE)
+
     @Gtk.Template.Callback()
     @log
     def _on_selection_changed(self, klass, value):
         self.emit('selection-changed')
 
+    @Gtk.Template.Callback()
+    def _on_drag_begin(self, klass, context):
+        gdk_window = self.get_window()
+        _, x, y, _ = gdk_window.get_device_position(context.get_device())
+        allocation = self.get_allocation()
+
+        self._drag_widget = Gtk.ListBox()
+        self._drag_widget.set_size_request(allocation.width, allocation.height)
+
+        drag_row = SongWidget(self.props.coresong)
+        self._drag_widget.add(drag_row)
+        self._drag_widget.drag_highlight_row(drag_row.get_parent())
+        self.hide()
+        self._drag_widget.show_all()
+        Gtk.drag_set_icon_widget(context, self._drag_widget, x, y)
+
+    @Gtk.Template.Callback()
+    def _on_drag_end(self, klass, context):
+        self.show()
+        self._drag_widget = None
+
+    @Gtk.Template.Callback()
+    def _on_drag_data_get(self, klass, context, selection_data, info, time_):
+        row_position = self.get_parent().get_index()
+        selection_data.set(
+            Gdk.Atom.intern("row_position", False), 0,
+            bytes(str(row_position), encoding="UTF8"))
+
+    @Gtk.Template.Callback()
+    def _on_drag_data_received(
+            self, klass, context, x, y, selection_data, info, time_):
+        source_position = int(str(selection_data.get_data(), "UTF-8"))
+        target_position = self.get_parent().get_index()
+        if source_position == target_position:
+            return
+
+        self.emit("widget-moved", source_position)
+
     @Gtk.Template.Callback()
     @log
     def _on_star_toggle(self, widget, event):


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