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>
This commit is contained in:
Chris Meyer 2013-08-26 16:15:23 -07:00 committed by The Qt Project
parent 2dcb0adc3a
commit 391459210d
19 changed files with 900 additions and 253 deletions

View File

@ -0,0 +1,92 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
** of its contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.2
Rectangle {
id: item
property string display
color: "#EEE"
Text {
anchors.fill: parent
text: item.display
wrapMode: Text.WordWrap
}
DropArea {
anchors.fill: parent
keys: ["text/plain"]
onEntered: {
item.color = "#FCC"
}
onExited: {
item.color = "#EEE"
}
onDropped: {
item.color = "#EEE"
if (drop.hasText) {
if (drop.proposedAction == Qt.MoveAction || drop.proposedAction == Qt.CopyAction) {
item.display = drop.text
drop.acceptProposedAction()
}
}
}
}
MouseArea {
id: mouseArea
anchors.fill: parent
drag.target: draggable
}
Item {
id: draggable
anchors.fill: parent
Drag.active: mouseArea.drag.active
Drag.hotSpot.x: 0
Drag.hotSpot.y: 0
Drag.mimeData: { "text/plain": item.display }
Drag.dragType: Drag.Automatic
Drag.onDragStarted: {
}
Drag.onDragFinished: {
if (dropAction == Qt.MoveAction) {
item.display = ""
}
}
} // Item
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View File

@ -0,0 +1,38 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: http://www.gnu.org/copyleft/fdl.html.
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\title Qt Quick Examples - externaldraganddrop
\example externaldraganddrop
\brief This is an example of drag and drop between Qml and other applications
\image qml-dnd2-example.png
\ingroup qtquickexamples
This example shows you how to respond to do drag and drop using MouseArea and DropArea.
Drag text between boxes, out of boxes into other applications, and from other applications into the boxes. Use option/ctrl to copy rather than move text when dragging between boxes.
*/

View File

@ -0,0 +1,11 @@
TEMPLATE = app
QT += quick qml
SOURCES += main.cpp
RESOURCES += externaldraganddrop.qrc
EXAMPLE_FILES = \
DragAndDropTextItem.qml
target.path = $$[QT_INSTALL_EXAMPLES]/quick/externaldraganddrop
INSTALLS += target

View File

@ -0,0 +1,79 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
** of its contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.2
import QtQuick.Layouts 1.0
Item {
id: root
width: 320
height: 480
ColumnLayout {
anchors.fill: parent
anchors.margins: 8
Text {
Layout.fillWidth: true
text: "Drag text into, out of, and between the boxes below."
wrapMode: Text.WordWrap
}
DragAndDropTextItem {
Layout.fillWidth: true
height: 142
display: "Sample Text"
}
DragAndDropTextItem {
Layout.fillWidth: true
height: 142
display: "Option/ctrl drag to copy instead of move text."
}
DragAndDropTextItem {
Layout.fillWidth: true
height: 142
display: "Drag out into other applications."
}
}
}

View File

@ -0,0 +1,16 @@
import QmlProject 1.1
Project {
mainFile: "externaldraganddrop.qml"
/* Include .qml, .js, and image files from current directory and subdirectories */
QmlFiles {
directory: "."
}
JavaScriptFiles {
directory: "."
}
ImageFiles {
directory: "."
}
}

View File

@ -0,0 +1,6 @@
<RCC>
<qresource prefix="/externaldraganddrop">
<file>externaldraganddrop.qml</file>
<file>DragAndDropTextItem.qml</file>
</qresource>
</RCC>

View File

@ -0,0 +1,41 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
** of its contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "../shared/shared.h"
DECLARATIVE_EXAMPLE_MAIN(externaldraganddrop/externaldraganddrop)

View File

@ -2,6 +2,7 @@ TEMPLATE = subdirs
SUBDIRS = quick-accessibility \
animation \
draganddrop \
externaldraganddrop \
canvas \
imageelements \
keyinteraction \

View File

@ -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();
}
@ -410,6 +428,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
@ -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

View File

