Merge lp:~osomon/unity-2d/dnd2 into lp:unity-2d/3.0
- dnd2
- Merge into natty
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Florian Boucault | ||||
Approved revision: | 406 | ||||
Merged at revision: | 391 | ||||
Proposed branch: | lp:~osomon/unity-2d/dnd2 | ||||
Merge into: | lp:unity-2d/3.0 | ||||
Diff against target: |
643 lines (+389/-48) 16 files modified
launcher/CMakeLists.txt (+4/-0) launcher/Launcher.qml (+5/-0) launcher/LauncherItem.qml (+4/-0) launcher/UnityApplications/launcheritem.cpp (+15/-0) launcher/UnityApplications/launcheritem.h (+8/-0) launcher/UnityApplications/trash.cpp (+26/-0) launcher/UnityApplications/trash.h (+6/-0) launcher/app/launcherview.cpp (+97/-43) launcher/app/launcherview.h (+19/-5) libunity-2d-private/Unity2d/CMakeLists.txt (+2/-0) libunity-2d-private/Unity2d/plugin.cpp (+7/-0) libunity-2d-private/src/CMakeLists.txt (+2/-0) libunity-2d-private/src/dragdropevent.cpp (+56/-0) libunity-2d-private/src/dragdropevent.h (+59/-0) libunity-2d-private/src/mimedata.cpp (+31/-0) libunity-2d-private/src/mimedata.h (+48/-0) |
||||
To merge this branch: | bzr merge lp:~osomon/unity-2d/dnd2 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Florian Boucault (community) | functional code | Needs Fixing | |
Aurélien Gâteau (community) | Approve | ||
Review via email: mp+49782@code.launchpad.net |
Commit message
[launcher] Support dragging files to the trash.
This changeset also implements the generic infrastructure needed to delegate drag’n’drop events’ handling to launcher items.
Description of the change
Olivier Tilloy (osomon) wrote : | # |
> It works well, but the cursor behavior is a bit weird. If I drag a file from
> Dolphin to the trash, I get the correct "Move" cursor, but if I drag it from
> Nautilus I get the "Copy" action. Not sure what is wrong here. Maybe Nautilus
> does not put "Move" in the proposed actions?
That’s exactly what happens. Not much we can do, apart from patching Nautilus itself…
Olivier Tilloy (osomon) wrote : | # |
> We ship Qt 4.7.1 in Natty, so you should already be able to use
> DeclarativeDrag
Right. For some reason I thought we may want to backport this feature to maverick, which is mostly why I kept this workaround. I also must admit it is very convenient to be able to develop on maverick while I haven’t migrated to natty yet.
Olivier Tilloy (osomon) wrote : | # |
> From what I understand, the dnd events are received in the C++ side, then
> forwarded to the QML side, which forwards them again back to C++. Which raise
> a question: is it necessary at all to go through QML?
That’s how it works indeed, and I’d be more than happy to find a solution that would avoid the roundtrip between C++ and QML and back, which on top of this is perceivably slow. The issue is that the LauncherView doesn’t have direct knowledge of the list model, and much less of how to associate a mouse position to a LauncherItem. Any suggestion?
Olivier Tilloy (osomon) wrote : | # |
> We ship Qt 4.7.1 in Natty, so you should already be able to use
> DeclarativeDrag
Fixed.
> I think you don't need to call setAccepted() in drop methods (onDrop() or
> dropEvent()). It only matters in drag methods (onDragEnter(),
> dragEnterEvent(), ondragMove(), dragMoveEvent()).
Verified and fixed, thanks for the tip!
> Usual nitpick: "}\nelse {" => "} else {" :)
Fixed too. I’ll never get used to it :/
All your comments have been addressed except the C++ to QML to C++ roundtrip, for which I welcome implementation ideas.
Aurélien Gâteau (agateau) wrote : | # |
Let's keep that way for now. Approved.
Florian Boucault (fboucault) wrote : | # |
How slow is "perceivably slow"? I doubt that if anything looking slow is because of the roundtrip between C++ and QML.
Florian Boucault (fboucault) wrote : | # |
Please make my life easier and readd the workaround for Qt 4.7
Florian Boucault (fboucault) wrote : | # |
Ignore my last comment, this feature will not be backported to Maverick.
Let's advise future OEM projects on Maverick or Lucid to use Qt 4.7.1
Florian Boucault (fboucault) wrote : | # |
I understand now why it's "perceivably slow". In LauncherView:
I do not understand why the plan has changed:
LauncherView should not know about the list of LauncherItems at all. The LauncherItem should take care of their own drag&drop events, not only the actions on drop but also the detection of the drag. Why are not we creating a QML item that is able to do that similar to what is done in:
https:/
It would be less code, faster and also above all it will allow much greater flexibility.
Olivier Tilloy (osomon) wrote : | # |
Have a look at the revisions in my branch, that is how I had implemented it first.
It is not less code.
And it handles drag events only for launcher items, meaning that other (empty) areas of the launcher cannot receive drag events, which breaks the current functionality (drag’n’drop of desktop files and URLs).
Florian Boucault (fboucault) wrote : | # |
It will be faster and more flexible.
I don't understand why can't you have the drag'n'drop of desktop files and URLs as you have them today, in the LauncherView and the rest in custom QML items.
Olivier Tilloy (osomon) wrote : | # |
Because if the LauncherView reimplements drag and drop event slots, it will eat the events and they won’t be propagated to the launcher items.
Also, I changed the implementation so as to allow implementing bug #607782: if we want "capable" launcher items to stand out when something is dragged over the launcher, the event needs to be handled by the view.
Preview Diff
1 | === modified file 'launcher/CMakeLists.txt' |
2 | --- launcher/CMakeLists.txt 2011-01-14 20:42:44 +0000 |
3 | +++ launcher/CMakeLists.txt 2011-02-16 11:14:09 +0000 |
4 | @@ -1,5 +1,9 @@ |
5 | project(unity-2d-launcher) |
6 | |
7 | +include_directories( |
8 | + ${libunity-2d-private_SOURCE_DIR}/src |
9 | + ) |
10 | + |
11 | # Source |
12 | add_subdirectory(UnityApplications) |
13 | add_subdirectory(app) |
14 | |
15 | === modified file 'launcher/Launcher.qml' |
16 | --- launcher/Launcher.qml 2011-02-15 11:48:13 +0000 |
17 | +++ launcher/Launcher.qml 2011-02-16 11:14:09 +0000 |
18 | @@ -1,5 +1,6 @@ |
19 | import Qt 4.7 |
20 | import UnityApplications 1.0 |
21 | +import Unity2d 1.0 /* required for drag’n’drop handling */ |
22 | |
23 | Item { |
24 | id: launcher |
25 | @@ -47,6 +48,10 @@ |
26 | |
27 | Binding { target: item.menu; property: "title"; value: item.name } |
28 | |
29 | + /* Drag’n’drop handling */ |
30 | + function dragEnterEvent(event) { item.onDragEnter(event) } |
31 | + function dropEvent(event) { item.onDrop(event) } |
32 | + |
33 | function showMenu() { |
34 | /* Prevent the simultaneous display of multiple menus */ |
35 | if (list.visibleMenu != item.menu && list.visibleMenu != undefined) { |
36 | |
37 | === modified file 'launcher/LauncherItem.qml' |
38 | --- launcher/LauncherItem.qml 2011-02-15 12:02:56 +0000 |
39 | +++ launcher/LauncherItem.qml 2011-02-16 11:14:09 +0000 |
40 | @@ -29,6 +29,10 @@ |
41 | */ |
42 | Item { |
43 | id: item |
44 | + /* The object name is used by the launcher view to find the current |
45 | + launcher item under the mouse cursor during a drag’n’drop event. */ |
46 | + objectName: "launcherItem" |
47 | + |
48 | anchors.horizontalCenter: parent.horizontalCenter |
49 | |
50 | property int tileSize |
51 | |
52 | === modified file 'launcher/UnityApplications/launcheritem.cpp' |
53 | --- launcher/UnityApplications/launcheritem.cpp 2010-12-16 11:07:52 +0000 |
54 | +++ launcher/UnityApplications/launcheritem.cpp 2011-02-16 11:14:09 +0000 |
55 | @@ -36,3 +36,18 @@ |
56 | { |
57 | return m_menu; |
58 | } |
59 | + |
60 | +void |
61 | +LauncherItem::onDragEnter(DeclarativeDragDropEvent* event) |
62 | +{ |
63 | + Q_UNUSED(event) |
64 | + /* Default to doing nothing, i.e. refusing the event. */ |
65 | +} |
66 | + |
67 | +void |
68 | +LauncherItem::onDrop(DeclarativeDragDropEvent* event) |
69 | +{ |
70 | + Q_UNUSED(event) |
71 | + /* Default to doing nothing. */ |
72 | +} |
73 | + |
74 | |
75 | === modified file 'launcher/UnityApplications/launcheritem.h' |
76 | --- launcher/UnityApplications/launcheritem.h 2011-02-10 01:00:41 +0000 |
77 | +++ launcher/UnityApplications/launcheritem.h 2011-02-16 11:14:09 +0000 |
78 | @@ -23,6 +23,8 @@ |
79 | #include <QObject> |
80 | #include <QString> |
81 | |
82 | +#include "dragdropevent.h" |
83 | + |
84 | class LauncherContextualMenu; |
85 | |
86 | class LauncherItem : public QObject |
87 | @@ -69,6 +71,12 @@ |
88 | void iconChanged(QString); |
89 | void launchingChanged(bool); |
90 | void menuChanged(QObject*); |
91 | + |
92 | +public Q_SLOTS: |
93 | + /* Default implementation of drag’n’drop handling, should be overridden in |
94 | + subclasses to implement custom behaviours. */ |
95 | + virtual void onDragEnter(DeclarativeDragDropEvent*); |
96 | + virtual void onDrop(DeclarativeDragDropEvent*); |
97 | }; |
98 | |
99 | #endif // LAUNCHERITEM_H |
100 | |
101 | === modified file 'launcher/UnityApplications/trash.cpp' |
102 | --- launcher/UnityApplications/trash.cpp 2011-02-10 11:36:14 +0000 |
103 | +++ launcher/UnityApplications/trash.cpp 2011-02-16 11:14:09 +0000 |
104 | @@ -214,6 +214,32 @@ |
105 | empty(); |
106 | } |
107 | |
108 | +void |
109 | +Trash::onDragEnter(DeclarativeDragDropEvent* event) |
110 | +{ |
111 | + Q_FOREACH(QUrl url, event->mimeData()->urls()) { |
112 | + if (url.scheme() == "file") { |
113 | + event->setDropAction(Qt::MoveAction); |
114 | + event->setAccepted(true); |
115 | + return; |
116 | + } |
117 | + } |
118 | +} |
119 | + |
120 | +void |
121 | +Trash::onDrop(DeclarativeDragDropEvent* event) |
122 | +{ |
123 | + Q_FOREACH(QUrl url, event->mimeData()->urls()) { |
124 | + if (url.scheme() == "file") { |
125 | + GFile* file = g_file_new_for_path(url.toLocalFile().toUtf8().constData()); |
126 | + if (!g_file_trash(file, NULL, NULL)) { |
127 | + qWarning() << "Unable to send" << url << "to the trash"; |
128 | + } |
129 | + g_object_unref(file); |
130 | + } |
131 | + } |
132 | +} |
133 | + |
134 | |
135 | Trashes::Trashes(QObject* parent) : |
136 | QAbstractListModel(parent) |
137 | |
138 | === modified file 'launcher/UnityApplications/trash.h' |
139 | --- launcher/UnityApplications/trash.h 2011-02-10 01:00:41 +0000 |
140 | +++ launcher/UnityApplications/trash.h 2011-02-16 11:14:09 +0000 |
141 | @@ -49,6 +49,12 @@ |
142 | Q_INVOKABLE virtual void activate(); |
143 | Q_INVOKABLE virtual void createMenuActions(); |
144 | |
145 | +public Q_SLOTS: |
146 | + /* Custom implementation of drag’n’drop handling. Dropping files on the |
147 | + trash will… move them to the trash! */ |
148 | + void onDragEnter(DeclarativeDragDropEvent*); |
149 | + void onDrop(DeclarativeDragDropEvent*); |
150 | + |
151 | private slots: |
152 | void onEmptyTriggered(); |
153 | |
154 | |
155 | === modified file 'launcher/app/launcherview.cpp' |
156 | --- launcher/app/launcherview.cpp 2011-02-15 12:06:55 +0000 |
157 | +++ launcher/app/launcherview.cpp 2011-02-16 11:14:09 +0000 |
158 | @@ -28,16 +28,59 @@ |
159 | #include <QDeclarativeEngine> |
160 | #include <QDeclarativeContext> |
161 | #include <QDeclarativeImageProvider> |
162 | +#include <QGraphicsObject> |
163 | +#include <QMetaObject> |
164 | |
165 | #include <X11/Xlib.h> |
166 | #include <X11/Xatom.h> |
167 | |
168 | +#include "dragdropevent.h" |
169 | + |
170 | LauncherView::LauncherView() : |
171 | - QDeclarativeView(), m_resizing(false), m_reserved(false) |
172 | + QDeclarativeView(), m_resizing(false), m_reserved(false), |
173 | + m_dndCurrentLauncherItem(NULL), m_dndCurrentLauncherItemAccepted(false), |
174 | + m_dndAccepted(false) |
175 | { |
176 | setAcceptDrops(true); |
177 | } |
178 | |
179 | +QGraphicsObject* |
180 | +LauncherView::launcherItemAt(const QPoint& pos) const |
181 | +{ |
182 | + QGraphicsItem* item = itemAt(pos); |
183 | + while(item != NULL) { |
184 | + QGraphicsObject* object = qgraphicsitem_cast<QGraphicsObject*>(item); |
185 | + if (object->objectName() == "launcherItem") { |
186 | + return object; |
187 | + } |
188 | + item = item->parentItem(); |
189 | + } |
190 | + return NULL; |
191 | +} |
192 | + |
193 | +void |
194 | +LauncherView::delegateDragEventHandlingToItem(QDropEvent* event, QGraphicsObject* item) |
195 | +{ |
196 | + if (item == NULL) { |
197 | + return; |
198 | + } |
199 | + DeclarativeDragDropEvent dde(event, this); |
200 | + QMetaObject::invokeMethod(item, "dragEnterEvent", |
201 | + Q_ARG(QVariant, QVariant::fromValue(&dde))); |
202 | +} |
203 | + |
204 | +bool |
205 | +LauncherView::acceptDndEvent(QDragEnterEvent* event) |
206 | +{ |
207 | + Q_FOREACH(QUrl url, getEventUrls(event)) { |
208 | + if ((url.scheme() == "file" && url.path().endsWith(".desktop")) || |
209 | + url.scheme().startsWith("http")) { |
210 | + return true; |
211 | + } |
212 | + } |
213 | + return false; |
214 | +} |
215 | + |
216 | QList<QUrl> |
217 | LauncherView::getEventUrls(QDropEvent* event) |
218 | { |
219 | @@ -63,51 +106,62 @@ |
220 | return urls; |
221 | } |
222 | } |
223 | - |
224 | return QList<QUrl>(); |
225 | } |
226 | |
227 | -void LauncherView::dragEnterEvent(QDragEnterEvent *event) |
228 | -{ |
229 | - // Check that data has a list of URLs and that at least one is either |
230 | - // a desktop file or a web page. |
231 | - QList<QUrl> urls = getEventUrls(event); |
232 | - |
233 | - if (urls.isEmpty()) { |
234 | - return; |
235 | - } |
236 | - |
237 | - foreach (QUrl url, urls) { |
238 | - if ((url.scheme() == "file" && url.path().endsWith(".desktop")) || |
239 | - url.scheme().startsWith("http")) { |
240 | - event->acceptProposedAction(); |
241 | - break; |
242 | - } |
243 | - } |
244 | -} |
245 | - |
246 | -void LauncherView::dragMoveEvent(QDragMoveEvent *event) |
247 | -{ |
248 | - event->acceptProposedAction(); |
249 | -} |
250 | - |
251 | -void LauncherView::dropEvent(QDropEvent *event) |
252 | -{ |
253 | - bool accepted = false; |
254 | - |
255 | - QList<QUrl> urls = getEventUrls(event); |
256 | - foreach (QUrl url, urls) { |
257 | - if (url.scheme() == "file" && url.path().endsWith(".desktop")) { |
258 | - emit desktopFileDropped(url.path()); |
259 | - accepted = true; |
260 | - } |
261 | - else if (url.scheme().startsWith("http")) { |
262 | - emit webpageUrlDropped(url); |
263 | - accepted = true; |
264 | - } |
265 | - } |
266 | - |
267 | - if (accepted) event->accept(); |
268 | +void |
269 | +LauncherView::dragEnterEvent(QDragEnterEvent* event) |
270 | +{ |
271 | + m_dndCurrentLauncherItem = NULL; |
272 | + m_dndCurrentLauncherItemAccepted = false; |
273 | + /* Compute whether the launcher itself accepts the event only once for this |
274 | + given event. */ |
275 | + m_dndAccepted = acceptDndEvent(event); |
276 | + /* Always accept the event so that subsequent move events are received. */ |
277 | + event->setAccepted(true); |
278 | +} |
279 | + |
280 | +void |
281 | +LauncherView::dragMoveEvent(QDragMoveEvent* event) |
282 | +{ |
283 | + QGraphicsObject* launcherItem = launcherItemAt(event->pos()); |
284 | + if (launcherItem == m_dndCurrentLauncherItem) { |
285 | + if (m_dndCurrentLauncherItemAccepted || m_dndAccepted) { |
286 | + event->setAccepted(true); |
287 | + } |
288 | + } else { |
289 | + m_dndCurrentLauncherItem = launcherItem; |
290 | + m_dndCurrentLauncherItemAccepted = false; |
291 | + |
292 | + if (m_dndCurrentLauncherItem != NULL) { |
293 | + delegateDragEventHandlingToItem(event, m_dndCurrentLauncherItem); |
294 | + if (event->isAccepted()) { |
295 | + m_dndCurrentLauncherItemAccepted = true; |
296 | + } |
297 | + } else { |
298 | + if (m_dndAccepted) { |
299 | + event->setAccepted(true); |
300 | + } |
301 | + } |
302 | + } |
303 | +} |
304 | + |
305 | +void |
306 | +LauncherView::dropEvent(QDropEvent* event) |
307 | +{ |
308 | + if (m_dndCurrentLauncherItemAccepted) { |
309 | + DeclarativeDragDropEvent dde(event, this); |
310 | + QMetaObject::invokeMethod(m_dndCurrentLauncherItem, "dropEvent", |
311 | + Q_ARG(QVariant, QVariant::fromValue(&dde))); |
312 | + } else if (m_dndAccepted) { |
313 | + Q_FOREACH(QUrl url, getEventUrls(event)) { |
314 | + if (url.scheme() == "file" && url.path().endsWith(".desktop")) { |
315 | + emit desktopFileDropped(url.path()); |
316 | + } else if (url.scheme().startsWith("http")) { |
317 | + emit webpageUrlDropped(url); |
318 | + } |
319 | + } |
320 | + } |
321 | } |
322 | |
323 | /* Calculates both the background color and the glow color of a launcher tile |
324 | |
325 | === modified file 'launcher/app/launcherview.h' |
326 | --- launcher/app/launcherview.h 2011-02-10 16:57:57 +0000 |
327 | +++ launcher/app/launcherview.h 2011-02-16 11:14:09 +0000 |
328 | @@ -22,8 +22,10 @@ |
329 | |
330 | #include <QDeclarativeView> |
331 | #include <QUrl> |
332 | +#include <QList> |
333 | #include <QDragEnterEvent> |
334 | -#include <QList> |
335 | + |
336 | +class QGraphicsObject; |
337 | |
338 | class LauncherView : public QDeclarativeView |
339 | { |
340 | @@ -40,15 +42,27 @@ |
341 | private: |
342 | QList<QUrl> getEventUrls(QDropEvent*); |
343 | |
344 | - void dragEnterEvent(QDragEnterEvent *event); |
345 | - void dropEvent(QDropEvent *event); |
346 | - void dragMoveEvent(QDragMoveEvent *event); |
347 | - |
348 | /* Whether the launcher is already being resized */ |
349 | bool m_resizing; |
350 | |
351 | /* Whether space at the left of the screen has already been reserved */ |
352 | bool m_reserved; |
353 | + |
354 | + /* Custom drag’n’drop handling */ |
355 | + void dragEnterEvent(QDragEnterEvent*); |
356 | + void dragMoveEvent(QDragMoveEvent*); |
357 | + void dropEvent(QDropEvent*); |
358 | + |
359 | + QGraphicsObject* launcherItemAt(const QPoint&) const; |
360 | + void delegateDragEventHandlingToItem(QDropEvent*, QGraphicsObject*); |
361 | + bool acceptDndEvent(QDragEnterEvent*); |
362 | + |
363 | + /* The launcher item currently under the mouse cursor during a dnd event */ |
364 | + QGraphicsObject* m_dndCurrentLauncherItem; |
365 | + /* Whether it accepted the event */ |
366 | + bool m_dndCurrentLauncherItemAccepted; |
367 | + /* Whether the launcher itself handles the current dnd event */ |
368 | + bool m_dndAccepted; |
369 | }; |
370 | |
371 | #endif // LAUNCHERVIEW |
372 | |
373 | === modified file 'libunity-2d-private/Unity2d/CMakeLists.txt' |
374 | --- libunity-2d-private/Unity2d/CMakeLists.txt 2011-02-10 08:40:03 +0000 |
375 | +++ libunity-2d-private/Unity2d/CMakeLists.txt 2011-02-16 11:14:09 +0000 |
376 | @@ -39,6 +39,7 @@ |
377 | ${WNCK_INCLUDE_DIRS} |
378 | ${QTBAMF_INCLUDE_DIRS} |
379 | ${QTGCONF_INCLUDE_DIRS} |
380 | + ${libunity-2d-private_SOURCE_DIR}/src |
381 | ) |
382 | |
383 | target_link_libraries(unity-2d-private-qml |
384 | @@ -48,6 +49,7 @@ |
385 | ${WNCK_LDFLAGS} |
386 | ${QTBAMF_LDFLAGS} |
387 | ${QTGCONF_LDFLAGS} |
388 | + unity-2d-private |
389 | ) |
390 | |
391 | # Install |
392 | |
393 | === modified file 'libunity-2d-private/Unity2d/plugin.cpp' |
394 | --- libunity-2d-private/Unity2d/plugin.cpp 2011-02-08 11:48:16 +0000 |
395 | +++ libunity-2d-private/Unity2d/plugin.cpp 2011-02-16 11:14:09 +0000 |
396 | @@ -32,6 +32,9 @@ |
397 | #include "plugin.h" |
398 | #include "cacheeffect.h" |
399 | |
400 | +#include "mimedata.h" |
401 | +#include "dragdropevent.h" |
402 | + |
403 | #include <QtDeclarative/qdeclarative.h> |
404 | #include <QDeclarativeEngine> |
405 | #include <QDeclarativeContext> |
406 | @@ -66,6 +69,10 @@ |
407 | qmlRegisterType<WorkspacesInfo>(); // Register the type as non creatable |
408 | |
409 | qmlRegisterType<CacheEffect>(uri, 0, 1, "CacheEffect"); |
410 | + |
411 | + /* Custom drag’n’drop implementation in QML */ |
412 | + qmlRegisterType<DeclarativeMimeData>(); |
413 | + qmlRegisterType<DeclarativeDragDropEvent>(); |
414 | } |
415 | |
416 | void Unity2dPlugin::initializeEngine(QDeclarativeEngine *engine, const char *uri) |
417 | |
418 | === modified file 'libunity-2d-private/src/CMakeLists.txt' |
419 | --- libunity-2d-private/src/CMakeLists.txt 2011-02-10 08:40:03 +0000 |
420 | +++ libunity-2d-private/src/CMakeLists.txt 2011-02-16 11:14:09 +0000 |
421 | @@ -4,6 +4,8 @@ |
422 | keyboardmodifiersmonitor.cpp |
423 | unity2dapplication.cpp |
424 | unity2dpanel.cpp |
425 | + mimedata.cpp |
426 | + dragdropevent.cpp |
427 | ) |
428 | |
429 | # Build |
430 | |
431 | === added file 'libunity-2d-private/src/dragdropevent.cpp' |
432 | --- libunity-2d-private/src/dragdropevent.cpp 1970-01-01 00:00:00 +0000 |
433 | +++ libunity-2d-private/src/dragdropevent.cpp 2011-02-16 11:14:09 +0000 |
434 | @@ -0,0 +1,56 @@ |
435 | +/* |
436 | + * Copyright (C) 2011 Canonical, Ltd. |
437 | + * |
438 | + * Authors: |
439 | + * Olivier Tilloy <olivier.tilloy@canonical.com> |
440 | + * |
441 | + * This program is free software; you can redistribute it and/or modify |
442 | + * it under the terms of the GNU General Public License as published by |
443 | + * the Free Software Foundation; version 3. |
444 | + * |
445 | + * This program is distributed in the hope that it will be useful, |
446 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
447 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
448 | + * GNU General Public License for more details. |
449 | + * |
450 | + * You should have received a copy of the GNU General Public License |
451 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
452 | + */ |
453 | + |
454 | +#include "dragdropevent.h" |
455 | + |
456 | +DeclarativeDragDropEvent::DeclarativeDragDropEvent(QDropEvent* event, QObject* parent) |
457 | + : QObject(parent) |
458 | + , m_event(event) |
459 | + , m_mimeData(event->mimeData()) |
460 | +{ |
461 | + /* By default the event is not accepted, let the receiver decide. */ |
462 | + m_event->setAccepted(false); |
463 | +} |
464 | + |
465 | +bool |
466 | +DeclarativeDragDropEvent::accepted() const |
467 | +{ |
468 | + return m_event->isAccepted(); |
469 | +} |
470 | + |
471 | +void |
472 | +DeclarativeDragDropEvent::setAccepted(bool accepted) |
473 | +{ |
474 | + m_event->setAccepted(accepted); |
475 | +} |
476 | + |
477 | +Qt::DropAction |
478 | +DeclarativeDragDropEvent::dropAction() const |
479 | +{ |
480 | + return m_event->dropAction(); |
481 | +} |
482 | + |
483 | +void |
484 | +DeclarativeDragDropEvent::setDropAction(Qt::DropAction action) |
485 | +{ |
486 | + m_event->setDropAction(action); |
487 | +} |
488 | + |
489 | +#include "dragdropevent.moc" |
490 | + |
491 | |
492 | === added file 'libunity-2d-private/src/dragdropevent.h' |
493 | --- libunity-2d-private/src/dragdropevent.h 1970-01-01 00:00:00 +0000 |
494 | +++ libunity-2d-private/src/dragdropevent.h 2011-02-16 11:14:09 +0000 |
495 | @@ -0,0 +1,59 @@ |
496 | +/* |
497 | + * Copyright (C) 2011 Canonical, Ltd. |
498 | + * |
499 | + * Authors: |
500 | + * Olivier Tilloy <olivier.tilloy@canonical.com> |
501 | + * |
502 | + * This program is free software; you can redistribute it and/or modify |
503 | + * it under the terms of the GNU General Public License as published by |
504 | + * the Free Software Foundation; version 3. |
505 | + * |
506 | + * This program is distributed in the hope that it will be useful, |
507 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
508 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
509 | + * GNU General Public License for more details. |
510 | + * |
511 | + * You should have received a copy of the GNU General Public License |
512 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
513 | + */ |
514 | + |
515 | +/* Original ideas for drag’n’drop implementation by Grégory Schlomoff |
516 | + (https://bitbucket.org/gregschlom/qml-drag-drop/). */ |
517 | + |
518 | +#ifndef DeclarativeDragDropEvent_H |
519 | +#define DeclarativeDragDropEvent_H |
520 | + |
521 | +#include "mimedata.h" |
522 | + |
523 | +#include <QtGui/QDropEvent> |
524 | +#include <QtCore/Qt> |
525 | + |
526 | +class DeclarativeDragDropEvent : public QObject |
527 | +{ |
528 | + Q_OBJECT |
529 | + |
530 | + Q_PROPERTY(DeclarativeMimeData* mimeData READ mimeData) |
531 | + Q_PROPERTY(bool accepted READ accepted WRITE setAccepted) |
532 | + Q_PROPERTY(Qt::DropAction dropAction READ dropAction WRITE setDropAction) |
533 | + |
534 | +public: |
535 | + DeclarativeDragDropEvent(QDropEvent* event, QObject* parent=0); |
536 | + |
537 | + /* getters */ |
538 | + DeclarativeMimeData* mimeData() { return &m_mimeData; } |
539 | + bool accepted() const; |
540 | + Qt::DropAction dropAction() const; |
541 | + |
542 | + /* setters */ |
543 | + void setAccepted(bool accepted); |
544 | + void setDropAction(Qt::DropAction action); |
545 | + |
546 | +private: |
547 | + QDropEvent* m_event; |
548 | + DeclarativeMimeData m_mimeData; |
549 | +}; |
550 | + |
551 | +Q_DECLARE_METATYPE(DeclarativeDragDropEvent*) |
552 | + |
553 | +#endif // DeclarativeDragDropEvent |
554 | + |
555 | |
556 | === added file 'libunity-2d-private/src/mimedata.cpp' |
557 | --- libunity-2d-private/src/mimedata.cpp 1970-01-01 00:00:00 +0000 |
558 | +++ libunity-2d-private/src/mimedata.cpp 2011-02-16 11:14:09 +0000 |
559 | @@ -0,0 +1,31 @@ |
560 | +/* |
561 | + * Copyright (C) 2011 Canonical, Ltd. |
562 | + * |
563 | + * Authors: |
564 | + * Olivier Tilloy <olivier.tilloy@canonical.com> |
565 | + * |
566 | + * This program is free software; you can redistribute it and/or modify |
567 | + * it under the terms of the GNU General Public License as published by |
568 | + * the Free Software Foundation; version 3. |
569 | + * |
570 | + * This program is distributed in the hope that it will be useful, |
571 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
572 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
573 | + * GNU General Public License for more details. |
574 | + * |
575 | + * You should have received a copy of the GNU General Public License |
576 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
577 | + */ |
578 | + |
579 | +#include "mimedata.h" |
580 | + |
581 | +DeclarativeMimeData::DeclarativeMimeData(const QMimeData* data) |
582 | + : QMimeData() |
583 | +{ |
584 | + Q_FOREACH(QString format, data->formats()) { |
585 | + setData(format, data->data(format)); |
586 | + } |
587 | +} |
588 | + |
589 | +#include "mimedata.moc" |
590 | + |
591 | |
592 | === added file 'libunity-2d-private/src/mimedata.h' |
593 | --- libunity-2d-private/src/mimedata.h 1970-01-01 00:00:00 +0000 |
594 | +++ libunity-2d-private/src/mimedata.h 2011-02-16 11:14:09 +0000 |
595 | @@ -0,0 +1,48 @@ |
596 | +/* |
597 | + * Copyright (C) 2011 Canonical, Ltd. |
598 | + * |
599 | + * Authors: |
600 | + * Olivier Tilloy <olivier.tilloy@canonical.com> |
601 | + * |
602 | + * This program is free software; you can redistribute it and/or modify |
603 | + * it under the terms of the GNU General Public License as published by |
604 | + * the Free Software Foundation; version 3. |
605 | + * |
606 | + * This program is distributed in the hope that it will be useful, |
607 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
608 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
609 | + * GNU General Public License for more details. |
610 | + * |
611 | + * You should have received a copy of the GNU General Public License |
612 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
613 | + */ |
614 | + |
615 | +/* Original ideas for drag’n’drop implementation by Grégory Schlomoff |
616 | + (https://bitbucket.org/gregschlom/qml-drag-drop/). */ |
617 | + |
618 | +#ifndef DeclarativeMimeData_H |
619 | +#define DeclarativeMimeData_H |
620 | + |
621 | +#include <QtCore/QMimeData> |
622 | +#include <QtCore/QStringList> |
623 | +#include <QtCore/QString> |
624 | +#include <QtCore/QList> |
625 | +#include <QtCore/QUrl> |
626 | + |
627 | +class DeclarativeMimeData : public QMimeData |
628 | +{ |
629 | + Q_OBJECT |
630 | + |
631 | + Q_PROPERTY(QStringList formats READ formats) |
632 | + Q_PROPERTY(QString text READ text) |
633 | + Q_PROPERTY(QString html READ html) |
634 | + Q_PROPERTY(QList<QUrl> urls READ urls) |
635 | + |
636 | +public: |
637 | + DeclarativeMimeData(const QMimeData* data); |
638 | +}; |
639 | + |
640 | +Q_DECLARE_METATYPE(DeclarativeMimeData*) |
641 | + |
642 | +#endif // DeclarativeMimeData |
643 | + |
# Functional
It works well, but the cursor behavior is a bit weird. If I drag a file from Dolphin to the trash, I get the correct "Move" cursor, but if I drag it from Nautilus I get the "Copy" action. Not sure what is wrong here. Maybe Nautilus does not put "Move" in the proposed actions?
# Code
90 + DropEvent* , but because bugreports. qt.nokia. com/browse/ QTBUG-13047 they need to be QObject* event);
91 +public Q_SLOTS:
92 + /* Default implementation of drag’n’drop handling, should be overridden in
93 + subclasses to implement custom behaviours. */
94 + /* The 'event' parameters should be DeclarativeDrag
95 + of http://
96 + passed around from QML to C++ as QObject*. This is fixed in Qt 4.7.1. */
97 + virtual void onDragEnter(
98 + virtual void onDrop(QObject* event);
We ship Qt 4.7.1 in Natty, so you should already be able to use DeclarativeDrag DropEvent* instead of QObject*.
I think you don't need to call setAccepted() in drop methods (onDrop() or dropEvent()). It only matters in drag methods (onDragEnter(), dragEnterEvent(), ondragMove(), dragMoveEvent()).
From what I understand, the dnd events are received in the C++ side, then forwarded to the QML side, which forwards them again back to C++. Which raise a question: is it necessary at all to go through QML?
Usual nitpick: "}\nelse {" => "} else {" :)