aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/qquickdrag.cpp
diff options
context:
space:
mode:
authorChris Meyer <cmeyer1969@gmail.com>2013-08-26 16:15:23 -0700
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-09 22:58:45 +0200
commit391459210de53e342ba5e9c44360754e86d7625c (patch)
treef68fca8e2f059f8e07b2638245451137af79b479 /src/quick/items/qquickdrag.cpp
parent2dcb0adc3a0a9b93b4cd09f26f2d1bac0e8cd110 (diff)
Add support for external drag and drop in Quick items.
Add dragType enums with values of None, Automatic, Internal (default). Setting to Automatic allows startDrag to be called automatically. Setting to Internal (default) retains old behavior. Add mimeData to Drag item to enable external drags. Call startDrag to start drag manually or change from internal drag to external drag. Added events dragStarted and dragFinished that get invoked from startDrag. Mime data must be specified in the mimeData property as mime-type / data pairs. Moved QQuickDrag from qquickmousearea* files to qquickdrag* files to reduce header interdependencies that caused linking errors in other modules and also to improve code organization. Allow DropArea to receive and process external data. Introduced new variable containsDrag to QQuickDropAreaPrivate. This replaces mimeData which was previously being used to determine if a drop operation was currently occurring. The problem was that mimeData was being externally destructed. Also introduced accessor methods for getting color, html, image, text, and urls out of the drop. This facilitates dropping of external data of those types onto a DropArea. Added example quick/externaldraganddrop. Task-number: QTBUG-27498 Change-Id: I1420df7c161ea3399e49a23305273e106baa246f Reviewed-by: Alan Alpert (Personal) <416365416c@gmail.com>
Diffstat (limited to 'src/quick/items/qquickdrag.cpp')
-rw-r--r--src/quick/items/qquickdrag.cpp304
1 files changed, 299 insertions, 5 deletions
diff --git a/src/quick/items/qquickdrag.cpp b/src/quick/items/qquickdrag.cpp
index f145ce259f..0ae26cb5c3 100644
--- a/src/quick/items/qquickdrag.cpp
+++ b/src/quick/items/qquickdrag.cpp
@@ -46,7 +46,9 @@
#include <private/qquickitemchangelistener_p.h>
#include <private/qv8engine_p.h>
#include <QtCore/qcoreapplication.h>
+#include <QtCore/qmimedata.h>
#include <QtQml/qqmlinfo.h>
+#include <QtGui/qdrag.h>
#include <QtGui/qevent.h>
#ifndef QT_NO_DRAGANDDROP
@@ -72,6 +74,7 @@ public:
, itemMoved(false)
, eventQueued(false)
, overrideActions(false)
+ , dragType(QQuickDrag::Internal)
{
}
@@ -83,8 +86,8 @@ public:
void deliverMoveEvent();
void deliverLeaveEvent();
void deliverEvent(QQuickWindow *window, QEvent *event);
- void start() { start(supportedActions); }
void start(Qt::DropActions supportedActions);
+ Qt::DropAction startDrag(Qt::DropActions supportedActions);
void setTarget(QQuickItem *item);
QQuickDragGrabber dragGrabber;
@@ -105,6 +108,8 @@ public:
bool overrideActions : 1;
QPointF hotSpot;
QStringList keys;
+ QVariantMap externalMimeData;
+ QQuickDrag::DragType dragType;
};
/*!
@@ -272,7 +277,10 @@ QQuickDragAttached::~QQuickDragAttached()
This property holds whether a drag event sequence is currently active.
- Setting this property to true will send a QDragEnter event to the scene
+ Binding this property to the active property of \l MouseArea::drag will
+ cause \l startDrag to be called when the user starts dragging.
+
+ Setting this property to true will also send a QDragEnter event to the scene
with the item's current position. Setting it to false will send a
QDragLeave event.
@@ -292,8 +300,18 @@ void QQuickDragAttached::setActive(bool active)
if (d->active != active) {
if (d->inEvent)
qmlInfo(this) << "active cannot be changed from within a drag event handler";
- else if (active)
- d->start(d->supportedActions);
+ else if (active) {
+ if (d->dragType == QQuickDrag::Internal) {
+ d->start(d->supportedActions);
+ }
+ else if (d->dragType == QQuickDrag::Automatic) {
+ // There are different semantics than start() since startDrag()
+ // may be called after an internal drag is already started.
+ active = true;
+ emit activeChanged();
+ d->startDrag(d->supportedActions);
+ }
+ }
else
cancel();
}
@@ -411,6 +429,28 @@ void QQuickDragAttached::setKeys(const QStringList &keys)
}
/*!
+ \qmlattachedproperty stringlist QtQuick2::Drag::mimeData
+ \since QtQuick 2.2
+
+ This property holds a map of mimeData that is used during startDrag.
+*/
+
+QVariantMap QQuickDragAttached::mimeData() const
+{
+ Q_D(const QQuickDragAttached);
+ return d->externalMimeData;
+}
+
+void QQuickDragAttached::setMimeData(const QVariantMap &mimeData)
+{
+ Q_D(QQuickDragAttached);
+ if (d->externalMimeData != mimeData) {
+ d->externalMimeData = mimeData;
+ emit mimeDataChanged();
+ }
+}
+
+/*!
\qmlattachedproperty flags QtQuick2::Drag::supportedActions
This property holds return values of Drag.drop() supported by the drag source.
@@ -465,6 +505,42 @@ void QQuickDragAttached::setProposedAction(Qt::DropAction action)
}
}
+/*!
+ \qmlattachedproperty enumeration QtQuick2::Drag::dragType
+ \since QtQuick 2.2
+
+ This property indicates whether to automatically start drags, do nothing, or
+ to use backwards compatible internal drags. The default is to use backwards
+ compatible internal drags.
+
+ A drag can also be started manually using \l startDrag.
+
+ \list
+ \li Drag.None - do not start drags automatically
+ \li Drag.Automatic - start drags automatically
+ \li Drag.Internal (default) - start backwards compatible drags automatically
+ \endlist
+
+ When using \l Drag.Automatic you should also define \l mimeData and bind the
+ \active property to the active property of \l MouseArea.drag.
+
+ */
+
+QQuickDrag::DragType QQuickDragAttached::dragType() const
+{
+ Q_D(const QQuickDragAttached);
+ return d->dragType;
+}
+
+void QQuickDragAttached::setDragType(QQuickDrag::DragType dragType)
+{
+ Q_D(QQuickDragAttached);
+ if (d->dragType != dragType) {
+ d->dragType = dragType;
+ emit dragTypeChanged();
+ }
+}
+
void QQuickDragAttachedPrivate::start(Qt::DropActions supportedActions)
{
Q_Q(QQuickDragAttached);
@@ -496,7 +572,8 @@ void QQuickDragAttachedPrivate::start(Qt::DropActions supportedActions)
/*!
\qmlattachedmethod void QtQuick2::Drag::start(flags supportedActions)
- Starts sending drag events.
+ Starts sending drag events. Used for starting old-style internal drags. \l startDrag is the
+ new-style, preferred method of starting drags.
The optional \a supportedActions argument can be used to override the \l supportedActions
property for the started sequence.
@@ -616,6 +693,223 @@ void QQuickDragAttached::cancel()
emit activeChanged();
}
+/*!
+ \qmlsignal QtQuick2::DropArea::onDragStarted()
+
+ This handler is called when a drag is started with the \l startDrag method
+ or when it is started automatically using the \l dragType property.
+ */
+
+/*!
+ \qmlsignal QtQuick2::DropArea::onDragFinished(DropAction action)
+
+ This handler is called when a drag finishes and the drag was started with the
+ \l startDrag method or started automatically using the \l dragType property.
+ */
+
+Qt::DropAction QQuickDragAttachedPrivate::startDrag(Qt::DropActions supportedActions)
+{
+ Q_Q(QQuickDragAttached);
+
+ QDrag *drag = new QDrag(q);
+ QMimeData *mimeData = new QMimeData();
+
+ Q_FOREACH (const QString &key, externalMimeData.keys()) {
+ mimeData->setData(key, externalMimeData[key].toString().toUtf8());
+ }
+
+ drag->setMimeData(mimeData);
+
+ // TODO: how to handle drag image?
+ // drag->setPixmap(iconPixmap);
+
+ emit q->dragStarted();
+
+ Qt::DropAction dropAction = drag->exec(supportedActions);
+
+ delete drag;
+
+ deliverLeaveEvent();
+
+ if (target) {
+ target = 0;
+ emit q->targetChanged();
+ }
+
+ emit q->dragFinished(dropAction);
+
+ active = false;
+ emit q->activeChanged();
+
+ return dropAction;
+}
+
+
+/*!
+ \qmlattachedmethod void QtQuick2::Drag::startDrag(flags supportedActions)
+
+ Starts sending drag events.
+
+ The optional \a supportedActions argument can be used to override the \l supportedActions
+ property for the started sequence.
+*/
+
+void QQuickDragAttached::startDrag(QQmlV4Function *args)
+{
+ Q_D(QQuickDragAttached);
+
+ if (d->inEvent) {
+ qmlInfo(this) << "startDrag() cannot be called from within a drag event handler";
+ return;
+ }
+
+ if (!d->active) {
+ qmlInfo(this) << "startDrag() drag must be active";
+ return;
+ }
+
+ Qt::DropActions supportedActions = d->supportedActions;
+
+ // check arguments for supportedActions
+ if (args->length() >= 1) {
+ QV4::Value v = (*args)[0];
+ if (v.isInt32()) {
+ supportedActions = Qt::DropActions(v.integerValue());
+ }
+ }
+
+ Qt::DropAction dropAction = d->startDrag(supportedActions);
+
+ args->setReturnValue(QV4::Value::fromInt32(dropAction));
+}
+
+QQuickDrag::QQuickDrag(QObject *parent)
+: QObject(parent), _target(0), _axis(XAndYAxis), _xmin(-FLT_MAX),
+_xmax(FLT_MAX), _ymin(-FLT_MAX), _ymax(FLT_MAX), _active(false), _filterChildren(false)
+{
+}
+
+QQuickDrag::~QQuickDrag()
+{
+}
+
+QQuickItem *QQuickDrag::target() const
+{
+ return _target;
+}
+
+void QQuickDrag::setTarget(QQuickItem *t)
+{
+ if (_target == t)
+ return;
+ _target = t;
+ emit targetChanged();
+}
+
+void QQuickDrag::resetTarget()
+{
+ if (_target == 0)
+ return;
+ _target = 0;
+ emit targetChanged();
+}
+
+QQuickDrag::Axis QQuickDrag::axis() const
+{
+ return _axis;
+}
+
+void QQuickDrag::setAxis(QQuickDrag::Axis a)
+{
+ if (_axis == a)
+ return;
+ _axis = a;
+ emit axisChanged();
+}
+
+qreal QQuickDrag::xmin() const
+{
+ return _xmin;
+}
+
+void QQuickDrag::setXmin(qreal m)
+{
+ if (_xmin == m)
+ return;
+ _xmin = m;
+ emit minimumXChanged();
+}
+
+qreal QQuickDrag::xmax() const
+{
+ return _xmax;
+}
+
+void QQuickDrag::setXmax(qreal m)
+{
+ if (_xmax == m)
+ return;
+ _xmax = m;
+ emit maximumXChanged();
+}
+
+qreal QQuickDrag::ymin() const
+{
+ return _ymin;
+}
+
+void QQuickDrag::setYmin(qreal m)
+{
+ if (_ymin == m)
+ return;
+ _ymin = m;
+ emit minimumYChanged();
+}
+
+qreal QQuickDrag::ymax() const
+{
+ return _ymax;
+}
+
+void QQuickDrag::setYmax(qreal m)
+{
+ if (_ymax == m)
+ return;
+ _ymax = m;
+ emit maximumYChanged();
+}
+
+bool QQuickDrag::active() const
+{
+ return _active;
+}
+
+void QQuickDrag::setActive(bool drag)
+{
+ if (_active == drag)
+ return;
+ _active = drag;
+ emit activeChanged();
+}
+
+bool QQuickDrag::filterChildren() const
+{
+ return _filterChildren;
+}
+
+void QQuickDrag::setFilterChildren(bool filter)
+{
+ if (_filterChildren == filter)
+ return;
+ _filterChildren = filter;
+ emit filterChildrenChanged();
+}
+
+QQuickDragAttached *QQuickDrag::qmlAttachedProperties(QObject *obj)
+{
+ return new QQuickDragAttached(obj);
+}
+
QT_END_NAMESPACE
#endif // QT_NO_DRAGANDDROP