Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
dnd.qdoc
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
3
4/*!
5 \keyword Drag and Drop in Qt
6 \page dnd.html
7 \title Drag and Drop
8 \brief An overview of the drag and drop system provided by Qt.
9
10 \ingroup qt-gui-concepts
11
12 Drag and drop provides a simple visual mechanism which users can use
13 to transfer information between and within applications. Drag
14 and drop is similar in function to the clipboard's cut and paste
15 mechanism.
16
17 This document describes the basic drag and drop mechanism and
18 outlines the approach used to enable it in custom controls. Drag
19 and drop operations are also supported by many of Qt's controls,
20 such as the item views and graphics view framework, as well as
21 editing controls for Qt Widgets and Qt Quick. More information
22 about item views and graphics view is available in
23 \l{Using drag and drop with item views} and \l{Graphics View
24 Framework}.
25
26 \section1 Drag and Drop Classes
27
28 These classes deal with drag and drop and the necessary mime type
29 encoding and decoding.
30
31 \annotatedlist draganddrop
32
33 \section1 Configuration
34
35 The QStyleHints object provides some properties that are related
36 to drag and drop operations:
37
38 \list
39 \li \l{QStyleHints::startDragTime()} describes the amount of time in
40 milliseconds that the user must hold down a mouse button over an
41 object before a drag will begin.
42 \li \l{QStyleHints::startDragDistance()} indicates how far the user has to
43 move the mouse while holding down a mouse button before the movement
44 will be interpreted as dragging.
45 \li \l{QStyleHints::startDragVelocity()} indicates how fast (in pixels/second)
46 the user has to move the mouse to start a drag. A value of \c 0 means
47 that there is no such limit.
48 \endlist
49
50 These quantities provide sensible default values that are compliant with
51 the underlying windowing system for you to use if you
52 provide drag and drop support in your controls.
53
54 \section1 Drag and Drop in Qt Quick
55
56 The rest of the document focuses mainly on how to implement drag and drop
57 in C++. For using drag and drop inside a Qt Quick scene, please read the
58 documentation for the Qt Quick \l{Drag}, \l{DragEvent}, and \l{DropArea} items,
59 as well as the \l {Qt Quick Examples - Drag and Drop}{Qt Quick Drag and Drop} examples.
60
61 \section1 Dragging
62
63 To start a drag, create a QDrag object, and call its
64 exec() function. In most applications, it is a good idea to begin a drag
65 and drop operation only after a mouse button has been pressed and the
66 cursor has been moved a certain distance. However, the simplest way to
67 enable dragging from a widget is to reimplement the widget's
68 \l{QWidget::mousePressEvent()}{mousePressEvent()} and start a drag
69 and drop operation:
70
71 \snippet dragging/mainwindow.cpp 0
72 \dots 8
73 \snippet dragging/mainwindow.cpp 2
74
75 Although the user may take some time to complete the dragging operation,
76 as far as the application is concerned the exec() function is a blocking
77 function that returns with \l{Qt::DropActions}{one of several values}.
78 These indicate how the operation ended, and are described in more detail
79 below.
80
81 Note that the exec() function does not block the main event loop.
82
83 For widgets that need to distinguish between mouse clicks and drags, it
84 is useful to reimplement the widget's
85 \l{QWidget::mousePressEvent()}{mousePressEvent()} function to record to
86 start position of the drag:
87
88 \snippet draganddrop/dragwidget.cpp 6
89
90 Later, in \l{QWidget::mouseMoveEvent()}{mouseMoveEvent()}, we can determine
91 whether a drag should begin, and construct a drag object to handle the
92 operation:
93
94 \snippet draganddrop/dragwidget.cpp 7
95 \dots
96 \snippet draganddrop/dragwidget.cpp 8
97
98 This particular approach uses the \l QPoint::manhattanLength() function
99 to get a rough estimate of the distance between where the mouse click
100 occurred and the current cursor position. This function trades accuracy
101 for speed, and is usually suitable for this purpose.
102
103 \section1 Dropping
104
105 To be able to receive media dropped on a widget, call
106 \l{QWidget::setAcceptDrops()}{setAcceptDrops(true)} for the widget,
107 and reimplement the \l{QWidget::dragEnterEvent()}{dragEnterEvent()} and
108 \l{QWidget::dropEvent()}{dropEvent()} event handler functions.
109
110 For example, the following code enables drop events in the constructor of
111 a QWidget subclass, making it possible to usefully implement drop event
112 handlers:
113
114 \snippet dropevents/window.cpp 0
115 \dots
116 \snippet dropevents/window.cpp 1
117 \snippet dropevents/window.cpp 2
118
119 The dragEnterEvent() function is typically used to inform Qt about the
120 types of data that the widget accepts.
121 You must reimplement this function if you want to receive either
122 QDragMoveEvent or QDropEvent in your reimplementations of
123 \l{QWidget::dragMoveEvent()}{dragMoveEvent()} and
124 \l{QWidget::dropEvent()}{dropEvent()}.
125
126 The following code shows how \l{QWidget::dragEnterEvent()}{dragEnterEvent()}
127 can be reimplemented to
128 tell the drag and drop system that we can only handle plain text:
129
130 \snippet dropevents/window.cpp 3
131
132 The \l{QWidget::dropEvent()}{dropEvent()} is used to unpack dropped data
133 and handle it in way that is suitable for your application.
134
135 In the following code, the text supplied in the event is passed to a
136 QTextBrowser and a QComboBox is filled with the list of MIME types that
137 are used to describe the data:
138
139 \snippet dropevents/window.cpp 4
140
141 In this case, we accept the proposed action without checking what it is.
142 In a real world application, it may be necessary to return from the
143 \l{QWidget::dropEvent()}{dropEvent()} function without accepting the
144 proposed action or handling
145 the data if the action is not relevant. For example, we may choose to
146 ignore Qt::LinkAction actions if we do not support
147 links to external sources in our application.
148
149 \section2 Overriding Proposed Actions
150
151 We may also ignore the proposed action, and perform some other action on
152 the data. To do this, we would call the event object's
153 \l{QDropEvent::setDropAction()}{setDropAction()} with the preferred
154 action from Qt::DropAction before calling \l{QEvent::}{accept()}.
155 This ensures that the replacement drop action is used instead of the
156 proposed action.
157
158 For more sophisticated applications, reimplementing
159 \l{QWidget::dragMoveEvent()}{dragMoveEvent()} and
160 \l{QWidget::dragLeaveEvent()}{dragLeaveEvent()} will let you make
161 certain parts of your widgets sensitive to drop events, and give you more
162 control over drag and drop in your application.
163
164 \section2 Subclassing Complex Widgets
165
166 Certain standard Qt widgets provide their own support for drag and drop.
167 When subclassing these widgets, it may be necessary to reimplement
168 \l{QWidget::dragMoveEvent()}{dragMoveEvent()} in addition to
169 \l{QWidget::dragEnterEvent()}{dragEnterEvent()} and
170 \l{QWidget::dropEvent()}{dropEvent()} to prevent the base class from
171 providing default drag and drop handling, and to handle any special
172 cases you are interested in.
173
174 \section1 Drag and Drop Actions
175
176 In the simplest case, the target of a drag and drop action receives a
177 copy of the data being dragged, and the source decides whether to
178 delete the original. This is described by the \c CopyAction action.
179 The target may also choose to handle other actions, specifically the
180 \c MoveAction and \c LinkAction actions. If the source calls
181 QDrag::exec(), and it returns \c MoveAction, the source is responsible
182 for deleting any original data if it chooses to do so. The QMimeData
183 and QDrag objects created by the source widget \e{should not be deleted}
184 - they will be destroyed by Qt. The target is responsible for taking
185 ownership of the data sent in the drag and drop operation; this is
186 usually done by keeping references to the data.
187
188 If the target understands the \c LinkAction action, it should
189 store its own reference to the original information; the source
190 does not need to perform any further processing on the data. The
191 most common use of drag and drop actions is when performing a
192 Move within the same widget; see the section on \l{Drop Actions}
193 for more information about this feature.
194
195 The other major use of drag actions is when using a reference type
196 such as text/uri-list, where the dragged data are actually references
197 to files or objects.
198
199 \section1 Adding New Drag and Drop Types
200
201 Drag and drop is not limited to text and images. Any type of information
202 can be transferred in a drag and drop operation. To drag information
203 between applications, the applications must be able to indicate to each
204 other which data formats they can accept and which they can produce.
205 This is achieved using
206 \l{http://www.rfc-editor.org/rfc/rfc1341.txt}{MIME types}. The QDrag
207 object constructed by the source contains a list of MIME types that it
208 uses to represent the data (ordered from most appropriate to least
209 appropriate), and the drop target uses one of these to access the data.
210 For common data types, the convenience functions handle the MIME types
211 used transparently but, for custom data types, it is necessary to
212 state them explicitly.
213
214 To implement drag and drop actions for a type of information that is
215 not covered by the QDrag convenience functions, the first and most
216 important step is to look for existing formats that are appropriate:
217 The Internet Assigned Numbers Authority (\l{http://www.iana.org}{IANA})
218 provides a
219 \l{http://www.iana.org/assignments/media-types/}{hierarchical
220 list of MIME media types} at the Information Sciences Institute
221 (\l{http://www.isi.edu}{ISI}).
222 Using standard MIME types maximizes the interoperability of
223 your application with other software now and in the future.
224
225 To support an additional media type, simply set the data in the QMimeData
226 object with the \l{QMimeData::setData()}{setData()} function, supplying
227 the full MIME type and a QByteArray containing the data in the appropriate
228 format. The following code takes a pixmap from a label and stores it
229 as a Portable Network Graphics (PNG) file in a QMimeData object:
230
231 \snippet separations/finalwidget.cpp 0
232
233 Of course, for this case we could have simply used
234 \l{QMimeData::setImageData()}{setImageData()} instead to supply image data
235 in a variety of formats:
236
237 \snippet separations/finalwidget.cpp 1
238
239 The QByteArray approach is still useful in this case because it provides
240 greater control over the amount of data stored in the QMimeData object.
241
242 Note that custom datatypes used in item views must be declared as
243 \l{QMetaObject}{meta objects} and that stream operators for them
244 must be implemented.
245
246 \section1 Drop Actions
247
248 In the clipboard model, the user can \e cut or \e copy the source
249 information, then later paste it. Similarly in the drag and drop
250 model, the user can drag a \e copy of the information or they can drag
251 the information itself to a new place (\e moving it). The
252 drag and drop model has an additional complication for the programmer:
253 The program doesn't know whether the user wants to cut or copy the
254 information until the operation is complete. This often makes no
255 difference when dragging information between applications, but within
256 an application it is important to check which drop action was used.
257
258 We can reimplement the mouseMoveEvent() for a widget, and start a drag
259 and drop operation with a combination of possible drop actions. For
260 example, we may want to ensure that dragging always moves objects in
261 the widget:
262
263 \snippet draganddrop/dragwidget.cpp 7
264 \dots
265 \snippet draganddrop/dragwidget.cpp 8
266
267 The action returned by the exec() function may default to a
268 \c CopyAction if the information is dropped into another application
269 but, if it is dropped in another widget in the same application, we
270 may obtain a different drop action.
271
272 The proposed drop actions can be filtered in a widget's dragMoveEvent()
273 function. However, it is possible to accept all proposed actions in
274 the dragEnterEvent() and let the user decide which they want to accept
275 later:
276
277 \snippet draganddrop/dragwidget.cpp 0
278
279 When a drop occurs in the widget, the dropEvent() handler function is
280 called, and we can deal with each possible action in turn. First, we
281 deal with drag and drop operations within the same widget:
282
283 \snippet draganddrop/dragwidget.cpp 1
284
285 In this case, we refuse to deal with move operations. Each type of drop
286 action that we accept is checked and dealt with accordingly:
287
288 \snippet draganddrop/dragwidget.cpp 2
289 \snippet draganddrop/dragwidget.cpp 3
290 \snippet draganddrop/dragwidget.cpp 4
291 \dots
292 \snippet draganddrop/dragwidget.cpp 5
293
294 Note that we checked for individual drop actions in the above code.
295 As mentioned above in the section on
296 \l{#Overriding Proposed Actions}{Overriding Proposed Actions}, it is
297 sometimes necessary to override the proposed drop action and choose a
298 different one from the selection of possible drop actions.
299 To do this, you need to check for the presence of each action in the value
300 supplied by the event's \l{QDropEvent::}{possibleActions()}, set the drop
301 action with \l{QDropEvent::}{setDropAction()}, and call
302 \l{QEvent::}{accept()}.
303
304 \section1 Drop Rectangles
305
306 The widget's dragMoveEvent() can be used to restrict drops to certain parts
307 of the widget by only accepting the proposed drop actions when the cursor
308 is within those areas. For example, the following code accepts any proposed
309 drop actions when the cursor is over a child widget (\c dropFrame):
310
311 \snippet droprectangle/window.cpp 0
312
313 The dragMoveEvent() can also be used if you need to give visual
314 feedback during a drag and drop operation, to scroll the window, or
315 whatever is appropriate.
316
317 \section1 The Clipboard
318
319 Applications can also communicate with each other by putting data on
320 the clipboard. To access this, you need to obtain a QClipboard object
321 from the QApplication object.
322
323 The QMimeData class is used to represent data that is transferred to and
324 from the clipboard. To put data on the clipboard, you can use the
325 setText(), setImage(), and setPixmap() convenience functions for common
326 data types. These functions are similar to those found in the QMimeData
327 class, except that they also take an additional argument that controls
328 where the data is stored: If \l{QClipboard::Mode}{Clipboard} is
329 specified, the data is placed on the clipboard; if
330 \l{QClipboard::Mode}{Selection} is specified, the data is placed in the
331 mouse selection (on X11 only). By default, data is put on the clipboard.
332
333 For example, we can copy the contents of a QLineEdit to the clipboard
334 with the following code:
335
336 \code
337 QGuiApplication::clipboard()->setText(lineEdit->text(), QClipboard::Clipboard);
338 \endcode
339
340 Data with different MIME types can also be put on the clipboard.
341 Construct a QMimeData object and set data with setData() function in
342 the way described in the previous section; this object can then be
343 put on the clipboard with the
344 \l{QClipboard::setMimeData()}{setMimeData()} function.
345
346 The QClipboard class can notify the application about changes to the
347 data it contains via its \l{QClipboard::dataChanged()}{dataChanged()}
348 signal. For example, we can monitor the clipboard by connecting this
349 signal to a slot in a widget:
350
351 \snippet clipboard/clipwindow.cpp 0
352
353 The slot connected to this signal can read the data on the clipboard
354 using one of the MIME types that can be used to represent it:
355
356 \snippet clipboard/clipwindow.cpp 1
357
358 The \l{QClipboard::selectionChanged()}{selectionChanged()} signal can
359 be used on X11 to monitor the mouse selection.
360
361 \section1 Examples
362
363 \list
364 \li \l{draganddrop/draggableicons}{Draggable Icons}
365 \li \l{draganddrop/draggabletext}{Draggable Text}
366 \li \l{draganddrop/dropsite}{Drop Site}
367 \endlist
368
369 \section1 Interoperating with Other Applications
370
371 On X11, the public
372 \l{https://freedesktop.org/wiki/Specifications/XDND}{XDND protocol} is
373 used, while on Windows Qt uses the OLE standard, and Qt for \macos uses the
374 Cocoa Drag Manager. On X11, XDND uses MIME, so no translation is necessary.
375 The Qt API is the same regardless of the platform. On Windows, MIME-aware
376 applications can communicate by using clipboard format names that are MIME
377 types. Some Windows applications already use MIME naming conventions for
378 their clipboard formats.
379
380 Custom classes for translating proprietary clipboard formats can be
381 registered by reimplementing QWindowsMimeConverter on Windows or
382 QUtiMimeConverter on \macos.
383*/