aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew den Exter <andrew.den-exter@nokia.com>2011-09-12 14:17:08 +1000
committerQt by Nokia <qt-info@nokia.com>2011-10-10 05:48:01 +0200
commitc825865cdd88445aa1db94cdf0da89426919acdb (patch)
tree93418f7a0ab78ddb3b51e59b0a30e30d3c1872b5
parent65bf7aa06a59790d0aea30b909577747510bb5d1 (diff)
Add DropArea item and Drag attached property.
Refactors drag API to improve compatibility with traditional drag and drop by reusing events and adding drop actions. Event sending is removed from MouseArea, instead the Drag object can be attached to the item that is dragged and it will send drag events when the position of that item is changed or when its active property changes. The DragTarget item is renamed to DropArea and can now communicate supported and suggested actions. Task-number: QTBUG-19747 Change-Id: I46cb77e68cf1ff32bbcbf0945facb593c9c2243c Reviewed-on: http://codereview.qt-project.org/4638 Sanity-Review: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Martin Jones <martin.jones@nokia.com>
-rw-r--r--doc/src/snippets/declarative/drag.qml75
-rw-r--r--examples/declarative/draganddrop/dragtarget.qmlproject (renamed from examples/declarative/dragtarget/dragtarget.qmlproject)0
-rw-r--r--examples/declarative/draganddrop/tiles/DragTile.qml (renamed from examples/declarative/dragtarget/tiles/DragTile.qml)78
-rw-r--r--examples/declarative/draganddrop/tiles/DropTile.qml (renamed from examples/declarative/dragtarget/tiles/DropTile.qml)34
-rw-r--r--examples/declarative/draganddrop/tiles/tiles.qml (renamed from examples/declarative/dragtarget/tiles/tiles.qml)30
-rw-r--r--examples/declarative/draganddrop/views/gridview.qml117
-rw-r--r--examples/declarative/dragtarget/lists/listmodel.qml296
-rw-r--r--examples/declarative/dragtarget/lists/lists.qmlproject16
-rw-r--r--examples/declarative/dragtarget/text/dragtext.qml182
-rw-r--r--examples/declarative/dragtarget/text/text.qmlproject16
-rw-r--r--examples/declarative/modelviews/visualdatamodel/dragselection.qml4
-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
-rw-r--r--tests/auto/declarative/declarative.pro2
-rw-r--r--tests/auto/declarative/qsgdrag/qsgdrag.pro11
-rw-r--r--tests/auto/declarative/qsgdrag/tst_qsgdrag.cpp768
-rw-r--r--tests/auto/declarative/qsgdroparea/qsgdroparea.pro11
-rw-r--r--tests/auto/declarative/qsgdroparea/tst_qsgdroparea.cpp1063
-rw-r--r--tools/qmlplugindump/main.cpp3
33 files changed, 3458 insertions, 1398 deletions
diff --git a/doc/src/snippets/declarative/drag.qml b/doc/src/snippets/declarative/drag.qml
new file mode 100644
index 0000000000..d863fdf510
--- /dev/null
+++ b/doc/src/snippets/declarative/drag.qml
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** 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 documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//![0]
+import QtQuick 2.0
+
+Item {
+ width: 200; height: 200
+
+ DropArea {
+ x: 75; y: 75
+ width: 50; height: 50
+
+ Rectangle {
+ anchors.fill: parent
+ color: "green"
+
+ visible: parent.containsDrag
+ }
+ }
+
+ Rectangle {
+ x: 10; y: 10
+ width: 20; height: 20
+ color: "red"
+
+ Drag.active: dragArea.drag.active
+ Drag.hotSpot.x: 10
+ Drag.hotSpot.y: 10
+
+ MouseArea {
+ id: dragArea
+ anchors.fill: parent
+
+ drag.target: parent
+ }
+ }
+}
+//![0]
diff --git a/examples/declarative/dragtarget/dragtarget.qmlproject b/examples/declarative/draganddrop/dragtarget.qmlproject
index d4909f8685..d4909f8685 100644
--- a/examples/declarative/dragtarget/dragtarget.qmlproject
+++ b/examples/declarative/draganddrop/dragtarget.qmlproject
diff --git a/examples/declarative/dragtarget/tiles/DragTile.qml b/examples/declarative/draganddrop/tiles/DragTile.qml
index f1bd79314a..d7bc920735 100644
--- a/examples/declarative/dragtarget/tiles/DragTile.qml
+++ b/examples/declarative/draganddrop/tiles/DragTile.qml
@@ -40,60 +40,50 @@
import QtQuick 2.0
-Rectangle {
- id: dragRectangle
+Item {
+ id: root
+ property string colorKey
- property Item dropTarget
+ width: 100; height: 100
- property string colorKey
+ MouseArea {
+ id: mouseArea
- color: colorKey
+ width: 100; height: 100
+ anchors.centerIn: parent
- width: 100; height: 100
+ drag.target: tile
- Text {
- anchors.fill: parent
- color: "white"
- font.pixelSize: 90
- text: modelData + 1
- horizontalAlignment:Text.AlignHCenter
- verticalAlignment: Text.AlignVCenter
- }
+ onReleased: parent = tile.Drag.target !== null ? tile.Drag.target : root
- MouseArea {
- id: draggable
+ Rectangle {
+ id: tile
- anchors.fill: parent
+ width: 100; height: 100
- drag.target: parent
- drag.keys: [ colorKey ]
+ anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: parent.verticalCenter
+ color: colorKey
- drag.onDropped: dropTarget = dropItem
+ Drag.keys: [ colorKey ]
+ Drag.active: mouseArea.drag.active
+ Drag.hotSpot.x: 50
+ Drag.hotSpot.y: 50
- states: [
- State {
- when: dragRectangle.dropTarget != undefined && !draggable.drag.active
- ParentChange {
- target: dragRectangle
- parent: dropTarget
- x: 0
- y: 0
- }
- },
- State {
- when: dragRectangle.dropTarget != undefined && draggable.drag.active
- ParentChange {
- target: dragRectangle
- parent: dropTarget
- }
- },
- State {
- when: !draggable.drag.active
- AnchorChanges {
- target: dragRectangle
- anchors.horizontalCenter: parent.horizontalCenter
- }
+ Text {
+ anchors.fill: parent
+ color: "white"
+ font.pixelSize: 90
+ text: modelData + 1
+ horizontalAlignment:Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
}
- ]
+
+ states: State {
+ when: mouseArea.drag.active
+ ParentChange { target: tile; parent: root }
+ AnchorChanges { target: tile; anchors.verticalCenter: undefined; anchors.horizontalCenter: undefined }
+ }
+ }
}
}
+
diff --git a/examples/declarative/dragtarget/tiles/DropTile.qml b/examples/declarative/draganddrop/tiles/DropTile.qml
index 80aa81f671..492706439a 100644
--- a/examples/declarative/dragtarget/tiles/DropTile.qml
+++ b/examples/declarative/draganddrop/tiles/DropTile.qml
@@ -40,31 +40,29 @@
import QtQuick 2.0
-Rectangle {
- id: dropRectangle
+DropArea {
+ id: dragTarget
property string colorKey
-
- color: colorKey
+ property alias dropProxy: dragTarget
width: 100; height: 100
+ keys: [ colorKey ]
- DragTarget {
- id: dragTarget
+ Rectangle {
+ id: dropRectangle
anchors.fill: parent
+ color: colorKey
- keys: [ colorKey ]
- dropItem: dropRectangle
- }
-
- states: [
- State {
- when: dragTarget.containsDrag
- PropertyChanges {
- target: dropRectangle
- color: "grey"
+ states: [
+ State {
+ when: dragTarget.containsDrag
+ PropertyChanges {
+ target: dropRectangle
+ color: "grey"
+ }
}
- }
- ]
+ ]
+ }
}
diff --git a/examples/declarative/dragtarget/tiles/tiles.qml b/examples/declarative/draganddrop/tiles/tiles.qml
index 1f783e3322..17dcd3b547 100644
--- a/examples/declarative/dragtarget/tiles/tiles.qml
+++ b/examples/declarative/draganddrop/tiles/tiles.qml
@@ -48,12 +48,6 @@ Rectangle {
color: "black"
- DragTarget {
- id: resetTarget
-
- anchors.fill: parent
- }
-
Grid {
id: redDestination
@@ -61,22 +55,16 @@ Rectangle {
anchors.margins: 5
width: 300
height: 300
-
opacity: 0.5
-
columns: 3
Repeater {
- model: 9
- delegate: DropTile {
- colorKey: "red"
- }
+ model: 9;
+ delegate: DropTile { colorKey: "red" }
}
}
Grid {
- id: blueDestination
-
anchors.right: blueSource.left; anchors.bottom: parent.bottom;
anchors.margins: 5
width: 300
@@ -88,9 +76,7 @@ Rectangle {
Repeater {
model: 9
- delegate: DropTile {
- colorKey: "blue"
- }
+ delegate: DropTile { colorKey: "blue" }
}
}
@@ -100,12 +86,11 @@ Rectangle {
anchors.left: parent.left; anchors.top: parent.top; anchors.bottom: parent.bottom
anchors.margins: 5
width: 100
+ spacing: -60
Repeater {
model: 9
- delegate: DragTile {
- colorKey: "red"
- }
+ delegate: DragTile { colorKey: "red" }
}
}
Column {
@@ -114,12 +99,11 @@ Rectangle {
anchors.right: parent.right; anchors.top: parent.top; anchors.bottom: parent.bottom
anchors.margins: 5
width: 100
+ spacing: -60
Repeater {
model: 9
- delegate: DragTile {
- colorKey: "blue"
- }
+ delegate: DragTile { colorKey: "blue" }
}
}
}
diff --git a/examples/declarative/draganddrop/views/gridview.qml b/examples/declarative/draganddrop/views/gridview.qml
new file mode 100644
index 0000000000..f16a79c9dc
--- /dev/null
+++ b/examples/declarative/draganddrop/views/gridview.qml
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+GridView {
+ id: root
+ width: 360; height: 360
+ cellWidth: 90; cellHeight: 90
+
+ model: VisualDataModel {
+ id: visualModel
+ model: ListModel {
+ id: colorModel
+ ListElement { color: "blue" }
+ ListElement { color: "green" }
+ ListElement { color: "red" }
+ ListElement { color: "yellow" }
+ ListElement { color: "orange" }
+ ListElement { color: "purple" }
+ ListElement { color: "cyan" }
+ ListElement { color: "magenta" }
+ ListElement { color: "chartreuse" }
+ ListElement { color: "aquamarine" }
+ ListElement { color: "indigo" }
+ ListElement { color: "black" }
+ ListElement { color: "chartreuse" }
+ ListElement { color: "violet" }
+ ListElement { color: "grey" }
+ ListElement { color: "springgreen" }
+ }
+
+ delegate: MouseArea {
+ id: delegateRoot
+
+ property int visualIndex: VisualDataModel.itemsIndex
+
+ width: 90; height: 90
+ drag.target: icon
+
+ Rectangle {
+ id: icon
+ width: 80; height: 80
+ anchors {
+ horizontalCenter: parent.horizontalCenter;
+ verticalCenter: parent.verticalCenter
+ }
+ color: model.color
+ radius: 3
+
+ Drag.active: delegateRoot.pressed
+ Drag.source: delegateRoot
+ Drag.hotSpot.x: 40
+ Drag.hotSpot.y: 40
+
+ states: [
+ State {
+ when: icon.Drag.active
+ ParentChange {
+ target: icon
+ parent: root
+ }
+
+ AnchorChanges {
+ target: icon;
+ anchors.horizontalCenter: undefined;
+ anchors.verticalCenter: undefined
+ }
+ }
+ ]
+ }
+
+ DropArea {
+ anchors { fill: parent; margins: 15 }
+
+ onEntered: visualModel.items.move(drag.source.visualIndex, delegateRoot.visualIndex)
+ }
+ }
+ }
+}
diff --git a/examples/declarative/dragtarget/lists/listmodel.qml b/examples/declarative/dragtarget/lists/listmodel.qml
deleted file mode 100644
index f153087e7b..0000000000
--- a/examples/declarative/dragtarget/lists/listmodel.qml
+++ /dev/null
@@ -1,296 +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 examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
-** the names of its contributors may be used to endorse or promote
-** products derived from this software without specific prior written
-** permission.
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-
-
-Rectangle {
- id: root
- color: "grey"
-
- width: 720
- height: 380
-
- Component {
- id: draggedText
- Text {
- x: rootTarget.dragX - 10
- y: rootTarget.dragY - 10
- width: 20
- height: 20
-
- text: rootTarget.dragData.display
- font.pixelSize: 18
- }
- }
-
- DragTarget {
- id: rootTarget
-
- anchors.fill: parent
- }
-
- Loader {
- anchors.fill: parent
- sourceComponent: rootTarget.containsDrag ? draggedText : undefined
- }
-
- GridView {
- id: gridView
-
- width: 240
- height: 360
-
- anchors.left: parent.left
- anchors.verticalCenter: parent.verticalCenter
- anchors.margins: 10
-
- cellWidth: 60
- cellHeight: 60
-
- model: ListModel {
- id: gridModel
-
- ListElement { display: "1" }
- ListElement { display: "2" }
- ListElement { display: "3" }
- ListElement { display: "4" }
- ListElement { display: "5" }
- ListElement { display: "6" }
- ListElement { display: "7" }
- ListElement { display: "8" }
- ListElement { display: "9" }
- ListElement { display: "10" }
- ListElement { display: "11" }
- ListElement { display: "12" }
- ListElement { display: "13" }
- ListElement { display: "14" }
- ListElement { display: "15" }
- ListElement { display: "16" }
- ListElement { display: "17" }
- ListElement { display: "18" }
- ListElement { display: "19" }
- ListElement { display: "20" }
- ListElement { display: "21" }
- ListElement { display: "22" }
- ListElement { display: "23" }
- ListElement { display: "24" }
- }
-
- delegate: Rectangle {
- id: root
-
- width: 60
- height: 60
-
- color: "black"
-
- Text {
- anchors.fill: parent
- color: draggable.drag.active ? "gold" : "white"
- text: display
- font.pixelSize: 16
- verticalAlignment: Text.AlignVCenter
- horizontalAlignment: Text.AlignHCenter
- }
-
- MouseArea {
- id: draggable
-
- property int initialIndex
-
- width: 60
- height: 60
-
- drag.data: model
- drag.keys: ["grid"]
- drag.target: draggable
-
- states: State {
- when: !draggable.drag.active
- PropertyChanges { target: draggable; x: 0; y: 0 }
- }
- }
- }
-
- DragTarget {
- anchors.fill: parent
-
- keys: [ "grid" ]
- onPositionChanged: {
- var index = gridView.indexAt(drag.x, drag.y)
- if (index != -1)
- gridModel.move(drag.data.index, index, 1)
- }
- }
-
- DragTarget {
- property int dragIndex
- anchors.fill: parent
-
- keys: [ "list" ]
- onEntered: {
- dragIndex = gridView.indexAt(drag.x, drag.y)
- if (dragIndex != -1) {
- gridModel.insert(dragIndex, { "display": drag.data.display })
- } else {
- event.accepted = false
- }
- }
- onPositionChanged: {
- var index = gridView.indexAt(drag.x, drag.y);
- if (index != -1) {
- gridModel.move(dragIndex, index, 1)
- dragIndex = index
- }
- }
- onExited: gridModel.remove(dragIndex, 1)
- }
- }
-
- ListView {
- id: listView
-
- width: 240
- height: 360
-
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
- anchors.margins: 10
-
- model: ListModel {
- id: listModel
-
- ListElement { display: "a" }
- ListElement { display: "b" }
- ListElement { display: "c" }
- ListElement { display: "d"}
- ListElement { display: "e" }
- ListElement { display: "f" }
- ListElement { display: "g" }
- ListElement { display: "h" }
- ListElement { display: "i" }
- ListElement { display: "j" }
- ListElement { display: "k" }
- ListElement { display: "l" }
- ListElement { display: "m" }
- ListElement { display: "n" }
- ListElement { display: "o" }
- ListElement { display: "p" }
- ListElement { display: "q" }
- ListElement { display: "r" }
- ListElement { display: "s" }
- ListElement { display: "t" }
- ListElement { display: "u" }
- ListElement { display: "v" }
- ListElement { display: "w" }
- ListElement { display: "x" }
- }
-
- delegate: Rectangle {
- id: root
-
- width: 240
- height: 15
-
- color: "black"
-
- Text {
- anchors.fill: parent
- color: draggable.drag.active ? "gold" : "white"
- text: display
- font.pixelSize: 12
- verticalAlignment: Text.AlignVCenter
- horizontalAlignment: Text.AlignHCenter
- }
-
- MouseArea {
- id: draggable
-
- width: 240
- height: 15
-
- drag.data: model
- drag.keys: ["list"]
- drag.target: draggable
-
- states: State {
- when: !draggable.drag.active
- PropertyChanges { target: draggable; x: 0; y: 0 }
- }
- }
- }
-
- DragTarget {
- anchors.fill: parent
-
- keys: [ "list" ]
- onPositionChanged: {
- var index = listView.indexAt(drag.x, drag.y)
- if (index != -1)
- listModel.move(drag.data.index, index, 1)
- }
- }
-
- DragTarget {
- property int dragIndex
- anchors.fill: parent
-
- keys: [ "grid" ]
-
- onEntered: {
- dragIndex = listView.indexAt(drag.x, drag.y)
- if (dragIndex != -1) {
- listModel.insert(dragIndex, { "display": drag.data.display })
- } else {
- event.accepted = false
- }
- }
- onPositionChanged: {
- var index = listView.indexAt(drag.x, drag.y);
- if (index != -1) {
- listModel.move(dragIndex, index, 1)
- dragIndex = index
- }
- }
- onExited: listModel.remove(dragIndex, 1)
- }
- }
-}
diff --git a/examples/declarative/dragtarget/lists/lists.qmlproject b/examples/declarative/dragtarget/lists/lists.qmlproject
deleted file mode 100644
index d4909f8685..0000000000
--- a/examples/declarative/dragtarget/lists/lists.qmlproject
+++ /dev/null
@@ -1,16 +0,0 @@
-import QmlProject 1.0
-
-Project {
- /* Include .qml, .js, and image files from current directory and subdirectories */
- QmlFiles {
- directory: "."
- }
- JavaScriptFiles {
- directory: "."
- }
- ImageFiles {
- directory: "."
- }
- /* List of plugin directories passed to QML runtime */
- // importPaths: [ " ../exampleplugin " ]
-}
diff --git a/examples/declarative/dragtarget/text/dragtext.qml b/examples/declarative/dragtarget/text/dragtext.qml
deleted file mode 100644
index 49858d1fc4..0000000000
--- a/examples/declarative/dragtarget/text/dragtext.qml
+++ /dev/null
@@ -1,182 +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 examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
-** the names of its contributors may be used to endorse or promote
-** products derived from this software without specific prior written
-** permission.
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-
-Item {
- id: root
- width: 320; height: 480
-
- Rectangle {
- id: inputRect
- anchors.left: parent.left; anchors.right: parent.right; anchors.top: parent.top
- anchors.margins: 2
- height: input.implicitHeight + 4
-
- border.width: 1
-
- TextInput {
- id: input
- anchors.fill: parent; anchors.margins: 2
-
- text: "the quick brown fox jumped over the lazy dog"
-
- DragTarget {
- id: inputTarget
-
- anchors.fill: parent
-
- Component {
- id: draggedInputText
- Text {
- x: inputTarget.dragX
- y: inputTarget.dragY
- text: inputTarget.dragData
- color: "blue"
- font: input.font
- }
- }
-
- Loader {
- sourceComponent: parent.containsDrag ? draggedInputText : undefined
- }
- }
-
-
- MouseArea {
- id: inputDraggable
-
- anchors.fill: parent
- enabled: input.selectionStart != input.selectionEnd
-
- drag.data: input.selectedText
- drag.target: inputDraggable
-
- drag.onDragged: {
- var position = input.positionAt(mouse.x);
- mouse.accepted = position >= input.selectionStart && position < input.selectionEnd
- }
-
- MouseArea {
- anchors.fill: parent
-
- onPressed: {
- var position = input.positionAt(mouse.x);
- if (position < input.selectionStart || position >= input.selectionEnd) {
- input.cursorPosition = position
- } else {
- mouse.accepted = false
- }
- }
- onPositionChanged: input.moveCursorSelection(input.positionAt(mouse.x))
- }
- }
- }
- }
-
- Rectangle {
- id: editRect
- anchors.left: parent.left; anchors.right: parent.right;
- anchors.top: inputRect.bottom; anchors.bottom: parent.bottom
- anchors.margins: 2
-
- border.width: 1
-
- TextEdit {
- id: edit
- anchors.fill: parent; anchors.margins: 2
-
- text: "the quick brown fox jumped over the lazy dog"
- font.pixelSize: 18
- wrapMode: TextEdit.WordWrap
-
- DragTarget {
- id: editTarget
-
- anchors.fill: parent
-
-
- Component {
- id: draggedEditText
- Text {
- x: editTarget.dragX
- y: editTarget.dragY
- text: editTarget.dragData
- color: "red"
- font: edit.font
- }
- }
-
- Loader {
- sourceComponent: parent.containsDrag ? draggedEditText : undefined
- }
- }
-
- MouseArea {
- id: editDraggable
-
- anchors.fill: parent
- enabled: edit.selectionStart != edit.selectionEnd
-
- drag.data: edit.selectedText
- drag.target: editDraggable
-
- drag.onDragged: {
- var position = edit.positionAt(mouse.x, mouse.y);
- mouse.accepted = position >= edit.selectionStart && position < edit.selectionEnd
- }
-
- MouseArea {
- anchors.fill: parent
-
- onPressed: {
- var position = edit.positionAt(mouse.x, mouse.y);
- if (position < edit.selectionStart || position >= edit.selectionEnd) {
- edit.cursorPosition = position
- } else {
- mouse.accepted = false
- }
- }
- onPositionChanged: edit.moveCursorSelection(edit.positionAt(mouse.x, mouse.y))
- }
- }
- }
- }
-}
diff --git a/examples/declarative/dragtarget/text/text.qmlproject b/examples/declarative/dragtarget/text/text.qmlproject
deleted file mode 100644
index d4909f8685..0000000000
--- a/examples/declarative/dragtarget/text/text.qmlproject
+++ /dev/null
@@ -1,16 +0,0 @@
-import QmlProject 1.0
-
-Project {
- /* Include .qml, .js, and image files from current directory and subdirectories */
- QmlFiles {
- directory: "."
- }
- JavaScriptFiles {
- directory: "."
- }
- ImageFiles {
- directory: "."
- }
- /* List of plugin directories passed to QML runtime */
- // importPaths: [ " ../exampleplugin " ]
-}
diff --git a/examples/declarative/modelviews/visualdatamodel/dragselection.qml b/examples/declarative/modelviews/visualdatamodel/dragselection.qml
index d4412f9719..afbea1ff94 100644
--- a/examples/declarative/modelviews/visualdatamodel/dragselection.qml
+++ b/examples/declarative/modelviews/visualdatamodel/dragselection.qml
@@ -69,6 +69,8 @@ Item {
width: 64
height: 64
+ Drag.active: visibleContainer.drag.active
+
anchors { horizontalCenter: parent.horizontalCenter; verticalCenter: parent.verticalCenter }
states: State {
@@ -79,7 +81,7 @@ Item {
ParentChange { target: draggable; parent: root }
}
}
- DragTarget {
+ DropArea {
anchors.fill: parent
onEntered: visualModel.items.move(selectedItems, 0, packageRoot.VisualDataModel.itemsIndex, selectedItems.count)
}
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;
diff --git a/tests/auto/declarative/declarative.pro b/tests/auto/declarative/declarative.pro
index 324880120b..c9b54b2908 100644
--- a/tests/auto/declarative/declarative.pro
+++ b/tests/auto/declarative/declarative.pro
@@ -64,6 +64,8 @@ SGTESTS = \
qsganimatedimage \
qsgborderimage \
qsgcanvas \
+ qsgdrag \
+ qsgdroparea \
qsgflickable \
qsgflipable \
qsgfocusscope \
diff --git a/tests/auto/declarative/qsgdrag/qsgdrag.pro b/tests/auto/declarative/qsgdrag/qsgdrag.pro
new file mode 100644
index 0000000000..213385cd1f
--- /dev/null
+++ b/tests/auto/declarative/qsgdrag/qsgdrag.pro
@@ -0,0 +1,11 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative gui network
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qsgdrag.cpp
+
+DEFINES += SRCDIR=\\\"$$PWD\\\"
+
+CONFIG += parallel_test
+
+QT += core-private gui-private declarative-private
diff --git a/tests/auto/declarative/qsgdrag/tst_qsgdrag.cpp b/tests/auto/declarative/qsgdrag/tst_qsgdrag.cpp
new file mode 100644
index 0000000000..5d5da9a931
--- /dev/null
+++ b/tests/auto/declarative/qsgdrag/tst_qsgdrag.cpp
@@ -0,0 +1,768 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite 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 <QtTest/QtTest>
+#include <QtTest/QSignalSpy>
+#include <QtDeclarative/qsgitem.h>
+#include <QtDeclarative/qsgview.h>
+#include <QtDeclarative/qdeclarativecontext.h>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativeexpression.h>
+#include "../../../shared/util.h"
+
+template <typename T> static T evaluate(QObject *scope, const QString &expression)
+{
+ QDeclarativeExpression expr(qmlContext(scope), scope, expression);
+ QVariant result = expr.evaluate();
+ if (expr.hasError())
+ qWarning() << expr.error().toString();
+ return result.value<T>();
+}
+
+template <> void evaluate<void>(QObject *scope, const QString &expression)
+{
+ QDeclarativeExpression expr(qmlContext(scope), scope, expression);
+ expr.evaluate();
+ if (expr.hasError())
+ qWarning() << expr.error().toString();
+}
+
+Q_DECLARE_METATYPE(Qt::DropActions)
+
+class TestDropTarget : public QSGItem
+{
+ Q_OBJECT
+public:
+ TestDropTarget(QSGItem *parent = 0)
+ : QSGItem(parent)
+ , enterEvents(0)
+ , moveEvents(0)
+ , leaveEvents(0)
+ , dropEvents(0)
+ , acceptAction(Qt::MoveAction)
+ , defaultAction(Qt::IgnoreAction)
+ , proposedAction(Qt::IgnoreAction)
+ , accept(true)
+ {
+ setFlags(ItemAcceptsDrops);
+ }
+
+ void reset()
+ {
+ enterEvents = 0;
+ moveEvents = 0;
+ leaveEvents = 0;
+ dropEvents = 0;
+ defaultAction = Qt::IgnoreAction;
+ proposedAction = Qt::IgnoreAction;
+ supportedActions = Qt::IgnoreAction;
+ }
+
+ void dragEnterEvent(QDragEnterEvent *event)
+ {
+ ++enterEvents;
+ position = event->pos();
+ defaultAction = event->dropAction();
+ proposedAction = event->proposedAction();
+ supportedActions = event->possibleActions();
+ event->setAccepted(accept);
+ }
+
+ void dragMoveEvent(QDragMoveEvent *event)
+ {
+ ++moveEvents;
+ position = event->pos();
+ defaultAction = event->dropAction();
+ proposedAction = event->proposedAction();
+ supportedActions = event->possibleActions();
+ event->setAccepted(accept);
+ }
+
+ void dragLeaveEvent(QDragLeaveEvent *event)
+ {
+ ++leaveEvents;
+ event->setAccepted(accept);
+ }
+
+ void dropEvent(QDropEvent *event)
+ {
+ ++dropEvents;
+ position = event->pos();
+ defaultAction = event->dropAction();
+ proposedAction = event->proposedAction();
+ supportedActions = event->possibleActions();
+ event->setDropAction(acceptAction);
+ event->setAccepted(accept);
+ }
+
+ int enterEvents;
+ int moveEvents;
+ int leaveEvents;
+ int dropEvents;
+ Qt::DropAction acceptAction;
+ Qt::DropAction defaultAction;
+ Qt::DropAction proposedAction;
+ Qt::DropActions supportedActions;
+ QPointF position;
+ bool accept;
+};
+
+class tst_QSGDrag: public QObject
+{
+ Q_OBJECT
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+ void active();
+ void drop();
+ void move();
+ void hotSpot();
+ void supportedActions();
+ void proposedAction();
+ void keys();
+ void source();
+
+private:
+ QDeclarativeEngine engine;
+};
+
+void tst_QSGDrag::initTestCase()
+{
+
+}
+
+void tst_QSGDrag::cleanupTestCase()
+{
+
+}
+
+void tst_QSGDrag::active()
+{
+ QSGCanvas canvas;
+ TestDropTarget dropTarget(canvas.rootItem());
+ dropTarget.setSize(QSizeF(100, 100));
+ QDeclarativeComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "Item {\n"
+ "property bool dragActive: Drag.active\n"
+ "property Item dragTarget: Drag.target\n"
+ "x: 50; y: 50\n"
+ "width: 10; height: 10\n"
+ "}", QUrl());
+ QSGItem *item = qobject_cast<QSGItem *>(component.create());
+ QVERIFY(item);
+ item->setParentItem(&dropTarget);
+
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), false);
+
+ evaluate<void>(item, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), true);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&dropTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&dropTarget));
+ QCOMPARE(dropTarget.enterEvents, 1); QCOMPARE(dropTarget.leaveEvents, 0);
+
+ dropTarget.reset();
+ evaluate<void>(item, "Drag.active = false");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), false);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 1);
+
+ dropTarget.reset();
+ evaluate<void>(item, "Drag.cancel()");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), false);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 0);
+
+ dropTarget.reset();
+ evaluate<void>(item, "Drag.start()");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), true);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&dropTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&dropTarget));
+ QCOMPARE(dropTarget.enterEvents, 1); QCOMPARE(dropTarget.leaveEvents, 0);
+
+ // Start while a drag is active, cancels the previous drag and starts a new one.
+ dropTarget.reset();
+ evaluate<void>(item, "Drag.start()");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), true);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&dropTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&dropTarget));
+ QCOMPARE(dropTarget.enterEvents, 1); QCOMPARE(dropTarget.leaveEvents, 1);
+
+ dropTarget.reset();
+ evaluate<void>(item, "Drag.cancel()");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), false);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 1);
+
+ // Enter events aren't sent to items without the QSGItem::ItemAcceptsDrops flag.
+ dropTarget.setFlags(QSGItem::Flags());
+
+ dropTarget.reset();
+ evaluate<void>(item, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), true);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 0);
+
+ dropTarget.reset();
+ evaluate<void>(item, "Drag.active = false");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), false);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 0);
+
+ dropTarget.setFlags(QSGItem::ItemAcceptsDrops);
+
+ dropTarget.reset();
+ evaluate<void>(item, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), true);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&dropTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&dropTarget));
+ QCOMPARE(dropTarget.enterEvents, 1); QCOMPARE(dropTarget.leaveEvents, 0);
+
+ dropTarget.setFlags(QSGItem::Flags());
+
+ dropTarget.reset();
+ evaluate<void>(item, "Drag.active = false");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), false);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 1);
+
+ // Follow up events aren't sent to items if the enter event isn't accepted.
+ dropTarget.setFlags(QSGItem::ItemAcceptsDrops);
+ dropTarget.accept = false;
+
+ dropTarget.reset();
+ evaluate<void>(item, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), true);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(dropTarget.enterEvents, 1); QCOMPARE(dropTarget.leaveEvents, 0);
+
+ dropTarget.reset();
+ evaluate<void>(item, "Drag.active = false");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), false);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 0);
+
+ dropTarget.accept = true;
+
+ dropTarget.reset();
+ evaluate<void>(item, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), true);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&dropTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&dropTarget));
+ QCOMPARE(dropTarget.enterEvents, 1); QCOMPARE(dropTarget.leaveEvents, 0);
+
+ dropTarget.accept = false;
+
+ dropTarget.reset();
+ evaluate<void>(item, "Drag.active = false");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), false);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 1);
+}
+
+void tst_QSGDrag::drop()
+{
+ QSGCanvas canvas;
+ TestDropTarget outerTarget(canvas.rootItem());
+ outerTarget.setSize(QSizeF(100, 100));
+ outerTarget.acceptAction = Qt::CopyAction;
+ TestDropTarget innerTarget(&outerTarget);
+ innerTarget.setSize(QSizeF(100, 100));
+ innerTarget.acceptAction = Qt::MoveAction;
+ QDeclarativeComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "Item {\n"
+ "property bool dragActive: Drag.active\n"
+ "property Item dragTarget: Drag.target\n"
+ "x: 50; y: 50\n"
+ "width: 10; height: 10\n"
+ "}", QUrl());
+ QSGItem *item = qobject_cast<QSGItem *>(component.create());
+ QVERIFY(item);
+ item->setParentItem(&outerTarget);
+
+ innerTarget.reset(); outerTarget.reset();
+ evaluate<void>(item, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), true);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&innerTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&innerTarget));
+ QCOMPARE(outerTarget.enterEvents, 1); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 0);
+ QCOMPARE(innerTarget.enterEvents, 1); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 0);
+
+ innerTarget.reset(); outerTarget.reset();
+ QCOMPARE(evaluate<bool>(item, "Drag.drop() == Qt.MoveAction"), true);
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), false);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&innerTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&innerTarget));
+ QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 1); QCOMPARE(outerTarget.dropEvents, 0);
+ QCOMPARE(innerTarget.enterEvents, 0); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 1);
+
+ innerTarget.reset(); outerTarget.reset();
+ evaluate<void>(item, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), true);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&innerTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&innerTarget));
+ QCOMPARE(outerTarget.enterEvents, 1); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 0);
+ QCOMPARE(innerTarget.enterEvents, 1); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 0);
+
+ // Inner target declines the drop so it is propagated to the outer target.
+ innerTarget.accept = false;
+
+ innerTarget.reset(); outerTarget.reset();
+ QCOMPARE(evaluate<bool>(item, "Drag.drop() == Qt.CopyAction"), true);
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), false);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 1);
+ QCOMPARE(innerTarget.enterEvents, 0); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 1);
+
+
+ // Inner target doesn't accept enter so drop goes directly to outer.
+ innerTarget.accept = true;
+ innerTarget.setFlags(QSGItem::Flags());
+
+ innerTarget.reset(); outerTarget.reset();
+ evaluate<void>(item, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), true);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(outerTarget.enterEvents, 1); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 0);
+ QCOMPARE(innerTarget.enterEvents, 0); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 0);
+
+ innerTarget.reset(); outerTarget.reset();
+ QCOMPARE(evaluate<bool>(item, "Drag.drop() == Qt.CopyAction"), true);
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), false);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 1);
+ QCOMPARE(innerTarget.enterEvents, 0); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 0);
+
+ // Neither target accepts drop so Qt::IgnoreAction is returned.
+ innerTarget.reset(); outerTarget.reset();
+ evaluate<void>(item, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), true);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(outerTarget.enterEvents, 1); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 0);
+ QCOMPARE(innerTarget.enterEvents, 0); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 0);
+
+ outerTarget.accept = false;
+
+ innerTarget.reset(); outerTarget.reset();
+ QCOMPARE(evaluate<bool>(item, "Drag.drop() == Qt.IgnoreAction"), true);
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), false);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 1);
+ QCOMPARE(innerTarget.enterEvents, 0); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 0);
+}
+
+void tst_QSGDrag::move()
+{
+ QSGCanvas canvas;
+ TestDropTarget outerTarget(canvas.rootItem());
+ outerTarget.setSize(QSizeF(100, 100));
+ TestDropTarget leftTarget(&outerTarget);
+ leftTarget.setPos(QPointF(0, 35));
+ leftTarget.setSize(QSizeF(30, 30));
+ TestDropTarget rightTarget(&outerTarget);
+ rightTarget.setPos(QPointF(70, 35));
+ rightTarget.setSize(QSizeF(30, 30));
+ QDeclarativeComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "Item {\n"
+ "property bool dragActive: Drag.active\n"
+ "property Item dragTarget: Drag.target\n"
+ "x: 50; y: 50\n"
+ "width: 10; height: 10\n"
+ "}", QUrl());
+ QSGItem *item = qobject_cast<QSGItem *>(component.create());
+ QVERIFY(item);
+ item->setParentItem(&outerTarget);
+
+ evaluate<void>(item, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), true);
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(outerTarget.enterEvents, 1); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 0);
+ QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
+ QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
+ QCOMPARE(outerTarget.position.x(), qreal(50)); QCOMPARE(outerTarget.position.y(), qreal(50));
+
+ // Move within the outer target.
+ outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
+ item->setPos(QPointF(60, 50));
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 1);
+ QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
+ QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
+ QCOMPARE(outerTarget.position.x(), qreal(60)); QCOMPARE(outerTarget.position.y(), qreal(50));
+
+ // Move into the right target.
+ outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
+ item->setPos(QPointF(75, 50));
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&rightTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&rightTarget));
+ QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 1);
+ QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
+ QCOMPARE(rightTarget.enterEvents, 1); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
+ QCOMPARE(outerTarget.position.x(), qreal(75)); QCOMPARE(outerTarget.position.y(), qreal(50));
+ QCOMPARE(rightTarget.position.x(), qreal(5)); QCOMPARE(rightTarget.position.y(), qreal(15));
+
+ // Move into the left target.
+ outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
+ item->setPos(QPointF(25, 50));
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&leftTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&leftTarget));
+ QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 1);
+ QCOMPARE(leftTarget .enterEvents, 1); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
+ QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 1); QCOMPARE(rightTarget.moveEvents, 0);
+ QCOMPARE(outerTarget.position.x(), qreal(25)); QCOMPARE(outerTarget.position.y(), qreal(50));
+ QCOMPARE(leftTarget.position.x(), qreal(25)); QCOMPARE(leftTarget.position.y(), qreal(15));
+
+ // Move within the left target.
+ outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
+ item->setPos(QPointF(25, 40));
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&leftTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&leftTarget));
+ QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 1);
+ QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 1);
+ QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
+ QCOMPARE(outerTarget.position.x(), qreal(25)); QCOMPARE(outerTarget.position.y(), qreal(40));
+ QCOMPARE(leftTarget.position.x(), qreal(25)); QCOMPARE(leftTarget.position.y(), qreal(5));
+
+ // Move out of all targets.
+ outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
+ item->setPos(QPointF(110, 50));
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
+ QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 1); QCOMPARE(outerTarget.moveEvents, 0);
+ QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 1); QCOMPARE(leftTarget .moveEvents, 0);
+ QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
+
+ // Stop the right target accepting drag events and move into it.
+ rightTarget.accept = false;
+
+ outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
+ item->setPos(QPointF(80, 50));
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(outerTarget.enterEvents, 1); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 0);
+ QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
+ QCOMPARE(rightTarget.enterEvents, 1); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
+ QCOMPARE(outerTarget.position.x(), qreal(80)); QCOMPARE(outerTarget.position.y(), qreal(50));
+
+ // Stop the outer target accepting drag events after it has accepted an enter event.
+ outerTarget.accept = false;
+
+ outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
+ item->setPos(QPointF(60, 50));
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 1);
+ QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
+ QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
+ QCOMPARE(outerTarget.position.x(), qreal(60)); QCOMPARE(outerTarget.position.y(), qreal(50));
+
+ // Clear the QSGItem::ItemAcceptsDrops flag from the outer target after it accepted an enter event.
+ outerTarget.setFlags(QSGItem::Flags());
+
+ outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
+ item->setPos(QPointF(40, 50));
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 1);
+ QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
+ QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
+ QCOMPARE(outerTarget.position.x(), qreal(40)); QCOMPARE(outerTarget.position.y(), qreal(50));
+
+ // Clear the QSGItem::ItemAcceptsDrops flag from the left target before it accepts an enter event.
+ leftTarget.setFlags(QSGItem::Flags());
+
+ outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
+ item->setPos(QPointF(25, 50));
+ QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
+ QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 1);
+ QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
+ QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
+ QCOMPARE(outerTarget.position.x(), qreal(25)); QCOMPARE(outerTarget.position.y(), qreal(50));
+}
+
+
+void tst_QSGDrag::hotSpot()
+{
+ QSGCanvas canvas;
+ TestDropTarget dropTarget(canvas.rootItem());
+ dropTarget.setSize(QSizeF(100, 100));
+ QDeclarativeComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "Item {\n"
+ "property real hotSpotX: Drag.hotSpot.x\n"
+ "property real hotSpotY: Drag.hotSpot.y\n"
+ "x: 50; y: 50\n"
+ "width: 10; height: 10\n"
+ "}", QUrl());
+ QSGItem *item = qobject_cast<QSGItem *>(component.create());
+ QVERIFY(item);
+ item->setParentItem(&dropTarget);
+
+ QCOMPARE(evaluate<qreal>(item, "Drag.hotSpot.x"), qreal(0));
+ QCOMPARE(evaluate<qreal>(item, "Drag.hotSpot.y"), qreal(0));
+ QCOMPARE(evaluate<qreal>(item, "hotSpotX"), qreal(0));
+ QCOMPARE(evaluate<qreal>(item, "hotSpotY"), qreal(0));
+
+ evaluate<void>(item, "{ Drag.start(); Drag.cancel() }");
+ QCOMPARE(dropTarget.position.x(), qreal(50));
+ QCOMPARE(dropTarget.position.y(), qreal(50));
+
+ evaluate<void>(item, "{ Drag.hotSpot.x = 5, Drag.hotSpot.y = 5 }");
+ QCOMPARE(evaluate<qreal>(item, "Drag.hotSpot.x"), qreal(5));
+ QCOMPARE(evaluate<qreal>(item, "Drag.hotSpot.y"), qreal(5));
+ QCOMPARE(evaluate<qreal>(item, "hotSpotX"), qreal(5));
+ QCOMPARE(evaluate<qreal>(item, "hotSpotY"), qreal(5));
+
+ evaluate<void>(item, "Drag.start()");
+ QCOMPARE(dropTarget.position.x(), qreal(55));
+ QCOMPARE(dropTarget.position.y(), qreal(55));
+
+ item->setPos(QPointF(30, 20));
+ QCOMPARE(dropTarget.position.x(), qreal(35));
+ QCOMPARE(dropTarget.position.y(), qreal(25));
+
+ evaluate<void>(item, "{ Drag.hotSpot.x = 10; Drag.hotSpot.y = 10 }");
+ QCOMPARE(evaluate<qreal>(item, "Drag.hotSpot.x"), qreal(10));
+ QCOMPARE(evaluate<qreal>(item, "Drag.hotSpot.y"), qreal(10));
+ QCOMPARE(evaluate<qreal>(item, "hotSpotX"), qreal(10));
+ QCOMPARE(evaluate<qreal>(item, "hotSpotY"), qreal(10));
+ // Changing the hotSpot won't generate a move event so the position is unchanged. Should it?
+ QCOMPARE(dropTarget.position.x(), qreal(35));
+ QCOMPARE(dropTarget.position.y(), qreal(25));
+
+ item->setPos(QPointF(10, 20));
+ QCOMPARE(dropTarget.position.x(), qreal(20));
+ QCOMPARE(dropTarget.position.y(), qreal(30));
+}
+
+void tst_QSGDrag::supportedActions()
+{
+ QSGCanvas canvas;
+ TestDropTarget dropTarget(canvas.rootItem());
+ dropTarget.setSize(QSizeF(100, 100));
+ QDeclarativeComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "Item {\n"
+ "property int supportedActions: Drag.supportedActions\n"
+ "x: 50; y: 50\n"
+ "width: 10; height: 10\n"
+ "}", QUrl());
+ QSGItem *item = qobject_cast<QSGItem *>(component.create());
+ QVERIFY(item);
+ item->setParentItem(&dropTarget);
+
+ QCOMPARE(evaluate<bool>(item, "Drag.supportedActions == Qt.CopyAction | Qt.MoveAction | Qt.LinkAction"), true);
+ QCOMPARE(evaluate<bool>(item, "supportedActions == Qt.CopyAction | Qt.MoveAction | Qt.LinkAction"), true);
+ evaluate<void>(item, "{ Drag.start(); Drag.cancel() }");
+ QCOMPARE(dropTarget.supportedActions, Qt::CopyAction | Qt::MoveAction | Qt::LinkAction);
+
+ evaluate<void>(item, "Drag.supportedActions = Qt.CopyAction | Qt.MoveAction");
+ QCOMPARE(evaluate<bool>(item, "Drag.supportedActions == Qt.CopyAction | Qt.MoveAction"), true);
+ QCOMPARE(evaluate<bool>(item, "supportedActions == Qt.CopyAction | Qt.MoveAction"), true);
+ evaluate<void>(item, "Drag.start()");
+ QCOMPARE(dropTarget.supportedActions, Qt::CopyAction | Qt::MoveAction);
+
+ // Once a drag is started the proposed actions are locked in for future events.
+ evaluate<void>(item, "Drag.supportedActions = Qt.MoveAction");
+ QCOMPARE(evaluate<bool>(item, "Drag.supportedActions == Qt.MoveAction"), true);
+ QCOMPARE(evaluate<bool>(item, "supportedActions == Qt.MoveAction"), true);
+ item->setPos(QPointF(60, 60));
+ QCOMPARE(dropTarget.supportedActions, Qt::CopyAction | Qt::MoveAction);
+
+ // Calling start with proposed actions will override the current actions for the next sequence.
+ evaluate<void>(item, "Drag.start(Qt.CopyAction)");
+ QCOMPARE(evaluate<bool>(item, "Drag.supportedActions == Qt.MoveAction"), true);
+ QCOMPARE(evaluate<bool>(item, "supportedActions == Qt.MoveAction"), true);
+ QCOMPARE(dropTarget.supportedActions, Qt::CopyAction);
+
+ evaluate<void>(item, "Drag.start()");
+ QCOMPARE(evaluate<bool>(item, "Drag.supportedActions == Qt.MoveAction"), true);
+ QCOMPARE(evaluate<bool>(item, "supportedActions == Qt.MoveAction"), true);
+ QCOMPARE(dropTarget.supportedActions, Qt::MoveAction);
+}
+
+void tst_QSGDrag::proposedAction()
+{
+ QSGCanvas canvas;
+ TestDropTarget dropTarget(canvas.rootItem());
+ dropTarget.setSize(QSizeF(100, 100));
+ QDeclarativeComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "Item {\n"
+ "property int proposedAction: Drag.proposedAction\n"
+ "x: 50; y: 50\n"
+ "width: 10; height: 10\n"
+ "}", QUrl());
+ QSGItem *item = qobject_cast<QSGItem *>(component.create());
+ QVERIFY(item);
+ item->setParentItem(&dropTarget);
+
+ QCOMPARE(evaluate<bool>(item, "Drag.proposedAction == Qt.MoveAction"), true);
+ QCOMPARE(evaluate<bool>(item, "proposedAction == Qt.MoveAction"), true);
+ evaluate<void>(item, "{ Drag.start(); Drag.cancel() }");
+ QCOMPARE(dropTarget.defaultAction, Qt::MoveAction);
+ QCOMPARE(dropTarget.proposedAction, Qt::MoveAction);
+
+ evaluate<void>(item, "Drag.proposedAction = Qt.CopyAction");
+ QCOMPARE(evaluate<bool>(item, "Drag.proposedAction == Qt.CopyAction"), true);
+ QCOMPARE(evaluate<bool>(item, "proposedAction == Qt.CopyAction"), true);
+ evaluate<void>(item, "Drag.start()");
+ QCOMPARE(dropTarget.defaultAction, Qt::CopyAction);
+ QCOMPARE(dropTarget.proposedAction, Qt::CopyAction);
+
+ // The proposed action can change during a drag.
+ evaluate<void>(item, "Drag.proposedAction = Qt.MoveAction");
+ QCOMPARE(evaluate<bool>(item, "Drag.proposedAction == Qt.MoveAction"), true);
+ QCOMPARE(evaluate<bool>(item, "proposedAction == Qt.MoveAction"), true);
+ item->setPos(QPointF(60, 60));
+ QCOMPARE(dropTarget.defaultAction, Qt::MoveAction);
+ QCOMPARE(dropTarget.proposedAction, Qt::MoveAction);
+
+ evaluate<void>(item, "Drag.proposedAction = Qt.LinkAction");
+ QCOMPARE(evaluate<bool>(item, "Drag.proposedAction == Qt.LinkAction"), true);
+ QCOMPARE(evaluate<bool>(item, "proposedAction == Qt.LinkAction"), true);
+ evaluate<void>(item, "Drag.drop()");
+ QCOMPARE(dropTarget.defaultAction, Qt::LinkAction);
+ QCOMPARE(dropTarget.proposedAction, Qt::LinkAction);
+}
+
+void tst_QSGDrag::keys()
+{
+ QDeclarativeComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "Item {\n"
+ "property variant keys: Drag.keys\n"
+ "x: 50; y: 50\n"
+ "width: 10; height: 10\n"
+ "}", QUrl());
+ QSGItem *item = qobject_cast<QSGItem *>(component.create());
+ QVERIFY(item);
+
+// QCOMPARE(evaluate<QStringList>(item, "Drag.keys"), QStringList());
+// QCOMPARE(evaluate<QStringList>(item, "keys"), QStringList());
+ QCOMPARE(item->property("keys").toStringList(), QStringList());
+
+ evaluate<void>(item, "Drag.keys = [\"red\", \"blue\"]");
+// QCOMPARE(evaluate<QStringList>(item, "Drag.keys"), QStringList() << "red" << "blue");
+// QCOMPARE(evaluate<QStringList>(item, "keys"), QStringList() << "red" << "blue");
+ QCOMPARE(item->property("keys").toStringList(), QStringList() << "red" << "blue");
+}
+
+void tst_QSGDrag::source()
+{
+
+ QDeclarativeComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "Item {\n"
+ "property Item source: Drag.source\n"
+ "x: 50; y: 50\n"
+ "width: 10; height: 10\n"
+ "Item { id: proxySource; objectName: \"proxySource\" }\n"
+ "}", QUrl());
+ QSGItem *item = qobject_cast<QSGItem *>(component.create());
+ QVERIFY(item);
+
+ QCOMPARE(evaluate<QObject *>(item, "Drag.source"), static_cast<QObject *>(item));
+ QCOMPARE(evaluate<QObject *>(item, "source"), static_cast<QObject *>(item));
+
+ QSGItem *proxySource = item->findChild<QSGItem *>("proxySource");
+ QVERIFY(proxySource);
+
+ evaluate<void>(item, "Drag.source = proxySource");
+ QCOMPARE(evaluate<QObject *>(item, "Drag.source"), static_cast<QObject *>(proxySource));
+ QCOMPARE(evaluate<QObject *>(item, "source"), static_cast<QObject *>(proxySource));
+}
+
+QTEST_MAIN(tst_QSGDrag)
+
+#include "tst_qsgdrag.moc"
diff --git a/tests/auto/declarative/qsgdroparea/qsgdroparea.pro b/tests/auto/declarative/qsgdroparea/qsgdroparea.pro
new file mode 100644
index 0000000000..2f4be247b0
--- /dev/null
+++ b/tests/auto/declarative/qsgdroparea/qsgdroparea.pro
@@ -0,0 +1,11 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative gui network
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qsgdroparea.cpp
+
+DEFINES += SRCDIR=\\\"$$PWD\\\"
+
+CONFIG += parallel_test
+
+QT += core-private gui-private declarative-private
diff --git a/tests/auto/declarative/qsgdroparea/tst_qsgdroparea.cpp b/tests/auto/declarative/qsgdroparea/tst_qsgdroparea.cpp
new file mode 100644
index 0000000000..4fa6704611
--- /dev/null
+++ b/tests/auto/declarative/qsgdroparea/tst_qsgdroparea.cpp
@@ -0,0 +1,1063 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite 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 <QtTest/QtTest>
+#include <QtTest/QSignalSpy>
+#include <QtDeclarative/qsgitem.h>
+#include <QtDeclarative/qsgview.h>
+#include <QtDeclarative/qdeclarativecontext.h>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativeexpression.h>
+#include "../../../shared/util.h"
+
+#include <QtGui/qwindowsysteminterface_qpa.h>
+
+template <typename T> static T evaluate(QObject *scope, const QString &expression)
+{
+ QDeclarativeExpression expr(qmlContext(scope), scope, expression);
+ QVariant result = expr.evaluate();
+ if (expr.hasError())
+ qWarning() << expr.error().toString();
+ return result.value<T>();
+}
+
+template <> void evaluate<void>(QObject *scope, const QString &expression)
+{
+ QDeclarativeExpression expr(qmlContext(scope), scope, expression);
+ expr.evaluate();
+ if (expr.hasError())
+ qWarning() << expr.error().toString();
+}
+
+class tst_QSGDropArea: public QObject
+{
+ Q_OBJECT
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+ void containsDrag_internal();
+ void containsDrag_external();
+ void keys_internal();
+ void keys_external();
+ void source_internal();
+// void source_external();
+ void position_internal();
+ void position_external();
+ void drop_internal();
+// void drop_external();
+ void simultaneousDrags();
+
+private:
+ QDeclarativeEngine engine;
+};
+
+void tst_QSGDropArea::initTestCase()
+{
+
+}
+
+void tst_QSGDropArea::cleanupTestCase()
+{
+
+}
+
+void tst_QSGDropArea::containsDrag_internal()
+{
+ QSGCanvas canvas;
+ QDeclarativeComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "DropArea {\n"
+ "property bool hasDrag: containsDrag\n"
+ "property int enterEvents: 0\n"
+ "property int exitEvents: 0\n"
+ "width: 100; height: 100\n"
+ "onEntered: {++enterEvents}\n"
+ "onExited: {++exitEvents}\n"
+ "Item {\n"
+ "objectName: \"dragItem\"\n"
+ "x: 50; y: 50\n"
+ "width: 10; height: 10\n"
+ "}\n"
+ "}", QUrl());
+ QSGItem *dropArea = qobject_cast<QSGItem *>(component.create());
+ QVERIFY(dropArea);
+ dropArea->setParentItem(canvas.rootItem());
+
+ QSGItem *dragItem = dropArea->findChild<QSGItem *>("dragItem");
+ QVERIFY(dragItem);
+
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
+ QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
+
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
+ QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 0);
+
+ evaluate<void>(dropArea, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dragItem, "Drag.active = false");
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
+ QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 1);
+
+ evaluate<void>(dropArea, "{ enterEvents = 0; exitEvents = 0 }");
+
+ dragItem->setPos(QPointF(150, 50));
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
+ QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 0);
+
+ dragItem->setPos(QPointF(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
+ QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 0);
+
+ evaluate<void>(dropArea, "{ enterEvents = 0; exitEvents = 0 }");
+ dragItem->setPos(QPointF(150, 50));
+
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
+ QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 1);
+
+ evaluate<void>(dragItem, "Drag.active = false");
+}
+
+void tst_QSGDropArea::containsDrag_external()
+{
+ QSGCanvas canvas;
+ QDeclarativeComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "DropArea {\n"
+ "property bool hasDrag: containsDrag\n"
+ "property int enterEvents: 0\n"
+ "property int exitEvents: 0\n"
+ "width: 100; height: 100\n"
+ "onEntered: {++enterEvents}\n"
+ "onExited: {++exitEvents}\n"
+ "}", QUrl());
+ QSGItem *dropArea = qobject_cast<QSGItem *>(component.create());
+ QVERIFY(dropArea);
+ dropArea->setParentItem(canvas.rootItem());
+
+ QMimeData data;
+ QSGCanvas alternateCanvas;
+
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
+ QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
+
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
+ QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 0);
+
+ evaluate<void>(dropArea, "{ enterEvents = 0; exitEvents = 0 }");
+ QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
+ QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 1);
+
+ evaluate<void>(dropArea, "{ enterEvents = 0; exitEvents = 0 }");
+
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(150, 50));
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
+ QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 0);
+
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
+ QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 0);
+
+ evaluate<void>(dropArea, "{ enterEvents = 0; exitEvents = 0 }");
+
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(150, 50));
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
+ QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 1);
+
+ QWindowSystemInterface::handleDrop(&canvas, &data, QPoint(150, 50));
+}
+
+void tst_QSGDropArea::keys_internal()
+{
+ QSGCanvas canvas;
+ QDeclarativeComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "DropArea {\n"
+ "property variant dragKeys\n"
+ "property variant dropKeys: keys\n"
+ "property int enterEvents: 0\n"
+ "width: 100; height: 100\n"
+ "onEntered: {++enterEvents; dragKeys = drag.keys }\n"
+ "Item {\n"
+ "objectName: \"dragItem\"\n"
+ "x: 50; y: 50\n"
+ "width: 10; height: 10\n"
+ "Drag.keys: [\"red\", \"blue\"]\n"
+ "}\n"
+ "}", QUrl());
+ QSGItem *dropArea = qobject_cast<QSGItem *>(component.create());
+ QVERIFY(dropArea);
+ dropArea->setParentItem(canvas.rootItem());
+
+ QSGItem *dragItem = dropArea->findChild<QSGItem *>("dragItem");
+ QVERIFY(dragItem);
+
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
+
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
+ QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "red" << "blue");
+
+ evaluate<void>(dragItem, "Drag.active = false");
+ evaluate<void>(dropArea, "keys = \"blue\"");
+ QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "blue");
+ QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "blue");
+ evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
+ QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "red" << "blue");
+
+ evaluate<void>(dragItem, "Drag.active = false");
+ evaluate<void>(dropArea, "keys = \"red\"");
+ QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "red");
+ QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "red");
+ evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
+ QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "red" << "blue");
+
+ evaluate<void>(dragItem, "Drag.active = false");
+ evaluate<void>(dropArea, "keys = \"green\"");
+ QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "green");
+ QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "green");
+ evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
+
+ evaluate<void>(dragItem, "Drag.active = false");
+ evaluate<void>(dropArea, "keys = [\"red\", \"green\"]");
+ QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "red" << "green");
+ QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "red" << "green");
+ evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
+ QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "red" << "blue");
+
+ evaluate<void>(dragItem, "Drag.active = false");
+ evaluate<void>(dragItem, "Drag.keys = []");
+ evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
+}
+
+void tst_QSGDropArea::keys_external()
+{
+ QSGCanvas canvas;
+ QDeclarativeComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "DropArea {\n"
+ "property variant dragKeys\n"
+ "property variant dropKeys: keys\n"
+ "property int enterEvents: 0\n"
+ "width: 100; height: 100\n"
+ "onEntered: {++enterEvents; dragKeys = drag.keys }\n"
+ "}", QUrl());
+ QSGItem *dropArea = qobject_cast<QSGItem *>(component.create());
+ QVERIFY(dropArea);
+ dropArea->setParentItem(canvas.rootItem());
+
+ QMimeData data;
+ QSGCanvas alternateCanvas;
+
+ data.setData("text/x-red", "red");
+ data.setData("text/x-blue", "blue");
+
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
+
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
+ QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "text/x-red" << "text/x-blue");
+
+ QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
+ evaluate<void>(dropArea, "keys = \"text/x-blue\"");
+ QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "text/x-blue");
+ QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "text/x-blue");
+ evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
+ QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "text/x-red" << "text/x-blue");
+
+ QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
+ evaluate<void>(dropArea, "keys = \"text/x-red\"");
+ QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "text/x-red");
+ QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "text/x-red");
+ evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
+ QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "text/x-red" << "text/x-blue");
+
+ QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
+ evaluate<void>(dropArea, "keys = \"text/x-green\"");
+ QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "text/x-green");
+ QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "text/x-green");
+ evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
+
+ QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
+ evaluate<void>(dropArea, "keys = [\"text/x-red\", \"text/x-green\"]");
+ QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "text/x-red" << "text/x-green");
+ QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "text/x-red" << "text/x-green");
+ evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
+ QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "text/x-red" << "text/x-blue");
+
+ QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
+ data.removeFormat("text/x-red");
+ data.removeFormat("text/x-blue");
+ evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
+
+ QWindowSystemInterface::handleDrop(&canvas, &data, QPoint(50, 50));
+}
+
+void tst_QSGDropArea::source_internal()
+{
+ QSGCanvas canvas;
+ QDeclarativeComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "DropArea {\n"
+ "property Item source: drag.source\n"
+ "property Item eventSource\n"
+ "width: 100; height: 100\n"
+ "onEntered: {eventSource = drag.source}\n"
+ "Item {\n"
+ "objectName: \"dragItem\"\n"
+ "x: 50; y: 50\n"
+ "width: 10; height: 10\n"
+ "}\n"
+ "Item { id: dragSource; objectName: \"dragSource\" }\n"
+ "}", QUrl());
+ QSGItem *dropArea = qobject_cast<QSGItem *>(component.create());
+ QVERIFY(dropArea);
+ dropArea->setParentItem(canvas.rootItem());
+
+ QSGItem *dragItem = dropArea->findChild<QSGItem *>("dragItem");
+ QVERIFY(dragItem);
+
+ QSGItem *dragSource = dropArea->findChild<QSGItem *>("dragSource");
+ QVERIFY(dragSource);
+
+ QCOMPARE(evaluate<QObject *>(dropArea, "source"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(dropArea, "drag.source"), static_cast<QObject *>(0));
+
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<QObject *>(dropArea, "source"), static_cast<QObject *>(dragItem));
+ QCOMPARE(evaluate<QObject *>(dropArea, "drag.source"), static_cast<QObject *>(dragItem));
+ QCOMPARE(evaluate<QObject *>(dropArea, "eventSource"), static_cast<QObject *>(dragItem));
+
+ evaluate<void>(dragItem, "Drag.active = false");
+ QCOMPARE(evaluate<QObject *>(dropArea, "source"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(dropArea, "drag.source"), static_cast<QObject *>(0));
+
+
+ evaluate<void>(dropArea, "{ eventSource = null }");
+ evaluate<void>(dragItem, "Drag.source = dragSource");
+
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<QObject *>(dropArea, "source"), static_cast<QObject *>(dragSource));
+ QCOMPARE(evaluate<QObject *>(dropArea, "drag.source"), static_cast<QObject *>(dragSource));
+ QCOMPARE(evaluate<QObject *>(dropArea, "eventSource"), static_cast<QObject *>(dragSource));
+
+ evaluate<void>(dragItem, "Drag.active = false");
+ QCOMPARE(evaluate<QObject *>(dropArea, "source"), static_cast<QObject *>(0));
+ QCOMPARE(evaluate<QObject *>(dropArea, "drag.source"), static_cast<QObject *>(0));
+}
+
+// Setting a source can't be emulated using the QWindowSystemInterface API.
+
+//void tst_QSGDropArea::source_external()
+//{
+//}
+
+void tst_QSGDropArea::position_internal()
+{
+ QSGCanvas canvas;
+ QDeclarativeComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "DropArea {\n"
+ "property real dragX: drag.x\n"
+ "property real dragY: drag.y\n"
+ "property real eventX\n"
+ "property real eventY\n"
+ "property int enterEvents: 0\n"
+ "property int moveEvents: 0\n"
+ "width: 100; height: 100\n"
+ "onEntered: {++enterEvents; eventX = drag.x; eventY = drag.y}\n"
+ "onPositionChanged: {++moveEvents; eventX = drag.x; eventY = drag.y}\n"
+ "Item {\n"
+ "objectName: \"dragItem\"\n"
+ "x: 50; y: 50\n"
+ "width: 10; height: 10\n"
+ "}\n"
+ "}", QUrl());
+ QSGItem *dropArea = qobject_cast<QSGItem *>(component.create());
+ QVERIFY(dropArea);
+ dropArea->setParentItem(canvas.rootItem());
+
+ QSGItem *dragItem = dropArea->findChild<QSGItem *>("dragItem");
+ QVERIFY(dragItem);
+
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea, "moveEvents"), 0);
+ QCOMPARE(evaluate<qreal>(dropArea, "drag.x"), qreal(50));
+ QCOMPARE(evaluate<qreal>(dropArea, "drag.y"), qreal(50));
+ QCOMPARE(evaluate<qreal>(dropArea, "dragX"), qreal(50));
+ QCOMPARE(evaluate<qreal>(dropArea, "dragY"), qreal(50));
+ QCOMPARE(evaluate<qreal>(dropArea, "eventX"), qreal(50));
+ QCOMPARE(evaluate<qreal>(dropArea, "eventY"), qreal(50));
+
+ evaluate<void>(dropArea, "{ enterEvents = 0; moveEvents = 0; eventX = -1; eventY = -1 }");
+ dragItem->setPos(QPointF(40, 50));
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea, "moveEvents"), 1);
+ QCOMPARE(evaluate<qreal>(dropArea, "drag.x"), qreal(40));
+ QCOMPARE(evaluate<qreal>(dropArea, "drag.y"), qreal(50));
+ QCOMPARE(evaluate<qreal>(dropArea, "dragX"), qreal(40));
+ QCOMPARE(evaluate<qreal>(dropArea, "dragY"), qreal(50));
+ QCOMPARE(evaluate<qreal>(dropArea, "eventX"), qreal(40));
+ QCOMPARE(evaluate<qreal>(dropArea, "eventY"), qreal(50));
+
+ evaluate<void>(dropArea, "{ enterEvents = 0; moveEvents = 0; eventX = -1; eventY = -1 }");
+ dragItem->setPos(QPointF(75, 25));
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea, "moveEvents"), 1);
+ QCOMPARE(evaluate<qreal>(dropArea, "drag.x"), qreal(75));
+ QCOMPARE(evaluate<qreal>(dropArea, "drag.y"), qreal(25));
+ QCOMPARE(evaluate<qreal>(dropArea, "dragX"), qreal(75));
+ QCOMPARE(evaluate<qreal>(dropArea, "dragY"), qreal(25));
+ QCOMPARE(evaluate<qreal>(dropArea, "eventX"), qreal(75));
+ QCOMPARE(evaluate<qreal>(dropArea, "eventY"), qreal(25));
+
+ evaluate<void>(dragItem, "Drag.active = false");
+}
+
+void tst_QSGDropArea::position_external()
+{
+ QSGCanvas canvas;
+ QDeclarativeComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "DropArea {\n"
+ "property real dragX: drag.x\n"
+ "property real dragY: drag.y\n"
+ "property real eventX\n"
+ "property real eventY\n"
+ "property int enterEvents: 0\n"
+ "property int moveEvents: 0\n"
+ "width: 100; height: 100\n"
+ "onEntered: {++enterEvents; eventX = drag.x; eventY = drag.y}\n"
+ "onPositionChanged: {++moveEvents; eventX = drag.x; eventY = drag.y}\n"
+ "}", QUrl());
+ QSGItem *dropArea = qobject_cast<QSGItem *>(component.create());
+ QVERIFY(dropArea);
+ dropArea->setParentItem(canvas.rootItem());
+
+ QMimeData data;
+
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea, "moveEvents"), 1);
+ QCOMPARE(evaluate<qreal>(dropArea, "drag.x"), qreal(50));
+ QCOMPARE(evaluate<qreal>(dropArea, "drag.y"), qreal(50));
+ QCOMPARE(evaluate<qreal>(dropArea, "dragX"), qreal(50));
+ QCOMPARE(evaluate<qreal>(dropArea, "dragY"), qreal(50));
+ QCOMPARE(evaluate<qreal>(dropArea, "eventX"), qreal(50));
+ QCOMPARE(evaluate<qreal>(dropArea, "eventY"), qreal(50));
+
+ evaluate<void>(dropArea, "{ enterEvents = 0; moveEvents = 0; eventX = -1; eventY = -1 }");
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(40, 50));
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea, "moveEvents"), 1);
+ QCOMPARE(evaluate<qreal>(dropArea, "drag.x"), qreal(40));
+ QCOMPARE(evaluate<qreal>(dropArea, "drag.y"), qreal(50));
+ QCOMPARE(evaluate<qreal>(dropArea, "dragX"), qreal(40));
+ QCOMPARE(evaluate<qreal>(dropArea, "dragY"), qreal(50));
+ QCOMPARE(evaluate<qreal>(dropArea, "eventX"), qreal(40));
+ QCOMPARE(evaluate<qreal>(dropArea, "eventY"), qreal(50));
+
+ evaluate<void>(dropArea, "{ enterEvents = 0; moveEvents = 0; eventX = -1; eventY = -1 }");
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(75, 25));
+ QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea, "moveEvents"), 1);
+ QCOMPARE(evaluate<qreal>(dropArea, "drag.x"), qreal(75));
+ QCOMPARE(evaluate<qreal>(dropArea, "drag.y"), qreal(25));
+ QCOMPARE(evaluate<qreal>(dropArea, "dragX"), qreal(75));
+ QCOMPARE(evaluate<qreal>(dropArea, "dragY"), qreal(25));
+ QCOMPARE(evaluate<qreal>(dropArea, "eventX"), qreal(75));
+ QCOMPARE(evaluate<qreal>(dropArea, "eventY"), qreal(25));
+
+ QWindowSystemInterface::handleDrop(&canvas, &data, QPoint(75, 25));
+}
+
+void tst_QSGDropArea::drop_internal()
+{
+ QSGCanvas canvas;
+ QDeclarativeComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "DropArea {\n"
+ "property bool accept: false\n"
+ "property bool setAccepted: false\n"
+ "property bool acceptDropAction: false\n"
+ "property bool setDropAction: false\n"
+ "property int dropAction: Qt.IgnoreAction\n"
+ "property int proposedAction: Qt.IgnoreAction\n"
+ "property int supportedActions: Qt.IgnoreAction\n"
+ "property int dropEvents: 0\n"
+ "width: 100; height: 100\n"
+ "onDropped: {\n"
+ "++dropEvents\n"
+ "supportedActions = drop.supportedActions\n"
+ "proposedAction = drop.action\n"
+ "if (setDropAction)\n"
+ "drop.action = dropAction\n"
+ "if (acceptDropAction)\n"
+ "drop.accept(dropAction)\n"
+ "else if (setAccepted)\n"
+ "drop.accepted = accept\n"
+ "else if (accept)\n"
+ "drop.accept()\n"
+ "}\n"
+ "Item {\n"
+ "objectName: \"dragItem\"\n"
+ "x: 50; y: 50\n"
+ "width: 10; height: 10\n"
+ "}\n"
+ "}", QUrl());
+ QSGItem *dropArea = qobject_cast<QSGItem *>(component.create());
+ QVERIFY(dropArea);
+ dropArea->setParentItem(canvas.rootItem());
+
+ QSGItem *dragItem = dropArea->findChild<QSGItem *>("dragItem");
+ QVERIFY(dragItem);
+
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::IgnoreAction));
+ QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction));
+ QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
+
+ evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
+ evaluate<void>(dropArea, "{ accept = true; setDropAction = true; dropAction = Qt.LinkAction }");
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::LinkAction));
+ QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction));
+ QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
+
+ evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
+ evaluate<void>(dropArea, "{ setAccepted = true; }");
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::LinkAction));
+ QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction));
+ QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
+
+ evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
+ evaluate<void>(dropArea, "{ accept = false; setAccepted = true; }");
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::IgnoreAction));
+ QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction));
+ QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
+
+ evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
+ evaluate<void>(dropArea, "{ setAccepted = false; setDropAction = false; acceptDropAction = true; }");
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::LinkAction));
+ QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction));
+ QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
+
+ evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
+ evaluate<void>(dropArea, "{ acceptDropAction = false; dropAction = Qt.IgnoreAction; accept = true }");
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::MoveAction));
+ QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction));
+ QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
+
+ evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
+ evaluate<void>(dropArea, "{ setAccepted = true }");
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::MoveAction));
+ QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction));
+ QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
+
+ evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
+ evaluate<void>(dropArea, "{ setAccepted = false }");
+ evaluate<void>(dragItem, "Drag.supportedActions = Qt.LinkAction");
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::MoveAction));
+ QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::LinkAction));
+ QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
+
+ evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
+ evaluate<void>(dropArea, "{ setAccepted = true }");
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::MoveAction));
+ QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::LinkAction));
+ QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
+
+ evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
+ evaluate<void>(dropArea, "{ setAccepted = false }");
+ evaluate<void>(dragItem, "Drag.proposedAction = Qt.LinkAction");
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::LinkAction));
+ QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::LinkAction));
+ QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::LinkAction));
+
+ evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
+ evaluate<void>(dropArea, "{ setAccepted = true }");
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::LinkAction));
+ QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::LinkAction));
+ QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::LinkAction));
+}
+
+// Setting the supportedActions can't be emulated using the QWindowSystemInterface API.
+
+//void tst_QSGDropArea::drop_external()
+//{
+//}
+
+void tst_QSGDropArea::simultaneousDrags()
+{
+ QSGCanvas canvas;
+ QDeclarativeComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "DropArea {\n"
+ "property int enterEvents: 0\n"
+ "property int exitEvents: 0\n"
+ "width: 100; height: 100\n"
+ "keys: [\"red\", \"text/x-red\"]\n"
+ "onEntered: {++enterEvents}\n"
+ "onExited: {++exitEvents}\n"
+ "DropArea {\n"
+ "objectName: \"dropArea2\"\n"
+ "property int enterEvents: 0\n"
+ "property int exitEvents: 0\n"
+ "width: 100; height: 100\n"
+ "keys: [\"blue\", \"text/x-blue\"]\n"
+ "onEntered: {++enterEvents}\n"
+ "onExited: {++exitEvents}\n"
+ "}\n"
+ "Item {\n"
+ "objectName: \"dragItem1\"\n"
+ "x: 50; y: 50\n"
+ "width: 10; height: 10\n"
+ "Drag.keys: [\"red\", \"blue\"]"
+ "}\n"
+ "Item {\n"
+ "objectName: \"dragItem2\"\n"
+ "x: 50; y: 50\n"
+ "width: 10; height: 10\n"
+ "Drag.keys: [\"red\", \"blue\"]"
+ "}\n"
+ "}", QUrl());
+
+ QSGItem *dropArea1 = qobject_cast<QSGItem *>(component.create());
+ QVERIFY(dropArea1);
+ dropArea1->setParentItem(canvas.rootItem());
+
+ QSGItem *dropArea2 = dropArea1->findChild<QSGItem *>("dropArea2");
+ QVERIFY(dropArea2);
+
+ QSGItem *dragItem1 = dropArea1->findChild<QSGItem *>("dragItem1");
+ QVERIFY(dragItem1);
+
+ QSGItem *dragItem2 = dropArea1->findChild<QSGItem *>("dragItem2");
+ QVERIFY(dragItem2);
+
+ QMimeData data;
+ data.setData("text/x-red", "red");
+ data.setData("text/x-blue", "blue");
+
+ QSGCanvas alternateCanvas;
+
+ // Mixed internal drags.
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dragItem1, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dragItem2, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ evaluate<void>(dragItem2, "Drag.active = false");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ evaluate<void>(dragItem2, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ evaluate<void>(dragItem1, "Drag.active = false");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 1);
+
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dragItem2, "Drag.active = false");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ // internal then external.
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dragItem1, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ evaluate<void>(dragItem1, "Drag.active = false");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 1);
+
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ // external then internal.
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dragItem2, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ evaluate<void>(dragItem2, "Drag.active = false");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ evaluate<void>(dragItem2, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 1);
+
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dragItem2, "Drag.active = false");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ // Different acceptance
+ evaluate<void>(dragItem1, "Drag.keys = \"red\"");
+ evaluate<void>(dragItem2, "Drag.keys = \"blue\"");
+ data.removeFormat("text/x-red");
+
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dragItem1, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dragItem2, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dragItem2, "Drag.active = false");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 1);
+
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dragItem2, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dragItem1, "Drag.active = false");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dragItem2, "Drag.active = false");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 1);
+
+ // internal then external
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dragItem1, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 1);
+
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dragItem1, "Drag.active = false");
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
+
+ evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
+ evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
+ QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 1);
+
+ QWindowSystemInterface::handleDrop(&alternateCanvas, &data, QPoint(50, 50));
+}
+
+QTEST_MAIN(tst_QSGDropArea)
+
+#include "tst_qsgdroparea.moc"
diff --git a/tools/qmlplugindump/main.cpp b/tools/qmlplugindump/main.cpp
index e7f183e798..d0ab0d8784 100644
--- a/tools/qmlplugindump/main.cpp
+++ b/tools/qmlplugindump/main.cpp
@@ -43,7 +43,6 @@
#include <QtDeclarative/private/qdeclarativemetatype_p.h>
#include <QtDeclarative/private/qdeclarativeopenmetaobject_p.h>
#include <QtDeclarative/private/qsgevents_p_p.h>
-#include <QtDeclarative/private/qsgdragtarget_p.h>
#include <QtDeclarative/private/qsgpincharea_p.h>
#include <QtWidgets/QApplication>
@@ -588,7 +587,7 @@ int main(int argc, char *argv[])
// add some otherwise unreachable QMetaObjects
defaultReachable.insert(&QSGMouseEvent::staticMetaObject);
- // QSGKeyEvent, QSGPinchEvent, QSGDragTargetEvent are not exported
+ // QSGKeyEvent, QSGPinchEvent, QSGDropEvent are not exported
// this will hold the meta objects we want to dump information of
QSet<const QMetaObject *> metas;