Drag and Drop with Pygobject and Gtk 4

Hello everyone!

I am trying to enable the drag of files from a Gtk.ListView into other apps, such as Nautilus, using Gtk 4 and Python. The docs are not the clearest and I can’t seem to find any coherent examples online. Would anyone happen to have any example of dragging and dropping files with Gtk 4?

First of all, inter-application dnd depends on the target application’s ability to receive the drop (e.g. nautilus). So, the first step is to know what types of drops the target application can receive, which should probably only be possible to discover by reading the target application’s code. Furthermore, if we are talking about a flatpak, there is still the issue of access to be considered.

With this information, you will have to use gdk.ContentProvider to offer the content to be transferred in a way that the target application understands. Personally, I only did dnd within the same application, but I believe the procedure is not that different once you are sure that the target application is ready to receive the drop.

There is a dnd example in Workbench that is very instructive. If you don’t already use Workbench, I suggest starting as it helps a lot.

Hi,

You usually just need to connect to the drag-prepare signal, and return a content provider with the file.

Should be more or less something like this:

def on_setup(factory, listitem):
    widget = ...
    listitem.set_child(widget)
    ev_drag = Gtk.DragSource(actions=Gdk.DragAction.COPY)
    ev_drag.connect('prepare', on_drag_prepare)
    widget.add_controller(ev_drag)

def on_bind(factory, listitem):
    widget = listitem.get_child()
    item = listitem.get_item()
    widget.item = item   # to find the item from the widget

def on_drag_prepare(event, x, y):
    widget = event.get_widget()
    item = widget.item
    gfile = ... # get the Gio.File from 'item' here
    content = Gdk.FileList.new_from_list([gfile])
    return Gdk.ContentProvider.new_for_value(content)

(not 100% sure about how to create the contentprovider from a filelist, but should be similar)

1 Like

Thanks! Looks like my Gdk version doesn’t have FileList yet, but I will definitely try this out when Ubuntu 24.04.01 drops.

It may be possible to use a simple URI string as content, but I can’t guarantee all drop targets will support that:

content = gfile.get_uri()

Or to go the hard way, declaring the various URI mimetypes as contentprovider…
Gdk.FileList will make everything easier, so I recommend to upgrade if you can.

No, it doesn’t seem like Nautilus supports that. It ends up creating a file with the filename in it. Oh well. It might prove useful for something in the future though…