Search code examples
python-3.xdrag-and-dropgtkgtk3pygobject

PyGObject drag and drop reorder widgets


I'm trying to implement DND in Gtk3 with Python, but so far I only managed to catch a drag-begin signal. Here's the code:

class MyWidget(Gtk.EventBox):
    def __init__(self):
        super(TrackBox, self).__init__()

        self.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, [], Gdk.DragAction.MOVE)
        self.connect('drag-begin', self._sig_drag_begin)
        self.connect('drag-data-get', self._sig_drag_data_get)

        self.drag_dest_set(Gtk.DestDefaults.HIGHLIGHT | Gtk.DestDefaults.DROP | Gtk.DestDefaults.MOTION, [Gtk.TargetEntry.new('GTK_MYWIDGET', Gtk.TargetFlags.SAME_APP, 0)], Gdk.DragAction.MOVE)
        self.connect('drag-drop', self._sig_drag_drop)
        self.connect('drag-data-received', self._sig_drag_data_received)

    def _sig_drag_begin(self, widget, context):
        print("drag begin")
        print(self, widget, context)

    def _sig_drag_data_get(self, widget, context, selection, info, timestamp):
        print("drag data get")
        print(self, widget, context, selection, info, timestamp)

    def _sig_drag_drop(self, widget, context, x, y, timestamp):
        print('drag-drop')
        print(self, widget, context, x, y, timestamp)

    def _sig_drag_data_received(self, widget, context, x, y, selection, info, timestamp):
        print('drag-data-received')
        print(self, widget, context, x, y, selection, info, timestamp)

I got the output from _sig_drag_begin, but nothing else. The goal would be to be able to reorder these Gtk.EventBox-es inside a Gtk.Box with a somewhat similar end result as we can get with a reorderable Gtk.TreeView.


Solution

  • Here's the solution in case anyone has the same question:

    class TrackBox(Gtk.EventBox):
        def __init__(self, title, artist, id, year, length, album):
            super(TrackBox, self).__init__()
            
            # do your stuff here
    
            # Looks like this one is needed
            targs = [Gtk.TargetEntry.new("dummy", Gtk.TargetFlags.SAME_APP, 1)]
    
            self.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, targs, Gdk.DragAction.MOVE)
    
            self.drag_dest_set(Gtk.DestDefaults.HIGHLIGHT | Gtk.DestDefaults.DROP | Gtk.DestDefaults.MOTION, targs, Gdk.DragAction.MOVE)
            self.connect('drag-drop', self._sig_drag_drop)
            self.connect('drag-end', self._sig_drag_end)
    
        def _sig_drag_drop(self, widget, *_):
            # Here you get the name of the target
            print('drag-drop: get target name')
            print(widget.get_name())
    
        def _sig_drag_end(self, widget, _):
            # And here you get the name of the source
            # also you should write moving related code here
            print('drag-end: actually move and get source name')
            print(widget.get_name())
    

    This video explains everything in detail.