summaryrefslogtreecommitdiff
path: root/examples/gtk/treeview_dnd.py
blob: ba4d3a43859bb1f1719dc572d0dd16aed4781ba6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#!/usr/bin/env python


# This file is based on http://code.google.com/p/quodlibet/source/browse/junk/dndtest.py


import gobject
import gtk


class TestTreeView(gtk.TreeView):
    __gtype_name__ = 'TestTreeView'

    def __init__(self, name):
        gtk.TreeView.__init__(self)

        model = gtk.ListStore(str)
        for i in range(10): model.append(row=['Item%d' % i])
        self.set_model(model)

        crt = gtk.CellRendererText()
        col = gtk.TreeViewColumn(name, crt, text=0)
        self.append_column(col)

        self.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
        targets = [('text/uri-list', 0, 1)]
        self.drag_source_set(gtk.gdk.BUTTON1_MASK|gtk.gdk.CONTROL_MASK,
                             targets,
                             gtk.gdk.ACTION_COPY|gtk.gdk.ACTION_MOVE)
        self.drag_dest_set(gtk.DEST_DEFAULT_ALL,
                           targets,
                           gtk.gdk.ACTION_COPY|gtk.gdk.ACTION_MOVE)
        self.connect('drag-begin', self._drag_begin)
        self.connect('drag-data-delete', self._drag_data_delete)
        self.connect('drag-motion', self._drag_motion)
        self.connect('drag-data-get', self._drag_data_get)
        self.connect('drag-data-received', self._drag_data_received)

    def _drag_begin(self, view, ctx):
        return True

    def _drag_data_delete(self, view, ctx):
        if ctx.is_source and ctx.action == gtk.gdk.ACTION_MOVE:
            # For some reason this gets called twice.
            map(self.get_model().remove, self.__iters)
            self.__iters = []

    def _drag_motion(self, view, ctx, x, y, time):
        try:
            self.set_drag_dest_row(*self.get_dest_row_at_pos(x, y))
        except TypeError:
            self.set_drag_dest_row(len(self.get_model()) - 1, gtk.TREE_VIEW_DROP_AFTER)

        # You can also pass None as the first parameter to set_drag_dest_row
        #try:
        #    print 'Testing set_drag_dest_row(None, pos)'
        #    (path, pos) = self.get_dest_row_at_pos(x, y)
        #    self.set_drag_dest_row(None, pos)
        #except TypeError:
        #    self.set_drag_dest_row(len(self.get_model()) - 1, gtk.TREE_VIEW_DROP_AFTER)

        if ctx.get_source_widget() == self:
            kind = gtk.gdk.ACTION_MOVE
        else:
            kind = gtk.gdk.ACTION_COPY

        ctx.drag_status(kind, time)
        return True

    def _drag_data_get(self, view, ctx, sel, tid, etime):
        model, paths = self.get_selection().get_selected_rows()
        uris = ['file:///' + model[path][0] for path in paths]

        if tid == 1:
            if ctx.action == gtk.gdk.ACTION_MOVE:
                self.__iters = map(model.get_iter, paths)
            else:
                self.__iters = []

            sel.set('text/uri-list', 8, '\x00'.join(uris))
        else:
            sel.set_uris(uris)

            return True

    def _drag_data_received(self, view, ctx, x, y, sel, info, etime):
        model = view.get_model()

        if info == 1:
            files = sel.data.split('\x00')
        elif info == 2:
            files = sel.get_uris()

        try:
            path, position = self.get_dest_row_at_pos(x, y)
        except TypeError:
            path, position = len(model) - 1, gtk.TREE_VIEW_DROP_AFTER

        iter = model.get_iter(path)
        file = files.pop(0)

        if position in (gtk.TREE_VIEW_DROP_BEFORE, gtk.TREE_VIEW_DROP_INTO_OR_BEFORE):
            iter = model.insert_before(iter, [file[8:]])
        else:
            iter = model.insert_after(iter, [file[8:]])

        for file in files:
            iter = model.insert_after(iter, [file[8:]])

        ctx.finish(True, True, etime)
        return True


if __name__ == '__main__':
    w = gtk.Window()
    w.connect('delete-event', gtk.main_quit)
    w.add(gtk.HBox(spacing=3))
    w.child.pack_start(TestTreeView('Test 1'))
    w.child.pack_start(TestTreeView('Test 2'))
    w.show_all()
    gtk.main()