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()
|