source: trunk/doc/src/dnd.qdoc@ 321

Last change on this file since 321 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

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