diff options
Diffstat (limited to 'src/declarative/items')
-rw-r--r-- | src/declarative/items/items.pri | 7 | ||||
-rw-r--r-- | src/declarative/items/qsgcanvas.cpp | 168 | ||||
-rw-r--r-- | src/declarative/items/qsgcanvas_p.h | 8 | ||||
-rw-r--r-- | src/declarative/items/qsgdrag.cpp | 474 | ||||
-rw-r--r-- | src/declarative/items/qsgdrag_p.h | 212 | ||||
-rw-r--r-- | src/declarative/items/qsgdragtarget.cpp | 363 | ||||
-rw-r--r-- | src/declarative/items/qsgdroparea.cpp | 426 | ||||
-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.h | 137 | ||||
-rw-r--r-- | src/declarative/items/qsgitem.cpp | 37 | ||||
-rw-r--r-- | src/declarative/items/qsgitem.h | 11 | ||||
-rw-r--r-- | src/declarative/items/qsgitem_p.h | 4 | ||||
-rw-r--r-- | src/declarative/items/qsgitemsmodule.cpp | 10 | ||||
-rw-r--r-- | src/declarative/items/qsgmousearea.cpp | 142 | ||||
-rw-r--r-- | src/declarative/items/qsgmousearea_p.h | 34 | ||||
-rw-r--r-- | src/declarative/items/qsgmousearea_p_p.h | 1 |
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; |