From 0797e0cb2072a0b5cac4d8db2205d932cc64d25c Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Fri, 18 Sep 2015 13:40:01 +0200 Subject: Merge Qt Quick Extras into Qt Quick Controls The original split existed because the public and enterprise controls were developed separately. Now that all controls are public and developed together, the split no longer makes sense and is difficult for users to understand. Change-Id: I00420f4d09f8c837232231d03fe818b7b3403fab Reviewed-by: Gabriel de Dietrich Reviewed-by: Frederik Gladhorn Reviewed-by: J-P Nurmi --- tests/auto/auto.pro | 1 - tests/auto/controls/data/TumblerDatePicker.qml | 87 +++ tests/auto/controls/data/tst_dial.qml | 287 +++++++++ tests/auto/controls/data/tst_drawer.qml | 66 ++ tests/auto/controls/data/tst_swipeview.qml | 518 ++++++++++++++++ tests/auto/controls/data/tst_tumbler.qml | 668 +++++++++++++++++++++ tests/auto/extras/data/TumblerDatePicker.qml | 88 --- tests/auto/extras/data/tst_dial.qml | 287 --------- tests/auto/extras/data/tst_drawer.qml | 66 -- tests/auto/extras/data/tst_swipeview.qml | 518 ---------------- tests/auto/extras/data/tst_tumbler.qml | 668 --------------------- tests/auto/extras/extras.pro | 12 - tests/auto/extras/tst_extras.cpp | 38 -- tests/auto/sanity/tst_sanity.cpp | 1 - .../data/dial/qtquickextras2-dial-background.qml | 2 +- .../data/dial/qtquickextras2-dial-handle.qml | 2 +- .../tumbler/qtquickextras2-tumbler-background.qml | 2 +- .../tumbler/qtquickextras2-tumbler-contentItem.qml | 2 +- .../tumbler/qtquickextras2-tumbler-delegate.qml | 2 +- tests/benchmarks/creationtime/tst_creationtime.cpp | 17 - .../gifs/data/qtquickcontrols2-tumbler-wrap.qml | 118 ++++ .../gifs/data/qtquickextras2-tumbler-wrap.qml | 119 ---- tests/manual/gifs/tst_gifs.cpp | 2 +- 23 files changed, 1750 insertions(+), 1821 deletions(-) create mode 100644 tests/auto/controls/data/TumblerDatePicker.qml create mode 100644 tests/auto/controls/data/tst_dial.qml create mode 100644 tests/auto/controls/data/tst_drawer.qml create mode 100644 tests/auto/controls/data/tst_swipeview.qml create mode 100644 tests/auto/controls/data/tst_tumbler.qml delete mode 100644 tests/auto/extras/data/TumblerDatePicker.qml delete mode 100644 tests/auto/extras/data/tst_dial.qml delete mode 100644 tests/auto/extras/data/tst_drawer.qml delete mode 100644 tests/auto/extras/data/tst_swipeview.qml delete mode 100644 tests/auto/extras/data/tst_tumbler.qml delete mode 100644 tests/auto/extras/extras.pro delete mode 100644 tests/auto/extras/tst_extras.cpp create mode 100644 tests/manual/gifs/data/qtquickcontrols2-tumbler-wrap.qml delete mode 100644 tests/manual/gifs/data/qtquickextras2-tumbler-wrap.qml (limited to 'tests') diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index c8076194..4c42920b 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -4,6 +4,5 @@ SUBDIRS += \ activeFocusOnTab \ applicationwindow \ controls \ - extras \ sanity \ snippets diff --git a/tests/auto/controls/data/TumblerDatePicker.qml b/tests/auto/controls/data/TumblerDatePicker.qml new file mode 100644 index 00000000..18d7fb97 --- /dev/null +++ b/tests/auto/controls/data/TumblerDatePicker.qml @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite 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 The Qt Company Ltd 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.6 +import QtQuick.Controls 2.0 + +Row { + id: datePicker + + readonly property var days: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] + + property alias dayTumbler: dayTumbler + property alias monthTumbler: monthTumbler + property alias yearTumbler: yearTumbler + + Tumbler { + id: dayTumbler + objectName: "dayTumbler" + + Component.onCompleted: updateModel() + + function updateModel() { + var previousIndex = dayTumbler.currentIndex; + var array = []; + var newDays = datePicker.days[monthTumbler.currentIndex]; + for (var i = 0; i < newDays; ++i) { + array.push(i + 1); + } + dayTumbler.model = array; + dayTumbler.currentIndex = Math.min(newDays - 1, previousIndex); + } + } + Tumbler { + id: monthTumbler + objectName: "monthTumbler" + model: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] + onCurrentIndexChanged: dayTumbler.updateModel() + } + Tumbler { + id: yearTumbler + objectName: "yearTumbler" + model: ListModel { + Component.onCompleted: { + for (var i = 2000; i < 2100; ++i) { + append({value: i.toString()}); + } + } + } + } +} diff --git a/tests/auto/controls/data/tst_dial.qml b/tests/auto/controls/data/tst_dial.qml new file mode 100644 index 00000000..5a4a66a5 --- /dev/null +++ b/tests/auto/controls/data/tst_dial.qml @@ -0,0 +1,287 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite 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 The Qt Company Ltd 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.2 +import QtTest 1.0 +import QtQuick.Controls 2.0 + +TestCase { + id: testCase + width: 200 + height: 200 + visible: true + when: windowShown + name: "Dial" + + Component { + id: dialComponent + Dial {} + } + + property var dial: null + + function init() { + dial = dialComponent.createObject(testCase); + verify(dial, "Dial: failed to create an instance"); + } + + function cleanup() { + if (dial) + dial.destroy(); + } + + function test_instance() { + compare(dial.value, 0.0); + compare(dial.from, 0.0); + compare(dial.to, 1.0); + compare(dial.stepSize, 0.0); + verify(dial.activeFocusOnTab); + verify(!dial.pressed); + } + + function test_value() { + compare(dial.value, 0.0); + compare(Math.floor(dial.handle.mapToItem(parent, 0, 0).x), 28); + compare(Math.floor(dial.handle.mapToItem(parent, 0, 0).y), 90); + + dial.value = 0.5; + compare(dial.value, 0.5); + + dial.value = 1.0; + compare(dial.value, 1.0); + + dial.value = -1.0; + compare(dial.value, 0.0); + + dial.value = 2.0; + compare(dial.value, 1.0); + } + + function test_range() { + dial.from = 0; + dial.to = 100; + dial.value = 50; + compare(dial.from, 0); + compare(dial.to, 100); + compare(dial.value, 50); + compare(dial.position, 0.5); + + dial.value = 1000 + compare(dial.value, 100); + compare(dial.position, 1); + + dial.value = -1 + compare(dial.value, 0); + compare(dial.position, 0); + + dial.from = 25 + compare(dial.from, 25); + compare(dial.value, 25); + compare(dial.position, 0); + + dial.to = 75 + compare(dial.to, 75); + compare(dial.value, 25); + compare(dial.position, 0); + + dial.value = 50 + compare(dial.value, 50); + compare(dial.position, 0.5); + } + + function test_inverted() { + dial.destroy(); + dial = dialComponent.createObject(testCase, { from: 1.0, to: -1.0 }); + verify(dial, "Dial: failed to create an instance"); + compare(dial.from, 1.0); + compare(dial.to, -1.0); + compare(dial.value, 0.0); + compare(dial.position, 0.5); + + dial.value = 2.0; + compare(dial.value, 1.0); + compare(dial.position, 0.0); + + dial.value = -2.0; + compare(dial.value, -1.0); + compare(dial.position, 1.0); + + dial.value = 0.0; + compare(dial.value, 0.0); + compare(dial.position, 0.5); + } + + SignalSpy { + id: pressSpy + signalName: "pressedChanged" + } + + function test_pressed() { + pressSpy.target = dial; + verify(pressSpy.valid); + verify(!dial.pressed); + + mousePress(dial, dial.width / 2, dial.height / 2); + verify(dial.pressed); + compare(pressSpy.count, 1); + + mouseRelease(dial, dial.width / 2, dial.height / 2); + verify(!dial.pressed); + compare(pressSpy.count, 2); + } + + SignalSpy { + id: valueSpy + signalName: "valueChanged" + } + + function test_dragging_data() { + return [ + { tag: "default", from: 0, to: 1, leftValue: 0.20, topValue: 0.5, rightValue: 0.8, bottomValue: 1.0 }, + { tag: "scaled2", from: 0, to: 2, leftValue: 0.4, topValue: 1.0, rightValue: 1.6, bottomValue: 2.0 }, + { tag: "scaled1", from: -1, to: 0, leftValue: -0.8, topValue: -0.5, rightValue: -0.2, bottomValue: 0.0 } + ] + } + + function test_dragging(data) { + dial.from = data.from; + dial.to = data.to; + + valueSpy.target = dial; + verify(valueSpy.valid); + + // drag to the left + mouseDrag(dial, dial.width / 2, dial.height / 2, -dial.width / 2, 0, Qt.LeftButton); + fuzzyCompare(dial.value, data.leftValue, 0.1); + verify(valueSpy.count > 0); + valueSpy.clear(); + + // drag to the top + mouseDrag(dial, dial.width / 2, dial.height / 2, 0, -dial.height / 2, Qt.LeftButton); + fuzzyCompare(dial.value, data.topValue, 0.1); + verify(valueSpy.count > 0); + valueSpy.clear(); + + // drag to the right + mouseDrag(dial, dial.width / 2, dial.height / 2, dial.width / 2, 0, Qt.LeftButton); + fuzzyCompare(dial.value, data.rightValue, 0.1); + verify(valueSpy.count > 0); + valueSpy.clear(); + + // drag to the bottom (* 0.6 to ensure we don't go over to the minimum position) + mouseDrag(dial, dial.width / 2, dial.height / 2, 10, dial.height / 2, Qt.LeftButton); + fuzzyCompare(dial.value, data.bottomValue, 0.1); + verify(valueSpy.count > 0); + valueSpy.clear(); + } + + property Component focusTest: Component { + FocusScope { + signal receivedKeyPress + + Component.onCompleted: forceActiveFocus() + anchors.fill: parent + Keys.onPressed: receivedKeyPress() + } + } + + SignalSpy { + id: parentEventSpy + } + + function test_keyboardNavigation() { + var focusScope = focusTest.createObject(testCase); + verify(focusScope); + + // Tests that we've accepted events that we're interested in. + parentEventSpy.target = focusScope; + parentEventSpy.signalName = "receivedKeyPress"; + + dial.parent = focusScope; + compare(dial.activeFocusOnTab, true); + compare(dial.value, 0); + + dial.focus = true; + compare(dial.activeFocus, true); + dial.stepSize = 0.1; + + keyClick(Qt.Key_Left); + compare(parentEventSpy.count, 0); + compare(dial.value, 0); + + + var keyPairs = [[Qt.Key_Left, Qt.Key_Right], [Qt.Key_Down, Qt.Key_Up]]; + for (var keyPairIndex = 0; keyPairIndex < 2; ++keyPairIndex) { + for (var i = 1; i <= 10; ++i) { + keyClick(keyPairs[keyPairIndex][1]); + compare(parentEventSpy.count, 0); + compare(dial.value, dial.stepSize * i); + } + + compare(dial.value, dial.to); + + for (i = 10; i > 0; --i) { + keyClick(keyPairs[keyPairIndex][0]); + compare(parentEventSpy.count, 0); + compare(dial.value, dial.stepSize * (i - 1)); + } + } + + compare(dial.value, dial.from); + + keyClick(Qt.Key_Home); + compare(parentEventSpy.count, 0); + compare(dial.value, dial.from); + + keyClick(Qt.Key_End); + compare(parentEventSpy.count, 0); + compare(dial.value, dial.to); + + keyClick(Qt.Key_End); + compare(parentEventSpy.count, 0); + compare(dial.value, dial.to); + + keyClick(Qt.Key_Home); + compare(parentEventSpy.count, 0); + compare(dial.value, dial.from); + + focusScope.destroy(); + } +} diff --git a/tests/auto/controls/data/tst_drawer.qml b/tests/auto/controls/data/tst_drawer.qml new file mode 100644 index 00000000..af815bed --- /dev/null +++ b/tests/auto/controls/data/tst_drawer.qml @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite 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 The Qt Company Ltd 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.2 +import QtTest 1.0 +import QtQuick.Controls 2.0 + +TestCase { + id: testCase + width: 400 + height: 400 + visible: true + when: windowShown + name: "Drawer" + + Component { + id: drawer + Drawer { } + } + + function test_defaults() { + var control = drawer.createObject(testCase) + verify(!control.contentItem) + compare(control.edge, Qt.LeftEdge) + compare(control.position, 0.0) + verify(control.animation) + control.destroy() + } +} diff --git a/tests/auto/controls/data/tst_swipeview.qml b/tests/auto/controls/data/tst_swipeview.qml new file mode 100644 index 00000000..a4dd41dd --- /dev/null +++ b/tests/auto/controls/data/tst_swipeview.qml @@ -0,0 +1,518 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite 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 The Qt Company Ltd 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.2 +import QtTest 1.0 +import QtQuick.Controls 2.0 + +TestCase { + id: testCase + width: 200 + height: 200 + visible: true + when: windowShown + name: "SwipeView" + + Component { + id: swipeView + SwipeView { } + } + + Component { + id: page + Text { } + } + + SignalSpy { + id: currentItemChangedSpy + signalName: "currentItemChanged" + } + + function cleanup() { + currentItemChangedSpy.clear() + currentItemChangedSpy.target = null + } + + function test_current() { + var control = swipeView.createObject(testCase) + + currentItemChangedSpy.target = control + + compare(control.count, 0) + compare(control.currentIndex, -1) + compare(control.currentItem, null) + + control.addItem(page.createObject(control, {text: "0"})) + compare(control.count, 1) + compare(control.currentIndex, 0) + compare(control.currentItem.text, "0") + compare(currentItemChangedSpy.count, 1); + + control.addItem(page.createObject(control, {text: "1"})) + compare(control.count, 2) + compare(control.currentIndex, 0) + compare(control.currentItem.text, "0") + compare(currentItemChangedSpy.count, 1); + + control.addItem(page.createObject(control, {text: "2"})) + compare(control.count, 3) + compare(control.currentIndex, 0) + compare(control.currentItem.text, "0") + compare(currentItemChangedSpy.count, 1); + + control.currentIndex = 1 + compare(control.currentIndex, 1) + compare(control.currentItem.text, "1") + compare(currentItemChangedSpy.count, 2); + + control.currentIndex = 2 + compare(control.currentIndex, 2) + compare(control.currentItem.text, "2") + compare(currentItemChangedSpy.count, 3); + + control.destroy() + } + + Component { + id: initialCurrentSwipeView + SwipeView { + currentIndex: 1 + + property alias item0: item0 + property alias item1: item1 + + Item { + id: item0 + } + Item { + id: item1 + } + } + } + + function test_initialCurrent() { + var control = initialCurrentSwipeView.createObject(testCase) + + compare(control.count, 2) + compare(control.currentIndex, 1) + compare(control.currentItem, control.item1) + + control.destroy() + } + + function test_addRemove() { + var control = swipeView.createObject(testCase) + + function verifyCurrentIndexCountDiff() { + verify(control.currentIndex < control.count) + } + control.currentIndexChanged.connect(verifyCurrentIndexCountDiff) + control.countChanged.connect(verifyCurrentIndexCountDiff) + + currentItemChangedSpy.target = control; + + compare(control.count, 0) + compare(control.currentIndex, -1) + compare(control.currentItem, null) + control.addItem(page.createObject(control, {text: "1"})) + compare(control.count, 1) + compare(control.currentIndex, 0) + compare(currentItemChangedSpy.count, 1) + compare(control.currentItem.text, "1") + control.addItem(page.createObject(control, {text: "2"})) + compare(control.count, 2) + compare(control.currentIndex, 0) + compare(currentItemChangedSpy.count, 1) + compare(control.currentItem.text, "1") + compare(control.itemAt(0).text, "1") + compare(control.itemAt(1).text, "2") + + control.currentIndex = 1 + compare(currentItemChangedSpy.count, 2) + + control.insertItem(1, page.createObject(control, {text: "3"})) + compare(control.count, 3) + compare(control.currentIndex, 2) + compare(control.currentItem.text, "2") + compare(control.itemAt(0).text, "1") + compare(control.itemAt(1).text, "3") + compare(control.itemAt(2).text, "2") + + control.insertItem(0, page.createObject(control, {text: "4"})) + compare(control.count, 4) + compare(control.currentIndex, 3) + compare(control.currentItem.text, "2") + compare(control.itemAt(0).text, "4") + compare(control.itemAt(1).text, "1") + compare(control.itemAt(2).text, "3") + compare(control.itemAt(3).text, "2") + + control.insertItem(control.count, page.createObject(control, {text: "5"})) + compare(control.count, 5) + compare(control.currentIndex, 3) + compare(control.currentItem.text, "2") + compare(control.itemAt(0).text, "4") + compare(control.itemAt(1).text, "1") + compare(control.itemAt(2).text, "3") + compare(control.itemAt(3).text, "2") + compare(control.itemAt(4).text, "5") + + control.removeItem(control.count - 1) + compare(control.count, 4) + compare(control.currentIndex, 3) + compare(control.currentItem.text, "2") + compare(control.itemAt(0).text, "4") + compare(control.itemAt(1).text, "1") + compare(control.itemAt(2).text, "3") + compare(control.itemAt(3).text, "2") + + control.removeItem(0) + compare(control.count, 3) + compare(control.currentIndex, 2) + compare(control.currentItem.text, "2") + compare(control.itemAt(0).text, "1") + compare(control.itemAt(1).text, "3") + compare(control.itemAt(2).text, "2") + + control.removeItem(1) + compare(control.count, 2) + compare(control.currentIndex, 1) + compare(control.currentItem.text, "2") + compare(control.itemAt(0).text, "1") + compare(control.itemAt(1).text, "2") + + currentItemChangedSpy.clear() + + control.removeItem(1) + compare(control.count, 1) + compare(control.currentIndex, 0) + compare(currentItemChangedSpy.count, 1) + compare(control.currentItem.text, "1") + compare(control.itemAt(0).text, "1") + + control.removeItem(0) + compare(control.count, 0) + compare(control.currentIndex, -1) + compare(currentItemChangedSpy.count, 2) + + control.destroy() + } + + Component { + id: contentView + SwipeView { + QtObject { objectName: "object" } + Item { objectName: "page1" } + Timer { objectName: "timer" } + Item { objectName: "page2" } + Component { Item { } } + } + } + + function test_content() { + var control = contentView.createObject(testCase) + + function compareObjectNames(content, names) { + if (content.length !== names.length) + return false + for (var i = 0; i < names.length; ++i) { + if (content[i].objectName !== names[i]) + return false + } + return true + } + + verify(compareObjectNames(control.contentData, ["object", "page1", "timer", "page2", ""])) + verify(compareObjectNames(control.contentChildren, ["page1", "page2"])) + + control.addItem(page.createObject(control, {objectName: "page3"})) + verify(compareObjectNames(control.contentData, ["object", "page1", "timer", "page2", "", "page3"])) + verify(compareObjectNames(control.contentChildren, ["page1", "page2", "page3"])) + + control.insertItem(0, page.createObject(control, {objectName: "page4"})) + verify(compareObjectNames(control.contentData, ["object", "page1", "timer", "page2", "", "page3", "page4"])) + verify(compareObjectNames(control.contentChildren, ["page4", "page1", "page2", "page3"])) + + control.moveItem(1, 2) + verify(compareObjectNames(control.contentData, ["object", "page1", "timer", "page2", "", "page3", "page4"])) + verify(compareObjectNames(control.contentChildren, ["page4", "page2", "page1", "page3"])) + + control.removeItem(0) + verify(compareObjectNames(control.contentData, ["object", "page1", "timer", "page2", "", "page3"])) + verify(compareObjectNames(control.contentChildren, ["page2", "page1", "page3"])) + + control.destroy() + } + + Component { + id: repeated + SwipeView { + property alias repeater: repeater + Repeater { + id: repeater + model: 5 + Item { property int idx: index } + } + } + } + + function test_repeater() { + var control = repeated.createObject(testCase) + verify(control) + + var model = control.contentModel + verify(model) + + var repeater = control.repeater + verify(repeater) + + compare(repeater.count, 5) + compare(model.count, 5) + + for (var i = 0; i < 5; ++i) { + var item1 = control.itemAt(i) + verify(item1) + compare(item1.idx, i) + compare(model.get(i), item1) + compare(repeater.itemAt(i), item1) + } + + repeater.model = 3 + compare(repeater.count, 3) + compare(model.count, 3) + + for (var j = 0; j < 3; ++j) { + var item2 = control.itemAt(j) + verify(item2) + compare(item2.idx, j) + compare(model.get(j), item2) + compare(repeater.itemAt(j), item2) + } + + control.destroy() + } + + Component { + id: ordered + SwipeView { + id: oview + property alias repeater: repeater + Text { text: "static_1" } + Repeater { + id: repeater + model: 2 + Text { text: "repeated_" + (index + 2) } + } + Text { text: "static_4" } + Component.onCompleted: { + addItem(page.createObject(oview, {text: "dynamic_5"})) + addItem(page.createObject(oview.contentItem, {text: "dynamic_6"})) + insertItem(0, page.createObject(oview, {text: "dynamic_0"})) + } + } + } + + function test_order() { + var control = ordered.createObject(testCase) + verify(control) + + compare(control.count, 7) + compare(control.itemAt(0).text, "dynamic_0") + compare(control.itemAt(1).text, "static_1") + compare(control.itemAt(2).text, "repeated_2") + compare(control.itemAt(3).text, "repeated_3") + compare(control.itemAt(4).text, "static_4") + compare(control.itemAt(5).text, "dynamic_5") + compare(control.itemAt(6).text, "dynamic_6") + + control.destroy() + } + + function test_move_data() { + return [ + {tag:"0->1 (0)", from: 0, to: 1, currentBefore: 0, currentAfter: 1}, + {tag:"0->1 (1)", from: 0, to: 1, currentBefore: 1, currentAfter: 0}, + {tag:"0->1 (2)", from: 0, to: 1, currentBefore: 2, currentAfter: 2}, + + {tag:"0->2 (0)", from: 0, to: 2, currentBefore: 0, currentAfter: 2}, + {tag:"0->2 (1)", from: 0, to: 2, currentBefore: 1, currentAfter: 0}, + {tag:"0->2 (2)", from: 0, to: 2, currentBefore: 2, currentAfter: 1}, + + {tag:"1->0 (0)", from: 1, to: 0, currentBefore: 0, currentAfter: 1}, + {tag:"1->0 (1)", from: 1, to: 0, currentBefore: 1, currentAfter: 0}, + {tag:"1->0 (2)", from: 1, to: 0, currentBefore: 2, currentAfter: 2}, + + {tag:"1->2 (0)", from: 1, to: 2, currentBefore: 0, currentAfter: 0}, + {tag:"1->2 (1)", from: 1, to: 2, currentBefore: 1, currentAfter: 2}, + {tag:"1->2 (2)", from: 1, to: 2, currentBefore: 2, currentAfter: 1}, + + {tag:"2->0 (0)", from: 2, to: 0, currentBefore: 0, currentAfter: 1}, + {tag:"2->0 (1)", from: 2, to: 0, currentBefore: 1, currentAfter: 2}, + {tag:"2->0 (2)", from: 2, to: 0, currentBefore: 2, currentAfter: 0}, + + {tag:"2->1 (0)", from: 2, to: 1, currentBefore: 0, currentAfter: 0}, + {tag:"2->1 (1)", from: 2, to: 1, currentBefore: 1, currentAfter: 2}, + {tag:"2->1 (2)", from: 2, to: 1, currentBefore: 2, currentAfter: 1}, + + {tag:"0->0", from: 0, to: 0, currentBefore: 0, currentAfter: 0}, + {tag:"-1->0", from: 0, to: 0, currentBefore: 1, currentAfter: 1}, + {tag:"0->-1", from: 0, to: 0, currentBefore: 2, currentAfter: 2}, + {tag:"1->10", from: 0, to: 0, currentBefore: 0, currentAfter: 0}, + {tag:"10->2", from: 0, to: 0, currentBefore: 1, currentAfter: 1}, + {tag:"10->-1", from: 0, to: 0, currentBefore: 2, currentAfter: 2} + ] + } + + Component { + id: pageAttached + + Text { + property int index: AbstractSwipeView.index + property SwipeView view: AbstractSwipeView.view + property bool isCurrentItem: AbstractSwipeView.isCurrentItem + } + } + + function test_move(data) { + var control = swipeView.createObject(testCase) + + compare(control.count, 0) + var titles = ["1", "2", "3"] + + var i = 0; + for (i = 0; i < titles.length; ++i) { + var item = pageAttached.createObject(control, {text: titles[i]}) + control.addItem(item) + } + + compare(control.count, titles.length) + for (i = 0; i < control.count; ++i) { + compare(control.itemAt(i).text, titles[i]) + compare(control.itemAt(i).AbstractSwipeView.index, i) + compare(control.itemAt(i).AbstractSwipeView.isCurrentItem, i === 0) + } + + control.currentIndex = data.currentBefore + for (i = 0; i < control.count; ++i) { + compare(control.itemAt(i).AbstractSwipeView.isCurrentItem, i === data.currentBefore) + } + + control.moveItem(data.from, data.to) + + compare(control.count, titles.length) + compare(control.currentIndex, data.currentAfter) + + var title = titles[data.from] + titles.splice(data.from, 1) + titles.splice(data.to, 0, title) + + compare(control.count, titles.length) + for (i = 0; i < control.count; ++i) { + compare(control.itemAt(i).text, titles[i]) + compare(control.itemAt(i).AbstractSwipeView.index, i); + compare(control.itemAt(i).AbstractSwipeView.isCurrentItem, i === data.currentAfter) + } + + control.destroy() + } + + Component { + id: dynamicView + SwipeView { + id: dview + Text { text: "static" } + Component.onCompleted: { + addItem(page.createObject(dview, {text: "added"})) + insertItem(0, page.createObject(dview, {text: "inserted"})) + page.createObject(dview, {text: "dynamic"}) + } + } + } + + function test_dynamic() { + var control = dynamicView.createObject(testCase) + + // insertItem(), addItem(), createObject() and static page {} + compare(control.count, 4) + compare(control.itemAt(0).text, "inserted") + + var tab = page.createObject(control, {text: "dying"}) + compare(control.count, 5) + compare(control.itemAt(4).text, "dying") + + // TODO: fix crash in QQuickItemView +// tab.destroy() +// wait(0) +// compare(control.count, 4) + + control.destroy() + } + + function test_attachedParent() { + var control = swipeView.createObject(testCase); + + var page = pageAttached.createObject(testCase); + compare(page.view, null); + compare(page.index, -1); + compare(page.isCurrentItem, false); + page.destroy(); + + page = pageAttached.createObject(null); + compare(page.view, null); + compare(page.index, -1); + compare(page.isCurrentItem, false); + + control.insertItem(0, page); + compare(control.count, 1); + compare(page.parent, control.contentItem.contentItem); + compare(page.view, control); + compare(page.index, 0); + compare(page.isCurrentItem, true); + + control.removeItem(0); + compare(control.count, 0); + compare(page.parent, null); + compare(page.view, null); + compare(page.index, -1); + compare(page.isCurrentItem, false); + + control.destroy(); + } +} diff --git a/tests/auto/controls/data/tst_tumbler.qml b/tests/auto/controls/data/tst_tumbler.qml new file mode 100644 index 00000000..c916b0f6 --- /dev/null +++ b/tests/auto/controls/data/tst_tumbler.qml @@ -0,0 +1,668 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite 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 The Qt Company Ltd 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.2 +import QtTest 1.0 +import QtQuick.Controls 2.0 + +TestCase { + id: testCase + width: 200 + height: 200 + visible: true + when: windowShown + name: "Tumbler" + + property var tumbler: null + readonly property real implicitTumblerWidth: 60 + readonly property real implicitTumblerHeight: 200 + readonly property real defaultImplicitDelegateHeight: implicitTumblerHeight / 3 + readonly property real defaultListViewTumblerOffset: -defaultImplicitDelegateHeight + + function init() { + tumbler = Qt.createQmlObject("import QtQuick.Controls 2.0; Tumbler { }", testCase, ""); + verify(tumbler, "Tumbler: failed to create an instance"); + compare(tumbler.contentItem.parent, tumbler); + } + + function cleanup() { + tumbler.destroy(); + } + + function tumblerXCenter() { + return tumbler.leftPadding + tumbler.width / 2; + } + + function tumblerYCenter() { + return tumbler.topPadding + tumbler.height / 2; + } + + // visualItemIndex is from 0 to the amount of visible items. + function itemCenterPos(visualItemIndex) { + var halfDelegateHeight = tumbler.contentItem.delegateHeight / 2; + var yCenter = tumbler.y + tumbler.topPadding + halfDelegateHeight + + (tumbler.contentItem.delegateHeight * visualItemIndex); + return Qt.point(tumblerXCenter(), yCenter); + } + + function checkItemSizes() { + var contentChildren = tumbler.contentItem.hasOwnProperty("contentItem") + ? tumbler.contentItem.contentItem.children : tumbler.contentItem.children; + verify(contentChildren.length >= tumbler.count); + for (var i = 0; i < contentChildren.length; ++i) { + compare(contentChildren[i].width, tumbler.width); + compare(contentChildren[i].height, tumbler.contentItem.delegateHeight); + } + } + + function tst_dynamicContentItemChange() { + // test that currentIndex is maintained between contentItem changes... + } + + function test_currentIndex() { + tumbler.model = 5; + + compare(tumbler.currentIndex, 0); + waitForRendering(tumbler); + + // Set it through user interaction. + var pos = Qt.point(tumblerXCenter(), tumbler.height / 2); + mouseDrag(tumbler, pos.x, pos.y, 0, -tumbler.contentItem.delegateHeight / 2, Qt.LeftButton, Qt.NoModifier, 200); + compare(tumbler.currentIndex, 1); + compare(tumbler.contentItem.currentIndex, 1); + + // Set it manually. + tumbler.currentIndex = 2; + tryCompare(tumbler, "currentIndex", 2); + compare(tumbler.contentItem.currentIndex, 2); + + // PathView has 0 as its currentIndex in this case for some reason. + tumbler.model = null; + tryCompare(tumbler, "currentIndex", 0); + + tumbler.model = ["A", "B", "C"]; + tryCompare(tumbler, "currentIndex", 0); + } + + function test_keyboardNavigation() { + tumbler.model = 5; + tumbler.forceActiveFocus(); + var keyClickDelay = 100; + + // Navigate upwards through entire wheel. + for (var j = 0; j < tumbler.count - 1; ++j) { + keyClick(Qt.Key_Up, Qt.NoModifier, keyClickDelay); + tryCompare(tumbler.contentItem, "offset", j + 1); + compare(tumbler.currentIndex, tumbler.count - 1 - j); + } + + keyClick(Qt.Key_Up, Qt.NoModifier, keyClickDelay); + tryCompare(tumbler.contentItem, "offset", 0); + compare(tumbler.currentIndex, 0); + + // Navigate downwards through entire wheel. + for (j = 0; j < tumbler.count - 1; ++j) { + keyClick(Qt.Key_Down, Qt.NoModifier, keyClickDelay); + tryCompare(tumbler.contentItem, "offset", tumbler.count - 1 - j); + compare(tumbler.currentIndex, j + 1); + } + + keyClick(Qt.Key_Down, Qt.NoModifier, keyClickDelay); + tryCompare(tumbler.contentItem, "offset", 0); + compare(tumbler.currentIndex, 0); + } + + function test_itemsCorrectlyPositioned() { + tumbler.model = 4; + tumbler.height = 120; + compare(tumbler.contentItem.delegateHeight, 40); + checkItemSizes(); + + wait(tumbler.contentItem.highlightMoveDuration); + var firstItemCenterPos = itemCenterPos(1); + var firstItem = tumbler.contentItem.itemAt(firstItemCenterPos.x, firstItemCenterPos.y); + var actualPos = testCase.mapFromItem(firstItem, 0, 0); + compare(actualPos.x, tumbler.leftPadding); + compare(actualPos.y, tumbler.topPadding + 40); + + tumbler.forceActiveFocus(); + keyClick(Qt.Key_Down); + tryCompare(tumbler.contentItem, "offset", 3.0); + firstItemCenterPos = itemCenterPos(0); + firstItem = tumbler.contentItem.itemAt(firstItemCenterPos.x, firstItemCenterPos.y); + verify(firstItem); + // Test QTBUG-40298. + actualPos = testCase.mapFromItem(firstItem, 0, 0); + compare(actualPos.x, tumbler.leftPadding); + compare(actualPos.y, tumbler.topPadding); + + var secondItemCenterPos = itemCenterPos(1); + var secondItem = tumbler.contentItem.itemAt(secondItemCenterPos.x, secondItemCenterPos.y); + verify(secondItem); + verify(firstItem.y < secondItem.y); + + var thirdItemCenterPos = itemCenterPos(2); + var thirdItem = tumbler.contentItem.itemAt(thirdItemCenterPos.x, thirdItemCenterPos.y); + verify(thirdItem); + verify(firstItem.y < thirdItem.y); + verify(secondItem.y < thirdItem.y); + } + + function test_resizeAfterFlicking() { + // Test QTBUG-40367 (which is actually invalid because it was my fault :)). + tumbler.model = 100; + + // Flick in some direction. + var pos = Qt.point(tumblerXCenter(), tumbler.topPadding); + mouseDrag(tumbler, pos.x, pos.y, 0, tumbler.height - tumbler.bottomPadding, + Qt.LeftButton, Qt.NoModifier, 400); + tryCompare(tumbler.contentItem, "offset", 3.0); + + tumbler.height += 100; + compare(tumbler.contentItem.delegateHeight, + (tumbler.height - tumbler.topPadding - tumbler.bottomPadding) / tumbler.visibleItemCount); + waitForRendering(tumbler); + pos = itemCenterPos(1); + var ninetyEighthItem = tumbler.contentItem.itemAt(pos.x, pos.y); + verify(ninetyEighthItem); + } + + function test_focusPastTumbler() { + var mouseArea = Qt.createQmlObject( + "import QtQuick 2.2; TextInput { activeFocusOnTab: true; width: 50; height: 50 }", testCase, ""); + + tumbler.forceActiveFocus(); + verify(tumbler.activeFocus); + + keyClick(Qt.Key_Tab); + verify(!tumbler.activeFocus); + verify(mouseArea.activeFocus); + + mouseArea.destroy(); + } + + function test_datePicker() { + tumbler.destroy(); + + var component = Qt.createComponent("TumblerDatePicker.qml"); + compare(component.status, Component.Ready, component.errorString()); + tumbler = component.createObject(testCase); + // Should not be any warnings. + + compare(tumbler.dayTumbler.currentIndex, 0); + compare(tumbler.dayTumbler.count, 31); + compare(tumbler.monthTumbler.currentIndex, 0); + compare(tumbler.monthTumbler.count, 12); + compare(tumbler.yearTumbler.currentIndex, 0); + compare(tumbler.yearTumbler.count, 100); + + verify(tumbler.dayTumbler.contentItem.children.length >= tumbler.dayTumbler.visibleItemCount); + verify(tumbler.monthTumbler.contentItem.children.length >= tumbler.monthTumbler.visibleItemCount); + // TODO: do this properly somehow + wait(100); + verify(tumbler.yearTumbler.contentItem.children.length >= tumbler.yearTumbler.visibleItemCount); + + // March. + tumbler.monthTumbler.currentIndex = 2; + tryCompare(tumbler.monthTumbler, "currentIndex", 2); + + // 30th of March. + tumbler.dayTumbler.currentIndex = 29; + tryCompare(tumbler.dayTumbler, "currentIndex", 29); + + // February. + tumbler.monthTumbler.currentIndex = 1; + tryCompare(tumbler.monthTumbler, "currentIndex", 1); + tryCompare(tumbler.dayTumbler, "currentIndex", 27); + } + + function test_displacement_data() { + var data = [ + // At 0 offset, the first item is current. + { index: 0, offset: 0, expectedDisplacement: 0 }, + { index: 1, offset: 0, expectedDisplacement: -1 }, + { index: 5, offset: 0, expectedDisplacement: 1 }, + // When we start to move the first item down, the second item above it starts to become current. + { index: 0, offset: 0.25, expectedDisplacement: -0.25 }, + { index: 1, offset: 0.25, expectedDisplacement: -1.25 }, + { index: 5, offset: 0.25, expectedDisplacement: 0.75 }, + { index: 0, offset: 0.5, expectedDisplacement: -0.5 }, + { index: 1, offset: 0.5, expectedDisplacement: -1.5 }, + { index: 5, offset: 0.5, expectedDisplacement: 0.5 }, + // By this stage, the delegate at index 1 is destroyed, so we can't test its displacement. + { index: 0, offset: 0.75, expectedDisplacement: -0.75 }, + { index: 5, offset: 0.75, expectedDisplacement: 0.25 }, + { index: 0, offset: 4.75, expectedDisplacement: 1.25 }, + { index: 1, offset: 4.75, expectedDisplacement: 0.25 }, + { index: 0, offset: 4.5, expectedDisplacement: 1.5 }, + { index: 1, offset: 4.5, expectedDisplacement: 0.5 }, + { index: 0, offset: 4.25, expectedDisplacement: 1.75 }, + { index: 1, offset: 4.25, expectedDisplacement: 0.75 } + ]; + for (var i = 0; i < data.length; ++i) { + var row = data[i]; + row.tag = "delegate" + row.index + " offset=" + row.offset + " expectedDisplacement=" + row.expectedDisplacement; + } + return data; + } + + property Component displacementDelegate: Text { + objectName: "delegate" + index + text: modelData + opacity: 0.2 + Math.max(0, 1 - Math.abs(AbstractTumbler.displacement)) * 0.8 + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + Text { + text: parent.displacement.toFixed(2) + anchors.right: parent.right + } + + property real displacement: AbstractTumbler.displacement + } + + function test_displacement(data) { + // TODO: test setting these in the opposite order (delegate after model + // doesn't seem to cause a change in delegates in PathView) + tumbler.delegate = displacementDelegate; + tumbler.model = 6; + compare(tumbler.count, 6); + + var delegate = findChild(tumbler.contentItem, "delegate" + data.index); + verify(delegate); + + tumbler.contentItem.offset = data.offset; + compare(delegate.displacement, data.expectedDisplacement); + + // test displacement after adding and removing items + } + + Component { + id: listViewTumblerComponent + + Tumbler { + id: listViewTumbler + + //! [contentItem] + contentItem: ListView { + anchors.fill: parent + model: listViewTumbler.model + delegate: listViewTumbler.delegate + + snapMode: ListView.SnapToItem + highlightRangeMode: ListView.StrictlyEnforceRange + preferredHighlightBegin: height / 2 - (height / listViewTumbler.visibleItemCount / 2) + preferredHighlightEnd: height / 2 + (height / listViewTumbler.visibleItemCount / 2) + clip: true + } + //! [contentItem] + } + } + + function test_displacementListView_data() { + var offset = defaultListViewTumblerOffset; + + var data = [ + // At 0 contentY, the first item is current. + { contentY: offset, expectedDisplacements: [ + { index: 0, displacement: 0 }, + { index: 1, displacement: -1 }, + { index: 2, displacement: -2 } ] + }, + // When we start to move the first item down, the second item above it starts to become current. + { contentY: offset + defaultImplicitDelegateHeight * 0.25, expectedDisplacements: [ + { index: 0, displacement: 0.25 }, + { index: 1, displacement: -0.75 }, + { index: 2, displacement: -1.75 } ] + }, + { contentY: offset + defaultImplicitDelegateHeight * 0.5, expectedDisplacements: [ + { index: 0, displacement: 0.5 }, + { index: 1, displacement: -0.5 }, + { index: 2, displacement: -1.5 } ] + }, + { contentY: offset + defaultImplicitDelegateHeight * 0.75, expectedDisplacements: [ + { index: 0, displacement: 0.75 }, + { index: 1, displacement: -0.25 } ] + }, + { contentY: offset + defaultImplicitDelegateHeight * 3.5, expectedDisplacements: [ + { index: 3, displacement: 0.5 }, + { index: 4, displacement: -0.5 } ] + } + ]; + for (var i = 0; i < data.length; ++i) { + var row = data[i]; + row.tag = "contentY=" + row.contentY; + } + return data; + } + + function test_displacementListView(data) { + tumbler.destroy(); + // Sanity check that they're aren't any children at this stage. + tryCompare(testCase.children, "length", 0); + + tumbler = listViewTumblerComponent.createObject(testCase); + verify(tumbler); + + tumbler.delegate = displacementDelegate; + tumbler.model = 5; + compare(tumbler.count, 5); + // Ensure assumptions about the tumbler used in our data() function are correct. + compare(tumbler.contentItem.contentY, -defaultImplicitDelegateHeight); + var delegateCount = 0; + var listView = tumbler.contentItem; + var listViewContentItem = tumbler.contentItem.contentItem; + + // We use the mouse instead of setting contentY directly, otherwise the + // items snap back into place. This doesn't seem to be an issue for + // PathView for some reason. + // + // I tried lots of things to get this test to work with small changes + // in ListView's contentY ( to match the tests for a PathView-based Tumbler), but they didn't work: + // + // - Pressing once and then directly moving the mouse to the correct location + // - Pressing once and interpolating the mouse position to the correct location + // - Pressing once and doing some dragging up and down to trigger the + // overThreshold of QQuickFlickable + // + // Even after the last item above, QQuickFlickable wouldn't consider it a drag. + // It seems that overThreshold is set too late, and because the drag distance is quite small + // to begin with, nothing changes (the displacement was always very close to 0 in the end). + + // Ensure that we at least cover the distance required to reach the desired contentY. + var distanceToReachContentY = data.contentY - defaultListViewTumblerOffset; + var distance = Math.abs(distanceToReachContentY) + tumbler.height / 2; + // If distanceToReachContentY is 0, we're testing 0 displacement, so we don't need to do anything. + if (distanceToReachContentY != 0) { + mousePress(tumbler, tumblerXCenter(), tumblerYCenter()); + + var dragDirection = distanceToReachContentY > 0 ? -1 : 1; + for (var i = 0; i < distance && Math.floor(listView.contentY) !== Math.floor(data.contentY); ++i) { + mouseMove(tumbler, tumblerXCenter(), tumblerYCenter() + i * dragDirection, 10); + } + } + + for (var i = 0; i < data.expectedDisplacements.length; ++i) { + var delegate = findChild(listViewContentItem, "delegate" + data.expectedDisplacements[i].index); + verify(delegate); + compare(delegate.height, defaultImplicitDelegateHeight); + // Due to the way we must perform this test, we can't expect high precision. + var expectedDisplacement = data.expectedDisplacements[i].displacement; + fuzzyCompare(delegate.displacement, expectedDisplacement, 0.1, + "Delegate of ListView-based Tumbler at index " + data.expectedDisplacements[i].index + + " has displacement of " + delegate.displacement + " when it should be " + expectedDisplacement); + } + + if (distanceToReachContentY != 0) + mouseRelease(tumbler, tumblerXCenter(), itemCenterPos(1) + (data.contentY - defaultListViewTumblerOffset), Qt.LeftButton); + } + + function test_listViewFlickAboveBounds_data() { + // Tests that flicking above the bounds when already at the top of the + // tumbler doesn't result in an incorrect displacement. + var data = []; + // Less than two items doesn't make sense. The default visibleItemCount + // is 3, so we test a bit more than double that. + for (var i = 2; i <= 7; ++i) { + data.push({ tag: i + " items", model: i }); + } + return data; + } + + function test_listViewFlickAboveBounds(data) { + tumbler.destroy(); + + tumbler = listViewTumblerComponent.createObject(testCase); + verify(tumbler); + + tumbler.delegate = displacementDelegate; + tumbler.model = data.model; + + mousePress(tumbler, tumblerXCenter(), tumblerYCenter()); + + // Ensure it's stationary. + var listView = tumbler.contentItem; + compare(listView.contentY, defaultListViewTumblerOffset); + + // We could just move up until the contentY changed, but this is safer. + var distance = tumbler.height; + var changed = false; + + for (var i = 0; i < distance && !changed; ++i) { + mouseMove(tumbler, tumblerXCenter(), tumblerYCenter() + i, 10); + + // Don't test until the contentY has actually changed. + if (Math.abs(listView.contentY) - listView.preferredHighlightBegin > 0.01) { + + for (var delegateIndex = 0; delegateIndex < Math.min(tumbler.count, tumbler.visibleItemCount); ++delegateIndex) { + var delegate = findChild(listView.contentItem, "delegate" + delegateIndex); + verify(delegate); + + verify(delegate.displacement <= -delegateIndex, "Delegate at index " + delegateIndex + " has a displacement of " + + delegate.displacement + " when it should be less than or equal to " + -delegateIndex); + verify(delegate.displacement > -delegateIndex - 0.1, "Delegate at index 0 has a displacement of " + + delegate.displacement + " when it should be greater than ~ " + -delegateIndex - 0.1); + } + + changed = true; + } + } + + // Sanity check that something was actually tested. + verify(changed); + + mouseRelease(tumbler, tumblerXCenter(), tumbler.topPadding); + } + + property Component objectNameDelegate: Text { + objectName: "delegate" + index + text: modelData + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + + function test_visibleItemCount_data() { + var data = [ + // e.g. {0: 2} = {delegate index: y pos / delegate height} + // Skip item at index 3, because it's out of view. + { model: 6, visibleItemCount: 5, expectedYPositions: {0: 2, 1: 3, 2: 4, 4: 0} }, + { model: 5, visibleItemCount: 3, expectedYPositions: {0: 1, 1: 2, 4: 0} }, + // Takes up the whole view. + { model: 2, visibleItemCount: 1, expectedYPositions: {0: 0} }, + ]; + + for (var i = 0; i < data.length; ++i) { + data[i].tag = "items=" + data[i].model + ", visibleItemCount=" + data[i].visibleItemCount; + } + return data; + } + + function test_visibleItemCount(data) { + tumbler.delegate = objectNameDelegate; + tumbler.visibleItemCount = data.visibleItemCount; + + tumbler.model = data.model; + compare(tumbler.count, data.model); + + for (var delegateIndex = 0; delegateIndex < data.visibleItemCount; ++delegateIndex) { + if (data.expectedYPositions.hasOwnProperty(delegateIndex)) { + var delegate = findChild(tumbler.contentItem, "delegate" + delegateIndex); + verify(delegate, "Delegate found at index " + delegateIndex); + var expectedYPos = data.expectedYPositions[delegateIndex] * tumbler.contentItem.delegateHeight; + compare(delegate.mapToItem(tumbler.contentItem, 0, 0).y, expectedYPos); + } + } + } + + property Component wrongDelegateTypeComponent: QtObject { + property real displacement: AbstractTumbler.displacement + } + + property Component noParentDelegateComponent: Item { + property real displacement: AbstractTumbler.displacement + } + + property Component gridViewComponent: GridView {} + property Component simpleDisplacementDelegate: Text { + property real displacement: AbstractTumbler.displacement + property int index: -1 + } + + function test_attachedProperties() { + // TODO: crashes somewhere in QML's guts +// tumbler.model = 5; +// tumbler.delegate = wrongDelegateTypeComponent; +// ignoreWarning("Attached properties of Tumbler must be accessed from within a delegate item"); +// // Cause displacement to be changed. The warning isn't triggered if we don't do this. +// tumbler.contentItem.offset += 1; + + ignoreWarning("Tumbler: attached properties must be accessed from within a delegate item that has a parent"); + noParentDelegateComponent.createObject(null); + + ignoreWarning("Tumbler: attempting to access attached property on item without an \"index\" property"); + var object = noParentDelegateComponent.createObject(testCase); + object.destroy(); + + // Should not be any warnings from this, as ListView, for example, doesn't produce warnings for the same code. + var gridView = gridViewComponent.createObject(testCase); + object = simpleDisplacementDelegate.createObject(gridView); + object.destroy(); + gridView.destroy(); + } + + property Component paddingDelegate: Text { + objectName: "delegate" + index + text: modelData + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + Rectangle { + anchors.fill: parent + color: "transparent" + border.color: "red" + border.width: 1 + } + } + + function test_padding_data() { + var data = []; + + data.push({ padding: 0 }); + data.push({ padding: 10 }); + data.push({ left: 10, top: 10 }); + data.push({ right: 10, bottom: 10 }); + + for (var i = 0; i < data.length; ++i) { + var tag = ""; + + if (data[i].padding !== undefined) + tag += "padding: " + data[i].padding + " "; + if (data[i].left !== undefined) + tag += "left: " + data[i].left + " "; + if (data[i].right !== undefined) + tag += "right: " + data[i].right + " "; + if (data[i].top !== undefined) + tag += "top: " + data[i].top + " "; + if (data[i].bottom !== undefined) + tag += "bottom: " + data[i].bottom + " "; + tag = tag.slice(0, -1); + + data[i].tag = tag; + } + + return data; + } + + function test_padding(data) { + tumbler.delegate = paddingDelegate; + tumbler.model = 5; + compare(tumbler.padding, 0); + compare(tumbler.leftPadding, 0); + compare(tumbler.rightPadding, 0); + compare(tumbler.topPadding, 0); + compare(tumbler.bottomPadding, 0); + compare(tumbler.contentItem.x, 0); + compare(tumbler.contentItem.y, 0); + + if (data.padding !== undefined) + tumbler.padding = data.padding; + if (data.left !== undefined) + tumbler.leftPadding = data.left; + if (data.right !== undefined) + tumbler.rightPadding = data.right; + if (data.top !== undefined) + tumbler.topPadding = data.top; + if (data.bottom !== undefined) + tumbler.bottomPadding = data.bottom; + + compare(tumbler.availableWidth, implicitTumblerWidth - tumbler.leftPadding - tumbler.rightPadding); + compare(tumbler.availableHeight, implicitTumblerHeight - tumbler.topPadding - tumbler.bottomPadding); + compare(tumbler.contentItem.x, tumbler.leftPadding); + compare(tumbler.contentItem.y, tumbler.topPadding); + + var pathView = tumbler.contentItem; + var expectedDelegateHeight = tumbler.availableHeight / tumbler.visibleItemCount; + var itemIndicesInVisualOrder = [4, 0, 1]; + for (var i = 0; i < itemIndicesInVisualOrder.length; ++i) { + var delegate = findChild(pathView, "delegate" + itemIndicesInVisualOrder[i]); + verify(delegate, "Couldn't find delegate at index " + itemIndicesInVisualOrder[i] + + " (iteration " + i + " out of " + (pathView.children.length - 1) + ")"); + + compare(delegate.width, tumbler.availableWidth); + compare(delegate.height, expectedDelegateHeight); + + var expectedY = tumbler.topPadding + i * expectedDelegateHeight; + var mappedPos = delegate.mapToItem(null, delegate.width / 2, 0); + fuzzyCompare(mappedPos.y, expectedY, 0.5, + "Tumbler's PathView delegate at index " + itemIndicesInVisualOrder[i] + + " should have a y pos of " + expectedY + ", but it's actually " + mappedPos.y.toFixed(20)); + + var expectedX = tumbler.leftPadding; + compare(delegate.mapToItem(null, 0, 0).x, expectedX, + "Tumbler's PathView delegate at index " + itemIndicesInVisualOrder[i] + + " should have a x pos of " + expectedX + ", but it's actually " + mappedPos.x.toFixed(20)); + } + + // Force new items to be created, as there was a bug where the path was correct until this happened. + compare(tumbler.contentItem.offset, 0); + ++tumbler.currentIndex; + tryCompare(tumbler.contentItem, "offset", 4, tumbler.contentItem.highlightMoveDuration * 2); + } +} diff --git a/tests/auto/extras/data/TumblerDatePicker.qml b/tests/auto/extras/data/TumblerDatePicker.qml deleted file mode 100644 index 673ed142..00000000 --- a/tests/auto/extras/data/TumblerDatePicker.qml +++ /dev/null @@ -1,88 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the test suite 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 The Qt Company Ltd 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.6 -import QtQuick.Controls 2.0 -import QtQuick.Extras 2.0 - -Row { - id: datePicker - - readonly property var days: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] - - property alias dayTumbler: dayTumbler - property alias monthTumbler: monthTumbler - property alias yearTumbler: yearTumbler - - Tumbler { - id: dayTumbler - objectName: "dayTumbler" - - Component.onCompleted: updateModel() - - function updateModel() { - var previousIndex = dayTumbler.currentIndex; - var array = []; - var newDays = datePicker.days[monthTumbler.currentIndex]; - for (var i = 0; i < newDays; ++i) { - array.push(i + 1); - } - dayTumbler.model = array; - dayTumbler.currentIndex = Math.min(newDays - 1, previousIndex); - } - } - Tumbler { - id: monthTumbler - objectName: "monthTumbler" - model: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] - onCurrentIndexChanged: dayTumbler.updateModel() - } - Tumbler { - id: yearTumbler - objectName: "yearTumbler" - model: ListModel { - Component.onCompleted: { - for (var i = 2000; i < 2100; ++i) { - append({value: i.toString()}); - } - } - } - } -} diff --git a/tests/auto/extras/data/tst_dial.qml b/tests/auto/extras/data/tst_dial.qml deleted file mode 100644 index 0d1a1124..00000000 --- a/tests/auto/extras/data/tst_dial.qml +++ /dev/null @@ -1,287 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the test suite 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 The Qt Company Ltd 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.2 -import QtTest 1.0 -import QtQuick.Extras 2.0 - -TestCase { - id: testCase - width: 200 - height: 200 - visible: true - when: windowShown - name: "Dial" - - Component { - id: dialComponent - Dial {} - } - - property var dial: null - - function init() { - dial = dialComponent.createObject(testCase); - verify(dial, "Dial: failed to create an instance"); - } - - function cleanup() { - if (dial) - dial.destroy(); - } - - function test_instance() { - compare(dial.value, 0.0); - compare(dial.from, 0.0); - compare(dial.to, 1.0); - compare(dial.stepSize, 0.0); - verify(dial.activeFocusOnTab); - verify(!dial.pressed); - } - - function test_value() { - compare(dial.value, 0.0); - compare(Math.floor(dial.handle.mapToItem(parent, 0, 0).x), 28); - compare(Math.floor(dial.handle.mapToItem(parent, 0, 0).y), 90); - - dial.value = 0.5; - compare(dial.value, 0.5); - - dial.value = 1.0; - compare(dial.value, 1.0); - - dial.value = -1.0; - compare(dial.value, 0.0); - - dial.value = 2.0; - compare(dial.value, 1.0); - } - - function test_range() { - dial.from = 0; - dial.to = 100; - dial.value = 50; - compare(dial.from, 0); - compare(dial.to, 100); - compare(dial.value, 50); - compare(dial.position, 0.5); - - dial.value = 1000 - compare(dial.value, 100); - compare(dial.position, 1); - - dial.value = -1 - compare(dial.value, 0); - compare(dial.position, 0); - - dial.from = 25 - compare(dial.from, 25); - compare(dial.value, 25); - compare(dial.position, 0); - - dial.to = 75 - compare(dial.to, 75); - compare(dial.value, 25); - compare(dial.position, 0); - - dial.value = 50 - compare(dial.value, 50); - compare(dial.position, 0.5); - } - - function test_inverted() { - dial.destroy(); - dial = dialComponent.createObject(testCase, { from: 1.0, to: -1.0 }); - verify(dial, "Dial: failed to create an instance"); - compare(dial.from, 1.0); - compare(dial.to, -1.0); - compare(dial.value, 0.0); - compare(dial.position, 0.5); - - dial.value = 2.0; - compare(dial.value, 1.0); - compare(dial.position, 0.0); - - dial.value = -2.0; - compare(dial.value, -1.0); - compare(dial.position, 1.0); - - dial.value = 0.0; - compare(dial.value, 0.0); - compare(dial.position, 0.5); - } - - SignalSpy { - id: pressSpy - signalName: "pressedChanged" - } - - function test_pressed() { - pressSpy.target = dial; - verify(pressSpy.valid); - verify(!dial.pressed); - - mousePress(dial, dial.width / 2, dial.height / 2); - verify(dial.pressed); - compare(pressSpy.count, 1); - - mouseRelease(dial, dial.width / 2, dial.height / 2); - verify(!dial.pressed); - compare(pressSpy.count, 2); - } - - SignalSpy { - id: valueSpy - signalName: "valueChanged" - } - - function test_dragging_data() { - return [ - { tag: "default", from: 0, to: 1, leftValue: 0.20, topValue: 0.5, rightValue: 0.8, bottomValue: 1.0 }, - { tag: "scaled2", from: 0, to: 2, leftValue: 0.4, topValue: 1.0, rightValue: 1.6, bottomValue: 2.0 }, - { tag: "scaled1", from: -1, to: 0, leftValue: -0.8, topValue: -0.5, rightValue: -0.2, bottomValue: 0.0 } - ] - } - - function test_dragging(data) { - dial.from = data.from; - dial.to = data.to; - - valueSpy.target = dial; - verify(valueSpy.valid); - - // drag to the left - mouseDrag(dial, dial.width / 2, dial.height / 2, -dial.width / 2, 0, Qt.LeftButton); - fuzzyCompare(dial.value, data.leftValue, 0.1); - verify(valueSpy.count > 0); - valueSpy.clear(); - - // drag to the top - mouseDrag(dial, dial.width / 2, dial.height / 2, 0, -dial.height / 2, Qt.LeftButton); - fuzzyCompare(dial.value, data.topValue, 0.1); - verify(valueSpy.count > 0); - valueSpy.clear(); - - // drag to the right - mouseDrag(dial, dial.width / 2, dial.height / 2, dial.width / 2, 0, Qt.LeftButton); - fuzzyCompare(dial.value, data.rightValue, 0.1); - verify(valueSpy.count > 0); - valueSpy.clear(); - - // drag to the bottom (* 0.6 to ensure we don't go over to the minimum position) - mouseDrag(dial, dial.width / 2, dial.height / 2, 10, dial.height / 2, Qt.LeftButton); - fuzzyCompare(dial.value, data.bottomValue, 0.1); - verify(valueSpy.count > 0); - valueSpy.clear(); - } - - property Component focusTest: Component { - FocusScope { - signal receivedKeyPress - - Component.onCompleted: forceActiveFocus() - anchors.fill: parent - Keys.onPressed: receivedKeyPress() - } - } - - SignalSpy { - id: parentEventSpy - } - - function test_keyboardNavigation() { - var focusScope = focusTest.createObject(testCase); - verify(focusScope); - - // Tests that we've accepted events that we're interested in. - parentEventSpy.target = focusScope; - parentEventSpy.signalName = "receivedKeyPress"; - - dial.parent = focusScope; - compare(dial.activeFocusOnTab, true); - compare(dial.value, 0); - - dial.focus = true; - compare(dial.activeFocus, true); - dial.stepSize = 0.1; - - keyClick(Qt.Key_Left); - compare(parentEventSpy.count, 0); - compare(dial.value, 0); - - - var keyPairs = [[Qt.Key_Left, Qt.Key_Right], [Qt.Key_Down, Qt.Key_Up]]; - for (var keyPairIndex = 0; keyPairIndex < 2; ++keyPairIndex) { - for (var i = 1; i <= 10; ++i) { - keyClick(keyPairs[keyPairIndex][1]); - compare(parentEventSpy.count, 0); - compare(dial.value, dial.stepSize * i); - } - - compare(dial.value, dial.to); - - for (i = 10; i > 0; --i) { - keyClick(keyPairs[keyPairIndex][0]); - compare(parentEventSpy.count, 0); - compare(dial.value, dial.stepSize * (i - 1)); - } - } - - compare(dial.value, dial.from); - - keyClick(Qt.Key_Home); - compare(parentEventSpy.count, 0); - compare(dial.value, dial.from); - - keyClick(Qt.Key_End); - compare(parentEventSpy.count, 0); - compare(dial.value, dial.to); - - keyClick(Qt.Key_End); - compare(parentEventSpy.count, 0); - compare(dial.value, dial.to); - - keyClick(Qt.Key_Home); - compare(parentEventSpy.count, 0); - compare(dial.value, dial.from); - - focusScope.destroy(); - } -} diff --git a/tests/auto/extras/data/tst_drawer.qml b/tests/auto/extras/data/tst_drawer.qml deleted file mode 100644 index 33919c13..00000000 --- a/tests/auto/extras/data/tst_drawer.qml +++ /dev/null @@ -1,66 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the test suite 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 The Qt Company Ltd 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.2 -import QtTest 1.0 -import QtQuick.Extras 2.0 - -TestCase { - id: testCase - width: 400 - height: 400 - visible: true - when: windowShown - name: "Drawer" - - Component { - id: drawer - Drawer { } - } - - function test_defaults() { - var control = drawer.createObject(testCase) - verify(!control.contentItem) - compare(control.edge, Qt.LeftEdge) - compare(control.position, 0.0) - verify(control.animation) - control.destroy() - } -} diff --git a/tests/auto/extras/data/tst_swipeview.qml b/tests/auto/extras/data/tst_swipeview.qml deleted file mode 100644 index 81c61f45..00000000 --- a/tests/auto/extras/data/tst_swipeview.qml +++ /dev/null @@ -1,518 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the test suite 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 The Qt Company Ltd 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.2 -import QtTest 1.0 -import QtQuick.Extras 2.0 - -TestCase { - id: testCase - width: 200 - height: 200 - visible: true - when: windowShown - name: "SwipeView" - - Component { - id: swipeView - SwipeView { } - } - - Component { - id: page - Text { } - } - - SignalSpy { - id: currentItemChangedSpy - signalName: "currentItemChanged" - } - - function cleanup() { - currentItemChangedSpy.clear() - currentItemChangedSpy.target = null - } - - function test_current() { - var control = swipeView.createObject(testCase) - - currentItemChangedSpy.target = control - - compare(control.count, 0) - compare(control.currentIndex, -1) - compare(control.currentItem, null) - - control.addItem(page.createObject(control, {text: "0"})) - compare(control.count, 1) - compare(control.currentIndex, 0) - compare(control.currentItem.text, "0") - compare(currentItemChangedSpy.count, 1); - - control.addItem(page.createObject(control, {text: "1"})) - compare(control.count, 2) - compare(control.currentIndex, 0) - compare(control.currentItem.text, "0") - compare(currentItemChangedSpy.count, 1); - - control.addItem(page.createObject(control, {text: "2"})) - compare(control.count, 3) - compare(control.currentIndex, 0) - compare(control.currentItem.text, "0") - compare(currentItemChangedSpy.count, 1); - - control.currentIndex = 1 - compare(control.currentIndex, 1) - compare(control.currentItem.text, "1") - compare(currentItemChangedSpy.count, 2); - - control.currentIndex = 2 - compare(control.currentIndex, 2) - compare(control.currentItem.text, "2") - compare(currentItemChangedSpy.count, 3); - - control.destroy() - } - - Component { - id: initialCurrentSwipeView - SwipeView { - currentIndex: 1 - - property alias item0: item0 - property alias item1: item1 - - Item { - id: item0 - } - Item { - id: item1 - } - } - } - - function test_initialCurrent() { - var control = initialCurrentSwipeView.createObject(testCase) - - compare(control.count, 2) - compare(control.currentIndex, 1) - compare(control.currentItem, control.item1) - - control.destroy() - } - - function test_addRemove() { - var control = swipeView.createObject(testCase) - - function verifyCurrentIndexCountDiff() { - verify(control.currentIndex < control.count) - } - control.currentIndexChanged.connect(verifyCurrentIndexCountDiff) - control.countChanged.connect(verifyCurrentIndexCountDiff) - - currentItemChangedSpy.target = control; - - compare(control.count, 0) - compare(control.currentIndex, -1) - compare(control.currentItem, null) - control.addItem(page.createObject(control, {text: "1"})) - compare(control.count, 1) - compare(control.currentIndex, 0) - compare(currentItemChangedSpy.count, 1) - compare(control.currentItem.text, "1") - control.addItem(page.createObject(control, {text: "2"})) - compare(control.count, 2) - compare(control.currentIndex, 0) - compare(currentItemChangedSpy.count, 1) - compare(control.currentItem.text, "1") - compare(control.itemAt(0).text, "1") - compare(control.itemAt(1).text, "2") - - control.currentIndex = 1 - compare(currentItemChangedSpy.count, 2) - - control.insertItem(1, page.createObject(control, {text: "3"})) - compare(control.count, 3) - compare(control.currentIndex, 2) - compare(control.currentItem.text, "2") - compare(control.itemAt(0).text, "1") - compare(control.itemAt(1).text, "3") - compare(control.itemAt(2).text, "2") - - control.insertItem(0, page.createObject(control, {text: "4"})) - compare(control.count, 4) - compare(control.currentIndex, 3) - compare(control.currentItem.text, "2") - compare(control.itemAt(0).text, "4") - compare(control.itemAt(1).text, "1") - compare(control.itemAt(2).text, "3") - compare(control.itemAt(3).text, "2") - - control.insertItem(control.count, page.createObject(control, {text: "5"})) - compare(control.count, 5) - compare(control.currentIndex, 3) - compare(control.currentItem.text, "2") - compare(control.itemAt(0).text, "4") - compare(control.itemAt(1).text, "1") - compare(control.itemAt(2).text, "3") - compare(control.itemAt(3).text, "2") - compare(control.itemAt(4).text, "5") - - control.removeItem(control.count - 1) - compare(control.count, 4) - compare(control.currentIndex, 3) - compare(control.currentItem.text, "2") - compare(control.itemAt(0).text, "4") - compare(control.itemAt(1).text, "1") - compare(control.itemAt(2).text, "3") - compare(control.itemAt(3).text, "2") - - control.removeItem(0) - compare(control.count, 3) - compare(control.currentIndex, 2) - compare(control.currentItem.text, "2") - compare(control.itemAt(0).text, "1") - compare(control.itemAt(1).text, "3") - compare(control.itemAt(2).text, "2") - - control.removeItem(1) - compare(control.count, 2) - compare(control.currentIndex, 1) - compare(control.currentItem.text, "2") - compare(control.itemAt(0).text, "1") - compare(control.itemAt(1).text, "2") - - currentItemChangedSpy.clear() - - control.removeItem(1) - compare(control.count, 1) - compare(control.currentIndex, 0) - compare(currentItemChangedSpy.count, 1) - compare(control.currentItem.text, "1") - compare(control.itemAt(0).text, "1") - - control.removeItem(0) - compare(control.count, 0) - compare(control.currentIndex, -1) - compare(currentItemChangedSpy.count, 2) - - control.destroy() - } - - Component { - id: contentView - SwipeView { - QtObject { objectName: "object" } - Item { objectName: "page1" } - Timer { objectName: "timer" } - Item { objectName: "page2" } - Component { Item { } } - } - } - - function test_content() { - var control = contentView.createObject(testCase) - - function compareObjectNames(content, names) { - if (content.length !== names.length) - return false - for (var i = 0; i < names.length; ++i) { - if (content[i].objectName !== names[i]) - return false - } - return true - } - - verify(compareObjectNames(control.contentData, ["object", "page1", "timer", "page2", ""])) - verify(compareObjectNames(control.contentChildren, ["page1", "page2"])) - - control.addItem(page.createObject(control, {objectName: "page3"})) - verify(compareObjectNames(control.contentData, ["object", "page1", "timer", "page2", "", "page3"])) - verify(compareObjectNames(control.contentChildren, ["page1", "page2", "page3"])) - - control.insertItem(0, page.createObject(control, {objectName: "page4"})) - verify(compareObjectNames(control.contentData, ["object", "page1", "timer", "page2", "", "page3", "page4"])) - verify(compareObjectNames(control.contentChildren, ["page4", "page1", "page2", "page3"])) - - control.moveItem(1, 2) - verify(compareObjectNames(control.contentData, ["object", "page1", "timer", "page2", "", "page3", "page4"])) - verify(compareObjectNames(control.contentChildren, ["page4", "page2", "page1", "page3"])) - - control.removeItem(0) - verify(compareObjectNames(control.contentData, ["object", "page1", "timer", "page2", "", "page3"])) - verify(compareObjectNames(control.contentChildren, ["page2", "page1", "page3"])) - - control.destroy() - } - - Component { - id: repeated - SwipeView { - property alias repeater: repeater - Repeater { - id: repeater - model: 5 - Item { property int idx: index } - } - } - } - - function test_repeater() { - var control = repeated.createObject(testCase) - verify(control) - - var model = control.contentModel - verify(model) - - var repeater = control.repeater - verify(repeater) - - compare(repeater.count, 5) - compare(model.count, 5) - - for (var i = 0; i < 5; ++i) { - var item1 = control.itemAt(i) - verify(item1) - compare(item1.idx, i) - compare(model.get(i), item1) - compare(repeater.itemAt(i), item1) - } - - repeater.model = 3 - compare(repeater.count, 3) - compare(model.count, 3) - - for (var j = 0; j < 3; ++j) { - var item2 = control.itemAt(j) - verify(item2) - compare(item2.idx, j) - compare(model.get(j), item2) - compare(repeater.itemAt(j), item2) - } - - control.destroy() - } - - Component { - id: ordered - SwipeView { - id: oview - property alias repeater: repeater - Text { text: "static_1" } - Repeater { - id: repeater - model: 2 - Text { text: "repeated_" + (index + 2) } - } - Text { text: "static_4" } - Component.onCompleted: { - addItem(page.createObject(oview, {text: "dynamic_5"})) - addItem(page.createObject(oview.contentItem, {text: "dynamic_6"})) - insertItem(0, page.createObject(oview, {text: "dynamic_0"})) - } - } - } - - function test_order() { - var control = ordered.createObject(testCase) - verify(control) - - compare(control.count, 7) - compare(control.itemAt(0).text, "dynamic_0") - compare(control.itemAt(1).text, "static_1") - compare(control.itemAt(2).text, "repeated_2") - compare(control.itemAt(3).text, "repeated_3") - compare(control.itemAt(4).text, "static_4") - compare(control.itemAt(5).text, "dynamic_5") - compare(control.itemAt(6).text, "dynamic_6") - - control.destroy() - } - - function test_move_data() { - return [ - {tag:"0->1 (0)", from: 0, to: 1, currentBefore: 0, currentAfter: 1}, - {tag:"0->1 (1)", from: 0, to: 1, currentBefore: 1, currentAfter: 0}, - {tag:"0->1 (2)", from: 0, to: 1, currentBefore: 2, currentAfter: 2}, - - {tag:"0->2 (0)", from: 0, to: 2, currentBefore: 0, currentAfter: 2}, - {tag:"0->2 (1)", from: 0, to: 2, currentBefore: 1, currentAfter: 0}, - {tag:"0->2 (2)", from: 0, to: 2, currentBefore: 2, currentAfter: 1}, - - {tag:"1->0 (0)", from: 1, to: 0, currentBefore: 0, currentAfter: 1}, - {tag:"1->0 (1)", from: 1, to: 0, currentBefore: 1, currentAfter: 0}, - {tag:"1->0 (2)", from: 1, to: 0, currentBefore: 2, currentAfter: 2}, - - {tag:"1->2 (0)", from: 1, to: 2, currentBefore: 0, currentAfter: 0}, - {tag:"1->2 (1)", from: 1, to: 2, currentBefore: 1, currentAfter: 2}, - {tag:"1->2 (2)", from: 1, to: 2, currentBefore: 2, currentAfter: 1}, - - {tag:"2->0 (0)", from: 2, to: 0, currentBefore: 0, currentAfter: 1}, - {tag:"2->0 (1)", from: 2, to: 0, currentBefore: 1, currentAfter: 2}, - {tag:"2->0 (2)", from: 2, to: 0, currentBefore: 2, currentAfter: 0}, - - {tag:"2->1 (0)", from: 2, to: 1, currentBefore: 0, currentAfter: 0}, - {tag:"2->1 (1)", from: 2, to: 1, currentBefore: 1, currentAfter: 2}, - {tag:"2->1 (2)", from: 2, to: 1, currentBefore: 2, currentAfter: 1}, - - {tag:"0->0", from: 0, to: 0, currentBefore: 0, currentAfter: 0}, - {tag:"-1->0", from: 0, to: 0, currentBefore: 1, currentAfter: 1}, - {tag:"0->-1", from: 0, to: 0, currentBefore: 2, currentAfter: 2}, - {tag:"1->10", from: 0, to: 0, currentBefore: 0, currentAfter: 0}, - {tag:"10->2", from: 0, to: 0, currentBefore: 1, currentAfter: 1}, - {tag:"10->-1", from: 0, to: 0, currentBefore: 2, currentAfter: 2} - ] - } - - Component { - id: pageAttached - - Text { - property int index: AbstractSwipeView.index - property SwipeView view: AbstractSwipeView.view - property bool isCurrentItem: AbstractSwipeView.isCurrentItem - } - } - - function test_move(data) { - var control = swipeView.createObject(testCase) - - compare(control.count, 0) - var titles = ["1", "2", "3"] - - var i = 0; - for (i = 0; i < titles.length; ++i) { - var item = pageAttached.createObject(control, {text: titles[i]}) - control.addItem(item) - } - - compare(control.count, titles.length) - for (i = 0; i < control.count; ++i) { - compare(control.itemAt(i).text, titles[i]) - compare(control.itemAt(i).AbstractSwipeView.index, i) - compare(control.itemAt(i).AbstractSwipeView.isCurrentItem, i === 0) - } - - control.currentIndex = data.currentBefore - for (i = 0; i < control.count; ++i) { - compare(control.itemAt(i).AbstractSwipeView.isCurrentItem, i === data.currentBefore) - } - - control.moveItem(data.from, data.to) - - compare(control.count, titles.length) - compare(control.currentIndex, data.currentAfter) - - var title = titles[data.from] - titles.splice(data.from, 1) - titles.splice(data.to, 0, title) - - compare(control.count, titles.length) - for (i = 0; i < control.count; ++i) { - compare(control.itemAt(i).text, titles[i]) - compare(control.itemAt(i).AbstractSwipeView.index, i); - compare(control.itemAt(i).AbstractSwipeView.isCurrentItem, i === data.currentAfter) - } - - control.destroy() - } - - Component { - id: dynamicView - SwipeView { - id: dview - Text { text: "static" } - Component.onCompleted: { - addItem(page.createObject(dview, {text: "added"})) - insertItem(0, page.createObject(dview, {text: "inserted"})) - page.createObject(dview, {text: "dynamic"}) - } - } - } - - function test_dynamic() { - var control = dynamicView.createObject(testCase) - - // insertItem(), addItem(), createObject() and static page {} - compare(control.count, 4) - compare(control.itemAt(0).text, "inserted") - - var tab = page.createObject(control, {text: "dying"}) - compare(control.count, 5) - compare(control.itemAt(4).text, "dying") - - // TODO: fix crash in QQuickItemView -// tab.destroy() -// wait(0) -// compare(control.count, 4) - - control.destroy() - } - - function test_attachedParent() { - var control = swipeView.createObject(testCase); - - var page = pageAttached.createObject(testCase); - compare(page.view, null); - compare(page.index, -1); - compare(page.isCurrentItem, false); - page.destroy(); - - page = pageAttached.createObject(null); - compare(page.view, null); - compare(page.index, -1); - compare(page.isCurrentItem, false); - - control.insertItem(0, page); - compare(control.count, 1); - compare(page.parent, control.contentItem.contentItem); - compare(page.view, control); - compare(page.index, 0); - compare(page.isCurrentItem, true); - - control.removeItem(0); - compare(control.count, 0); - compare(page.parent, null); - compare(page.view, null); - compare(page.index, -1); - compare(page.isCurrentItem, false); - - control.destroy(); - } -} diff --git a/tests/auto/extras/data/tst_tumbler.qml b/tests/auto/extras/data/tst_tumbler.qml deleted file mode 100644 index 928d53fa..00000000 --- a/tests/auto/extras/data/tst_tumbler.qml +++ /dev/null @@ -1,668 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the test suite 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 The Qt Company Ltd 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.2 -import QtTest 1.0 -import QtQuick.Extras 2.0 - -TestCase { - id: testCase - width: 200 - height: 200 - visible: true - when: windowShown - name: "Tumbler" - - property var tumbler: null - readonly property real implicitTumblerWidth: 60 - readonly property real implicitTumblerHeight: 200 - readonly property real defaultImplicitDelegateHeight: implicitTumblerHeight / 3 - readonly property real defaultListViewTumblerOffset: -defaultImplicitDelegateHeight - - function init() { - tumbler = Qt.createQmlObject("import QtQuick.Extras 2.0; Tumbler { }", testCase, ""); - verify(tumbler, "Tumbler: failed to create an instance"); - compare(tumbler.contentItem.parent, tumbler); - } - - function cleanup() { - tumbler.destroy(); - } - - function tumblerXCenter() { - return tumbler.leftPadding + tumbler.width / 2; - } - - function tumblerYCenter() { - return tumbler.topPadding + tumbler.height / 2; - } - - // visualItemIndex is from 0 to the amount of visible items. - function itemCenterPos(visualItemIndex) { - var halfDelegateHeight = tumbler.contentItem.delegateHeight / 2; - var yCenter = tumbler.y + tumbler.topPadding + halfDelegateHeight - + (tumbler.contentItem.delegateHeight * visualItemIndex); - return Qt.point(tumblerXCenter(), yCenter); - } - - function checkItemSizes() { - var contentChildren = tumbler.contentItem.hasOwnProperty("contentItem") - ? tumbler.contentItem.contentItem.children : tumbler.contentItem.children; - verify(contentChildren.length >= tumbler.count); - for (var i = 0; i < contentChildren.length; ++i) { - compare(contentChildren[i].width, tumbler.width); - compare(contentChildren[i].height, tumbler.contentItem.delegateHeight); - } - } - - function tst_dynamicContentItemChange() { - // test that currentIndex is maintained between contentItem changes... - } - - function test_currentIndex() { - tumbler.model = 5; - - compare(tumbler.currentIndex, 0); - waitForRendering(tumbler); - - // Set it through user interaction. - var pos = Qt.point(tumblerXCenter(), tumbler.height / 2); - mouseDrag(tumbler, pos.x, pos.y, 0, -tumbler.contentItem.delegateHeight / 2, Qt.LeftButton, Qt.NoModifier, 200); - compare(tumbler.currentIndex, 1); - compare(tumbler.contentItem.currentIndex, 1); - - // Set it manually. - tumbler.currentIndex = 2; - tryCompare(tumbler, "currentIndex", 2); - compare(tumbler.contentItem.currentIndex, 2); - - // PathView has 0 as its currentIndex in this case for some reason. - tumbler.model = null; - tryCompare(tumbler, "currentIndex", 0); - - tumbler.model = ["A", "B", "C"]; - tryCompare(tumbler, "currentIndex", 0); - } - - function test_keyboardNavigation() { - tumbler.model = 5; - tumbler.forceActiveFocus(); - var keyClickDelay = 100; - - // Navigate upwards through entire wheel. - for (var j = 0; j < tumbler.count - 1; ++j) { - keyClick(Qt.Key_Up, Qt.NoModifier, keyClickDelay); - tryCompare(tumbler.contentItem, "offset", j + 1); - compare(tumbler.currentIndex, tumbler.count - 1 - j); - } - - keyClick(Qt.Key_Up, Qt.NoModifier, keyClickDelay); - tryCompare(tumbler.contentItem, "offset", 0); - compare(tumbler.currentIndex, 0); - - // Navigate downwards through entire wheel. - for (j = 0; j < tumbler.count - 1; ++j) { - keyClick(Qt.Key_Down, Qt.NoModifier, keyClickDelay); - tryCompare(tumbler.contentItem, "offset", tumbler.count - 1 - j); - compare(tumbler.currentIndex, j + 1); - } - - keyClick(Qt.Key_Down, Qt.NoModifier, keyClickDelay); - tryCompare(tumbler.contentItem, "offset", 0); - compare(tumbler.currentIndex, 0); - } - - function test_itemsCorrectlyPositioned() { - tumbler.model = 4; - tumbler.height = 120; - compare(tumbler.contentItem.delegateHeight, 40); - checkItemSizes(); - - wait(tumbler.contentItem.highlightMoveDuration); - var firstItemCenterPos = itemCenterPos(1); - var firstItem = tumbler.contentItem.itemAt(firstItemCenterPos.x, firstItemCenterPos.y); - var actualPos = testCase.mapFromItem(firstItem, 0, 0); - compare(actualPos.x, tumbler.leftPadding); - compare(actualPos.y, tumbler.topPadding + 40); - - tumbler.forceActiveFocus(); - keyClick(Qt.Key_Down); - tryCompare(tumbler.contentItem, "offset", 3.0); - firstItemCenterPos = itemCenterPos(0); - firstItem = tumbler.contentItem.itemAt(firstItemCenterPos.x, firstItemCenterPos.y); - verify(firstItem); - // Test QTBUG-40298. - actualPos = testCase.mapFromItem(firstItem, 0, 0); - compare(actualPos.x, tumbler.leftPadding); - compare(actualPos.y, tumbler.topPadding); - - var secondItemCenterPos = itemCenterPos(1); - var secondItem = tumbler.contentItem.itemAt(secondItemCenterPos.x, secondItemCenterPos.y); - verify(secondItem); - verify(firstItem.y < secondItem.y); - - var thirdItemCenterPos = itemCenterPos(2); - var thirdItem = tumbler.contentItem.itemAt(thirdItemCenterPos.x, thirdItemCenterPos.y); - verify(thirdItem); - verify(firstItem.y < thirdItem.y); - verify(secondItem.y < thirdItem.y); - } - - function test_resizeAfterFlicking() { - // Test QTBUG-40367 (which is actually invalid because it was my fault :)). - tumbler.model = 100; - - // Flick in some direction. - var pos = Qt.point(tumblerXCenter(), tumbler.topPadding); - mouseDrag(tumbler, pos.x, pos.y, 0, tumbler.height - tumbler.bottomPadding, - Qt.LeftButton, Qt.NoModifier, 400); - tryCompare(tumbler.contentItem, "offset", 3.0); - - tumbler.height += 100; - compare(tumbler.contentItem.delegateHeight, - (tumbler.height - tumbler.topPadding - tumbler.bottomPadding) / tumbler.visibleItemCount); - waitForRendering(tumbler); - pos = itemCenterPos(1); - var ninetyEighthItem = tumbler.contentItem.itemAt(pos.x, pos.y); - verify(ninetyEighthItem); - } - - function test_focusPastTumbler() { - var mouseArea = Qt.createQmlObject( - "import QtQuick 2.2; TextInput { activeFocusOnTab: true; width: 50; height: 50 }", testCase, ""); - - tumbler.forceActiveFocus(); - verify(tumbler.activeFocus); - - keyClick(Qt.Key_Tab); - verify(!tumbler.activeFocus); - verify(mouseArea.activeFocus); - - mouseArea.destroy(); - } - - function test_datePicker() { - tumbler.destroy(); - - var component = Qt.createComponent("TumblerDatePicker.qml"); - compare(component.status, Component.Ready, component.errorString()); - tumbler = component.createObject(testCase); - // Should not be any warnings. - - compare(tumbler.dayTumbler.currentIndex, 0); - compare(tumbler.dayTumbler.count, 31); - compare(tumbler.monthTumbler.currentIndex, 0); - compare(tumbler.monthTumbler.count, 12); - compare(tumbler.yearTumbler.currentIndex, 0); - compare(tumbler.yearTumbler.count, 100); - - verify(tumbler.dayTumbler.contentItem.children.length >= tumbler.dayTumbler.visibleItemCount); - verify(tumbler.monthTumbler.contentItem.children.length >= tumbler.monthTumbler.visibleItemCount); - // TODO: do this properly somehow - wait(100); - verify(tumbler.yearTumbler.contentItem.children.length >= tumbler.yearTumbler.visibleItemCount); - - // March. - tumbler.monthTumbler.currentIndex = 2; - tryCompare(tumbler.monthTumbler, "currentIndex", 2); - - // 30th of March. - tumbler.dayTumbler.currentIndex = 29; - tryCompare(tumbler.dayTumbler, "currentIndex", 29); - - // February. - tumbler.monthTumbler.currentIndex = 1; - tryCompare(tumbler.monthTumbler, "currentIndex", 1); - tryCompare(tumbler.dayTumbler, "currentIndex", 27); - } - - function test_displacement_data() { - var data = [ - // At 0 offset, the first item is current. - { index: 0, offset: 0, expectedDisplacement: 0 }, - { index: 1, offset: 0, expectedDisplacement: -1 }, - { index: 5, offset: 0, expectedDisplacement: 1 }, - // When we start to move the first item down, the second item above it starts to become current. - { index: 0, offset: 0.25, expectedDisplacement: -0.25 }, - { index: 1, offset: 0.25, expectedDisplacement: -1.25 }, - { index: 5, offset: 0.25, expectedDisplacement: 0.75 }, - { index: 0, offset: 0.5, expectedDisplacement: -0.5 }, - { index: 1, offset: 0.5, expectedDisplacement: -1.5 }, - { index: 5, offset: 0.5, expectedDisplacement: 0.5 }, - // By this stage, the delegate at index 1 is destroyed, so we can't test its displacement. - { index: 0, offset: 0.75, expectedDisplacement: -0.75 }, - { index: 5, offset: 0.75, expectedDisplacement: 0.25 }, - { index: 0, offset: 4.75, expectedDisplacement: 1.25 }, - { index: 1, offset: 4.75, expectedDisplacement: 0.25 }, - { index: 0, offset: 4.5, expectedDisplacement: 1.5 }, - { index: 1, offset: 4.5, expectedDisplacement: 0.5 }, - { index: 0, offset: 4.25, expectedDisplacement: 1.75 }, - { index: 1, offset: 4.25, expectedDisplacement: 0.75 } - ]; - for (var i = 0; i < data.length; ++i) { - var row = data[i]; - row.tag = "delegate" + row.index + " offset=" + row.offset + " expectedDisplacement=" + row.expectedDisplacement; - } - return data; - } - - property Component displacementDelegate: Text { - objectName: "delegate" + index - text: modelData - opacity: 0.2 + Math.max(0, 1 - Math.abs(AbstractTumbler.displacement)) * 0.8 - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - - Text { - text: parent.displacement.toFixed(2) - anchors.right: parent.right - } - - property real displacement: AbstractTumbler.displacement - } - - function test_displacement(data) { - // TODO: test setting these in the opposite order (delegate after model - // doesn't seem to cause a change in delegates in PathView) - tumbler.delegate = displacementDelegate; - tumbler.model = 6; - compare(tumbler.count, 6); - - var delegate = findChild(tumbler.contentItem, "delegate" + data.index); - verify(delegate); - - tumbler.contentItem.offset = data.offset; - compare(delegate.displacement, data.expectedDisplacement); - - // test displacement after adding and removing items - } - - Component { - id: listViewTumblerComponent - - Tumbler { - id: listViewTumbler - - //! [contentItem] - contentItem: ListView { - anchors.fill: parent - model: listViewTumbler.model - delegate: listViewTumbler.delegate - - snapMode: ListView.SnapToItem - highlightRangeMode: ListView.StrictlyEnforceRange - preferredHighlightBegin: height / 2 - (height / listViewTumbler.visibleItemCount / 2) - preferredHighlightEnd: height / 2 + (height / listViewTumbler.visibleItemCount / 2) - clip: true - } - //! [contentItem] - } - } - - function test_displacementListView_data() { - var offset = defaultListViewTumblerOffset; - - var data = [ - // At 0 contentY, the first item is current. - { contentY: offset, expectedDisplacements: [ - { index: 0, displacement: 0 }, - { index: 1, displacement: -1 }, - { index: 2, displacement: -2 } ] - }, - // When we start to move the first item down, the second item above it starts to become current. - { contentY: offset + defaultImplicitDelegateHeight * 0.25, expectedDisplacements: [ - { index: 0, displacement: 0.25 }, - { index: 1, displacement: -0.75 }, - { index: 2, displacement: -1.75 } ] - }, - { contentY: offset + defaultImplicitDelegateHeight * 0.5, expectedDisplacements: [ - { index: 0, displacement: 0.5 }, - { index: 1, displacement: -0.5 }, - { index: 2, displacement: -1.5 } ] - }, - { contentY: offset + defaultImplicitDelegateHeight * 0.75, expectedDisplacements: [ - { index: 0, displacement: 0.75 }, - { index: 1, displacement: -0.25 } ] - }, - { contentY: offset + defaultImplicitDelegateHeight * 3.5, expectedDisplacements: [ - { index: 3, displacement: 0.5 }, - { index: 4, displacement: -0.5 } ] - } - ]; - for (var i = 0; i < data.length; ++i) { - var row = data[i]; - row.tag = "contentY=" + row.contentY; - } - return data; - } - - function test_displacementListView(data) { - tumbler.destroy(); - // Sanity check that they're aren't any children at this stage. - tryCompare(testCase.children, "length", 0); - - tumbler = listViewTumblerComponent.createObject(testCase); - verify(tumbler); - - tumbler.delegate = displacementDelegate; - tumbler.model = 5; - compare(tumbler.count, 5); - // Ensure assumptions about the tumbler used in our data() function are correct. - compare(tumbler.contentItem.contentY, -defaultImplicitDelegateHeight); - var delegateCount = 0; - var listView = tumbler.contentItem; - var listViewContentItem = tumbler.contentItem.contentItem; - - // We use the mouse instead of setting contentY directly, otherwise the - // items snap back into place. This doesn't seem to be an issue for - // PathView for some reason. - // - // I tried lots of things to get this test to work with small changes - // in ListView's contentY ( to match the tests for a PathView-based Tumbler), but they didn't work: - // - // - Pressing once and then directly moving the mouse to the correct location - // - Pressing once and interpolating the mouse position to the correct location - // - Pressing once and doing some dragging up and down to trigger the - // overThreshold of QQuickFlickable - // - // Even after the last item above, QQuickFlickable wouldn't consider it a drag. - // It seems that overThreshold is set too late, and because the drag distance is quite small - // to begin with, nothing changes (the displacement was always very close to 0 in the end). - - // Ensure that we at least cover the distance required to reach the desired contentY. - var distanceToReachContentY = data.contentY - defaultListViewTumblerOffset; - var distance = Math.abs(distanceToReachContentY) + tumbler.height / 2; - // If distanceToReachContentY is 0, we're testing 0 displacement, so we don't need to do anything. - if (distanceToReachContentY != 0) { - mousePress(tumbler, tumblerXCenter(), tumblerYCenter()); - - var dragDirection = distanceToReachContentY > 0 ? -1 : 1; - for (var i = 0; i < distance && Math.floor(listView.contentY) !== Math.floor(data.contentY); ++i) { - mouseMove(tumbler, tumblerXCenter(), tumblerYCenter() + i * dragDirection, 10); - } - } - - for (var i = 0; i < data.expectedDisplacements.length; ++i) { - var delegate = findChild(listViewContentItem, "delegate" + data.expectedDisplacements[i].index); - verify(delegate); - compare(delegate.height, defaultImplicitDelegateHeight); - // Due to the way we must perform this test, we can't expect high precision. - var expectedDisplacement = data.expectedDisplacements[i].displacement; - fuzzyCompare(delegate.displacement, expectedDisplacement, 0.1, - "Delegate of ListView-based Tumbler at index " + data.expectedDisplacements[i].index - + " has displacement of " + delegate.displacement + " when it should be " + expectedDisplacement); - } - - if (distanceToReachContentY != 0) - mouseRelease(tumbler, tumblerXCenter(), itemCenterPos(1) + (data.contentY - defaultListViewTumblerOffset), Qt.LeftButton); - } - - function test_listViewFlickAboveBounds_data() { - // Tests that flicking above the bounds when already at the top of the - // tumbler doesn't result in an incorrect displacement. - var data = []; - // Less than two items doesn't make sense. The default visibleItemCount - // is 3, so we test a bit more than double that. - for (var i = 2; i <= 7; ++i) { - data.push({ tag: i + " items", model: i }); - } - return data; - } - - function test_listViewFlickAboveBounds(data) { - tumbler.destroy(); - - tumbler = listViewTumblerComponent.createObject(testCase); - verify(tumbler); - - tumbler.delegate = displacementDelegate; - tumbler.model = data.model; - - mousePress(tumbler, tumblerXCenter(), tumblerYCenter()); - - // Ensure it's stationary. - var listView = tumbler.contentItem; - compare(listView.contentY, defaultListViewTumblerOffset); - - // We could just move up until the contentY changed, but this is safer. - var distance = tumbler.height; - var changed = false; - - for (var i = 0; i < distance && !changed; ++i) { - mouseMove(tumbler, tumblerXCenter(), tumblerYCenter() + i, 10); - - // Don't test until the contentY has actually changed. - if (Math.abs(listView.contentY) - listView.preferredHighlightBegin > 0.01) { - - for (var delegateIndex = 0; delegateIndex < Math.min(tumbler.count, tumbler.visibleItemCount); ++delegateIndex) { - var delegate = findChild(listView.contentItem, "delegate" + delegateIndex); - verify(delegate); - - verify(delegate.displacement <= -delegateIndex, "Delegate at index " + delegateIndex + " has a displacement of " - + delegate.displacement + " when it should be less than or equal to " + -delegateIndex); - verify(delegate.displacement > -delegateIndex - 0.1, "Delegate at index 0 has a displacement of " - + delegate.displacement + " when it should be greater than ~ " + -delegateIndex - 0.1); - } - - changed = true; - } - } - - // Sanity check that something was actually tested. - verify(changed); - - mouseRelease(tumbler, tumblerXCenter(), tumbler.topPadding); - } - - property Component objectNameDelegate: Text { - objectName: "delegate" + index - text: modelData - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - } - - function test_visibleItemCount_data() { - var data = [ - // e.g. {0: 2} = {delegate index: y pos / delegate height} - // Skip item at index 3, because it's out of view. - { model: 6, visibleItemCount: 5, expectedYPositions: {0: 2, 1: 3, 2: 4, 4: 0} }, - { model: 5, visibleItemCount: 3, expectedYPositions: {0: 1, 1: 2, 4: 0} }, - // Takes up the whole view. - { model: 2, visibleItemCount: 1, expectedYPositions: {0: 0} }, - ]; - - for (var i = 0; i < data.length; ++i) { - data[i].tag = "items=" + data[i].model + ", visibleItemCount=" + data[i].visibleItemCount; - } - return data; - } - - function test_visibleItemCount(data) { - tumbler.delegate = objectNameDelegate; - tumbler.visibleItemCount = data.visibleItemCount; - - tumbler.model = data.model; - compare(tumbler.count, data.model); - - for (var delegateIndex = 0; delegateIndex < data.visibleItemCount; ++delegateIndex) { - if (data.expectedYPositions.hasOwnProperty(delegateIndex)) { - var delegate = findChild(tumbler.contentItem, "delegate" + delegateIndex); - verify(delegate, "Delegate found at index " + delegateIndex); - var expectedYPos = data.expectedYPositions[delegateIndex] * tumbler.contentItem.delegateHeight; - compare(delegate.mapToItem(tumbler.contentItem, 0, 0).y, expectedYPos); - } - } - } - - property Component wrongDelegateTypeComponent: QtObject { - property real displacement: AbstractTumbler.displacement - } - - property Component noParentDelegateComponent: Item { - property real displacement: AbstractTumbler.displacement - } - - property Component gridViewComponent: GridView {} - property Component simpleDisplacementDelegate: Text { - property real displacement: AbstractTumbler.displacement - property int index: -1 - } - - function test_attachedProperties() { - // TODO: crashes somewhere in QML's guts -// tumbler.model = 5; -// tumbler.delegate = wrongDelegateTypeComponent; -// ignoreWarning("Attached properties of Tumbler must be accessed from within a delegate item"); -// // Cause displacement to be changed. The warning isn't triggered if we don't do this. -// tumbler.contentItem.offset += 1; - - ignoreWarning("Tumbler: attached properties must be accessed from within a delegate item that has a parent"); - noParentDelegateComponent.createObject(null); - - ignoreWarning("Tumbler: attempting to access attached property on item without an \"index\" property"); - var object = noParentDelegateComponent.createObject(testCase); - object.destroy(); - - // Should not be any warnings from this, as ListView, for example, doesn't produce warnings for the same code. - var gridView = gridViewComponent.createObject(testCase); - object = simpleDisplacementDelegate.createObject(gridView); - object.destroy(); - gridView.destroy(); - } - - property Component paddingDelegate: Text { - objectName: "delegate" + index - text: modelData - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - - Rectangle { - anchors.fill: parent - color: "transparent" - border.color: "red" - border.width: 1 - } - } - - function test_padding_data() { - var data = []; - - data.push({ padding: 0 }); - data.push({ padding: 10 }); - data.push({ left: 10, top: 10 }); - data.push({ right: 10, bottom: 10 }); - - for (var i = 0; i < data.length; ++i) { - var tag = ""; - - if (data[i].padding !== undefined) - tag += "padding: " + data[i].padding + " "; - if (data[i].left !== undefined) - tag += "left: " + data[i].left + " "; - if (data[i].right !== undefined) - tag += "right: " + data[i].right + " "; - if (data[i].top !== undefined) - tag += "top: " + data[i].top + " "; - if (data[i].bottom !== undefined) - tag += "bottom: " + data[i].bottom + " "; - tag = tag.slice(0, -1); - - data[i].tag = tag; - } - - return data; - } - - function test_padding(data) { - tumbler.delegate = paddingDelegate; - tumbler.model = 5; - compare(tumbler.padding, 0); - compare(tumbler.leftPadding, 0); - compare(tumbler.rightPadding, 0); - compare(tumbler.topPadding, 0); - compare(tumbler.bottomPadding, 0); - compare(tumbler.contentItem.x, 0); - compare(tumbler.contentItem.y, 0); - - if (data.padding !== undefined) - tumbler.padding = data.padding; - if (data.left !== undefined) - tumbler.leftPadding = data.left; - if (data.right !== undefined) - tumbler.rightPadding = data.right; - if (data.top !== undefined) - tumbler.topPadding = data.top; - if (data.bottom !== undefined) - tumbler.bottomPadding = data.bottom; - - compare(tumbler.availableWidth, implicitTumblerWidth - tumbler.leftPadding - tumbler.rightPadding); - compare(tumbler.availableHeight, implicitTumblerHeight - tumbler.topPadding - tumbler.bottomPadding); - compare(tumbler.contentItem.x, tumbler.leftPadding); - compare(tumbler.contentItem.y, tumbler.topPadding); - - var pathView = tumbler.contentItem; - var expectedDelegateHeight = tumbler.availableHeight / tumbler.visibleItemCount; - var itemIndicesInVisualOrder = [4, 0, 1]; - for (var i = 0; i < itemIndicesInVisualOrder.length; ++i) { - var delegate = findChild(pathView, "delegate" + itemIndicesInVisualOrder[i]); - verify(delegate, "Couldn't find delegate at index " + itemIndicesInVisualOrder[i] - + " (iteration " + i + " out of " + (pathView.children.length - 1) + ")"); - - compare(delegate.width, tumbler.availableWidth); - compare(delegate.height, expectedDelegateHeight); - - var expectedY = tumbler.topPadding + i * expectedDelegateHeight; - var mappedPos = delegate.mapToItem(null, delegate.width / 2, 0); - fuzzyCompare(mappedPos.y, expectedY, 0.5, - "Tumbler's PathView delegate at index " + itemIndicesInVisualOrder[i] - + " should have a y pos of " + expectedY + ", but it's actually " + mappedPos.y.toFixed(20)); - - var expectedX = tumbler.leftPadding; - compare(delegate.mapToItem(null, 0, 0).x, expectedX, - "Tumbler's PathView delegate at index " + itemIndicesInVisualOrder[i] - + " should have a x pos of " + expectedX + ", but it's actually " + mappedPos.x.toFixed(20)); - } - - // Force new items to be created, as there was a bug where the path was correct until this happened. - compare(tumbler.contentItem.offset, 0); - ++tumbler.currentIndex; - tryCompare(tumbler.contentItem, "offset", 4, tumbler.contentItem.highlightMoveDuration * 2); - } -} diff --git a/tests/auto/extras/extras.pro b/tests/auto/extras/extras.pro deleted file mode 100644 index 434e4196..00000000 --- a/tests/auto/extras/extras.pro +++ /dev/null @@ -1,12 +0,0 @@ -TEMPLATE = app -TARGET = tst_extras -CONFIG += qmltestcase - -SOURCES += \ - $$PWD/tst_extras.cpp - -TESTDATA += \ - $$PWD/data/* - -OTHER_FILES += \ - $$PWD/data/* diff --git a/tests/auto/extras/tst_extras.cpp b/tests/auto/extras/tst_extras.cpp deleted file mode 100644 index 057176d1..00000000 --- a/tests/auto/extras/tst_extras.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -QUICK_TEST_MAIN(tst_extras) diff --git a/tests/auto/sanity/tst_sanity.cpp b/tests/auto/sanity/tst_sanity.cpp index a32502f0..1b9eebdd 100644 --- a/tests/auto/sanity/tst_sanity.cpp +++ b/tests/auto/sanity/tst_sanity.cpp @@ -149,7 +149,6 @@ void tst_Sanity::initTestCase() foreach (const QString &path, engine.importPathList()) { files.unite(listQmlFiles(QDir(path + "/QtQuick/Calendar.2"))); files.unite(listQmlFiles(QDir(path + "/QtQuick/Controls.2"))); - files.unite(listQmlFiles(QDir(path + "/QtQuick/Extras.2"))); } } diff --git a/tests/auto/snippets/data/dial/qtquickextras2-dial-background.qml b/tests/auto/snippets/data/dial/qtquickextras2-dial-background.qml index bdd95411..b9a48498 100644 --- a/tests/auto/snippets/data/dial/qtquickextras2-dial-background.qml +++ b/tests/auto/snippets/data/dial/qtquickextras2-dial-background.qml @@ -1,5 +1,5 @@ import QtQuick 2.0 -import QtQuick.Extras 2.0 +import QtQuick.Controls 2.0 Dial { Rectangle { diff --git a/tests/auto/snippets/data/dial/qtquickextras2-dial-handle.qml b/tests/auto/snippets/data/dial/qtquickextras2-dial-handle.qml index f7ab5d4d..9851478e 100644 --- a/tests/auto/snippets/data/dial/qtquickextras2-dial-handle.qml +++ b/tests/auto/snippets/data/dial/qtquickextras2-dial-handle.qml @@ -1,5 +1,5 @@ import QtQuick 2.0 -import QtQuick.Extras 2.0 +import QtQuick.Controls 2.0 Dial { id: dial diff --git a/tests/auto/snippets/data/tumbler/qtquickextras2-tumbler-background.qml b/tests/auto/snippets/data/tumbler/qtquickextras2-tumbler-background.qml index 93fc9e5e..5a9832c4 100644 --- a/tests/auto/snippets/data/tumbler/qtquickextras2-tumbler-background.qml +++ b/tests/auto/snippets/data/tumbler/qtquickextras2-tumbler-background.qml @@ -1,5 +1,5 @@ import QtQuick 2.0 -import QtQuick.Extras 2.0 +import QtQuick.Controls 2.0 Tumbler { model: 5 diff --git a/tests/auto/snippets/data/tumbler/qtquickextras2-tumbler-contentItem.qml b/tests/auto/snippets/data/tumbler/qtquickextras2-tumbler-contentItem.qml index 0bb25dff..51a0a7bb 100644 --- a/tests/auto/snippets/data/tumbler/qtquickextras2-tumbler-contentItem.qml +++ b/tests/auto/snippets/data/tumbler/qtquickextras2-tumbler-contentItem.qml @@ -1,5 +1,5 @@ import QtQuick 2.0 -import QtQuick.Extras 2.0 +import QtQuick.Controls 2.0 Tumbler { model: 5 diff --git a/tests/auto/snippets/data/tumbler/qtquickextras2-tumbler-delegate.qml b/tests/auto/snippets/data/tumbler/qtquickextras2-tumbler-delegate.qml index 2b775c11..d7f02c0c 100644 --- a/tests/auto/snippets/data/tumbler/qtquickextras2-tumbler-delegate.qml +++ b/tests/auto/snippets/data/tumbler/qtquickextras2-tumbler-delegate.qml @@ -1,5 +1,5 @@ import QtQuick 2.0 -import QtQuick.Extras 2.0 +import QtQuick.Controls 2.0 Tumbler { id: tumbler diff --git a/tests/benchmarks/creationtime/tst_creationtime.cpp b/tests/benchmarks/creationtime/tst_creationtime.cpp index 47416045..9185d5b5 100644 --- a/tests/benchmarks/creationtime/tst_creationtime.cpp +++ b/tests/benchmarks/creationtime/tst_creationtime.cpp @@ -50,9 +50,6 @@ private slots: void calendar(); void calendar_data(); - void extras(); - void extras_data(); - private: QQmlEngine engine; }; @@ -128,20 +125,6 @@ void tst_CreationTime::calendar_data() addTestRows(engine.importPathList(), "QtQuick/Calendar.2"); } -void tst_CreationTime::extras() -{ - QFETCH(QByteArray, control); - QQmlComponent component(&engine); - component.setData("import QtQuick.Extras 2.0;" + control + "{}", QUrl()); - doBenchmark(&component); -} - -void tst_CreationTime::extras_data() -{ - QTest::addColumn("control"); - addTestRows(engine.importPathList(), "QtQuick/Extras.2"); -} - QTEST_MAIN(tst_CreationTime) #include "tst_creationtime.moc" diff --git a/tests/manual/gifs/data/qtquickcontrols2-tumbler-wrap.qml b/tests/manual/gifs/data/qtquickcontrols2-tumbler-wrap.qml new file mode 100644 index 00000000..1fcaeba7 --- /dev/null +++ b/tests/manual/gifs/data/qtquickcontrols2-tumbler-wrap.qml @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite 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 The Qt Company Ltd 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.6 +import QtQuick.Controls 2.0 + +Item { + width: 200 + height: 200 + + Frame { + padding: 0 + anchors.centerIn: parent + width: row.implicitWidth + height: row.implicitHeight + + FontMetrics { + id: fontMetrics + } + + Component { + id: delegateComponent + + Text { + text: modelData.toString().length < 2 ? "0" + modelData : modelData + color: "#666666" + opacity: 0.4 + Math.max(0, 1 - Math.abs(AbstractTumbler.displacement)) * 0.6 + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + font.pixelSize: fontMetrics.font.pixelSize * 1.25 + } + } + + Row { + id: row + + Tumbler { + id: hoursTumbler + model: 12 + delegate: Text { + text: (modelData.toString().length < 2 ? "0" : "") + (modelData + 1) + color: "#666666" + opacity: 0.4 + Math.max(0, 1 - Math.abs(AbstractTumbler.displacement)) * 0.6 + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + font.pixelSize: fontMetrics.font.pixelSize * 1.25 + } + width: 50 + height: 150 + } + + Tumbler { + id: minutesTumbler + currentIndex: 6 + model: 60 + delegate: delegateComponent + width: 50 + height: 150 + } + + Tumbler { + id: amPmTumbler + model: ["AM", "PM"] + delegate: delegateComponent + width: 50 + height: 150 + contentItem: ListView { + anchors.fill: parent + model: amPmTumbler.model + delegate: amPmTumbler.delegate + + snapMode: ListView.SnapToItem + highlightRangeMode: ListView.StrictlyEnforceRange + preferredHighlightBegin: height / 2 - (height / 3 / 2) + preferredHighlightEnd: height / 2 + (height / 3 / 2) + clip: true + } + } + } + } +} diff --git a/tests/manual/gifs/data/qtquickextras2-tumbler-wrap.qml b/tests/manual/gifs/data/qtquickextras2-tumbler-wrap.qml deleted file mode 100644 index e2517d53..00000000 --- a/tests/manual/gifs/data/qtquickextras2-tumbler-wrap.qml +++ /dev/null @@ -1,119 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the test suite 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 The Qt Company Ltd 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.6 -import QtQuick.Controls 2.0 -import QtQuick.Extras 2.0 - -Item { - width: 200 - height: 200 - - Frame { - padding: 0 - anchors.centerIn: parent - width: row.implicitWidth - height: row.implicitHeight - - FontMetrics { - id: fontMetrics - } - - Component { - id: delegateComponent - - Text { - text: modelData.toString().length < 2 ? "0" + modelData : modelData - color: "#666666" - opacity: 0.4 + Math.max(0, 1 - Math.abs(AbstractTumbler.displacement)) * 0.6 - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - font.pixelSize: fontMetrics.font.pixelSize * 1.25 - } - } - - Row { - id: row - - Tumbler { - id: hoursTumbler - model: 12 - delegate: Text { - text: (modelData.toString().length < 2 ? "0" : "") + (modelData + 1) - color: "#666666" - opacity: 0.4 + Math.max(0, 1 - Math.abs(AbstractTumbler.displacement)) * 0.6 - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - font.pixelSize: fontMetrics.font.pixelSize * 1.25 - } - width: 50 - height: 150 - } - - Tumbler { - id: minutesTumbler - currentIndex: 6 - model: 60 - delegate: delegateComponent - width: 50 - height: 150 - } - - Tumbler { - id: amPmTumbler - model: ["AM", "PM"] - delegate: delegateComponent - width: 50 - height: 150 - contentItem: ListView { - anchors.fill: parent - model: amPmTumbler.model - delegate: amPmTumbler.delegate - - snapMode: ListView.SnapToItem - highlightRangeMode: ListView.StrictlyEnforceRange - preferredHighlightBegin: height / 2 - (height / 3 / 2) - preferredHighlightEnd: height / 2 + (height / 3 / 2) - clip: true - } - } - } - } -} diff --git a/tests/manual/gifs/tst_gifs.cpp b/tests/manual/gifs/tst_gifs.cpp index da33eec0..a74fa894 100644 --- a/tests/manual/gifs/tst_gifs.cpp +++ b/tests/manual/gifs/tst_gifs.cpp @@ -81,7 +81,7 @@ void tst_Gifs::tumblerWrap() gifRecorder.setDataDirPath(dataDirPath); gifRecorder.setOutputDir(outputDir); gifRecorder.setRecordingDuration(4); - gifRecorder.setQmlFileName("qtquickextras2-tumbler-wrap.qml"); + gifRecorder.setQmlFileName("qtquickcontrols2-tumbler-wrap.qml"); gifRecorder.setView(&view); view.show(); -- cgit v1.2.3