diff options
Diffstat (limited to 'tests/auto')
-rw-r--r-- | tests/auto/controls/data/splitview/fillItemInMiddle.qml | 77 | ||||
-rw-r--r-- | tests/auto/controls/data/splitview/fillItemOnLeft.qml | 77 | ||||
-rw-r--r-- | tests/auto/controls/data/splitview/fillItemOnTop.qml | 78 | ||||
-rw-r--r-- | tests/auto/controls/data/tst_splitview.qml | 1923 | ||||
-rw-r--r-- | tests/auto/controls/default/tst_default.cpp | 1 | ||||
-rw-r--r-- | tests/auto/controls/fusion/tst_fusion.cpp | 1 | ||||
-rw-r--r-- | tests/auto/controls/imagine/tst_imagine.cpp | 1 | ||||
-rw-r--r-- | tests/auto/controls/material/tst_material.cpp | 1 | ||||
-rw-r--r-- | tests/auto/controls/universal/tst_universal.cpp | 1 | ||||
-rw-r--r-- | tests/auto/shared/qtest_quickcontrols.h | 4 |
10 files changed, 2155 insertions, 9 deletions
diff --git a/tests/auto/controls/data/splitview/fillItemInMiddle.qml b/tests/auto/controls/data/splitview/fillItemInMiddle.qml new file mode 100644 index 00000000..33aa5a8b --- /dev/null +++ b/tests/auto/controls/data/splitview/fillItemInMiddle.qml @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, 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.12 +import QtQuick.Controls 2.5 + +SplitView { + anchors.fill: parent + + Rectangle { + objectName: "salmon" + color: objectName + implicitWidth: 25 + implicitHeight: 25 + } + Rectangle { + objectName: "navajowhite" + color: objectName + implicitWidth: 100 + implicitHeight: 100 + + SplitView.fillWidth: true + } + Rectangle { + objectName: "steelblue" + color: objectName + implicitWidth: 200 + implicitHeight: 200 + } +} diff --git a/tests/auto/controls/data/splitview/fillItemOnLeft.qml b/tests/auto/controls/data/splitview/fillItemOnLeft.qml new file mode 100644 index 00000000..ca20652b --- /dev/null +++ b/tests/auto/controls/data/splitview/fillItemOnLeft.qml @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, 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.12 +import QtQuick.Controls 2.5 + +SplitView { + anchors.fill: parent + + Rectangle { + objectName: "salmon" + color: objectName + implicitWidth: 25 + implicitHeight: 25 + + SplitView.fillWidth: true + } + Rectangle { + objectName: "navajowhite" + color: objectName + implicitWidth: 200 + implicitHeight: 200 + } + Rectangle { + objectName: "steelblue" + color: objectName + implicitWidth: 200 + implicitHeight: 200 + } +} diff --git a/tests/auto/controls/data/splitview/fillItemOnTop.qml b/tests/auto/controls/data/splitview/fillItemOnTop.qml new file mode 100644 index 00000000..ea7aa2b6 --- /dev/null +++ b/tests/auto/controls/data/splitview/fillItemOnTop.qml @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, 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.12 +import QtQuick.Controls 2.5 + +SplitView { + anchors.fill: parent + orientation: Qt.Vertical + + Rectangle { + objectName: "salmon" + color: objectName + implicitWidth: 25 + implicitHeight: 25 + + SplitView.fillHeight: true + } + Rectangle { + objectName: "navajowhite" + color: objectName + implicitWidth: 200 + implicitHeight: 200 + } + Rectangle { + objectName: "steelblue" + color: objectName + implicitWidth: 200 + implicitHeight: 200 + } +} diff --git a/tests/auto/controls/data/tst_splitview.qml b/tests/auto/controls/data/tst_splitview.qml new file mode 100644 index 00000000..28c00179 --- /dev/null +++ b/tests/auto/controls/data/tst_splitview.qml @@ -0,0 +1,1923 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, 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.12 +import QtQuick.Controls 2.5 +import QtQuick.Window 2.5 +import QtTest 1.0 +import Qt.labs.settings 1.0 + +TestCase { + id: testCase + width: 400 + height: 400 + visible: true + when: windowShown + name: "SplitView" + + function initTestCase() { + // For the serialization tests. + Qt.application.name = "qtquickcontrols2-splitview-auto-test" + Qt.application.domain = "org.qt-project" + Qt.application.organization = "Qt Project" + } + + function findHandles(splitView) { + var handles = [] + for (var i = 0; i < splitView.children.length; ++i) { + var child = splitView.children[i] + if (child.objectName.toLowerCase().indexOf("handle") !== -1) + handles.push(child) + } + return handles + } + + function compareSizes(control, expectedGeometries, context) { + if (context === undefined) + context = "" + else + context = " (" + context + ")" + + compare(control.count, Math.floor(expectedGeometries.length / 2) + 1, + "Mismatch in actual vs expected number of split items" + context) + + var handles = findHandles(control) + compare(handles.length, Math.floor(expectedGeometries.length / 2), + "Mismatch in actual vs expected number of handle items" + context) + + for (var i = 0, splitItemIndex = 0, handleItemIndex = 0; i < expectedGeometries.length; ++i) { + var item = null + var itemType = "" + var typeSpecificIndex = -1 + if (i % 2 == 0) { + item = control.itemAt(splitItemIndex) + itemType = "split item" + typeSpecificIndex = splitItemIndex + ++splitItemIndex + } else { + item = handles[handleItemIndex] + itemType = "handle item" + typeSpecificIndex = handleItemIndex + ++handleItemIndex + } + + verify(item, itemType + " at index " + typeSpecificIndex + " should not be null" + context) + + var expectedGeometry = expectedGeometries[i] + if (expectedGeometry.hasOwnProperty("hidden")) { + // It's geometry doesn't matter because it's hidden. + verify(!item.visible, itemType + " at index " + typeSpecificIndex + " should be hidden" + context) + continue + } + + // Note that the indices mentioned here account for handles; they do not + // match the indices reported by QQuickSplitView's logging categories. + compare(item.x, expectedGeometry.x, "Mismatch in actual vs expected x value of " + + itemType + " at index " + typeSpecificIndex + context) + compare(item.y, expectedGeometry.y, "Mismatch in actual vs expected y value of " + + itemType + " at index " + typeSpecificIndex + context) + compare(item.width, expectedGeometry.width, "Mismatch in actual vs expected width value of " + + itemType + " at index " + typeSpecificIndex + context) + compare(item.height, expectedGeometry.height, "Mismatch in actual vs expected height value of " + + itemType + " at index " + typeSpecificIndex + context) + } + } + + property real defaultHorizontalHandleWidth: 10 + property real defaultVerticalHandleHeight: 10 + + + Component { + id: signalSpyComponent + SignalSpy {} + } + + Component { + id: handleComponent + Rectangle { + objectName: "handle" + implicitWidth: defaultHorizontalHandleWidth + implicitHeight: defaultVerticalHandleHeight + color: "#444" + } + } + + SplitView { + id: dummyHorizontalSplitView + handle: handleComponent + + Item { objectName: "dummyItem" } + Item { objectName: "dummyItem" } + } + + SplitView { + id: dummyVerticalSplitView + orientation: Qt.Vertical + handle: handleComponent + + Item { objectName: "dummyItem" } + Item { objectName: "dummyItem" } + } + + Component { + id: splitViewComponent + + SplitView { + anchors.fill: parent + handle: handleComponent + } + } + + Component { + id: rectangleComponent + + Rectangle {} + } + + function test_addItemsAfterCompletion() { + var control = createTemporaryObject(splitViewComponent, testCase) + verify(control) + + var item0 = rectangleComponent.createObject(control, { implicitWidth: 25, color: "salmon" }) + verify(item0) + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) + // The last item fills the width by default, and since there is only one item... + compare(item0.x, 0) + compare(item0.y, 0) + compare(item0.width, testCase.width) + compare(item0.height, testCase.height) + + var item1 = rectangleComponent.createObject(control, { implicitWidth: 25, color: "steelblue" }) + verify(item1) + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) + // Now that a second item has been added, the first item goes back to its preferred (implicit) width. + compare(item0.x, 0) + compare(item0.y, 0) + compare(item0.width, item0.implicitWidth) + compare(item0.height, testCase.height) + var handles = findHandles(control) + var handle0 = handles[0] + compare(handle0.x, item0.implicitWidth) + compare(handle0.y, 0) + compare(handle0.width, defaultHorizontalHandleWidth) + compare(handle0.height, testCase.height) + compare(item1.x, item0.implicitWidth + defaultHorizontalHandleWidth) + compare(item1.y, 0) + compare(item1.width, testCase.width - item0.implicitWidth - defaultHorizontalHandleWidth) + compare(item1.height, testCase.height) + } + + function test_addItemsWithNoSizeAfterCompletion() { + var control = createTemporaryObject(splitViewComponent, testCase) + verify(control) + + var item0 = rectangleComponent.createObject(control, { color: "salmon" }) + verify(item0) + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) + compare(item0.x, 0) + compare(item0.y, 0) + compare(item0.width, testCase.width) + compare(item0.height, testCase.height) + + var item1 = rectangleComponent.createObject(control, { color: "steelblue" }) + verify(item1) + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) + compare(item0.x, 0) + compare(item0.y, 0) + compare(item0.width, 0) + compare(item0.height, testCase.height) + var handles = findHandles(control) + var handle0 = handles[0] + compare(handle0.x, 0) + compare(handle0.y, 0) + compare(handle0.width, defaultHorizontalHandleWidth) + compare(handle0.height, testCase.height) + compare(item1.x, defaultHorizontalHandleWidth) + compare(item1.y, 0) + compare(item1.width, testCase.width - defaultHorizontalHandleWidth) + compare(item1.height, testCase.height) + } + + Component { + id: threeZeroSizedItemsComponent + + SplitView { + anchors.fill: parent + handle: handleComponent + + Rectangle { + objectName: "salmon" + color: objectName + } + Rectangle { + objectName: "navajowhite" + color: objectName + } + Rectangle { + objectName: "steelblue" + color: objectName + } + } + } + + function test_changeAttachedPropertiesAfterCompletion() { + var control = createTemporaryObject(threeZeroSizedItemsComponent, testCase) + verify(control) + + var item0 = control.itemAt(0) + compare(item0.x, 0) + compare(item0.y, 0) + compare(item0.width, 0) + compare(item0.height, testCase.height) + + var handles = findHandles(control) + var handle0 = handles[0] + compare(handle0.x, 0) + compare(handle0.y, 0) + compare(handle0.width, defaultHorizontalHandleWidth) + compare(handle0.height, testCase.height) + + var item1 = control.itemAt(1) + compare(item1.x, defaultHorizontalHandleWidth) + compare(item1.y, 0) + compare(item1.width, 0) + compare(item1.height, testCase.height) + + var handle1 = handles[1] + compare(handle1.x, defaultHorizontalHandleWidth) + compare(handle1.y, 0) + compare(handle1.width, defaultHorizontalHandleWidth) + compare(handle1.height, testCase.height) + + var item2 = control.itemAt(2) + compare(item2.x, defaultHorizontalHandleWidth * 2) + compare(item2.y, 0) + compare(item2.width, testCase.width - item2.x) + compare(item2.height, testCase.height) + + item0.SplitView.preferredWidth = 25 + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) + compare(item0.x, 0) + compare(item0.y, 0) + compare(item0.width, 25) + compare(item0.height, testCase.height) + compare(handle0.x, item0.width) + compare(handle0.y, 0) + compare(handle0.width, defaultHorizontalHandleWidth) + compare(handle0.height, testCase.height) + compare(item1.x, 25 + defaultHorizontalHandleWidth) + compare(item1.y, 0) + compare(item1.width, 0) + compare(item1.height, testCase.height) + compare(handle1.x, item1.x + item1.width) + compare(handle1.y, 0) + compare(handle1.width, defaultHorizontalHandleWidth) + compare(handle1.height, testCase.height) + compare(item2.x, item1.x + item1.width + defaultHorizontalHandleWidth) + compare(item2.y, 0) + compare(item2.width, testCase.width - item2.x) + compare(item2.height, testCase.height) + + item0.SplitView.minimumWidth = 50 + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) + compare(item0.x, 0) + compare(item0.y, 0) + compare(item0.width, 50) + compare(item0.height, testCase.height) + compare(handle0.x, item0.width) + compare(handle0.y, 0) + compare(handle0.width, defaultHorizontalHandleWidth) + compare(handle0.height, testCase.height) + compare(item1.x, 50 + defaultHorizontalHandleWidth) + compare(item1.y, 0) + compare(item1.width, 0) + compare(item1.height, testCase.height) + compare(handle1.x, item1.x + item1.width) + compare(handle1.y, 0) + compare(handle1.width, defaultHorizontalHandleWidth) + compare(handle1.height, testCase.height) + compare(item2.x, item1.x + item1.width + defaultHorizontalHandleWidth) + compare(item2.y, 0) + compare(item2.width, testCase.width - item2.x) + compare(item2.height, testCase.height) + + item0.SplitView.preferredWidth = 100 + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) + compare(item0.x, 0) + compare(item0.y, 0) + compare(item0.width, 100) + compare(item0.height, testCase.height) + compare(handle0.x, item0.width) + compare(handle0.y, 0) + compare(handle0.width, defaultHorizontalHandleWidth) + compare(handle0.height, testCase.height) + compare(item1.x, 100 + defaultHorizontalHandleWidth) + compare(item1.y, 0) + compare(item1.width, 0) + compare(item1.height, testCase.height) + compare(handle1.x, item1.x + item1.width) + compare(handle1.y, 0) + compare(handle1.width, defaultHorizontalHandleWidth) + compare(handle1.height, testCase.height) + compare(item2.x, item1.x + item1.width + defaultHorizontalHandleWidth) + compare(item2.y, 0) + compare(item2.width, testCase.width - item2.x) + compare(item2.height, testCase.height) + + item0.SplitView.maximumWidth = 75 + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) + compare(item0.x, 0) + compare(item0.y, 0) + compare(item0.width, 75) + compare(item0.height, testCase.height) + compare(handle0.x, item0.width) + compare(handle0.y, 0) + compare(handle0.width, defaultHorizontalHandleWidth) + compare(handle0.height, testCase.height) + compare(item1.x, 75 + defaultHorizontalHandleWidth) + compare(item1.y, 0) + compare(item1.width, 0) + compare(item1.height, testCase.height) + compare(handle1.x, item1.x + item1.width) + compare(handle1.y, 0) + compare(handle1.width, defaultHorizontalHandleWidth) + compare(handle1.height, testCase.height) + compare(item2.x, item1.x + item1.width + defaultHorizontalHandleWidth) + compare(item2.y, 0) + compare(item2.width, testCase.width - item2.x) + compare(item2.height, testCase.height) + + item1.SplitView.fillWidth = true + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) + compare(item0.x, 0) + compare(item0.y, 0) + compare(item0.width, 75) + compare(item0.height, testCase.height) + compare(handle0.x, item0.width) + compare(handle0.y, 0) + compare(handle0.width, defaultHorizontalHandleWidth) + compare(handle0.height, testCase.height) + compare(item1.x, 75 + defaultHorizontalHandleWidth) + compare(item1.y, 0) + compare(item1.width, testCase.width - 75 - defaultHorizontalHandleWidth * 2) + compare(item1.height, testCase.height) + compare(handle1.x, item1.x + item1.width) + compare(handle1.y, 0) + compare(handle1.width, defaultHorizontalHandleWidth) + compare(handle1.height, testCase.height) + compare(item2.x, testCase.width) + compare(item2.y, 0) + compare(item2.width, 0) + compare(item2.height, testCase.height) + } + + function test_useAttachedPropertiesIncorrectly() { + var control = createTemporaryObject(splitViewComponent, testCase) + verify(control) + + var item = rectangleComponent.createObject(control, { implicitWidth: 25, color: "salmon" }) + verify(item) + + ignoreWarning(/.*SplitView: attached properties must be accessed through a direct child of SplitView/) + testCase.SplitView.fillWidth = true; + } + + function test_sizes_data() { + var splitViewWidth = testCase.width + var splitViewHeight = testCase.height + var data = [ + { + // When the combined size of items is too large, the non-fill items should just exceed + // the size of the SplitView, exactly as they would were they in a RowLayout, for example. + tag: "fillItemOnLeft", + expectedGeometries: [ + // We're the fill item, but since the combined implicitWidths + // of the other two items take up all the space, we get none. + { x: 0, y: 0, width: 0, height: splitViewHeight }, + // First handle. + { x: 0, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + // The second item does not fill, so its width should be unchanged. + { x: defaultHorizontalHandleWidth, y: 0, width: 200, height: splitViewHeight }, + // Second handle. + { x: 200 + defaultHorizontalHandleWidth, y: 0, width: defaultHorizontalHandleWidth, + height: splitViewHeight }, + // The third item also gets its implicitWidth. + { x: 200 + defaultHorizontalHandleWidth * 2, y: 0, width: 200, height: splitViewHeight } + ] + }, + { + // Same as above except vertical. + tag: "fillItemOnTop", + expectedGeometries: [ + // We're the fill item, but since the combined implicitHeights + // of the other two items take up all the space, we get none. + { x: 0, y: 0, width: splitViewWidth, height: 0 }, + // First handle. + { x: 0, y: 0, width: splitViewWidth, height: defaultVerticalHandleHeight }, + // The second item does not fill, so its height should be unchanged. + { x: 0, y: defaultVerticalHandleHeight, width: splitViewWidth, height: 200 }, + // Second handle. + { x: 0, y: 200 + defaultVerticalHandleHeight, width: splitViewWidth, + height: defaultVerticalHandleHeight }, + // The third item also gets its implicitHeight. + { x: 0, y: 200 + defaultVerticalHandleHeight * 2, width: splitViewWidth, height: 200 } + ] + }, + { + tag: "fillItemInMiddle", + expectedGeometries: [ + // Our size is fixed. + { x: 0, y: 0, width: 25, height: splitViewHeight }, + // First handle. + { x: 25, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + // The second item fills. + { x: 25 + defaultHorizontalHandleWidth, y: 0, + width: splitViewWidth - 25 - 200 - defaultHorizontalHandleWidth * 2, height: splitViewHeight }, + // Second handle. + { x: splitViewWidth - 200 - defaultHorizontalHandleWidth, y: 0, + width: defaultHorizontalHandleWidth, height: splitViewHeight }, + // The third item's size is also fixed. + { x: splitViewWidth - 200, y: 0, width: 200, height: splitViewHeight } + ] + } + ] + return data + } + + function test_sizes(data) { + var component = Qt.createComponent("splitview/" + data.tag + ".qml") + compare(component.status, Component.Ready, component.errorString()); + var control = createTemporaryObject(component, testCase, { "handle": handleComponent }) + verify(control) + + compareSizes(control, data.expectedGeometries) + } + + Component { + id: threeSizedItemsComponent + + SplitView { + anchors.fill: parent + handle: handleComponent + + Rectangle { + objectName: "salmon" + color: objectName + implicitWidth: 25 + implicitHeight: 25 + } + Rectangle { + objectName: "navajowhite" + color: objectName + implicitWidth: 100 + implicitHeight: 100 + } + Rectangle { + objectName: "steelblue" + color: objectName + implicitWidth: 200 + implicitHeight: 200 + } + } + } + + function test_resetAttachedProperties_data() { + var splitViewWidth = testCase.width + var splitViewHeight = testCase.height + var data = [ + { + tag: "resetMinimumWidth", + orientation: Qt.Horizontal, + // Set the minimumWidth to 50. It should be used instead of implicitWidth since it's greater than 25. + splitItemIndex: 0, + propertyName: "minimumWidth", + propertyValue: 50, + expectedGeometriesBefore: [ + { x: 0, y: 0, width: 50, height: splitViewHeight }, + { x: 50, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + { x: 50 + defaultHorizontalHandleWidth, y: 0, width: 100, height: splitViewHeight }, + { x: 50 + 100 + defaultHorizontalHandleWidth, y: 0, width: defaultHorizontalHandleWidth, + height: splitViewHeight }, + { x: 50 + 100 + defaultHorizontalHandleWidth * 2, y: 0, + width: splitViewWidth - 50 - 100 - defaultHorizontalHandleWidth * 2, height: splitViewHeight } + ], + // minimumWidth is now undefined, so implicitWidth should be used instead. + expectedGeometriesAfter: [ + { x: 0, y: 0, width: 25, height: splitViewHeight }, + { x: 25, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + { x: 25 + defaultHorizontalHandleWidth, y: 0, width: 100, height: splitViewHeight }, + { x: 25 + 100 + defaultHorizontalHandleWidth, y: 0, width: defaultHorizontalHandleWidth, + height: splitViewHeight }, + { x: 25 + 100 + defaultHorizontalHandleWidth * 2, y: 0, + width: splitViewWidth - 25 - 100 - defaultHorizontalHandleWidth * 2, height: splitViewHeight } + ] + }, + { + tag: "resetMinimumHeight", + orientation: Qt.Vertical, + // Set the minimumHeight to 50. It should be used instead of implicitHeight since it's greater than 25. + splitItemIndex: 0, + propertyName: "minimumHeight", + propertyValue: 50, + expectedGeometriesBefore: [ + { x: 0, y: 0, width: splitViewWidth, height: 50 }, + { x: 0, y: 50, width: splitViewWidth, height: defaultVerticalHandleHeight }, + { x: 0, y: 50 + defaultVerticalHandleHeight, width: splitViewWidth, height: 100 }, + { x: 0, y: 50 + 100 + defaultVerticalHandleHeight, width: splitViewWidth, + height: defaultVerticalHandleHeight }, + { x: 0, y: 50 + 100 + defaultVerticalHandleHeight * 2, width: splitViewWidth, + height: splitViewHeight - 50 - 100 - defaultVerticalHandleHeight * 2 } + ], + // preferredHeight is now undefined, so implicitHeight should be used instead. + expectedGeometriesAfter: [ + { x: 0, y: 0, width: splitViewWidth, height: 25 }, + { x: 0, y: 25, width: splitViewWidth, height: defaultVerticalHandleHeight }, + { x: 0, y: 25 + defaultVerticalHandleHeight, width: splitViewWidth, height: 100 }, + { x: 0, y: 25 + 100 + defaultVerticalHandleHeight, width: splitViewWidth, + height: defaultVerticalHandleHeight }, + { x: 0, y: 25 + 100 + defaultVerticalHandleHeight * 2, width: splitViewWidth, + height: splitViewHeight - 25 - 100 - defaultVerticalHandleHeight * 2 } + ] + }, + { + tag: "resetPreferredWidth", + orientation: Qt.Horizontal, + // Set the preferredWidth to 50; it should be used instead of implicitWidth. + splitItemIndex: 0, + propertyName: "preferredWidth", + propertyValue: 50, + expectedGeometriesBefore: [ + { x: 0, y: 0, width: 50, height: splitViewHeight }, + { x: 50, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + { x: 50 + defaultHorizontalHandleWidth, y: 0, width: 100, height: splitViewHeight }, + { x: 50 + 100 + defaultHorizontalHandleWidth, y: 0, width: defaultHorizontalHandleWidth, + height: splitViewHeight }, + { x: 50 + 100 + defaultHorizontalHandleWidth * 2, y: 0, + width: splitViewWidth - 50 - 100 - defaultHorizontalHandleWidth * 2, height: splitViewHeight } + ], + // preferredWidth is now undefined, so implicitWidth should be used instead. + expectedGeometriesAfter: [ + { x: 0, y: 0, width: 25, height: splitViewHeight }, + { x: 25, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + { x: 25 + defaultHorizontalHandleWidth, y: 0, width: 100, height: splitViewHeight }, + { x: 25 + 100 + defaultHorizontalHandleWidth, y: 0, width: defaultHorizontalHandleWidth, + height: splitViewHeight }, + { x: 25 + 100 + defaultHorizontalHandleWidth * 2, y: 0, + width: splitViewWidth - 25 - 100 - defaultHorizontalHandleWidth * 2, height: splitViewHeight } + ] + }, + { + tag: "resetPreferredHeight", + orientation: Qt.Vertical, + // Set the preferredHeight to 50; it should be used instead of implicitHeight. + splitItemIndex: 0, + propertyName: "preferredHeight", + propertyValue: 50, + expectedGeometriesBefore: [ + { x: 0, y: 0, width: splitViewWidth, height: 50 }, + { x: 0, y: 50, width: splitViewWidth, height: defaultVerticalHandleHeight }, + { x: 0, y: 50 + defaultVerticalHandleHeight, width: splitViewWidth, height: 100 }, + { x: 0, y: 50 + 100 + defaultVerticalHandleHeight, width: splitViewWidth, + height: defaultVerticalHandleHeight }, + { x: 0, y: 50 + 100 + defaultVerticalHandleHeight * 2, width: splitViewWidth, + height: splitViewHeight - 50 - 100 - defaultVerticalHandleHeight * 2 } + ], + // preferredHeight is now undefined, so implicitHeight should be used instead. + expectedGeometriesAfter: [ + { x: 0, y: 0, width: splitViewWidth, height: 25 }, + { x: 0, y: 25, width: splitViewWidth, height: defaultVerticalHandleHeight }, + { x: 0, y: 25 + defaultVerticalHandleHeight, width: splitViewWidth, height: 100 }, + { x: 0, y: 25 + 100 + defaultVerticalHandleHeight, width: splitViewWidth, + height: defaultVerticalHandleHeight }, + { x: 0, y: 25 + 100 + defaultVerticalHandleHeight * 2, width: splitViewWidth, + height: splitViewHeight - 25 - 100 - defaultVerticalHandleHeight * 2 } + ] + }, + { + tag: "resetMaximumWidth", + orientation: Qt.Horizontal, + // Set the maximumWidth to 15. It should be used instead of implicitWidth since it's less than 25. + splitItemIndex: 0, + propertyName: "maximumWidth", + propertyValue: 15, + expectedGeometriesBefore: [ + { x: 0, y: 0, width: 15, height: splitViewHeight }, + { x: 15, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + { x: 15 + defaultHorizontalHandleWidth, y: 0, width: 100, height: splitViewHeight }, + { x: 15 + 100 + defaultHorizontalHandleWidth, y: 0, width: defaultHorizontalHandleWidth, + height: splitViewHeight }, + { x: 15 + 100 + defaultHorizontalHandleWidth * 2, y: 0, + width: splitViewWidth - 15 - 100 - defaultHorizontalHandleWidth * 2, height: splitViewHeight } + ], + // maximumWidth is now undefined, so implicitWidth should be used instead. + expectedGeometriesAfter: [ + { x: 0, y: 0, width: 25, height: splitViewHeight }, + { x: 25, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + { x: 25 + defaultHorizontalHandleWidth, y: 0, width: 100, height: splitViewHeight }, + { x: 25 + 100 + defaultHorizontalHandleWidth, y: 0, width: defaultHorizontalHandleWidth, + height: splitViewHeight }, + { x: 25 + 100 + defaultHorizontalHandleWidth * 2, y: 0, + width: splitViewWidth - 25 - 100 - defaultHorizontalHandleWidth * 2, height: splitViewHeight } + ] + }, + { + tag: "resetMaximumHeight", + orientation: Qt.Vertical, + // Set the preferredHeight to 15. It should be used instead of implicitHeight if it's not undefined. + splitItemIndex: 0, + propertyName: "maximumHeight", + propertyValue: 15, + expectedGeometriesBefore: [ + { x: 0, y: 0, width: splitViewWidth, height: 15 }, + { x: 0, y: 15, width: splitViewWidth, height: defaultVerticalHandleHeight }, + { x: 0, y: 15 + defaultVerticalHandleHeight, width: splitViewWidth, height: 100 }, + { x: 0, y: 15 + 100 + defaultVerticalHandleHeight, width: splitViewWidth, + height: defaultVerticalHandleHeight }, + { x: 0, y: 15 + 100 + defaultVerticalHandleHeight * 2, width: splitViewWidth, + height: splitViewHeight - 15 - 100 - defaultVerticalHandleHeight * 2 } + ], + // preferredHeight is now undefined, so implicitHeight should be used instead. + expectedGeometriesAfter: [ + { x: 0, y: 0, width: splitViewWidth, height: 25 }, + { x: 0, y: 25, width: splitViewWidth, height: defaultVerticalHandleHeight }, + { x: 0, y: 25 + defaultVerticalHandleHeight, width: splitViewWidth, height: 100 }, + { x: 0, y: 25 + 100 + defaultVerticalHandleHeight, width: splitViewWidth, + height: defaultVerticalHandleHeight }, + { x: 0, y: 25 + 100 + defaultVerticalHandleHeight * 2, width: splitViewWidth, + height: splitViewHeight - 25 - 100 - defaultVerticalHandleHeight * 2 } + ] + }, + ] + return data; + } + + function test_resetAttachedProperties(data) { + var control = createTemporaryObject(threeSizedItemsComponent, testCase, + { "orientation": data.orientation }) + verify(control) + + var splitItem = control.itemAt(data.splitItemIndex) + splitItem.SplitView[data.propertyName] = data.propertyValue + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) + compareSizes(control, data.expectedGeometriesBefore, "after setting attached property") + + splitItem.SplitView[data.propertyName] = undefined + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) + compareSizes(control, data.expectedGeometriesAfter, "after resetting attached property") + } + + function test_orientation() { + var control = createTemporaryObject(threeSizedItemsComponent, testCase) + verify(control) + + var item0 = control.itemAt(0) + compare(item0.x, 0) + compare(item0.y, 0) + compare(item0.width, item0.implicitWidth) + compare(item0.height, testCase.height) + + var handles = findHandles(control) + var handle0 = handles[0] + compare(handle0.x, item0.implicitWidth) + compare(handle0.y, 0) + compare(handle0.width, defaultHorizontalHandleWidth) + compare(handle0.height, testCase.height) + + var item1 = control.itemAt(1) + compare(item1.x, item0.width + defaultHorizontalHandleWidth) + compare(item1.y, 0) + compare(item1.width, item1.implicitWidth) + compare(item1.height, testCase.height) + + var handle1 = handles[1] + compare(handle1.x, item1.x + item1.width) + compare(handle1.y, 0) + compare(handle1.width, defaultHorizontalHandleWidth) + compare(handle1.height, testCase.height) + + var item2 = control.itemAt(2) + compare(item2.x, item0.width + item1.width + defaultHorizontalHandleWidth * 2) + compare(item2.y, 0) + compare(item2.width, testCase.width - item2.x) + compare(item2.height, testCase.height) + + control.orientation = Qt.Vertical + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) + compare(item0.x, 0) + compare(item0.y, 0) + compare(item0.width, testCase.width) + compare(item0.height, item0.implicitHeight) + handles = findHandles(control) + handle0 = handles[0] + compare(handle0.x, 0) + compare(handle0.y, item0.implicitHeight) + compare(handle0.width, testCase.width) + compare(handle0.height, defaultVerticalHandleHeight) + compare(item1.x, 0) + compare(item1.y, item0.height + defaultVerticalHandleHeight) + compare(item1.width, testCase.width) + compare(item1.height, item1.implicitHeight) + handle1 = handles[1] + compare(handle1.x, 0) + compare(handle1.y, item1.y + item1.height) + compare(handle1.width, testCase.width) + compare(handle1.height, defaultVerticalHandleHeight) + compare(item2.x, 0) + compare(item2.y, item0.height + item1.height + defaultVerticalHandleHeight * 2) + compare(item2.width, testCase.width) + compare(item2.height, testCase.height - item2.y) + } + + readonly property int splitViewMargins: 50 + + Component { + id: threeItemsMinSizeAndFillComponent + + SplitView { + anchors.fill: parent + handle: handleComponent + + Rectangle { + objectName: "salmon" + color: objectName + implicitWidth: 25 + implicitHeight: 25 + SplitView.minimumWidth: 25 + SplitView.minimumHeight: 25 + SplitView.fillWidth: true + SplitView.fillHeight: true + } + Rectangle { + objectName: "navajowhite" + color: objectName + implicitWidth: 100 + implicitHeight: 100 + } + Rectangle { + objectName: "steelblue" + color: objectName + implicitWidth: 200 + implicitHeight: 200 + } + } + } + + function test_dragHandle_data() { + var splitViewWidth = testCase.width - splitViewMargins * 2 + var splitViewHeight = testCase.height - splitViewMargins * 2 + var data = [ + { + tag: "fillThirdItemAndDragFirstHandlePastRightSide", + component: threeSizedItemsComponent, + orientation: Qt.Horizontal, + // The index of the item that will fill. + fillIndex: 2, + // The index of the handle to be dragged. + handleIndex: 0, + // The position where the center of the handle will be. + newHandlePos: Qt.point(testCase.width + 20, testCase.height / 2), + // The expected geometry of each item managed by the SplitView before dragging the handle. + expectedGeometriesBeforeDrag: [ + // First item. + { x: 0, y: 0, width: 25, height: splitViewHeight }, + // First handle. + { x: 25, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + // Second item. + { x: 25 + defaultHorizontalHandleWidth, y: 0, width: 100, height: splitViewHeight }, + // Second handle. + { x: 25 + 100 + defaultHorizontalHandleWidth, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + // Third item (fills). + { x: 25 + 100 + defaultHorizontalHandleWidth * 2, y: 0, + width: splitViewWidth - 25 - 100 - defaultHorizontalHandleWidth * 2, height: splitViewHeight } + ], + // The expected geometry of each item managed by the SplitView after dragging the handle. + expectedGeometriesAfterDrag: [ + // The fill item is to the right of the handle at index 0, so the handle belongs + // to the left item: us. We should consume all of the fill item's width. + { x: 0, y: 0, width: splitViewWidth - 100 - defaultHorizontalHandleWidth * 2, + height: splitViewHeight }, + // First handle. + { x: splitViewWidth - defaultHorizontalHandleWidth * 2 - 100, + y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + // The second item does not fill, so its width should be unchanged. + { x: splitViewWidth - 100 - defaultHorizontalHandleWidth, + y: 0, width: 100, height: splitViewHeight }, + // Second handle. + { x: splitViewWidth - defaultHorizontalHandleWidth, + y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + // The last item does fill, so it should lose all of its width. + { x: splitViewWidth, y: 0, width: 0, height: splitViewHeight } + ] + }, + { + tag: "fillThirdItemAndDragFirstHandlePastBottomSide", + component: threeSizedItemsComponent, + orientation: Qt.Vertical, + fillIndex: 2, + handleIndex: 0, + newHandlePos: Qt.point(testCase.width / 2, testCase.height + 20), + expectedGeometriesBeforeDrag: [ + { x: 0, y: 0, width: splitViewWidth, height: 25 }, + { x: 0, y: 25, width: splitViewWidth, height: defaultVerticalHandleHeight }, + { x: 0, y: 25 + defaultVerticalHandleHeight, width: splitViewWidth, height: 100 }, + { x: 0, y: 25 + 100 + defaultVerticalHandleHeight, width: splitViewWidth, height: defaultVerticalHandleHeight }, + { x: 0, y: 25 + 100 + defaultVerticalHandleHeight * 2, + width: splitViewWidth, height: splitViewHeight - 25 - 100 - defaultVerticalHandleHeight * 2 } + ], + // The expected geometry of each item managed by the SplitView after dragging the handle. + expectedGeometriesAfterDrag: [ + // The fill item is to the bottom of the handle at index 0, so the handle belongs + // to the top item: us. We should consume all of the fill item's width. + { x: 0, y: 0, width: splitViewWidth, + height: splitViewHeight - 100 - defaultVerticalHandleHeight * 2 }, + // First handle. + { x: 0, y: splitViewHeight - defaultVerticalHandleHeight * 2 - 100, + width: splitViewWidth, height: defaultVerticalHandleHeight }, + // The second item does not fill, so its height should be unchanged. + { x: 0, y: splitViewWidth - 100 - defaultVerticalHandleHeight, + width: splitViewWidth, height: 100 }, + // Second handle. + { x: 0, y: splitViewHeight - defaultVerticalHandleHeight, + width: splitViewWidth, height: defaultVerticalHandleHeight }, + // The last item does fill, so it should lose all of its width. + { x: 0, y: splitViewHeight, width: splitViewWidth, height: 0 } + ] + }, + { + tag: "fillThirdItemAndDragSecondHandlePastLeftSide", + component: threeSizedItemsComponent, + orientation: Qt.Horizontal, + fillIndex: 2, + handleIndex: 1, + newHandlePos: Qt.point(-20, testCase.height / 2), + expectedGeometriesBeforeDrag: [ + { x: 0, y: 0, width: 25, height: splitViewHeight }, + { x: 25, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + { x: 25 + defaultHorizontalHandleWidth, y: 0, width: 100, height: splitViewHeight }, + { x: 25 + 100 + defaultHorizontalHandleWidth, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + { x: 25 + 100 + defaultHorizontalHandleWidth * 2, y: 0, + width: splitViewWidth - 25 - 100 - defaultHorizontalHandleWidth * 2, height: splitViewHeight } + ], + expectedGeometriesAfterDrag: [ + // The fill item is to the right of the handle at index 1, so the handle belongs + // to the second item; our width should be unchanged. + { x: 0, y: 0, width: 25, height: splitViewHeight }, + // First handle. + { x: 25, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + // The second item is the one being resized, and since we're dragging its handle + // to the left, its width should decrease. + { x: 25 + defaultHorizontalHandleWidth, y: 0, width: 0, height: splitViewHeight }, + // Second handle. + { x: 25 + defaultHorizontalHandleWidth, y: 0, width: defaultHorizontalHandleWidth, + height: splitViewHeight }, + // The last item fills, so it should get the second item's lost width. + { x: 25 + defaultHorizontalHandleWidth * 2, y: 0, + width: splitViewWidth - 25 - defaultHorizontalHandleWidth * 2, height: splitViewHeight } + ] + }, + { + tag: "fillThirdItemAndDragSecondHandlePastTopSide", + component: threeSizedItemsComponent, + orientation: Qt.Vertical, + fillIndex: 2, + handleIndex: 1, + newHandlePos: Qt.point(testCase.width / 2, -20), + expectedGeometriesBeforeDrag: [ + { x: 0, y: 0, width: splitViewWidth, height: 25 }, + { x: 0, y: 25, width: splitViewWidth, height: defaultVerticalHandleHeight }, + { x: 0, y: 25 + defaultVerticalHandleHeight, width: splitViewWidth, height: 100 }, + { x: 0, y: 25 + 100 + defaultVerticalHandleHeight, width: splitViewWidth, height: defaultVerticalHandleHeight }, + { x: 0, y: 25 + 100 + defaultVerticalHandleHeight * 2, + width: splitViewWidth, height: splitViewHeight - 25 - 100 - defaultVerticalHandleHeight * 2 } + ], + expectedGeometriesAfterDrag: [ + // The fill item is to the bottom of the handle at index 1, so the handle belongs + // to the second item; our height should be unchanged. + { x: 0, y: 0, width: splitViewWidth, height: 25 }, + // First handle. + { x: 0, y: 25, width: splitViewWidth, height: defaultVerticalHandleHeight }, + // The second item is the one being resized, and since we're dragging its handle + // to the top, its height should decrease. + { x: 0, y: 25 + defaultVerticalHandleHeight, width: splitViewWidth, height: 0 }, + // Second handle. + { x: 0, y: 25 + defaultVerticalHandleHeight, width: splitViewWidth, + height: defaultVerticalHandleHeight }, + // The last item fills, so it should get the second item's lost height. + { x: 0, y: 25 + defaultVerticalHandleHeight * 2, + width: splitViewWidth, height: splitViewHeight - 25 - defaultVerticalHandleHeight * 2 } + ] + }, + { + // First item should start off empty and then eventually take up all of 3rd item's space + // as the handle is dragged past the right side. + tag: "fillFirstItemAndDragSecondHandlePastRightSide", + component: threeSizedItemsComponent, + orientation: Qt.Horizontal, + fillIndex: 0, + handleIndex: 1, + newHandlePos: Qt.point(testCase.width + 20, testCase.height / 2), + expectedGeometriesBeforeDrag: [ + { x: 0, y: 0, width: 0, height: splitViewHeight }, + { x: 0, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + { x: defaultHorizontalHandleWidth, y: 0, width: 100, height: splitViewHeight }, + { x: 100 + defaultHorizontalHandleWidth, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + { x: 100 + defaultHorizontalHandleWidth * 2, y: 0, width: 200, height: splitViewHeight } + ], + expectedGeometriesAfterDrag: [ + // The fill item is to the left of the handle at index 1, so the handle belongs + // to the third item. Since we're moving the handle to the right side of the + // SplitView, our width should grow as we consume the width of the third item. + { x: 0, y: 0, width: splitViewWidth - 100 - defaultHorizontalHandleWidth * 2, height: splitViewHeight }, + // First handle. + { x: splitViewWidth - 100 - defaultHorizontalHandleWidth * 2, y: 0, + width: defaultHorizontalHandleWidth, height: splitViewHeight }, + // The second item's width remains unchanged. + { x: splitViewWidth - 100 - defaultHorizontalHandleWidth, y: 0, width: 100, height: splitViewHeight }, + // Second handle. + { x: splitViewWidth - defaultHorizontalHandleWidth, y: 0, + width: defaultHorizontalHandleWidth, height: splitViewHeight }, + // The last item loses its width. + { x: splitViewWidth, y: 0, width: 0, height: splitViewHeight } + ] + }, + { + // First item should start off empty and then eventually take up all of 3rd item's space + // as the handle is dragged past the bottom side. + tag: "fillFirstItemAndDragSecondHandlePastBottomSide", + component: threeSizedItemsComponent, + orientation: Qt.Vertical, + fillIndex: 0, + handleIndex: 1, + newHandlePos: Qt.point(testCase.width / 2, testCase.height + 20), + expectedGeometriesBeforeDrag: [ + { x: 0, y: 0, width: splitViewWidth, height: 0 }, + { x: 0, y: 0, width: splitViewWidth, height: defaultVerticalHandleHeight }, + { x: 0, y: defaultVerticalHandleHeight, width: splitViewWidth, height: 100 }, + { x: 0, y: 100 + defaultVerticalHandleHeight, width: splitViewWidth, height: defaultVerticalHandleHeight }, + { x: 0, y: 100 + defaultVerticalHandleHeight * 2, width: splitViewWidth, height: 200 } + ], + expectedGeometriesAfterDrag: [ + // The fill item is to the top of the handle at index 1, so the handle belongs + // to the third item. Since we're moving the handle to the bottom side of the + // SplitView, our height should grow as we consume the height of the third item. + { x: 0, y: 0, width: splitViewWidth, height: splitViewHeight - 100 - defaultVerticalHandleHeight * 2 }, + // First handle. + { x: 0, y: splitViewHeight - 100 - defaultVerticalHandleHeight * 2, + width: splitViewWidth, height: defaultVerticalHandleHeight }, + // The second item's width remains unchanged. + { x: 0, y: splitViewHeight - 100 - defaultVerticalHandleHeight, width: splitViewWidth, height: 100 }, + // Second handle. + { x: 0, y: splitViewHeight - defaultVerticalHandleHeight, + width: splitViewWidth, height: defaultVerticalHandleHeight }, + // The last item loses its width. + { x: 0, y: splitViewHeight, width: splitViewHeight, height: 0 } + ] + }, + { + tag: "fillFirstItemAndDragFirstHandlePastLeftSide", + component: threeSizedItemsComponent, + orientation: Qt.Horizontal, + fillIndex: 0, + handleIndex: 0, + newHandlePos: Qt.point(-20, testCase.height / 2), + expectedGeometriesBeforeDrag: [ + { x: 0, y: 0, width: 0, height: splitViewHeight }, + { x: 0, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + { x: defaultHorizontalHandleWidth, y: 0, width: 100, height: splitViewHeight }, + { x: 100 + defaultHorizontalHandleWidth, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + // The second item's implicitWidth is 100, and ours is 200. The available width is 300, + // so both items get their implicit widths. + { x: 100 + defaultHorizontalHandleWidth * 2, y: 0, width: splitViewWidth - 100, height: splitViewHeight } + ], + // Should be unchanged. + expectedGeometriesAfterDrag: [ + { x: 0, y: 0, width: 0, height: splitViewHeight }, + { x: 0, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + { x: defaultHorizontalHandleWidth, y: 0, width: 100, height: splitViewHeight }, + { x: 100 + defaultHorizontalHandleWidth, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + { x: 100 + defaultHorizontalHandleWidth * 2, y: 0, width: splitViewWidth - 100, height: splitViewHeight } + ] + }, + { + tag: "fillFirstItemWithMinWidthAndDragFirstHandlePastLeftSide", + component: threeItemsMinSizeAndFillComponent, + orientation: Qt.Horizontal, + fillIndex: 0, + handleIndex: 0, + newHandlePos: Qt.point(-20, testCase.height / 2), + expectedGeometriesBeforeDrag: [ + { x: 0, y: 0, width: 25, height: splitViewHeight }, + { x: 25, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + { x: 25 + defaultHorizontalHandleWidth, y: 0, width: 100, height: splitViewHeight }, + { x: 25 + 100 + defaultHorizontalHandleWidth, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + { x: 25 + 100 + defaultHorizontalHandleWidth * 2, y: 0, width: splitViewWidth - 100, height: splitViewHeight } + ], + // Should be unchanged. + expectedGeometriesAfterDrag: [ + { x: 0, y: 0, width: 25, height: splitViewHeight }, + { x: 25, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + { x: 25 + defaultHorizontalHandleWidth, y: 0, width: 100, height: splitViewHeight }, + { x: 25 + 100 + defaultHorizontalHandleWidth, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + { x: 25 + 100 + defaultHorizontalHandleWidth * 2, y: 0, width: splitViewWidth - 100, height: splitViewHeight } + ] + } + ] + return data + } + + function test_dragHandle(data) { + var control = createTemporaryObject(data.component, testCase) + verify(control) + + control.orientation = data.orientation + + // Ensure that there is space to drag outside of the SplitView. + control.anchors.margins = splitViewMargins + + var fillItem = control.itemAt(data.fillIndex) + if (control.orientation === Qt.Horizontal) + fillItem.SplitView.fillWidth = true + else + fillItem.SplitView.fillHeight = true + + // Check the sizes of the items before the drag. + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) + compareSizes(control, data.expectedGeometriesBeforeDrag, "before drag") + + // Drag the handle. + var handles = findHandles(control) + var targetHandle = handles[data.handleIndex] + mousePress(targetHandle) + verify(control.resizing) + var localPos = testCase.mapToItem(targetHandle, data.newHandlePos.x, data.newHandlePos.y) + mouseMove(targetHandle, localPos.x - targetHandle.width / 2, localPos.y - targetHandle.height / 2) + verify(control.resizing) + compareSizes(control, data.expectedGeometriesAfterDrag, "after drag move") + + // The geometries should remain unchanged after releasing. + mouseRelease(targetHandle, localPos.x - targetHandle.width / 2, localPos.y - targetHandle.height / 2, Qt.LeftButton) + verify(!control.resizing) + compareSizes(control, data.expectedGeometriesAfterDrag, "after drag release") + } + + function test_splitViewGeometryChanges_data() { + var defaultSplitViewWidth = testCase.width + var defaultSplitViewHeight = testCase.height + + var data = [ + { + tag: "growWidth", + orientation: Qt.Horizontal, + splitViewWidth: 800, + expectedGeometries: [ + { x: 0, y: 0, width: 25, height: defaultSplitViewHeight }, + { x: 25, y: 0, width: defaultHorizontalHandleWidth, height: defaultSplitViewHeight }, + { x: 25 + defaultHorizontalHandleWidth, y: 0, width: 100, height: defaultSplitViewHeight }, + { x: 25 + 100 + defaultHorizontalHandleWidth, y: 0, width: defaultHorizontalHandleWidth, + height: defaultSplitViewHeight }, + { x: 25 + 100 + defaultHorizontalHandleWidth * 2, y: 0, + width: 800 - 25 - 100 - defaultHorizontalHandleWidth * 2, height: defaultSplitViewHeight } + ] + }, + { + // Same as above except vertical. + tag: "growHeight", + orientation: Qt.Vertical, + splitViewHeight: 800, + expectedGeometries: [ + { x: 0, y: 0, width: defaultSplitViewWidth, height: 25 }, + { x: 0, y: 25, width: defaultSplitViewWidth, height: defaultVerticalHandleHeight }, + { x: 0, y: 25 + defaultVerticalHandleHeight, width: defaultSplitViewWidth, height: 100 }, + { x: 0, y: 25 + 100 + defaultVerticalHandleHeight, width: defaultSplitViewWidth, + height: defaultVerticalHandleHeight }, + { x: 0, y: 25 + 100 + defaultVerticalHandleHeight * 2, width: defaultSplitViewWidth, + height: 800 - 25 - 100 - defaultVerticalHandleHeight * 2 } + ] + }, + { + tag: "shrinkWidth", + orientation: Qt.Horizontal, + splitViewWidth: 200, + expectedGeometries: [ + { x: 0, y: 0, width: 25, height: defaultSplitViewHeight }, + { x: 25, y: 0, width: defaultHorizontalHandleWidth, height: defaultSplitViewHeight }, + { x: 25 + defaultHorizontalHandleWidth, y: 0, width: 100, height: defaultSplitViewHeight }, + { x: 25 + 100 + defaultHorizontalHandleWidth, y: 0, width: defaultHorizontalHandleWidth, + height: defaultSplitViewHeight }, + { x: 25 + 100 + defaultHorizontalHandleWidth * 2, y: 0, + width: 200 - 25 - 100 - defaultHorizontalHandleWidth * 2, height: defaultSplitViewHeight } + ] + }, + { + // Same as above except vertical. + tag: "shrinkHeight", + orientation: Qt.Vertical, + splitViewHeight: 200, + expectedGeometries: [ + { x: 0, y: 0, width: defaultSplitViewWidth, height: 25 }, + { x: 0, y: 25, width: defaultSplitViewWidth, height: defaultVerticalHandleHeight }, + { x: 0, y: 25 + defaultVerticalHandleHeight, width: defaultSplitViewWidth, height: 100 }, + { x: 0, y: 25 + 100 + defaultVerticalHandleHeight, width: defaultSplitViewWidth, + height: defaultVerticalHandleHeight }, + { x: 0, y: 25 + 100 + defaultVerticalHandleHeight * 2, width: defaultSplitViewWidth, + height: 200 - 25 - 100 - defaultVerticalHandleHeight * 2 } + ] + }, + ] + return data + } + + function test_splitViewGeometryChanges(data) { + var control = createTemporaryObject(threeSizedItemsComponent, testCase, + { "handle": handleComponent, "anchors.fill": undefined, "orientation": data.orientation }) + verify(control) + + if (data.hasOwnProperty("splitViewWidth")) + control.width = data.splitViewWidth + else + control.width = testCase.width + + if (data.hasOwnProperty("splitViewHeight")) + control.height = data.splitViewHeight + else + control.height = testCase.height + + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) + compareSizes(control, data.expectedGeometries) + } + + function test_splitItemImplicitSizeChanges_data() { + var defaultSplitViewWidth = testCase.width + var defaultSplitViewHeight = testCase.height + + var data = [ + { + tag: "growImplicitWidth", + orientation: Qt.Horizontal, + splitItemImplicitWidth: 50, + expectedGeometries: [ + { x: 0, y: 0, width: 50, height: defaultSplitViewHeight }, + { x: 50, y: 0, width: defaultHorizontalHandleWidth, height: defaultSplitViewHeight }, + { x: 50 + defaultHorizontalHandleWidth, y: 0, width: 100, height: defaultSplitViewHeight }, + { x: 50 + 100 + defaultHorizontalHandleWidth, y: 0, width: defaultHorizontalHandleWidth, + height: defaultSplitViewHeight }, + { x: 50 + 100 + defaultHorizontalHandleWidth * 2, y: 0, + width: defaultSplitViewWidth - 50 - 100 - defaultHorizontalHandleWidth * 2, height: defaultSplitViewHeight } + ] + }, + { + tag: "growImplicitHeight", + orientation: Qt.Vertical, + splitItemImplicitHeight: 50, + expectedGeometries: [ + { x: 0, y: 0, width: defaultSplitViewWidth, height: 50 }, + { x: 0, y: 50, width: defaultSplitViewWidth, height: defaultVerticalHandleHeight }, + { x: 0, y: 50 + defaultVerticalHandleHeight, width: defaultSplitViewWidth, height: 100 }, + { x: 0, y: 50 + 100 + defaultVerticalHandleHeight, width: defaultSplitViewWidth, + height: defaultVerticalHandleHeight }, + { x: 0, y: 50 + 100 + defaultVerticalHandleHeight * 2, width: defaultSplitViewWidth, + height: defaultSplitViewHeight - 50 - 100 - defaultVerticalHandleHeight * 2 } + ] + } + ] + return data + } + + // Tests that implicitWidth/Height changes in items are noticed by SplitView. + function test_splitItemImplicitSizeChanges(data) { + var control = createTemporaryObject(threeSizedItemsComponent, testCase, + { "handle": handleComponent, "orientation": data.orientation }) + verify(control) + + var firstItem = control.itemAt(0) + + if (data.hasOwnProperty("splitItemImplicitWidth")) + firstItem.implicitWidth = data.splitItemImplicitWidth + + if (data.hasOwnProperty("splitItemImplicitHeight")) + firstItem.implicitHeight = data.splitItemImplicitHeight + + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) + compareSizes(control, data.expectedGeometries) + } + + Component { + id: largerHandle + Rectangle { + objectName: "largerHandle" + implicitWidth: 20 + implicitHeight: 20 + color: "#444" + } + } + + Component { + id: smallerHandle + Rectangle { + objectName: "smallerHandle" + implicitWidth: 5 + implicitHeight: 5 + color: "#444" + } + } + + function test_handleChanges_data() { + var splitViewWidth = testCase.width + var splitViewHeight = testCase.height + + var data = [ + { + tag: "growHandleWidth", + orientation: Qt.Horizontal, + handleComponent: largerHandle, + expectedGeometries: [ + { x: 0, y: 0, width: 25, height: splitViewHeight }, + { x: 25, y: 0, width: 20, height: splitViewHeight }, + { x: 25 + 20, y: 0, width: 100, height: splitViewHeight }, + { x: 25 + 100 + 20, y: 0, width: 20, height: splitViewHeight }, + { x: 25 + 100 + 20 * 2, y: 0, width: splitViewWidth - 25 - 100 - 20 * 2, + height: splitViewHeight } + ] + }, + { + // Same as above except vertical. + tag: "growHandleHeight", + orientation: Qt.Vertical, + handleComponent: largerHandle, + expectedGeometries: [ + { x: 0, y: 0, width: splitViewWidth, height: 25 }, + { x: 0, y: 25, width: splitViewWidth, height: 20 }, + { x: 0, y: 25 + 20, width: splitViewWidth, height: 100 }, + { x: 0, y: 25 + 100 + 20, width: splitViewWidth, height: 20 }, + { x: 0, y: 25 + 100 + 20 * 2, width: splitViewWidth, + height: splitViewHeight - 25 - 100 - 20 * 2 } + ] + }, + { + tag: "shrinkHandleWidth", + orientation: Qt.Horizontal, + handleComponent: smallerHandle, + expectedGeometries: [ + { x: 0, y: 0, width: 25, height: splitViewHeight }, + { x: 25, y: 0, width: 5, height: splitViewHeight }, + { x: 25 + 5, y: 0, width: 100, height: splitViewHeight }, + { x: 25 + 100 + 5, y: 0, width: 5, height: splitViewHeight }, + { x: 25 + 100 + 5 * 2, y: 0, width: splitViewWidth - 25 - 100 - 5 * 2, + height: splitViewHeight } + ] + }, + { + // Same as above except vertical. + tag: "shrinkHandleHeight", + orientation: Qt.Vertical, + handleComponent: smallerHandle, + expectedGeometries: [ + { x: 0, y: 0, width: splitViewWidth, height: 25 }, + { x: 0, y: 25, width: splitViewWidth, height: 5 }, + { x: 0, y: 25 + 5, width: splitViewWidth, height: 100 }, + { x: 0, y: 25 + 100 + 5, width: splitViewWidth, height: 5 }, + { x: 0, y: 25 + 100 + 5 * 2, width: splitViewWidth, + height: splitViewHeight - 25 - 100 - 5 * 2 } + ] + } + ] + return data + } + + function test_handleChanges(data) { + var control = createTemporaryObject(threeSizedItemsComponent, testCase, + { "orientation": data.orientation }) + verify(control) + + control.handle = data.handleComponent + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) + compareSizes(control, data.expectedGeometries) + } + + function test_insertRemoveItems_data() { + var splitViewWidth = testCase.width + var splitViewHeight = testCase.height + + var data = [ + { + tag: "insertItemAtHorizontalEnd", + orientation: Qt.Horizontal, + insertItemAtIndex: 3, + expectedGeometries: [ + { x: 0, y: 0, width: 25, height: splitViewHeight }, + { x: 25, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + { x: 25 + defaultHorizontalHandleWidth, y: 0, width: 100, height: splitViewHeight }, + { x: 25 + 100 + defaultHorizontalHandleWidth, y: 0, + width: defaultHorizontalHandleWidth, height: splitViewHeight }, + // This was the fill item originally, but since no fill item is explicitly + // specified, and we added an item to the right of it, it is no longer the fill item + // because it's no longer last. + { x: 25 + 100 + defaultHorizontalHandleWidth * 2, y: 0, + width: 200, height: splitViewHeight }, + // Handle for newly added item. + { x: 25 + 100 + 200 + defaultHorizontalHandleWidth * 2, y: 0, + width: defaultHorizontalHandleWidth, height: splitViewHeight }, + // Newly added item. + { x: 25 + 100 + 200 + defaultHorizontalHandleWidth * 3, y: 0, + width: splitViewWidth - 25 - 100 - 200 - defaultHorizontalHandleWidth * 3, + height: splitViewHeight }, + ] + }, + { + tag: "insertItemAtHorizontalBeginning", + orientation: Qt.Horizontal, + insertItemAtIndex: 0, + expectedGeometries: [ + // Newly added item. + { x: 0, y: 0, width: 25, height: splitViewHeight }, + { x: 25, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + { x: 25 + defaultHorizontalHandleWidth, y: 0, width: 25, height: splitViewHeight }, + { x: 25 * 2 + defaultHorizontalHandleWidth, y: 0, + width: defaultHorizontalHandleWidth, height: splitViewHeight }, + { x: 25 * 2 + defaultHorizontalHandleWidth * 2, y: 0, width: 100, height: splitViewHeight }, + { x: 25 * 2 + 100 + defaultHorizontalHandleWidth * 2, y: 0, + width: defaultHorizontalHandleWidth, height: splitViewHeight }, + // Fill item doesn't change. + { x: 25 * 2 + 100 + defaultHorizontalHandleWidth * 3, y: 0, + width: splitViewWidth - 25 * 2 - 100 - defaultHorizontalHandleWidth * 3, + height: splitViewHeight }, + ] + }, + { + tag: "removeItemFromHorizontalEnd", + orientation: Qt.Horizontal, + removeItemAtIndex: 2, + expectedGeometries: [ + { x: 0, y: 0, width: 25, height: splitViewHeight }, + { x: 25, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + { x: 25 + defaultHorizontalHandleWidth, y: 0, + width: splitViewWidth - 25 - defaultHorizontalHandleWidth, height: splitViewHeight }, + ] + }, + { + tag: "removeItemFromHorizontalBeginning", + orientation: Qt.Horizontal, + removeItemAtIndex: 0, + expectedGeometries: [ + { x: 0, y: 0, width: 100, height: splitViewHeight }, + { x: 100, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + { x: 100 + defaultHorizontalHandleWidth, y: 0, + width: splitViewWidth - 100 - defaultHorizontalHandleWidth, height: splitViewHeight }, + ] + } + ] + return data + } + + Component { + id: smallRectComponent + + Rectangle { + objectName: "darkseagreen" + color: objectName + implicitWidth: 25 + implicitHeight: 25 + } + } + + function test_insertRemoveItems(data) { + var control = createTemporaryObject(threeSizedItemsComponent, testCase, + { "orientation": data.orientation }) + verify(control) + + if (data.hasOwnProperty("removeItemAtIndex")) { + var itemToRemove = control.itemAt(data.removeItemAtIndex) + verify(itemToRemove) + + control.removeItem(itemToRemove) + } else if (data.hasOwnProperty("insertItemAtIndex")) { + var itemToAdd = smallRectComponent.createObject(control) + control.insertItem(data.insertItemAtIndex, itemToAdd) + } + + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) + compareSizes(control, data.expectedGeometries) + } + + function test_removeAllItems() { + var control = createTemporaryObject(threeSizedItemsComponent, testCase) + verify(control) + + while (control.count > 0) + var itemToRemove = control.removeItem(0) + // Shouldn't crash. + } + + function test_hideItems_data() { + var splitViewWidth = testCase.width + var splitViewHeight = testCase.height + + var data = [ + { + tag: "hideItemAtHorizontalEnd", + orientation: Qt.Horizontal, + hideIndices: [2], + expectedGeometries: [ + { x: 0, y: 0, width: 25, height: splitViewHeight }, + { x: 25, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + { x: 25 + defaultHorizontalHandleWidth, y: 0, + width: splitViewWidth - 25 - defaultHorizontalHandleWidth, height: splitViewHeight }, + { hidden: true }, // Handle for second item should be hidden. + { hidden: true } // Last item should be hidden. + ] + }, + { + tag: "hideItemAtHorizontalBeginning", + orientation: Qt.Horizontal, + hideIndices: [0], + expectedGeometries: [ + { hidden: true }, // First item should be hidden. + { hidden: true }, // Handle for first item should be hidden. + { x: 0, y: 0, width: 100, height: splitViewHeight }, + { x: 100, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + { x: 100 + defaultHorizontalHandleWidth, y: 0, + width: splitViewWidth - 100 - defaultHorizontalHandleWidth, height: splitViewHeight } + ] + }, + { + tag: "hideItemAtVerticalEnd", + orientation: Qt.Vertical, + hideIndices: [2], + expectedGeometries: [ + { x: 0, y: 0, width: splitViewWidth, height: 25 }, + { x: 0, y: 25, width: splitViewWidth, height: defaultVerticalHandleHeight }, + { x: 0, y: 25 + defaultVerticalHandleHeight, + width: splitViewWidth, height: splitViewHeight - 25 - defaultVerticalHandleHeight }, + { hidden: true }, // Handle for second item should be hidden. + { hidden: true } // Last item should be hidden. + ] + }, + { + tag: "hideItemAtVerticalBeginning", + orientation: Qt.Vertical, + hideIndices: [0], + expectedGeometries: [ + { hidden: true }, // First item should be hidden. + { hidden: true }, // Handle for first item should be hidden. + { x: 0, y: 0, width: splitViewWidth, height: 100 }, + { x: 0, y: 100, width: splitViewWidth, height: defaultVerticalHandleHeight }, + { x: 0, y: 100 + defaultVerticalHandleHeight, + width: splitViewWidth, height: splitViewHeight - 100 - defaultVerticalHandleHeight } + ] + }, + { + // No handles should be visible when there's only one item. + tag: "hideLastTwoHorizontalItems", + orientation: Qt.Horizontal, + hideIndices: [1, 2], + expectedGeometries: [ + { x: 0, y: 0, width: splitViewWidth, height: splitViewHeight }, + { hidden: true }, // Handle for first item should be hidden. + { hidden: true }, // Second item should be hidden. + { hidden: true }, // Handle for second item should be hidden. + { hidden: true } // Third item should be hidden. + ] + } + ] + return data + } + + function test_hideItems(data) { + var control = createTemporaryObject(threeSizedItemsComponent, testCase, + { "orientation": data.orientation }) + verify(control) + + for (var i = 0; i < data.hideIndices.length; ++i) { + var itemToHide = control.itemAt(data.hideIndices[i]) + verify(itemToHide) + itemToHide.visible = false + } + + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) + compareSizes(control, data.expectedGeometries) + } + + function test_hideAndShowItems_data() { + var splitViewWidth = testCase.width + var splitViewHeight = testCase.height + + var data = [ + { + tag: "hideLastTwoHorizontalItems", + orientation: Qt.Horizontal, + hideIndices: [1, 2], + expectedGeometriesAfterHiding: [ + { x: 0, y: 0, width: splitViewWidth, height: splitViewHeight }, + { hidden: true }, // Handle for first item should be hidden. + { hidden: true }, // Second item should be hidden. + { hidden: true }, // Handle for second item should be hidden. + { hidden: true } // Third item should be hidden. + ], + showIndices: [1], + expectedGeometriesAfterShowing: [ + // First item should be visible with its implicit size. + { x: 0, y: 0, width: 25, height: splitViewHeight }, + // Handle for first item should be visible. + { x: 25, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + // Second item should be visible and fill. + { x: 25 + defaultHorizontalHandleWidth, y: 0, + width: splitViewWidth - 25 - defaultHorizontalHandleWidth, height: splitViewHeight }, + { hidden: true }, // Handle for second item should be hidden. + { hidden: true } // Third item should be hidden. + ] + } + ] + return data + } + + function test_hideAndShowItems(data) { + var control = createTemporaryObject(threeSizedItemsComponent, testCase, + { "orientation": data.orientation }) + verify(control) + + for (var i = 0; i < data.hideIndices.length; ++i) { + var itemToHide = control.itemAt(data.hideIndices[i]) + verify(itemToHide) + itemToHide.visible = false + } + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) + compareSizes(control, data.expectedGeometriesAfterHiding, "after hiding") + + for (i = 0; i < data.showIndices.length; ++i) { + var itemToShow = control.itemAt(data.showIndices[i]) + verify(itemToShow) + itemToShow.visible = true + } + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) + compareSizes(control, data.expectedGeometriesAfterShowing, "after showing") + } + + function test_moveHiddenItems_data() { + var splitViewWidth = testCase.width + var splitViewHeight = testCase.height + + var data = [ + { + tag: "hideSecondItemAndMoveItToFirst", + orientation: Qt.Horizontal, + hideIndices: [1], + moveFromIndex: 1, + moveToIndex: 0, + expectedGeometriesAfterMoving: [ + { hidden: true }, // First item (was second) should be hidden. + { hidden: true }, // Handle for first item should be hidden. + // Second item (was first) should get its implicit size. + { x: 0, y: 0, width: 25, height: splitViewHeight }, + { x: 25, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + { x: 25 + defaultHorizontalHandleWidth, y: 0, + width: splitViewWidth - 25 - defaultHorizontalHandleWidth, height: splitViewHeight }, + ], + showIndices: [0], + expectedGeometriesAfterShowing: [ + // First item (was second) should be visible with its implicit size. + { x: 0, y: 0, width: 100, height: splitViewHeight }, + // Handle for first item (was second) should be visible. + { x: 100, y: 0, width: defaultHorizontalHandleWidth, height: splitViewHeight }, + // Second item (was first) should be visible with its implicit size. + { x: 100 + defaultHorizontalHandleWidth, y: 0, + width: 25, height: splitViewHeight }, + { x: 100 + 25 + defaultHorizontalHandleWidth, y: 0, + width: defaultHorizontalHandleWidth, height: splitViewHeight }, + { x: 100 + 25 + defaultHorizontalHandleWidth * 2, y: 0, + width: splitViewWidth - 100 - 25 - defaultHorizontalHandleWidth * 2, height: splitViewHeight } + ] + } + ] + return data + } + + function test_moveHiddenItems(data) { + var control = createTemporaryObject(threeSizedItemsComponent, testCase, + { "orientation": data.orientation }) + verify(control) + + for (var i = 0; i < data.hideIndices.length; ++i) { + var itemToHide = control.itemAt(data.hideIndices[i]) + verify(itemToHide) + itemToHide.visible = false + } + + control.moveItem(data.moveFromIndex, data.moveToIndex) + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) + compareSizes(control, data.expectedGeometriesAfterMoving, "after moving") + + for (i = 0; i < data.showIndices.length; ++i) { + var itemToShow = control.itemAt(data.showIndices[i]) + verify(itemToShow) + itemToShow.visible = true + } + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) + compareSizes(control, data.expectedGeometriesAfterShowing, "after showing") + } + + Component { + id: flickableComponent + + Flickable { + anchors.fill: parent + anchors.margins: 100 + } + } + + function test_draggingHandleInFlickable() { + var flickable = createTemporaryObject(flickableComponent, testCase) + verify(flickable) + + var control = threeSizedItemsComponent.createObject(flickable.contentItem, + { "orientation": data.orientation }) + verify(control) + + control.anchors.fill = undefined + control.width = 400 + control.height = control.parent.height - 100 + flickable.contentWidth = control.width + flickable.contentHeight = control.height + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) + + var contentXSpy = signalSpyComponent.createObject(flickable, + { target: flickable, signalName: "contentXChanged" }) + verify(contentXSpy.valid) + var contentYSpy = signalSpyComponent.createObject(flickable, + { target: flickable, signalName: "contentYChanged" }) + verify(contentYSpy.valid) + + // Drag the first handle to the right; + // the flickable's contentX and contentY shouldn't change. + var firstItem = control.itemAt(0) + var firstItemOriginalWidth = firstItem.width + var handles = findHandles(control) + var firstHandle = handles[0] + // Add some vertical movement in there as well. + mouseDrag(firstHandle, firstHandle.width / 2, firstHandle.height / 2, 100, 50) + compare(contentXSpy.count, 0) + compare(contentYSpy.count, 0) + verify(firstItem.width > firstItemOriginalWidth) + + // Now do the same except vertically. + control.orientation = Qt.Vertical + control.width = control.parent.width - 100 + control.height = 400 + var firstItemOriginalHeight = firstItem.height + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) + + // Add some horizontal movement in there as well. + mouseDrag(firstHandle, firstHandle.width / 2, firstHandle.height / 2, 50, 100) + compare(contentXSpy.count, 0) + compare(contentYSpy.count, 0) + verify(firstItem.height > firstItemOriginalHeight) + } + + function test_hoveredPressed() { + if ((Qt.platform.pluginName === "offscreen") || (Qt.platform.pluginName === "minimal")) + skip("Mouse hovering not functional on offscreen/minimal platforms") + + var control = createTemporaryObject(threeSizedItemsComponent, testCase) + verify(control) + control.anchors.margins = 50 + + var handles = findHandles(control) + var firstHandle = handles[0] + + var handleCenter = control.mapFromItem(firstHandle, firstHandle.width / 2, firstHandle.height / 2) + // Test fails if we don't do two moves for some reason... + mouseMove(control, handleCenter.x, handleCenter.y) + mouseMove(control, handleCenter.x, handleCenter.y) + verify(firstHandle.SplitHandle.hovered) + verify(!firstHandle.SplitHandle.pressed) + + mousePress(control, handleCenter.x, handleCenter.y) + verify(firstHandle.SplitHandle.hovered) + verify(firstHandle.SplitHandle.pressed) + + mouseRelease(control, handleCenter.x, handleCenter.y) + verify(firstHandle.SplitHandle.hovered) + verify(!firstHandle.SplitHandle.pressed) + + mouseMove(control, 0, 0) + verify(!firstHandle.SplitHandle.hovered) + verify(!firstHandle.SplitHandle.pressed) + } + + // Tests removing/adding/moving an item while it's pressed. + function test_modifyWhileHoveredPressed() { + if ((Qt.platform.pluginName === "offscreen") || (Qt.platform.pluginName === "minimal")) + skip("Mouse hovering not functional on offscreen/minimal platforms") + + var control = createTemporaryObject(threeSizedItemsComponent, testCase) + verify(control) + control.anchors.margins = 50 + + var handles = findHandles(control) + var firstHandle = handles[0] + + // First, ensure that the handle is hovered + pressed. + var handleCenter = control.mapFromItem(firstHandle, firstHandle.width / 2, firstHandle.height / 2) + // Test fails if we don't do two moves for some reason... + mouseMove(control, handleCenter.x, handleCenter.y) + mouseMove(control, handleCenter.x, handleCenter.y) + verify(firstHandle.SplitHandle.hovered) + verify(!firstHandle.SplitHandle.pressed) + + mousePress(control, handleCenter.x, handleCenter.y) + verify(firstHandle.SplitHandle.hovered) + verify(firstHandle.SplitHandle.pressed) + + // Then, remove it by removing the first item. + control.removeItem(0) + handles = findHandles(control) + firstHandle = null + compare(handles.length, 1) + + // No handles should be hovered/pressed. + for (var i = 0; i < handles.length; ++i) { + var handle = handles[i] + verify(!handle.SplitHandle.hovered, "handle at index " + i + " should not be hovered") + verify(!handle.SplitHandle.pressed, "handle at index " + i + " should not be hovered") + } + + mouseRelease(control, handleCenter.x, handleCenter.y) + } + + Component { + id: settingsComponent + Settings { + id: settings + } + } + + function test_saveAndRestoreState() { + var control = createTemporaryObject(threeSizedItemsComponent, testCase) + verify(control) + + var lastItem = control.itemAt(2) + verify(lastItem) + lastItem.SplitView.preferredWidth = 123 + + // Save the state. + var settings = createTemporaryObject(settingsComponent, testCase) + verify(settings) + settings.setValue("splitView", control.saveState()) + + // Recreate the item to restore it to its "default" values. + control = createTemporaryObject(threeSizedItemsComponent, testCase) + lastItem = control.itemAt(2) + verify(lastItem) + compare(lastItem.SplitView.preferredWidth, -1) + + settings = createTemporaryObject(settingsComponent, testCase) + verify(settings) + + // Restore the state. + control.restoreState(settings.value("splitView")) + compare(lastItem.SplitView.preferredWidth, 123) + } + + function test_changePreferredSizeDuringLayout() { + var control = createTemporaryObject(threeSizedItemsComponent, testCase) + verify(control) + + var firstItem = control.itemAt(0) + var secondItem = control.itemAt(1) + secondItem.widthChanged.connect(function() { + if (secondItem.width < 10) + firstItem.SplitView.preferredWidth = 50 + }) + + // Change the size of the item so that a layout happens, but + // make the size small enough that the item's onWidthChanged handler gets triggered. + // The onWidthChanged handler will set the preferredWidth of another item during the + // layout, so we need to make sure the assignment isn't lost since we return early in that case. + secondItem.implicitWidth = 5 + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) + compare(secondItem.width, 5) + compare(firstItem.width, 50) + + // Now do the same for height. + control.orientation = Qt.Vertical + secondItem.heightChanged.connect(function() { + if (secondItem.height < 10) + firstItem.SplitView.preferredHeight = 50 + }) + // Get the polishes for the orientation out of the way so that they + // don't intefere with our results. + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) + + secondItem.implicitHeight = 5 + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) + compare(secondItem.height, 5) + compare(firstItem.height, 50) + } + + // When the user drags a handle, we internally set preferredWidth/Height + // to reflect the new value. However, we also have to make sure that when + // we do so, it doesn't trigger a delayed layout. This is why we have + // m_ignoreNextDelayedLayoutRequest. This test checks that + // m_ignoreNextDelayedLayoutRequest doesn't interfere with any action from + // the user that results in a delayed layout. + function test_changePreferredSizeDuringLayoutWhileDraggingHandle() { + var control = createTemporaryObject(threeSizedItemsComponent, testCase) + verify(control) + + var firstItem = control.itemAt(0) + var secondItem = control.itemAt(1) + firstItem.widthChanged.connect(function() { + if (firstItem.width === 0) + secondItem.SplitView.preferredWidth = 50 + }) + + // Start dragging the handle. + var handles = findHandles(control) + var targetHandle = handles[0] + mousePress(targetHandle) + verify(control.resizing) + var localPos = testCase.mapToItem(targetHandle, 15, testCase.height / 2) + + // Move the handle to the very left, so that the item's width becomes zero. + mouseMove(targetHandle, -100, targetHandle.height / 2) + verify(control.resizing) + compare(firstItem.width, 0) + compare(secondItem.SplitView.preferredWidth, 50) + compare(secondItem.width, 50) + mouseRelease(targetHandle, -100, targetHandle.height / 2, Qt.LeftButton) + verify(!control.resizing) + } +} diff --git a/tests/auto/controls/default/tst_default.cpp b/tests/auto/controls/default/tst_default.cpp index d21f13ad..4c575ce6 100644 --- a/tests/auto/controls/default/tst_default.cpp +++ b/tests/auto/controls/default/tst_default.cpp @@ -38,7 +38,6 @@ int main(int argc, char *argv[]) { - QTEST_ADD_GPU_BLACKLIST_SUPPORT QTEST_SET_MAIN_SOURCE_PATH qputenv("QML_NO_TOUCH_COMPRESSION", "1"); return quick_test_main(argc, argv, "tst_controls::Default", TST_CONTROLS_DATA); diff --git a/tests/auto/controls/fusion/tst_fusion.cpp b/tests/auto/controls/fusion/tst_fusion.cpp index 84f9c231..7528ccea 100644 --- a/tests/auto/controls/fusion/tst_fusion.cpp +++ b/tests/auto/controls/fusion/tst_fusion.cpp @@ -39,7 +39,6 @@ int main(int argc, char *argv[]) { - QTEST_ADD_GPU_BLACKLIST_SUPPORT QTEST_SET_MAIN_SOURCE_PATH qputenv("QML_NO_TOUCH_COMPRESSION", "1"); QQuickStyle::setStyle("Fusion"); diff --git a/tests/auto/controls/imagine/tst_imagine.cpp b/tests/auto/controls/imagine/tst_imagine.cpp index 9777c9c9..9db7ed4d 100644 --- a/tests/auto/controls/imagine/tst_imagine.cpp +++ b/tests/auto/controls/imagine/tst_imagine.cpp @@ -39,7 +39,6 @@ int main(int argc, char *argv[]) { - QTEST_ADD_GPU_BLACKLIST_SUPPORT QTEST_SET_MAIN_SOURCE_PATH qputenv("QML_NO_TOUCH_COMPRESSION", "1"); QQuickStyle::setStyle("Imagine"); diff --git a/tests/auto/controls/material/tst_material.cpp b/tests/auto/controls/material/tst_material.cpp index 7d1953c2..ae8bb3a1 100644 --- a/tests/auto/controls/material/tst_material.cpp +++ b/tests/auto/controls/material/tst_material.cpp @@ -39,7 +39,6 @@ int main(int argc, char *argv[]) { - QTEST_ADD_GPU_BLACKLIST_SUPPORT QTEST_SET_MAIN_SOURCE_PATH qputenv("QML_NO_TOUCH_COMPRESSION", "1"); QQuickStyle::setStyle("Material"); diff --git a/tests/auto/controls/universal/tst_universal.cpp b/tests/auto/controls/universal/tst_universal.cpp index d293dc4c..db5b560e 100644 --- a/tests/auto/controls/universal/tst_universal.cpp +++ b/tests/auto/controls/universal/tst_universal.cpp @@ -39,7 +39,6 @@ int main(int argc, char *argv[]) { - QTEST_ADD_GPU_BLACKLIST_SUPPORT QTEST_SET_MAIN_SOURCE_PATH qputenv("QML_NO_TOUCH_COMPRESSION", "1"); QQuickStyle::setStyle("Universal"); diff --git a/tests/auto/shared/qtest_quickcontrols.h b/tests/auto/shared/qtest_quickcontrols.h index 0ae74481..4a06c021 100644 --- a/tests/auto/shared/qtest_quickcontrols.h +++ b/tests/auto/shared/qtest_quickcontrols.h @@ -73,15 +73,11 @@ static int runTests(QObject *testObject, int argc, char *argv[]) } #define QTEST_QUICKCONTROLS_MAIN(TestCase) \ -QT_BEGIN_NAMESPACE \ -QTEST_ADD_GPU_BLACKLIST_SUPPORT_DEFS \ -QT_END_NAMESPACE \ int main(int argc, char *argv[]) \ { \ qputenv("QML_NO_TOUCH_COMPRESSION", "1"); \ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); \ QGuiApplication app(argc, argv); \ - QTEST_ADD_GPU_BLACKLIST_SUPPORT \ TestCase tc; \ QTEST_SET_MAIN_SOURCE_PATH \ return runTests(&tc, argc, argv); \ |