@ -143,18 +143,90 @@ private:
};
class QQmlV4Function;
class QQuickDragAttached;
class Q_AUTOTEST_EXPORT QQuickDrag : public QObject
{
Q_OBJECT
Q_ENUMS(Axis DragType)
Q_PROPERTY(QQuickItem *target READ target WRITE setTarget NOTIFY targetChanged RESET resetTarget)
Q_PROPERTY(Axis axis READ axis WRITE setAxis NOTIFY axisChanged)
Q_PROPERTY(qreal minimumX READ xmin WRITE setXmin NOTIFY minimumXChanged)
Q_PROPERTY(qreal maximumX READ xmax WRITE setXmax NOTIFY maximumXChanged)
Q_PROPERTY(qreal minimumY READ ymin WRITE setYmin NOTIFY minimumYChanged)
Q_PROPERTY(qreal maximumY READ ymax WRITE setYmax NOTIFY maximumYChanged)
Q_PROPERTY(bool active READ active NOTIFY activeChanged)
Q_PROPERTY(bool filterChildren READ filterChildren WRITE setFilterChildren NOTIFY filterChildrenChanged)
//### consider drag and drop
public:
QQuickDrag(QObject *parent=0);
~QQuickDrag();
enum DragType { None, Automatic, Internal };
QQuickItem *target() const;
void setTarget(QQuickItem *target);
void resetTarget();
enum Axis { XAxis=0x01, YAxis=0x02, XAndYAxis=0x03, XandYAxis=XAndYAxis };
Axis axis() const;
void setAxis(Axis);
qreal xmin() const;
void setXmin(qreal);
qreal xmax() const;
void setXmax(qreal);
qreal ymin() const;
void setYmin(qreal);
qreal ymax() const;
void setYmax(qreal);
bool active() const;
void setActive(bool);
bool filterChildren() const;
void setFilterChildren(bool);
static QQuickDragAttached *qmlAttachedProperties(QObject *obj);
Q_SIGNALS:
void targetChanged();
void axisChanged();
void minimumXChanged();
void maximumXChanged();
void minimumYChanged();
void maximumYChanged();
void activeChanged();
void filterChildrenChanged();
private:
QQuickItem *_target;
Axis _axis;
qreal _xmin;
qreal _xmax;
qreal _ymin;
qreal _ymax;
bool _active : 1;
bool _filterChildren: 1;
Q_DISABLE_COPY(QQuickDrag)
};
class QQuickDragAttachedPrivate;
class QQuickDragAttached : public QObject
{
Q_OBJECT
Q_DECLARE_PRIVATE(QQuickDragAttached)
Q_PROPERTY(bool active READ isActive WRITE setActive NOTIFY activeChanged)
Q_PROPERTY(QObject *source READ source WRITE setSource NOTIFY sourceChanged RESET resetSource)
Q_PROPERTY(QObject *target READ target NOTIFY targetChanged)
Q_PROPERTY(QPointF hotSpot READ hotSpot WRITE setHotSpot NOTIFY hotSpotChanged)
Q_PROPERTY(QStringList keys READ keys WRITE setKeys NOTIFY keysChanged)
Q_PROPERTY(QVariantMap mimeData READ mimeData WRITE setMimeData NOTIFY mimeDataChanged)
Q_PROPERTY(Qt::DropActions supportedActions READ supportedActions WRITE setSupportedActions NOTIFY supportedActionsChanged)
Q_PROPERTY(Qt::DropAction proposedAction READ proposedAction WRITE setProposedAction NOTIFY proposedActionChanged)
Q_PROPERTY(QQuickDrag::DragType dragType READ dragType WRITE setDragType NOTIFY dragTypeChanged)
public:
QQuickDragAttached(QObject *parent);
~QQuickDragAttached();
@ -174,36 +246,47 @@ public:
QStringList keys() const;
void setKeys(const QStringList &keys);
QVariantMap mimeData() const;
void setMimeData(const QVariantMap &mimeData);
Qt::DropActions supportedActions() const;
void setSupportedActions(Qt::DropActions actions);
Qt::DropAction proposedAction() const;
void setProposedAction(Qt::DropAction action);
QQuickDrag::DragType dragType() const;
void setDragType(QQuickDrag::DragType dragType);
Q_INVOKABLE int drop();
bool event(QEvent *event);
public Q_SLOTS:
void start(QQmlV4Function *);
void startDrag(QQmlV4Function *);
void cancel();
Q_SIGNALS:
void dragStarted();
void dragFinished(Qt::DropAction dropAction);
void activeChanged();
void sourceChanged();
void targetChanged();
void hotSpotChanged();
void keysChanged();
void mimeDataChanged();
void supportedActionsChanged();
void proposedActionChanged();
private:
Q_DECLARE_PRIVATE(QQuickDragAttached)
void dragTypeChanged();
};
QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickDrag)
QML_DECLARE_TYPEINFO(QQuickDrag, QML_HAS_ATTACHED_PROPERTIES)
#endif // QT_NO_DRAGANDDROP
#endif

