#!/usr/bin/env python

import sys
import gtk
import gtk.gdk

class DNDTest:
    TARGET_TYPE_XDS = 42
    TARGET_TYPE_OCTET = 43
    XDS_ATOM = gtk.gdk.atom_intern("XdndDirectSave0")
    TEXT_ATOM = gtk.gdk.atom_intern("text/plain")
    XDS_FAILURE = "F"

    def __init__(self):
        # Main window
        window = gtk.Window()
        window.connect("destroy", self.quit)

        # VBox to pack the two buttons into
        vbox = gtk.VBox(False, 5)
        vbox.set_border_width(5)
        window.add(vbox)
        vbox.show()

        # First button
        # When this button is dragged and dropped on a file manager,
        # a file named 'tar' should appear in the drop location, and
        # it should be identical to the file '/bin/tar' on the source.
        dnd_xds = gtk.Button("Drag Me to Test XDS")
        vbox.pack_start(dnd_xds, False, False, 0)
        dnd_xds_targets = [("XdndDirectSave0", 0, self.TARGET_TYPE_XDS),
                   ("application/octet-stream", 0, self.TARGET_TYPE_OCTET)]
        dnd_xds.drag_source_set(gtk.gdk.BUTTON1_MASK,
                                dnd_xds_targets,
                                gtk.gdk.ACTION_COPY)
        dnd_xds.connect("drag-begin", self.on_drag_begin)
        dnd_xds.connect("drag-data-get", self.on_drag_data_get)
        dnd_xds.connect("drag-end", self.on_drag_end)
        dnd_xds.show()

        # Second button
        # When this button is dragged and dropped on a file manager,
        # a file should appear in the drop location, and it should be
        # identical to the file '/bin/tar' on the source. The file
        # manager will have to choose a name, since none was supplied.
        dnd_raw = gtk.Button("Drag Me to Test XDND of Raw Data")
        vbox.pack_start(dnd_raw, False, False, 0)
        dnd_raw_targets = [("application/octet-stream", 0, self.TARGET_TYPE_OCTET)]
        dnd_raw.drag_source_set(gtk.gdk.BUTTON1_MASK,
                                dnd_raw_targets,
                                gtk.gdk.ACTION_COPY)
        dnd_raw.connect("drag-data-get", self.on_drag_data_get)
        dnd_raw.show()

        window.show()

    def on_drag_begin(self, widget, context):
        # When doing an XDS DND, this sets the filename to use
        # in the destination.
        # I have hard-coded it to be 'tar' for testing purposes.
        filename = "tar"
        context.source_window.property_change(self.XDS_ATOM, self.TEXT_ATOM, 8,
                                              gtk.gdk.PROP_MODE_REPLACE,
                                              filename)

    def on_drag_data_get(self, widget, context, selection, info, time):
        if info == self.TARGET_TYPE_XDS:
            # The destination has requested that we save the file ourselves.
            # We won't even try to do this, since this program might be
            # running on a different machine than the one running the file
            # manager. When the file manager gets this response, it should
            # request the raw data from us--type application/octet-stream--
            # and it will take care of saving the file for us.
            selection.set(selection.target, 8, self.XDS_FAILURE)
        elif info == self.TARGET_TYPE_OCTET:
            # This is the raw data to send to the destination. It could be
            # an image or a binary executable or anything. It could contain
            # embedded nul bytes. The destination must be prepared to deal
            # with this binary data.
            # I have hard-coded '/bin/tar' as the file to send, since I
            # suppose that everyone has that file.
            f = open('/bin/tar', 'r')
            selection.set(selection.target, 8, f.read())

    def on_drag_end(self, widget, context):
        # Clear the XDS property.
        context.source_window.property_delete(self.XDS_ATOM)

    def quit(self, unused):
        sys.exit(0)

if __name__ == '__main__':
    dnd = DNDTest()
    gtk.main()
