Search code examples
drag-and-dropgtk

Drag a file from my GTK app to another app (not the other way around)


I have searched for examples, but all the examples were the opposite direction (my app is getting file drag-and-drop from another application). But this must be possible because I can drag a file from Files (Nautilus) to another app, Text Editor (gedit).

Could you show me a very simple example of a GTK Window with one widget on it, and when I drag from the widget to Text Editor, it passes a text file on the system (such as /home/user/.profile) to the Text Editor so that it will open the text file?


Solution

  • In order to make it so that your application can receive files, you need to use uri. In the function you bind to drag-data-received, you can use data.get_uris() to get a list of the files that were dropped. Make sure that you call drag_dest_add_uri_targets(), so that the widget can receive URIs.

    This code example has one button that drags a file, and another button that can receive it. You can also drag the file and drop it into any file-receiving app, such as gedit (Text Editor) or VSCode.

    import gi
    gi.require_version("Gdk", "3.0")
    gi.require_version("Gtk", "3.0")
    from gi.repository import Gtk, Gdk
    
    window = Gtk.Window()
    window.connect("delete-event", Gtk.main_quit)
    
    box = Gtk.HBox()
    window.add(box)
    
    # Called when the Drag button is dragged on
    def on_drag_data_get(widget, drag_context, data, info, time):
        data.set_uris(["file:///home/user/test.html"])
    
    # Called when the Drop button is dropped on
    def on_drag_data_received(widget, drag_context, x, y, data, info, time):
        print("Received uris: %s" % data.get_uris())
    
    # The button from which the file is dragged
    drag_button = Gtk.Button(label="Drag")
    drag_button.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, [], Gdk.DragAction.LINK)
    drag_button.drag_source_add_uri_targets() # This makes sure that the buttons are using URIs, not text
    drag_button.connect("drag-data-get", on_drag_data_get)
    box.add(drag_button)
    
    # The button into which the file can be dropped
    drop_button = Gtk.Button(label="Drop")
    drop_button.drag_dest_set(Gtk.DestDefaults.ALL, [], Gdk.DragAction.LINK)
    drop_button.drag_dest_add_uri_targets() # This makes sure that the buttons are using URIs, not text
    drop_button.connect("drag-data-received", on_drag_data_received)
    box.add(drop_button)
    
    window.show_all()
    Gtk.main()