View File

@ -77,11 +77,12 @@ public:
QPointF dragPosition;
QQuickDropAreaDrag *drag;
QPointer<QObject> source;
QPointer<QMimeData> mimeData;
bool containsDrag;
};
QQuickDropAreaPrivate::QQuickDropAreaPrivate()
: drag(0)
, containsDrag(false)
{
}
@ -133,7 +134,7 @@ QQuickDropArea::~QQuickDropArea()
bool QQuickDropArea::containsDrag() const
{
Q_D(const QQuickDropArea);
return d->mimeData;
return d->containsDrag;
}
/*!
@ -217,7 +218,7 @@ qreal QQuickDropAreaDrag::y() const
void QQuickDropArea::dragMoveEvent(QDragMoveEvent *event)
{
Q_D(QQuickDropArea);
if (!d->mimeData)
if (!d->containsDrag)
return;
d->dragPosition = event->pos();
@ -259,28 +260,27 @@ void QQuickDropArea::dragEnterEvent(QDragEnterEvent *event)
{
Q_D(QQuickDropArea);
const QMimeData *mimeData = event->mimeData();
if (!d->effectiveEnable || d->mimeData || !mimeData || !d->hasMatchingKey(d->getKeys(mimeData)))
if (!d->effectiveEnable || d->containsDrag || !mimeData || !d->hasMatchingKey(d->getKeys(mimeData)))
return;
d->dragPosition = event->pos();
event->accept();
QQuickDropEvent dragTargetEvent(d, event);
emit entered(&dragTargetEvent);
if (event->isAccepted()) {
d->mimeData = const_cast<QMimeData *>(mimeData);
if (QQuickDragMimeData *dragMime = qobject_cast<QQuickDragMimeData *>(d->mimeData))
d->source = dragMime->source();
else
d->source = event->source();
d->dragPosition = event->pos();
if (d->drag) {
emit d->drag->positionChanged();
emit d->drag->sourceChanged();
}
emit containsDragChanged();
d->containsDrag = true;
if (QQuickDragMimeData *dragMime = qobject_cast<QQuickDragMimeData *>(const_cast<QMimeData *>(mimeData)))
d->source = dragMime->source();
else
d->source = event->source();
d->dragPosition = event->pos();
if (d->drag) {
emit d->drag->positionChanged();
emit d->drag->sourceChanged();
}
emit containsDragChanged();
}
/*!
@ -292,12 +292,12 @@ void QQuickDropArea::dragEnterEvent(QDragEnterEvent *event)
void QQuickDropArea::dragLeaveEvent(QDragLeaveEvent *)
{
Q_D(QQuickDropArea);
if (!d->mimeData)
if (!d->containsDrag)
return;
emit exited();
d->mimeData = 0;
d->containsDrag = false;
d->source = 0;
emit containsDragChanged();
if (d->drag)
@ -314,13 +314,13 @@ void QQuickDropArea::dragLeaveEvent(QDragLeaveEvent *)
void QQuickDropArea::dropEvent(QDropEvent *event)
{
Q_D(QQuickDropArea);
if (!d->mimeData)
if (!d->containsDrag)
return;
QQuickDropEvent dragTargetEvent(d, event);
emit dropped(&dragTargetEvent);
d->mimeData = 0;
d->containsDrag = false;
d->source = 0;
emit containsDragChanged();
if (d->drag)
@ -337,6 +337,16 @@ void QQuickDropArea::dropEvent(QDropEvent *event)
The position of the drag event can be obtained from the \l x and \l y
properties, and the \l keys property identifies the drag keys of the event
\l source.
The existence of specific drag types can be determined using the \l hasColor,
\l hasHtml, \l hasText, and \l hasUrls properties.
The list of all supplied formats can be determined using the \l formats property.
Specific drag types can be obtained using the \l colorData, \l html, \l text,
and \l urls properties.
A string version of any available mimeType can be obtained using \l getDataAsString.
*/
/*!
@ -357,14 +367,6 @@ void QQuickDropArea::dropEvent(QDropEvent *event)
This property holds the source of a drag event.
*/
QObject *QQuickDropEvent::source()
{
if (const QQuickDragMimeData *dragMime = qobject_cast<const QQuickDragMimeData *>(event->mimeData()))
return dragMime->source();
else
return event->source();
}
/*!
\qmlproperty stringlist QtQuick2::DragEvent::keys
@ -372,11 +374,6 @@ QObject *QQuickDropEvent::source()
drag event.
*/
QStringList QQuickDropEvent::keys() const
{
return d->getKeys(event->mimeData());
}
/*!
\qmlproperty enumeration QtQuick2::DragEvent::action
@ -399,6 +396,14 @@ QStringList QQuickDropEvent::keys() const
drag source.
*/
/*!
\qmlproperty flags QtQuick2::DragEvent::proposedAction
\since QtQuick 2.2
This property holds the set of \l {action}{actions} proposed by the
drag source.
*/
/*!
\qmlproperty bool QtQuick2::DragEvent::accepted
@ -416,6 +421,157 @@ QStringList QQuickDropEvent::keys() const
If an \a action is specified it will overwrite the value of the \l action property.
*/
/*!
\qmlmethod QtQuick2::DragEvent::acceptProposedAction()
\since QtQuick 2.2
Accepts the drag event with the \l proposedAction.
*/
/*!
\qmlproperty bool QtQuick2::DragEvent::hasColor
\since QtQuick 2.2
This property holds whether the drag event contains a color item.
*/
/*!
\qmlproperty bool QtQuick2::DragEvent::hasHtml
\since QtQuick 2.2
This property holds whether the drag event contains a html item.
*/
/*!
\qmlproperty bool QtQuick2::DragEvent::hasText
\since QtQuick 2.2
This property holds whether the drag event contains a text item.
*/
/*!
\qmlproperty bool QtQuick2::DragEvent::hasUrls
\since QtQuick 2.2
This property holds whether the drag event contains one or more url items.
*/
/*!
\qmlproperty color QtQuick2::DragEvent::colorData
\since QtQuick 2.2
This property holds color data, if any.
*/
/*!
\qmlproperty string QtQuick2::DragEvent::html
\since QtQuick 2.2
This property holds html data, if any.
*/
/*!
\qmlproperty string QtQuick2::DragEvent::text
\since QtQuick 2.2
This property holds text data, if any.
*/
/*!
\qmlproperty urllist QtQuick2::DragEvent::urls
\since QtQuick 2.2
This property holds a list of urls, if any.
*/
/*!
\qmlproperty stringlist QtQuick2::DragEvent::formats
\since QtQuick 2.2
This property holds a list of mime type formats contained in the drag data.
*/
/*!
\qmlmethod string QtQuick2::DragEvent::getDataAsString(string format)
\since QtQuick 2.2
Returns the data for the given \a format converted to a string. \a format should be one contained in the \l formats property.
*/
QObject *QQuickDropEvent::source()
{
if (const QQuickDragMimeData *dragMime = qobject_cast<const QQuickDragMimeData *>(event->mimeData()))
return dragMime->source();
else
return event->source();
}
QStringList QQuickDropEvent::keys() const
{
return d->getKeys(event->mimeData());
}
bool QQuickDropEvent::hasColor() const
{
return event->mimeData()->hasColor();
}
bool QQuickDropEvent::hasHtml() const
{
return event->mimeData()->hasHtml();
}
bool QQuickDropEvent::hasText() const
{
return event->mimeData()->hasText();
}
bool QQuickDropEvent::hasUrls() const
{
return event->mimeData()->hasUrls();
}
QVariant QQuickDropEvent::colorData() const
{
return event->mimeData()->colorData();
}
QString QQuickDropEvent::html() const
{
return event->mimeData()->html();
}
QString QQuickDropEvent::text() const
{
return event->mimeData()->text();
}
QList<QUrl> QQuickDropEvent::urls() const
{
return event->mimeData()->urls();
}
QStringList QQuickDropEvent::formats() const
{
return event->mimeData()->formats();
}
void QQuickDropEvent::getDataAsString(QQmlV4Function *args)
{
if (args->length() != 0) {
QV4::Value v = (*args)[0];
QString format = v.toQString();
QString rv = QString::fromUtf8(event->mimeData()->data(format));
QV4::ExecutionEngine *v4 = QV8Engine::getV4(args->engine());
args->setReturnValue(QV4::Value::fromString(v4, rv));
}
}
void QQuickDropEvent::acceptProposedAction(QQmlV4Function *)
{
event->acceptProposedAction();
}
void QQuickDropEvent::accept(QQmlV4Function *args)
{
Qt::DropAction action = event->dropAction();
@ -425,6 +581,7 @@ void QQuickDropEvent::accept(QQmlV4Function *args)
if (v.isInt32())
action = Qt::DropAction(v.integerValue());
}
// get action from arguments.
event->setDropAction(action);
event->accept();

