From 2df9abf7047afbe20b19d156ac37b58d9b047575 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Thu, 9 Feb 2012 17:59:44 +1000 Subject: [PATCH] Built-in transition support for ListView & GridView ListView and GridView can now be assigned transitions to be run when: - Populating the view (when initially setting the model / resetting) - Adding items - Removing items - Moving items The ViewTransition attached object can be used from within a transition declaration to access various information about the items that are being transitioned. Task-number: QTBUG-21504 Change-Id: Ie5c75ea511c8b15acc3f06fccf19abe34d3677f9 Reviewed-by: Martin Jones --- doc/src/images/viewtransitions-basic.gif | Bin 0 -> 49932 bytes doc/src/images/viewtransitions-delayedbyindex.gif | Bin 0 -> 69623 bytes .../images/viewtransitions-intermediatemove.gif | Bin 0 -> 109530 bytes doc/src/images/viewtransitions-interruptedbad.gif | Bin 0 -> 30112 bytes doc/src/images/viewtransitions-interruptedgood.gif | Bin 0 -> 38076 bytes doc/src/images/viewtransitions-pathanim.gif | Bin 0 -> 43741 bytes doc/src/images/viewtransitions-scriptactionbad.gif | Bin 0 -> 49200 bytes .../viewtransitions/viewtransitions-basic.qml | 70 ++ .../viewtransitions-delayedbyindex.qml | 78 ++ .../viewtransitions-intermediatemove.qml | 90 ++ .../viewtransitions-interruptedgood.qml | 74 ++ .../viewtransitions/viewtransitions-pathanim.qml | 105 ++ .../viewtransitions-scriptactionbad.qml | 81 ++ .../viewtransitions-scriptactiongood.qml | 84 ++ doc/src/whatsnew.qdoc | 5 +- src/quick/items/qquickgridview.cpp | 416 +++++++- src/quick/items/qquickitemsmodule.cpp | 1 + src/quick/items/qquickitemview.cpp | 1126 +++++++++++++++++++- src/quick/items/qquickitemview_p.h | 86 +- src/quick/items/qquickitemview_p_p.h | 139 ++- src/quick/items/qquicklistview.cpp | 417 +++++++- .../qquickgridview/data/addTransitions.qml | 129 +++ .../qquickgridview/data/moveTransitions.qml | 143 +++ .../qquickgridview/data/multipleTransitions.qml | 123 +++ .../qquickgridview/data/populateTransitions.qml | 103 ++ .../qquickgridview/data/removeTransitions.qml | 146 +++ .../qtquick2/qquickgridview/tst_qquickgridview.cpp | 977 ++++++++++++++++- .../qquicklistview/data/addTransitions.qml | 134 +++ .../qquicklistview/data/moveTransitions.qml | 141 +++ .../qquicklistview/data/multipleTransitions.qml | 121 +++ .../qquicklistview/data/populateTransitions.qml | 102 ++ .../qquicklistview/data/removeTransitions.qml | 144 +++ .../qtquick2/qquicklistview/tst_qquicklistview.cpp | 950 ++++++++++++++++- tests/auto/qtquick2/shared/viewtestutil.cpp | 148 +++ tests/auto/qtquick2/shared/viewtestutil.h | 48 +- tests/auto/qtquick2/shared/visualtestutil.h | 10 + 36 files changed, 6039 insertions(+), 152 deletions(-) create mode 100644 doc/src/images/viewtransitions-basic.gif create mode 100644 doc/src/images/viewtransitions-delayedbyindex.gif create mode 100644 doc/src/images/viewtransitions-intermediatemove.gif create mode 100644 doc/src/images/viewtransitions-interruptedbad.gif create mode 100644 doc/src/images/viewtransitions-interruptedgood.gif create mode 100644 doc/src/images/viewtransitions-pathanim.gif create mode 100644 doc/src/images/viewtransitions-scriptactionbad.gif create mode 100644 doc/src/snippets/declarative/viewtransitions/viewtransitions-basic.qml create mode 100644 doc/src/snippets/declarative/viewtransitions/viewtransitions-delayedbyindex.qml create mode 100644 doc/src/snippets/declarative/viewtransitions/viewtransitions-intermediatemove.qml create mode 100644 doc/src/snippets/declarative/viewtransitions/viewtransitions-interruptedgood.qml create mode 100644 doc/src/snippets/declarative/viewtransitions/viewtransitions-pathanim.qml create mode 100644 doc/src/snippets/declarative/viewtransitions/viewtransitions-scriptactionbad.qml create mode 100644 doc/src/snippets/declarative/viewtransitions/viewtransitions-scriptactiongood.qml create mode 100644 tests/auto/qtquick2/qquickgridview/data/addTransitions.qml create mode 100644 tests/auto/qtquick2/qquickgridview/data/moveTransitions.qml create mode 100644 tests/auto/qtquick2/qquickgridview/data/multipleTransitions.qml create mode 100644 tests/auto/qtquick2/qquickgridview/data/populateTransitions.qml create mode 100644 tests/auto/qtquick2/qquickgridview/data/removeTransitions.qml create mode 100644 tests/auto/qtquick2/qquicklistview/data/addTransitions.qml create mode 100644 tests/auto/qtquick2/qquicklistview/data/moveTransitions.qml create mode 100644 tests/auto/qtquick2/qquicklistview/data/multipleTransitions.qml create mode 100644 tests/auto/qtquick2/qquicklistview/data/populateTransitions.qml create mode 100644 tests/auto/qtquick2/qquicklistview/data/removeTransitions.qml diff --git a/doc/src/images/viewtransitions-basic.gif b/doc/src/images/viewtransitions-basic.gif new file mode 100644 index 0000000000000000000000000000000000000000..b2a6a618c0f826e323983baa771d016ad256583a GIT binary patch literal 49932 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 a)N}v;-5?Mh@Bx9rD7yXhrhoG{IsPANqrcAp literal 0 HcmV?d00001 diff --git a/doc/src/images/viewtransitions-delayedbyindex.gif b/doc/src/images/viewtransitions-delayedbyindex.gif new file mode 100644 index 0000000000000000000000000000000000000000..4ece2a2ffbb9a1f181fd978bcb3f2831817407a8 GIT binary patch literal 69623 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�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 L=l|e;vhV)@pX3P- literal 0 HcmV?d00001 diff --git a/doc/src/images/viewtransitions-intermediatemove.gif b/doc/src/images/viewtransitions-intermediatemove.gif new file mode 100644 index 0000000000000000000000000000000000000000..e826183b19a24de9c646ab54d1e2e6b4b61d7383 GIT binary patch literal 109530 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%0Dl>$BO9&k$4lxES2yyJi}d|s6wo(ktw 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 literal 0 HcmV?d00001 diff --git a/doc/src/images/viewtransitions-scriptactionbad.gif b/doc/src/images/viewtransitions-scriptactionbad.gif new file mode 100644 index 0000000000000000000000000000000000000000..9e618d911cd3b5427b29b68ee1a9dbce38f1ab9f GIT binary patch literal 49200 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

EgvOuc~`a-osO+lX+gs57z*Er(NPmYdXRr^ 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 I_&-_uA5H|{3jhEB literal 0 HcmV?d00001 diff --git a/doc/src/snippets/declarative/viewtransitions/viewtransitions-basic.qml b/doc/src/snippets/declarative/viewtransitions/viewtransitions-basic.qml new file mode 100644 index 0000000..8a05491 --- /dev/null +++ b/doc/src/snippets/declarative/viewtransitions/viewtransitions-basic.qml @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** 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$ +** +****************************************************************************/ + +import QtQuick 2.0 + +//! [0] +ListView { + width: 240; height: 320 + model: ListModel {} + + delegate: Rectangle { + width: 100; height: 30 + border.width: 1 + color: "lightsteelblue" + Text { + anchors.centerIn: parent + text: name + } + } + + add: Transition { + NumberAnimation { property: "opacity"; from: 0; to: 1.0; duration: 400 } + NumberAnimation { property: "scale"; from: 0; to: 1.0; duration: 400 } + } + + addDisplaced: Transition { + NumberAnimation { properties: "x,y"; duration: 400; easing.type: Easing.OutBounce } + } + + focus: true + Keys.onSpacePressed: model.insert(0, { "name": "Item " + model.count }) +} +//! [0] diff --git a/doc/src/snippets/declarative/viewtransitions/viewtransitions-delayedbyindex.qml b/doc/src/snippets/declarative/viewtransitions/viewtransitions-delayedbyindex.qml new file mode 100644 index 0000000..79d00d2 --- /dev/null +++ b/doc/src/snippets/declarative/viewtransitions/viewtransitions-delayedbyindex.qml @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** 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$ +** +****************************************************************************/ + +import QtQuick 2.0 + +ListView { + width: 240; height: 320 + model: ListModel {} + + delegate: Rectangle { + width: 100; height: 30 + border.width: 1 + color: "lightsteelblue" + Text { + anchors.centerIn: parent + text: name + } + } + + add: Transition { + NumberAnimation { property: "opacity"; from: 0; to: 1.0; duration: 400 } + NumberAnimation { property: "scale"; from: 0; to: 1.0; duration: 400 } + } + +//! [0] + addDisplaced: Transition { + id: addDispTrans + SequentialAnimation { + PauseAnimation { + duration: (addDispTrans.ViewTransition.index - + addDispTrans.ViewTransition.targetIndexes[0]) * 100 + } + NumberAnimation { properties: "x,y"; duration: 400; easing.type: Easing.OutBounce } + } + } +//! [0] + + focus: true + Keys.onSpacePressed: model.insert(0, { "name": "Item " + model.count }) +} + diff --git a/doc/src/snippets/declarative/viewtransitions/viewtransitions-intermediatemove.qml b/doc/src/snippets/declarative/viewtransitions/viewtransitions-intermediatemove.qml new file mode 100644 index 0000000..a43d3a8 --- /dev/null +++ b/doc/src/snippets/declarative/viewtransitions/viewtransitions-intermediatemove.qml @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** 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$ +** +****************************************************************************/ + +import QtQuick 2.0 + +ListView { + width: 240; height: 320 + model: ListModel {} + + delegate: Rectangle { + width: 100; height: 30 + border.width: 1 + color: "lightsteelblue" + Text { + anchors.centerIn: parent + text: name + } + } + + add: Transition { + NumberAnimation { property: "opacity"; from: 0; to: 1.0; duration: 400 } + NumberAnimation { property: "scale"; from: 0; to: 1.0; duration: 400 } + } + +//! [0] + addDisplaced: Transition { + id: addDispTrans + SequentialAnimation { + PauseAnimation { + duration: (addDispTrans.ViewTransition.index - + addDispTrans.ViewTransition.targetIndexes[0]) * 100 + } + ParallelAnimation { + NumberAnimation { + property: "x"; to: addDispTrans.ViewTransition.item.x + 20 + easing.type: Easing.OutQuad + } + NumberAnimation { + property: "y"; to: addDispTrans.ViewTransition.item.y + 50 + easing.type: Easing.OutQuad + } + } + NumberAnimation { properties: "x,y"; duration: 500; easing.type: Easing.OutBounce } + } + } + +//! [0] + + focus: true + Keys.onSpacePressed: model.insert(0, { "name": "Item " + model.count }) +} + + diff --git a/doc/src/snippets/declarative/viewtransitions/viewtransitions-interruptedgood.qml b/doc/src/snippets/declarative/viewtransitions/viewtransitions-interruptedgood.qml new file mode 100644 index 0000000..1355268 --- /dev/null +++ b/doc/src/snippets/declarative/viewtransitions/viewtransitions-interruptedgood.qml @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** 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$ +** +****************************************************************************/ + +import QtQuick 2.0 + +ListView { + width: 240; height: 320 + model: ListModel {} + + delegate: Rectangle { + width: 100; height: 30 + border.width: 1 + color: "lightsteelblue" + Text { + anchors.centerIn: parent + text: name + } + } + + add: Transition { + NumberAnimation { property: "opacity"; from: 0; to: 1.0; duration: 400 } + NumberAnimation { property: "scale"; from: 0; to: 1.0; duration: 400 } + } + +//! [0] + addDisplaced: Transition { + NumberAnimation { properties: "x,y"; duration: 400; easing.type: Easing.OutBounce } + + // ensure opacity and scale values return to 1.0 + NumberAnimation { property: "opacity"; to: 1.0 } + NumberAnimation { property: "scale"; to: 1.0 } + } +//! [0] + + focus: true + Keys.onSpacePressed: model.insert(0, { "name": "Item " + model.count }) +} diff --git a/doc/src/snippets/declarative/viewtransitions/viewtransitions-pathanim.qml b/doc/src/snippets/declarative/viewtransitions/viewtransitions-pathanim.qml new file mode 100644 index 0000000..3d075c4 --- /dev/null +++ b/doc/src/snippets/declarative/viewtransitions/viewtransitions-pathanim.qml @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** 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$ +** +****************************************************************************/ + +import QtQuick 2.0 + +ListView { + width: 240; height: 320 + model: ListModel {} + + delegate: Rectangle { + width: 100; height: 30 + border.width: 1 + color: "lightsteelblue" + Text { + anchors.centerIn: parent + text: name + } + } + +//! [0] + add: Transition { + id: addTrans + NumberAnimation { property: "opacity"; from: 0; to: 1.0; duration: 400 } + NumberAnimation { property: "scale"; from: 0; to: 1.0; duration: 400 } + + PathAnimation { + duration: 1000 + path: Path { + startX: addTrans.ViewTransition.destination.x + 200 + startY: addTrans.ViewTransition.destination.y + 200 + PathCurve { relativeX: -100; relativeY: -50 } + PathCurve { relativeX: 50; relativeY: -150 } + PathCurve { + x: addTrans.ViewTransition.destination.x + y: addTrans.ViewTransition.destination.y + } + } + } + } +//! [0] + + addDisplaced: Transition { + id: addDispTrans + SequentialAnimation { + PauseAnimation { + duration: (addDispTrans.ViewTransition.index - + addDispTrans.ViewTransition.targetIndexes[0]) * 100 + } + ParallelAnimation { + NumberAnimation { + property: "x"; to: addDispTrans.ViewTransition.item.x + 20 + easing.type: Easing.OutQuad + } + NumberAnimation { + property: "y"; to: addDispTrans.ViewTransition.item.y + 50 + easing.type: Easing.OutQuad + } + } + NumberAnimation { properties: "x,y"; duration: 500; easing.type: Easing.OutBounce } + } + } + + focus: true + Keys.onSpacePressed: model.insert(0, { "name": "Item " + model.count }) +} + + + diff --git a/doc/src/snippets/declarative/viewtransitions/viewtransitions-scriptactionbad.qml b/doc/src/snippets/declarative/viewtransitions/viewtransitions-scriptactionbad.qml new file mode 100644 index 0000000..0334835 --- /dev/null +++ b/doc/src/snippets/declarative/viewtransitions/viewtransitions-scriptactionbad.qml @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** 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$ +** +****************************************************************************/ + +import QtQuick 2.0 + +//! [0] +ListView { + width: 240; height: 320 + model: ListModel { + Component.onCompleted: { + for (var i=0; i<8; i++) + append({"name": i}) + } + } + + delegate: Rectangle { + width: 100; height: 30 + border.width: 1 + color: "lightsteelblue" + Text { + anchors.centerIn: parent + text: name + } + objectName: name + } + + move: Transition { + id: moveTrans + SequentialAnimation { + ColorAnimation { property: "color"; to: "yellow"; duration: 400 } + NumberAnimation { properties: "x,y"; duration: 800; easing.type: Easing.OutBack } + ScriptAction { script: moveTrans.ViewTransition.item.color = "lightsteelblue" } + } + } + + moveDisplaced: Transition { + NumberAnimation { properties: "x,y"; duration: 400; easing.type: Easing.OutBounce } + } + + focus: true + Keys.onSpacePressed: model.move(5, 1, 3) +} +//! [0] + diff --git a/doc/src/snippets/declarative/viewtransitions/viewtransitions-scriptactiongood.qml b/doc/src/snippets/declarative/viewtransitions/viewtransitions-scriptactiongood.qml new file mode 100644 index 0000000..eda5c35 --- /dev/null +++ b/doc/src/snippets/declarative/viewtransitions/viewtransitions-scriptactiongood.qml @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** 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$ +** +****************************************************************************/ + +import QtQuick 2.0 + +ListView { + width: 240; height: 320 + model: ListModel { + Component.onCompleted: { + for (var i=0; i<8; i++) + append({"name": i}) + } + } + + delegate: Rectangle { + width: 100; height: 30 + border.width: 1 + color: "lightsteelblue" + Text { + anchors.centerIn: parent + text: name + } + objectName: name + } + +//! [0] + move: Transition { + id: moveTrans + SequentialAnimation { + ColorAnimation { property: "color"; to: "yellow"; duration: 400 } + NumberAnimation { properties: "x,y"; duration: 800; easing.type: Easing.OutBack } + //ScriptAction { script: moveTrans.ViewTransition.item.color = "lightsteelblue" } BAD! + + PropertyAction { property: "color"; value: "lightsteelblue" } + } + } +//! [0] + + moveDisplaced: Transition { + NumberAnimation { properties: "x,y"; duration: 400; easing.type: Easing.OutBounce } + } + + focus: true + Keys.onSpacePressed: model.move(5, 1, 3) +} + + diff --git a/doc/src/whatsnew.qdoc b/doc/src/whatsnew.qdoc index c7baa26..34dfe21 100644 --- a/doc/src/whatsnew.qdoc +++ b/doc/src/whatsnew.qdoc @@ -134,7 +134,10 @@ a y parameter. PathView now has a \c currentItem property ListView and GridView: - - now have headerItem and footerItem properties (the instantiated header and footer items). + - Can now apply specified transitions whenever items are added, removed or moved in a view. + See the documentation for ViewTransition and ListView.add, ListView.addDisplaced, + GridView.add, GridView.addDisplaced etc. for details. + - These now have headerItem and footerItem properties (the instantiated header and footer items). - In RightToLeft layout the preferredHighlightBegin/End are now also reversed. ListView section.labelPositioning property added to allow keeping the current section label diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp index 522c09a..39c7eab 100644 --- a/src/quick/items/qquickgridview.cpp +++ b/src/quick/items/qquickgridview.cpp @@ -92,9 +92,9 @@ public: qreal rowPos() const { if (view->flow() == QQuickGridView::LeftToRight) - return item->y(); + return itemY(); else - return (view->effectiveLayoutDirection() == Qt::RightToLeft ? -view->cellWidth()-item->x() : item->x()); + return (view->effectiveLayoutDirection() == Qt::RightToLeft ? -view->cellWidth()-itemX() : itemX()); } qreal colPos() const { @@ -102,45 +102,53 @@ public: if (view->effectiveLayoutDirection() == Qt::RightToLeft) { qreal colSize = view->cellWidth(); int columns = view->width()/colSize; - return colSize * (columns-1) - item->x(); + return colSize * (columns-1) - itemX(); } else { - return item->x(); + return itemX(); } } else { - return item->y(); + return itemY(); } } qreal endRowPos() const { if (view->flow() == QQuickGridView::LeftToRight) { - return item->y() + view->cellHeight(); + return itemY() + view->cellHeight(); } else { if (view->effectiveLayoutDirection() == Qt::RightToLeft) - return -item->x(); + return -itemX(); else - return item->x() + view->cellWidth(); + return itemX() + view->cellWidth(); } } void setPosition(qreal col, qreal row) { + moveTo(pointForPosition(col, row)); + } + bool contains(qreal x, qreal y) const { + return (x >= itemX() && x < itemX() + view->cellWidth() && + y >= itemY() && y < itemY() + view->cellHeight()); + } + QQuickItemView *itemView() const { + return view; + } + + QQuickGridView *view; + +private: + QPointF pointForPosition(qreal col, qreal row) const { if (view->effectiveLayoutDirection() == Qt::RightToLeft) { if (view->flow() == QQuickGridView::LeftToRight) { int columns = view->width()/view->cellWidth(); - item->setPos(QPointF((view->cellWidth() * (columns-1) - col), row)); + return QPointF(view->cellWidth() * (columns-1) - col, row); } else { - item->setPos(QPointF(-view->cellWidth()-row, col)); + return QPointF(-view->cellWidth() - row, col); } } else { if (view->flow() == QQuickGridView::LeftToRight) - item->setPos(QPointF(col, row)); + return QPointF(col, row); else - item->setPos(QPointF(row, col)); + return QPointF(row, col); } } - bool contains(qreal x, qreal y) const { - return (x >= item->x() && x < item->x() + view->cellWidth() && - y >= item->y() && y < item->y() + view->cellHeight()); - } - - QQuickGridView *view; }; //---------------------------------------------------------------------------- @@ -173,6 +181,8 @@ public: virtual bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo); virtual FxViewItem *newViewItem(int index, QQuickItem *item); + virtual void initializeViewItem(FxViewItem *item); + virtual void repositionItemAt(FxViewItem *item, int index, qreal sizeBuffer); virtual void repositionPackageItemAt(QQuickItem *item, int index); virtual void resetFirstItemPosition(qreal pos = 0.0); virtual void adjustFirstItem(qreal forwards, qreal backwards, int changeBeforeVisible); @@ -183,7 +193,8 @@ public: virtual void setPosition(qreal pos); virtual void layoutVisibleItems(int fromModelIndex = 0); - virtual bool applyInsertionChange(const QDeclarativeChangeSet::Insert &insert, ChangeResult *changeResult, QList *addedItems); + virtual bool applyInsertionChange(const QDeclarativeChangeSet::Insert &insert, ChangeResult *changeResult, QList *addedItems, QList *movingIntoView); + virtual void translateAndTransitionItemsAfter(int afterModelIndex, const ChangeResult &insertionResult, const ChangeResult &removalResult); virtual bool needsRefillForAddedOrRemovedIndex(int index) const; virtual qreal headerSize() const; @@ -309,8 +320,11 @@ qreal QQuickGridViewPrivate::colPosAt(int modelIndex) const col = (columns - count + col) % columns; return col * colSize(); } else { - int count = columns - 1 - (modelIndex - visibleItems.last()->index - 1) % columns; - return static_cast(visibleItems.last())->colPos() - count * colSize(); + FxGridItemSG *lastItem = static_cast(visibleItems.last()); + int count = modelIndex - lastItem->index; + int col = lastItem->colPos() / colSize(); + col = (col + count) % columns; + return col * colSize(); } } return (modelIndex % columns) * colSize(); @@ -415,6 +429,15 @@ FxViewItem *QQuickGridViewPrivate::newViewItem(int modelIndex, QQuickItem *item) return new FxGridItemSG(item, q, false); } +void QQuickGridViewPrivate::initializeViewItem(FxViewItem *item) +{ + QQuickItemViewPrivate::initializeViewItem(item); + + // need to track current items that are animating + QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item->item); + itemPrivate->addItemChangeListener(this, QQuickItemPrivate::Geometry); +} + bool QQuickGridViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, bool doBuffer) { qreal colPos = colPosAt(visibleIndex); @@ -462,7 +485,8 @@ bool QQuickGridViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, bool d #endif if (!(item = static_cast(createItem(modelIndex, doBuffer)))) break; - item->setPosition(colPos, rowPos); + if (!(usePopulateTransition && populateTransition)) // pos will be set by layoutVisibleItems() + item->setPosition(colPos, rowPos); item->item->setVisible(!doBuffer); visibleItems.append(item); if (++colNum >= columns) { @@ -499,7 +523,8 @@ bool QQuickGridViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, bool d if (!(item = static_cast(createItem(visibleIndex-1, doBuffer)))) break; --visibleIndex; - item->setPosition(colPos, rowPos); + if (!(usePopulateTransition && populateTransition)) // pos will be set by layoutVisibleItems() + item->setPosition(colPos, rowPos); item->item->setVisible(!doBuffer); visibleItems.prepend(item); if (--colNum < 0) { @@ -529,7 +554,15 @@ bool QQuickGridViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal buffer if (item->index != -1) visibleIndex++; visibleItems.removeFirst(); - releaseItem(item); + if (item->transitionScheduledOrRunning()) { +#ifdef DEBUG_DELEGATE_LIFECYCLE + qDebug() << "\tnot releasing animating item:" << item->index << item->item->objectName(); +#endif + item->releaseAfterTransition = true; + releasePendingTransition.append(item); + } else { + releaseItem(item); + } changed = true; } while (visibleItems.count() > 1 @@ -541,7 +574,15 @@ bool QQuickGridViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal buffer qDebug() << "refill: remove last" << visibleIndex+visibleItems.count()-1; #endif visibleItems.removeLast(); - releaseItem(item); + if (item->transitionScheduledOrRunning()) { +#ifdef DEBUG_DELEGATE_LIFECYCLE + qDebug() << "\tnot releasing animating item:" << item->index << item->item->objectName(); +#endif + item->releaseAfterTransition = true; + releasePendingTransition.append(item); + } else { + releaseItem(item); + } changed = true; } @@ -567,7 +608,7 @@ void QQuickGridViewPrivate::layoutVisibleItems(int fromModelIndex) if (colPos != col * colSize()) { colPos = col * colSize(); firstItem->setPosition(colPos, rowPos); - firstItem->item->setVisible(rowPos + rowSize() >= from && rowPos <= to); + firstItem->setVisible(firstItem->rowPos() + rowSize() >= from && firstItem->rowPos() <= to); } for (int i = 1; i < visibleItems.count(); ++i) { FxGridItemSG *item = static_cast(visibleItems.at(i)); @@ -578,12 +619,18 @@ void QQuickGridViewPrivate::layoutVisibleItems(int fromModelIndex) colPos = col * colSize(); if (item->index >= fromModelIndex) { item->setPosition(colPos, rowPos); - item->item->setVisible(rowPos + rowSize() >= from && rowPos <= to); + item->setVisible(item->rowPos() + rowSize() >= from && item->rowPos() <= to); } } } } +void QQuickGridViewPrivate::repositionItemAt(FxViewItem *item, int index, qreal sizeBuffer) +{ + int count = sizeBuffer / rowSize(); + static_cast(item)->setPosition(colPosAt(index + count), rowPosAt(index + count)); +} + void QQuickGridViewPrivate::repositionPackageItemAt(QQuickItem *item, int index) { Q_Q(QQuickGridView); @@ -668,8 +715,8 @@ void QQuickGridViewPrivate::updateHighlight() bool strictHighlight = haveHighlightRange && highlightRange == QQuickGridView::StrictlyEnforceRange; if (currentItem && autoHighlight && highlight && (!strictHighlight || !pressed)) { // auto-update highlight - highlightXAnimator->to = currentItem->item->x(); - highlightYAnimator->to = currentItem->item->y(); + highlightXAnimator->to = currentItem->itemX(); + highlightYAnimator->to = currentItem->itemY(); highlight->item->setWidth(currentItem->item->width()); highlight->item->setHeight(currentItem->item->height()); @@ -797,7 +844,11 @@ void QQuickGridViewPrivate::initializeCurrentItem() { if (currentItem && currentIndex >= 0) { FxGridItemSG *gridItem = static_cast(currentItem); - gridItem->setPosition(colPosAt(currentIndex), rowPosAt(currentIndex)); + FxViewItem *actualItem = visibleItem(currentIndex); + + // don't reposition the item if it's about to be transitioned to another position + if ((!actualItem || !actualItem->transitionScheduledOrRunning())) + gridItem->setPosition(colPosAt(currentIndex), rowPosAt(currentIndex)); } } @@ -1144,17 +1195,17 @@ void QQuickGridView::setHighlightFollowsCurrentItem(bool autoHighlight) /*! \qmlattachedproperty bool QtQuick2::GridView::delayRemove - This attached property holds whether the delegate may be destroyed. - - It is attached to each instance of the delegate. + This attached property holds whether the delegate may be destroyed. It + is attached to each instance of the delegate. The default value is false. It is sometimes necessary to delay the destruction of an item - until an animation completes. - - The example below ensures that the animation completes before - the item is removed from the grid. + until an animation completes. The example delegate below ensures that the + animation completes before the item is removed from the list. \snippet doc/src/snippets/declarative/gridview/gridview.qml delayRemove + + If a \l remove transition has been specified, it will not be applied until + delayRemove is returned to \c false. */ /*! @@ -1165,6 +1216,9 @@ void QQuickGridView::setHighlightFollowsCurrentItem(bool autoHighlight) /*! \qmlattachedsignal QtQuick2::GridView::onRemove() This attached handler is called immediately before an item is removed from the view. + + If a \l remove transition has been specified, it is applied after + this signal handler is called, providing that delayRemove is false. */ @@ -1530,6 +1584,228 @@ void QQuickGridView::setSnapMode(SnapMode mode) \sa footer, headerItem */ +/*! + \qmlproperty Transition QtQuick2::GridView::populate + This property holds the transition to apply to items that are initially created for a + view. + + This transition is applied to all the items that are created when: + + \list + \o The view is first created + \o The view's \l model changes + \o The view's \l model is \l {QAbstractItemModel::reset}{reset}, if the model is a QAbstractItemModel subclass + \endlist + + For example, here is a view that specifies such a transition: + + \code + GridView { + ... + populate: Transition { + NumberAnimation { properties: "x,y"; duration: 1000 } + } + } + \endcode + + When the view is initialized, the view will create all the necessary items for the view, + then animate them to their correct positions within the view over one second. + + For more details and examples on how to use view transitions, see the ViewTransition + documentation. + + \sa add, ViewTransition +*/ + +/*! + \qmlproperty Transition QtQuick2::GridView::add + This property holds the transition to apply to items that are added within the view. + + The transition is applied to items that have been added to the visible area of the view. For + example, here is a view that specifies such a transition: + + \code + GridView { + ... + add: Transition { + NumberAnimation { properties: "x,y"; from: 100; duration: 1000 } + } + } + \endcode + + Whenever an item is added to the above view, the item will be animated from the position (100,100) + to its final x,y position within the view, over one second. The transition only applies to + the new items that are added to the view; it does not apply to the items below that are + displaced by the addition of the new items. To animate the displaced items, set the \l + addDisplaced property. + + For more details and examples on how to use view transitions, see the ViewTransition + documentation. + + \note This transition is not applied to the items that are created when the view is initially + populated, or when the view's \l model changes. In those cases, the \l populate transition is + applied instead. + + \sa addDisplaced, populate, ViewTransition +*/ + +/*! + \qmlproperty Transition QtQuick2::GridView::addDisplaced + This property holds the transition to apply to items in the view that are displaced by other + items that have been added to the view. + + The transition is applied to items that are currently visible and have been displaced by newly + added items. For example, here is a view that specifies such a transition: + + \code + GridView { + ... + addDisplaced: Transition { + NumberAnimation { properties: "x,y"; duration: 1000 } + } + } + \endcode + + Whenever an item is added to the above view, all items beneath the new item are displaced, causing + them to move down (or sideways, if horizontally orientated) within the view. As this + displacement occurs, the items' movement to their new x,y positions within the view will be + animated by a NumberAnimation over one second, as specified. This transition is not applied to + the new item that has been added to the view; to animate the added items, set the \l add + property. + + For more details and examples on how to use view transitions, see the ViewTransition + documentation. + + \note This transition is not applied to the items that are created when the view is initially + populated, or when the view's \l model changes. In those cases, the \l populate transition is + applied instead. + + \sa add, populate, ViewTransition +*/ +/*! + \qmlproperty Transition QtQuick2::GridView::move + This property holds the transition to apply to items in the view that are moved by a move + operation. + + The transition is applied to items that are moving within the view or are moving + into the view as a result of a move operation in the view's model. For example: + + \code + GridView { + ... + move: Transition { + NumberAnimation { properties: "x,y"; duration: 1000 } + } + } + \endcode + + Whenever an item is moved within the above view, the item will be animated to its new position in + the view over one second. The transition only applies to the items that are the subject of the + move operation in the model; it does not apply to the items below them that are displaced by + the move operation. To animate the displaced items, set the \l moveDisplaced property. + + For more details and examples on how to use view transitions, see the ViewTransition + documentation. + + \sa moveDisplaced, ViewTransition +*/ + +/*! + \qmlproperty Transition QtQuick2::GridView::moveDisplaced + This property holds the transition to apply to items in the view that are displaced by a + move operation in the view. + + The transition is applied to items that are currently visible and have been displaced following + a move operation in the view's model. For example, here is a view that specifies such a transition: + + \code + GridView { + ... + moveDisplaced: Transition { + NumberAnimation { properties: "x,y"; duration: 1000 } + } + } + \endcode + + Whenever an item moves within (or moves into) the above view, all items beneath it are + displaced, causing them to move upwards (or sideways, if horizontally orientated) within the + view. As this displacement occurs, the items' movement to their new x,y positions within the + view will be animated by a NumberAnimation over one second, as specified. This transition is + not applied to the item that are actually the subject of the move operation; to animate the + moved items, set the \l move property. + + For more details and examples on how to use view transitions, see the ViewTransition + documentation. + + \sa move, ViewTransition +*/ + +/*! + \qmlproperty Transition QtQuick2::GridView::remove + This property holds the transition to apply to items that are removed from the view. + + The transition is applied to items that have been removed from the visible area of the view. For + example: + + \code + GridView { + ... + remove: Transition { + ParallelAnimation { + NumberAnimation { property: "opacity"; to: 0; duration: 1000 } + NumberAnimation { properties: "x,y"; to: 100; duration: 1000 } + } + } + } + \endcode + + Whenever an item is removed from the above view, the item will be animated to the position (100,100) + over one second, and in parallel will also change its opacity to 0. The transition + only applies to the items that are removed from the view; it does not apply to the items below + them that are displaced by the removal of the items. To animate the displaced items, set the \l + removeDisplaced property. + + Note that by the time the transition is applied, the item has already been removed from the + model; any references to the model data for the removed index will not be valid. + + Additionally, if the \l delayRemove attached property has been set for a delegate item, the + remove transition will not be applied until \l delayRemove becomes false again. + + For more details and examples on how to use view transitions, see the ViewTransition + documentation. + + \sa removeDisplaced, ViewTransition +*/ + +/*! + \qmlproperty Transition QtQuick2::GridView::removeDisplaced + This property holds the transition to apply to items in the view that are displaced by the + removal of other items in the view. + + The transition is applied to items that are currently visible and have been displaced by + the removal of items. For example, here is a view that specifies such a transition: + + \code + GridView { + ... + removeDisplaced: Transition { + NumberAnimation { properties: "x,y"; duration: 1000 } + } + } + \endcode + + Whenever an item is removed from the above view, all items beneath it are displaced, causing + them to move upwards (or sideways, if horizontally orientated) within the view. As this + displacement occurs, the items' movement to their new x,y positions within the view will be + animated by a NumberAnimation over one second, as specified. This transition is not applied to + the item that has actually been removed from the view; to animate the removed items, set the + \l remove property. + + For more details and examples on how to use view transitions, see the ViewTransition + documentation. + + \sa remove, ViewTransition +*/ void QQuickGridView::viewportMoved() { Q_D(QQuickGridView); @@ -1583,9 +1859,9 @@ void QQuickGridView::viewportMoved() d->updateCurrent(idx); if (d->currentItem && static_cast(d->currentItem)->colPos() != static_cast(d->highlight)->colPos() && d->autoHighlight) { if (d->flow == LeftToRight) - d->highlightXAnimator->to = d->currentItem->item->x(); + d->highlightXAnimator->to = d->currentItem->itemX(); else - d->highlightYAnimator->to = d->currentItem->item->y(); + d->highlightYAnimator->to = d->currentItem->itemY(); } } } @@ -1775,7 +2051,7 @@ void QQuickGridView::moveCurrentIndexRight() } } -bool QQuickGridViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::Insert &change, ChangeResult *insertResult, QList *addedItems) +bool QQuickGridViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::Insert &change, ChangeResult *insertResult, QList *addedItems, QList *movingIntoView) { Q_Q(QQuickGridView); @@ -1831,8 +2107,13 @@ bool QQuickGridViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::In // Update the indexes of the following visible items. for (int i = 0; i < visibleItems.count(); ++i) { FxViewItem *item = visibleItems.at(i); - if (item->index != -1 && item->index >= modelIndex) + if (item->index != -1 && item->index >= modelIndex) { item->index += count; + if (change.isMove()) + transitionNextReposition(item, FxViewItemTransitionManager::MoveTransition, false); + else + transitionNextReposition(item, FxViewItemTransitionManager::AddTransition, false); + } } int prevVisibleCount = visibleItems.count(); @@ -1845,7 +2126,7 @@ bool QQuickGridViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::In while (i >= 0) { if (rowPos > from && insertionIdx < visibleIndex) { // item won't be visible, just note the size for repositioning - insertResult->changeBeforeVisible++; + insertResult->countChangeBeforeVisible++; } else { // item is before first visible e.g. in cache buffer FxViewItem *item = 0; @@ -1858,8 +2139,12 @@ bool QQuickGridViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::In item->item->setVisible(true); visibleItems.insert(insertionIdx, item); - if (!change.isMove()) + if (insertionIdx == 0) + insertResult->changedFirstItem = true; + if (!change.isMove()) { addedItems->append(item); + transitionNextReposition(item, FxViewItemTransitionManager::AddTransition, true); + } insertResult->sizeChangesBeforeVisiblePos += rowSize(); } @@ -1878,6 +2163,7 @@ bool QQuickGridViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::In FxViewItem *item = 0; if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(modelIndex + i)))) item->index = modelIndex + i; + bool newItem = !item; if (!item) item = createItem(modelIndex + i); if (!item) @@ -1887,8 +2173,15 @@ bool QQuickGridViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::In visibleItems.insert(index, item); if (index == 0) insertResult->changedFirstItem = true; - if (!change.isMove()) + if (change.isMove()) { + // we know this is a move target, since move displaced items that are + // shuffled into view due to a move would be added in refill() + if (moveTransition && newItem) + movingIntoView->append(MovedItem(item, change.moveKey(item->index))); + } else { addedItems->append(item); + transitionNextReposition(item, FxViewItemTransitionManager::AddTransition, true); + } insertResult->sizeChangesAfterVisiblePos += rowSize(); if (++colNum >= columns) { @@ -1906,6 +2199,41 @@ bool QQuickGridViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::In return visibleItems.count() > prevVisibleCount; } +void QQuickGridViewPrivate::translateAndTransitionItemsAfter(int afterModelIndex, const ChangeResult &insertionResult, const ChangeResult &removalResult) +{ + int markerItemIndex = -1; + for (int i=0; iindex == afterModelIndex) { + markerItemIndex = i; + break; + } + } + if (markerItemIndex < 0) + return; + + const qreal viewEndPos = isContentFlowReversed() ? -position() : position() + size(); + int countItemsRemoved = -(removalResult.sizeChangesAfterVisiblePos / rowSize()); + + // account for whether first item has changed if < 1 row was removed before visible + int changeBeforeVisible = insertionResult.countChangeBeforeVisible - removalResult.countChangeBeforeVisible; + if (changeBeforeVisible != 0) + countItemsRemoved += (changeBeforeVisible % columns) - (columns - 1); + + countItemsRemoved -= removalResult.countChangeAfterVisibleItems; + + for (int i=markerItemIndex+1; iposition() < viewEndPos; i++) { + FxGridItemSG *gridItem = static_cast(visibleItems[i]); + if (!gridItem->transitionScheduledOrRunning()) { + qreal origRowPos = gridItem->colPos(); + qreal origColPos = gridItem->rowPos(); + int indexDiff = gridItem->index - countItemsRemoved; + gridItem->setPosition((indexDiff % columns) * colSize(), (indexDiff / columns) * rowSize()); + transitionNextReposition(gridItem, FxViewItemTransitionManager::RemoveTransition, false); + gridItem->setPosition(origRowPos, origColPos); + } + } +} + bool QQuickGridViewPrivate::needsRefillForAddedOrRemovedIndex(int modelIndex) const { // If we add or remove items before visible items, a layout may be diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp index 3d1e96d..a4cfa26 100644 --- a/src/quick/items/qquickitemsmodule.cpp +++ b/src/quick/items/qquickitemsmodule.cpp @@ -184,6 +184,7 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor) qmlRegisterUncreatableType(uri,major,minor,"KeyNavigation",QQuickKeyNavigationAttached::tr("KeyNavigation is only available via attached properties")); qmlRegisterUncreatableType(uri,major,minor,"Keys",QQuickKeysAttached::tr("Keys is only available via attached properties")); qmlRegisterUncreatableType(uri,major,minor,"LayoutMirroring", QQuickLayoutMirroringAttached::tr("LayoutMirroring is only available via attached properties")); + qmlRegisterUncreatableType(uri,major,minor,"ViewTransition",QQuickViewTransitionAttached::tr("ViewTransition is only available via attached properties")); qmlRegisterType(uri,major,minor,"PinchArea"); qmlRegisterType(uri,major,minor,"Pinch"); diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp index f09be2b..87a428a 100644 --- a/src/quick/items/qquickitemview.cpp +++ b/src/quick/items/qquickitemview.cpp @@ -40,17 +40,26 @@ ****************************************************************************/ #include "qquickitemview_p_p.h" +#include QT_BEGIN_NAMESPACE FxViewItem::FxViewItem(QQuickItem *i, bool own) - : item(i), ownItem(own), index(-1) + : item(i), ownItem(own), index(-1), releaseAfterTransition(false) + , transition(0) + , nextTransitionType(FxViewItemTransitionManager::NoTransition) + , isTransitionTarget(false) + , nextTransitionToSet(false) { } FxViewItem::~FxViewItem() { + if (transition) + transition->m_item = 0; + delete transition; + if (ownItem && item) { item->setParentItem(0); item->deleteLater(); @@ -58,6 +67,273 @@ FxViewItem::~FxViewItem() } } +qreal FxViewItem::itemX() const +{ + if (nextTransitionType != FxViewItemTransitionManager::NoTransition) + return nextTransitionToSet ? nextTransitionTo.x() : item->x(); + else if (transition && transition->isActive()) + return transition->m_toPos.x(); + else + return item->x(); +} + +qreal FxViewItem::itemY() const +{ + // If item is transitioning to some pos, return that dest pos. + // If item was redirected to some new pos before the current transition finished, + // return that new pos. + if (nextTransitionType != FxViewItemTransitionManager::NoTransition) + return nextTransitionToSet ? nextTransitionTo.y() : item->y(); + else if (transition && transition->isActive()) + return transition->m_toPos.y(); + else + return item->y(); +} + +void FxViewItem::setVisible(bool visible) +{ + if (!visible && transitionScheduledOrRunning()) + return; + item->setVisible(visible); +} + +void FxViewItem::setNextTransition(FxViewItemTransitionManager::TransitionType type, bool isTargetItem) +{ + // Don't reset nextTransitionToSet - once it is set, it cannot be changed + // until the animation finishes since the itemX() and itemY() may be used + // to calculate positions for transitions for other items in the view. + nextTransitionType = type; + isTransitionTarget = isTargetItem; +} + +bool FxViewItem::transitionScheduledOrRunning() const +{ + return (transition && transition->isActive()) + || nextTransitionType != FxViewItemTransitionManager::NoTransition; +} + +bool FxViewItem::prepareTransition(const QRectF &viewBounds) +{ + bool doTransition = false; + + switch (nextTransitionType) { + case FxViewItemTransitionManager::NoTransition: + { + return false; + } + case FxViewItemTransitionManager::PopulateTransition: + { + return true; + } + case FxViewItemTransitionManager::AddTransition: + case FxViewItemTransitionManager::RemoveTransition: + // For Add targets, do transition if item is moving into visible area + // For Remove targets, do transition if item is currently in visible area + if (isTransitionTarget) { + doTransition = (nextTransitionType == FxViewItemTransitionManager::AddTransition) + ? viewBounds.intersects(QRectF(nextTransitionTo.x(), nextTransitionTo.y(), item->width(), item->height())) + : viewBounds.intersects(QRectF(item->x(), item->y(), item->width(), item->height())); + if (!doTransition) + item->setPos(nextTransitionTo); + } else { + if (viewBounds.intersects(QRectF(item->x(), item->y(), item->width(), item->height())) + || viewBounds.intersects(QRectF(nextTransitionTo.x(), nextTransitionTo.y(), item->width(), item->height()))) { + doTransition = (nextTransitionTo != item->pos()); + } else { + item->setPos(nextTransitionTo); + } + } + break; + case FxViewItemTransitionManager::MoveTransition: + // do transition if moving from or into visible area + if (nextTransitionTo != item->pos()) { + doTransition = viewBounds.intersects(QRectF(item->x(), item->y(), item->width(), item->height())) + || viewBounds.intersects(QRectF(nextTransitionTo.x(), nextTransitionTo.y(), item->width(), item->height())); + if (!doTransition) + item->setPos(nextTransitionTo); + } + break; + } + + if (!doTransition) + resetTransitionData(); + return doTransition; +} + +void FxViewItem::startTransition() +{ + if (nextTransitionType == FxViewItemTransitionManager::NoTransition) + return; + + if (!transition || transition->m_type != nextTransitionType || transition->m_type != isTransitionTarget) { + delete transition; + transition = new FxViewItemTransitionManager; + } + + // if item is not already moving somewhere, set it to not move anywhere + // so that removed items do not move to the default (0,0) + if (!nextTransitionToSet) + moveTo(item->pos()); + + transition->startTransition(this, nextTransitionType, nextTransitionTo, isTransitionTarget); + nextTransitionType = FxViewItemTransitionManager::NoTransition; +} + +void FxViewItem::stopTransition() +{ + if (transition) { + transition->cancel(); + delete transition; + transition = 0; + } + resetTransitionData(); + finishedTransition(); +} + +void FxViewItem::finishedTransition() +{ + nextTransitionToSet = false; + nextTransitionTo = QPointF(); + + if (releaseAfterTransition) { + QQuickItemViewPrivate *vp = static_cast(QObjectPrivate::get(itemView())); + vp->releasePendingTransition.removeOne(this); + vp->releaseItem(this); + } +} + +void FxViewItem::resetTransitionData() +{ + nextTransitionType = FxViewItemTransitionManager::NoTransition; + isTransitionTarget = false; + nextTransitionTo = QPointF(); + nextTransitionToSet = false; +} + +bool FxViewItem::isPendingRemoval() const +{ + if (nextTransitionType == FxViewItemTransitionManager::RemoveTransition) + return isTransitionTarget; + if (transition && transition->isActive() && transition->m_type == FxViewItemTransitionManager::RemoveTransition) + return transition->m_isTarget; + return false; +} + +void FxViewItem::moveTo(const QPointF &pos) +{ + if (transitionScheduledOrRunning()) { + nextTransitionTo = pos; + nextTransitionToSet = true; + } else { + item->setPos(pos); + } +} + + +FxViewItemTransitionManager::FxViewItemTransitionManager() + : m_active(false), m_item(0), m_type(FxViewItemTransitionManager::NoTransition), m_isTarget(false) +{ +} + +FxViewItemTransitionManager::~FxViewItemTransitionManager() +{ +} + +bool FxViewItemTransitionManager::isActive() const +{ + return m_active; +} + +void FxViewItemTransitionManager::startTransition(FxViewItem *item, FxViewItemTransitionManager::TransitionType type, const QPointF &to, bool isTargetItem) +{ + if (!item) { + qWarning("startTransition(): invalid item"); + return; + } + + QQuickItemViewPrivate *vp = static_cast(QObjectPrivate::get(item->itemView())); + + QDeclarativeTransition *trans = 0; + switch (type) { + case NoTransition: + break; + case PopulateTransition: + trans = vp->populateTransition; + break; + case AddTransition: + trans = isTargetItem ? vp->addTransition : vp->addDisplacedTransition; + break; + case MoveTransition: + trans = isTargetItem ? vp->moveTransition : vp->moveDisplacedTransition; + break; + case RemoveTransition: + trans = isTargetItem ? vp->removeTransition : vp->removeDisplacedTransition; + break; + } + + if (!trans) { + qWarning("QQuickItemView: invalid view transition!"); + return; + } + + m_active = true; + m_item = item; + m_toPos = to; + m_type = type; + m_isTarget = isTargetItem; + + QQuickViewTransitionAttached *attached = + static_cast(qmlAttachedPropertiesObject(trans)); + if (attached) { + attached->m_index = item->index; + attached->m_item = item->item; + attached->m_destination = to; + switch (type) { + case NoTransition: + break; + case PopulateTransition: + case AddTransition: + attached->m_targetIndexes = vp->addTransitionIndexes; + attached->m_targetItems = vp->addTransitionTargets; + break; + case MoveTransition: + attached->m_targetIndexes = vp->moveTransitionIndexes; + attached->m_targetItems = vp->moveTransitionTargets; + break; + case RemoveTransition: + attached->m_targetIndexes = vp->removeTransitionIndexes; + attached->m_targetItems = vp->removeTransitionTargets; + break; + } + emit attached->indexChanged(); + emit attached->itemChanged(); + emit attached->destinationChanged(); + emit attached->targetIndexesChanged(); + emit attached->targetItemsChanged(); + } + + QDeclarativeStateOperation::ActionList actions; + actions << QDeclarativeAction(item->item, QLatin1String("x"), QVariant(to.x())); + actions << QDeclarativeAction(item->item, QLatin1String("y"), QVariant(to.y())); + + QDeclarativeTransitionManager::transition(actions, trans, item->item); +} + +void FxViewItemTransitionManager::finished() +{ + QDeclarativeTransitionManager::finished(); + + m_active = false; + + if (m_item) + m_item->finishedTransition(); + m_item = 0; + m_toPos.setX(0); + m_toPos.setY(0); + m_type = NoTransition; + m_isTarget = false; +} + QQuickItemViewChangeSet::QQuickItemViewChangeSet() : active(false) @@ -137,6 +413,364 @@ void QQuickItemViewChangeSet::reset() } +QQuickViewTransitionAttached::QQuickViewTransitionAttached(QObject *parent) + : QObject(parent), m_index(-1), m_item(0) +{ +} +/*! + \qmlclass ViewTransition QQuickViewTransitionAttached + \inqmlmodule QtQuick 2 + \ingroup qml-view-elements + \brief The ViewTransition attached property provides details on items under transition in a view. + + With ListView and GridView, it is possible to specify transitions that should be applied whenever + the items in the view change as a result of modifications to the view's model. They both have the + following properties that can be set to the appropriate transitions to be run for various + operations: + + \list + \o \c add and \c addDisplaced - the transitions to run when items are added to the view + \o \c remove and \c removeDisplaced - the transitions to run when items are removed from the view + \o \c move and \c moveDisplaced - the transitions to run when items are moved within the view + (i.e. as a result of a move operation in the model) + \o \c populate - the transition to run when a view is created, or when the model changes + \endlist + + Such view transitions additionally have access to a ViewTransition attached property that + provides details of the items that are under transition and the operation that triggered the + transition. Since view transitions are run once per item, these details can be used to customise + each transition for each individual item. + + The ViewTransition attached property provides the following properties specific to the item to + which the transition is applied: + + \list + \o ViewTransition.item - the item that is under transition + \o ViewTransition.index - the index of this item + \o ViewTransition.destination - the (x,y) point to which this item is moving for the relevant view operation + \endlist + + In addition, ViewTransition provides properties specific to the items which are the target + of the operation that triggered the transition: + + \list + \o ViewTransition.targetIndexes - the indexes of the target items + \o ViewTransition.targetItems - the target items themselves + \endlist + + View transitions can be written without referring to any of the attributes listed + above. These attributes merely provide extra details that are useful for customising view + transitions. + + Following is an introduction to view transitions and the ways in which the ViewTransition + attached property can be used to augment view transitions. + + + \section2 View transitions: a simple example + + Here is a basic example of the use of view transitions. The view below specifies transitions for + the \c add and \c addDisplaced properties, which will be run when items are added to the view: + + \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-basic.qml 0 + + When the space key is pressed, adding an item to the model, the new item will fade in and + increase in scale over 400 milliseconds as it is added to the view. Also, any item that is + displaced by the addition of a new item will animate to its new position in the view over + 400 milliseconds, as specified by the \c addDisplaced transition. + + If five items were inserted in succession at index 0, the effect would be this: + + \image viewtransitions-basic.gif + + Notice that the NumberAnimation objects above do not need to specify a \c target to animate + the appropriate item. Also, the NumberAnimation in the \c addTransition does not need to specify + the \c to value to move the item to its correct position in the view. This is because the view + implicitly sets the \c target and \c to values with the correct item and final item position + values if these properties are not explicitly defined. + + At its simplest, a view transition may just animate an item to its new position following a + view operation, just as the \c addDisplaced transition does above, or animate some item properties, + as in the \c add transition above. Additionally, a view transition may make use of the + ViewTransition attached property to customise animation behavior for different items. Following + are some examples of how this can be achieved. + + + \section2 Using the ViewTransition attached property + + As stated, the various ViewTransition properties provide details specific to the individual item + being transitioned as well as the operation that triggered the transition. In the animation above, + five items are inserted in succession at index 0. When the fifth and final insertion takes place, + adding "Item 4" to the view, the \c add transition is run once (for the inserted item) and the + \c addDisplaced transition is run four times (once for each of the four existing items in the view). + + At this point, if we examined the \c addDisplaced transition that was run for the bottom displaced + item ("Item 0"), the ViewTransition property values provided to this transition would be as follows: + + \table + \header + \o Property + \o Value + \o Explanation + \row + \o ViewTransition.item + \o "Item 0" delegate instance + \o The "Item 0" \l Rectangle object itself + \row + \o ViewTransition.index + \o \c int value of 4 + \o The index of "Item 0" within the model following the add operation + \row + \o ViewTransition.destination + \o \l point value of (0, 120) + \o The position that "Item 0" is moving to + \row + \o ViewTransition.targetIndexes + \o \c int array, just contains the integer "0" (zero) + \o The index of "Item 4", the new item added to the view + \row + \o ViewTransition.targetItems + \o object array, just contains the "Item 4" delegate instance + \o The "Item 4" \l Rectangle object - the new item added to the view + \endtable + + The ViewTransition.targetIndexes and ViewTransition.targetItems lists provide the items and + indexes of all delegate instances that are the targets of the relevant operation. For an add + operation, these are all the items that are added into the view; for a remove, these are all + the items removed from the view, and so on. (Note these lists will only contain references to + items that have been created within the view or its cached items; targets that are not within + the visible area of the view or within the item cache will not be accessible.) + + So, while the ViewTransition.item, ViewTransition.index and ViewTransition.destination values + vary for each individual transition that is run, the ViewTransition.targetIndexes and + ViewTransition.targetItems values are the same for every \c add and \c addDisplaced transition + that is triggered by a particular add operation. + + + \section3 Delaying animations based on index + + Since each view transition is run once for each item affected by the transition, the ViewTransition + properties can be used within a transition to define custom behavior for each item's transition. + For example, the ListView in the previous example could use this information to create a ripple-type + effect on the movement of the displaced items. + + This can be achieved by modifying the \c addDisplaced transition so that it delays the animation of + each displaced item based on the difference between its index (provided by ViewTransition.index) + and the first removed index (provided by ViewTransition.targetIndexes): + + \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-delayedbyindex.qml 0 + + Each displaced item delays its animation by an additional 100 milliseconds, producing a subtle + ripple-type effect when items are displaced by the add, like this: + + \image viewtransitions-delayedbyindex.gif + + + \section3 Animating items to intermediate positions + + The ViewTransition.item property gives a reference to the item to which the transition is being + applied. This can be used to access any of the item's attributes, custom \c property values, + and so on. + + Below is a modification of the \c addDisplaced transition from the previous example. It adds a + ParallelAnimation with nested NumberAnimation objects that reference ViewTransition.item to access + each item's \c x and \c y values at the start of their transitions. This allows each item to + animate to an intermediate position relative to its starting point for the transition, before + animating to its final position in the view: + + \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-intermediatemove.qml 0 + + Now, a displaced item will first move to a position of (20, 50) relative to its starting + position, and then to its final, correct position in the view: + + \image viewtransitions-intermediatemove.gif + + Since the final NumberAnimation does not specify a \c to value, the view implicitly sets this + value to the item's final position in the view, and so this last animation will move this item + to the correct place. If the transition requires the final position of the item for some calculation, + this is accessible through ViewTransition.destination. + + Instead of using multiple NumberAnimations, you could use a PathAnimation to animate an item over + a curved path. For example, the \c add transition in the previous example could be augmented with + a PathAnimation as follows: to animate newly added items along a path: + + \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-pathanim.qml 0 + + This animates newly added items along a path. Notice that each path is specified relative to + each item's final destination point, so that items inserted at different indexes start their + paths from different positions: + + \image viewtransitions-pathanim.gif + + + \section2 Handling interrupted animations + + A view transition may be interrupted at any time if a different view transition needs to be + applied while the original transition is in progress. For example, say Item A is inserted at index 0 + and undergoes an "add" transition; then, Item B is inserted at index 0 in quick succession before + Item A's transition has finished. Since Item B is inserted before Item A, it will displace Item + A, causing the view to interrupt Item A's "add" transition mid-way and start an "addDisplaced" + transition on Item A instead. + + For simple animations that simply animate an item's movement to its final destination, this + interruption is unlikely to require additional consideration. However, if a transition changes other + properties, this interruption may cause unwanted side effects. Consider the first example on this + page, repeated below for convenience: + + \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-basic.qml 0 + + If multiple items are added in rapid succession, without waiting for a previous transition + to finish, this is the result: + + \image viewtransitions-interruptedbad.gif + + Each newly added item undergoes an \c add transition, but before the transition can finish, + another item is added, displacing the previously added item. Because of this, the \c add + transition on the previously added item is interrupted and an \c addDisplaced transition is + started on the item instead. Due to the interruption, the \c opacity and \c scale animations + have not completed, thus producing items with opacity and scale that are below 1.0. + + To fix this, the \c addDisplaced transition should additionally ensure the item properties are + set to the end values specified in the \c add transition, effectively resetting these values + whenever an item is displaced. In this case, it means setting the item opacity and scale to 1.0: + + \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-interruptedgood.qml 0 + + Now, when an item's \c add transition is interrupted, its opacity and scale are animated to 1.0 + upon displacement, avoiding the erroneous visual effects from before: + + \image viewtransitions-interruptedgood.gif + + The same principle applies to any combination of view transitions. An added item may be moved + before its add transition finishes, or a moved item may be removed before its moved transition + finishes, and so on; so, the rule of thumb is that every transition should handle the same set of + properties. + + + \section2 Restrictions regarding ScriptAction + + When a view transition is initialized, any property bindings that refer to the ViewTransition + attached property are evaluated in preparation for the transition. Due to the nature of the + internal construction of a view transition, the attributes of the ViewTransition attached + property are only valid for the relevant item when the transition is initialized, and may not be + valid when the transition is actually run. + + Therefore, a ScriptAction within a view transition should not refer to the ViewTransition + attached property, as it may not refer to the expected values at the time that the ScriptAction + is actually invoked. Consider the following example: + + \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-scriptactionbad.qml 0 + + When the space key is pressed, three items are moved from index 5 to index 1. For each moved + item, the \c moveTransition sequence presumably animates the item's color to "yellow", then + animates it to its final position, then changes the item color back to "lightsteelblue" using a + ScriptAction. However, when run, the transition does not produce the intended result: + + \image viewtransitions-scriptactionbad.gif + + Only the last moved item is returned to the "lightsteelblue" color; the others remain yellow. This + is because the ScriptAction is not run until after the transition has already been initialized, by + which time the ViewTransition.item value has changed to refer to a different item; the item that + the script had intended to refer to is not the one held by ViewTransition.item at the time the + ScriptAction is actually invoked. + + In this instance, to avoid this issue, the view could set the property using a PropertyAction + instead: + + \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-scriptactiongood.qml 0 + + When the transition is initialized, the PropertyAction \c target will be set to the respective + ViewTransition.item for the transition and will later run with the correct item target as + expected. + */ + +/*! + \qmlattachedproperty list QtQuick2::ViewTransition::index + + This attached property holds the index of the item that is being + transitioned. + + Note that if the item is being moved, this property holds the index that + the item is moving to, not from. +*/ + +/*! + \qmlattachedproperty list QtQuick2::ViewTransition::item + + This attached property holds the the item that is being transitioned. + + \warning This item should not be kept and referred to outside of the transition + as it may become invalid as the view changes. +*/ + +/*! + \qmlattachedproperty list QtQuick2::ViewTransition::destination + + This attached property holds the final destination position for the transitioned + item within the view. + + This property value is a \l point with \c x and \c y properties. +*/ + +/*! + \qmlattachedproperty list QtQuick2::ViewTransition::targetIndexes + + This attached property holds a list of the indexes of the items in view + that are the target of the relevant operation. + + The targets are the items that are the subject of the operation. For + an add operation, these are the items being added; for a remove, these + are the items being removed; for a move, these are the items being + moved. + + For example, if the transition was triggered by an insert operation + that added two items at index 1 and 2, this targetIndexes list would + have the value [1,2]. + + \note The targetIndexes list only contains the indexes of items that are actually + in view, or will be in the view once the relevant operation completes. + + \sa QtQuick2::ViewTransition::targetIndexes +*/ + +/*! + \qmlattachedproperty list QtQuick2::ViewTransition::targetItems + + This attached property holds the list of items in view that are the + target of the relevant operation. + + The targets are the items that are the subject of the operation. For + an add operation, these are the items being added; for a remove, these + are the items being removed; for a move, these are the items being + moved. + + For example, if the transition was triggered by an insert operation + that added two items at index 1 and 2, this targetItems list would + contain these two items. + + \note The targetItems list only contains items that are actually + in view, or will be in the view once the relevant operation completes. + + \warning The objects in this list should not be kept and referred to + outside of the transition as the items may become invalid. The targetItems + are only valid when the Transition is initially created; this also means + they should not be used by ScriptAction objects in the Transition, which are + not evaluated until the transition is run. + + \sa QtQuick2::ViewTransition::targetIndexes +*/ +QDeclarativeListProperty QQuickViewTransitionAttached::targetItems() +{ + return QDeclarativeListProperty(this, m_targetItems); +} + +QQuickViewTransitionAttached *QQuickViewTransitionAttached::qmlAttachedProperties(QObject *obj) +{ + return new QQuickViewTransitionAttached(obj); +} + + +//----------------------------------- + QQuickItemView::QQuickItemView(QQuickFlickablePrivate &dd, QQuickItem *parent) : QQuickFlickable(dd, parent) { @@ -232,6 +866,12 @@ void QQuickItemView::setModel(const QVariant &model) d->moveReason = QQuickItemViewPrivate::Other; } d->updateViewport(); + + if (d->populateTransition) { + d->forceLayout = true; + d->usePopulateTransition = true; + polish(); + } } connect(d->model, SIGNAL(modelUpdated(QDeclarativeChangeSet,bool)), this, SLOT(modelUpdated(QDeclarativeChangeSet,bool))); @@ -585,6 +1225,111 @@ void QQuickItemView::setHighlightMoveDuration(int duration) } } +QDeclarativeTransition *QQuickItemView::populateTransition() const +{ + Q_D(const QQuickItemView); + return d->populateTransition; +} + +void QQuickItemView::setPopulateTransition(QDeclarativeTransition *transition) +{ + Q_D(QQuickItemView); + if (d->populateTransition != transition) { + d->populateTransition = transition; + emit populateTransitionChanged(); + } +} + +QDeclarativeTransition *QQuickItemView::addTransition() const +{ + Q_D(const QQuickItemView); + return d->addTransition; +} + +void QQuickItemView::setAddTransition(QDeclarativeTransition *transition) +{ + Q_D(QQuickItemView); + if (d->addTransition != transition) { + d->addTransition = transition; + emit addTransitionChanged(); + } +} + +QDeclarativeTransition *QQuickItemView::addDisplacedTransition() const +{ + Q_D(const QQuickItemView); + return d->addDisplacedTransition; +} + +void QQuickItemView::setAddDisplacedTransition(QDeclarativeTransition *transition) +{ + Q_D(QQuickItemView); + if (d->addDisplacedTransition != transition) { + d->addDisplacedTransition = transition; + emit addDisplacedTransitionChanged(); + } +} + +QDeclarativeTransition *QQuickItemView::moveTransition() const +{ + Q_D(const QQuickItemView); + return d->moveTransition; +} + +void QQuickItemView::setMoveTransition(QDeclarativeTransition *transition) +{ + Q_D(QQuickItemView); + if (d->moveTransition != transition) { + d->moveTransition = transition; + emit moveTransitionChanged(); + } +} + +QDeclarativeTransition *QQuickItemView::moveDisplacedTransition() const +{ + Q_D(const QQuickItemView); + return d->moveDisplacedTransition; +} + +void QQuickItemView::setMoveDisplacedTransition(QDeclarativeTransition *transition) +{ + Q_D(QQuickItemView); + if (d->moveDisplacedTransition != transition) { + d->moveDisplacedTransition = transition; + emit moveDisplacedTransitionChanged(); + } +} + +QDeclarativeTransition *QQuickItemView::removeTransition() const +{ + Q_D(const QQuickItemView); + return d->removeTransition; +} + +void QQuickItemView::setRemoveTransition(QDeclarativeTransition *transition) +{ + Q_D(QQuickItemView); + if (d->removeTransition != transition) { + d->removeTransition = transition; + emit removeTransitionChanged(); + } +} + +QDeclarativeTransition *QQuickItemView::removeDisplacedTransition() const +{ + Q_D(const QQuickItemView); + return d->removeDisplacedTransition; +} + +void QQuickItemView::setRemoveDisplacedTransition(QDeclarativeTransition *transition) +{ + Q_D(QQuickItemView); + if (d->removeDisplacedTransition != transition) { + d->removeDisplacedTransition = transition; + emit removeDisplacedTransitionChanged(); + } +} + void QQuickItemViewPrivate::positionViewAtIndex(int index, int mode) { Q_Q(QQuickItemView); @@ -719,6 +1464,64 @@ void QQuickItemViewPrivate::applyPendingChanges() layout(); } +bool QQuickItemViewPrivate::hasItemTransitions() const +{ + return populateTransition + || addTransition || addDisplacedTransition + || moveTransition || moveDisplacedTransition + || removeTransition || removeDisplacedTransition; +} + +void QQuickItemViewPrivate::transitionNextReposition(FxViewItem *item, FxViewItemTransitionManager::TransitionType type, bool isTarget) +{ + switch (type) { + case FxViewItemTransitionManager::NoTransition: + return; + case FxViewItemTransitionManager::PopulateTransition: + if (populateTransition) { + item->setNextTransition(FxViewItemTransitionManager::PopulateTransition, isTarget); + return; + } + break; + case FxViewItemTransitionManager::AddTransition: + if (!usePopulateTransition) { + if ((isTarget && addTransition) || (!isTarget && addDisplacedTransition)) { + item->setNextTransition(type, isTarget); + return; + } + } + break; + case FxViewItemTransitionManager::MoveTransition: + if ((isTarget && moveTransition) || (!isTarget && moveDisplacedTransition)) { + item->setNextTransition(type, isTarget); + return; + } + break; + case FxViewItemTransitionManager::RemoveTransition: + if ((isTarget && removeTransition) || (!isTarget && removeDisplacedTransition)) { + item->setNextTransition(type, isTarget); + return; + } + break; + } + + // the requested transition type is not valid, but the item is scheduled/in another + // transition, so cancel it to allow the item to move directly to the correct pos + if (item->transitionScheduledOrRunning()) + item->stopTransition(); +} + +int QQuickItemViewPrivate::findMoveKeyIndex(QDeclarativeChangeSet::MoveKey key, const QVector &changes) const +{ + for (int i=0; iindex + << visibleItems[i]->item->objectName() + << visibleItems[i]->position(); + } +} + void QQuickItemViewPrivate::itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) { Q_Q(QQuickItemView); @@ -752,8 +1566,19 @@ void QQuickItemViewPrivate::itemGeometryChanged(QQuickItem *item, const QRectF & fixupPosition(); } - if (currentItem && currentItem->item == item) + if (currentItem && currentItem->item == item) { + // don't allow item movement transitions to trigger a re-layout and + // start new transitions + bool prevDisableLayout = disableLayout; + if (!disableLayout) { + FxViewItem *actualItem = hasItemTransitions() ? visibleItem(currentIndex) : 0; + if (actualItem && actualItem->transition && actualItem->transition->isRunning()) + disableLayout = true; + } updateHighlight(); + disableLayout = prevDisableLayout; + } + if (trackedItem && trackedItem->item == item) q->trackedPositionChanged(); } @@ -765,8 +1590,15 @@ void QQuickItemView::destroyRemoved() it != d->visibleItems.end();) { FxViewItem *item = *it; if (item->index == -1 && item->attached->delayRemove() == false) { - d->releaseItem(item); - it = d->visibleItems.erase(it); + if (d->removeTransition) { + // don't remove from visibleItems until next layout() + d->runDelayedRemoveTransition = true; + QObject::disconnect(item->attached, SIGNAL(delayRemoveChanged()), this, SLOT(destroyRemoved())); + ++it; + } else { + d->releaseItem(item); + it = d->visibleItems.erase(it); + } } else { ++it; } @@ -782,6 +1614,7 @@ void QQuickItemView::modelUpdated(const QDeclarativeChangeSet &changeSet, bool r { Q_D(QQuickItemView); if (reset) { + d->usePopulateTransition = true; d->moveReason = QQuickItemViewPrivate::SetIndex; d->regenerate(); if (d->highlight && d->currentItem) { @@ -790,8 +1623,11 @@ void QQuickItemView::modelUpdated(const QDeclarativeChangeSet &changeSet, bool r d->updateTrackedItem(); } d->moveReason = QQuickItemViewPrivate::Other; - emit countChanged(); + if (d->populateTransition) { + d->forceLayout = true; + polish(); + } } else { d->currentChanges.prepare(d->currentIndex, d->itemCount); d->currentChanges.applyChanges(changeSet); @@ -1088,6 +1924,8 @@ void QQuickItemView::componentComplete() d->updateFooter(); d->updateViewport(); d->setPosition(d->contentStartOffset()); + d->usePopulateTransition = true; + if (d->isValid()) { d->refill(); d->moveReason = QQuickItemViewPrivate::SetIndex; @@ -1122,11 +1960,16 @@ QQuickItemViewPrivate::QQuickItemViewPrivate() , highlightRangeStart(0), highlightRangeEnd(0) , highlightMoveDuration(150) , headerComponent(0), header(0), footerComponent(0), footer(0) + , populateTransition(0) + , addTransition(0), addDisplacedTransition(0) + , moveTransition(0), moveDisplacedTransition(0) + , removeTransition(0), removeDisplacedTransition(0) , minExtent(0), maxExtent(0) , ownModel(false), wrap(false) - , inApplyModelChanges(false), inViewportMoved(false), forceLayout(false), currentIndexCleared(false) + , disableLayout(false), inViewportMoved(false), forceLayout(false), currentIndexCleared(false) , haveHighlightRange(false), autoHighlight(true), highlightRangeStartValid(false), highlightRangeEndValid(false) , fillCacheBuffer(false), inRequest(false), requestedAsync(false) + , usePopulateTransition(false), runDelayedRemoveTransition(false) { } @@ -1193,6 +2036,8 @@ FxViewItem *QQuickItemViewPrivate::visibleItem(int modelIndex) const { return 0; } +// should rename to firstItemInView() to avoid confusion with other "*visible*" methods +// that don't look at the view position and size FxViewItem *QQuickItemViewPrivate::firstVisibleItem() const { const qreal pos = isContentFlowReversed() ? -position()-size() : position(); for (int i = 0; i < visibleItems.count(); ++i) { @@ -1203,6 +2048,16 @@ FxViewItem *QQuickItemViewPrivate::firstVisibleItem() const { return visibleItems.count() ? visibleItems.first() : 0; } +int QQuickItemViewPrivate::findLastIndexInView() const +{ + const qreal viewEndPos = isContentFlowReversed() ? -position() : position() + size(); + for (int i=visibleItems.count() - 1; i>=0; i--) { + if (visibleItems.at(i)->position() <= viewEndPos && visibleItems.at(i)->index != -1) + return visibleItems.at(i)->index; + } + return -1; +} + // Map a model index to visibleItems list index. // These may differ if removed items are still present in the visible list, // e.g. doing a removal animation @@ -1284,6 +2139,12 @@ void QQuickItemViewPrivate::clear() visibleItems.clear(); visibleIndex = 0; + for (int i = 0; i < releasePendingTransition.count(); ++i) { + releasePendingTransition.at(i)->releaseAfterTransition = false; + releaseItem(releasePendingTransition.at(i)); + } + releasePendingTransition.clear(); + releaseItem(currentItem); currentItem = 0; createHighlight(); @@ -1382,16 +2243,26 @@ void QQuickItemViewPrivate::updateViewport() void QQuickItemViewPrivate::layout() { Q_Q(QQuickItemView); - if (inApplyModelChanges) + if (disableLayout) return; if (!isValid() && !visibleItems.count()) { clear(); setPosition(contentStartOffset()); + usePopulateTransition = false; return; } - if (!applyModelChanges() && !forceLayout) { + if (runDelayedRemoveTransition && removeDisplacedTransition) { + // assume that any items moving now are moving due to the remove - if they schedule + // a different transition, that will override this one anyway + for (int i=0; iisMoving() && !q->isFlicking()) { @@ -1416,20 +2291,49 @@ void QQuickItemViewPrivate::layout() updateFooter(); updateViewport(); updateUnrequestedPositions(); + + if (hasItemTransitions()) { + // items added in the last refill() may need to be transitioned in - e.g. a remove + // causes items to slide up into view + if (moveDisplacedTransition || removeDisplacedTransition) + translateAndTransitionItemsAfter(lastIndexInView, insertionPosChanges, removalPosChanges); + + prepareVisibleItemTransitions(); + + QRectF viewBounds(0, position(), q->width(), q->height()); + for (QList::Iterator it = releasePendingTransition.begin(); + it != releasePendingTransition.end(); ) { + FxViewItem *item = *it; + if ( (item->transition && item->transition->isActive()) + || prepareNonVisibleItemTransition(item, viewBounds)) { + ++it; + } else { + releaseItem(item); + it = releasePendingTransition.erase(it); + } + } + + for (int i=0; istartTransition(); + for (int i=0; istartTransition(); + } + usePopulateTransition = false; + runDelayedRemoveTransition = false; } -bool QQuickItemViewPrivate::applyModelChanges() +bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult, ChangeResult *totalRemovalResult) { Q_Q(QQuickItemView); - if (!q->isComponentComplete() || !currentChanges.hasPendingChanges() || inApplyModelChanges) + if (!q->isComponentComplete() || (!currentChanges.hasPendingChanges() && !runDelayedRemoveTransition) || disableLayout) return false; - inApplyModelChanges = true; + disableLayout = true; updateUnrequestedIndexes(); moveReason = QQuickItemViewPrivate::Other; - FxViewItem *prevVisibleItemsFirst = visibleItems.count() ? visibleItems.first() : 0; + FxViewItem *prevVisibleItemsFirst = visibleItems.count() ? *visibleItems.constBegin() : 0; int prevItemCount = itemCount; int prevVisibleItemsCount = visibleItems.count(); bool visibleAffected = false; @@ -1445,10 +2349,13 @@ bool QQuickItemViewPrivate::applyModelChanges() } qreal prevVisibleItemsFirstPos = visibleItems.count() ? visibleItems.first()->position() : 0.0; + totalInsertionResult->visiblePos = prevViewPos; + totalRemovalResult->visiblePos = prevViewPos; + const QVector &removals = currentChanges.pendingChanges.removes(); const QVector &insertions = currentChanges.pendingChanges.inserts(); - ChangeResult removalResult(prevViewPos); ChangeResult insertionResult(prevViewPos); + ChangeResult removalResult(prevViewPos); int removedCount = 0; for (int i=0; i= 0 && removals[i].index < prevFirstVisibleIndex) { if (removals[i].index + removals[i].count < prevFirstVisibleIndex) - removalResult.changeBeforeVisible -= removals[i].count; + removalResult.countChangeBeforeVisible += removals[i].count; else - removalResult.changeBeforeVisible -= (prevFirstVisibleIndex - removals[i].index); + removalResult.countChangeBeforeVisible += (prevFirstVisibleIndex - removals[i].index); } } + if (runDelayedRemoveTransition) { + QDeclarativeChangeSet::Remove removal; + for (QList::Iterator it = visibleItems.begin(); it != visibleItems.end();) { + FxViewItem *item = *it; + if (item->index == -1 && !item->attached->delayRemove()) { + removeItem(item, removal, &removalResult); + removedCount++; + it = visibleItems.erase(it); + } else { + ++it; + } + } + } + *totalRemovalResult += removalResult; if (!removals.isEmpty()) { updateVisibleIndex(); @@ -1475,31 +2396,50 @@ bool QQuickItemViewPrivate::applyModelChanges() } QList newItems; + QList movingIntoView; + for (int i=0; iattached->emitAdd(); + // for each item that was moved directly into the view as a result of a move(), + // find the index it was moved from in order to set its initial position, so that we + // can transition it from this "original" position to its new position in the view + if (moveTransition) { + for (int i=0; i= 0) { + if (prevFirstVisibleIndex >= 0 && fromIndex < prevFirstVisibleIndex) + repositionItemAt(movingIntoView[i].item, fromIndex, -totalInsertionResult->sizeChangesAfterVisiblePos); + else + repositionItemAt(movingIntoView[i].item, fromIndex, totalInsertionResult->sizeChangesAfterVisiblePos); + transitionNextReposition(movingIntoView[i].item, FxViewItemTransitionManager::MoveTransition, true); + } + } + } + // reposition visibleItems.first() correctly so that the content y doesn't jump if (removedCount != prevVisibleItemsCount) repositionFirstItem(prevVisibleItemsFirst, prevVisibleItemsFirstPos, prevFirstVisible, &insertionResult, &removalResult); // Whatever removed/moved items remain are no longer visible items. + prepareRemoveTransitions(¤tChanges.removedItems); for (QHash::Iterator it = currentChanges.removedItems.begin(); it != currentChanges.removedItems.end(); ++it) { releaseItem(it.value()); @@ -1526,7 +2466,7 @@ bool QQuickItemViewPrivate::applyModelChanges() if (!visibleAffected && viewportChanged) updateViewport(); - inApplyModelChanges = false; + disableLayout = false; return visibleAffected; } @@ -1535,6 +2475,13 @@ bool QQuickItemViewPrivate::applyRemovalChange(const QDeclarativeChangeSet::Remo Q_Q(QQuickItemView); bool visibleAffected = false; + if (visibleItems.count() && removal.index + removal.count > visibleItems.last()->index) { + if (removal.index > visibleItems.last()->index) + removeResult->countChangeAfterVisibleItems += removal.count; + else + removeResult->countChangeAfterVisibleItems += ((removal.index + removal.count - 1) - visibleItems.last()->index); + } + QList::Iterator it = visibleItems.begin(); while (it != visibleItems.end()) { FxViewItem *item = *it; @@ -1546,6 +2493,10 @@ bool QQuickItemViewPrivate::applyRemovalChange(const QDeclarativeChangeSet::Remo } else if (item->index >= removal.index + removal.count) { // after removed items item->index -= removal.count; + if (removal.isMove()) + transitionNextReposition(item, FxViewItemTransitionManager::MoveTransition, false); + else + transitionNextReposition(item, FxViewItemTransitionManager::RemoveTransition, false); ++it; } else { // removed item @@ -1558,21 +2509,9 @@ bool QQuickItemViewPrivate::applyRemovalChange(const QDeclarativeChangeSet::Remo QObject::connect(item->attached, SIGNAL(delayRemoveChanged()), q, SLOT(destroyRemoved()), Qt::QueuedConnection); ++it; } else { - if (removeResult->visiblePos.isValid()) { - if (item->position() < removeResult->visiblePos) - removeResult->sizeChangesBeforeVisiblePos += item->size(); - else - removeResult->sizeChangesAfterVisiblePos += item->size(); - } - if (removal.isMove()) { - currentChanges.removedItems.insert(removal.moveKey(item->index), item); - } else { - // track item so it is released later - currentChanges.removedItems.insertMulti(QDeclarativeChangeSet::MoveKey(), item); + removeItem(item, removal, removeResult); + if (!removal.isMove()) (*removedCount)++; - } - if (!removeResult->changedFirstItem && item == visibleItems.first()) - removeResult->changedFirstItem = true; it = visibleItems.erase(it); } } @@ -1581,6 +2520,25 @@ bool QQuickItemViewPrivate::applyRemovalChange(const QDeclarativeChangeSet::Remo return visibleAffected; } +void QQuickItemViewPrivate::removeItem(FxViewItem *item, const QDeclarativeChangeSet::Remove &removal, ChangeResult *removeResult) +{ + if (removeResult->visiblePos.isValid()) { + if (item->position() < removeResult->visiblePos) + removeResult->sizeChangesBeforeVisiblePos += item->size(); + else + removeResult->sizeChangesAfterVisiblePos += item->size(); + } + if (removal.isMove()) { + currentChanges.removedItems.insert(removal.moveKey(item->index), item); + transitionNextReposition(item, FxViewItemTransitionManager::MoveTransition, true); + } else { + // track item so it is released later + currentChanges.removedItems.insertMulti(QDeclarativeChangeSet::MoveKey(), item); + } + if (!removeResult->changedFirstItem && item == *visibleItems.constBegin()) + removeResult->changedFirstItem = true; +} + void QQuickItemViewPrivate::repositionFirstItem(FxViewItem *prevVisibleItemsFirst, qreal prevVisibleItemsFirstPos, FxViewItem *prevFirstVisible, @@ -1613,13 +2571,102 @@ void QQuickItemViewPrivate::repositionFirstItem(FxViewItem *prevVisibleItemsFirs moveForwardsBy = removalResult->sizeChangesBeforeVisiblePos; moveBackwardsBy = insertionResult->sizeChangesBeforeVisiblePos; } - adjustFirstItem(moveForwardsBy, moveBackwardsBy, insertionResult->changeBeforeVisible + removalResult->changeBeforeVisible); + adjustFirstItem(moveForwardsBy, moveBackwardsBy, insertionResult->countChangeBeforeVisible - removalResult->countChangeBeforeVisible); } insertionResult->reset(); removalResult->reset(); } } +void QQuickItemViewPrivate::prepareVisibleItemTransitions() +{ + Q_Q(QQuickItemView); + if (!hasItemTransitions()) + return; + + addTransitionIndexes.clear(); + addTransitionTargets.clear(); + moveTransitionIndexes.clear(); + moveTransitionTargets.clear(); + + QRectF viewBounds(0, position(), q->width(), q->height()); + for (int i=0; iprepareTransition(viewBounds)) + continue; + if (visibleItems[i]->isTransitionTarget) { + switch (visibleItems[i]->nextTransitionType) { + case FxViewItemTransitionManager::NoTransition: + break; + case FxViewItemTransitionManager::PopulateTransition: + case FxViewItemTransitionManager::AddTransition: + addTransitionIndexes.append(visibleItems[i]->index); + addTransitionTargets.append(visibleItems[i]->item); + break; + case FxViewItemTransitionManager::MoveTransition: + moveTransitionIndexes.append(visibleItems[i]->index); + moveTransitionTargets.append(visibleItems[i]->item); + break; + case FxViewItemTransitionManager::RemoveTransition: + // removed targets won't be in visibleItems, handle these + // in prepareNonVisibleItemTransition() + break; + } + } + } +} + +void QQuickItemViewPrivate::prepareRemoveTransitions(QHash *removedItems) +{ + if (!removeTransition && !removeDisplacedTransition) + return; + + removeTransitionIndexes.clear(); + removeTransitionTargets.clear(); + + if (removeTransition) { + for (QHash::Iterator it = removedItems->begin(); + it != removedItems->end(); ) { + bool isRemove = it.key().moveId < 0; + if (isRemove) { + FxViewItem *item = *it; + item->releaseAfterTransition = true; + releasePendingTransition.append(item); + transitionNextReposition(item, FxViewItemTransitionManager::RemoveTransition, true); + it = removedItems->erase(it); + } else { + ++it; + } + } + } +} + +bool QQuickItemViewPrivate::prepareNonVisibleItemTransition(FxViewItem *item, const QRectF &viewBounds) +{ + // Called for items that have been removed from visibleItems and may now be + // transitioned out of the view. This applies to items that are being directly + // removed, or moved to outside of the view, as well as those that are + // displaced to a position outside of the view due to an insert or move. + + if (item->nextTransitionType == FxViewItemTransitionManager::MoveTransition) + repositionItemAt(item, item->index, 0); + if (!item->prepareTransition(viewBounds)) + return false; + + if (item->isTransitionTarget) { + if (item->nextTransitionType == FxViewItemTransitionManager::MoveTransition) { + moveTransitionIndexes.append(item->index); + moveTransitionTargets.append(item->item); + } else if (item->nextTransitionType == FxViewItemTransitionManager::RemoveTransition) { + removeTransitionIndexes.append(item->index); + removeTransitionTargets.append(item->item); + } + } + + item->releaseAfterTransition = true; + return true; +} + /* This may return 0 if the item is being created asynchronously. When the item becomes available, refill() will be called and the item @@ -1628,6 +2675,7 @@ void QQuickItemViewPrivate::repositionFirstItem(FxViewItem *prevVisibleItemsFirs FxViewItem *QQuickItemViewPrivate::createItem(int modelIndex, bool asynchronous) { Q_Q(QQuickItemView); + if (requestedIndex == modelIndex && (asynchronous || requestedAsync == asynchronous)) return 0; @@ -1638,6 +2686,14 @@ FxViewItem *QQuickItemViewPrivate::createItem(int modelIndex, bool asynchronous) requestedItem = 0; } + for (int i=0; iindex == modelIndex + && !releasePendingTransition[i]->isPendingRemoval()) { + releasePendingTransition[i]->releaseAfterTransition = false; + return releasePendingTransition.takeAt(i); + } + } + requestedIndex = modelIndex; requestedAsync = asynchronous; inRequest = true; diff --git a/src/quick/items/qquickitemview_p.h b/src/quick/items/qquickitemview_p.h index e43f7c6..0d3cd1c 100644 --- a/src/quick/items/qquickitemview_p.h +++ b/src/quick/items/qquickitemview_p.h @@ -48,6 +48,8 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE +QT_MODULE(Declarative) + class QDeclarativeChangeSet; class QQuickItemViewPrivate; @@ -74,6 +76,14 @@ class Q_AUTOTEST_EXPORT QQuickItemView : public QQuickFlickable Q_PROPERTY(QDeclarativeComponent *footer READ footer WRITE setFooter NOTIFY footerChanged) Q_PROPERTY(QQuickItem *footerItem READ footerItem NOTIFY footerItemChanged) + Q_PROPERTY(QDeclarativeTransition *populate READ populateTransition WRITE setPopulateTransition NOTIFY populateTransitionChanged) + Q_PROPERTY(QDeclarativeTransition *add READ addTransition WRITE setAddTransition NOTIFY addTransitionChanged) + Q_PROPERTY(QDeclarativeTransition *addDisplaced READ addDisplacedTransition WRITE setAddDisplacedTransition NOTIFY addDisplacedTransitionChanged) + Q_PROPERTY(QDeclarativeTransition *move READ moveTransition WRITE setMoveTransition NOTIFY moveTransitionChanged) + Q_PROPERTY(QDeclarativeTransition *moveDisplaced READ moveDisplacedTransition WRITE setMoveDisplacedTransition NOTIFY moveDisplacedTransitionChanged) + Q_PROPERTY(QDeclarativeTransition *remove READ removeTransition WRITE setRemoveTransition NOTIFY removeTransitionChanged) + Q_PROPERTY(QDeclarativeTransition *removeDisplaced READ removeDisplacedTransition WRITE setRemoveDisplacedTransition NOTIFY removeDisplacedTransitionChanged) + Q_PROPERTY(QDeclarativeComponent *highlight READ highlight WRITE setHighlight NOTIFY highlightChanged) Q_PROPERTY(QQuickItem *highlightItem READ highlightItem NOTIFY highlightItemChanged) Q_PROPERTY(bool highlightFollowsCurrentItem READ highlightFollowsCurrentItem WRITE setHighlightFollowsCurrentItem NOTIFY highlightFollowsCurrentItemChanged) @@ -120,6 +130,27 @@ public: void setHeader(QDeclarativeComponent *); QQuickItem *headerItem() const; + QDeclarativeTransition *populateTransition() const; + void setPopulateTransition(QDeclarativeTransition *transition); + + QDeclarativeTransition *addTransition() const; + void setAddTransition(QDeclarativeTransition *transition); + + QDeclarativeTransition *addDisplacedTransition() const; + void setAddDisplacedTransition(QDeclarativeTransition *transition); + + QDeclarativeTransition *moveTransition() const; + void setMoveTransition(QDeclarativeTransition *transition); + + QDeclarativeTransition *moveDisplacedTransition() const; + void setMoveDisplacedTransition(QDeclarativeTransition *transition); + + QDeclarativeTransition *removeTransition() const; + void setRemoveTransition(QDeclarativeTransition *transition); + + QDeclarativeTransition *removeDisplacedTransition() const; + void setRemoveDisplacedTransition(QDeclarativeTransition *transition); + QDeclarativeComponent *highlight() const; void setHighlight(QDeclarativeComponent *); @@ -173,6 +204,14 @@ signals: void headerItemChanged(); void footerItemChanged(); + void populateTransitionChanged(); + void addTransitionChanged(); + void addDisplacedTransitionChanged(); + void moveTransitionChanged(); + void moveDisplacedTransitionChanged(); + void removeTransitionChanged(); + void removeDisplacedTransitionChanged(); + void highlightChanged(); void highlightItemChanged(); void highlightFollowsCurrentItemChanged(); @@ -200,8 +239,6 @@ protected slots: void animStopped(); void trackedPositionChanged(); - - private: Q_DECLARE_PRIVATE(QQuickItemView) }; @@ -287,8 +324,53 @@ public: QString m_nextSection; }; +class QQuickViewTransitionAttached : public QObject +{ + Q_OBJECT + + Q_PROPERTY(int index READ index NOTIFY indexChanged) + Q_PROPERTY(QQuickItem* item READ item NOTIFY itemChanged) + Q_PROPERTY(QPointF destination READ destination NOTIFY destinationChanged) + + Q_PROPERTY(QList targetIndexes READ targetIndexes NOTIFY targetIndexesChanged) + Q_PROPERTY(QDeclarativeListProperty targetItems READ targetItems NOTIFY targetItemsChanged) + +public: + QQuickViewTransitionAttached(QObject *parent); + + int index() const { return m_index; } + QQuickItem *item() const { return m_item; } + QPointF destination() const { return m_destination; } + + QList targetIndexes() const { return m_targetIndexes; } + QDeclarativeListProperty targetItems(); + + static QQuickViewTransitionAttached *qmlAttachedProperties(QObject *); + +signals: + void indexChanged(); + void itemChanged(); + void destinationChanged(); + + void targetIndexesChanged(); + void targetItemsChanged(); + +private: + friend class FxViewItemTransitionManager; + int m_index; + QQuickItem *m_item; + QPointF m_destination; + + QList m_targetIndexes; + QList m_targetItems; +}; + QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickViewTransitionAttached) +QML_DECLARE_TYPEINFO(QQuickViewTransitionAttached, QML_HAS_ATTACHED_PROPERTIES) + QT_END_HEADER #endif // QQUICKITEMVIEW_P_H diff --git a/src/quick/items/qquickitemview_p_p.h b/src/quick/items/qquickitemview_p_p.h index f191f06..6768149 100644 --- a/src/quick/items/qquickitemview_p_p.h +++ b/src/quick/items/qquickitemview_p_p.h @@ -45,6 +45,8 @@ #include "qquickitemview_p.h" #include "qquickflickable_p_p.h" #include "qquickvisualdatamodel_p.h" +#include "qquickvisualitemmodel_p.h" +#include #include @@ -52,12 +54,58 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE +QT_MODULE(Declarative) + + +class FxViewItem; +class FxViewItemTransitionManager : public QDeclarativeTransitionManager +{ +public: + enum TransitionType { + NoTransition, + PopulateTransition, + AddTransition, + MoveTransition, + RemoveTransition + }; + + FxViewItemTransitionManager(); + ~FxViewItemTransitionManager(); + + bool isActive() const; + void startTransition(FxViewItem *item, FxViewItemTransitionManager::TransitionType type, const QPointF &to, bool isTargetItem); + + bool m_active; + FxViewItem *m_item; + QPointF m_toPos; + FxViewItemTransitionManager::TransitionType m_type; + bool m_isTarget; + +protected: + virtual void finished(); +}; + + class FxViewItem { public: FxViewItem(QQuickItem *, bool own); virtual ~FxViewItem(); + qreal itemX() const; + qreal itemY() const; + + void setVisible(bool visible); + + void setNextTransition(FxViewItemTransitionManager::TransitionType, bool isTargetItem); + bool transitionScheduledOrRunning() const; + bool isPendingRemoval() const; + + bool prepareTransition(const QRectF &viewBounds); + void startTransition(); + void stopTransition(); + void finishedTransition(); + // these are positions and sizes along the current direction of scrolling/flicking virtual qreal position() const = 0; virtual qreal endPosition() const = 0; @@ -65,13 +113,26 @@ public: virtual qreal sectionSize() const = 0; virtual bool contains(qreal x, qreal y) const = 0; + virtual QQuickItemView *itemView() const = 0; QQuickItem *item; bool ownItem; int index; + bool releaseAfterTransition; QQuickItemViewAttached *attached; + + FxViewItemTransitionManager *transition; + QPointF nextTransitionTo; + FxViewItemTransitionManager::TransitionType nextTransitionType; + bool isTransitionTarget; + bool nextTransitionToSet; + +protected: + void moveTo(const QPointF &pos); + void resetTransitionData(); }; + class QQuickItemViewChangeSet { public: @@ -93,6 +154,7 @@ public: bool currentRemoved : 1; }; + class QQuickItemViewPrivate : public QQuickFlickablePrivate { Q_DECLARE_PUBLIC(QQuickItemView) @@ -101,20 +163,39 @@ public: struct ChangeResult { QDeclarativeNullableValue visiblePos; + bool changedFirstItem; qreal sizeChangesBeforeVisiblePos; qreal sizeChangesAfterVisiblePos; - bool changedFirstItem; - int changeBeforeVisible; + int countChangeBeforeVisible; + int countChangeAfterVisibleItems; + + ChangeResult() + : visiblePos(0), changedFirstItem(false), + sizeChangesBeforeVisiblePos(0), sizeChangesAfterVisiblePos(0), + countChangeBeforeVisible(0), countChangeAfterVisibleItems(0) {} ChangeResult(const QDeclarativeNullableValue &p) - : visiblePos(p), sizeChangesBeforeVisiblePos(0), sizeChangesAfterVisiblePos(0), - changedFirstItem(false), changeBeforeVisible(0) {} + : visiblePos(p), changedFirstItem(false), + sizeChangesBeforeVisiblePos(0), sizeChangesAfterVisiblePos(0), + countChangeBeforeVisible(0), countChangeAfterVisibleItems(0) {} + + ChangeResult &operator+=(const ChangeResult &other) { + if (&other == this) + return *this; + changedFirstItem &= other.changedFirstItem; + sizeChangesBeforeVisiblePos += other.sizeChangesBeforeVisiblePos; + sizeChangesAfterVisiblePos += other.sizeChangesAfterVisiblePos; + countChangeBeforeVisible += other.countChangeBeforeVisible; + countChangeAfterVisibleItems += other.countChangeAfterVisibleItems; + return *this; + } void reset() { + changedFirstItem = false; sizeChangesBeforeVisiblePos = 0.0; sizeChangesAfterVisiblePos = 0.0; - changedFirstItem = false; - changeBeforeVisible = 0; + countChangeBeforeVisible = 0; + countChangeAfterVisibleItems = 0; } }; @@ -130,6 +211,7 @@ public: int findLastVisibleIndex(int defaultValue = -1) const; FxViewItem *visibleItem(int modelIndex) const; FxViewItem *firstVisibleItem() const; + int findLastIndexInView() const; int mapFromModel(int modelIndex) const; virtual void init(); @@ -155,12 +237,22 @@ public: void updateVisibleIndex(); void positionViewAtIndex(int index, int mode); void applyPendingChanges(); - bool applyModelChanges(); + bool applyModelChanges(ChangeResult *insertionResult, ChangeResult *removalResult); bool applyRemovalChange(const QDeclarativeChangeSet::Remove &removal, ChangeResult *changeResult, int *removedCount); + void removeItem(FxViewItem *item, const QDeclarativeChangeSet::Remove &removal, ChangeResult *removeResult); void repositionFirstItem(FxViewItem *prevVisibleItemsFirst, qreal prevVisibleItemsFirstPos, FxViewItem *prevFirstVisible, ChangeResult *insertionResult, ChangeResult *removalResult); + void prepareVisibleItemTransitions(); + void prepareRemoveTransitions(QHash *removedItems); + bool prepareNonVisibleItemTransition(FxViewItem *item, const QRectF &viewBounds); + + bool hasItemTransitions() const; + void transitionNextReposition(FxViewItem *item, FxViewItemTransitionManager::TransitionType type, bool isTarget); + int findMoveKeyIndex(QDeclarativeChangeSet::MoveKey key, const QVector &changes) const; + void checkVisible() const; + void showVisibleItems() const; void markExtentsDirty() { if (layoutOrientation() == Qt::Vertical) @@ -201,12 +293,35 @@ public: QDeclarativeComponent *footerComponent; FxViewItem *footer; + QDeclarativeTransition *populateTransition; + QDeclarativeTransition *addTransition; + QDeclarativeTransition *addDisplacedTransition; + QDeclarativeTransition *moveTransition; + QDeclarativeTransition *moveDisplacedTransition; + QDeclarativeTransition *removeTransition; + QDeclarativeTransition *removeDisplacedTransition; + + QList addTransitionIndexes; + QList moveTransitionIndexes; + QList removeTransitionIndexes; + QList addTransitionTargets; + QList moveTransitionTargets; + QList removeTransitionTargets; + + struct MovedItem { + FxViewItem *item; + QDeclarativeChangeSet::MoveKey moveKey; + MovedItem(FxViewItem *i, QDeclarativeChangeSet::MoveKey k) + : item(i), moveKey(k) {} + }; + QList releasePendingTransition; + mutable qreal minExtent; mutable qreal maxExtent; bool ownModel : 1; bool wrap : 1; - bool inApplyModelChanges : 1; + bool disableLayout : 1; bool inViewportMoved : 1; bool forceLayout : 1; bool currentIndexCleared : 1; @@ -217,6 +332,8 @@ public: bool fillCacheBuffer : 1; bool inRequest : 1; bool requestedAsync : 1; + bool usePopulateTransition : 1; + bool runDelayedRemoveTransition : 1; protected: virtual Qt::Orientation layoutOrientation() const = 0; @@ -246,15 +363,19 @@ protected: virtual void visibleItemsChanged() {} virtual FxViewItem *newViewItem(int index, QQuickItem *item) = 0; + virtual void repositionItemAt(FxViewItem *item, int index, qreal sizeBuffer) = 0; virtual void repositionPackageItemAt(QQuickItem *item, int index) = 0; virtual void resetFirstItemPosition(qreal pos = 0.0) = 0; virtual void adjustFirstItem(qreal forwards, qreal backwards, int changeBeforeVisible) = 0; virtual void layoutVisibleItems(int fromModelIndex = 0) = 0; virtual void changedVisibleIndex(int newIndex) = 0; - virtual bool applyInsertionChange(const QDeclarativeChangeSet::Insert &insert, ChangeResult *changeResult, QList *newItems) = 0; + + virtual bool applyInsertionChange(const QDeclarativeChangeSet::Insert &insert, ChangeResult *changeResult, + QList *newItems, QList *movingIntoView) = 0; virtual bool needsRefillForAddedOrRemovedIndex(int) const { return false; } + virtual void translateAndTransitionItemsAfter(int afterIndex, const ChangeResult &insertionResult, const ChangeResult &removalResult) = 0; virtual void initializeViewItem(FxViewItem *) {} virtual void initializeCurrentItem() {} diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp index 424edc5..03be177 100644 --- a/src/quick/items/qquicklistview.cpp +++ b/src/quick/items/qquicklistview.cpp @@ -94,6 +94,7 @@ public: virtual FxViewItem *newViewItem(int index, QQuickItem *item); virtual void initializeViewItem(FxViewItem *item); virtual void releaseItem(FxViewItem *item); + virtual void repositionItemAt(FxViewItem *item, int index, qreal sizeBuffer); virtual void repositionPackageItemAt(QQuickItem *item, int index); virtual void resetFirstItemPosition(qreal pos = 0.0); virtual void adjustFirstItem(qreal forwards, qreal backwards, int); @@ -104,7 +105,9 @@ public: virtual void setPosition(qreal pos); virtual void layoutVisibleItems(int fromModelIndex = 0); - virtual bool applyInsertionChange(const QDeclarativeChangeSet::Insert &insert, ChangeResult *changeResult, QList *addedItems); + + virtual bool applyInsertionChange(const QDeclarativeChangeSet::Insert &insert, ChangeResult *changeResult, QList *addedItems, QList *movingIntoView); + virtual void translateAndTransitionItemsAfter(int afterIndex, const ChangeResult &insertionResult, const ChangeResult &removalResult); virtual void updateSections(); QQuickItem *getSectionItem(const QString §ion); @@ -253,9 +256,9 @@ public: } qreal itemPosition() const { if (view->orientation() == QQuickListView::Vertical) - return item->y(); + return itemY(); else - return (view->effectiveLayoutDirection() == Qt::RightToLeft ? -item->width()-item->x() : item->x()); + return (view->effectiveLayoutDirection() == Qt::RightToLeft ? -item->width()-itemX() : itemX()); } qreal size() const { if (section) @@ -273,35 +276,26 @@ public: } qreal endPosition() const { if (view->orientation() == QQuickListView::Vertical) { - return item->y() + item->height(); + return itemY() + item->height(); } else { return (view->effectiveLayoutDirection() == Qt::RightToLeft - ? -item->x() - : item->x() + item->width()); + ? -itemX() + : itemX() + item->width()); } } void setPosition(qreal pos) { - if (view->orientation() == QQuickListView::Vertical) { - if (section) { + // position the section immediately even if there is a transition + if (section) { + if (view->orientation() == QQuickListView::Vertical) { section->setY(pos); - pos += section->height(); - } - item->setY(pos); - } else { - if (view->effectiveLayoutDirection() == Qt::RightToLeft) { - if (section) { - section->setX(-section->width()-pos); - pos += section->width(); - } - item->setX(-item->width()-pos); } else { - if (section) { + if (view->effectiveLayoutDirection() == Qt::RightToLeft) + section->setX(-section->width()-pos); + else section->setX(pos); - pos += section->width(); - } - item->setX(pos); } } + moveTo(pointForPosition(pos)); } void setSize(qreal size) { if (view->orientation() == QQuickListView::Vertical) @@ -310,12 +304,34 @@ public: item->setWidth(size); } bool contains(qreal x, qreal y) const { - return (x >= item->x() && x < item->x() + item->width() && - y >= item->y() && y < item->y() + item->height()); + return (x >= itemX() && x < itemX() + item->width() && + y >= itemY() && y < itemY() + item->height()); + } + QQuickItemView *itemView() const { + return view; } QQuickItem *section; QQuickListView *view; + +private: + QPointF pointForPosition(qreal pos) const { + if (view->orientation() == QQuickListView::Vertical) { + if (section) + pos += section->height(); + return QPointF(itemX(), pos); + } else { + if (view->effectiveLayoutDirection() == Qt::RightToLeft) { + if (section) + pos += section->width(); + return QPointF(-item->width() - pos, itemY()); + } else { + if (section) + pos += section->width(); + return QPointF(pos, itemY()); + } + } + } }; //---------------------------------------------------------------------------- @@ -401,8 +417,9 @@ qreal QQuickListViewPrivate::lastPosition() const qreal QQuickListViewPrivate::positionAt(int modelIndex) const { - if (FxViewItem *item = visibleItem(modelIndex)) + if (FxViewItem *item = visibleItem(modelIndex)) { return item->position(); + } if (!visibleItems.isEmpty()) { if (modelIndex < visibleIndex) { int count = visibleIndex - modelIndex; @@ -612,7 +629,8 @@ bool QQuickListViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, bool d #endif if (!(item = static_cast(createItem(modelIndex, doBuffer)))) break; - item->setPosition(pos); + if (!(usePopulateTransition && populateTransition)) // pos will be set by layoutVisibleItems() + item->setPosition(pos); item->item->setVisible(!doBuffer); pos += item->size() + spacing; visibleItems.append(item); @@ -631,7 +649,8 @@ bool QQuickListViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, bool d break; --visibleIndex; visiblePos -= item->size() + spacing; - item->setPosition(visiblePos); + if (!(usePopulateTransition && populateTransition)) // pos will be set by layoutVisibleItems() + item->setPosition(visiblePos); item->item->setVisible(!doBuffer); visibleItems.prepend(item); changed = true; @@ -654,6 +673,7 @@ bool QQuickListViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal buffer && (item = visibleItems.at(index)) && item->endPosition() < bufferFrom) { if (item->attached->delayRemove()) break; + if (item->size() > 0) { #ifdef DEBUG_DELEGATE_LIFECYCLE qDebug() << "refill: remove first" << visibleIndex << "top end pos" << item->endPosition(); @@ -663,7 +683,15 @@ bool QQuickListViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal buffer if (item->index != -1) visibleIndex++; visibleItems.removeAt(index); - releaseItem(item); + if (item->transitionScheduledOrRunning()) { +#ifdef DEBUG_DELEGATE_LIFECYCLE + qDebug() << "refill not releasing animating item" << item->index << item->item->objectName(); +#endif + item->releaseAfterTransition = true; + releasePendingTransition.append(item); + } else { + releaseItem(item); + } if (index == 0) break; item = visibleItems.at(--index); @@ -681,7 +709,15 @@ bool QQuickListViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal buffer qDebug() << "refill: remove last" << visibleIndex+visibleItems.count()-1 << item->position(); #endif visibleItems.removeLast(); - releaseItem(item); + if (item->transitionScheduledOrRunning()) { +#ifdef DEBUG_DELEGATE_LIFECYCLE + qDebug() << "refill not releasing animating item" << item->index << item->item->objectName(); +#endif + item->releaseAfterTransition = true; + releasePendingTransition.append(item); + } else { + releaseItem(item); + } changed = true; } @@ -713,11 +749,12 @@ void QQuickListViewPrivate::layoutVisibleItems(int fromModelIndex) qreal sum = firstItem->size(); qreal pos = firstItem->position() + firstItem->size() + spacing; firstItem->item->setVisible(firstItem->endPosition() >= from && firstItem->position() <= to); + for (int i=1; i < visibleItems.count(); ++i) { FxListItemSG *item = static_cast(visibleItems.at(i)); if (item->index >= fromModelIndex) { item->setPosition(pos); - item->item->setVisible(item->endPosition() >= from && item->position() <= to); + item->setVisible(item->endPosition() >= from && item->position() <= to); } pos += item->size() + spacing; sum += item->size(); @@ -726,12 +763,16 @@ void QQuickListViewPrivate::layoutVisibleItems(int fromModelIndex) averageSize = qRound(sum / visibleItems.count()); // move current item if it is not a visible item. - if (currentIndex >= 0 && currentItem && !fixedCurrent) { + if (currentIndex >= 0 && currentItem && !fixedCurrent) static_cast(currentItem)->setPosition(positionAt(currentIndex)); - } } } +void QQuickListViewPrivate::repositionItemAt(FxViewItem *item, int index, qreal sizeBuffer) +{ + static_cast(item)->setPosition(positionAt(index) + sizeBuffer); +} + void QQuickListViewPrivate::repositionPackageItemAt(QQuickItem *item, int index) { Q_Q(QQuickListView); @@ -1132,13 +1173,17 @@ void QQuickListViewPrivate::initializeCurrentItem() if (currentItem) { FxListItemSG *listItem = static_cast(currentItem); - if (currentIndex == visibleIndex - 1 && visibleItems.count()) { - // We can calculate exact postion in this case - listItem->setPosition(visibleItems.first()->position() - currentItem->size() - spacing); - } else { - // Create current item now and position as best we can. - // Its position will be corrected when it becomes visible. - listItem->setPosition(positionAt(currentIndex)); + // don't reposition the item if it's about to be transitioned to another position + FxViewItem *actualItem = visibleItem(currentIndex); + if ((!actualItem || !actualItem->transitionScheduledOrRunning())) { + if (currentIndex == visibleIndex - 1 && visibleItems.count()) { + // We can calculate exact postion in this case + listItem->setPosition(visibleItems.first()->position() - currentItem->size() - spacing); + } else { + // Create current item now and position as best we can. + // Its position will be corrected when it becomes visible. + listItem->setPosition(positionAt(currentIndex)); + } } // Avoid showing section delegate twice. We still need the section heading so that @@ -1653,27 +1698,34 @@ QQuickListView::~QQuickListView() /*! \qmlattachedproperty bool QtQuick2::ListView::delayRemove - This attached property holds whether the delegate may be destroyed. - It is attached to each instance of the delegate. + This attached property holds whether the delegate may be destroyed. It + is attached to each instance of the delegate. The default value is false. It is sometimes necessary to delay the destruction of an item - until an animation completes. - - The example delegate below ensures that the animation completes before - the item is removed from the list. + until an animation completes. The example delegate below ensures that the + animation completes before the item is removed from the list. \snippet doc/src/snippets/declarative/listview/listview.qml delayRemove + + If a \l remove transition has been specified, it will not be applied until + delayRemove is returned to \c false. */ /*! \qmlattachedsignal QtQuick2::ListView::onAdd() - This attached handler is called immediately after an item is added to the view. + This attached signal handler is called immediately after an item is added to the view. + + If an \l add transition is specified, it is applied immediately after + this signal handler is called. */ /*! \qmlattachedsignal QtQuick2::ListView::onRemove() This attached handler is called immediately before an item is removed from the view. + + If a \l remove transition has been specified, it is applied after + this signal handler is called, providing that delayRemove is false. */ /*! @@ -2191,6 +2243,231 @@ void QQuickListView::setSnapMode(SnapMode mode) \sa footer, headerItem */ +/*! + \qmlproperty Transition QtQuick2::ListView::populate + This property holds the transition to apply to items that are initially created for a + view. + + This transition is applied to all the items that are created when: + + \list + \o The view is first created + \o The view's \l model changes + \o The view's \l model is \l {QAbstractItemModel::reset}{reset}, if the model is a QAbstractItemModel subclass + \endlist + + For example, here is a view that specifies such a transition: + + \code + ListView { + ... + populate: Transition { + NumberAnimation { properties: "x,y"; duration: 1000 } + } + } + \endcode + + When the view is initialized, the view will create all the necessary items for the view, + then animate them to their correct positions within the view over one second. + + For more details and examples on how to use view transitions, see the ViewTransition + documentation. + + \sa add, ViewTransition +*/ + +/*! + \qmlproperty Transition QtQuick2::ListView::add + This property holds the transition to apply to items that are added within the view. + + The transition is applied to items that have been added to the visible area of the view. For + example, here is a view that specifies such a transition: + + \code + ListView { + ... + add: Transition { + NumberAnimation { properties: "x,y"; from: 100; duration: 1000 } + } + } + \endcode + + Whenever an item is added to the above view, the item will be animated from the position (100,100) + to its final x,y position within the view, over one second. The transition only applies to + the new items that are added to the view; it does not apply to the items below that are + displaced by the addition of the new items. To animate the displaced items, set the \l + addDisplaced property. + + For more details and examples on how to use view transitions, see the ViewTransition + documentation. + + \note This transition is not applied to the items that are created when the view is initially + populated, or when the view's \l model changes. In those cases, the \l populate transition is + applied instead. + + \sa addDisplaced, populate, ViewTransition +*/ + +/*! + \qmlproperty Transition QtQuick2::ListView::addDisplaced + This property holds the transition to apply to items in the view that are displaced by other + items that have been added to the view. + + The transition is applied to items that are currently visible and have been displaced by newly + added items. For example, here is a view that specifies such a transition: + + \code + ListView { + ... + addDisplaced: Transition { + NumberAnimation { properties: "x,y"; duration: 1000 } + } + } + \endcode + + Whenever an item is added to the above view, all items beneath the new item are displaced, causing + them to move down (or sideways, if horizontally orientated) within the view. As this + displacement occurs, the items' movement to their new x,y positions within the view will be + animated by a NumberAnimation over one second, as specified. This transition is not applied to + the new item that has been added to the view; to animate the added items, set the \l add + property. + + For more details and examples on how to use view transitions, see the ViewTransition + documentation. + + \note This transition is not applied to the items that are created when the view is initially + populated, or when the view's \l model changes. In those cases, the \l populate transition is + applied instead. + + \sa add, populate, ViewTransition +*/ + +/*! + \qmlproperty Transition QtQuick2::ListView::move + This property holds the transition to apply to items in the view that are moved by a move + operation. + + The transition is applied to items that are moving within the view or are moving + into the view as a result of a move operation in the view's model. For example: + + \code + ListView { + ... + move: Transition { + NumberAnimation { properties: "x,y"; duration: 1000 } + } + } + \endcode + + Whenever an item is moved within the above view, the item will be animated to its new position in + the view over one second. The transition only applies to the items that are the subject of the + move operation in the model; it does not apply to the items below them that are displaced by + the move operation. To animate the displaced items, set the \l moveDisplaced property. + + For more details and examples on how to use view transitions, see the ViewTransition + documentation. + + \sa moveDisplaced, ViewTransition +*/ + +/*! + \qmlproperty Transition QtQuick2::ListView::moveDisplaced + This property holds the transition to apply to items in the view that are displaced by a + move operation in the view. + + The transition is applied to items that are currently visible and have been displaced following + a move operation in the view's model. For example, here is a view that specifies such a transition: + + \code + ListView { + ... + moveDisplaced: Transition { + NumberAnimation { properties: "x,y"; duration: 1000 } + } + } + \endcode + + Whenever an item moves within (or moves into) the above view, all items beneath it are + displaced, causing them to move upwards (or sideways, if horizontally orientated) within the + view. As this displacement occurs, the items' movement to their new x,y positions within the + view will be animated by a NumberAnimation over one second, as specified. This transition is + not applied to the item that are actually the subject of the move operation; to animate the + moved items, set the \l move property. + + For more details and examples on how to use view transitions, see the ViewTransition + documentation. + + \sa move, ViewTransition +*/ + +/*! + \qmlproperty Transition QtQuick2::ListView::remove + This property holds the transition to apply to items that are removed from the view. + + The transition is applied to items that have been removed from the visible area of the view. For + example: + + \code + ListView { + ... + remove: Transition { + ParallelAnimation { + NumberAnimation { property: "opacity"; to: 0; duration: 1000 } + NumberAnimation { properties: "x,y"; to: 100; duration: 1000 } + } + } + } + \endcode + + Whenever an item is removed from the above view, the item will be animated to the position (100,100) + over one second, and in parallel will also change its opacity to 0. The transition + only applies to the items that are removed from the view; it does not apply to the items below + them that are displaced by the removal of the items. To animate the displaced items, set the \l + removeDisplaced property. + + Note that by the time the transition is applied, the item has already been removed from the + model; any references to the model data for the removed index will not be valid. + + Additionally, if the \l delayRemove attached property has been set for a delegate item, the + remove transition will not be applied until \l delayRemove becomes false again. + + For more details and examples on how to use view transitions, see the ViewTransition + documentation. + + \sa removeDisplaced, ViewTransition +*/ + +/*! + \qmlproperty Transition QtQuick2::ListView::removeDisplaced + This property holds the transition to apply to items in the view that are displaced by the + removal of other items in the view. + + The transition is applied to items that are currently visible and have been displaced by + the removal of items. For example, here is a view that specifies such a transition: + + \code + ListView { + ... + removeDisplaced: Transition { + NumberAnimation { properties: "x,y"; duration: 1000 } + } + } + \endcode + + Whenever an item is removed from the above view, all items beneath it are displaced, causing + them to move upwards (or sideways, if horizontally orientated) within the view. As this + displacement occurs, the items' movement to their new x,y positions within the view will be + animated by a NumberAnimation over one second, as specified. This transition is not applied to + the item that has actually been removed from the view; to animate the removed items, set the + \l remove property. + + For more details and examples on how to use view transitions, see the ViewTransition + documentation. + + \sa remove, ViewTransition +*/ + + void QQuickListView::viewportMoved() { Q_D(QQuickListView); @@ -2385,7 +2662,7 @@ void QQuickListView::updateSections() } } -bool QQuickListViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::Insert &change, ChangeResult *insertResult, QList *addedItems) +bool QQuickListViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::Insert &change, ChangeResult *insertResult, QList *addedItems, QList *movingIntoView) { int modelIndex = change.index; int count = change.count; @@ -2450,8 +2727,10 @@ bool QQuickListViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::In visibleItems.insert(insertionIdx, item); if (insertionIdx == 0) insertResult->changedFirstItem = true; - if (!change.isMove()) + if (!change.isMove()) { addedItems->append(item); + transitionNextReposition(item, FxViewItemTransitionManager::AddTransition, true); + } insertResult->sizeChangesBeforeVisiblePos += item->size() + spacing; pos -= item->size() + spacing; } @@ -2464,6 +2743,7 @@ bool QQuickListViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::In FxViewItem *item = 0; if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(modelIndex + i)))) item->index = modelIndex + i; + bool newItem = !item; if (!item) item = createItem(modelIndex + i); if (!item) @@ -2472,8 +2752,15 @@ bool QQuickListViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::In visibleItems.insert(index, item); if (index == 0) insertResult->changedFirstItem = true; - if (!change.isMove()) + if (change.isMove()) { + // we know this is a move target, since move displaced items that are + // shuffled into view due to a move would be added in refill() + if (moveTransition && newItem) + movingIntoView->append(MovedItem(item, change.moveKey(item->index))); + } else { addedItems->append(item); + transitionNextReposition(item, FxViewItemTransitionManager::AddTransition, true); + } insertResult->sizeChangesAfterVisiblePos += item->size() + spacing; pos += item->size() + spacing; ++index; @@ -2484,6 +2771,10 @@ bool QQuickListViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::In FxViewItem *item = visibleItems.at(index); if (item->index != -1) item->index += count; + if (change.isMove()) + transitionNextReposition(item, FxViewItemTransitionManager::MoveTransition, false); + else + transitionNextReposition(item, FxViewItemTransitionManager::AddTransition, false); } updateVisibleIndex(); @@ -2491,6 +2782,34 @@ bool QQuickListViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::In return visibleItems.count() > prevVisibleCount; } +void QQuickListViewPrivate::translateAndTransitionItemsAfter(int afterModelIndex, const ChangeResult &insertionResult, const ChangeResult &removalResult) +{ + Q_UNUSED(insertionResult); + + int markerItemIndex = -1; + for (int i=0; iindex == afterModelIndex) { + markerItemIndex = i; + break; + } + } + if (markerItemIndex < 0) + return; + + const qreal viewEndPos = isContentFlowReversed() ? -position() : position() + size(); + qreal sizeRemoved = -removalResult.sizeChangesAfterVisiblePos + - (removalResult.countChangeAfterVisibleItems * (averageSize + spacing)); + + for (int i=markerItemIndex+1; iposition() < viewEndPos; i++) { + FxListItemSG *listItem = static_cast(visibleItems[i]); + if (!listItem->transitionScheduledOrRunning()) { + qreal pos = listItem->position(); + listItem->setPosition(pos - sizeRemoved); + transitionNextReposition(listItem, FxViewItemTransitionManager::RemoveTransition, false); + listItem->setPosition(pos); + } + } +} /*! \qmlmethod QtQuick2::ListView::positionViewAtIndex(int index, PositionMode mode) diff --git a/tests/auto/qtquick2/qquickgridview/data/addTransitions.qml b/tests/auto/qtquick2/qquickgridview/data/addTransitions.qml new file mode 100644 index 0000000..faea02a --- /dev/null +++ b/tests/auto/qtquick2/qquickgridview/data/addTransitions.qml @@ -0,0 +1,129 @@ +import QtQuick 2.0 + +Rectangle { + id: root + width: 550 + height: 600 + + property int duration: 10 + property int count: grid.count + + Component { + id: myDelegate + + Rectangle { + id: wrapper + + property string nameData: name + + objectName: "wrapper" + width: 80 + height: 60 + border.width: 1 + Column { + Text { text: index } + Text { + text: wrapper.x + ", " + wrapper.y + } + Text { + id: textName + objectName: "textName" + text: name + } + } + color: GridView.isCurrentItem ? "lightsteelblue" : "white" + + onXChanged: checkPos() + onYChanged: checkPos() + + function checkPos() { + if (Qt.point(x, y) == targetItems_transitionFrom) + model_targetItems_transitionFrom.addItem(name, "") + if (Qt.point(x, y) == displacedItems_transitionVia) + model_displacedItems_transitionVia.addItem(name, "") + } + } + } + + GridView { + id: grid + + property int targetTransitionsDone + property int displaceTransitionsDone + + property var targetTrans_items: new Object() + property var targetTrans_targetIndexes: new Array() + property var targetTrans_targetItems: new Array() + + property var displacedTrans_items: new Object() + property var displacedTrans_targetIndexes: new Array() + property var displacedTrans_targetItems: new Array() + + objectName: "grid" + width: 240 + height: 320 + cellWidth: 80 + cellHeight: 60 + anchors.centerIn: parent + model: testModel + delegate: myDelegate + + // for QDeclarativeListProperty types + function copyList(propList) { + var temp = new Array() + for (var i=0; i #include #include +#include #include +#include #include "../../shared/util.h" #include "../shared/viewtestutil.h" #include "../shared/visualtestutil.h" @@ -127,6 +129,23 @@ private slots: void cacheBuffer(); void asynchronous(); void unrequestedVisibility(); + + void populateTransitions(); + void populateTransitions_data(); + void addTransitions(); + void addTransitions_data(); + void moveTransitions(); + void moveTransitions_data(); + void removeTransitions(); + void removeTransitions_data(); + void multipleTransitions(); + void multipleTransitions_data(); + +private: + QList toIntList(const QVariantList &list); + void matchIndexLists(const QVariantList &indexLists, const QList &expectedIndexes); + void matchItemsAndIndexes(const QVariantMap &items, const QaimModel &model, const QList &expectedIndexes); + void matchItemLists(const QVariantList &itemLists, const QList &expectedItems); }; tst_QQuickGridView::tst_QQuickGridView() @@ -500,13 +519,15 @@ void tst_QQuickGridView::insertBeforeVisible() QTRY_VERIFY(contentItem != 0); gridview->setCacheBuffer(cacheBuffer); + QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false); // trigger a refill (not just setting contentY) so that the visibleItems grid is updated int firstVisibleIndex = 12; // move to an index where the top item is not visible gridview->setContentY(firstVisibleIndex/3 * 60.0); gridview->setCurrentIndex(firstVisibleIndex); - qApp->processEvents(); + QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false); + QTRY_COMPARE(gridview->currentIndex(), firstVisibleIndex); QQuickItem *item = findItem(contentItem, "wrapper", firstVisibleIndex); QVERIFY(item); @@ -521,6 +542,7 @@ void tst_QQuickGridView::insertBeforeVisible() // now, moving to the top of the view should position the inserted items correctly int itemsOffsetAfterMove = (insertCount / 3) * -60.0; gridview->setCurrentIndex(0); + QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false); QTRY_COMPARE(gridview->currentIndex(), 0); QTRY_COMPARE(gridview->contentY(), 0.0 + itemsOffsetAfterMove); @@ -1283,12 +1305,19 @@ void tst_QQuickGridView::multipleChanges() } case ListChange::Removed: model.removeItems(changes[i].index, changes[i].count); + QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false); break; case ListChange::Moved: model.moveItems(changes[i].index, changes[i].to, changes[i].count); + QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false); break; case ListChange::SetCurrent: gridview->setCurrentIndex(changes[i].index); + QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false); + break; + case ListChange::SetContentY: + gridview->setContentY(changes[i].pos); + QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false); break; } } @@ -2005,10 +2034,10 @@ void tst_QQuickGridView::componentChanges() QTRY_VERIFY(gridView); QDeclarativeComponent component(canvas->engine()); - component.setData("import QtQuick 2.0; Rectangle { color: \"blue\"; }", QUrl::fromLocalFile("")); + component.setData("import QtQuick 1.0; Rectangle { color: \"blue\"; }", QUrl::fromLocalFile("")); QDeclarativeComponent delegateComponent(canvas->engine()); - delegateComponent.setData("import QtQuick 2.0; Text { text: 'Name: ' + name }", QUrl::fromLocalFile("")); + delegateComponent.setData("import QtQuick 1.0; Text { text: 'Name: ' + name }", QUrl::fromLocalFile("")); QSignalSpy highlightSpy(gridView, SIGNAL(highlightChanged())); QSignalSpy delegateSpy(gridView, SIGNAL(delegateChanged())); @@ -3769,6 +3798,898 @@ void tst_QQuickGridView::unaligned() delete canvas; } +void tst_QQuickGridView::populateTransitions() +{ + QFETCH(bool, staticallyPopulate); + QFETCH(bool, dynamicallyPopulate); + QFETCH(bool, usePopulateTransition); + + QPointF transitionFrom(-50, -50); + QPointF transitionVia(100, 100); + QaimModel model_transitionFrom; + QaimModel model_transitionVia; + + QaimModel model; + if (staticallyPopulate) { + for (int i = 0; i < 30; i++) + model.addItem("item" + QString::number(i), ""); + } + + QQuickView *canvas = createView(); + canvas->rootContext()->setContextProperty("testModel", &model); + canvas->rootContext()->setContextProperty("usePopulateTransition", usePopulateTransition); + canvas->rootContext()->setContextProperty("dynamicallyPopulate", dynamicallyPopulate); + canvas->rootContext()->setContextProperty("transitionFrom", transitionFrom); + canvas->rootContext()->setContextProperty("transitionVia", transitionVia); + canvas->rootContext()->setContextProperty("model_transitionFrom", &model_transitionFrom); + canvas->rootContext()->setContextProperty("model_transitionVia", &model_transitionVia); + canvas->setSource(testFileUrl("populateTransitions.qml")); + canvas->show(); + + QQuickGridView *gridview = findItem(canvas->rootObject(), "grid"); + QVERIFY(gridview); + QQuickItem *contentItem = gridview->contentItem(); + QVERIFY(contentItem); + + if (staticallyPopulate || dynamicallyPopulate) { + // check the populate transition is run + if (usePopulateTransition) { + QTRY_COMPARE(gridview->property("countPopulateTransitions").toInt(), 19); + } else { + QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false); + QTRY_COMPARE(gridview->property("countPopulateTransitions").toInt(), 0); + } + QTRY_COMPARE(gridview->property("countAddTransitions").toInt(), 0); + } else { + QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false); + } + + int itemCount = findItems(contentItem, "wrapper").count(); + if (usePopulateTransition) + QCOMPARE(itemCount, gridview->property("countPopulateTransitions").toInt()); + for (int i=0; i < model.count() && i < itemCount; ++i) { + QQuickItem *item = findItem(contentItem, "wrapper", i); + QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i))); + QCOMPARE(item->x(), (i%3)*80.0); + QCOMPARE(item->y(), (i/3)*60.0); + QQuickText *name = findItem(contentItem, "textName", i); + QVERIFY(name != 0); + QTRY_COMPARE(name->text(), model.name(i)); + } + + // add an item and check this is done with add transition, not populate + model.insertItem(0, "another item", ""); + QTRY_COMPARE(gridview->property("countAddTransitions").toInt(), 1); + QTRY_COMPARE(gridview->property("countPopulateTransitions").toInt(), + (usePopulateTransition && (staticallyPopulate || dynamicallyPopulate)) ? 19 : 0); + + // clear the model + canvas->rootContext()->setContextProperty("testModel", QVariant()); + QTRY_COMPARE(gridview->count(), 0); + QTRY_COMPARE(findItems(contentItem, "wrapper").count(), 0); + gridview->setProperty("countPopulateTransitions", 0); + gridview->setProperty("countAddTransitions", 0); + + // set to a valid model and check populate transition is run a second time + model.clear(); + for (int i = 0; i < 30; i++) + model.addItem("item" + QString::number(i), ""); + canvas->rootContext()->setContextProperty("testModel", &model); + QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false); + + QTRY_COMPARE(gridview->property("countPopulateTransitions").toInt(), usePopulateTransition ? 19 : 0); + QTRY_COMPARE(gridview->property("countAddTransitions").toInt(), 0); + + itemCount = findItems(contentItem, "wrapper").count(); + if (usePopulateTransition) + QCOMPARE(itemCount, gridview->property("countPopulateTransitions").toInt()); + for (int i=0; i < model.count() && i < itemCount; ++i) { + QQuickItem *item = findItem(contentItem, "wrapper", i); + QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i))); + QCOMPARE(item->x(), (i%3)*80.0); + QCOMPARE(item->y(), (i/3)*60.0); + QQuickText *name = findItem(contentItem, "textName", i); + QVERIFY(name != 0); + QTRY_COMPARE(name->text(), model.name(i)); + } + + // reset model and check populate transition is run again + gridview->setProperty("countPopulateTransitions", 0); + gridview->setProperty("countAddTransitions", 0); + model.reset(); + QTRY_COMPARE(gridview->property("countPopulateTransitions").toInt(), usePopulateTransition ? 19 : 0); + QTRY_COMPARE(gridview->property("countAddTransitions").toInt(), 0); + + itemCount = findItems(contentItem, "wrapper").count(); + if (usePopulateTransition) + QCOMPARE(itemCount, gridview->property("countPopulateTransitions").toInt()); + for (int i=0; i < model.count() && i < itemCount; ++i) { + QQuickItem *item = findItem(contentItem, "wrapper", i); + QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i))); + QCOMPARE(item->x(), (i%3)*80.0); + QCOMPARE(item->y(), (i/3)*60.0); + QQuickText *name = findItem(contentItem, "textName", i); + QVERIFY(name != 0); + QTRY_COMPARE(name->text(), model.name(i)); + } + + delete canvas; +} + +void tst_QQuickGridView::populateTransitions_data() +{ + QTest::addColumn("staticallyPopulate"); + QTest::addColumn("dynamicallyPopulate"); + QTest::addColumn("usePopulateTransition"); + + QTest::newRow("static") << true << false << true; + QTest::newRow("static, no populate") << true << false << false; + + QTest::newRow("dynamic") << false << true << true; + QTest::newRow("dynamic, no populate") << false << true << false; + + QTest::newRow("empty to start with") << false << false << true; + QTest::newRow("empty to start with, no populate") << false << false << false; +} + +void tst_QQuickGridView::addTransitions() +{ + QFETCH(int, initialItemCount); + QFETCH(bool, shouldAnimateTargets); + QFETCH(qreal, contentY); + QFETCH(int, insertionIndex); + QFETCH(int, insertionCount); + QFETCH(ListRange, expectedDisplacedIndexes); + + // added items should start here + QPointF targetItems_transitionFrom(-50, -50); + + // displaced items should pass through this point + QPointF displacedItems_transitionVia(100, 100); + + QaimModel model; + for (int i = 0; i < initialItemCount; i++) + model.addItem("Original item" + QString::number(i), ""); + QaimModel model_targetItems_transitionFrom; + QaimModel model_displacedItems_transitionVia; + + QQuickView *canvas = createView(); + QDeclarativeContext *ctxt = canvas->rootContext(); + ctxt->setContextProperty("testModel", &model); + ctxt->setContextProperty("model_targetItems_transitionFrom", &model_targetItems_transitionFrom); + ctxt->setContextProperty("model_displacedItems_transitionVia", &model_displacedItems_transitionVia); + ctxt->setContextProperty("targetItems_transitionFrom", targetItems_transitionFrom); + ctxt->setContextProperty("displacedItems_transitionVia", displacedItems_transitionVia); + canvas->setSource(testFileUrl("addTransitions.qml")); + canvas->show(); + + QQuickGridView *gridview = findItem(canvas->rootObject(), "grid"); + QTRY_VERIFY(gridview != 0); + QQuickItem *contentItem = gridview->contentItem(); + QVERIFY(contentItem != 0); + QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false); + + if (contentY != 0) { + gridview->setContentY(contentY); + QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false); + } + + QList > expectedDisplacedValues = expectedDisplacedIndexes.getModelDataValues(model); + + // only target items that will become visible should be animated + QList > newData; + QList > expectedTargetData; + QList targetIndexes; + if (shouldAnimateTargets) { + for (int i=insertionIndex; i= (contentY / 60)*3 && i < qCeil((contentY + gridview->height()) / 60.0)*3) { + expectedTargetData << newData.last(); + targetIndexes << i; + } + } + QVERIFY(expectedTargetData.count() > 0); + } + + // start animation + if (!newData.isEmpty()) { + model.insertItems(insertionIndex, newData); + QTRY_COMPARE(model.count(), gridview->count()); + } + + QList targetItems = findItems(contentItem, "wrapper", targetIndexes); + + if (shouldAnimateTargets) { + QTRY_COMPARE(gridview->property("targetTransitionsDone").toInt(), expectedTargetData.count()); + QTRY_COMPARE(gridview->property("displaceTransitionsDone").toInt(), + expectedDisplacedIndexes.isValid() ? expectedDisplacedIndexes.count() : 0); + + // check the target and displaced items were animated + model_targetItems_transitionFrom.matchAgainst(expectedTargetData, "wasn't animated from target 'from' pos", "shouldn't have been animated from target 'from' pos"); + model_displacedItems_transitionVia.matchAgainst(expectedDisplacedValues, "wasn't animated with displaced anim", "shouldn't have been animated with displaced anim"); + + // check attached properties + matchItemsAndIndexes(gridview->property("targetTrans_items").toMap(), model, targetIndexes); + matchIndexLists(gridview->property("targetTrans_targetIndexes").toList(), targetIndexes); + matchItemLists(gridview->property("targetTrans_targetItems").toList(), targetItems); + if (expectedDisplacedIndexes.isValid()) { + // adjust expectedDisplacedIndexes to their final values after the move + QList displacedIndexes = adjustIndexesForAddDisplaced(expectedDisplacedIndexes.indexes, insertionIndex, insertionCount); + matchItemsAndIndexes(gridview->property("displacedTrans_items").toMap(), model, displacedIndexes); + matchIndexLists(gridview->property("displacedTrans_targetIndexes").toList(), targetIndexes); + matchItemLists(gridview->property("displacedTrans_targetItems").toList(), targetItems); + } + } else { + QTRY_COMPARE(model_targetItems_transitionFrom.count(), 0); + QTRY_COMPARE(model_displacedItems_transitionVia.count(), 0); + } + + QList items = findItems(contentItem, "wrapper"); + int firstVisibleIndex = -1; + for (int i=0; iy() >= contentY) { + QDeclarativeExpression e(qmlContext(items[i]), items[i], "index"); + firstVisibleIndex = e.evaluate().toInt(); + break; + } + } + QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex)); + + // verify all items moved to the correct final positions + int itemCount = findItems(contentItem, "wrapper").count(); + for (int i = firstVisibleIndex; i < model.count() && i < itemCount; ++i) { + QQuickItem *item = findItem(contentItem, "wrapper", i); + QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i))); + QCOMPARE(item->x(), (i%3)*80.0); + QCOMPARE(item->y(), (i/3)*60.0); + QQuickText *name = findItem(contentItem, "textName", i); + QVERIFY(name != 0); + QCOMPARE(name->text(), model.name(i)); + } + + delete canvas; +} + +void tst_QQuickGridView::addTransitions_data() +{ + QTest::addColumn("initialItemCount"); + QTest::addColumn("contentY"); + QTest::addColumn("shouldAnimateTargets"); + QTest::addColumn("insertionIndex"); + QTest::addColumn("insertionCount"); + QTest::addColumn("expectedDisplacedIndexes"); + + // if inserting a full row before visible index, items don't appear or animate in, even if there are > 1 new items + QTest::newRow("insert 1, just before start") + << 30 << 20.0 << false + << 0 << 1 << ListRange(); + QTest::newRow("insert 1, way before start") + << 30 << 20.0 << false + << 0 << 1 << ListRange(); + QTest::newRow("insert multiple, just before start") + << 30 << 100.0 << false + << 0 << 3 << ListRange(); + QTest::newRow("insert multiple (< 1 row), just before start") + << 30 << 100.0 << false + << 0 << 2 << ListRange(); + QTest::newRow("insert multiple, way before start") + << 30 << 100.0 << false + << 0 << 3 << ListRange(); + + QTest::newRow("insert 1 at start") + << 30 << 0.0 << true + << 0 << 1 << ListRange(0, 17); + QTest::newRow("insert multiple at start") + << 30 << 0.0 << true + << 0 << 3 << ListRange(0, 17); + QTest::newRow("insert multiple (> 1 row) at start") + << 30 << 0.0 << true + << 0 << 5 << ListRange(0, 17); + QTest::newRow("insert 1 at start, content y not 0") + << 30 << 60.0 << true // first visible is index 3 + << 3 << 1 << ListRange(0 + 3, 17 + 3); + QTest::newRow("insert multiple at start, content y not 0") + << 30 << 60.0 << true // first visible is index 3 + << 3 << 3 << ListRange(0 + 3, 17 + 3); + QTest::newRow("insert multiple (> 1 row) at start, content y not 0") + << 30 << 60.0 << true // first visible is index 3 + << 3 << 5 << ListRange(0 + 3, 17 + 3); + + QTest::newRow("insert 1 at start, to empty grid") + << 0 << 0.0 << true + << 0 << 1 << ListRange(); + QTest::newRow("insert multiple at start, to empty grid") + << 0 << 0.0 << true + << 0 << 3 << ListRange(); + + QTest::newRow("insert 1 at middle") + << 30 << 0.0 << true + << 7 << 1 << ListRange(7, 17); + QTest::newRow("insert multiple at middle") + << 30 << 0.0 << true + << 7 << 3 << ListRange(7, 17); + QTest::newRow("insert multiple (> 1 row) at middle") + << 30 << 0.0 << true + << 7 << 5 << ListRange(7, 17); + + QTest::newRow("insert 1 at bottom") + << 30 << 0.0 << true + << 17 << 1 << ListRange(17, 17); + QTest::newRow("insert multiple at bottom") + << 30 << 0.0 << true + << 17 << 3 << ListRange(17, 17); + QTest::newRow("insert 1 at bottom, content y not 0") + << 30 << 20.0 * 3 << true + << 17 + 3 << 1 << ListRange(17 + 3, 17 + 3); + QTest::newRow("insert multiple at bottom, content y not 0") + << 30 << 20.0 * 3 << true + << 17 + 3 << 3 << ListRange(17 + 3, 17 + 3); + + + // items added after the last visible will not be animated in, since they + // do not appear in the final view + QTest::newRow("insert 1 after end") + << 30 << 0.0 << false + << 18 << 1 << ListRange(); + QTest::newRow("insert multiple after end") + << 30 << 0.0 << false + << 18 << 3 << ListRange(); +} + +void tst_QQuickGridView::moveTransitions() +{ + QFETCH(int, initialItemCount); + QFETCH(qreal, contentY); + QFETCH(qreal, itemsOffsetAfterMove); + QFETCH(int, moveFrom); + QFETCH(int, moveTo); + QFETCH(int, moveCount); + QFETCH(ListRange, expectedDisplacedIndexes); + + // target and displaced items should pass through these points + QPointF targetItems_transitionVia(-50, 50); + QPointF displacedItems_transitionVia(100, 100); + + QaimModel model; + for (int i = 0; i < initialItemCount; i++) + model.addItem("Original item" + QString::number(i), ""); + QaimModel model_targetItems_transitionVia; + QaimModel model_displacedItems_transitionVia; + + QQuickView *canvas = createView(); + QDeclarativeContext *ctxt = canvas->rootContext(); + ctxt->setContextProperty("testModel", &model); + ctxt->setContextProperty("model_targetItems_transitionVia", &model_targetItems_transitionVia); + ctxt->setContextProperty("model_displacedItems_transitionVia", &model_displacedItems_transitionVia); + ctxt->setContextProperty("targetItems_transitionVia", targetItems_transitionVia); + ctxt->setContextProperty("displacedItems_transitionVia", displacedItems_transitionVia); + canvas->setSource(testFileUrl("moveTransitions.qml")); + canvas->show(); + + QQuickGridView *gridview = findItem(canvas->rootObject(), "grid"); + QTRY_VERIFY(gridview != 0); + QQuickItem *contentItem = gridview->contentItem(); + QVERIFY(contentItem != 0); + QQuickText *name; + + if (contentY != 0) { + gridview->setContentY(contentY); + QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false); + } + + QList > expectedDisplacedValues = expectedDisplacedIndexes.getModelDataValues(model); + + // Items moving to *or* from visible positions should be animated. + // Otherwise, they should not be animated. + QList > expectedTargetData; + QList targetIndexes; + for (int i=moveFrom; iheight()) / 60.0)*3) - 1; + if ((i >= firstVisibleIndex && i <= lastVisibleIndex) + || (toIndex >= firstVisibleIndex && toIndex <= lastVisibleIndex)) { + expectedTargetData << qMakePair(model.name(i), model.number(i)); + targetIndexes << i; + } + } + // ViewTransition.index provides the indices that items are moving to, not from + targetIndexes = adjustIndexesForMove(targetIndexes, moveFrom, moveTo, moveCount); + + // start animation + model.moveItems(moveFrom, moveTo, moveCount); + + QTRY_COMPARE(gridview->property("targetTransitionsDone").toInt(), expectedTargetData.count()); + QTRY_COMPARE(gridview->property("displaceTransitionsDone").toInt(), + expectedDisplacedIndexes.isValid() ? expectedDisplacedIndexes.count() : 0); + + QList targetItems = findItems(contentItem, "wrapper", targetIndexes); + + // check the target and displaced items were animated + model_targetItems_transitionVia.matchAgainst(expectedTargetData, "wasn't animated from target 'from' pos", "shouldn't have been animated from target 'from' pos"); + model_displacedItems_transitionVia.matchAgainst(expectedDisplacedValues, "wasn't animated with displaced anim", "shouldn't have been animated with displaced anim"); + + // check attached properties + matchItemsAndIndexes(gridview->property("targetTrans_items").toMap(), model, targetIndexes); + matchIndexLists(gridview->property("targetTrans_targetIndexes").toList(), targetIndexes); + matchItemLists(gridview->property("targetTrans_targetItems").toList(), targetItems); + if (expectedDisplacedIndexes.isValid()) { + // adjust expectedDisplacedIndexes to their final values after the move + QList displacedIndexes = adjustIndexesForMove(expectedDisplacedIndexes.indexes, moveFrom, moveTo, moveCount); + matchItemsAndIndexes(gridview->property("displacedTrans_items").toMap(), model, displacedIndexes); + matchIndexLists(gridview->property("displacedTrans_targetIndexes").toList(), targetIndexes); + matchItemLists(gridview->property("displacedTrans_targetItems").toList(), targetItems); + } + + QList items = findItems(contentItem, "wrapper"); + int firstVisibleIndex = -1; + for (int i=0; iy() >= contentY) { + QDeclarativeExpression e(qmlContext(items[i]), items[i], "index"); + firstVisibleIndex = e.evaluate().toInt(); + break; + } + } + QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex)); + + // verify all items moved to the correct final positions + int itemCount = findItems(contentItem, "wrapper").count(); + for (int i=firstVisibleIndex; i < model.count() && i < itemCount; ++i) { + QQuickItem *item = findItem(contentItem, "wrapper", i); + QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i))); + QCOMPARE(item->x(), (i%3)*80.0); + QCOMPARE(item->y(), (i/3)*60.0 + itemsOffsetAfterMove); + name = findItem(contentItem, "textName", i); + QVERIFY(name != 0); + QTRY_COMPARE(name->text(), model.name(i)); + } + + delete canvas; +} + +void tst_QQuickGridView::moveTransitions_data() +{ + QTest::addColumn("initialItemCount"); + QTest::addColumn("contentY"); + QTest::addColumn("itemsOffsetAfterMove"); + QTest::addColumn("moveFrom"); + QTest::addColumn("moveTo"); + QTest::addColumn("moveCount"); + QTest::addColumn("expectedDisplacedIndexes"); + + QTest::newRow("move from above view, outside visible items, move 1") << 30 << 120.0 << 0.0 + << 1 << 10 << 1 << ListRange(6, 10); + QTest::newRow("move from above view, outside visible items, move 1 (first item)") << 30 << 120.0 << 0.0 + << 0 << 10 << 1 << ListRange(6, 10); + QTest::newRow("move from above view, outside visible items, move multiple") << 30 << 120.0 << 60.0 + << 1 << 10 << 3 << ListRange(13, 23); + QTest::newRow("move from above view, mix of visible/non-visible") << 30 << 120.0 << 60.0 + << 1 << 10 << 6 << (ListRange(7, 15) + ListRange(16, 23)); + QTest::newRow("move from above view, mix of visible/non-visible (move first)") << 30 << 120.0 << 120.0 + << 0 << 10 << 6 << ListRange(16, 23); + + QTest::newRow("move within view, move 1 down") << 30 << 0.0 << 0.0 + << 1 << 10 << 1 << ListRange(2, 10); + QTest::newRow("move within view, move 1 down, move first item") << 30 << 0.0 << 0.0 + << 0 << 10 << 1 << ListRange(1, 10); + QTest::newRow("move within view, move 1 down, move first item, contentY not 0") << 30 << 120.0 << 0.0 + << 0+6 << 10+6 << 1 << ListRange(1+6, 10+6); + QTest::newRow("move within view, move 1 down, to last item") << 30 << 0.0 << 0.0 + << 10 << 17 << 1 << ListRange(11, 17); + QTest::newRow("move within view, move first->last") << 30 << 0.0 << 0.0 + << 0 << 17 << 1 << ListRange(1, 17); + + QTest::newRow("move within view, move multiple down") << 30 << 0.0 << 0.0 + << 1 << 10 << 3 << ListRange(4, 12); + QTest::newRow("move within view, move multiple down, move first item") << 30 << 0.0 << 0.0 + << 0 << 10 << 3 << ListRange(3, 12); + QTest::newRow("move within view, move multiple down, move first item, contentY not 0") << 30 << 60.0 << 0.0 + << 0+3 << 10+3 << 3 << ListRange(3+3, 12+3); + QTest::newRow("move within view, move multiple down, displace last item") << 30 << 0.0 << 0.0 + << 5 << 15 << 3 << ListRange(8, 17); + QTest::newRow("move within view, move multiple down, move first->last") << 30 << 0.0 << 0.0 + << 0 << 15 << 3 << ListRange(3, 17); + + QTest::newRow("move within view, move 1 up") << 30 << 0.0 << 0.0 + << 10 << 1 << 1 << ListRange(1, 9); + QTest::newRow("move within view, move 1 up, move to first index") << 30 << 0.0 << 0.0 + << 10 << 0 << 1 << ListRange(0, 9); + QTest::newRow("move within view, move 1 up, move to first index, contentY not 0") << 30 << 120.0 << 0.0 + << 10+6 << 0+6 << 1 << ListRange(0+6, 9+6); + QTest::newRow("move within view, move 1 up, move to first index, contentY not on item border") << 30 << 80.0 << 0.0 + << 10+3 << 0+3 << 1 << ListRange(0+3, 9+3); + QTest::newRow("move within view, move 1 up, move last item") << 30 << 0.0 << 0.0 + << 17 << 10 << 1 << ListRange(10, 16); + QTest::newRow("move within view, move 1 up, move last->first") << 30 << 0.0 << 0.0 + << 17 << 0 << 1 << ListRange(0, 16); + + QTest::newRow("move within view, move multiple up") << 30 << 0.0 << 0.0 + << 10 << 1 << 3 << ListRange(1, 9); + QTest::newRow("move within view, move multiple (> 1 row) up") << 30 << 0.0 << 0.0 + << 10 << 1 << 5 << ListRange(1, 9); + QTest::newRow("move within view, move multiple up, move to first index") << 30 << 0.0 << 0.0 + << 10 << 0 << 3 << ListRange(0, 9); + QTest::newRow("move within view, move multiple up, move to first index, contentY not 0") << 30 << 60.0 << 0.0 + << 10+3 << 0+3 << 3 << ListRange(0+3, 9+3); + QTest::newRow("move within view, move multiple up (> 1 row), move to first index, contentY not on border") << 30 << 80.0 << 0.0 + << 10+3 << 0+3 << 5 << ListRange(0+3, 9+3); + QTest::newRow("move within view, move multiple up, move last item") << 30 << 0.0 << 0.0 + << 15 << 5 << 3 << ListRange(5, 14); + QTest::newRow("move within view, move multiple up, move last->first") << 30 << 0.0 << 0.0 + << 15 << 0 << 3 << ListRange(0, 14); + + QTest::newRow("move from below view, move 1 up") << 30 << 0.0 << 0.0 + << 20 << 5 << 1 << ListRange(5, 17); + QTest::newRow("move from below view, move 1 up, move to top") << 30 << 0.0 << 0.0 + << 20 << 0 << 1 << ListRange(0, 17); + QTest::newRow("move from below view, move 1 up, move to top, contentY not 0") << 30 << 60.0 << 0.0 + << 25 << 3 << 1 << ListRange(0+3, 17+3); + QTest::newRow("move from below view, move multiple (> 1 row) up") << 30 << 0.0 << 0.0 + << 20 << 5 << 5 << ListRange(5, 17); + QTest::newRow("move from below view, move multiple up, move to top") << 30 << 0.0 << 0.0 + << 20 << 0 << 3 << ListRange(0, 17); + QTest::newRow("move from below view, move multiple up, move to top, contentY not 0") << 30 << 60.0 << 0.0 + << 25 << 3 << 3 << ListRange(0+3, 17+3); + + QTest::newRow("move from below view, move 1 up, move to bottom") << 30 << 0.0 << 0.0 + << 20 << 17 << 1 << ListRange(17, 17); + QTest::newRow("move from below view, move 1 up, move to bottom, contentY not 0") << 30 << 60.0 << 0.0 + << 25 << 17+3 << 1 << ListRange(17+3, 17+3); + QTest::newRow("move from below view, move multiple up, move to to bottom") << 30 << 0.0 << 0.0 + << 20 << 17 << 3 << ListRange(17, 17); + QTest::newRow("move from below view, move multiple up, move to bottom, contentY not 0") << 30 << 60.0 << 0.0 + << 25 << 17+3 << 3 << ListRange(17+3, 17+3); +} + +void tst_QQuickGridView::removeTransitions() +{ + QFETCH(int, initialItemCount); + QFETCH(bool, shouldAnimateTargets); + QFETCH(qreal, contentY); + QFETCH(int, removalIndex); + QFETCH(int, removalCount); + QFETCH(ListRange, expectedDisplacedIndexes); + + // added items should end here + QPointF targetItems_transitionTo(-50, -50); + + // displaced items should pass through this points + QPointF displacedItems_transitionVia(100, 100); + + QaimModel model; + for (int i = 0; i < initialItemCount; i++) + model.addItem("Original item" + QString::number(i), ""); + QaimModel model_targetItems_transitionTo; + QaimModel model_displacedItems_transitionVia; + + QQuickView *canvas = createView(); + QDeclarativeContext *ctxt = canvas->rootContext(); + ctxt->setContextProperty("testModel", &model); + ctxt->setContextProperty("model_targetItems_transitionTo", &model_targetItems_transitionTo); + ctxt->setContextProperty("model_displacedItems_transitionVia", &model_displacedItems_transitionVia); + ctxt->setContextProperty("targetItems_transitionTo", targetItems_transitionTo); + ctxt->setContextProperty("displacedItems_transitionVia", displacedItems_transitionVia); + canvas->setSource(testFileUrl("removeTransitions.qml")); + canvas->show(); + + QQuickGridView *gridview = findItem(canvas->rootObject(), "grid"); + QTRY_VERIFY(gridview != 0); + QQuickItem *contentItem = gridview->contentItem(); + QVERIFY(contentItem != 0); + QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false); + + if (contentY != 0) { + gridview->setContentY(contentY); + QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false); + } + + QList > expectedDisplacedValues = expectedDisplacedIndexes.getModelDataValues(model); + + // only target items that are visible should be animated + QList > expectedTargetData; + QList targetIndexes; + if (shouldAnimateTargets) { + for (int i=removalIndex; iheight()) / 60.0)*3) - 1; + if (i >= firstVisibleIndex && i <= lastVisibleIndex) { + expectedTargetData << qMakePair(model.name(i), model.number(i)); + targetIndexes << i; + } + } + QVERIFY(expectedTargetData.count() > 0); + } + + // calculate targetItems and expectedTargets before model changes + QList targetItems = findItems(contentItem, "wrapper", targetIndexes); + QVariantMap expectedTargets; + for (int i=0; icount()); + + if (shouldAnimateTargets || expectedDisplacedIndexes.isValid()) { + QTRY_COMPARE(gridview->property("targetTransitionsDone").toInt(), expectedTargetData.count()); + QTRY_COMPARE(gridview->property("displaceTransitionsDone").toInt(), + expectedDisplacedIndexes.isValid() ? expectedDisplacedIndexes.count() : 0); + + // check the target and displaced items were animated + model_targetItems_transitionTo.matchAgainst(expectedTargetData, "wasn't animated to target 'to' pos", "shouldn't have been animated to target 'to' pos"); + model_displacedItems_transitionVia.matchAgainst(expectedDisplacedValues, "wasn't animated with displaced anim", "shouldn't have been animated with displaced anim"); + + // check attached properties + QCOMPARE(gridview->property("targetTrans_items").toMap(), expectedTargets); + matchIndexLists(gridview->property("targetTrans_targetIndexes").toList(), targetIndexes); + matchItemLists(gridview->property("targetTrans_targetItems").toList(), targetItems); + if (expectedDisplacedIndexes.isValid()) { + // adjust expectedDisplacedIndexes to their final values after the move + QList displacedIndexes = adjustIndexesForRemoveDisplaced(expectedDisplacedIndexes.indexes, removalIndex, removalCount); + matchItemsAndIndexes(gridview->property("displacedTrans_items").toMap(), model, displacedIndexes); + matchIndexLists(gridview->property("displacedTrans_targetIndexes").toList(), targetIndexes); + matchItemLists(gridview->property("displacedTrans_targetItems").toList(), targetItems); + } + } else { + QTRY_COMPARE(model_targetItems_transitionTo.count(), 0); + QTRY_COMPARE(model_displacedItems_transitionVia.count(), 0); + } + + QList items = findItems(contentItem, "wrapper"); + int itemCount = items.count(); + int firstVisibleIndex = -1; + for (int i=0; iy() >= contentY) + firstVisibleIndex = index; + else if (index < 0) + itemCount--; // exclude deleted items + } + QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex)); + + // verify all items moved to the correct final positions + for (int i=firstVisibleIndex; i < model.count() && i < itemCount; ++i) { + QQuickItem *item = findItem(contentItem, "wrapper", i); + QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i))); + QCOMPARE(item->x(), (i%3)*80.0); + QCOMPARE(item->y(), contentY + ((i-firstVisibleIndex)/3) * 60.0); + QQuickText *name = findItem(contentItem, "textName", i); + QVERIFY(name != 0); + QTRY_COMPARE(name->text(), model.name(i)); + } + + delete canvas; +} + +void tst_QQuickGridView::removeTransitions_data() +{ + QTest::addColumn("initialItemCount"); + QTest::addColumn("contentY"); + QTest::addColumn("shouldAnimateTargets"); + QTest::addColumn("removalIndex"); + QTest::addColumn("removalCount"); + QTest::addColumn("expectedDisplacedIndexes"); + + // All items that are visible following the remove operation should be animated. + // Remove targets that are outside of the view should not be animated. + + // For a GridView, removing any number of items other than a full row before the start + // should displace all items in the view + QTest::newRow("remove 1 before start") + << 30 << 120.0 << false + << 2 << 1 << ListRange(6, 24); // 6-24 are displaced + QTest::newRow("remove 1 row, before start") + << 30 << 120.0 << false + << 3 << 3 << ListRange(); + QTest::newRow("remove between 1-2 rows, before start") + << 30 << 120.0 << false + << 0 << 5 << ListRange(6, 25); + QTest::newRow("remove 2 rows, before start") + << 30 << 120.0 << false + << 0 << 6 << ListRange(); + QTest::newRow("remove mix of before and after start") + << 30 << 60.0 << true + << 2 << 3 << ListRange(5, 23); // 5-23 are displaced into view + + + QTest::newRow("remove 1 from start") + << 30 << 0.0 << true + << 0 << 1 << ListRange(1, 18); // 1-18 are displaced into view + QTest::newRow("remove multiple from start") + << 30 << 0.0 << true + << 0 << 3 << ListRange(3, 20); // 3-18 are displaced into view + QTest::newRow("remove 1 from start, content y not 0") + << 30 << 60.0 << true + << 3 << 1 << ListRange(1 + 3, 18 + 3); + QTest::newRow("remove multiple from start, content y not 0") + << 30 << 60.0 << true + << 3 << 3 << ListRange(3 + 3, 20 + 3); + + + QTest::newRow("remove 1 from middle") + << 30 << 0.0 << true + << 5 << 1 << ListRange(6, 18); + QTest::newRow("remove multiple from middle") + << 30 << 0.0 << true + << 5 << 3 << ListRange(8, 20); + + + QTest::newRow("remove 1 from bottom") + << 30 << 0.0 << true + << 17 << 1 << ListRange(18, 18); + QTest::newRow("remove multiple (1 row) from bottom") + << 30 << 0.0 << true + << 15 << 3 << ListRange(18, 20); + QTest::newRow("remove multiple (> 1 row) from bottom") + << 30 << 0.0 << true + << 15 << 5 << ListRange(20, 22); + QTest::newRow("remove 1 from bottom, content y not 0") + << 30 << 60.0 << true + << 17 + 3 << 1 << ListRange(18 + 3, 18 + 3); + QTest::newRow("remove multiple (1 row) from bottom, content y not 0") + << 30 << 60.0 << true + << 15 + 3 << 3 << ListRange(18 + 3, 20 + 3); + + + QTest::newRow("remove 1 after end") + << 30 << 0.0 << false + << 18 << 1 << ListRange(); + QTest::newRow("remove multiple after end") + << 30 << 0.0 << false + << 18 << 3 << ListRange(); +} + +void tst_QQuickGridView::multipleTransitions() +{ + // Tests that if you interrupt a transition in progress with another action that + // cancels the previous transition, the resulting items are still placed correctly. + + QFETCH(int, initialCount); + QFETCH(qreal, contentY); + QFETCH(QList, changes); + + // add transitions on the left, moves on the right + QPointF addTargets_transitionFrom(-50, -50); + QPointF addDisplaced_transitionFrom(-50, 50); + QPointF moveTargets_transitionFrom(50, -50); + QPointF moveDisplaced_transitionFrom(50, 50); + + QmlListModel model; + for (int i = 0; i < initialCount; i++) + model.addItem("Original item" + QString::number(i), ""); + + QQuickView *canvas = createView(); + QDeclarativeContext *ctxt = canvas->rootContext(); + ctxt->setContextProperty("testModel", &model); + ctxt->setContextProperty("addTargets_transitionFrom", addTargets_transitionFrom); + ctxt->setContextProperty("addDisplaced_transitionFrom", addDisplaced_transitionFrom); + ctxt->setContextProperty("moveTargets_transitionFrom", moveTargets_transitionFrom); + ctxt->setContextProperty("moveDisplaced_transitionFrom", moveDisplaced_transitionFrom); + canvas->setSource(testFileUrl("multipleTransitions.qml")); + canvas->show(); + + QQuickGridView *gridview = findItem(canvas->rootObject(), "grid"); + QTRY_VERIFY(gridview != 0); + QQuickItem *contentItem = gridview->contentItem(); + QVERIFY(contentItem != 0); + QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false); + + int timeBetweenActions = canvas->rootObject()->property("timeBetweenActions").toInt(); + + QList > targetItems; + for (int i=0; icount()); + QTRY_VERIFY(gridview->property("runningAddTargets").toBool()); + QTRY_VERIFY(gridview->property("runningAddDisplaced").toBool()); + if (i == changes.count() - 1) { + QTRY_VERIFY(!gridview->property("runningAddTargets").toBool()); + QTRY_VERIFY(!gridview->property("runningAddDisplaced").toBool()); + } else { + QTest::qWait(timeBetweenActions); + } + break; + } + case ListChange::Removed: + for (int j=changes[i].index; jcount()); + QTRY_VERIFY(gridview->property("runningRemoveTargets").toBool()); + QTRY_VERIFY(gridview->property("runningRemoveDisplaced").toBool()); + if (i == changes.count() - 1) { + QTRY_VERIFY(!gridview->property("runningRemoveTargets").toBool()); + QTRY_VERIFY(!gridview->property("runningRemoveDisplaced").toBool()); + } else { + QTest::qWait(timeBetweenActions); + } + break; + case ListChange::Moved: + for (int j=changes[i].index; jproperty("runningMoveTargets").toBool()); + QTRY_VERIFY(gridview->property("runningMoveDisplaced").toBool()); + if (i == changes.count() - 1) { + QTRY_VERIFY(!gridview->property("runningMoveTargets").toBool()); + QTRY_VERIFY(!gridview->property("runningMoveDisplaced").toBool()); + } else { + QTest::qWait(timeBetweenActions); + } + break; + case ListChange::SetCurrent: + gridview->setCurrentIndex(changes[i].index); + QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false); + break; + case ListChange::SetContentY: + gridview->setContentY(changes[i].pos); + QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false); + break; + } + } + QCOMPARE(gridview->count(), model.count()); + + QList items = findItems(contentItem, "wrapper"); + int firstVisibleIndex = -1; + for (int i=0; iy() >= contentY) { + QDeclarativeExpression e(qmlContext(items[i]), items[i], "index"); + firstVisibleIndex = e.evaluate().toInt(); + break; + } + } + QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex)); + + // verify all items moved to the correct final positions + int itemCount = findItems(contentItem, "wrapper").count(); + for (int i=firstVisibleIndex; i < model.count() && i < itemCount; ++i) { + QQuickItem *item = findItem(contentItem, "wrapper", i); + QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i))); + QCOMPARE(item->x(), (i%3)*80.0); + QCOMPARE(item->y(), (i/3)*60.0); + QQuickText *name = findItem(contentItem, "textName", i); + QVERIFY(name != 0); + QTRY_COMPARE(name->text(), model.name(i)); + } + + delete canvas; +} + +void tst_QQuickGridView::multipleTransitions_data() +{ + QTest::addColumn("initialCount"); + QTest::addColumn("contentY"); + QTest::addColumn >("changes"); + + // the added item and displaced items should move to final dest correctly + QTest::newRow("add item, then move it immediately") << 10 << 0.0 << (QList() + << ListChange::insert(0, 1) + << ListChange::move(0, 3, 1) + ); + + // items affected by the add should change from move to add transition + QTest::newRow("move, then insert item before the moved item") << 20 << 0.0 << (QList() + << ListChange::move(1, 10, 3) + << ListChange::insert(0, 1) + ); + + // items should be placed correctly if you trigger a transition then refill for that index + QTest::newRow("add at 0, flick down, flick back to top and add at 0 again") << 20 << 0.0 << (QList() + << ListChange::insert(0, 1) + << ListChange::setContentY(160.0) + << ListChange::setContentY(0.0) + << ListChange::insert(0, 1) + ); +} + void tst_QQuickGridView::cacheBuffer() { QQuickView *canvas = createView(); @@ -4085,6 +5006,56 @@ void tst_QQuickGridView::unrequestedVisibility() delete canvas; } +QList tst_QQuickGridView::toIntList(const QVariantList &list) +{ + QList ret; + bool ok = true; + for (int i=0; i &expectedIndexes) +{ + for (int i=0; i current = indexLists[i].value >().toSet(); + if (current != expectedIndexes.toSet()) + qDebug() << "Cannot match actual targets" << current << "with expected" << expectedIndexes; + QCOMPARE(current, expectedIndexes.toSet()); + } +} + +void tst_QQuickGridView::matchItemsAndIndexes(const QVariantMap &items, const QaimModel &model, const QList &expectedIndexes) +{ + for (QVariantMap::const_iterator it = items.begin(); it != items.end(); ++it) { + QVERIFY(it.value().type() == QVariant::Int); + QString name = it.key(); + int itemIndex = it.value().toInt(); + QVERIFY2(expectedIndexes.contains(itemIndex), QTest::toString(QString("Index %1 not found in expectedIndexes").arg(itemIndex))); + if (model.name(itemIndex) != name) + qDebug() << itemIndex; + QCOMPARE(model.name(itemIndex), name); + } + QCOMPARE(items.count(), expectedIndexes.count()); +} + +void tst_QQuickGridView::matchItemLists(const QVariantList &itemLists, const QList &expectedItems) +{ + for (int i=0; i(current[j].value()); + QVERIFY2(o, QTest::toString(QString("Invalid actual item at %1").arg(j))); + QVERIFY2(expectedItems.contains(o), QTest::toString(QString("Cannot match item %1").arg(j))); + } + QCOMPARE(current.count(), expectedItems.count()); + } +} + QTEST_MAIN(tst_QQuickGridView) #include "tst_qquickgridview.moc" diff --git a/tests/auto/qtquick2/qquicklistview/data/addTransitions.qml b/tests/auto/qtquick2/qquicklistview/data/addTransitions.qml new file mode 100644 index 0000000..ff90ead --- /dev/null +++ b/tests/auto/qtquick2/qquicklistview/data/addTransitions.qml @@ -0,0 +1,134 @@ +import QtQuick 2.0 + +Rectangle { + id: root + width: 500 + height: 600 + + property int duration: 10 + property int count: list.count + + Component { + id: myDelegate + Rectangle { + id: wrapper + + property string nameData: name + + objectName: "wrapper" + height: 20 + width: 240 + Text { text: index } + Text { + x: 30 + id: textName + objectName: "textName" + text: name + } + Text { + x: 200 + text: wrapper.y + } + color: ListView.isCurrentItem ? "lightsteelblue" : "white" + + onXChanged: checkPos() + onYChanged: checkPos() + + function checkPos() { + if (Qt.point(x, y) == targetItems_transitionFrom) + model_targetItems_transitionFrom.addItem(name, "") + if (Qt.point(x, y) == displacedItems_transitionVia) + model_displacedItems_transitionVia.addItem(name, "") + } + } + } + + ListView { + id: list + + property int targetTransitionsDone + property int displaceTransitionsDone + + property var targetTrans_items: new Object() + property var targetTrans_targetIndexes: new Array() + property var targetTrans_targetItems: new Array() + + property var displacedTrans_items: new Object() + property var displacedTrans_targetIndexes: new Array() + property var displacedTrans_targetItems: new Array() + + objectName: "list" + focus: true + anchors.centerIn: parent + width: 240 + height: 320 + model: testModel + delegate: myDelegate + + // for QDeclarativeListProperty types + function copyList(propList) { + var temp = new Array() + for (var i=0; i #include #include -#include #include "../../shared/util.h" #include "../shared/viewtestutil.h" #include "../shared/visualtestutil.h" @@ -171,6 +170,17 @@ private slots: void asynchronous(); void unrequestedVisibility(); + void populateTransitions(); + void populateTransitions_data(); + void addTransitions(); + void addTransitions_data(); + void moveTransitions(); + void moveTransitions_data(); + void removeTransitions(); + void removeTransitions_data(); + void multipleTransitions(); + void multipleTransitions_data(); + private: template void items(const QUrl &source, bool forceLayout); template void changed(const QUrl &source, bool forceLayout); @@ -182,6 +192,11 @@ private: template void clear(const QUrl &source); template void sections(const QUrl &source); + QList toIntList(const QVariantList &list); + void matchIndexLists(const QVariantList &indexLists, const QList &expectedIndexes); + void matchItemsAndIndexes(const QVariantMap &items, const QaimModel &model, const QList &expectedIndexes); + void matchItemLists(const QVariantList &itemLists, const QList &expectedItems); + void inserted_more_data(); void removed_more_data(); void moved_data(); @@ -1356,18 +1371,26 @@ void tst_QQuickListView::multipleChanges() { QList > items; for (int j=changes[i].index; jpolishScheduled, false); break; } case ListChange::Removed: model.removeItems(changes[i].index, changes[i].count); + QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false); break; case ListChange::Moved: model.moveItems(changes[i].index, changes[i].to, changes[i].count); + QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false); break; case ListChange::SetCurrent: listview->setCurrentIndex(changes[i].index); + QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false); + break; + case ListChange::SetContentY: + listview->setContentY(changes[i].pos); + QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false); break; } } @@ -4729,6 +4752,929 @@ void tst_QQuickListView::unrequestedVisibility() delete canvas; } +void tst_QQuickListView::populateTransitions() +{ + QFETCH(bool, staticallyPopulate); + QFETCH(bool, dynamicallyPopulate); + QFETCH(bool, usePopulateTransition); + + QPointF transitionFrom(-50, -50); + QPointF transitionVia(100, 100); + QaimModel model_transitionFrom; + QaimModel model_transitionVia; + + QaimModel model; + if (staticallyPopulate) { + for (int i = 0; i < 30; i++) + model.addItem("item" + QString::number(i), ""); + } + + QQuickView *canvas = createView(); + canvas->rootContext()->setContextProperty("testModel", &model); + canvas->rootContext()->setContextProperty("testObject", new TestObject(canvas->rootContext())); + canvas->rootContext()->setContextProperty("usePopulateTransition", usePopulateTransition); + canvas->rootContext()->setContextProperty("dynamicallyPopulate", dynamicallyPopulate); + canvas->rootContext()->setContextProperty("transitionFrom", transitionFrom); + canvas->rootContext()->setContextProperty("transitionVia", transitionVia); + canvas->rootContext()->setContextProperty("model_transitionFrom", &model_transitionFrom); + canvas->rootContext()->setContextProperty("model_transitionVia", &model_transitionVia); + canvas->setSource(testFileUrl("populateTransitions.qml")); + canvas->show(); + + QQuickListView *listview = findItem(canvas->rootObject(), "list"); + QVERIFY(listview); + QQuickItem *contentItem = listview->contentItem(); + QVERIFY(contentItem); + + if (staticallyPopulate || dynamicallyPopulate) { + // check the populate transition is run + if (usePopulateTransition) { + QTRY_COMPARE(listview->property("countPopulateTransitions").toInt(), 17); + } else { + QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false); + QTRY_COMPARE(listview->property("countPopulateTransitions").toInt(), 0); + } + QTRY_COMPARE(listview->property("countAddTransitions").toInt(), 0); + } else { + QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false); + } + + int itemCount = findItems(contentItem, "wrapper").count(); + if (usePopulateTransition) + QCOMPARE(itemCount, listview->property("countPopulateTransitions").toInt()); + for (int i=0; i < model.count() && i < itemCount; ++i) { + QQuickItem *item = findItem(contentItem, "wrapper", i); + QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i))); + QTRY_COMPARE(item->x(), 0.0); + QTRY_COMPARE(item->y(), i*20.0); + QQuickText *name = findItem(contentItem, "textName", i); + QVERIFY(name != 0); + QTRY_COMPARE(name->text(), model.name(i)); + } + + // add an item and check this is done with add trantion, not populate + model.insertItem(0, "another item", ""); + QTRY_COMPARE(listview->property("countAddTransitions").toInt(), 1); + QTRY_COMPARE(listview->property("countPopulateTransitions").toInt(), + (usePopulateTransition && (staticallyPopulate || dynamicallyPopulate)) ? 17 : 0); + + // clear the model + canvas->rootContext()->setContextProperty("testModel", QVariant()); + QTRY_COMPARE(listview->count(), 0); + QTRY_COMPARE(findItems(contentItem, "wrapper").count(), 0); + listview->setProperty("countPopulateTransitions", 0); + listview->setProperty("countAddTransitions", 0); + + // set to a valid model and check populate transition is run a second time + model.clear(); + for (int i = 0; i < 30; i++) + model.addItem("item" + QString::number(i), ""); + canvas->rootContext()->setContextProperty("testModel", &model); + QTRY_COMPARE(listview->property("countPopulateTransitions").toInt(), usePopulateTransition ? 17 : 0); + QTRY_COMPARE(listview->property("countAddTransitions").toInt(), 0); + + itemCount = findItems(contentItem, "wrapper").count(); + if (usePopulateTransition) + QCOMPARE(itemCount, listview->property("countPopulateTransitions").toInt()); + for (int i=0; i < model.count() && i < itemCount; ++i) { + QQuickItem *item = findItem(contentItem, "wrapper", i); + QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i))); + QTRY_COMPARE(item->x(), 0.0); + QTRY_COMPARE(item->y(), i*20.0); + QQuickText *name = findItem(contentItem, "textName", i); + QVERIFY(name != 0); + QTRY_COMPARE(name->text(), model.name(i)); + } + + // reset model and check populate transition is run again + listview->setProperty("countPopulateTransitions", 0); + listview->setProperty("countAddTransitions", 0); + model.reset(); + QTRY_COMPARE(listview->property("countPopulateTransitions").toInt(), usePopulateTransition ? 17 : 0); + QTRY_COMPARE(listview->property("countAddTransitions").toInt(), 0); + + itemCount = findItems(contentItem, "wrapper").count(); + if (usePopulateTransition) + QCOMPARE(itemCount, listview->property("countPopulateTransitions").toInt()); + for (int i=0; i < model.count() && i < itemCount; ++i) { + QQuickItem *item = findItem(contentItem, "wrapper", i); + QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i))); + QTRY_COMPARE(item->x(), 0.0); + QTRY_COMPARE(item->y(), i*20.0); + QQuickText *name = findItem(contentItem, "textName", i); + QVERIFY(name != 0); + QTRY_COMPARE(name->text(), model.name(i)); + } + + delete canvas; +} + +void tst_QQuickListView::populateTransitions_data() +{ + QTest::addColumn("staticallyPopulate"); + QTest::addColumn("dynamicallyPopulate"); + QTest::addColumn("usePopulateTransition"); + + QTest::newRow("static") << true << false << true; + QTest::newRow("static, no populate") << true << false << false; + + QTest::newRow("dynamic") << false << true << true; + QTest::newRow("dynamic, no populate") << false << true << false; + + QTest::newRow("empty to start with") << false << false << true; + QTest::newRow("empty to start with, no populate") << false << false << false; +} + +void tst_QQuickListView::addTransitions() +{ + QFETCH(int, initialItemCount); + QFETCH(bool, shouldAnimateTargets); + QFETCH(qreal, contentY); + QFETCH(int, insertionIndex); + QFETCH(int, insertionCount); + QFETCH(ListRange, expectedDisplacedIndexes); + + // added items should start here + QPointF targetItems_transitionFrom(-50, -50); + + // displaced items should pass through this point + QPointF displacedItems_transitionVia(100, 100); + + QaimModel model; + for (int i = 0; i < initialItemCount; i++) + model.addItem("Original item" + QString::number(i), ""); + QaimModel model_targetItems_transitionFrom; + QaimModel model_displacedItems_transitionVia; + + QQuickView *canvas = createView(); + QDeclarativeContext *ctxt = canvas->rootContext(); + TestObject *testObject = new TestObject; + ctxt->setContextProperty("testModel", &model); + ctxt->setContextProperty("model_targetItems_transitionFrom", &model_targetItems_transitionFrom); + ctxt->setContextProperty("model_displacedItems_transitionVia", &model_displacedItems_transitionVia); + ctxt->setContextProperty("targetItems_transitionFrom", targetItems_transitionFrom); + ctxt->setContextProperty("displacedItems_transitionVia", displacedItems_transitionVia); + ctxt->setContextProperty("testObject", testObject); + canvas->setSource(testFileUrl("addTransitions.qml")); + canvas->show(); + + QQuickListView *listview = findItem(canvas->rootObject(), "list"); + QTRY_VERIFY(listview != 0); + QQuickItem *contentItem = listview->contentItem(); + QVERIFY(contentItem != 0); + QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false); + + if (contentY != 0) { + listview->setContentY(contentY); + QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false); + } + + QList > expectedDisplacedValues = expectedDisplacedIndexes.getModelDataValues(model); + + // only target items that will become visible should be animated + QList > newData; + QList > expectedTargetData; + QList targetIndexes; + if (shouldAnimateTargets) { + for (int i=insertionIndex; i= contentY / 20 && i < (contentY + listview->height()) / 20) { // only grab visible items + expectedTargetData << newData.last(); + targetIndexes << i; + } + } + QVERIFY(expectedTargetData.count() > 0); + } + + // start animation + if (!newData.isEmpty()) { + model.insertItems(insertionIndex, newData); + QTRY_COMPARE(model.count(), listview->count()); + } + + QList targetItems = findItems(contentItem, "wrapper", targetIndexes); + + if (shouldAnimateTargets) { + QTRY_COMPARE(listview->property("targetTransitionsDone").toInt(), expectedTargetData.count()); + QTRY_COMPARE(listview->property("displaceTransitionsDone").toInt(), + expectedDisplacedIndexes.isValid() ? expectedDisplacedIndexes.count() : 0); + + // check the target and displaced items were animated + model_targetItems_transitionFrom.matchAgainst(expectedTargetData, "wasn't animated from target 'from' pos", "shouldn't have been animated from target 'from' pos"); + model_displacedItems_transitionVia.matchAgainst(expectedDisplacedValues, "wasn't animated with displaced anim", "shouldn't have been animated with displaced anim"); + + // check attached properties + matchItemsAndIndexes(listview->property("targetTrans_items").toMap(), model, targetIndexes); + matchIndexLists(listview->property("targetTrans_targetIndexes").toList(), targetIndexes); + matchItemLists(listview->property("targetTrans_targetItems").toList(), targetItems); + if (expectedDisplacedIndexes.isValid()) { + // adjust expectedDisplacedIndexes to their final values after the move + QList displacedIndexes = adjustIndexesForAddDisplaced(expectedDisplacedIndexes.indexes, insertionIndex, insertionCount); + matchItemsAndIndexes(listview->property("displacedTrans_items").toMap(), model, displacedIndexes); + matchIndexLists(listview->property("displacedTrans_targetIndexes").toList(), targetIndexes); + matchItemLists(listview->property("displacedTrans_targetItems").toList(), targetItems); + } + + } else { + QTRY_COMPARE(model_targetItems_transitionFrom.count(), 0); + QTRY_COMPARE(model_displacedItems_transitionVia.count(), 0); + } + + QList items = findItems(contentItem, "wrapper"); + int firstVisibleIndex = -1; + int itemCount = items.count(); + for (int i=0; iy() >= contentY) { + QDeclarativeExpression e(qmlContext(items[i]), items[i], "index"); + firstVisibleIndex = e.evaluate().toInt(); + break; + } + } + QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex)); + + // verify all items moved to the correct final positions + for (int i=firstVisibleIndex; i < model.count() && i < itemCount; ++i) { + QQuickItem *item = findItem(contentItem, "wrapper", i); + QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i))); + QTRY_COMPARE(item->y(), i*20.0); + QQuickText *name = findItem(contentItem, "textName", i); + QVERIFY(name != 0); + QTRY_COMPARE(name->text(), model.name(i)); + } + + delete canvas; + delete testObject; +} + +void tst_QQuickListView::addTransitions_data() +{ + QTest::addColumn("initialItemCount"); + QTest::addColumn("contentY"); + QTest::addColumn("shouldAnimateTargets"); + QTest::addColumn("insertionIndex"); + QTest::addColumn("insertionCount"); + QTest::addColumn("expectedDisplacedIndexes"); + + // if inserting before visible index, items should not appear or animate in, even if there are > 1 new items + QTest::newRow("insert 1, just before start") + << 30 << 20.0 << false + << 0 << 1 << ListRange(); + QTest::newRow("insert 1, way before start") + << 30 << 20.0 << false + << 0 << 1 << ListRange(); + QTest::newRow("insert multiple, just before start") + << 30 << 100.0 << false + << 0 << 3 << ListRange(); + QTest::newRow("insert multiple, way before start") + << 30 << 100.0 << false + << 0 << 3 << ListRange(); + + QTest::newRow("insert 1 at start") + << 30 << 0.0 << true + << 0 << 1 << ListRange(0, 15); + QTest::newRow("insert multiple at start") + << 30 << 0.0 << true + << 0 << 3 << ListRange(0, 15); + QTest::newRow("insert 1 at start, content y not 0") + << 30 << 40.0 << true // first visible is index 2, so translate the displaced indexes by 2 + << 2 << 1 << ListRange(0 + 2, 15 + 2); + QTest::newRow("insert multiple at start, content y not 0") + << 30 << 40.0 << true // first visible is index 2 + << 2 << 3 << ListRange(0 + 2, 15 + 2); + + QTest::newRow("insert 1 at start, to empty list") + << 0 << 0.0 << true + << 0 << 1 << ListRange(); + QTest::newRow("insert multiple at start, to empty list") + << 0 << 0.0 << true + << 0 << 3 << ListRange(); + + QTest::newRow("insert 1 at middle") + << 30 << 0.0 << true + << 5 << 1 << ListRange(5, 15); + QTest::newRow("insert multiple at middle") + << 30 << 0.0 << true + << 5 << 3 << ListRange(5, 15); + + QTest::newRow("insert 1 at bottom") + << 30 << 0.0 << true + << 15 << 1 << ListRange(15, 15); + QTest::newRow("insert multiple at bottom") + << 30 << 0.0 << true + << 15 << 3 << ListRange(15, 15); + QTest::newRow("insert 1 at bottom, content y not 0") + << 30 << 20.0 * 3 << true + << 15 + 3 << 1 << ListRange(15 + 3, 15 + 3); + QTest::newRow("insert multiple at bottom, content y not 0") + << 30 << 20.0 * 3 << true + << 15 + 3 << 3 << ListRange(15 + 3, 15 + 3); + + // items added after the last visible will not be animated in, since they + // do not appear in the final view + QTest::newRow("insert 1 after end") + << 30 << 0.0 << false + << 17 << 1 << ListRange(); + QTest::newRow("insert multiple after end") + << 30 << 0.0 << false + << 17 << 3 << ListRange(); +} + +void tst_QQuickListView::moveTransitions() +{ + QFETCH(int, initialItemCount); + QFETCH(qreal, contentY); + QFETCH(qreal, itemsOffsetAfterMove); + QFETCH(int, moveFrom); + QFETCH(int, moveTo); + QFETCH(int, moveCount); + QFETCH(ListRange, expectedDisplacedIndexes); + + // target and displaced items should pass through these points + QPointF targetItems_transitionVia(-50, 50); + QPointF displacedItems_transitionVia(100, 100); + + QaimModel model; + for (int i = 0; i < initialItemCount; i++) + model.addItem("Original item" + QString::number(i), ""); + QaimModel model_targetItems_transitionVia; + QaimModel model_displacedItems_transitionVia; + + QQuickView *canvas = createView(); + QDeclarativeContext *ctxt = canvas->rootContext(); + TestObject *testObject = new TestObject; + ctxt->setContextProperty("testModel", &model); + ctxt->setContextProperty("model_targetItems_transitionVia", &model_targetItems_transitionVia); + ctxt->setContextProperty("model_displacedItems_transitionVia", &model_displacedItems_transitionVia); + ctxt->setContextProperty("targetItems_transitionVia", targetItems_transitionVia); + ctxt->setContextProperty("displacedItems_transitionVia", displacedItems_transitionVia); + ctxt->setContextProperty("testObject", testObject); + canvas->setSource(testFileUrl("moveTransitions.qml")); + canvas->show(); + + QQuickListView *listview = findItem(canvas->rootObject(), "list"); + QTRY_VERIFY(listview != 0); + QQuickItem *contentItem = listview->contentItem(); + QVERIFY(contentItem != 0); + QQuickText *name; + + if (contentY != 0) { + listview->setContentY(contentY); + QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false); + } + + QList > expectedDisplacedValues = expectedDisplacedIndexes.getModelDataValues(model); + + // Items moving to *or* from visible positions should be animated. + // Otherwise, they should not be animated. + QList > expectedTargetData; + QList targetIndexes; + for (int i=moveFrom; iheight()) / 20 + || toIndex < (contentY + listview->height()) / 20) { + expectedTargetData << qMakePair(model.name(i), model.number(i)); + targetIndexes << i; + } + } + // ViewTransition.index provides the indices that items are moving to, not from + targetIndexes = adjustIndexesForMove(targetIndexes, moveFrom, moveTo, moveCount); + + // start animation + model.moveItems(moveFrom, moveTo, moveCount); + + QTRY_COMPARE(listview->property("targetTransitionsDone").toInt(), expectedTargetData.count()); + QTRY_COMPARE(listview->property("displaceTransitionsDone").toInt(), + expectedDisplacedIndexes.isValid() ? expectedDisplacedIndexes.count() : 0); + + QList targetItems = findItems(contentItem, "wrapper", targetIndexes); + + // check the target and displaced items were animated + model_targetItems_transitionVia.matchAgainst(expectedTargetData, "wasn't animated from target 'from' pos", "shouldn't have been animated from target 'from' pos"); + model_displacedItems_transitionVia.matchAgainst(expectedDisplacedValues, "wasn't animated with displaced anim", "shouldn't have been animated with displaced anim"); + + // check attached properties + matchItemsAndIndexes(listview->property("targetTrans_items").toMap(), model, targetIndexes); + matchIndexLists(listview->property("targetTrans_targetIndexes").toList(), targetIndexes); + matchItemLists(listview->property("targetTrans_targetItems").toList(), targetItems); + if (expectedDisplacedIndexes.isValid()) { + // adjust expectedDisplacedIndexes to their final values after the move + QList displacedIndexes = adjustIndexesForMove(expectedDisplacedIndexes.indexes, moveFrom, moveTo, moveCount); + matchItemsAndIndexes(listview->property("displacedTrans_items").toMap(), model, displacedIndexes); + matchIndexLists(listview->property("displacedTrans_targetIndexes").toList(), targetIndexes); + matchItemLists(listview->property("displacedTrans_targetItems").toList(), targetItems); + } + + QList items = findItems(contentItem, "wrapper"); + int firstVisibleIndex = -1; + for (int i=0; iy() >= contentY) { + QDeclarativeExpression e(qmlContext(items[i]), items[i], "index"); + firstVisibleIndex = e.evaluate().toInt(); + break; + } + } + QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex)); + + // verify all items moved to the correct final positions + int itemCount = findItems(contentItem, "wrapper").count(); + for (int i=firstVisibleIndex; i < model.count() && i < itemCount; ++i) { + QQuickItem *item = findItem(contentItem, "wrapper", i); + QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i))); + QTRY_COMPARE(item->y(), i*20.0 + itemsOffsetAfterMove); + name = findItem(contentItem, "textName", i); + QVERIFY(name != 0); + QTRY_COMPARE(name->text(), model.name(i)); + } + + delete canvas; + delete testObject; +} + +void tst_QQuickListView::moveTransitions_data() +{ + QTest::addColumn("initialItemCount"); + QTest::addColumn("contentY"); + QTest::addColumn("itemsOffsetAfterMove"); + QTest::addColumn("moveFrom"); + QTest::addColumn("moveTo"); + QTest::addColumn("moveCount"); + QTest::addColumn("expectedDisplacedIndexes"); + + // when removing from above the visible, all items shift down depending on how many + // items have been removed from above the visible + QTest::newRow("move from above view, outside visible items, move 1") << 30 << 4*20.0 << 20.0 + << 1 << 10 << 1 << ListRange(11, 15+4); + QTest::newRow("move from above view, outside visible items, move 1 (first item)") << 30 << 4*20.0 << 20.0 + << 0 << 10 << 1 << ListRange(11, 15+4); + QTest::newRow("move from above view, outside visible items, move multiple") << 30 << 4*20.0 << 2*20.0 + << 1 << 10 << 2 << ListRange(12, 15+4); + QTest::newRow("move from above view, outside visible items, move multiple (first item)") << 30 << 4*20.0 << 3*20.0 + << 0 << 10 << 3 << ListRange(13, 15+4); + QTest::newRow("move from above view, mix of visible/non-visible") << 30 << 4*20.0 << 3*20.0 + << 1 << 10 << 5 << ListRange(6, 14) + ListRange(15, 15+4); + QTest::newRow("move from above view, mix of visible/non-visible (move first)") << 30 << 4*20.0 << 4*20.0 + << 0 << 10 << 5 << ListRange(5, 14) + ListRange(15, 15+4); + + QTest::newRow("move within view, move 1 down") << 30 << 0.0 << 0.0 + << 1 << 10 << 1 << ListRange(2, 10); + QTest::newRow("move within view, move 1 down, move first item") << 30 << 0.0 << 0.0 + << 0 << 10 << 1 << ListRange(1, 10); + QTest::newRow("move within view, move 1 down, move first item, contentY not 0") << 30 << 4*20.0 << 0.0 + << 0+4 << 10+4 << 1 << ListRange(1+4, 10+4); + QTest::newRow("move within view, move 1 down, to last item") << 30 << 0.0 << 0.0 + << 10 << 15 << 1 << ListRange(11, 15); + QTest::newRow("move within view, move first->last") << 30 << 0.0 << 0.0 + << 0 << 15 << 1 << ListRange(1, 15); + + QTest::newRow("move within view, move multiple down") << 30 << 0.0 << 0.0 + << 1 << 10 << 3 << ListRange(4, 12); + QTest::newRow("move within view, move multiple down, move first item") << 30 << 0.0 << 0.0 + << 0 << 10 << 3 << ListRange(3, 12); + QTest::newRow("move within view, move multiple down, move first item, contentY not 0") << 30 << 4*20.0 << 0.0 + << 0+4 << 10+4 << 3 << ListRange(3+4, 12+4); + QTest::newRow("move within view, move multiple down, displace last item") << 30 << 0.0 << 0.0 + << 5 << 13 << 3 << ListRange(8, 15); + QTest::newRow("move within view, move multiple down, move first->last") << 30 << 0.0 << 0.0 + << 0 << 13 << 3 << ListRange(3, 15); + + QTest::newRow("move within view, move 1 up") << 30 << 0.0 << 0.0 + << 10 << 1 << 1 << ListRange(1, 9); + QTest::newRow("move within view, move 1 up, move to first index") << 30 << 0.0 << 0.0 + << 10 << 0 << 1 << ListRange(0, 9); + QTest::newRow("move within view, move 1 up, move to first index, contentY not 0") << 30 << 4*20.0 << 0.0 + << 10+4 << 0+4 << 1 << ListRange(0+4, 9+4); + QTest::newRow("move within view, move 1 up, move to first index, contentY not on item border") << 30 << 4*20.0 - 10 << 0.0 + << 10+4 << 0+4 << 1 << ListRange(0+4, 9+4); + QTest::newRow("move within view, move 1 up, move last item") << 30 << 0.0 << 0.0 + << 15 << 10 << 1 << ListRange(10, 14); + QTest::newRow("move within view, move 1 up, move last->first") << 30 << 0.0 << 0.0 + << 15 << 0 << 1 << ListRange(0, 14); + + QTest::newRow("move within view, move multiple up") << 30 << 0.0 << 0.0 + << 10 << 1 << 3 << ListRange(1, 9); + QTest::newRow("move within view, move multiple up, move to first index") << 30 << 0.0 << 0.0 + << 10 << 0 << 3 << ListRange(0, 9); + QTest::newRow("move within view, move multiple up, move to first index, contentY not 0") << 30 << 4*20.0 << 0.0 + << 10+4 << 0+4 << 3 << ListRange(0+4, 9+4); + QTest::newRow("move within view, move multiple up, move last item") << 30 << 0.0 << 0.0 + << 13 << 5 << 3 << ListRange(5, 12); + QTest::newRow("move within view, move multiple up, move last->first") << 30 << 0.0 << 0.0 + << 13 << 0 << 3 << ListRange(0, 12); + + QTest::newRow("move from below view, move 1 up, move to top") << 30 << 0.0 << 0.0 + << 20 << 0 << 1 << ListRange(0, 15); + QTest::newRow("move from below view, move 1 up, move to top, contentY not 0") << 30 << 4*20.0 << 0.0 + << 25 << 4 << 1 << ListRange(0+4, 15+4); + QTest::newRow("move from below view, move multiple up, move to top") << 30 << 0.0 << 0.0 + << 20 << 0 << 3 << ListRange(0, 15); + QTest::newRow("move from below view, move multiple up, move to top, contentY not 0") << 30 << 4*20.0 << 0.0 + << 25 << 4 << 3 << ListRange(0+4, 15+4); + + QTest::newRow("move from below view, move 1 up, move to bottom") << 30 << 0.0 << 0.0 + << 20 << 15 << 1 << ListRange(15, 15); + QTest::newRow("move from below view, move 1 up, move to bottom, contentY not 0") << 30 << 4*20.0 << 0.0 + << 25 << 15+4 << 1 << ListRange(15+4, 15+4); + QTest::newRow("move from below view, move multiple up, move to to bottom") << 30 << 0.0 << 0.0 + << 20 << 15 << 3 << ListRange(15, 15); + QTest::newRow("move from below view, move multiple up, move to bottom, contentY not 0") << 30 << 4*20.0 << 0.0 + << 25 << 15+4 << 3 << ListRange(15+4, 15+4); +} + +void tst_QQuickListView::removeTransitions() +{ + QFETCH(int, initialItemCount); + QFETCH(bool, shouldAnimateTargets); + QFETCH(qreal, contentY); + QFETCH(int, removalIndex); + QFETCH(int, removalCount); + QFETCH(ListRange, expectedDisplacedIndexes); + + // added items should end here + QPointF targetItems_transitionTo(-50, -50); + + // displaced items should pass through this points + QPointF displacedItems_transitionVia(100, 100); + + QaimModel model; + for (int i = 0; i < initialItemCount; i++) + model.addItem("Original item" + QString::number(i), ""); + QaimModel model_targetItems_transitionTo; + QaimModel model_displacedItems_transitionVia; + + QQuickView *canvas = createView(); + QDeclarativeContext *ctxt = canvas->rootContext(); + TestObject *testObject = new TestObject; + ctxt->setContextProperty("testModel", &model); + ctxt->setContextProperty("model_targetItems_transitionTo", &model_targetItems_transitionTo); + ctxt->setContextProperty("model_displacedItems_transitionVia", &model_displacedItems_transitionVia); + ctxt->setContextProperty("targetItems_transitionTo", targetItems_transitionTo); + ctxt->setContextProperty("displacedItems_transitionVia", displacedItems_transitionVia); + ctxt->setContextProperty("testObject", testObject); + canvas->setSource(testFileUrl("removeTransitions.qml")); + canvas->show(); + + QQuickListView *listview = findItem(canvas->rootObject(), "list"); + QTRY_VERIFY(listview != 0); + QQuickItem *contentItem = listview->contentItem(); + QVERIFY(contentItem != 0); + QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false); + + if (contentY != 0) { + listview->setContentY(contentY); + QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false); + } + + QList > expectedDisplacedValues = expectedDisplacedIndexes.getModelDataValues(model); + + // only target items that are visible should be animated + QList > expectedTargetData; + QList targetIndexes; + if (shouldAnimateTargets) { + for (int i=removalIndex; i= contentY / 20 && i < (contentY + listview->height()) / 20) { + expectedTargetData << qMakePair(model.name(i), model.number(i)); + targetIndexes << i; + } + } + QVERIFY(expectedTargetData.count() > 0); + } + + // calculate targetItems and expectedTargets before model changes + QList targetItems = findItems(contentItem, "wrapper", targetIndexes); + QVariantMap expectedTargets; + for (int i=0; icount()); + + if (shouldAnimateTargets) { + QTRY_COMPARE(listview->property("targetTransitionsDone").toInt(), expectedTargetData.count()); + QTRY_COMPARE(listview->property("displaceTransitionsDone").toInt(), + expectedDisplacedIndexes.isValid() ? expectedDisplacedIndexes.count() : 0); + + // check the target and displaced items were animated + model_targetItems_transitionTo.matchAgainst(expectedTargetData, "wasn't animated to target 'to' pos", "shouldn't have been animated to target 'to' pos"); + model_displacedItems_transitionVia.matchAgainst(expectedDisplacedValues, "wasn't animated with displaced anim", "shouldn't have been animated with displaced anim"); + + // check attached properties + QCOMPARE(listview->property("targetTrans_items").toMap(), expectedTargets); + matchIndexLists(listview->property("targetTrans_targetIndexes").toList(), targetIndexes); + matchItemLists(listview->property("targetTrans_targetItems").toList(), targetItems); + if (expectedDisplacedIndexes.isValid()) { + // adjust expectedDisplacedIndexes to their final values after the move + QList displacedIndexes = adjustIndexesForRemoveDisplaced(expectedDisplacedIndexes.indexes, removalIndex, removalCount); + matchItemsAndIndexes(listview->property("displacedTrans_items").toMap(), model, displacedIndexes); + matchIndexLists(listview->property("displacedTrans_targetIndexes").toList(), targetIndexes); + matchItemLists(listview->property("displacedTrans_targetItems").toList(), targetItems); + } + } else { + QTRY_COMPARE(model_targetItems_transitionTo.count(), 0); + QTRY_COMPARE(model_displacedItems_transitionVia.count(), 0); + } + + QList items = findItems(contentItem, "wrapper"); + int firstVisibleIndex = -1; + int itemCount = items.count(); + + for (int i=0; iy() >= contentY) + firstVisibleIndex = index; + if (index < 0) + itemCount--; // exclude deleted items + } + QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex)); + + // verify all items moved to the correct final positions + for (int i=firstVisibleIndex; i < model.count() && i < itemCount; ++i) { + QQuickItem *item = findItem(contentItem, "wrapper", i); + QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i))); + QCOMPARE(item->x(), 0.0); + QCOMPARE(item->y(), contentY + (i-firstVisibleIndex) * 20.0); + QQuickText *name = findItem(contentItem, "textName", i); + QVERIFY(name != 0); + QTRY_COMPARE(name->text(), model.name(i)); + } + + delete canvas; + delete testObject; +} + +void tst_QQuickListView::removeTransitions_data() +{ + QTest::addColumn("initialItemCount"); + QTest::addColumn("contentY"); + QTest::addColumn("shouldAnimateTargets"); + QTest::addColumn("removalIndex"); + QTest::addColumn("removalCount"); + QTest::addColumn("expectedDisplacedIndexes"); + + // All items that are visible following the remove operation should be animated. + // Remove targets that are outside of the view should not be animated. + + QTest::newRow("remove 1 before start") + << 30 << 20.0 * 3 << false + << 2 << 1 << ListRange(); + QTest::newRow("remove multiple, all before start") + << 30 << 20.0 * 3 << false + << 0 << 3 << ListRange(); + QTest::newRow("remove mix of before and after start") + << 30 << 20.0 * 3 << true + << 2 << 3 << ListRange(5, 20); // 5-20 are visible after the remove + + QTest::newRow("remove 1 from start") + << 30 << 0.0 << true + << 0 << 1 << ListRange(1, 16); // 1-16 are visible after the remove + QTest::newRow("remove multiple from start") + << 30 << 0.0 << true + << 0 << 3 << ListRange(3, 18); // 3-18 are visible after the remove + QTest::newRow("remove 1 from start, content y not 0") + << 30 << 20.0 * 2 << true // first visible is index 2, so translate the displaced indexes by 2 + << 2 << 1 << ListRange(1 + 2, 16 + 2); + QTest::newRow("remove multiple from start, content y not 0") + << 30 << 20.0 * 2 << true // first visible is index 2 + << 2 << 3 << ListRange(3 + 2, 18 + 2); + + QTest::newRow("remove 1 from middle") + << 30 << 0.0 << true + << 5 << 1 << ListRange(6, 16); + QTest::newRow("remove multiple from middle") + << 30 << 0.0 << true + << 5 << 3 << ListRange(8, 18); + + + QTest::newRow("remove 1 from bottom") + << 30 << 0.0 << true + << 15 << 1 << ListRange(16, 16); + + // remove 15, 16, 17 + // 15 will animate as the target item, 16 & 17 won't be animated since they are outside + // the view, and 18 will be animated as the displaced item to replace the last item + QTest::newRow("remove multiple from bottom") + << 30 << 0.0 << true + << 15 << 3 << ListRange(18, 18); + + QTest::newRow("remove 1 from bottom, content y not 0") + << 30 << 20.0 * 2 << true + << 15 + 2 << 1 << ListRange(16 + 2, 16 + 2); + QTest::newRow("remove multiple from bottom, content y not 0") + << 30 << 20.0 * 2 << true + << 15 + 2 << 3 << ListRange(18 + 2, 18 + 2); + + + QTest::newRow("remove 1 after end") + << 30 << 0.0 << false + << 17 << 1 << ListRange(); + QTest::newRow("remove multiple after end") + << 30 << 0.0 << false + << 17 << 3 << ListRange(); +} + +void tst_QQuickListView::multipleTransitions() +{ + // Tests that if you interrupt a transition in progress with another action that + // cancels the previous transition, the resulting items are still placed correctly. + + QFETCH(int, initialCount); + QFETCH(qreal, contentY); + QFETCH(QList, changes); + + // add transitions on the left, moves on the right + QPointF addTargets_transitionFrom(-50, -50); + QPointF addDisplaced_transitionFrom(-50, 50); + QPointF moveTargets_transitionFrom(50, -50); + QPointF moveDisplaced_transitionFrom(50, 50); + + QmlListModel model; + for (int i = 0; i < initialCount; i++) + model.addItem("Original item" + QString::number(i), ""); + + QQuickView *canvas = createView(); + QDeclarativeContext *ctxt = canvas->rootContext(); + TestObject *testObject = new TestObject; + ctxt->setContextProperty("testModel", &model); + ctxt->setContextProperty("testObject", testObject); + ctxt->setContextProperty("addTargets_transitionFrom", addTargets_transitionFrom); + ctxt->setContextProperty("addDisplaced_transitionFrom", addDisplaced_transitionFrom); + ctxt->setContextProperty("moveTargets_transitionFrom", moveTargets_transitionFrom); + ctxt->setContextProperty("moveDisplaced_transitionFrom", moveDisplaced_transitionFrom); + canvas->setSource(testFileUrl("multipleTransitions.qml")); + canvas->show(); + + QQuickListView *listview = findItem(canvas->rootObject(), "list"); + QTRY_VERIFY(listview != 0); + QQuickItem *contentItem = listview->contentItem(); + QVERIFY(contentItem != 0); + QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false); + + int timeBetweenActions = canvas->rootObject()->property("timeBetweenActions").toInt(); + + QList > targetItems; + for (int i=0; icount()); + QTRY_VERIFY(listview->property("runningAddTargets").toBool()); + QTRY_VERIFY(listview->property("runningAddDisplaced").toBool()); + if (i == changes.count() - 1) { + QTRY_VERIFY(!listview->property("runningAddTargets").toBool()); + QTRY_VERIFY(!listview->property("runningAddDisplaced").toBool()); + } else { + QTest::qWait(timeBetweenActions); + } + break; + } + case ListChange::Removed: + for (int j=changes[i].index; jcount()); + QTRY_VERIFY(listview->property("runningRemoveTargets").toBool()); + QTRY_VERIFY(listview->property("runningRemoveDisplaced").toBool()); + if (i == changes.count() - 1) { + QTRY_VERIFY(!listview->property("runningRemoveTargets").toBool()); + QTRY_VERIFY(!listview->property("runningRemoveDisplaced").toBool()); + } else { + QTest::qWait(timeBetweenActions); + } + break; + case ListChange::Moved: + for (int j=changes[i].index; jproperty("runningMoveTargets").toBool()); + QTRY_VERIFY(listview->property("runningMoveDisplaced").toBool()); + if (i == changes.count() - 1) { + QTRY_VERIFY(!listview->property("runningMoveTargets").toBool()); + QTRY_VERIFY(!listview->property("runningMoveDisplaced").toBool()); + } else { + QTest::qWait(timeBetweenActions); + } + break; + case ListChange::SetCurrent: + listview->setCurrentIndex(changes[i].index); + break; + case ListChange::SetContentY: + listview->setContentY(changes[i].pos); + QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false); + break; + } + } + QCOMPARE(listview->count(), model.count()); + + QList items = findItems(contentItem, "wrapper"); + int firstVisibleIndex = -1; + for (int i=0; iy() >= contentY) { + QDeclarativeExpression e(qmlContext(items[i]), items[i], "index"); + firstVisibleIndex = e.evaluate().toInt(); + break; + } + } + QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex)); + + // verify all items moved to the correct final positions + int itemCount = findItems(contentItem, "wrapper").count(); + for (int i=firstVisibleIndex; i < model.count() && i < itemCount; ++i) { + QQuickItem *item = findItem(contentItem, "wrapper", i); + QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i))); + QTRY_COMPARE(item->x(), 0.0); + QTRY_COMPARE(item->y(), i*20.0); + QQuickText *name = findItem(contentItem, "textName", i); + QVERIFY(name != 0); + QTRY_COMPARE(name->text(), model.name(i)); + } + + delete canvas; + delete testObject; +} + +void tst_QQuickListView::multipleTransitions_data() +{ + QTest::addColumn("initialCount"); + QTest::addColumn("contentY"); + QTest::addColumn >("changes"); + + // the added item and displaced items should move to final dest correctly + QTest::newRow("add item, then move it immediately") << 10 << 0.0 << (QList() + << ListChange::insert(0, 1) + << ListChange::move(0, 3, 1) + ); + + // items affected by the add should change from move to add transition + QTest::newRow("move, then insert item before the moved item") << 20 << 0.0 << (QList() + << ListChange::move(1, 10, 3) + << ListChange::insert(0, 1) + ); + + // items should be placed correctly if you trigger a transition then refill for that index + QTest::newRow("add at 0, flick down, flick back to top and add at 0 again") << 20 << 0.0 << (QList() + << ListChange::insert(0, 1) + << ListChange::setContentY(80.0) + << ListChange::setContentY(0.0) + << ListChange::insert(0, 1) + ); +} + +QList tst_QQuickListView::toIntList(const QVariantList &list) +{ + QList ret; + bool ok = true; + for (int i=0; i &expectedIndexes) +{ + for (int i=0; i current = indexLists[i].value >().toSet(); + if (current != expectedIndexes.toSet()) + qDebug() << "Cannot match actual targets" << current << "with expected" << expectedIndexes; + QCOMPARE(current, expectedIndexes.toSet()); + } +} + +void tst_QQuickListView::matchItemsAndIndexes(const QVariantMap &items, const QaimModel &model, const QList &expectedIndexes) +{ + for (QVariantMap::const_iterator it = items.begin(); it != items.end(); ++it) { + QVERIFY(it.value().type() == QVariant::Int); + QString name = it.key(); + int itemIndex = it.value().toInt(); + QVERIFY2(expectedIndexes.contains(itemIndex), QTest::toString(QString("Index %1 not found in expectedIndexes").arg(itemIndex))); + if (model.name(itemIndex) != name) + qDebug() << itemIndex; + QCOMPARE(model.name(itemIndex), name); + } + QCOMPARE(items.count(), expectedIndexes.count()); +} + +void tst_QQuickListView::matchItemLists(const QVariantList &itemLists, const QList &expectedItems) +{ + for (int i=0; i(current[j].value()); + QVERIFY2(o, QTest::toString(QString("Invalid actual item at %1").arg(j))); + QVERIFY2(expectedItems.contains(o), QTest::toString(QString("Cannot match item %1").arg(j))); + } + QCOMPARE(current.count(), expectedItems.count()); + } +} + QTEST_MAIN(tst_QQuickListView) diff --git a/tests/auto/qtquick2/shared/viewtestutil.cpp b/tests/auto/qtquick2/shared/viewtestutil.cpp index ed2066d..eeef230 100644 --- a/tests/auto/qtquick2/shared/viewtestutil.cpp +++ b/tests/auto/qtquick2/shared/viewtestutil.cpp @@ -99,6 +99,53 @@ void QQuickViewTestUtil::flick(QQuickView *canvas, const QPoint &from, const QPo QTest::qWait(50); } +QList QQuickViewTestUtil::adjustIndexesForAddDisplaced(const QList &indexes, int index, int count) +{ + QList result; + for (int i=0; i= index) { + num += count; + } + result << num; + } + return result; +} + +QList QQuickViewTestUtil::adjustIndexesForMove(const QList &indexes, int from, int to, int count) +{ + QList result; + for (int i=0; i= from && num < from + count) + num += (to - from); // target + else if (num >= from && num < to + count) + num -= count; // displaced + } else if (from > to) { + if (num >= from && num < from + count) + num -= (from - to); // target + else if (num >= to && num < from + count) + num += count; // displaced + } + result << num; + } + return result; +} + +QList QQuickViewTestUtil::adjustIndexesForRemoveDisplaced(const QList &indexes, int index, int count) +{ + QList result; + for (int i=0; i= index) + num -= count; + result << num; + } + return result; +} + + QQuickViewTestUtil::QmlListModel::QmlListModel(QObject *parent) : QListModelInterface(parent) { @@ -228,6 +275,17 @@ void QQuickViewTestUtil::QmlListModel::clear() { emit itemsRemoved(0, count); } +void QQuickViewTestUtil::QmlListModel::matchAgainst(const QList > &other, const QString &error1, const QString &error2) { + for (int i=0; i > &other, const QString &error1, const QString &error2) { + for (int i=0; i > QQuickViewTestUtil::ListRange::getModelDataValues(const QmlListModel &model) +{ + QList > data; + if (!valid) + return data; + for (int i=0; i > QQuickViewTestUtil::ListRange::getModelDataValues(const QaimModel &model) +{ + QList > data; + if (!valid) + return data; + for (int i=0; i adjustIndexesForAddDisplaced(const QList &indexes, int index, int count); + QList adjustIndexesForMove(const QList &indexes, int from, int to, int count); + QList adjustIndexesForRemoveDisplaced(const QList &indexes, int index, int count); + struct ListChange { - enum { Inserted, Removed, Moved, SetCurrent } type; + enum { Inserted, Removed, Moved, SetCurrent, SetContentY } type; int index; int count; int to; // Move + qreal pos; // setContentY - static ListChange insert(int index, int count = 1) { ListChange c = { Inserted, index, count, -1 }; return c; } - static ListChange remove(int index, int count = 1) { ListChange c = { Removed, index, count, -1 }; return c; } - static ListChange move(int index, int to, int count) { ListChange c = { Moved, index, count, to }; return c; } - static ListChange setCurrent(int index) { ListChange c = { SetCurrent, index, -1, -1 }; return c; } + static ListChange insert(int index, int count = 1) { ListChange c = { Inserted, index, count, -1, 0.0 }; return c; } + static ListChange remove(int index, int count = 1) { ListChange c = { Removed, index, count, -1, 0.0 }; return c; } + static ListChange move(int index, int to, int count) { ListChange c = { Moved, index, count, to, 0.0 }; return c; } + static ListChange setCurrent(int index) { ListChange c = { SetCurrent, index, -1, -1, 0.0 }; return c; } + static ListChange setContentY(qreal pos) { ListChange c = { SetContentY, -1, -1, -1, pos }; return c; } }; class QmlListModel : public QListModelInterface @@ -87,7 +93,7 @@ namespace QQuickViewTestUtil QVariant data(int index, int role) const; QHash data(int index, const QList &roles) const; - void addItem(const QString &name, const QString &number); + Q_INVOKABLE void addItem(const QString &name, const QString &number); void insertItem(int index, const QString &name, const QString &number); void insertItems(int index, const QList > &items); @@ -101,6 +107,8 @@ namespace QQuickViewTestUtil void clear(); + void matchAgainst(const QList > &other, const QString &error1, const QString &error2); + private: QList > list; }; @@ -120,7 +128,7 @@ namespace QQuickViewTestUtil QString name(int index) const; QString number(int index) const; - void addItem(const QString &name, const QString &number); + Q_INVOKABLE void addItem(const QString &name, const QString &number); void addItems(const QList > &items); void insertItem(int index, const QString &name, const QString &number); void insertItems(int index, const QList > &items); @@ -134,13 +142,39 @@ namespace QQuickViewTestUtil void modifyItem(int idx, const QString &name, const QString &number); void clear(); + void reset(); + + void matchAgainst(const QList > &other, const QString &error1, const QString &error2); private: QList > list; }; + class ListRange + { + public: + ListRange(); + ListRange(const ListRange &other); + ListRange(int start, int end); + + ~ListRange(); + + ListRange operator+(const ListRange &other) const; + bool operator==(const ListRange &other) const; + bool operator!=(const ListRange &other) const; + + bool isValid() const; + int count() const; + + QList > getModelDataValues(const QmlListModel &model); + QList > getModelDataValues(const QaimModel &model); + + QList indexes; + bool valid; + }; } Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(QQuickViewTestUtil::ListRange) #endif // QQUICKVIEWTESTUTIL_H diff --git a/tests/auto/qtquick2/shared/visualtestutil.h b/tests/auto/qtquick2/shared/visualtestutil.h index ceed4b0..09bb03c 100644 --- a/tests/auto/qtquick2/shared/visualtestutil.h +++ b/tests/auto/qtquick2/shared/visualtestutil.h @@ -97,6 +97,16 @@ namespace QQuickVisualTestUtil return items; } + + template + QList findItems(QQuickItem *parent, const QString &objectName, const QList &indexes) + { + QList items; + for (int i=0; i(findItem(parent, objectName, indexes[i])); + return items; + } + } #endif // QQUICKVISUALTESTUTIL_H -- 2.7.4