Merge remote-tracking branch 'gerrit/master' into newdocs
[profile/ivi/qtbase.git] / src / gui / kernel / qdrag.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include <qdrag.h>
43 #include "private/qguiapplication_p.h"
44 #include <qpixmap.h>
45 #include <qpoint.h>
46 #include "qdnd_p.h"
47
48 #ifndef QT_NO_DRAGANDDROP
49
50 QT_BEGIN_NAMESPACE
51
52 /*!
53     \class QDrag
54     \inmodule QtGui
55     \ingroup draganddrop
56     \brief The QDrag class provides support for MIME-based drag and drop data
57     transfer.
58
59     Drag and drop is an intuitive way for users to copy or move data around in an
60     application, and is used in many desktop environments as a mechanism for copying
61     data between applications. Drag and drop support in Qt is centered around the
62     QDrag class that handles most of the details of a drag and drop operation.
63
64     The data to be transferred by the drag and drop operation is contained in a
65     QMimeData object. This is specified with the setMimeData() function in the
66     following way:
67
68     \snippet dragging/mainwindow.cpp 1
69
70     Note that setMimeData() assigns ownership of the QMimeData object to the
71     QDrag object. The QDrag must be constructed on the heap with a parent QObject
72     to ensure that Qt can clean up after the drag and drop operation has been
73     completed.
74
75     A pixmap can be used to represent the data while the drag is in
76     progress, and will move with the cursor to the drop target. This
77     pixmap typically shows an icon that represents the MIME type of
78     the data being transferred, but any pixmap can be set with
79     setPixmap(). The cursor's hot spot can be given a position
80     relative to the top-left corner of the pixmap with the
81     setHotSpot() function. The following code positions the pixmap so
82     that the cursor's hot spot points to the center of its bottom
83     edge:
84
85     \snippet separations/finalwidget.cpp 2
86
87     \note On X11, the pixmap may not be able to keep up with the mouse
88     movements if the hot spot causes the pixmap to be displayed
89     directly under the cursor.
90
91     The source and target widgets can be found with source() and target().
92     These functions are often used to determine whether drag and drop operations
93     started and finished at the same widget, so that special behavior can be
94     implemented.
95
96     QDrag only deals with the drag and drop operation itself. It is up to the
97     developer to decide when a drag operation begins, and how a QDrag object should
98     be constructed and used. For a given widget, it is often necessary to
99     reimplement \l{QWidget::mousePressEvent()}{mousePressEvent()} to determine
100     whether the user has pressed a mouse button, and reimplement
101     \l{QWidget::mouseMoveEvent()}{mouseMoveEvent()} to check whether a QDrag is
102     required.
103
104     \sa {Drag and Drop}, QClipboard, QMimeData, QWindowsMime, QMacPasteboardMime,
105         {Draggable Icons Example}, {Draggable Text Example}, {Drop Site Example},
106             {Fridge Magnets Example}
107 */
108
109 /*!
110     Constructs a new drag object for the widget specified by \a dragSource.
111 */
112 QDrag::QDrag(QObject *dragSource)
113     : QObject(*new QDragPrivate, dragSource)
114 {
115     Q_D(QDrag);
116     d->source = dragSource;
117     d->target = 0;
118     d->data = 0;
119     d->hotspot = QPoint(-10, -10);
120     d->executed_action = Qt::IgnoreAction;
121     d->supported_actions = Qt::IgnoreAction;
122     d->default_action = Qt::IgnoreAction;
123 }
124
125 /*!
126     Destroys the drag object.
127 */
128 QDrag::~QDrag()
129 {
130     Q_D(QDrag);
131     delete d->data;
132 }
133
134 /*!
135     Sets the data to be sent to the given MIME \a data. Ownership of the data is
136     transferred to the QDrag object.
137 */
138 void QDrag::setMimeData(QMimeData *data)
139 {
140     Q_D(QDrag);
141     if (d->data == data)
142         return;
143     if (d->data != 0)
144         delete d->data;
145     d->data = data;
146 }
147
148 /*!
149     Returns the MIME data that is encapsulated by the drag object.
150 */
151 QMimeData *QDrag::mimeData() const
152 {
153     Q_D(const QDrag);
154     return d->data;
155 }
156
157 /*!
158     Sets \a pixmap as the pixmap used to represent the data in a drag
159     and drop operation. You can only set a pixmap before the drag is
160     started.
161 */
162 void QDrag::setPixmap(const QPixmap &pixmap)
163 {
164     Q_D(QDrag);
165     d->pixmap = pixmap;
166 }
167
168 /*!
169     Returns the pixmap used to represent the data in a drag and drop operation.
170 */
171 QPixmap QDrag::pixmap() const
172 {
173     Q_D(const QDrag);
174     return d->pixmap;
175 }
176
177 /*!
178     Sets the position of the hot spot relative to the top-left corner of the
179     pixmap used to the point specified by \a hotspot.
180
181     \b{Note:} on X11, the pixmap may not be able to keep up with the mouse
182     movements if the hot spot causes the pixmap to be displayed
183     directly under the cursor.
184 */
185 void QDrag::setHotSpot(const QPoint& hotspot)
186 {
187     Q_D(QDrag);
188     d->hotspot = hotspot;
189 }
190
191 /*!
192     Returns the position of the hot spot relative to the top-left corner of the
193     cursor.
194 */
195 QPoint QDrag::hotSpot() const
196 {
197     Q_D(const QDrag);
198     return d->hotspot;
199 }
200
201 /*!
202     Returns the source of the drag object. This is the widget where the drag
203     and drop operation originated.
204 */
205 QObject *QDrag::source() const
206 {
207     Q_D(const QDrag);
208     return d->source;
209 }
210
211 /*!
212     Returns the target of the drag and drop operation. This is the widget where
213     the drag object was dropped.
214 */
215 QObject *QDrag::target() const
216 {
217     Q_D(const QDrag);
218     return d->target;
219 }
220
221 /*!
222     \since 4.3
223
224     Starts the drag and drop operation and returns a value indicating the requested
225     drop action when it is completed. The drop actions that the user can choose
226     from are specified in \a supportedActions. The default proposed action will be selected
227     among the allowed actions in the following order: Move, Copy and Link.
228
229     \b{Note:} On Linux and Mac OS X, the drag and drop operation
230     can take some time, but this function does not block the event
231     loop. Other events are still delivered to the application while
232     the operation is performed. On Windows, the Qt event loop is
233     blocked during the operation.
234 */
235
236 Qt::DropAction QDrag::exec(Qt::DropActions supportedActions)
237 {
238     return exec(supportedActions, Qt::IgnoreAction);
239 }
240
241 /*!
242     \since 4.3
243
244     Starts the drag and drop operation and returns a value indicating the requested
245     drop action when it is completed. The drop actions that the user can choose
246     from are specified in \a supportedActions.
247
248     The \a defaultDropAction determines which action will be proposed when the user performs a
249     drag without using modifier keys.
250
251     \b{Note:} On Linux and Mac OS X, the drag and drop operation
252     can take some time, but this function does not block the event
253     loop. Other events are still delivered to the application while
254     the operation is performed. On Windows, the Qt event loop is
255     blocked during the operation. However, QDrag::exec() on
256         Windows causes processEvents() to be called frequently to keep the GUI responsive.
257         If any loops or operations are called while a drag operation is active, it will block the drag operation.
258 */
259
260 Qt::DropAction QDrag::exec(Qt::DropActions supportedActions, Qt::DropAction defaultDropAction)
261 {
262     Q_D(QDrag);
263     if (!d->data) {
264         qWarning("QDrag: No mimedata set before starting the drag");
265         return d->executed_action;
266     }
267     Qt::DropAction transformedDefaultDropAction = Qt::IgnoreAction;
268
269     if (defaultDropAction == Qt::IgnoreAction) {
270         if (supportedActions & Qt::MoveAction) {
271             transformedDefaultDropAction = Qt::MoveAction;
272         } else if (supportedActions & Qt::CopyAction) {
273             transformedDefaultDropAction = Qt::CopyAction;
274         } else if (supportedActions & Qt::LinkAction) {
275             transformedDefaultDropAction = Qt::LinkAction;
276         }
277     } else {
278         transformedDefaultDropAction = defaultDropAction;
279     }
280     d->supported_actions = supportedActions;
281     d->default_action = transformedDefaultDropAction;
282     d->executed_action = QDragManager::self()->drag(this);
283
284     return d->executed_action;
285 }
286
287 /*!
288     \obsolete
289
290     \b{Note:} It is recommended to use exec() instead of this function.
291
292     Starts the drag and drop operation and returns a value indicating the requested
293     drop action when it is completed. The drop actions that the user can choose
294     from are specified in \a request. Qt::CopyAction is always allowed.
295
296     \b{Note:} Although the drag and drop operation can take some time, this function
297     does not block the event loop. Other events are still delivered to the application
298     while the operation is performed.
299
300     \sa exec()
301 */
302 Qt::DropAction QDrag::start(Qt::DropActions request)
303 {
304     Q_D(QDrag);
305     if (!d->data) {
306         qWarning("QDrag: No mimedata set before starting the drag");
307         return d->executed_action;
308     }
309     d->supported_actions = request | Qt::CopyAction;
310     d->default_action = Qt::IgnoreAction;
311     d->executed_action = QDragManager::self()->drag(this);
312     return d->executed_action;
313 }
314
315 /*!
316     Sets the drag \a cursor for the \a action. This allows you
317     to override the default native cursors. To revert to using the
318     native cursor for \a action pass in a null QPixmap as \a cursor.
319
320     The \a action can only be CopyAction, MoveAction or LinkAction.
321     All other values of DropAction are ignored.
322 */
323 void QDrag::setDragCursor(const QPixmap &cursor, Qt::DropAction action)
324 {
325     Q_D(QDrag);
326     if (action != Qt::CopyAction && action != Qt::MoveAction && action != Qt::LinkAction)
327         return;
328     if (cursor.isNull())
329         d->customCursors.remove(action);
330     else
331         d->customCursors[action] = cursor;
332 }
333
334 /*!
335     Returns the drag cursor for the \a action.
336
337     \since 5.0
338 */
339
340 QPixmap QDrag::dragCursor(Qt::DropAction action) const
341 {
342     typedef QMap<Qt::DropAction, QPixmap>::const_iterator Iterator;
343
344     Q_D(const QDrag);
345     const Iterator it = d->customCursors.constFind(action);
346     if (it != d->customCursors.constEnd())
347         return it.value();
348
349     Qt::CursorShape shape = Qt::ForbiddenCursor;
350     switch (action) {
351     case Qt::MoveAction:
352         shape = Qt::DragMoveCursor;
353         break;
354     case Qt::CopyAction:
355         shape = Qt::DragCopyCursor;
356         break;
357     case Qt::LinkAction:
358         shape = Qt::DragLinkCursor;
359         break;
360     default:
361         shape = Qt::ForbiddenCursor;
362     }
363     return QGuiApplicationPrivate::instance()->getPixmapCursor(shape);
364 }
365
366 /*!
367     Returns the set of possible drop actions for this drag operation.
368
369     \sa exec(), defaultAction()
370 */
371 Qt::DropActions QDrag::supportedActions() const
372 {
373     Q_D(const QDrag);
374     return d->supported_actions;
375 }
376
377
378 /*!
379     Returns the default proposed drop action for this drag operation.
380
381     \sa exec(), supportedActions()
382 */
383 Qt::DropAction QDrag::defaultAction() const
384 {
385     Q_D(const QDrag);
386     return d->default_action;
387 }
388 /*!
389     \fn void QDrag::actionChanged(Qt::DropAction action)
390
391     This signal is emitted when the \a action associated with the
392     drag changes.
393
394     \sa targetChanged()
395 */
396
397 /*!
398     \fn void QDrag::targetChanged(QObject *newTarget)
399
400     This signal is emitted when the target of the drag and drop
401     operation changes, with \a newTarget the new target.
402
403     \sa target(), actionChanged()
404 */
405
406 QT_END_NAMESPACE
407
408 #endif // QT_NO_DRAGANDDROP