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