aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;