View File

@ -62,8 +62,18 @@ class QQuickDropEvent : public QObject
Q_PROPERTY(QObject *source READ source)
Q_PROPERTY(QStringList keys READ keys)
Q_PROPERTY(Qt::DropActions supportedActions READ supportedActions)
Q_PROPERTY(Qt::DropActions proposedAction READ proposedAction)
Q_PROPERTY(Qt::DropAction action READ action WRITE setAction RESET resetAction)
Q_PROPERTY(bool accepted READ accepted WRITE setAccepted)
Q_PROPERTY(bool hasColor READ hasColor)
Q_PROPERTY(bool hasHtml READ hasHtml)
Q_PROPERTY(bool hasText READ hasText)
Q_PROPERTY(bool hasUrls READ hasUrls)
Q_PROPERTY(QVariant colorData READ colorData)
Q_PROPERTY(QString html READ html)
Q_PROPERTY(QString text READ text)
Q_PROPERTY(QList<QUrl> urls READ urls)
Q_PROPERTY(QStringList formats READ formats)
public:
QQuickDropEvent(QQuickDropAreaPrivate *d, QDropEvent *event) : d(d), event(event) {}
@ -73,6 +83,7 @@ public:
QObject *source();
Qt::DropActions supportedActions() const { return event->possibleActions(); }
Qt::DropActions proposedAction() const { return event->proposedAction(); }
Qt::DropAction action() const { return event->dropAction(); }
void setAction(Qt::DropAction action) { event->setDropAction(action); }
void resetAction() { event->setDropAction(event->proposedAction()); }
@ -82,6 +93,18 @@ public:
bool accepted() const { return event->isAccepted(); }
void setAccepted(bool accepted) { event->setAccepted(accepted); }
bool hasColor() const;
bool hasHtml() const;
bool hasText() const;
bool hasUrls() const;
QVariant colorData() const;
QString html() const;
QString text() const;
QList<QUrl> urls() const;
QStringList formats() const;
Q_INVOKABLE void getDataAsString(QQmlV4Function *);
Q_INVOKABLE void acceptProposedAction(QQmlV4Function *);
Q_INVOKABLE void accept(QQmlV4Function *);
private:

