6

I'm creating a small app must be able to receive URLs. If the apps window is open, I should be able to drag a link from a browser and drop it into the app - and the app will save the URL to a database.

I'm creating this in Python/GTk. But I am a bit confused about the drag and drop functionality in it. So, how do it?

Some sample code to implement drag/drop(my app uses a bit of this code)...

import pygtk
pygtk.require('2.0')
import gtk

# function to print out the mime type of the drop item
def drop_cb(wid, context, x, y, time):
    l.set_text('\n'.join([str(t) for t in context.targets]))
    # What should I put here to get the URL of the link?

    context.finish(True, False, time)
    return True

# Create a GTK window and Label, and hook up
# drag n drop signal handlers to the window
w = gtk.Window()
w.set_size_request(200, 150)
w.drag_dest_set(0, [], 0)
w.connect('drag_drop', drop_cb)
w.connect('destroy', lambda w: gtk.main_quit())
l = gtk.Label()
w.add(l)
w.show_all()

# Start the program
gtk.main()
Georg Fritzsche
  • 97,545
  • 26
  • 194
  • 236
Binny V A
  • 2,036
  • 3
  • 20
  • 23

4 Answers4

8

You must fetch the data yourself. Here's a simple working example that will set a label to the url dropped:

#!/usr/local/env python

import pygtk
pygtk.require('2.0')
import gtk

def motion_cb(wid, context, x, y, time):
    l.set_text('\n'.join([str(t) for t in context.targets]))
    context.drag_status(gtk.gdk.ACTION_COPY, time)
    # Returning True which means "I accept this data".
    return True

def drop_cb(wid, context, x, y, time):
    # Some data was dropped, get the data
    wid.drag_get_data(context, context.targets[-1], time)
    return True

def got_data_cb(wid, context, x, y, data, info, time):
    # Got data.
    l.set_text(data.get_text())
    context.finish(True, False, time)

w = gtk.Window()
w.set_size_request(200, 150)
w.drag_dest_set(0, [], 0)
w.connect('drag_motion', motion_cb)
w.connect('drag_drop', drop_cb)
w.connect('drag_data_received', got_data_cb)
w.connect('destroy', lambda w: gtk.main_quit())
l = gtk.Label()
w.add(l)
w.show_all()

gtk.main()
nosklo
  • 217,122
  • 57
  • 293
  • 297
  • 8
    Be careful in that you might have to call data.get_uris() if the data is in the form of a uri list. So for example, if you were DnD'ing a list of files from konqueror/nautilus to the window and your accepting say 'text/uri-list', get_data() on the GtkSelectionData will return None. – Jason Mock Aug 31 '09 at 21:41
  • There could be an undesirable behavior if we drag onto the window and drag off the window window without releasing the mouse of the label retaining the text. Clearing the label seems to make more sense – demongolem Oct 02 '12 at 14:51
3

To be sure to get only the data of one file or directory on DnD'ing a list of files from your file explorer, you could use something like:

data.get_text().split(None,1)[0]

the code for the "got_data_cb" method would then look like this:

def got_data_cb(wid, context, x, y, data, info, time):
    # Got data.
    l.set_text(data.get_text().split(None,1)[0])
    context.finish(True, False, time)

This would split the data by any whitespace and returns you the first item.

Alexibaba
  • 31
  • 1
2

The following code is ported from an example of the (old) PyGTK tutorial which I guess inspired the accepted answer, but with pygi:

#!/usr/local/env python
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk

def motion_cb(wid, context, x, y, time):
    Gdk.drag_status(context, Gdk.DragAction.COPY, time)
    return True

def drop_cb(wid, context, x, y, time):
    l.set_text('\n'.join([str(t) for t in context.list_targets()]))
    context.finish(True, False, time)
    return True

w = Gtk.Window()
w.set_size_request(200, 150)
w.drag_dest_set(0, [], 0)
w.connect('drag-motion', motion_cb)
w.connect('drag-drop', drop_cb)
w.connect('destroy', lambda w: Gtk.main_quit())
l = Gtk.Label()
w.add(l)
w.show_all()

Gtk.main()
Community
  • 1
  • 1
Frederick Nord
  • 1,246
  • 1
  • 14
  • 31
1

The only solution working for me is :

def got_data_cb(wid, context, x, y, data, info, time):
    # Got data.
    l.set_text(data.get_uris()[0])
    context.finish(True, False, time)
Fabrice LARRIBE
  • 322
  • 3
  • 9