| 1 | /**************************************************************************** | 
|---|
| 2 | ** | 
|---|
| 3 | ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). | 
|---|
| 4 | ** Contact: Qt Software Information (qt-info@nokia.com) | 
|---|
| 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 qt-sales@nokia.com. | 
|---|
| 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 <koss@napri.sk> | 
|---|
| 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 | */ | 
|---|