View File

@ -61,137 +61,6 @@ DEFINE_BOOL_CONFIG_OPTION(qmlVisualTouchDebugging, QML_VISUAL_TOUCH_DEBUGGING)
static const int PressAndHoldDelay = 800;
#ifndef QT_NO_DRAGANDDROP
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);
}
#endif // QT_NO_DRAGANDDROP
QQuickMouseAreaPrivate::QQuickMouseAreaPrivate()
: enabled(true), hovered(false), longPress(false),
moved(false), stealMouse(false), doubleClick(false), preventStealing(false),

View File

@ -49,78 +49,7 @@
QT_BEGIN_NAMESPACE
class QQuickMouseEvent;
#ifndef QT_NO_DRAGANDDROP
class QQuickDragAttached;
class Q_AUTOTEST_EXPORT QQuickDrag : public QObject
{
Q_OBJECT
Q_ENUMS(Axis)
Q_PROPERTY(QQuickItem *target READ target WRITE setTarget NOTIFY targetChanged RESET resetTarget)
Q_PROPERTY(Axis axis READ axis WRITE setAxis NOTIFY axisChanged)
Q_PROPERTY(qreal minimumX READ xmin WRITE setXmin NOTIFY minimumXChanged)
Q_PROPERTY(qreal maximumX READ xmax WRITE setXmax NOTIFY maximumXChanged)
Q_PROPERTY(qreal minimumY READ ymin WRITE setYmin NOTIFY minimumYChanged)
Q_PROPERTY(qreal maximumY READ ymax WRITE setYmax NOTIFY maximumYChanged)
Q_PROPERTY(bool active READ active NOTIFY activeChanged)
Q_PROPERTY(bool filterChildren READ filterChildren WRITE setFilterChildren NOTIFY filterChildrenChanged)
//### consider drag and drop
public:
QQuickDrag(QObject *parent=0);
~QQuickDrag();
QQuickItem *target() const;
void setTarget(QQuickItem *target);
void resetTarget();
enum Axis { XAxis=0x01, YAxis=0x02, XAndYAxis=0x03, XandYAxis=XAndYAxis };
Axis axis() const;
void setAxis(Axis);
qreal xmin() const;
void setXmin(qreal);
qreal xmax() const;
void setXmax(qreal);
qreal ymin() const;
void setYmin(qreal);
qreal ymax() const;
void setYmax(qreal);
bool active() const;
void setActive(bool);
bool filterChildren() const;
void setFilterChildren(bool);
static QQuickDragAttached *qmlAttachedProperties(QObject *obj);
Q_SIGNALS:
void targetChanged();
void axisChanged();
void minimumXChanged();
void maximumXChanged();
void minimumYChanged();
void maximumYChanged();
void activeChanged();
void filterChildrenChanged();
private:
QQuickItem *_target;
Axis _axis;
qreal _xmin;
qreal _xmax;
qreal _ymin;
qreal _ymax;
bool _active : 1;
bool _filterChildren: 1;
Q_DISABLE_COPY(QQuickDrag)
};
#endif // QT_NO_DRAGANDDROP
class QQuickDrag;
class QQuickMouseAreaPrivate;
class QQuickWheelEvent;
// used in Qt Location
@ -244,10 +173,6 @@ private:
QT_END_NAMESPACE
#ifndef QT_NO_DRAGANDDROP
QML_DECLARE_TYPE(QQuickDrag)
QML_DECLARE_TYPEINFO(QQuickDrag, QML_HAS_ATTACHED_PROPERTIES)
#endif
QML_DECLARE_TYPE(QQuickMouseArea)
#endif // QQUICKMOUSEAREA_P_H

