[gnome-music/wip/jfelder/gtk4-v3: 200/200] songwidget: Restore drag and drop




commit fa15dc8043b849e645864a2ff39e2e50a1f64429
Author: Jean Felder <jfelder src gnome org>
Date:   Fri Feb 11 15:09:42 2022 +0100

    songwidget: Restore drag and drop

 data/ui/SongWidget.ui            |  37 ++++++++------
 gnomemusic/widgets/songwidget.py | 103 +++++++++++++++++++--------------------
 2 files changed, 73 insertions(+), 67 deletions(-)
---
diff --git a/data/ui/SongWidget.ui b/data/ui/SongWidget.ui
index 8c4b273b2..367849c83 100644
--- a/data/ui/SongWidget.ui
+++ b/data/ui/SongWidget.ui
@@ -1,29 +1,20 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.20.0 -->
 <interface>
-  <requires lib="gtk+" version="3.10"/>
+  <requires lib="gtk" version="4.0"/>
   <template class="SongWidget" parent="GtkListBoxRow">
     <property name="focusable">False</property>
     <property name="selectable">False</property>
-    <!-- <signal name="drag_data_received" handler="_on_drag_data_received"/> -->
     <child>
       <object class="GtkBox" id="box1">
         <property name="focusable">False</property>
         <property name="spacing">6</property>
         <child>
-          <object class="GtkBox" id="_dnd_eventbox">
+          <object class="GtkImage" id="_dnd_icon">
             <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="icon-name">list-drag-handle-symbolic</property>
-                <style>
-                  <class name="drag-handle"/>
-                </style>
-              </object>
-            </child>
+            <property name="icon-name">list-drag-handle-symbolic</property>
+            <style>
+              <class name="drag-handle"/>
+            </style>
           </object>
         </child>
         <child>
@@ -191,6 +182,22 @@
         <signal name="released" handler="_on_click" swapped="no"/>
       </object>
     </child>
+    <child>
+      <object class="GtkDragSource" id="_drag_source">
+        <property name="actions">move</property>
+        <property name="propagation-phase">none</property>
+        <signal name="prepare" handler="_on_drag_prepare" swapped="no"/>
+        <signal name="drag-begin" handler="_on_drag_begin" swapped="no"/>
+      </object>
+    </child>
+    <child>
+      <object class="GtkDropTarget">
+        <property name="actions">move</property>
+        <property name="formats">SongWidget</property>
+        <property name="preload">True</property>
+        <signal name="drop" handler="_on_drop" swapped="no"/>
+      </object>
+    </child>
     <style>
       <class name="songwidget"/>
     </style>
diff --git a/gnomemusic/widgets/songwidget.py b/gnomemusic/widgets/songwidget.py
index c39b8b6aa..ff3dbf3f4 100644
--- a/gnomemusic/widgets/songwidget.py
+++ b/gnomemusic/widgets/songwidget.py
@@ -22,6 +22,8 @@
 # code, but you are not obligated to do so.  If you do not wish to do so,
 # delete this exception statement from your version.
 
+from __future__ import annotations
+
 from enum import IntEnum
 from typing import Optional
 
@@ -60,7 +62,8 @@ class SongWidget(Gtk.ListBoxRow):
     _album_duration_box = Gtk.Template.Child()
     _artist_box = Gtk.Template.Child()
     _artist_label = Gtk.Template.Child()
-    # _dnd_eventbox = Gtk.Template.Child()
+    _dnd_icon = Gtk.Template.Child()
+    _drag_source = Gtk.Template.Child()
     _menu_button = Gtk.Template.Child()
     _select_button = Gtk.Template.Child()
     _number_label = Gtk.Template.Child()
@@ -142,57 +145,53 @@ class SongWidget(Gtk.ListBoxRow):
         if not self.props.coresong.props.is_tracker:
             self._star_stack.props.visible_child_name = "empty"
 
-    #     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()
-    # 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)
-    #     drag_row.props.show_song_number = self.props.show_song_number
-
-    #     self._drag_widget.add(drag_row)
-    #     self._drag_widget.drag_highlight_row(drag_row)
-    #     self._drag_widget.props.visible = True
-    #     Gtk.drag_set_icon_widget(
-    #         context, self._drag_widget, x - allocation.x, y - allocation.y)
-
-    # @Gtk.Template.Callback()
-    # def _on_drag_end(self, klass, context):
-    #     self._drag_widget = None
-
-    # @Gtk.Template.Callback()
-    # def _on_drag_data_get(self, klass, context, selection_data, info, time_):
-    #     row_position = self.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_index()
-    #     if source_position == target_position:
-    #         return
-
-    #     self.emit("widget-moved", source_position)
+        self._drag_x = 0.
+        self._drag_y = 0.
+        self._drag_widget: Optional[Gtk.ListBox] = None
+        if can_dnd:
+            capture_phase = Gtk.PropagationPhase.CAPTURE
+            self._drag_source.props.propagation_phase = capture_phase
+            self._dnd_icon.props.visible = True
+
+    @Gtk.Template.Callback()
+    def _on_drag_prepare(
+        self, drag_source: Gtk.DragSource, x: float,
+            y: float) -> Gdk.ContentProvider:
+        self._drag_x = x
+        self._drag_y = y
+        return Gdk.ContentProvider.new_for_value(self)
+
+    @Gtk.Template.Callback()
+    def _on_drag_begin(
+            self, drag_source: Gtk.DragSource, drag: Gdk.Drag) -> None:
+        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, False, True)
+        drag_row.props.show_song_number = self.props.show_song_number
+        self._drag_widget.append(drag_row)
+        self._drag_widget.drag_highlight_row(drag_row)
+
+        drag_icon = Gtk.DragIcon.get_for_drag(drag)
+        drag_icon.props.child = self._drag_widget
+        drag.set_hotspot(self._drag_x, self._drag_y)
+
+    @Gtk.Template.Callback()
+    def _on_drop(
+            self, target: Gtk.DropTarget,
+            source_widget: SongWidget, x: float, y: float) -> bool:
+        self._drag_widget = None
+        self._drag_x = 0.
+        self._drag_y = 0.
+
+        source_position = source_widget.get_index()
+        target_position = self.get_index()
+        if source_position == target_position:
+            return False
+
+        self.emit("widget-moved", source_position)
+        return True
 
     @Gtk.Template.Callback()
     def _on_click(


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