|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the documentation of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 /*! |
|
43 \group draganddrop |
|
44 \title Drag And Drop Classes |
|
45 |
|
46 \brief Classes dealing with drag and drop and mime type encoding and decoding. |
|
47 */ |
|
48 |
|
49 /*! |
|
50 \page dnd.html |
|
51 \title Drag and Drop |
|
52 \brief An overview of the drag and drop system provided by Qt. |
|
53 |
|
54 \ingroup frameworks-technologies |
|
55 |
|
56 Drag and drop provides a simple visual mechanism which users can use |
|
57 to transfer information between and within applications. (In the |
|
58 literature this is referred to as a "direct manipulation model".) Drag |
|
59 and drop is similar in function to the clipboard's cut and paste |
|
60 mechanism. |
|
61 |
|
62 \tableofcontents |
|
63 |
|
64 This document describes the basic drag and drop mechanism and |
|
65 outlines the approach used to enable it in custom widgets. Drag |
|
66 and drop operations are also supported by Qt's item views and by |
|
67 the graphics view framework; more information is available in the |
|
68 \l{Using Drag and Drop with Item Views} and \l{The Graphics View |
|
69 Framework} documents. |
|
70 |
|
71 \section1 Drag and Drop Classes |
|
72 |
|
73 These classes deal with drag and drop and the necessary mime type |
|
74 encoding and decoding. |
|
75 |
|
76 \annotatedlist draganddrop |
|
77 |
|
78 \section1 Configuration |
|
79 |
|
80 The QApplication object provides some properties that are related |
|
81 to drag and drop operations: |
|
82 |
|
83 \list |
|
84 \i \l{QApplication::startDragTime} describes the amount of time in |
|
85 milliseconds that the user must hold down a mouse button over an |
|
86 object before a drag will begin. |
|
87 \i \l{QApplication::startDragDistance} indicates how far the user has to |
|
88 move the mouse while holding down a mouse button before the movement |
|
89 will be interpreted as dragging. Use of high values for this quantity |
|
90 prevents accidental dragging when the user only meant to click on an |
|
91 object. |
|
92 \endlist |
|
93 |
|
94 These quantities provide sensible default values for you to use if you |
|
95 provide drag and drop support in your widgets. |
|
96 |
|
97 \section1 Dragging |
|
98 |
|
99 To start a drag, create a QDrag object, and call its |
|
100 exec() function. In most applications, it is a good idea to begin a drag |
|
101 and drop operation only after a mouse button has been pressed and the |
|
102 cursor has been moved a certain distance. However, the simplest way to |
|
103 enable dragging from a widget is to reimplement the widget's |
|
104 \l{QWidget::mousePressEvent()}{mousePressEvent()} and start a drag |
|
105 and drop operation: |
|
106 |
|
107 \snippet doc/src/snippets/dragging/mainwindow.cpp 0 |
|
108 \dots 8 |
|
109 \snippet doc/src/snippets/dragging/mainwindow.cpp 2 |
|
110 |
|
111 Although the user may take some time to complete the dragging operation, |
|
112 as far as the application is concerned the exec() function is a blocking |
|
113 function that returns with \l{Qt::DropActions}{one of several values}. |
|
114 These indicate how the operation ended, and are described in more detail |
|
115 below. |
|
116 |
|
117 Note that the exec() function does not block the main event loop. |
|
118 |
|
119 For widgets that need to distinguish between mouse clicks and drags, it |
|
120 is useful to reimplement the widget's |
|
121 \l{QWidget::mousePressEvent()}{mousePressEvent()} function to record to |
|
122 start position of the drag: |
|
123 |
|
124 \snippet doc/src/snippets/draganddrop/dragwidget.cpp 6 |
|
125 |
|
126 Later, in \l{QWidget::mouseMoveEvent()}{mouseMoveEvent()}, we can determine |
|
127 whether a drag should begin, and construct a drag object to handle the |
|
128 operation: |
|
129 |
|
130 \snippet doc/src/snippets/draganddrop/dragwidget.cpp 7 |
|
131 \dots |
|
132 \snippet doc/src/snippets/draganddrop/dragwidget.cpp 8 |
|
133 |
|
134 This particular approach uses the \l QPoint::manhattanLength() function |
|
135 to get a rough estimate of the distance between where the mouse click |
|
136 occurred and the current cursor position. This function trades accuracy |
|
137 for speed, and is usually suitable for this purpose. |
|
138 |
|
139 \section1 Dropping |
|
140 |
|
141 To be able to receive media dropped on a widget, call |
|
142 \l{QWidget::setAcceptDrops()}{setAcceptDrops(true)} for the widget, |
|
143 and reimplement the \l{QWidget::dragEnterEvent()}{dragEnterEvent()} and |
|
144 \l{QWidget::dropEvent()}{dropEvent()} event handler functions. |
|
145 |
|
146 For example, the following code enables drop events in the constructor of |
|
147 a QWidget subclass, making it possible to usefully implement drop event |
|
148 handlers: |
|
149 |
|
150 \snippet doc/src/snippets/dropevents/window.cpp 0 |
|
151 \dots |
|
152 \snippet doc/src/snippets/dropevents/window.cpp 1 |
|
153 \snippet doc/src/snippets/dropevents/window.cpp 2 |
|
154 |
|
155 The dragEnterEvent() function is typically used to inform Qt about the |
|
156 types of data that the widget accepts. |
|
157 You must reimplement this function if you want to receive either |
|
158 QDragMoveEvent or QDropEvent in your reimplementations of |
|
159 \l{QWidget::dragMoveEvent()}{dragMoveEvent()} and |
|
160 \l{QWidget::dropEvent()}{dropEvent()}. |
|
161 |
|
162 The following code shows how \l{QWidget::dragEnterEvent()}{dragEnterEvent()} |
|
163 can be reimplemented to |
|
164 tell the drag and drop system that we can only handle plain text: |
|
165 |
|
166 \snippet doc/src/snippets/dropevents/window.cpp 3 |
|
167 |
|
168 The \l{QWidget::dropEvent()}{dropEvent()} is used to unpack dropped data |
|
169 and handle it in way that is suitable for your application. |
|
170 |
|
171 In the following code, the text supplied in the event is passed to a |
|
172 QTextBrowser and a QComboBox is filled with the list of MIME types that |
|
173 are used to describe the data: |
|
174 |
|
175 \snippet doc/src/snippets/dropevents/window.cpp 4 |
|
176 |
|
177 In this case, we accept the proposed action without checking what it is. |
|
178 In a real world application, it may be necessary to return from the |
|
179 \l{QWidget::dropEvent()}{dropEvent()} function without accepting the |
|
180 proposed action or handling |
|
181 the data if the action is not relevant. For example, we may choose to |
|
182 ignore Qt::LinkAction actions if we do not support |
|
183 links to external sources in our application. |
|
184 |
|
185 \section2 Overriding Proposed Actions |
|
186 |
|
187 We may also ignore the proposed action, and perform some other action on |
|
188 the data. To do this, we would call the event object's |
|
189 \l{QDropEvent::setDropAction()}{setDropAction()} with the preferred |
|
190 action from Qt::DropAction before calling \l{QEvent::}{accept()}. |
|
191 This ensures that the replacement drop action is used instead of the |
|
192 proposed action. |
|
193 |
|
194 For more sophisticated applications, reimplementing |
|
195 \l{QWidget::dragMoveEvent()}{dragMoveEvent()} and |
|
196 \l{QWidget::dragLeaveEvent()}{dragLeaveEvent()} will let you make |
|
197 certain parts of your widgets sensitive to drop events, and give you more |
|
198 control over drag and drop in your application. |
|
199 |
|
200 \section2 Subclassing Complex Widgets |
|
201 |
|
202 Certain standard Qt widgets provide their own support for drag and drop. |
|
203 When subclassing these widgets, it may be necessary to reimplement |
|
204 \l{QWidget::dragMoveEvent()}{dragMoveEvent()} in addition to |
|
205 \l{QWidget::dragEnterEvent()}{dragEnterEvent()} and |
|
206 \l{QWidget::dropEvent()}{dropEvent()} to prevent the base class from |
|
207 providing default drag and drop handling, and to handle any special |
|
208 cases you are interested in. |
|
209 |
|
210 \section1 Drag and Drop Actions |
|
211 |
|
212 In the simplest case, the target of a drag and drop action receives a |
|
213 copy of the data being dragged, and the source decides whether to |
|
214 delete the original. This is described by the \c CopyAction action. |
|
215 The target may also choose to handle other actions, specifically the |
|
216 \c MoveAction and \c LinkAction actions. If the source calls |
|
217 QDrag::exec(), and it returns \c MoveAction, the source is responsible |
|
218 for deleting any original data if it chooses to do so. The QMimeData |
|
219 and QDrag objects created by the source widget \e{should not be deleted} |
|
220 - they will be destroyed by Qt. The target is responsible for taking |
|
221 ownership of the data sent in the drag and drop operation; this is |
|
222 usually done by keeping references to the data. |
|
223 |
|
224 If the target understands the \c LinkAction action, it should |
|
225 store its own reference to the original information; the source |
|
226 does not need to perform any further processing on the data. The |
|
227 most common use of drag and drop actions is when performing a |
|
228 Move within the same widget; see the section on \l{Drop Actions} |
|
229 for more information about this feature. |
|
230 |
|
231 The other major use of drag actions is when using a reference type |
|
232 such as text/uri-list, where the dragged data are actually references |
|
233 to files or objects. |
|
234 |
|
235 \section1 Adding New Drag and Drop Types |
|
236 |
|
237 Drag and drop is not limited to text and images. Any type of information |
|
238 can be transferred in a drag and drop operation. To drag information |
|
239 between applications, the applications must be able to indicate to each |
|
240 other which data formats they can accept and which they can produce. |
|
241 This is achieved using |
|
242 \l{http://www.rfc-editor.org/rfc/rfc1341.txt}{MIME types}. The QDrag |
|
243 object constructed by the source contains a list of MIME types that it |
|
244 uses to represent the data (ordered from most appropriate to least |
|
245 appropriate), and the drop target uses one of these to access the data. |
|
246 For common data types, the convenience functions handle the MIME types |
|
247 used transparently but, for custom data types, it is necessary to |
|
248 state them explicitly. |
|
249 |
|
250 To implement drag and drop actions for a type of information that is |
|
251 not covered by the QDrag convenience functions, the first and most |
|
252 important step is to look for existing formats that are appropriate: |
|
253 The Internet Assigned Numbers Authority (\l{http://www.iana.org}{IANA}) |
|
254 provides a |
|
255 \l{http://www.iana.org/assignments/media-types/}{hierarchical |
|
256 list of MIME media types} at the Information Sciences Institute |
|
257 (\l{http://www.isi.edu}{ISI}). |
|
258 Using standard MIME types maximizes the interoperability of |
|
259 your application with other software now and in the future. |
|
260 |
|
261 To support an additional media type, simply set the data in the QMimeData |
|
262 object with the \l{QMimeData::setData()}{setData()} function, supplying |
|
263 the full MIME type and a QByteArray containing the data in the appropriate |
|
264 format. The following code takes a pixmap from a label and stores it |
|
265 as a Portable Network Graphics (PNG) file in a QMimeData object: |
|
266 |
|
267 \snippet doc/src/snippets/separations/finalwidget.cpp 0 |
|
268 |
|
269 Of course, for this case we could have simply used |
|
270 \l{QMimeData::setImageData()}{setImageData()} instead to supply image data |
|
271 in a variety of formats: |
|
272 |
|
273 \snippet doc/src/snippets/separations/finalwidget.cpp 1 |
|
274 |
|
275 The QByteArray approach is still useful in this case because it provides |
|
276 greater control over the amount of data stored in the QMimeData object. |
|
277 |
|
278 Note that custom datatypes used in item views must be declared as |
|
279 \l{QMetaObject}{meta objects} and that stream operators for them |
|
280 must be implemented. |
|
281 |
|
282 \section1 Drop Actions |
|
283 |
|
284 In the clipboard model, the user can \e cut or \e copy the source |
|
285 information, then later paste it. Similarly in the drag and drop |
|
286 model, the user can drag a \e copy of the information or they can drag |
|
287 the information itself to a new place (\e moving it). The |
|
288 drag and drop model has an additional complication for the programmer: |
|
289 The program doesn't know whether the user wants to cut or copy the |
|
290 information until the operation is complete. This often makes no |
|
291 difference when dragging information between applications, but within |
|
292 an application it is important to check which drop action was used. |
|
293 |
|
294 We can reimplement the mouseMoveEvent() for a widget, and start a drag |
|
295 and drop operation with a combination of possible drop actions. For |
|
296 example, we may want to ensure that dragging always moves objects in |
|
297 the widget: |
|
298 |
|
299 \snippet doc/src/snippets/draganddrop/dragwidget.cpp 7 |
|
300 \dots |
|
301 \snippet doc/src/snippets/draganddrop/dragwidget.cpp 8 |
|
302 |
|
303 The action returned by the exec() function may default to a |
|
304 \c CopyAction if the information is dropped into another application |
|
305 but, if it is dropped in another widget in the same application, we |
|
306 may obtain a different drop action. |
|
307 |
|
308 The proposed drop actions can be filtered in a widget's dragMoveEvent() |
|
309 function. However, it is possible to accept all proposed actions in |
|
310 the dragEnterEvent() and let the user decide which they want to accept |
|
311 later: |
|
312 |
|
313 \snippet doc/src/snippets/draganddrop/dragwidget.cpp 0 |
|
314 |
|
315 When a drop occurs in the widget, the dropEvent() handler function is |
|
316 called, and we can deal with each possible action in turn. First, we |
|
317 deal with drag and drop operations within the same widget: |
|
318 |
|
319 \snippet doc/src/snippets/draganddrop/dragwidget.cpp 1 |
|
320 |
|
321 In this case, we refuse to deal with move operations. Each type of drop |
|
322 action that we accept is checked and dealt with accordingly: |
|
323 |
|
324 \snippet doc/src/snippets/draganddrop/dragwidget.cpp 2 |
|
325 \snippet doc/src/snippets/draganddrop/dragwidget.cpp 3 |
|
326 \snippet doc/src/snippets/draganddrop/dragwidget.cpp 4 |
|
327 \dots |
|
328 \snippet doc/src/snippets/draganddrop/dragwidget.cpp 5 |
|
329 |
|
330 Note that we checked for individual drop actions in the above code. |
|
331 As mentioned above in the section on |
|
332 \l{#Overriding Proposed Actions}{Overriding Proposed Actions}, it is |
|
333 sometimes necessary to override the proposed drop action and choose a |
|
334 different one from the selection of possible drop actions. |
|
335 To do this, you need to check for the presence of each action in the value |
|
336 supplied by the event's \l{QDropEvent::}{possibleActions()}, set the drop |
|
337 action with \l{QDropEvent::}{setDropAction()}, and call |
|
338 \l{QEvent::}{accept()}. |
|
339 |
|
340 \section1 Drop Rectangles |
|
341 |
|
342 The widget's dragMoveEvent() can be used to restrict drops to certain parts |
|
343 of the widget by only accepting the proposed drop actions when the cursor |
|
344 is within those areas. For example, the following code accepts any proposed |
|
345 drop actions when the cursor is over a child widget (\c dropFrame): |
|
346 |
|
347 \snippet doc/src/snippets/droprectangle/window.cpp 0 |
|
348 |
|
349 The dragMoveEvent() can also be used if you need to give visual |
|
350 feedback during a drag and drop operation, to scroll the window, or |
|
351 whatever is appropriate. |
|
352 |
|
353 \section1 The Clipboard |
|
354 |
|
355 Applications can also communicate with each other by putting data on |
|
356 the clipboard. To access this, you need to obtain a QClipboard object |
|
357 from the QApplication object: |
|
358 |
|
359 \snippet examples/widgets/charactermap/mainwindow.cpp 3 |
|
360 |
|
361 The QMimeData class is used to represent data that is transferred to and |
|
362 from the clipboard. To put data on the clipboard, you can use the |
|
363 setText(), setImage(), and setPixmap() convenience functions for common |
|
364 data types. These functions are similar to those found in the QMimeData |
|
365 class, except that they also take an additional argument that controls |
|
366 where the data is stored: If \l{QClipboard::Mode}{Clipboard} is |
|
367 specified, the data is placed on the clipboard; if |
|
368 \l{QClipboard::Mode}{Selection} is specified, the data is placed in the |
|
369 mouse selection (on X11 only). By default, data is put on the clipboard. |
|
370 |
|
371 For example, we can copy the contents of a QLineEdit to the clipboard |
|
372 with the following code: |
|
373 |
|
374 \snippet examples/widgets/charactermap/mainwindow.cpp 11 |
|
375 |
|
376 Data with different MIME types can also be put on the clipboard. |
|
377 Construct a QMimeData object and set data with setData() function in |
|
378 the way described in the previous section; this object can then be |
|
379 put on the clipboard with the |
|
380 \l{QClipboard::setMimeData()}{setMimeData()} function. |
|
381 |
|
382 The QClipboard class can notify the application about changes to the |
|
383 data it contains via its \l{QClipboard::dataChanged()}{dataChanged()} |
|
384 signal. For example, we can monitor the clipboard by connecting this |
|
385 signal to a slot in a widget: |
|
386 |
|
387 \snippet doc/src/snippets/clipboard/clipwindow.cpp 0 |
|
388 |
|
389 The slot connected to this signal can read the data on the clipboard |
|
390 using one of the MIME types that can be used to represent it: |
|
391 |
|
392 \snippet doc/src/snippets/clipboard/clipwindow.cpp 1 |
|
393 \dots |
|
394 \snippet doc/src/snippets/clipboard/clipwindow.cpp 2 |
|
395 |
|
396 The \l{QClipboard::selectionChanged()}{selectionChanged()} signal can |
|
397 be used on X11 to monitor the mouse selection. |
|
398 |
|
399 \section1 Examples |
|
400 |
|
401 \list |
|
402 \o \l{draganddrop/draggableicons}{Draggable Icons} |
|
403 \o \l{draganddrop/draggabletext}{Draggable Text} |
|
404 \o \l{draganddrop/dropsite}{Drop Site} |
|
405 \o \l{draganddrop/fridgemagnets}{Fridge Magnets} |
|
406 \o \l{draganddrop/puzzle}{Drag and Drop Puzzle} |
|
407 \endlist |
|
408 |
|
409 \section1 Interoperating with Other Applications |
|
410 |
|
411 On X11, the public \l{http://www.newplanetsoftware.com/xdnd/}{XDND |
|
412 protocol} is used, while on Windows Qt uses the OLE standard, and |
|
413 Qt for Mac OS X uses the Carbon Drag Manager. On X11, XDND uses MIME, |
|
414 so no translation is necessary. The Qt API is the same regardless of |
|
415 the platform. On Windows, MIME-aware applications can communicate by |
|
416 using clipboard format names that are MIME types. Already some |
|
417 Windows applications use MIME naming conventions for their |
|
418 clipboard formats. Internally, Qt uses QWindowsMime and |
|
419 QMacPasteboardMime for translating proprietary clipboard formats |
|
420 to and from MIME types. |
|
421 |
|
422 On X11, Qt also supports drops via the Motif Drag & Drop Protocol. The |
|
423 implementation incorporates some code that was originally written by |
|
424 Daniel Dardailler, and adapted for Qt by Matt Koss <koss@napri.sk> |
|
425 and Nokia. Here is the original copyright notice: |
|
426 |
|
427 \legalese |
|
428 Copyright 1996 Daniel Dardailler. |
|
429 |
|
430 Permission to use, copy, modify, distribute, and sell this software |
|
431 for any purpose is hereby granted without fee, provided that the above |
|
432 copyright notice appear in all copies and that both that copyright |
|
433 notice and this permission notice appear in supporting documentation, |
|
434 and that the name of Daniel Dardailler not be used in advertising or |
|
435 publicity pertaining to distribution of the software without specific, |
|
436 written prior permission. Daniel Dardailler makes no representations |
|
437 about the suitability of this software for any purpose. It is |
|
438 provided "as is" without express or implied warranty. |
|
439 |
|
440 Modifications Copyright 1999 Matt Koss, under the same license as |
|
441 above. |
|
442 \endlegalese |
|
443 \omit NOTE: The copyright notice is from qmotifdnd_x11.cpp. \endomit |
|
444 |
|
445 Note: The Motif Drag \& Drop Protocol only allows receivers to |
|
446 request data in response to a QDropEvent. If you attempt to |
|
447 request data in response to e.g. a QDragMoveEvent, an empty |
|
448 QByteArray is returned. |
|
449 */ |