View File

@ -48,6 +48,7 @@
#include <QtCore/qcoreapplication.h>
#include <QtCore/qmimedata.h>
#include <QtQml/qqmlinfo.h>
#include <QtGui/qevent.h>
#include <QTextBoundaryFinder>

View File

@ -46,6 +46,8 @@
#include "qquickitem_p.h"
#include "qquickevents_p_p.h"
#include <private/qquickdrag_p.h>
#include <QtQuick/private/qsgrenderer_p.h>
#include <QtQuick/private/qsgtexture_p.h>
#include <QtQuick/private/qsgflashnode_p.h>
@ -363,6 +365,9 @@ QQuickWindowPrivate::QQuickWindowPrivate()
, mouseGrabberItem(0)
#ifndef QT_NO_CURSOR
, cursorItem(0)
#endif
#ifndef QT_NO_DRAGANDDROP
, dragGrabber(0)
#endif
, touchMouseId(-1)
, touchMousePressTimestamp(0)
@ -380,6 +385,9 @@ QQuickWindowPrivate::QQuickWindowPrivate()
, renderTargetId(0)
, incubationController(0)
{
#ifndef QT_NO_DRAGANDDROP
dragGrabber = new QQuickDragGrabber;
#endif
}
QQuickWindowPrivate::~QQuickWindowPrivate()
@ -984,7 +992,9 @@ QQuickWindow::~QQuickWindow()
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
delete d->incubationController; d->incubationController = 0;
#ifndef QT_NO_DRAGANDDROP
delete d->dragGrabber; d->dragGrabber = 0;
#endif
delete d->contentItem; d->contentItem = 0;
}
@ -1202,7 +1212,7 @@ bool QQuickWindow::event(QEvent *e)
case QEvent::DragLeave:
case QEvent::DragMove:
case QEvent::Drop:
d->deliverDragEvent(&d->dragGrabber, e);
d->deliverDragEvent(d->dragGrabber, e);
break;
#endif
case QEvent::WindowDeactivate:

View File

@ -57,7 +57,6 @@
#include "qquickwindow.h"
#include <QtQuick/private/qsgcontext_p.h>
#include <private/qquickdrag_p.h>
#include <QtCore/qthread.h>
#include <QtCore/qmutex.h>
@ -73,6 +72,7 @@ QT_BEGIN_NAMESPACE
//Make it easy to identify and customize the root item if needed
class QSGRenderLoop;
class QQuickDragGrabber;
class QQuickRootItem : public QQuickItem
{
@ -116,7 +116,7 @@ public:
QQuickItem *cursorItem;
#endif
#ifndef QT_NO_DRAGANDDROP
QQuickDragGrabber dragGrabber;
QQuickDragGrabber *dragGrabber;
#endif
int touchMouseId;
bool checkIfDoubleClicked(ulong newPressEventTimestamp);

View File

@ -41,6 +41,7 @@
#include <QtTest/QtTest>
#include <QtTest/QSignalSpy>
#include <QtQuick/private/qquickdrag_p.h>
#include <QtQuick/private/qquickmousearea_p.h>
#include <QtQuick/private/qquickrectangle_p.h>
#include <private/qquickflickable_p.h>