Here is how to achieve drag and drop functionality in GTK in python. Recently I needed this for my project and it took me some time to find how to do that, so now I'm sharing it in case anyone needs it.
Drag source implementation:
button = Gtk.Button(label="Drag File")
drag = Gtk.DragSource.new()
drag.set_actions(Gdk.DragAction.COPY)
def on_drag(drag_source, x, y):
file_list = ["/path/to/your/file1","/path/to/your/file2"]
data = Gdk.FileList.new_from_list([Gio.File.new_for_path(i) for i in file_list])
print("Draged file(s):", [i.get_path() for i in data.get_files()])
content = Gdk.ContentProvider.new_for_value(data)
return content
drag.connect('prepare', on_drag)
drag.connect('drag-begin', lambda drag_source,data: print('drag begin') )
drag.connect('drag-end', lambda drag,drag_data,flag: print('drag end'))
button.add_controller(drag)
container.append(button)
Drop target implementation:
label = Gtk.Label(label="Drop File Here")
drop = Gtk.DropTarget.new(Gdk.FileList, Gdk.DragAction.COPY)
def on_drop(value, user_data, x, y):
print("Dropped file(s):", [i.get_path() for i in user_data.get_files()])
drop.connect('drop', on_drop)
drop.connect('accept', lambda drop,user_data: True)
drop.connect('enter', lambda drop_target,x,y: Gdk.DragAction.COPY)
drop.connect('motion', lambda drop_target,x,y: Gdk.DragAction.COPY)
drop.connect('leave', lambda user_data: None)
label.add_controller(drop)
container.append(label)
Drag source implementation:
button = Gtk.Button(label="Drag File")
button.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, [Gtk.TargetEntry.new('text/uri-list', Gtk.TargetFlags.SAME_WIDGET, 0)], Gdk.DragAction.COPY)
def on_drag(widget, context, data, info, time):
file_list = ["/path/to/your/file1","/path/to/your/file2"]
uris = [("file://" + i.replace(" ","%20")) for i in file_list]
print("Draged file(s):", uris)
data.set_uris(uris)
button.connect("drag-data-get", on_drag)
container.add(button)
Drop target implementation:
label = Gtk.Label(label="Drop File Here")
label.drag_dest_set(Gtk.DestDefaults.ALL, [Gtk.TargetEntry.new("text/uri-list", 0, 0)], Gdk.DragAction.COPY)
def on_drop(widget, context, x, y, data, info, time):
uris = data.get_uris()
print("Dropped file(s):", uris)
label.connect("drag-data-received", on_drop)
container.add(label)