aboutsummaryrefslogtreecommitdiffstats
path: root/src/declarative/items
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative/items')
-rw-r--r--src/declarative/items/items.pri7
-rw-r--r--src/declarative/items/qsgcanvas.cpp168
-rw-r--r--src/declarative/items/qsgcanvas_p.h8
-rw-r--r--src/declarative/items/qsgdrag.cpp474
-rw-r--r--src/declarative/items/qsgdrag_p.h212
-rw-r--r--src/declarative/items/qsgdragtarget.cpp363
-rw-r--r--src/declarative/items/qsgdroparea.cpp426
-rw-r--r--src/declarative/items/qsgdroparea_p.h (renamed from src/declarative/items/qsgdragtarget_p.h)116
-rw-r--r--src/declarative/items/qsgevent.h137
-rw-r--r--src/declarative/items/qsgitem.cpp37
-rw-r--r--src/declarative/items/qsgitem.h11
-rw-r--r--src/declarative/items/qsgitem_p.h4
-rw-r--r--src/declarative/items/qsgitemsmodule.cpp10
-rw-r--r--src/declarative/items/qsgmousearea.cpp142
-rw-r--r--src/declarative/items/qsgmousearea_p.h34
-rw-r--r--src/declarative/items/qsgmousearea_p_p.h1
16 files changed, 1350 insertions, 800 deletions
diff --git a/src/declarative/items/items.pri b/src/declarative/items/items.pri
index 04330748e1..355a762764 100644
--- a/src/declarative/items/items.pri
+++ b/src/declarative/items/items.pri
@@ -64,8 +64,8 @@ HEADERS += \
$$PWD/qsgspriteengine_p.h \
$$PWD/qsgsprite_p.h \
$$PWD/qsgspriteimage_p.h \
- $$PWD/qsgevent.h \
- $$PWD/qsgdragtarget_p.h \
+ $$PWD/qsgdrag_p.h \
+ $$PWD/qsgdroparea_p.h \
$$PWD/qsgitemview_p.h \
$$PWD/qsgitemview_p_p.h
@@ -110,7 +110,8 @@ SOURCES += \
$$PWD/qsgspriteengine.cpp \
$$PWD/qsgsprite.cpp \
$$PWD/qsgspriteimage.cpp \
- $$PWD/qsgdragtarget.cpp \
+ $$PWD/qsgdrag.cpp \
+ $$PWD/qsgdroparea.cpp \
$$PWD/qsgitemview.cpp
SOURCES += \
diff --git a/src/declarative/items/qsgcanvas.cpp b/src/declarative/items/qsgcanvas.cpp
index 4eb6f92395..09a13f403c 100644
--- a/src/declarative/items/qsgcanvas.cpp
+++ b/src/declarative/items/qsgcanvas.cpp
@@ -45,8 +45,6 @@
#include "qsgitem.h"
#include "qsgitem_p.h"
-#include "qsgevent.h"
-
#include <private/qsgrenderer_p.h>
#include <private/qsgflashnode_p.h>
@@ -897,11 +895,11 @@ bool QSGCanvas::event(QEvent *e)
d->clearHover();
d->lastMousePosition = QPoint();
break;
- case QSGEvent::SGDragEnter:
- case QSGEvent::SGDragExit:
- case QSGEvent::SGDragMove:
- case QSGEvent::SGDragDrop:
- d->deliverDragEvent(static_cast<QSGDragEvent *>(e));
+ case QEvent::DragEnter:
+ case QEvent::DragLeave:
+ case QEvent::DragMove:
+ case QEvent::Drop:
+ d->deliverDragEvent(&d->dragGrabber, e);
break;
case QEvent::WindowDeactivate:
rootItem()->windowDeactivateEvent();
@@ -1362,76 +1360,124 @@ bool QSGCanvasPrivate::deliverTouchPoints(QSGItem *item, QTouchEvent *event, con
return false;
}
-void QSGCanvasPrivate::deliverDragEvent(QSGDragEvent *event)
+void QSGCanvasPrivate::deliverDragEvent(QSGDragGrabber *grabber, QEvent *event)
{
Q_Q(QSGCanvas);
- if (event->type() == QSGEvent::SGDragExit || event->type() == QSGEvent::SGDragDrop) {
- if (QSGItem *grabItem = event->grabItem()) {
- event->setPosition(grabItem->mapFromScene(event->scenePosition()));
- q->sendEvent(grabItem, event);
+ grabber->resetTarget();
+ QSGDragGrabber::iterator grabItem = grabber->begin();
+ if (grabItem != grabber->end()) {
+ Q_ASSERT(event->type() != QEvent::DragEnter);
+ if (event->type() == QEvent::Drop) {
+ QDropEvent *e = static_cast<QDropEvent *>(event);
+ for (e->setAccepted(false); !e->isAccepted() && grabItem != grabber->end(); grabItem = grabber->release(grabItem)) {
+ QPointF p = (**grabItem)->mapFromScene(e->pos());
+ QDropEvent translatedEvent(
+ p.toPoint(),
+ e->possibleActions(),
+ e->mimeData(),
+ e->mouseButtons(),
+ e->keyboardModifiers());
+ QSGDropEventEx::copyActions(&translatedEvent, *e);
+ q->sendEvent(**grabItem, &translatedEvent);
+ e->setAccepted(translatedEvent.isAccepted());
+ e->setDropAction(translatedEvent.dropAction());
+ grabber->setTarget(**grabItem);
+ }
}
- } else if (!deliverDragEvent(rootItem, event)) {
- if (QSGItem *grabItem = event->grabItem()) {
- QSGDragEvent exitEvent(QSGEvent::SGDragExit, *event);
- exitEvent.setPosition(grabItem->mapFromScene(event->scenePosition()));
- q->sendEvent(grabItem, &exitEvent);
- event->setDropItem(0);
- event->setGrabItem(0);
+ if (event->type() != QEvent::DragMove) { // Either an accepted drop or a leave.
+ QDragLeaveEvent leaveEvent;
+ for (; grabItem != grabber->end(); grabItem = grabber->release(grabItem))
+ q->sendEvent(**grabItem, &leaveEvent);
+ return;
+ } else for (; grabItem != grabber->end(); grabItem = grabber->release(grabItem)) {
+ QDragMoveEvent *moveEvent = static_cast<QDragMoveEvent *>(event);
+ if (deliverDragEvent(grabber, **grabItem, moveEvent)) {
+ moveEvent->setAccepted(true);
+ for (++grabItem; grabItem != grabber->end();) {
+ QPointF p = (**grabItem)->mapFromScene(moveEvent->pos());
+ if (QRectF(0, 0, (**grabItem)->width(), (**grabItem)->height()).contains(p)) {
+ QDragMoveEvent translatedEvent(
+ p.toPoint(),
+ moveEvent->possibleActions(),
+ moveEvent->mimeData(),
+ moveEvent->mouseButtons(),
+ moveEvent->keyboardModifiers());
+ QSGDropEventEx::copyActions(&translatedEvent, *moveEvent);
+ q->sendEvent(**grabItem, &translatedEvent);
+ ++grabItem;
+ } else {
+ QDragLeaveEvent leaveEvent;
+ q->sendEvent(**grabItem, &leaveEvent);
+ grabItem = grabber->release(grabItem);
+ }
+ }
+ return;
+ } else {
+ QDragLeaveEvent leaveEvent;
+ q->sendEvent(**grabItem, &leaveEvent);
+ }
}
- event->setAccepted(false);
+ }
+ if (event->type() == QEvent::DragEnter || event->type() == QEvent::DragMove) {
+ QDragMoveEvent *e = static_cast<QDragMoveEvent *>(event);
+ QDragEnterEvent enterEvent(
+ e->pos(),
+ e->possibleActions(),
+ e->mimeData(),
+ e->mouseButtons(),
+ e->keyboardModifiers());
+ QSGDropEventEx::copyActions(&enterEvent, *e);
+ event->setAccepted(deliverDragEvent(grabber, rootItem, &enterEvent));
}
}
-bool QSGCanvasPrivate::deliverDragEvent(QSGItem *item, QSGDragEvent *event)
+bool QSGCanvasPrivate::deliverDragEvent(QSGDragGrabber *grabber, QSGItem *item, QDragMoveEvent *event)
{
Q_Q(QSGCanvas);
+ bool accepted = false;
QSGItemPrivate *itemPrivate = QSGItemPrivate::get(item);
- if (itemPrivate->opacity == 0.0)
+ if (itemPrivate->opacity == 0.0 || !item->isVisible() || !item->isEnabled())
return false;
- if (itemPrivate->flags & QSGItem::ItemClipsChildrenToShape) {
- QPointF p = item->mapFromScene(event->scenePosition());
- if (!QRectF(0, 0, item->width(), item->height()).contains(p))
- return false;
- }
-
- QList<QSGItem *> children = itemPrivate->paintOrderChildItems();
- for (int ii = children.count() - 1; ii >= 0; --ii) {
- QSGItem *child = children.at(ii);
- if (!child->isVisible() || !child->isEnabled())
- continue;
- if (deliverDragEvent(child, event))
- return true;
- }
-
- QPointF p = item->mapFromScene(event->scenePosition());
+ QPointF p = item->mapFromScene(event->pos());
if (QRectF(0, 0, item->width(), item->height()).contains(p)) {
- event->setPosition(p);
-
- if (event->type() == QSGEvent::SGDragMove && item != event->grabItem()) {
- QSGDragEvent enterEvent(QSGEvent::SGDragEnter, *event);
- q->sendEvent(item, &enterEvent);
- if (enterEvent.isAccepted()) {
- if (QSGItem *grabItem = event->grabItem()) {
- QSGDragEvent exitEvent(QSGEvent::SGDragExit, *event);
- q->sendEvent(grabItem, &exitEvent);
+ if (event->type() == QEvent::DragMove || itemPrivate->flags & QSGItem::ItemAcceptsDrops) {
+ QDragMoveEvent translatedEvent(
+ p.toPoint(),
+ event->possibleActions(),
+ event->mimeData(),
+ event->mouseButtons(),
+ event->keyboardModifiers(),
+ event->type());
+ QSGDropEventEx::copyActions(&translatedEvent, *event);
+ q->sendEvent(item, &translatedEvent);
+ if (event->type() == QEvent::DragEnter) {
+ if (translatedEvent.isAccepted()) {
+ grabber->grab(item);
+ accepted = true;
}
- event->setDropItem(enterEvent.dropItem());
- event->setGrabItem(item);
} else {
- return false;
+ accepted = true;
}
}
+ } else if (itemPrivate->flags & QSGItem::ItemClipsChildrenToShape) {
+ return false;
+ }
- q->sendEvent(item, event);
- if (event->isAccepted()) {
- event->setGrabItem(item);
+ QDragEnterEvent enterEvent(
+ event->pos(),
+ event->possibleActions(),
+ event->mimeData(),
+ event->mouseButtons(),
+ event->keyboardModifiers());
+ QSGDropEventEx::copyActions(&enterEvent, *event);
+ QList<QSGItem *> children = itemPrivate->paintOrderChildItems();
+ for (int ii = children.count() - 1; ii >= 0; --ii) {
+ if (deliverDragEvent(grabber, children.at(ii), &enterEvent))
return true;
- }
- event->setAccepted(true);
}
- return false;
+ return accepted;
}
bool QSGCanvasPrivate::sendFilteredMouseEvent(QSGItem *target, QSGItem *item, QMouseEvent *event)
@@ -1509,11 +1555,11 @@ bool QSGCanvas::sendEvent(QSGItem *item, QEvent *e)
case QEvent::TouchEnd:
QSGItemPrivate::get(item)->deliverTouchEvent(static_cast<QTouchEvent *>(e));
break;
- case QSGEvent::SGDragEnter:
- case QSGEvent::SGDragExit:
- case QSGEvent::SGDragMove:
- case QSGEvent::SGDragDrop:
- QSGItemPrivate::get(item)->deliverDragEvent(static_cast<QSGDragEvent *>(e));
+ case QEvent::DragEnter:
+ case QEvent::DragMove:
+ case QEvent::DragLeave:
+ case QEvent::Drop:
+ QSGItemPrivate::get(item)->deliverDragEvent(e);
break;
default:
break;
diff --git a/src/declarative/items/qsgcanvas_p.h b/src/declarative/items/qsgcanvas_p.h
index 4a53e6bb1b..e2ec7a1963 100644
--- a/src/declarative/items/qsgcanvas_p.h
+++ b/src/declarative/items/qsgcanvas_p.h
@@ -55,10 +55,10 @@
#include "qsgitem.h"
#include "qsgcanvas.h"
-#include "qsgevent.h"
#include <private/qdeclarativeguard_p.h>
#include <private/qsgcontext_p.h>
+#include <private/qsgdrag_p.h>
#include <QtCore/qthread.h>
#include <QtCore/qmutex.h>
@@ -102,6 +102,7 @@ public:
QSGItem *activeFocusItem;
QSGItem *mouseGrabberItem;
+ QSGDragGrabber dragGrabber;
// Mouse positions are saved in widget coordinates
QPointF lastMousePosition;
@@ -118,8 +119,8 @@ public:
bool sendHoverEvent(QEvent::Type, QSGItem *, const QPointF &scenePos, const QPointF &lastScenePos,
Qt::KeyboardModifiers modifiers, bool accepted);
bool clearHover();
- void deliverDragEvent(QSGDragEvent *);
- bool deliverDragEvent(QSGItem *item, QSGDragEvent *);
+ void deliverDragEvent(QSGDragGrabber *, QEvent *);
+ bool deliverDragEvent(QSGDragGrabber *, QSGItem *, QDragMoveEvent *);
QList<QSGItem*> hoverItems;
enum FocusOption {
@@ -300,7 +301,6 @@ public:
void run();
};
-
Q_DECLARE_OPERATORS_FOR_FLAGS(QSGCanvasPrivate::FocusOptions)
QT_END_NAMESPACE
diff --git a/src/declarative/items/qsgdrag.cpp b/src/declarative/items/qsgdrag.cpp
new file mode 100644
index 0000000000..7c73db7d38
--- /dev/null
+++ b/src/declarative/items/qsgdrag.cpp
@@ -0,0 +1,474 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsgdrag_p.h"
+
+#include <private/qsgitem_p.h>
+#include <private/qsgevents_p_p.h>
+#include <private/qsgitemchangelistener_p.h>
+#include <private/qv8engine_p.h>
+
+#include <QtGui/qevent.h>
+
+QT_BEGIN_NAMESPACE
+
+class QSGDragAttachedPrivate : public QObjectPrivate, public QSGItemChangeListener
+{
+ Q_DECLARE_PUBLIC(QSGDragAttached)
+public:
+ static QSGDragAttachedPrivate *get(QSGDragAttached *attached) {
+ return static_cast<QSGDragAttachedPrivate *>(QObjectPrivate::get(attached)); }
+
+ QSGDragAttachedPrivate()
+ : attachedItem(0)
+ , mimeData(0)
+ , proposedAction(Qt::MoveAction)
+ , supportedActions(Qt::MoveAction | Qt::CopyAction | Qt::LinkAction)
+ , active(false)
+ , listening(false)
+ {
+ }
+
+ void itemGeometryChanged(QSGItem *, const QRectF &, const QRectF &);
+ void start() { start(supportedActions); }
+ void start(Qt::DropActions supportedActions);
+ void setTarget(QSGItem *item);
+
+ QSGDragGrabber dragGrabber;
+
+ QDeclarativeGuard<QObject> source;
+ QDeclarativeGuard<QObject> target;
+ QSGItem *attachedItem;
+ QSGDragMimeData *mimeData;
+ Qt::DropAction proposedAction;
+ Qt::DropActions supportedActions;
+ bool active : 1;
+ bool listening : 1;
+ QPointF hotSpot;
+ QStringList keys;
+};
+
+/*!
+ \qmlclass Drag QSGDrag
+ \inqmlmodule QtQuick 2
+ \brief The Drag attached property provides drag and drop events for moved Items.
+
+ Using the Drag attached property any Item can made a source of drag and drop
+ events within a scene.
+
+ When a drag is \l active on an item any change in that items position will
+ generate a drag events that will be sent to any DropArea that intersects
+ the with new position of the item. Other items which implement drag and
+ drop event handlers can also receive these events.
+
+ The following snippet shows how an item can be dragged with a MouseArea.
+ However, dragging is not limited to mouse drags, anything that can move an item
+ can generate drag events, this can include touch events, animations and bindings.
+
+ \snippet doc/src/snippets/declarative/drag.qml 0
+
+ A drag can be terminated either by cancelling it with Drag.cancel() or setting
+ Drag.active to false, or it can be terminated with a drop event by calling
+ Drag.drop(). If the drop event is accepted Drag.drop() will return the
+ \l {supportedActions}{drop action} chosen by the recipient of the event,
+ otherwise it will return Qt.IgnoreAction.
+
+*/
+
+QSGDragAttached *QSGDragAttached::properties(QObject *obj)
+{
+ QSGDragAttached *rv = attachedProperties.value(obj);
+ if (!rv) {
+ rv = new QSGDragAttached(obj);
+ attachedProperties.insert(obj, rv);
+ }
+ return rv;
+}
+
+QHash<QObject*, QSGDragAttached *> QSGDragAttached::attachedProperties;
+
+void QSGDragAttachedPrivate::itemGeometryChanged(QSGItem *, const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ Q_Q(QSGDragAttached);
+ if (newGeometry.topLeft() == oldGeometry.topLeft() || !active)
+ return;
+
+ if (QSGCanvas *canvas = attachedItem->canvas()) {
+ QPoint scenePos = attachedItem->mapToScene(hotSpot).toPoint();
+ QDragMoveEvent event(scenePos, mimeData->m_supportedActions, mimeData, Qt::NoButton, Qt::NoModifier);
+ QSGDropEventEx::setProposedAction(&event, proposedAction);
+ QSGCanvasPrivate::get(canvas)->deliverDragEvent(&dragGrabber, &event);
+ if (target != dragGrabber.target()) {
+ target = dragGrabber.target();
+ emit q->targetChanged();
+ }
+ }
+}
+
+QSGDragAttached::QSGDragAttached(QObject *parent)
+ : QObject(*new QSGDragAttachedPrivate, parent)
+{
+ Q_D(QSGDragAttached);
+ d->attachedItem = qobject_cast<QSGItem *>(parent);
+ d->source = d->attachedItem;
+}
+
+QSGDragAttached::~QSGDragAttached()
+{
+ Q_D(QSGDragAttached);
+ delete d->mimeData;
+}
+
+/*!
+ \qmlattachedproperty bool QtQuick2::Drag::active
+
+ This property holds whether a drag event sequence is currently active.
+
+ Setting this property to true will send a QDragEnter event to the scene
+ with the item's current position. Setting it to false will send a
+ QDragLeave event.
+
+ While a drag is active any change in an item's position will send a QDragMove
+ event with item's new position to the scene.
+*/
+
+bool QSGDragAttached::isActive() const
+{
+ Q_D(const QSGDragAttached);
+ return d->active;
+}
+
+void QSGDragAttached::setActive(bool active)
+{
+ Q_D(QSGDragAttached);
+ if (d->active != active) {
+ if (active)
+ d->start(d->supportedActions);
+ else
+ cancel();
+ }
+}
+
+/*!
+ \qmlattachedproperty Object QtQuick2::Drag::source
+
+ This property holds an object that is identified to recipients of drag events as
+ the source of the events. By default this is the item Drag property is attached to.
+
+ Changes to source while a Drag is active don't take effect until a new drag is started.
+*/
+
+QObject *QSGDragAttached::source() const
+{
+ Q_D(const QSGDragAttached);
+ return d->source;
+}
+
+void QSGDragAttached::setSource(QObject *item)
+{
+ Q_D(QSGDragAttached);
+ if (d->source != item) {
+ d->source = item;
+ emit sourceChanged();
+ }
+}
+
+void QSGDragAttached::resetSource()
+{
+ Q_D(QSGDragAttached);
+ if (d->source != d->attachedItem) {
+ d->source = d->attachedItem;
+ emit sourceChanged();
+ }
+}
+
+/*!
+ \qmlattachedproperty Object QtQuick2::Drag::target
+
+ While a drag is active this property holds the last object to accept an
+ enter event from the dragged item, if the current drag position doesn't
+ intersect any accepting targets it is null.
+
+ When a drag is not active this property holds the object that accepted
+ the drop event that ended the drag, if no object accepted the drop or
+ the drag was cancelled the target will then be null.
+*/
+
+QObject *QSGDragAttached::target() const
+{
+ Q_D(const QSGDragAttached);
+ return d->target;
+}
+
+/*!
+ \qmlattachedproperty QPointF QtQuick2::Drag::hotSpot
+
+ This property holds the drag position relative to the top left of the item.
+
+ By default this is (0, 0).
+
+ Changes to hotSpot will take effect when the next event is sent.
+*/
+
+QPointF QSGDragAttached::hotSpot() const
+{
+ Q_D(const QSGDragAttached);
+ return d->hotSpot;
+}
+
+void QSGDragAttached::setHotSpot(const QPointF &hotSpot)
+{
+ Q_D(QSGDragAttached);
+ if (d->hotSpot != hotSpot) {
+ d->hotSpot = hotSpot;
+ emit hotSpotChanged();
+ // Send a move event if active?
+ }
+}
+
+/*!
+ \qmlattachedproperty stringlist QtQuick2::Drag::keys
+
+ This property holds a list of keys that can be used by a DropArea to filter drag events.
+
+ Changes to keys while a Drag is active don't take effect until a new drag is started.
+*/
+
+QStringList QSGDragAttached::keys() const
+{
+ Q_D(const QSGDragAttached);
+ return d->keys;
+}
+
+void QSGDragAttached::setKeys(const QStringList &keys)
+{
+ Q_D(QSGDragAttached);
+ if (d->keys != keys) {
+ d->keys = keys;
+ emit keysChanged();
+ }
+}
+
+/*!
+ \qmlattachedproperty flags QtQuick2::Drag::supportedActions
+
+ This property holds return values of Drag.drop() supported by the drag source.
+
+ Changes to supportedActions while a Drag is active don't take effect
+ until a new drag is started.
+*/
+
+Qt::DropActions QSGDragAttached::supportedActions() const
+{
+ Q_D(const QSGDragAttached);
+ return d->supportedActions;
+}
+
+void QSGDragAttached::setSupportedActions(Qt::DropActions actions)
+{
+ Q_D(QSGDragAttached);
+ if (d->supportedActions != actions) {
+ d->supportedActions = actions;
+ emit supportedActionsChanged();
+ }
+}
+
+/*!
+ \qmlattachedproperty enumeration QtQuick2::Drag::proposedAction
+
+ This property holds an action that is recommended by the drag source as a
+ return value from Drag.drop().
+
+ Changes to proposedAction will take effect when the next event is sent.
+*/
+
+Qt::DropAction QSGDragAttached::proposedAction() const
+{
+ Q_D(const QSGDragAttached);
+ return d->proposedAction;
+}
+
+void QSGDragAttached::setProposedAction(Qt::DropAction action)
+{
+ Q_D(QSGDragAttached);
+ if (d->proposedAction != action) {
+ d->proposedAction = action;
+ emit proposedActionChanged();
+ // send a move event with the new default action if active?
+ }
+}
+
+void QSGDragAttachedPrivate::start(Qt::DropActions supportedActions)
+{
+ Q_Q(QSGDragAttached);
+ Q_ASSERT(!active);
+
+ if (QSGCanvas *canvas = attachedItem ? attachedItem->canvas() : 0) {
+ if (!mimeData)
+ mimeData = new QSGDragMimeData;
+ if (!listening) {
+ QSGItemPrivate::get(attachedItem)->addItemChangeListener(this, QSGItemPrivate::Geometry);
+ listening = true;
+ }
+
+ mimeData->m_source = source;
+ mimeData->m_supportedActions = supportedActions;
+ mimeData->m_keys = keys;
+ active = true;
+
+ QPoint scenePos = attachedItem->mapToScene(hotSpot).toPoint();
+ QDragEnterEvent event(scenePos, supportedActions, mimeData, Qt::NoButton, Qt::NoModifier);
+ QSGDropEventEx::setProposedAction(&event, proposedAction);
+ QSGCanvasPrivate::get(canvas)->deliverDragEvent(&dragGrabber, &event);
+
+ emit q->activeChanged();
+ if (target != dragGrabber.target()) {
+ target = dragGrabber.target();
+ emit q->targetChanged();
+ }
+ }
+}
+
+/*!
+ \qmlattachedmethod void QtQuick2::Drag::start(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 QSGDragAttached::start(QDeclarativeV8Function *args)
+{
+ Q_D(QSGDragAttached);
+ if (d->active)
+ cancel();
+
+ Qt::DropActions supportedActions = d->supportedActions;
+ // check arguments for supportedActions, maybe data?
+ if (args->Length() >= 1) {
+ v8::Local<v8::Value> v = (*args)[0];
+ if (v->IsInt32())
+ supportedActions = Qt::DropActions(v->Int32Value());
+ }
+
+ d->start(supportedActions);
+}
+
+/*!
+ \qmlattachedmethod enum QtQuick2::Drag::drop()
+
+ Ends a drag sequence by sending a drop event to the target item.
+
+ Returns the action accepted by the target item. If the target item or a parent doesn't accept
+ the drop event then Qt.IgnoreAction will be returned.
+
+ The returned drop action may be one of:
+
+ \list
+ \o Qt.CopyAction Copy the data to the target
+ \o Qt.MoveAction Move the data from the source to the target
+ \o Qt.LinkAction Create a link from the source to the target.
+ \o Qt.IgnoreAction Ignore the action (do nothing with the data).
+ \endlist
+
+*/
+
+int QSGDragAttached::drop()
+{
+ Q_D(QSGDragAttached);
+ Qt::DropAction acceptedAction = Qt::IgnoreAction;
+
+ if (!d->active)
+ return acceptedAction;
+
+ QObject *target = 0;
+
+ if (QSGCanvas *canvas = d->attachedItem->canvas()) {
+ QPoint scenePos = d->attachedItem->mapToScene(d->hotSpot).toPoint();
+
+ QDropEvent event(
+ scenePos, d->mimeData->m_supportedActions, d->mimeData, Qt::NoButton, Qt::NoModifier);
+ QSGDropEventEx::setProposedAction(&event, d->proposedAction);
+ QSGCanvasPrivate::get(canvas)->deliverDragEvent(&d->dragGrabber, &event);
+
+ if (event.isAccepted()) {
+ acceptedAction = event.dropAction();
+ target = d->dragGrabber.target();
+ }
+ }
+
+ d->active = false;
+ if (d->target != target) {
+ d->target = target;
+ emit targetChanged();
+ }
+
+ emit activeChanged();
+ return acceptedAction;
+}
+
+/*!
+ \qmlattachedmethod void QtQuick2::Drag::cancel()
+
+ Ends a drag sequence.
+*/
+
+void QSGDragAttached::cancel()
+{
+ Q_D(QSGDragAttached);
+ if (!d->active)
+ return;
+
+ if (QSGCanvas *canvas = d->attachedItem->canvas()) {
+ QDragLeaveEvent event;
+ QSGCanvasPrivate::get(canvas)->deliverDragEvent(&d->dragGrabber, &event);
+ }
+
+ d->active = false;
+ if (d->target) {
+ d->target = 0;
+ emit targetChanged();
+ }
+ emit activeChanged();
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/items/qsgdrag_p.h b/src/declarative/items/qsgdrag_p.h
new file mode 100644
index 0000000000..a1b6cdca9b
--- /dev/null
+++ b/src/declarative/items/qsgdrag_p.h
@@ -0,0 +1,212 @@
+// Commit: c6e6a35aeb8794d68a3ca0c4e27a3a1181c066b5
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSGDRAG_P_H
+#define QSGDRAG_P_H
+
+#include <qsgitem.h>
+
+#include <private/qv8engine_p.h>
+
+#include <QtCore/qmimedata.h>
+#include <QtCore/qstringlist.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QSGItem;
+class QSGDrag;
+class QSGDragPrivate;
+
+class QSGDragGrabber
+{
+ class Item : public QDeclarativeGuard<QSGItem>
+ {
+ public:
+ Item(QSGItem *item) : QDeclarativeGuard<QSGItem>(item) {}
+
+ QIntrusiveListNode node;
+ protected:
+ void objectDestroyed(QSGItem *) { delete this; }
+ };
+
+ typedef QIntrusiveList<Item, &Item::node> ItemList;
+
+public:
+ QSGDragGrabber() : m_target(0) {}
+ ~QSGDragGrabber() { while (!m_items.isEmpty()) delete m_items.first(); }
+
+
+ QObject *target() const
+ {
+ if (m_target)
+ return m_target;
+ else if (!m_items.isEmpty())
+ return *m_items.first();
+ else
+ return 0;
+ }
+ void setTarget(QObject *target) { m_target = target; }
+ void resetTarget() { m_target = 0; }
+
+ typedef ItemList::iterator iterator;
+ iterator begin() { return m_items.begin(); }
+ iterator end() { return m_items.end(); }
+
+ void grab(QSGItem *item) { m_items.insert(new Item(item)); }
+ iterator release(iterator at) { Item *item = *at; at = at.erase(); delete item; return at; }
+
+private:
+
+ ItemList m_items;
+ QObject *m_target;
+};
+
+class QSGDropEventEx : public QDropEvent
+{
+public:
+ void setProposedAction(Qt::DropAction action) { default_action = action; drop_action = action; }
+
+ static void setProposedAction(QDropEvent *event, Qt::DropAction action) {
+ static_cast<QSGDropEventEx *>(event)->setProposedAction(action);
+ }
+
+ void copyActions(const QDropEvent &from) {
+ default_action = from.proposedAction(); drop_action = from.dropAction(); }
+
+ static void copyActions(QDropEvent *to, const QDropEvent &from) {
+ static_cast<QSGDropEventEx *>(to)->copyActions(from);
+ }
+};
+
+class QSGDragMimeData : public QMimeData
+{
+ Q_OBJECT
+public:
+ QSGDragMimeData()
+ : m_source(0)
+ {
+ }
+
+ QStringList keys() const { return m_keys; }
+ QObject *source() const { return m_source; }
+
+private:
+ QObject *m_source;
+ Qt::DropActions m_supportedActions;
+ QStringList m_keys;
+
+ friend class QSGDragAttached;
+ friend class QSGDragAttachedPrivate;
+};
+
+class QDeclarativeV8Function;
+
+class QSGDragAttachedPrivate;
+class QSGDragAttached : public QObject
+{
+ Q_OBJECT
+ 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(Qt::DropActions supportedActions READ supportedActions WRITE setSupportedActions NOTIFY supportedActionsChanged)
+ Q_PROPERTY(Qt::DropAction proposedAction READ proposedAction WRITE setProposedAction NOTIFY proposedActionChanged)
+public:
+ QSGDragAttached(QObject *parent);
+ ~QSGDragAttached();
+
+ bool isActive() const;
+ void setActive(bool active);
+
+ QObject *source() const;
+ void setSource(QObject *item);
+ void resetSource();
+
+ QObject *target() const;
+
+ QPointF hotSpot() const;
+ void setHotSpot(const QPointF &hotSpot);
+
+ QStringList keys() const;
+ void setKeys(const QStringList &keys);
+
+ Qt::DropActions supportedActions() const;
+ void setSupportedActions(Qt::DropActions actions);
+
+ Qt::DropAction proposedAction() const;
+ void setProposedAction(Qt::DropAction action);
+
+ Q_INVOKABLE int drop();
+
+ static QSGDragAttached *properties(QObject *obj);
+
+public Q_SLOTS:
+ void start(QDeclarativeV8Function *);
+ void cancel();
+
+Q_SIGNALS:
+ void activeChanged();
+ void sourceChanged();
+ void targetChanged();
+ void hotSpotChanged();
+ void keysChanged();
+ void supportedActionsChanged();
+ void proposedActionChanged();
+
+private:
+ static QHash<QObject*, QSGDragAttached *> attachedProperties;
+
+ Q_DECLARE_PRIVATE(QSGDragAttached)
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/items/qsgdragtarget.cpp b/src/declarative/items/qsgdragtarget.cpp
deleted file mode 100644
index 5b6d36ee11..0000000000
--- a/src/declarative/items/qsgdragtarget.cpp
+++ /dev/null
@@ -1,363 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qsgdragtarget_p.h"
-#include "qsgitem_p.h"
-#include "qsgcanvas.h"
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \qmlclass DragEvent QSGDragEvent
- \brief The DragEvent object provides information about a drag event.
-
- The position of the drag event can be obtained from the \l x and \l
- properties, the \l keys property identifies the drag keys of the event
- source and the \l data property contains the payload of the drag event.
-*/
-
-/*!
- \qmlproperty real DragEvent::x
-
- This property holds the x coordinate of a drag event.
-*/
-
-/*!
- \qmlproperty real DragEvent::y
-
- This property holds the y coordinate of a drag event.
-*/
-
-/*!
- \qmlproperty stringlist DragEvent::keys
-
- This property holds a list of keys identifying the data type or source of a
- drag event.
-*/
-
-/*!
- \qmlproperty variant DragEvent::data
-
- This property holds data payload of a drag event.
-*/
-
-/*!
- \qmlproperty real DragEvent::accepted
-
- This property holds whether the drag event was accepted by a handler.
-
- The default value is true.
-*/
-
-class QSGDragTargetPrivate : public QSGItemPrivate
-{
- Q_DECLARE_PUBLIC(QSGDragTarget)
-
-public:
- QSGDragTargetPrivate();
- ~QSGDragTargetPrivate();
-
- bool hasMatchingKey(const QStringList &keys) const;
-
- QStringList keys;
- QRegExp keyRegExp;
- QVariant dragData;
- QPointF dragPosition;
- QSGItem *dropItem;
- bool containsDrag : 1;
-};
-
-QSGDragTargetPrivate::QSGDragTargetPrivate()
- : dropItem(0)
- , containsDrag(false)
-{
-}
-
-QSGDragTargetPrivate::~QSGDragTargetPrivate()
-{
-}
-
-/*!
- \qmlclass DragTarget QSGDragTarget
- \brief The DragTarget item provides drag and drop handling.
-
- A DragTarget is an invisible item which receives events when another item
- is dragged over it.
-
- A MouseArea item can be used to drag items.
-
- The \l keys property can be used to filter drag events which don't include
- a matching key.
-
- The \l dropItem property is communicated to the source of a drag event as
- the recipient of a drop on the drag target.
-
- The \l delegate property provides a means to specify a component to be
- instantiated for each active drag over a drag target.
-*/
-
-QSGDragTarget::QSGDragTarget(QSGItem *parent)
- : QSGItem(*new QSGDragTargetPrivate, parent)
-{
-}
-
-QSGDragTarget::~QSGDragTarget()
-{
-}
-
-/*!
- \qmlproperty bool DragTarget::containsDrag
-
- This property identifies whether the DragTarget currently contains any
- dragged items.
-*/
-
-bool QSGDragTarget::containsDrag() const
-{
- Q_D(const QSGDragTarget);
- return d->containsDrag;
-}
-
-/*!
- \qmlproperty stringlist DragTarget::keys
-
- This property holds a list of drag keys a DragTarget will accept.
-*/
-
-QStringList QSGDragTarget::keys() const
-{
- Q_D(const QSGDragTarget);
- return d->keys;
-}
-
-void QSGDragTarget::setKeys(const QStringList &keys)
-{
- Q_D(QSGDragTarget);
- if (d->keys != keys) {
- d->keys = keys;
-
- if (keys.isEmpty()) {
- d->keyRegExp = QRegExp();
- } else {
- QString pattern = QLatin1Char('(') + QRegExp::escape(keys.first());
- for (int i = 1; i < keys.count(); ++i)
- pattern += QLatin1Char('|') + QRegExp::escape(keys.at(i));
- pattern += QLatin1Char(')');
- d->keyRegExp = QRegExp(pattern.replace(QLatin1String("\\*"), QLatin1String(".+")));
- }
- emit keysChanged();
- }
-}
-
-/*!
- \qmlproperty Item DragTarget::dropItem
-
- This property identifies an item as the recipient of a drop event within
- a DragTarget.
-
- \sa MouseArea::drag.dropItem
-*/
-
-QSGItem *QSGDragTarget::dropItem() const
-{
- Q_D(const QSGDragTarget);
- return d->dropItem;
-}
-
-void QSGDragTarget::setDropItem(QSGItem *item)
-{
- Q_D(QSGDragTarget);
- if (d->dropItem != item) {
- d->dropItem = item;
- emit dropItemChanged();
- }
-}
-
-void QSGDragTarget::resetDropItem()
-{
- Q_D(QSGDragTarget);
- if (d->dropItem) {
- d->dropItem = 0;
- emit dropItemChanged();
- }
-}
-
-qreal QSGDragTarget::dragX() const
-{
- Q_D(const QSGDragTarget);
- return d->dragPosition.x();
-}
-
-qreal QSGDragTarget::dragY() const
-{
- Q_D(const QSGDragTarget);
- return d->dragPosition.y();
-}
-
-QVariant QSGDragTarget::dragData() const
-{
- Q_D(const QSGDragTarget);
- return d->dragData;
-}
-
-/*!
- \qmlsignal DragTarget::onPositionChanged(DragEvent drag)
- \qmlattachedsignal DragTarget::onPositionChanged(DragEvent drag)
-
- This handler is called when the position of a drag has changed.
-*/
-
-void QSGDragTarget::dragMoveEvent(QSGDragEvent *event)
-{
- Q_D(QSGDragTarget);
- if (!d->containsDrag) {
- event->setAccepted(false);
- return;
- }
-
- event->setDropItem(d->dropItem);
-
- d->dragPosition = event->position();
- emit dragPositionChanged();
-
- QSGDragTargetEvent dragTargetEvent(event);
- emit positionChanged(&dragTargetEvent);
-}
-
-bool QSGDragTargetPrivate::hasMatchingKey(const QStringList &keys) const
-{
- if (keyRegExp.isEmpty())
- return true;
-
- foreach (const QString &key, keys) {
- if (keyRegExp.exactMatch(key))
- return true;
- }
- return false;
-}
-
-/*!
- \qmlsignal DragTarget::onEntered(DragEvent drag)
- \qmlattachedsignal DragTarget::onEntered(DragEvent drag)
-
- This handler is called when a drag enters the bounds of a DragTarget.
-*/
-
-void QSGDragTarget::dragEnterEvent(QSGDragEvent *event)
-{
- Q_D(QSGDragTarget);
- if (!d->effectiveEnable || !d->hasMatchingKey(event->keys()) || d->containsDrag) {
- event->setAccepted(false);
- return;
- }
-
- event->setDropItem(d->dropItem);
-
- QSGDragTargetEvent dragTargetEvent(event);
- emit entered(&dragTargetEvent);
-
- if (event->isAccepted()) {
-
- d->dragData = event->data();
- d->containsDrag = true;
- if (!d->dragData.isNull())
- emit dragDataChanged();
- emit containsDragChanged();
- }
-}
-
-/*!
- \qmlsignal DragTarget::onExited(DragEvent drag)
- \qmlattachedsignal DragTarget::onExited(DragEvent drag)
-
- This handler is called when a drag exits the bounds of a DragTarget.
-*/
-
-void QSGDragTarget::dragExitEvent(QSGDragEvent *event)
-{
- Q_D(QSGDragTarget);
- if (!d->containsDrag) {
- event->setAccepted(false);
- return;
- }
-
- QSGDragTargetEvent dragTargetEvent(event);
- emit exited(&dragTargetEvent);
-
- d->containsDrag = false;
- emit containsDragChanged();
- if (!d->dragData.isNull()) {
- d->dragData = QVariant();
- emit dragDataChanged();
- }
-}
-
-/*!
- \qmlsignal DragTarget::onDropped(DragEvent drag)
- \qmlattachedsignal DragTarget::onDropped(DragEvent drag)
-
- This handler is called when a drop event occurs within the bounds of a
- a DragTarget.
-*/
-
-void QSGDragTarget::dragDropEvent(QSGDragEvent *event)
-{
- Q_D(QSGDragTarget);
- if (!d->containsDrag) {
- event->setAccepted(false);
- return;
- }
-
- event->setDropItem(d->dropItem);
-
- QSGDragTargetEvent dragTargetEvent(event);
- emit dropped(&dragTargetEvent);
-
- d->containsDrag = false;
- emit containsDragChanged();
- if (!d->dragData.isNull()) {
- d->dragData = QVariant();
- emit dragDataChanged();
- }
-}
-
-QT_END_NAMESPACE
-
diff --git a/src/declarative/items/qsgdroparea.cpp b/src/declarative/items/qsgdroparea.cpp
new file mode 100644
index 0000000000..a1b81be1ae
--- /dev/null
+++ b/src/declarative/items/qsgdroparea.cpp
@@ -0,0 +1,426 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsgdroparea_p.h"
+#include "qsgdrag_p.h"
+#include "qsgitem_p.h"
+#include "qsgcanvas.h"
+
+#include <private/qdeclarativeengine_p.h>
+
+QSGDropAreaDrag::QSGDropAreaDrag(QSGDropAreaPrivate *d, QObject *parent)
+ : QObject(parent)
+ , d(d)
+{
+}
+
+QSGDropAreaDrag::~QSGDropAreaDrag()
+{
+}
+
+class QSGDropAreaPrivate : public QSGItemPrivate
+{
+ Q_DECLARE_PUBLIC(QSGDropArea)
+
+public:
+ QSGDropAreaPrivate();
+ ~QSGDropAreaPrivate();
+
+ bool hasMatchingKey(const QStringList &keys) const;
+
+ QStringList getKeys(const QMimeData *mimeData) const;
+
+ QStringList keys;
+ QRegExp keyRegExp;
+ QPointF dragPosition;
+ QSGDropAreaDrag *drag;
+ QDeclarativeGuard<QObject> source;
+ QDeclarativeGuard<QMimeData> mimeData;
+};
+
+QSGDropAreaPrivate::QSGDropAreaPrivate()
+ : drag(0)
+{
+}
+
+QSGDropAreaPrivate::~QSGDropAreaPrivate()
+{
+ delete drag;
+}
+
+/*!
+ \qmlclass DropArea QSGDropArea
+ \inqmlmodule QtQuick 2
+ \brief The DropArea item provides drag and drop handling.
+
+ A DropArea is an invisible item which receives events when other items are
+ dragged over it.
+
+ The Drag attached property can be used to notify the DropArea when an Item is
+ dragged over it.
+
+ The \l keys property can be used to filter drag events which don't include
+ a matching key.
+
+ The \l dropItem property is communicated to the source of a drag event as
+ the recipient of a drop on the drag target.
+
+ The \l delegate property provides a means to specify a component to be
+ instantiated for each active drag over a drag target.
+*/
+
+QSGDropArea::QSGDropArea(QSGItem *parent)
+ : QSGItem(*new QSGDropAreaPrivate, parent)
+{
+ setFlags(ItemAcceptsDrops);
+}
+
+QSGDropArea::~QSGDropArea()
+{
+}
+
+/*!
+ \qmlproperty bool QtQuick2::DropArea::containsDrag
+
+ This property identifies whether the DropArea currently contains any
+ dragged items.
+*/
+
+bool QSGDropArea::containsDrag() const
+{
+ Q_D(const QSGDropArea);
+ return d->mimeData;
+}
+
+/*!
+ \qmlproperty stringlist QtQuick2::DropArea::keys
+
+ This property holds a list of drag keys a DropArea will accept.
+
+ If no keys are listed the DropArea will accept events from any drag source,
+ otherwise the drag source must have at least one compatible key.
+
+ \sa QtQuick2::Drag::keys
+*/
+
+QStringList QSGDropArea::keys() const
+{
+ Q_D(const QSGDropArea);
+ return d->keys;
+}
+
+void QSGDropArea::setKeys(const QStringList &keys)
+{
+ Q_D(QSGDropArea);
+ if (d->keys != keys) {
+ d->keys = keys;
+
+ if (keys.isEmpty()) {
+ d->keyRegExp = QRegExp();
+ } else {
+ QString pattern = QLatin1Char('(') + QRegExp::escape(keys.first());
+ for (int i = 1; i < keys.count(); ++i)
+ pattern += QLatin1Char('|') + QRegExp::escape(keys.at(i));
+ pattern += QLatin1Char(')');
+ d->keyRegExp = QRegExp(pattern.replace(QLatin1String("\\*"), QLatin1String(".+")));
+ }
+ emit keysChanged();
+ }
+}
+
+QSGDropAreaDrag *QSGDropArea::drag()
+{
+ Q_D(QSGDropArea);
+ if (!d->drag)
+ d->drag = new QSGDropAreaDrag(d);
+ return d->drag;
+}
+
+/*!
+ \qmlproperty Object QtQuick2::DropArea::drag.source
+
+ This property holds the source of a drag.
+*/
+
+QObject *QSGDropAreaDrag::source() const
+{
+ return d->source;
+}
+
+/*!
+ \qmlproperty qreal QtQuick2::DropArea::drag.x
+ \qmlproperty qreal QtQuick2::DropArea::drag.y
+
+ These properties hold the coordinates of the last drag event.
+*/
+
+qreal QSGDropAreaDrag::x() const
+{
+ return d->dragPosition.x();
+}
+
+qreal QSGDropAreaDrag::y() const
+{
+ return d->dragPosition.y();
+}
+
+/*!
+ \qmlsignal QtQuick2::DropArea::onPositionChanged(DragEvent drag)
+
+ This handler is called when the position of a drag has changed.
+*/
+
+void QSGDropArea::dragMoveEvent(QDragMoveEvent *event)
+{
+ Q_D(QSGDropArea);
+ if (!d->mimeData)
+ return;
+
+ d->dragPosition = event->pos();
+ if (d->drag)
+ emit d->drag->positionChanged();
+
+ event->accept();
+ QSGDropEvent dragTargetEvent(d, event);
+ emit positionChanged(&dragTargetEvent);
+}
+
+bool QSGDropAreaPrivate::hasMatchingKey(const QStringList &keys) const
+{
+ if (keyRegExp.isEmpty())
+ return true;
+
+ foreach (const QString &key, keys) {
+ if (keyRegExp.exactMatch(key))
+ return true;
+ }
+ return false;
+}
+
+QStringList QSGDropAreaPrivate::getKeys(const QMimeData *mimeData) const
+{
+ if (const QSGDragMimeData *dragMime = qobject_cast<const QSGDragMimeData *>(mimeData))
+ return dragMime->keys();
+ return mimeData->formats();
+}
+
+/*!
+ \qmlsignal QtQuick2::DropArea::onEntered(DragEvent drag)
+
+ This handler is called when a \a drag enters the bounds of a DropArea.
+*/
+
+void QSGDropArea::dragEnterEvent(QDragEnterEvent *event)
+{
+ Q_D(QSGDropArea);
+ const QMimeData *mimeData = event->mimeData();
+ if (!d->effectiveEnable || d->mimeData || !mimeData || !d->hasMatchingKey(d->getKeys(mimeData)))
+ return;
+
+ d->dragPosition = event->pos();
+
+ event->accept();
+ QSGDropEvent dragTargetEvent(d, event);
+ emit entered(&dragTargetEvent);
+
+ if (event->isAccepted()) {
+ d->mimeData = const_cast<QMimeData *>(mimeData);
+ if (QSGDragMimeData *dragMime = qobject_cast<QSGDragMimeData *>(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();
+ }
+}
+
+/*!
+ \qmlsignal QtQuick2::DropArea::onExited()
+
+ This handler is called when a drag exits the bounds of a DropArea.
+*/
+
+void QSGDropArea::dragLeaveEvent(QDragLeaveEvent *)
+{
+ Q_D(QSGDropArea);
+ if (!d->mimeData)
+ return;
+
+ emit exited();
+
+ d->mimeData = 0;
+ d->source = 0;
+ emit containsDragChanged();
+ if (d->drag)
+ emit d->drag->sourceChanged();
+}
+
+/*!
+ \qmlsignal QtQuick2::DropArea::onDropped(DragEvent drop)
+
+ This handler is called when a drop event occurs within the bounds of a
+ a DropArea.
+*/
+
+void QSGDropArea::dropEvent(QDropEvent *event)
+{
+ Q_D(QSGDropArea);
+ if (!d->mimeData)
+ return;
+
+ QSGDropEvent dragTargetEvent(d, event);
+ emit dropped(&dragTargetEvent);
+
+ d->mimeData = 0;
+ d->source = 0;
+ emit containsDragChanged();
+ if (d->drag)
+ emit d->drag->sourceChanged();
+}
+
+/*!
+ \qmlclass DragEvent QSGDragEvent
+ \inqmlmodule QtQuick 2
+ \brief The DragEvent object provides information about a drag 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.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::DragEvent::x
+
+ This property holds the x coordinate of a drag event.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::DragEvent::y
+
+ This property holds the y coordinate of a drag event.
+*/
+
+/*!
+ \qmlproperty Object QtQuick2::DragEvent::drag.source
+
+ This property holds the source of a drag event.
+*/
+
+QObject *QSGDropEvent::source()
+{
+ if (const QSGDragMimeData *dragMime = qobject_cast<const QSGDragMimeData *>(event->mimeData()))
+ return dragMime->source();
+ else
+ return event->source();
+}
+
+/*!
+ \qmlproperty stringlist QtQuick2::DragEvent::keys
+
+ This property holds a list of keys identifying the data type or source of a
+ drag event.
+*/
+
+QStringList QSGDropEvent::keys() const
+{
+ return d->getKeys(event->mimeData());
+}
+
+/*!
+ \qmlproperty enum QtQuick2::DragEvent::action
+
+ This property holds the action that the \l source is to perform on an accepted drop.
+
+ The drop action may be one of:
+
+ \list
+ \o Qt.CopyAction Copy the data to the target
+ \o Qt.MoveAction Move the data from the source to the target
+ \o Qt.LinkAction Create a link from the source to the target.
+ \o Qt.IgnoreAction Ignore the action (do nothing with the data).
+ \endlist
+*/
+
+/*!
+ \qmlproperty flags QtQuick2::DragEvent::supportedActions
+
+ This property holds the set of \l {action}{actions} supported by the
+ drag source.
+*/
+
+/*!
+ \qmlproperty real QtQuick2::DragEvent::accepted
+
+ This property holds whether the drag event was accepted by a handler.
+
+ The default value is true.
+*/
+
+/*!
+ \qmlmethod void QtQuick2::DragEvent::accept()
+ \qmlmethod void QtQuick2::DragEvent::accept(enum action)
+
+ Accepts the drag event.
+
+ If an \a action is specified it will overwrite the value of the \l action property.
+*/
+
+void QSGDropEvent::accept(QDeclarativeV8Function *args)
+{
+ Qt::DropAction action = event->dropAction();
+
+ if (args->Length() >= 1) {
+ v8::Local<v8::Value> v = (*args)[0];
+ if (v->IsInt32())
+ action = Qt::DropAction(v->Int32Value());
+ }
+ // get action from arguments.
+ event->setDropAction(action);
+ event->accept();
+}
+
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/items/qsgdragtarget_p.h b/src/declarative/items/qsgdroparea_p.h
index 004bec1f20..cd51f57e0b 100644
--- a/src/declarative/items/qsgdragtarget_p.h
+++ b/src/declarative/items/qsgdroparea_p.h
@@ -39,11 +39,15 @@
**
****************************************************************************/
-#ifndef QSGDRAGTARGET_P_H
-#define QSGDRAGTARGET_P_H
+#ifndef QSGDROPAREA_P_H
+#define QSGDROPAREA_P_H
#include "qsgitem.h"
-#include "qsgevent.h"
+
+#include <private/qdeclarativeguard_p.h>
+#include <private/qv8engine_p.h>
+
+#include <QtGui/qevent.h>
QT_BEGIN_HEADER
@@ -51,44 +55,78 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
-class QSGDragTargetEvent : public QObject
+class QSGDropAreaPrivate;
+class QSGDropEvent : public QObject
{
Q_OBJECT
Q_PROPERTY(qreal x READ x)
Q_PROPERTY(qreal y READ y)
- Q_PROPERTY(QVariant data READ data)
+ Q_PROPERTY(QObject *source READ source)
Q_PROPERTY(QStringList keys READ keys)
+ Q_PROPERTY(Qt::DropActions supportedActions READ supportedActions)
+ Q_PROPERTY(Qt::DropAction action READ action WRITE setAction RESET resetAction)
Q_PROPERTY(bool accepted READ accepted WRITE setAccepted)
public:
- QSGDragTargetEvent(QSGDragEvent *event) : _event(event) {}
+ QSGDropEvent(QSGDropAreaPrivate *d, QDropEvent *event) : d(d), event(event) {}
+
+ qreal x() const { return event->pos().x(); }
+ qreal y() const { return event->pos().y(); }
+
+ QObject *source();
+
+ Qt::DropActions supportedActions() const { return event->possibleActions(); }
+ Qt::DropAction action() const { return event->dropAction(); }
+ void setAction(Qt::DropAction action) { event->setDropAction(action); }
+ void resetAction() { event->setDropAction(event->proposedAction()); }
+
+ QStringList keys() const;
+
+ bool accepted() const { return event->isAccepted(); }
+ void setAccepted(bool accepted) { event->setAccepted(accepted); }
+
+ Q_INVOKABLE void accept(QDeclarativeV8Function *);
- qreal x() const { return _event->x(); }
- qreal y() const { return _event->y(); }
+private:
+ QSGDropAreaPrivate *d;
+ QDropEvent *event;
+};
- QVariant data() const { return _event->data(); }
- QStringList keys() const { return _event->keys(); }
+class QSGDropAreaDrag : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal x READ x NOTIFY positionChanged)
+ Q_PROPERTY(qreal y READ y NOTIFY positionChanged)
+ Q_PROPERTY(QObject *source READ source NOTIFY sourceChanged)
+public:
+ QSGDropAreaDrag(QSGDropAreaPrivate *d, QObject *parent = 0);
+ ~QSGDropAreaDrag();
- bool accepted() const { return _event->isAccepted(); }
- void setAccepted(bool accepted) { _event->setAccepted(accepted); }
+ qreal x() const;
+ qreal y() const;
+ QObject *source() const;
+
+Q_SIGNALS:
+ void positionChanged();
+ void sourceChanged();
private:
- QSGDragEvent *_event;
+ QSGDropAreaPrivate *d;
+
+ friend class QSGDropArea;
+ friend class QSGDropAreaPrivate;
};
-class QSGDragTargetPrivate;
-class Q_AUTOTEST_EXPORT QSGDragTarget : public QSGItem
+class QSGDropAreaPrivate;
+class Q_AUTOTEST_EXPORT QSGDropArea : public QSGItem
{
Q_OBJECT
Q_PROPERTY(bool containsDrag READ containsDrag NOTIFY containsDragChanged)
- Q_PROPERTY(QSGItem *dropItem READ dropItem WRITE setDropItem NOTIFY dropItemChanged RESET resetDropItem)
Q_PROPERTY(QStringList keys READ keys WRITE setKeys NOTIFY keysChanged)
- Q_PROPERTY(qreal dragX READ dragX NOTIFY dragPositionChanged)
- Q_PROPERTY(qreal dragY READ dragY NOTIFY dragPositionChanged)
- Q_PROPERTY(QVariant dragData READ dragData NOTIFY dragDataChanged)
+ Q_PROPERTY(QSGDropAreaDrag *drag READ drag CONSTANT)
public:
- QSGDragTarget(QSGItem *parent=0);
- ~QSGDragTarget();
+ QSGDropArea(QSGItem *parent=0);
+ ~QSGDropArea();
bool containsDrag() const;
void setContainsDrag(bool drag);
@@ -96,41 +134,33 @@ public:
QStringList keys() const;
void setKeys(const QStringList &keys);
- QSGItem *dropItem() const;
- void setDropItem(QSGItem *item);
- void resetDropItem();
-
- qreal dragX() const;
- qreal dragY() const;
- QVariant dragData() const;
+ QSGDropAreaDrag *drag();
Q_SIGNALS:
void containsDragChanged();
void keysChanged();
- void dropItemChanged();
- void dragPositionChanged();
- void dragDataChanged();
+ void sourceChanged();
- void entered(QSGDragTargetEvent *drag);
- void exited(QSGDragTargetEvent *drag);
- void positionChanged(QSGDragTargetEvent *drag);
- void dropped(QSGDragTargetEvent *drag);
+ void entered(QSGDropEvent *drag);
+ void exited();
+ void positionChanged(QSGDropEvent *drag);
+ void dropped(QSGDropEvent *drop);
protected:
- void dragMoveEvent(QSGDragEvent *event);
- void dragEnterEvent(QSGDragEvent *event);
- void dragExitEvent(QSGDragEvent *event);
- void dragDropEvent(QSGDragEvent *event);
+ void dragMoveEvent(QDragMoveEvent *event);
+ void dragEnterEvent(QDragEnterEvent *event);
+ void dragLeaveEvent(QDragLeaveEvent *event);
+ void dropEvent(QDropEvent *event);
private:
- Q_DISABLE_COPY(QSGDragTarget)
- Q_DECLARE_PRIVATE(QSGDragTarget)
+ Q_DISABLE_COPY(QSGDropArea)
+ Q_DECLARE_PRIVATE(QSGDropArea)
};
QT_END_NAMESPACE
-QML_DECLARE_TYPE(QSGDragTargetEvent)
-QML_DECLARE_TYPE(QSGDragTarget)
+QML_DECLARE_TYPE(QSGDropEvent)
+QML_DECLARE_TYPE(QSGDropArea)
QT_END_HEADER
diff --git a/src/declarative/items/qsgevent.h b/src/declarative/items/qsgevent.h
deleted file mode 100644
index d82ee809ae..0000000000
--- a/src/declarative/items/qsgevent.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QDRAGEVENT_H
-#define QDRAGEVENT_H
-
-#include <QtCore/qcoreevent.h>
-#include <QtCore/qnamespace.h>
-#include <QtCore/qpoint.h>
-#include <QtCore/qstringlist.h>
-#include <QtCore/qvariant.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QSGItem;
-
-class Q_DECLARATIVE_EXPORT QSGEvent : public QEvent
-{
-public:
- // XXX: Merge types into QEvent or formally reserve a suitable range.
- // Alternatively start from QEvent::User and add a SGUser value for use by items.
- enum SGType
- {
- SGDragEnter = 600,
- SGDragExit,
- SGDragMove,
- SGDragDrop
- };
-
- QSGEvent(QSGEvent::SGType type) : QEvent(Type(type)) {}
-
- SGType type() const { return SGType(QEvent::type()); }
-};
-
-class Q_DECLARATIVE_EXPORT QSGDragEvent : public QSGEvent
-{
-public:
- QSGDragEvent(
- SGType type,
- const QPointF &scenePosition,
- const QVariant &data,
- const QStringList &keys,
- QSGItem *grabItem = 0)
- : QSGEvent(type)
- , _scenePosition(scenePosition),
- _data(data)
- , _keys(keys)
- , _dropItem(0)
- , _grabItem(grabItem)
- {
- }
- QSGDragEvent(SGType type, const QSGDragEvent &event)
- : QSGEvent(type)
- , _scenePosition(event._scenePosition)
- , _position(event._position)
- , _data(event._data)
- , _keys(event._keys)
- , _dropItem(event._dropItem)
- , _grabItem(event._grabItem)
- {
- }
-
- QVariant data() const { return _data; }
-
- qreal x() const { return _position.x(); }
- qreal y() const { return _position.y(); }
- QPointF position() const { return _position; }
- void setPosition(const QPointF &position) { _position = position; }
-
- QPointF scenePosition() const { return _scenePosition; }
-
- QStringList keys() const { return _keys; }
-
- QSGItem *dropItem() const { return _dropItem; }
- void setDropItem(QSGItem *dropItem) { _dropItem = dropItem; }
-
- QSGItem *grabItem() const { return _grabItem; }
- void setGrabItem(QSGItem *item) { _grabItem = item; }
-
-private:
- QPointF _scenePosition;
- QPointF _position;
- QVariant _data;
- QStringList _keys;
- QSGItem *_dropItem;
- QSGItem *_grabItem;
-};
-
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif
-
diff --git a/src/declarative/items/qsgitem.cpp b/src/declarative/items/qsgitem.cpp
index 76a1f1bef9..8ede2a490e 100644
--- a/src/declarative/items/qsgitem.cpp
+++ b/src/declarative/items/qsgitem.cpp
@@ -44,7 +44,6 @@
#include "qsgcanvas.h"
#include <QtDeclarative/qjsengine.h>
#include "qsgcanvas_p.h"
-#include "qsgevent.h"
#include "qsgevents_p_p.h"
@@ -2882,24 +2881,26 @@ void QSGItem::hoverLeaveEvent(QHoverEvent *event)
Q_UNUSED(event);
}
-void QSGItem::dragMoveEvent(QSGDragEvent *event)
+void QSGItem::dragEnterEvent(QDragEnterEvent *event)
{
- event->setAccepted(false);
+ Q_UNUSED(event);
}
-void QSGItem::dragEnterEvent(QSGDragEvent *event)
+void QSGItem::dragMoveEvent(QDragMoveEvent *event)
{
- event->setAccepted(false);
+
+ Q_UNUSED(event);
}
-void QSGItem::dragExitEvent(QSGDragEvent *event)
+void QSGItem::dragLeaveEvent(QDragLeaveEvent *event)
{
- event->setAccepted(false);
+
+ Q_UNUSED(event);
}
-void QSGItem::dragDropEvent(QSGDragEvent *event)
+void QSGItem::dropEvent(QDropEvent *event)
{
- event->setAccepted(false);
+ Q_UNUSED(event);
}
bool QSGItem::childMouseEventFilter(QSGItem *, QEvent *)
@@ -3424,23 +3425,23 @@ void QSGItemPrivate::deliverHoverEvent(QHoverEvent *e)
}
}
-void QSGItemPrivate::deliverDragEvent(QSGDragEvent *e)
+void QSGItemPrivate::deliverDragEvent(QEvent *e)
{
Q_Q(QSGItem);
switch (e->type()) {
default:
Q_ASSERT(!"Unknown event type");
- case QSGEvent::SGDragEnter:
- q->dragEnterEvent(e);
+ case QEvent::DragEnter:
+ q->dragEnterEvent(static_cast<QDragEnterEvent *>(e));
break;
- case QSGEvent::SGDragExit:
- q->dragExitEvent(e);
+ case QEvent::DragLeave:
+ q->dragLeaveEvent(static_cast<QDragLeaveEvent *>(e));
break;
- case QSGEvent::SGDragMove:
- q->dragMoveEvent(e);
+ case QEvent::DragMove:
+ q->dragMoveEvent(static_cast<QDragMoveEvent *>(e));
break;
- case QSGEvent::SGDragDrop:
- q->dragDropEvent(e);
+ case QEvent::Drop:
+ q->dropEvent(static_cast<QDropEvent *>(e));
break;
}
}
diff --git a/src/declarative/items/qsgitem.h b/src/declarative/items/qsgitem.h
index e340a6a364..018453f68f 100644
--- a/src/declarative/items/qsgitem.h
+++ b/src/declarative/items/qsgitem.h
@@ -154,7 +154,8 @@ public:
ItemClipsChildrenToShape = 0x01,
ItemAcceptsInputMethod = 0x02,
ItemIsFocusScope = 0x04,
- ItemHasContents = 0x08
+ ItemHasContents = 0x08,
+ ItemAcceptsDrops = 0x10
// Remember to increment the size of QSGItemPrivate::flags
};
Q_DECLARE_FLAGS(Flags, Flag)
@@ -373,10 +374,10 @@ protected:
virtual void hoverEnterEvent(QHoverEvent *event);
virtual void hoverMoveEvent(QHoverEvent *event);
virtual void hoverLeaveEvent(QHoverEvent *event);
- virtual void dragMoveEvent(QSGDragEvent *event);
- virtual void dragEnterEvent(QSGDragEvent *event);
- virtual void dragExitEvent(QSGDragEvent *event);
- virtual void dragDropEvent(QSGDragEvent *event);
+ virtual void dragEnterEvent(QDragEnterEvent *);
+ virtual void dragMoveEvent(QDragMoveEvent *);
+ virtual void dragLeaveEvent(QDragLeaveEvent *);
+ virtual void dropEvent(QDropEvent *);
virtual bool childMouseEventFilter(QSGItem *, QEvent *);
virtual void windowDeactivateEvent();
diff --git a/src/declarative/items/qsgitem_p.h b/src/declarative/items/qsgitem_p.h
index e48c1043e5..02c3f8772f 100644
--- a/src/declarative/items/qsgitem_p.h
+++ b/src/declarative/items/qsgitem_p.h
@@ -232,7 +232,7 @@ public:
QDeclarativeStateGroup *_stateGroup;
QSGItem::TransformOrigin origin:5;
- quint32 flags:4;
+ quint32 flags:5;
bool widthValid:1;
bool heightValid:1;
bool componentComplete:1;
@@ -326,7 +326,7 @@ public:
void deliverWheelEvent(QWheelEvent *);
void deliverTouchEvent(QTouchEvent *);
void deliverHoverEvent(QHoverEvent *);
- void deliverDragEvent(QSGDragEvent *);
+ void deliverDragEvent(QEvent *);
bool calcEffectiveVisible() const;
void setEffectiveVisibleRecur(bool);
diff --git a/src/declarative/items/qsgitemsmodule.cpp b/src/declarative/items/qsgitemsmodule.cpp
index db98dc4ad5..70a9499266 100644
--- a/src/declarative/items/qsgitemsmodule.cpp
+++ b/src/declarative/items/qsgitemsmodule.cpp
@@ -78,7 +78,8 @@
#include "qsgcontext2d_p.h"
#include "qsgsprite_p.h"
#include "qsgspriteimage_p.h"
-#include "qsgdragtarget_p.h"
+#include "qsgdrag_p.h"
+#include "qsgdroparea_p.h"
static QDeclarativePrivate::AutoParentResult qsgitem_autoParent(QObject *obj, QObject *parent)
{
@@ -106,7 +107,6 @@ static void qt_sgitems_defineModule(const char *uri, int major, int minor)
#endif
qmlRegisterType<QSGBorderImage>(uri,major,minor,"BorderImage");
qmlRegisterType<QSGColumn>(uri,major,minor,"Column");
- qmlRegisterType<QSGDrag>(uri,major,minor,"Drag");
qmlRegisterType<QSGFlickable>(uri,major,minor,"Flickable");
qmlRegisterType<QSGFlipable>(uri,major,minor,"Flipable");
qmlRegisterType<QSGFlow>(uri,major,minor,"Flow");
@@ -196,8 +196,10 @@ static void qt_sgitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QSGPathAnimation>("QtQuick",2,0,"PathAnimation");
qmlRegisterType<QDeclarativePathInterpolator>("QtQuick",2,0,"PathInterpolator");
- qmlRegisterType<QSGDragTarget>("QtQuick", 2, 0, "DragTarget");
- qmlRegisterType<QSGDragTargetEvent>();
+ qmlRegisterType<QSGDropArea>("QtQuick", 2, 0, "DropArea");
+ qmlRegisterType<QSGDropEvent>();
+ qmlRegisterType<QSGDropAreaDrag>();
+ qmlRegisterUncreatableType<QSGDrag>("QtQuick", 2, 0, "Drag", QSGDragAttached::tr("Drag is only available via attached properties"));
}
void QSGItemsModule::defineModule()
diff --git a/src/declarative/items/qsgmousearea.cpp b/src/declarative/items/qsgmousearea.cpp
index cae0be60c5..de7913c3d1 100644
--- a/src/declarative/items/qsgmousearea.cpp
+++ b/src/declarative/items/qsgmousearea.cpp
@@ -42,8 +42,8 @@
#include "qsgmousearea_p.h"
#include "qsgmousearea_p_p.h"
#include "qsgcanvas.h"
-#include "qsgevent.h"
#include "qsgevents_p_p.h"
+#include "qsgdrag_p.h"
#include <QtGui/qevent.h>
#include <QtGui/qguiapplication.h>
@@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE
static const int PressAndHoldDelay = 800;
QSGDrag::QSGDrag(QObject *parent)
-: QObject(parent), _target(0), _dropItem(0), _grabItem(0), _axis(XandYAxis), _xmin(-FLT_MAX),
+: QObject(parent), _target(0), _axis(XandYAxis), _xmin(-FLT_MAX),
_xmax(FLT_MAX), _ymin(-FLT_MAX), _ymax(FLT_MAX), _active(false), _filterChildren(false)
{
}
@@ -85,64 +85,6 @@ void QSGDrag::resetTarget()
emit targetChanged();
}
-/*!
- \qmlproperty Item QtQuick2::MouseArea::drag.dropItem
-
- This property holds the item an active drag will be dropped on if released
- at the current position.
-*/
-
-QSGItem *QSGDrag::dropItem() const
-{
- return _dropItem;
-}
-
-void QSGDrag::setDropItem(QSGItem *item)
-{
- if (_dropItem != item) {
- _dropItem = item;
- emit dropItemChanged();
- }
-}
-
-QSGItem *QSGDrag::grabItem() const
-{
- return _grabItem;
-}
-
-void QSGDrag::setGrabItem(QSGItem *item)
-{
- _grabItem = item;
-}
-
-/*!
- \qmlproperty variant QtQuick2::MouseArea::drag.data
-
- This property holds the data sent to recipients of drag events generated
- by a MouseArea.
-*/
-
-QVariant QSGDrag::data() const
-{
- return _data;
-}
-
-void QSGDrag::setData(const QVariant &data)
-{
- if (_data != data) {
- _data = data;
- emit dataChanged();
- }
-}
-
-void QSGDrag::resetData()
-{
- if (!_data.isNull()) {
- _data = QVariant();
- emit dataChanged();
- }
-}
-
QSGDrag::Axis QSGDrag::axis() const
{
return _axis;
@@ -234,29 +176,14 @@ void QSGDrag::setFilterChildren(bool filter)
emit filterChildrenChanged();
}
-/*!
- \qmlproperty stringlist QtQuick2::MouseArea::drag.keys
-
- This property holds a list of keys drag recipients can use to identify the
- source or data type of a drag event.
-*/
-
-QStringList QSGDrag::keys() const
+QSGDragAttached *QSGDrag::qmlAttachedProperties(QObject *obj)
{
- return _keys;
-}
-
-void QSGDrag::setKeys(const QStringList &keys)
-{
- if (_keys != keys) {
- _keys = keys;
- emit keysChanged();
- }
+ return QSGDragAttached::properties(obj);
}
QSGMouseAreaPrivate::QSGMouseAreaPrivate()
: absorb(true), hovered(false), pressed(false), longPress(false),
- moved(false), stealMouse(false), doubleClick(false), preventStealing(false), dragRejected(false),
+ moved(false), stealMouse(false), doubleClick(false), preventStealing(false),
drag(0)
{
}
@@ -708,7 +635,6 @@ void QSGMouseArea::mousePressEvent(QMouseEvent *event)
QSGItem::mousePressEvent(event);
else {
d->longPress = false;
- d->dragRejected = false;
d->saveEvent(event);
if (d->drag) {
d->dragX = drag()->axis() & QSGDrag::XAxis;
@@ -744,7 +670,6 @@ void QSGMouseArea::mouseMoveEvent(QMouseEvent *event)
setHovered(true);
if (d->drag && d->drag->target()) {
-
if (!d->moved) {
d->targetStartPos = d->drag->target()->parentItem()
? d->drag->target()->parentItem()->mapToScene(d->drag->target()->pos())
@@ -765,36 +690,22 @@ void QSGMouseArea::mouseMoveEvent(QMouseEvent *event)
qreal dx = qAbs(curLocalPos.x() - startLocalPos.x());
qreal dy = qAbs(curLocalPos.y() - startLocalPos.y());
- if (keepMouseGrab() && d->stealMouse && !d->dragRejected && !d->drag->active()) {
- QSGMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, false, d->longPress);
- d->drag->emitDragged(&me);
- if (me.isAccepted()) {
- d->drag->setActive(true);
- QSGDragEvent dragEvent(
- QSGEvent::SGDragEnter,
- d->startScene,
- d->drag->data(),
- d->drag->keys());
- QCoreApplication::sendEvent(canvas(), &dragEvent);
-
- d->drag->setGrabItem(dragEvent.grabItem());
- d->drag->setDropItem(dragEvent.dropItem());
- } else {
- d->dragRejected = true;
- }
- }
+ if (keepMouseGrab() && d->stealMouse && !d->drag->active())
+ d->drag->setActive(true);
QPointF startPos = d->drag->target()->parentItem()
? d->drag->target()->parentItem()->mapFromScene(d->targetStartPos)
: d->targetStartPos;
+ QPointF dragPos = d->drag->target()->pos();
+
if (d->dragX && d->drag->active()) {
qreal x = (curLocalPos.x() - startLocalPos.x()) + startPos.x();
if (x < drag()->xmin())
x = drag()->xmin();
else if (x > drag()->xmax())
x = drag()->xmax();
- drag()->target()->setX(x);
+ dragPos.setX(x);
}
if (d->dragY && d->drag->active()) {
qreal y = (curLocalPos.y() - startLocalPos.y()) + startPos.y();
@@ -802,8 +713,9 @@ void QSGMouseArea::mouseMoveEvent(QMouseEvent *event)
y = drag()->ymin();
else if (y > drag()->ymax())
y = drag()->ymax();
- drag()->target()->setY(y);
+ dragPos.setY(y);
}
+ d->drag->target()->setPos(dragPos);
if (!keepMouseGrab()) {
if ((!d->dragY && dy < dragThreshold && d->dragX && dx > dragThreshold)
@@ -815,18 +727,6 @@ void QSGMouseArea::mouseMoveEvent(QMouseEvent *event)
}
d->moved = true;
-
- if (d->drag->active()) {
- QSGDragEvent dragEvent(
- QSGEvent::SGDragMove,
- event->windowPos(),
- d->drag->data(),
- d->drag->keys(),
- d->drag->grabItem());
- QCoreApplication::sendEvent(canvas(), &dragEvent);
- d->drag->setGrabItem(dragEvent.grabItem());
- d->drag->setDropItem(dragEvent.dropItem());
- }
}
QSGMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, false, d->longPress);
emit mouseXChanged(&me);
@@ -845,24 +745,8 @@ void QSGMouseArea::mouseReleaseEvent(QMouseEvent *event)
} else {
d->saveEvent(event);
setPressed(false);
- if (d->drag && d->drag->active()) {
- QSGDragEvent dragEvent(
- QSGEvent::SGDragDrop,
- event->windowPos(),
- d->drag->data(),
- d->drag->keys(),
- d->drag->grabItem());
- QCoreApplication::sendEvent(canvas(), &dragEvent);
- d->drag->setGrabItem(0);
- if (dragEvent.isAccepted()) {
- d->drag->setDropItem(dragEvent.dropItem());
- d->drag->emitDropped(dragEvent.dropItem());
- } else {
- d->drag->emitCanceled();
- }
- d->drag->setDropItem(0);
+ if (d->drag)
d->drag->setActive(false);
- }
// If we don't accept hover, we need to reset containsMouse.
if (!acceptHoverEvents())
setHovered(false);
diff --git a/src/declarative/items/qsgmousearea_p.h b/src/declarative/items/qsgmousearea_p.h
index a8015fc99b..f0edf41777 100644
--- a/src/declarative/items/qsgmousearea_p.h
+++ b/src/declarative/items/qsgmousearea_p.h
@@ -53,6 +53,7 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
+class QSGDragAttached;
class QSGMouseEvent;
class Q_AUTOTEST_EXPORT QSGDrag : public QObject
{
@@ -60,8 +61,6 @@ class Q_AUTOTEST_EXPORT QSGDrag : public QObject
Q_ENUMS(Axis)
Q_PROPERTY(QSGItem *target READ target WRITE setTarget NOTIFY targetChanged RESET resetTarget)
- Q_PROPERTY(QSGItem *dropItem READ dropItem NOTIFY dropItemChanged)
- Q_PROPERTY(QVariant data READ data WRITE setData NOTIFY dataChanged RESET resetData)
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)
@@ -69,7 +68,6 @@ class Q_AUTOTEST_EXPORT QSGDrag : public QObject
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)
- Q_PROPERTY(QStringList keys READ keys WRITE setKeys NOTIFY keysChanged)
//### consider drag and drop
public:
@@ -77,19 +75,9 @@ public:
~QSGDrag();
QSGItem *target() const;
- void setTarget(QSGItem *);
+ void setTarget(QSGItem *target);
void resetTarget();
- QSGItem *dropItem() const;
- void setDropItem(QSGItem *item);
-
- QSGItem *grabItem() const;
- void setGrabItem(QSGItem *grabItem);
-
- QVariant data() const;
- void setData(const QVariant &data);
- void resetData();
-
enum Axis { XAxis=0x01, YAxis=0x02, XandYAxis=0x03 };
Axis axis() const;
void setAxis(Axis);
@@ -109,17 +97,10 @@ public:
bool filterChildren() const;
void setFilterChildren(bool);
- QStringList keys() const;
- void setKeys(const QStringList &keys);
-
- void emitDragged(QSGMouseEvent *event) { emit dragged(event); }
- void emitDropped(QSGItem *dropItem) { emit dropped(dropItem); }
- void emitCanceled() { emit canceled(); }
+ static QSGDragAttached *qmlAttachedProperties(QObject *obj);
Q_SIGNALS:
void targetChanged();
- void dropItemChanged();
- void dataChanged();
void axisChanged();
void minimumXChanged();
void maximumXChanged();
@@ -127,17 +108,9 @@ Q_SIGNALS:
void maximumYChanged();
void activeChanged();
void filterChildrenChanged();
- void keysChanged();
- void dragged(QSGMouseEvent *mouse);
- void dropped(QSGItem *dropItem);
- void canceled();
private:
- QStringList _keys;
- QVariant _data;
QSGItem *_target;
- QSGItem *_dropItem;
- QSGItem *_grabItem;
Axis _axis;
qreal _xmin;
qreal _xmax;
@@ -245,6 +218,7 @@ private:
QT_END_NAMESPACE
QML_DECLARE_TYPE(QSGDrag)
+QML_DECLARE_TYPEINFO(QSGDrag, QML_HAS_ATTACHED_PROPERTIES)
QML_DECLARE_TYPE(QSGMouseArea)
QT_END_HEADER
diff --git a/src/declarative/items/qsgmousearea_p_p.h b/src/declarative/items/qsgmousearea_p_p.h
index 2ec1eda3f7..6cf663ac6d 100644
--- a/src/declarative/items/qsgmousearea_p_p.h
+++ b/src/declarative/items/qsgmousearea_p_p.h
@@ -95,7 +95,6 @@ public:
bool stealMouse : 1;
bool doubleClick : 1;
bool preventStealing : 1;
- bool dragRejected : 1;
QSGDrag *drag;
QPointF startScene;
QPointF targetStartPos;