From 4acc402d97683d56243713d72dc91c9a9010527a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= <manuq@laptop.org>
Date: Tue, 2 Apr 2013 22:56:05 -0300
Subject: [PATCH] Bring back drag and drop to the frame clipboard - SL #3819
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Mail-Followup-To: <sugar-devel@lists.sugarlabs.org>
API fixes:
- gtk.SelectionData.type -> Gtk.SelectionData.get_data_type() [1]
- gtk.SelectionData.data -> Gtk.SelectionData.get_data() [2]
- gtk.SelectionData.target -> Gtk.SelectionData.get_target() [3]
- context.targets -> context.list_targets() [4]
- context.drop_finish(...) -> Gdk.drop_finish(context, ...) [5]
- context.drag_status(...) -> Gdk.drag_status(context, ...) [6]
- context.get_source_widget() -> Gdk.drag_get_source_widget(context) [7]
[1] https://developer.gnome.org/gtk3/3.5/gtk3-Selections.html#gtk-selection-data-get-data-type
[2] https://developer.gnome.org/gtk3/3.5/gtk3-Selections.html#gtk-selection-data-get-data
[3] https://developer.gnome.org/gtk3/3.5/gtk3-Selections.html#gtk-selection-data-get-target
[4] https://developer.gnome.org/gdk/stable/gdk-Drag-and-Drop.html#gdk-drag-context-list-targets
[5] https://developer.gnome.org/gdk/stable/gdk-Drag-and-Drop.html#gdk-drop-finish
[6] https://developer.gnome.org/gdk/stable/gdk-Drag-and-Drop.html#gdk-drag-status
[7] https://developer.gnome.org/gtk3/stable/gtk3-Drag-and-Drop.html#gtk-drag-get-source-widget
Cast the data type from Gdk.Atom to str. Our code treats it as str
and asks methods like startswith which fails if it is not a str like
object.
FIXME: the data has a character 'x00' at the end. Could be encoding
or upstream issue.
Signed-off-by: Manuel Quiñones <manuq@laptop.org>
---
src/jarabe/frame/clipboard.py | 3 +++
src/jarabe/frame/clipboardmenu.py | 11 +++++++----
src/jarabe/frame/clipboardobject.py | 2 ++
src/jarabe/frame/clipboardtray.py | 36 ++++++++++++++++++++----------------
4 files changed, 32 insertions(+), 20 deletions(-)
diff --git a/src/jarabe/frame/clipboard.py b/src/jarabe/frame/clipboard.py
index 7305360..242a2b7 100644
a
|
b
|
class Clipboard(GObject.GObject): |
85 | 85 | logging.debug('Clipboard.add_object_format') |
86 | 86 | cb_object = self._objects[object_id] |
87 | 87 | |
| 88 | if isinstance(format_type, Gdk.Atom): |
| 89 | format_type = str(format_type) |
| 90 | |
88 | 91 | if on_disk and cb_object.get_percent() == 100: |
89 | 92 | new_uri = self._copy_file(data) |
90 | 93 | cb_object.add_format(Format(format_type, new_uri, on_disk)) |
diff --git a/src/jarabe/frame/clipboardmenu.py b/src/jarabe/frame/clipboardmenu.py
index e6766fb..35d0e9c 100644
a
|
b
|
class ClipboardMenu(Palette): |
193 | 193 | most_significant_mime_type = mime.choose_most_significant(formats) |
194 | 194 | format_ = self._cb_object.get_formats()[most_significant_mime_type] |
195 | 195 | |
| 196 | # FIXME last character is 'x00' |
| 197 | format_data = format_.get_data()[:-1] |
| 198 | |
196 | 199 | transfer_ownership = False |
197 | 200 | if most_significant_mime_type == 'text/uri-list': |
198 | | uris = mime.split_uri_list(format_.get_data()) |
| 201 | uris = mime.split_uri_list(format_data) |
199 | 202 | if len(uris) == 1 and uris[0].startswith('file://'): |
200 | 203 | parsed_url = urlparse.urlparse(uris[0]) |
201 | 204 | file_path = parsed_url.path # pylint: disable=E1101 |
202 | 205 | transfer_ownership = False |
203 | 206 | mime_type = mime.get_for_file(file_path) |
204 | 207 | else: |
205 | | file_path = self._write_to_temp_file(format_.get_data()) |
| 208 | file_path = self._write_to_temp_file(format_data) |
206 | 209 | transfer_ownership = True |
207 | 210 | mime_type = 'text/uri-list' |
208 | 211 | else: |
209 | 212 | if format_.is_on_disk(): |
210 | | parsed_url = urlparse.urlparse(format_.get_data()) |
| 213 | parsed_url = urlparse.urlparse(format_data) |
211 | 214 | file_path = parsed_url.path # pylint: disable=E1101 |
212 | 215 | transfer_ownership = False |
213 | 216 | mime_type = mime.get_for_file(file_path) |
214 | 217 | else: |
215 | | file_path = self._write_to_temp_file(format_.get_data()) |
| 218 | file_path = self._write_to_temp_file(format_data) |
216 | 219 | transfer_ownership = True |
217 | 220 | sniffed_mime_type = mime.get_for_file(file_path) |
218 | 221 | if sniffed_mime_type == 'application/octet-stream': |
diff --git a/src/jarabe/frame/clipboardobject.py b/src/jarabe/frame/clipboardobject.py
index e79fa46..6e5c4e2 100644
a
|
b
|
class ClipboardObject(object): |
104 | 104 | format_ = mime.choose_most_significant(self._formats.keys()) |
105 | 105 | if format_ == 'text/uri-list': |
106 | 106 | data = self._formats['text/uri-list'].get_data() |
| 107 | # FIXME last character is 'x00' |
| 108 | data = data[:-1] |
107 | 109 | uri = urlparse.urlparse(mime.split_uri_list(data)[0], 'file') |
108 | 110 | scheme = uri.scheme # pylint: disable=E1101 |
109 | 111 | if scheme == 'file': |
diff --git a/src/jarabe/frame/clipboardtray.py b/src/jarabe/frame/clipboardtray.py
index abc885e..b784acd 100644
a
|
b
|
class ClipboardTray(tray.VTray): |
76 | 76 | return False |
77 | 77 | |
78 | 78 | def _add_selection(self, object_id, selection): |
79 | | if not selection.data: |
| 79 | if not selection.get_data(): |
80 | 80 | return |
81 | 81 | |
82 | | logging.debug('ClipboardTray: adding type %r', selection.type) |
| 82 | selection_data = selection.get_data() |
| 83 | selection_type = selection.get_data_type() |
| 84 | |
| 85 | logging.debug('ClipboardTray: adding type %r', selection_type) |
83 | 86 | |
84 | 87 | cb_service = clipboard.get_instance() |
85 | | if selection.type == 'text/uri-list': |
86 | | uris = selection.data.split('\n') |
| 88 | if selection_type == 'text/uri-list': |
| 89 | uris = selection_data.split('\n') |
87 | 90 | if len(uris) > 1: |
88 | 91 | raise NotImplementedError('Multiple uris in text/uri-list' \ |
89 | 92 | ' still not supported.') |
90 | 93 | |
91 | 94 | cb_service.add_object_format(object_id, |
92 | | selection.type, |
| 95 | selection_type, |
93 | 96 | uris[0], |
94 | 97 | on_disk=True) |
95 | 98 | else: |
96 | 99 | cb_service.add_object_format(object_id, |
97 | | selection.type, |
98 | | selection.data, |
| 100 | selection_type, |
| 101 | selection_data, |
99 | 102 | on_disk=False) |
100 | 103 | |
101 | 104 | def _object_added_cb(self, cb_service, cb_object): |
… |
… |
class ClipboardTray(tray.VTray): |
132 | 135 | logging.debug('ClipboardTray._drag_motion_cb') |
133 | 136 | |
134 | 137 | if self._internal_drag(context): |
135 | | context.drag_status(Gdk.DragAction.MOVE, time) |
| 138 | Gdk.drag_status(context, Gdk.DragAction.MOVE, time) |
136 | 139 | else: |
137 | | context.drag_status(Gdk.DragAction.COPY, time) |
| 140 | Gdk.drag_status(context, Gdk.DragAction.COPY, time) |
138 | 141 | self.props.drag_active = True |
139 | 142 | |
140 | 143 | return True |
… |
… |
class ClipboardTray(tray.VTray): |
148 | 151 | if self._internal_drag(context): |
149 | 152 | # TODO: We should move the object within the clipboard here |
150 | 153 | if not self._context_map.has_context(context): |
151 | | context.drop_finish(False, Gtk.get_current_event_time()) |
| 154 | Gdk.drop_finish(context, False, Gtk.get_current_event_time()) |
152 | 155 | return False |
153 | 156 | |
154 | 157 | cb_service = clipboard.get_instance() |
155 | 158 | object_id = cb_service.add_object(name="") |
156 | 159 | |
157 | | self._context_map.add_context(context, object_id, len(context.targets)) |
| 160 | context_targets = context.list_targets() |
| 161 | self._context_map.add_context(context, object_id, len(context_targets)) |
158 | 162 | |
159 | | for target in context.targets: |
| 163 | for target in context_targets: |
160 | 164 | if str(target) not in ('TIMESTAMP', 'TARGETS', 'MULTIPLE'): |
161 | 165 | widget.drag_get_data(context, target, time) |
162 | 166 | |
… |
… |
class ClipboardTray(tray.VTray): |
167 | 171 | def drag_data_received_cb(self, widget, context, x, y, selection, |
168 | 172 | targetType, time): |
169 | 173 | logging.debug('ClipboardTray: got data for target %r', |
170 | | selection.target) |
| 174 | selection.get_target()) |
171 | 175 | |
172 | 176 | object_id = self._context_map.get_object_id(context) |
173 | 177 | try: |
174 | 178 | if selection is None: |
175 | 179 | logging.warn('ClipboardTray: empty selection for target %s', |
176 | | selection.target) |
| 180 | selection.get_target()) |
177 | 181 | else: |
178 | 182 | self._add_selection(object_id, selection) |
179 | 183 | |
… |
… |
class ClipboardTray(tray.VTray): |
181 | 185 | # If it's the last target to be processed, finish |
182 | 186 | # the dnd transaction |
183 | 187 | if not self._context_map.has_context(context): |
184 | | context.drop_finish(True, Gtk.get_current_event_time()) |
| 188 | Gdk.drop_finish(context, True, Gtk.get_current_event_time()) |
185 | 189 | |
186 | 190 | def _internal_drag(self, context): |
187 | | source_widget = context.get_source_widget() |
| 191 | source_widget = Gtk.drag_get_source_widget(context) |
188 | 192 | if source_widget is None: |
189 | 193 | return False |
190 | 194 | view_ancestor = source_widget.get_ancestor(Gtk.Viewport) |