aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/controls/data
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/controls/data')
-rw-r--r--tests/auto/controls/data/TumblerDatePicker.qml4
-rw-r--r--tests/auto/controls/data/TumblerListView.qml53
-rw-r--r--tests/auto/controls/data/TumblerPathView.qml63
-rw-r--r--tests/auto/controls/data/tst_abstractbutton.qml2
-rw-r--r--tests/auto/controls/data/tst_busyindicator.qml2
-rw-r--r--tests/auto/controls/data/tst_button.qml16
-rw-r--r--tests/auto/controls/data/tst_buttongroup.qml28
-rw-r--r--tests/auto/controls/data/tst_checkbox.qml2
-rw-r--r--tests/auto/controls/data/tst_checkdelegate.qml2
-rw-r--r--tests/auto/controls/data/tst_combobox.qml3
-rw-r--r--tests/auto/controls/data/tst_container.qml4
-rw-r--r--tests/auto/controls/data/tst_control.qml44
-rw-r--r--tests/auto/controls/data/tst_dial.qml2
-rw-r--r--tests/auto/controls/data/tst_dialog.qml297
-rw-r--r--tests/auto/controls/data/tst_dialogbuttonbox.qml188
-rw-r--r--tests/auto/controls/data/tst_drawer.qml2
-rw-r--r--tests/auto/controls/data/tst_frame.qml2
-rw-r--r--tests/auto/controls/data/tst_groupbox.qml2
-rw-r--r--tests/auto/controls/data/tst_itemdelegate.qml2
-rw-r--r--tests/auto/controls/data/tst_label.qml2
-rw-r--r--tests/auto/controls/data/tst_menuitem.qml2
-rw-r--r--tests/auto/controls/data/tst_page.qml102
-rw-r--r--tests/auto/controls/data/tst_pageindicator.qml2
-rw-r--r--tests/auto/controls/data/tst_pane.qml2
-rw-r--r--tests/auto/controls/data/tst_popup.qml8
-rw-r--r--tests/auto/controls/data/tst_progressbar.qml2
-rw-r--r--tests/auto/controls/data/tst_radiobutton.qml2
-rw-r--r--tests/auto/controls/data/tst_radiodelegate.qml2
-rw-r--r--tests/auto/controls/data/tst_rangeslider.qml29
-rw-r--r--tests/auto/controls/data/tst_roundbutton.qml79
-rw-r--r--tests/auto/controls/data/tst_scrollbar.qml40
-rw-r--r--tests/auto/controls/data/tst_scrollindicator.qml16
-rw-r--r--tests/auto/controls/data/tst_slider.qml22
-rw-r--r--tests/auto/controls/data/tst_spinbox.qml31
-rw-r--r--tests/auto/controls/data/tst_stackview.qml177
-rw-r--r--tests/auto/controls/data/tst_swipedelegate.qml265
-rw-r--r--tests/auto/controls/data/tst_swipeview.qml28
-rw-r--r--tests/auto/controls/data/tst_switch.qml2
-rw-r--r--tests/auto/controls/data/tst_switchdelegate.qml2
-rw-r--r--tests/auto/controls/data/tst_tabbar.qml12
-rw-r--r--tests/auto/controls/data/tst_tabbutton.qml2
-rw-r--r--tests/auto/controls/data/tst_textarea.qml192
-rw-r--r--tests/auto/controls/data/tst_textfield.qml192
-rw-r--r--tests/auto/controls/data/tst_toolbar.qml2
-rw-r--r--tests/auto/controls/data/tst_toolbutton.qml2
-rw-r--r--tests/auto/controls/data/tst_toolseparator.qml99
-rw-r--r--tests/auto/controls/data/tst_tooltip.qml2
-rw-r--r--tests/auto/controls/data/tst_tumbler.qml464
48 files changed, 2326 insertions, 174 deletions
diff --git a/tests/auto/controls/data/TumblerDatePicker.qml b/tests/auto/controls/data/TumblerDatePicker.qml
index 18d7fb97..e5340493 100644
--- a/tests/auto/controls/data/TumblerDatePicker.qml
+++ b/tests/auto/controls/data/TumblerDatePicker.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2016 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -39,7 +39,7 @@
****************************************************************************/
import QtQuick 2.6
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
Row {
id: datePicker
diff --git a/tests/auto/controls/data/TumblerListView.qml b/tests/auto/controls/data/TumblerListView.qml
new file mode 100644
index 00000000..cccf8adf
--- /dev/null
+++ b/tests/auto/controls/data/TumblerListView.qml
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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
+
+ListView {
+ anchors.fill: parent
+ model: parent.model
+ delegate: parent.delegate
+
+ snapMode: ListView.SnapToItem
+ highlightRangeMode: ListView.StrictlyEnforceRange
+ preferredHighlightBegin: height / 2 - (height / parent.visibleItemCount / 2)
+ preferredHighlightEnd: height / 2 + (height / parent.visibleItemCount / 2)
+ clip: true
+}
diff --git a/tests/auto/controls/data/TumblerPathView.qml b/tests/auto/controls/data/TumblerPathView.qml
new file mode 100644
index 00000000..e325faf6
--- /dev/null
+++ b/tests/auto/controls/data/TumblerPathView.qml
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** 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
+
+PathView {
+ id: pathView
+ model: parent.model
+ delegate: parent.delegate
+ clip: true
+ pathItemCount: parent.visibleItemCount + 1
+ preferredHighlightBegin: 0.5
+ preferredHighlightEnd: 0.5
+ dragMargin: width / 2
+
+ path: Path {
+ startX: pathView.width / 2
+ startY: -pathView.delegateHeight / 2
+ PathLine {
+ x: pathView.width / 2
+ y: pathView.pathItemCount * pathView.delegateHeight - pathView.delegateHeight / 2
+ }
+ }
+
+ property real delegateHeight: parent.availableHeight / parent.visibleItemCount
+}
diff --git a/tests/auto/controls/data/tst_abstractbutton.qml b/tests/auto/controls/data/tst_abstractbutton.qml
index ba5ee94c..27fc4525 100644
--- a/tests/auto/controls/data/tst_abstractbutton.qml
+++ b/tests/auto/controls/data/tst_abstractbutton.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
diff --git a/tests/auto/controls/data/tst_busyindicator.qml b/tests/auto/controls/data/tst_busyindicator.qml
index 142ec70a..c456a2e8 100644
--- a/tests/auto/controls/data/tst_busyindicator.qml
+++ b/tests/auto/controls/data/tst_busyindicator.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
diff --git a/tests/auto/controls/data/tst_button.qml b/tests/auto/controls/data/tst_button.qml
index 1de43426..16d1bb94 100644
--- a/tests/auto/controls/data/tst_button.qml
+++ b/tests/auto/controls/data/tst_button.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
@@ -213,8 +213,11 @@ TestCase {
control.spy.expectedSequence = repeatSequence
mousePress(control)
compare(control.pressed, true)
- tryCompare(clickSpy, "count", repeatCount)
- verify(control.spy.success)
+ tryVerify(function() { return clickSpy.count >= repeatCount })
+ if (clickSpy.count > repeatCount)
+ warn("Expected auto-repeat count " + repeatCount + " exceeded (" + clickSpy.count + ") - busy CI?")
+ else
+ verify(control.spy.success)
control.spy.expectedSequence = [["pressedChanged", { "pressed": false }],
["downChanged", { "down": false }],
@@ -229,8 +232,11 @@ TestCase {
control.spy.expectedSequence = repeatSequence
keyPress(Qt.Key_Space)
compare(control.pressed, true)
- tryCompare(clickSpy, "count", repeatCount)
- verify(control.spy.success)
+ tryVerify(function() { return clickSpy.count >= repeatCount })
+ if (clickSpy.count > repeatCount)
+ warn("Expected auto-repeat count " + repeatCount + " exceeded (" + clickSpy.count + ") - busy CI?")
+ else
+ verify(control.spy.success)
control.spy.expectedSequence = [["pressedChanged", { "pressed": false }],
["downChanged", { "down": false }],
diff --git a/tests/auto/controls/data/tst_buttongroup.qml b/tests/auto/controls/data/tst_buttongroup.qml
index 754e4f0b..186eb9d1 100644
--- a/tests/auto/controls/data/tst_buttongroup.qml
+++ b/tests/auto/controls/data/tst_buttongroup.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
@@ -196,6 +196,32 @@ TestCase {
group.destroy()
}
+ function test_clicked() {
+ var group = buttonGroup.createObject(testCase)
+ verify(group)
+
+ var clickedSpy = signalSpy.createObject(testCase, {target: group, signalName: "clicked"})
+ verify(clickedSpy.valid)
+
+ var button1 = button.createObject(testCase)
+ var button2 = button.createObject(testCase)
+
+ group.addButton(button1)
+ group.addButton(button2)
+
+ button1.clicked()
+ compare(clickedSpy.count, 1)
+ compare(clickedSpy.signalArguments[0][0], button1)
+
+ button2.clicked()
+ compare(clickedSpy.count, 2)
+ compare(clickedSpy.signalArguments[1][0], button2)
+
+ group.destroy()
+ button1.destroy()
+ button2.destroy()
+ }
+
Component {
id: checkBoxes
Item {
diff --git a/tests/auto/controls/data/tst_checkbox.qml b/tests/auto/controls/data/tst_checkbox.qml
index 7969b589..d1b590e4 100644
--- a/tests/auto/controls/data/tst_checkbox.qml
+++ b/tests/auto/controls/data/tst_checkbox.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
diff --git a/tests/auto/controls/data/tst_checkdelegate.qml b/tests/auto/controls/data/tst_checkdelegate.qml
index a471b1d6..2fa8b4be 100644
--- a/tests/auto/controls/data/tst_checkdelegate.qml
+++ b/tests/auto/controls/data/tst_checkdelegate.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
diff --git a/tests/auto/controls/data/tst_combobox.qml b/tests/auto/controls/data/tst_combobox.qml
index 97ba7ea4..b74911c7 100644
--- a/tests/auto/controls/data/tst_combobox.qml
+++ b/tests/auto/controls/data/tst_combobox.qml
@@ -41,7 +41,7 @@
import QtQuick 2.2
import QtQuick.Window 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
@@ -76,6 +76,7 @@ TestCase {
compare(control.count, 0)
compare(control.model, undefined)
+ compare(control.flat, false)
compare(control.pressed, false)
compare(control.currentIndex, -1)
compare(control.highlightedIndex, -1)
diff --git a/tests/auto/controls/data/tst_container.qml b/tests/auto/controls/data/tst_container.qml
index d1ff54e0..3c7032c7 100644
--- a/tests/auto/controls/data/tst_container.qml
+++ b/tests/auto/controls/data/tst_container.qml
@@ -40,8 +40,8 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
-import QtQuick.Templates 2.0 as T
+import QtQuick.Controls 2.1
+import QtQuick.Templates 2.1 as T
TestCase {
id: testCase
diff --git a/tests/auto/controls/data/tst_control.qml b/tests/auto/controls/data/tst_control.qml
index 3018498e..1b60eb73 100644
--- a/tests/auto/controls/data/tst_control.qml
+++ b/tests/auto/controls/data/tst_control.qml
@@ -40,8 +40,8 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
-import QtQuick.Templates 2.0 as T
+import QtQuick.Controls 2.1
+import QtQuick.Templates 2.1 as T
TestCase {
id: testCase
@@ -859,7 +859,9 @@ TestCase {
verify(control)
compare(control.hovered, false)
- compare(control.hoverEnabled, false)
+ compare(control.hoverEnabled, Qt.styleHints.useHoverEffects)
+
+ control.hoverEnabled = false
mouseMove(control, control.width / 2, control.height / 2)
compare(control.hovered, false)
@@ -891,6 +893,42 @@ TestCase {
control.destroy()
}
+ function test_hoverEnabled() {
+ var control = component.createObject(testCase)
+ compare(control.hoverEnabled, Qt.styleHints.useHoverEffects)
+
+ var child = component.createObject(control)
+ var grandChild = component.createObject(child)
+
+ var childExplicitHoverEnabled = component.createObject(control, {hoverEnabled: true})
+ var grandChildExplicitHoverDisabled = component.createObject(childExplicitHoverEnabled, {hoverEnabled: false})
+
+ var childExplicitHoverDisabled = component.createObject(control, {hoverEnabled: false})
+ var grandChildExplicitHoverEnabled = component.createObject(childExplicitHoverDisabled, {hoverEnabled: true})
+
+ control.hoverEnabled = false
+ compare(control.hoverEnabled, false)
+ compare(grandChild.hoverEnabled, false)
+
+ compare(childExplicitHoverEnabled.hoverEnabled, true)
+ compare(grandChildExplicitHoverDisabled.hoverEnabled, false)
+
+ compare(childExplicitHoverDisabled.hoverEnabled, false)
+ compare(grandChildExplicitHoverEnabled.hoverEnabled, true)
+
+ control.hoverEnabled = true
+ compare(control.hoverEnabled, true)
+ compare(grandChild.hoverEnabled, true)
+
+ compare(childExplicitHoverEnabled.hoverEnabled, true)
+ compare(grandChildExplicitHoverDisabled.hoverEnabled, false)
+
+ compare(childExplicitHoverDisabled.hoverEnabled, false)
+ compare(grandChildExplicitHoverEnabled.hoverEnabled, true)
+
+ control.destroy()
+ }
+
function test_implicitSize() {
var control = component.createObject(testCase)
verify(control)
diff --git a/tests/auto/controls/data/tst_dial.qml b/tests/auto/controls/data/tst_dial.qml
index a2ebf192..e6446d3e 100644
--- a/tests/auto/controls/data/tst_dial.qml
+++ b/tests/auto/controls/data/tst_dial.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
diff --git a/tests/auto/controls/data/tst_dialog.qml b/tests/auto/controls/data/tst_dialog.qml
new file mode 100644
index 00000000..d4cbc222
--- /dev/null
+++ b/tests/auto/controls/data/tst_dialog.qml
@@ -0,0 +1,297 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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.4
+import QtTest 1.0
+import QtQuick.Controls 2.1
+import QtQuick.Templates 2.1 as T
+
+TestCase {
+ id: testCase
+ width: 400
+ height: 400
+ visible: true
+ when: windowShown
+ name: "Dialog"
+
+ Component {
+ id: dialog
+ Dialog { }
+ }
+
+ Component {
+ id: buttonBox
+ DialogButtonBox { }
+ }
+
+ Component {
+ id: headerBox
+ DialogButtonBox { position: DialogButtonBox.Header }
+ }
+
+ Component {
+ id: footerBox
+ DialogButtonBox { position: DialogButtonBox.Footer }
+ }
+
+ Component {
+ id: signalSpy
+ SignalSpy { }
+ }
+
+ function test_defaults() {
+ var control = dialog.createObject(testCase)
+ verify(control)
+ verify(!control.header)
+ verify(!control.footer)
+ verify(control.buttonBox)
+ compare(control.standardButtons, 0)
+ control.destroy()
+ }
+
+ function test_accept() {
+ var control = dialog.createObject(testCase)
+
+ control.open()
+ waitForRendering(control.contentItem)
+ verify(control.visible)
+
+ var acceptedSpy = signalSpy.createObject(testCase, {target: control, signalName: "accepted"})
+ verify(acceptedSpy.valid)
+ control.accept()
+ compare(acceptedSpy.count, 1)
+
+ tryCompare(control, "visible", false)
+
+ control.destroy()
+ }
+
+ function test_reject() {
+ var control = dialog.createObject(testCase)
+
+ control.open()
+ waitForRendering(control.contentItem)
+ verify(control.visible)
+
+ var rejectedSpy = signalSpy.createObject(testCase, {target: control, signalName: "rejected"})
+ verify(rejectedSpy.valid)
+ control.reject()
+ compare(rejectedSpy.count, 1)
+
+ tryCompare(control, "visible", false)
+
+ control.destroy()
+ }
+
+ function test_buttonBox_data() {
+ return [
+ { tag: "default header", property: "header", buttonBox: headerBox },
+ { tag: "default footer", property: "footer", buttonBox: footerBox },
+ { tag: "custom header", property: "header", position: DialogButtonBox.Header },
+ { tag: "custom footer", property: "footer", position: DialogButtonBox.Footer }
+ ]
+ }
+
+ function test_buttonBox(data) {
+ var control = dialog.createObject(testCase)
+
+ if (data.buttonBox)
+ control.buttonBox = data.buttonBox
+ else
+ control[data.property] = buttonBox.createObject(testCase, {position: data.position})
+ control.standardButtons = Dialog.Ok | Dialog.Cancel
+ var box = control[data.property]
+ verify(box)
+ compare(box.standardButtons, Dialog.Ok | Dialog.Cancel)
+
+ var acceptedSpy = signalSpy.createObject(testCase, {target: control, signalName: "accepted"})
+ verify(acceptedSpy.valid)
+ box.accepted()
+ compare(acceptedSpy.count, 1)
+
+ var rejectedSpy = signalSpy.createObject(testCase, {target: control, signalName: "rejected"})
+ verify(rejectedSpy.valid)
+ box.rejected()
+ compare(rejectedSpy.count, 1)
+
+ control.destroy()
+ }
+
+ function test_standardButtons() {
+ var control = dialog.createObject(testCase)
+
+ control.standardButtons = Dialog.Ok
+
+ var box = control.footer ? control.footer : control.header
+ verify(box)
+ compare(box.count, 1)
+ var okButton = box.itemAt(0)
+ verify(okButton)
+ compare(okButton.text.toUpperCase(), "OK")
+
+ control.standardButtons = Dialog.Cancel
+ compare(box.count, 1)
+ var cancelButton = control.footer.itemAt(0)
+ verify(cancelButton)
+ compare(cancelButton.text.toUpperCase(), "CANCEL")
+
+ control.standardButtons = Dialog.Ok | Dialog.Cancel
+ compare(box.count, 2)
+ if (box.itemAt(0).text.toUpperCase() === "OK") {
+ okButton = box.itemAt(0)
+ cancelButton = box.itemAt(1)
+ } else {
+ okButton = box.itemAt(1)
+ cancelButton = box.itemAt(0)
+ }
+ verify(okButton)
+ verify(cancelButton)
+ compare(okButton.text.toUpperCase(), "OK")
+ compare(cancelButton.text.toUpperCase(), "CANCEL")
+
+ control.standardButtons = 0
+ compare(box.count, 0)
+
+ control.destroy()
+ }
+
+ function test_warnings() {
+ var control = dialog.createObject(testCase)
+ verify(control)
+
+ var testComponent = Qt.createComponent("TestItem.qml")
+ verify(testComponent)
+
+ control.buttonBox = headerBox
+ control.header = testComponent.createObject(testCase)
+ ignoreWarning(Qt.resolvedUrl("tst_dialog.qml") + ":56:9: QML Dialog: Custom header detected. Cannot assign buttonBox as a header. No standard buttons will appear in the header.")
+ control.standardButtons = Dialog.Apply
+
+ control.buttonBox = footerBox
+ control.footer = testComponent.createObject(testCase)
+ ignoreWarning(Qt.resolvedUrl("tst_dialog.qml") + ":56:9: QML Dialog: Custom footer detected. Cannot assign buttonBox as a footer. No standard buttons will appear in the footer.")
+ control.standardButtons = Dialog.Cancel
+
+ control.buttonBox = testComponent
+ ignoreWarning(Qt.resolvedUrl("tst_dialog.qml") + ":56:9: QML Dialog: buttonBox must be an instance of DialogButtonBox")
+ control.standardButtons = Dialog.Ok
+
+ control.destroy()
+ }
+
+ function test_layout() {
+ var control = dialog.createObject(testCase, {width: 100, height: 100})
+ verify(control)
+
+ control.open()
+ waitForRendering(control.contentItem)
+ verify(control.visible)
+
+ compare(control.width, 100)
+ compare(control.height, 100)
+ compare(control.contentItem.width, control.availableWidth)
+ compare(control.contentItem.height, control.availableHeight)
+
+ control.header = buttonBox.createObject(control.contentItem)
+ compare(control.header.width, control.width)
+ verify(control.header.height > 0)
+ compare(control.contentItem.width, control.availableWidth)
+ compare(control.contentItem.height, control.availableHeight - control.header.height)
+
+ control.footer = buttonBox.createObject(control.contentItem)
+ compare(control.footer.width, control.width)
+ verify(control.footer.height > 0)
+ compare(control.contentItem.width, control.availableWidth)
+ compare(control.contentItem.height, control.availableHeight - control.header.height - control.footer.height)
+
+ control.topPadding = 9
+ control.leftPadding = 2
+ control.rightPadding = 6
+ control.bottomPadding = 7
+
+ compare(control.header.x, 0)
+ compare(control.header.y, 0)
+ compare(control.header.width, control.width)
+ verify(control.header.height > 0)
+
+ compare(control.footer.x, 0)
+ compare(control.footer.y, control.height - control.footer.height)
+ compare(control.footer.width, control.width)
+ verify(control.footer.height > 0)
+
+ compare(control.contentItem.x, control.leftPadding)
+ compare(control.contentItem.y, control.topPadding + control.header.height)
+ compare(control.contentItem.width, control.availableWidth)
+ compare(control.contentItem.height, control.availableHeight - control.header.height - control.footer.height)
+
+ control.header.visible = false
+ compare(control.contentItem.x, control.leftPadding)
+ compare(control.contentItem.y, control.topPadding)
+ compare(control.contentItem.width, control.availableWidth)
+ compare(control.contentItem.height, control.availableHeight - control.footer.height)
+
+ control.footer.visible = false
+ compare(control.contentItem.x, control.leftPadding)
+ compare(control.contentItem.y, control.topPadding)
+ compare(control.contentItem.width, control.availableWidth)
+ compare(control.contentItem.height, control.availableHeight)
+
+ control.contentItem.implicitWidth = 50
+ control.contentItem.implicitHeight = 60
+ compare(control.implicitWidth, control.contentItem.implicitWidth + control.leftPadding + control.rightPadding)
+ compare(control.implicitHeight, control.contentItem.implicitHeight + control.topPadding + control.bottomPadding)
+
+ control.header.visible = true
+ compare(control.implicitHeight, control.contentItem.implicitHeight + control.topPadding + control.bottomPadding
+ + control.header.implicitHeight)
+
+ control.footer.visible = true
+ compare(control.implicitHeight, control.contentItem.implicitHeight + control.topPadding + control.bottomPadding
+ + control.header.implicitHeight + control.footer.implicitHeight)
+
+ control.header.implicitWidth = 150
+ compare(control.implicitWidth, control.header.implicitWidth)
+
+ control.footer.implicitWidth = 160
+ compare(control.implicitWidth, control.footer.implicitWidth)
+
+ control.destroy()
+ }
+}
diff --git a/tests/auto/controls/data/tst_dialogbuttonbox.qml b/tests/auto/controls/data/tst_dialogbuttonbox.qml
new file mode 100644
index 00000000..8474e89b
--- /dev/null
+++ b/tests/auto/controls/data/tst_dialogbuttonbox.qml
@@ -0,0 +1,188 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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.1
+
+TestCase {
+ id: testCase
+ width: 200
+ height: 200
+ visible: true
+ when: windowShown
+ name: "DialogButtonBox"
+
+ Component {
+ id: buttonBox
+ DialogButtonBox { }
+ }
+
+ Component {
+ id: button
+ Button { }
+ }
+
+ Component {
+ id: signalSpy
+ SignalSpy { }
+ }
+
+ function test_defaults() {
+ var control = buttonBox.createObject(testCase)
+ verify(control)
+ compare(control.count, 0)
+ verify(control.delegate)
+ compare(control.standardButtons, 0)
+ control.destroy()
+ }
+
+ function test_standardButtons() {
+ var control = buttonBox.createObject(testCase)
+
+ compare(control.count, 0)
+
+ control.standardButtons = DialogButtonBox.Ok
+ compare(control.count, 1)
+ var okButton = control.itemAt(0)
+ verify(okButton)
+ compare(okButton.text.toUpperCase(), "OK")
+
+ control.standardButtons = DialogButtonBox.Cancel
+ compare(control.count, 1)
+ var cancelButton = control.itemAt(0)
+ verify(cancelButton)
+ compare(cancelButton.text.toUpperCase(), "CANCEL")
+
+ control.standardButtons = DialogButtonBox.Ok | DialogButtonBox.Cancel
+ compare(control.count, 2)
+ if (control.itemAt(0).text.toUpperCase() === "OK") {
+ okButton = control.itemAt(0)
+ cancelButton = control.itemAt(1)
+ } else {
+ okButton = control.itemAt(1)
+ cancelButton = control.itemAt(0)
+ }
+ verify(okButton)
+ verify(cancelButton)
+ compare(okButton.text.toUpperCase(), "OK")
+ compare(cancelButton.text.toUpperCase(), "CANCEL")
+
+ control.standardButtons = 0
+ compare(control.count, 0)
+
+ control.destroy()
+ }
+
+ function test_attached() {
+ var control = buttonBox.createObject(testCase)
+
+ control.standardButtons = DialogButtonBox.Ok
+ var okButton = control.itemAt(0)
+ compare(okButton.DialogButtonBox.buttonBox, control)
+ compare(okButton.DialogButtonBox.buttonRole, DialogButtonBox.AcceptRole)
+
+ var saveButton = button.createObject(control, {text: "Save"})
+ compare(saveButton.DialogButtonBox.buttonBox, control)
+ compare(saveButton.DialogButtonBox.buttonRole, DialogButtonBox.InvalidRole)
+ saveButton.DialogButtonBox.buttonRole = DialogButtonBox.AcceptRole
+ compare(saveButton.DialogButtonBox.buttonRole, DialogButtonBox.AcceptRole)
+
+ var closeButton = button.createObject(null, {text: "Save"})
+ compare(closeButton.DialogButtonBox.buttonBox, null)
+ compare(closeButton.DialogButtonBox.buttonRole, DialogButtonBox.InvalidRole)
+ closeButton.DialogButtonBox.buttonRole = DialogButtonBox.DestructiveRole
+ compare(closeButton.DialogButtonBox.buttonRole, DialogButtonBox.DestructiveRole)
+ control.addItem(closeButton)
+ compare(closeButton.DialogButtonBox.buttonBox, control)
+
+ control.contentModel.clear()
+ compare(okButton.DialogButtonBox.buttonBox, null)
+ compare(saveButton.DialogButtonBox.buttonBox, null)
+ compare(closeButton.DialogButtonBox.buttonBox, null)
+
+ control.destroy()
+ }
+
+ function test_signals_data() {
+ return [
+ { tag: "Ok", standardButton: DialogButtonBox.Ok, buttonRole: DialogButtonBox.AcceptRole, signalName: "accepted" },
+ { tag: "Open", standardButton: DialogButtonBox.Open, buttonRole: DialogButtonBox.AcceptRole, signalName: "accepted" },
+ { tag: "Save", standardButton: DialogButtonBox.Save, buttonRole: DialogButtonBox.AcceptRole, signalName: "accepted" },
+ { tag: "Cancel", standardButton: DialogButtonBox.Cancel, buttonRole: DialogButtonBox.RejectRole, signalName: "rejected" },
+ { tag: "Close", standardButton: DialogButtonBox.Close, buttonRole: DialogButtonBox.RejectRole, signalName: "rejected" },
+ { tag: "Discard", standardButton: DialogButtonBox.Discard, buttonRole: DialogButtonBox.DestructiveRole },
+ { tag: "Apply", standardButton: DialogButtonBox.Apply, buttonRole: DialogButtonBox.ApplyRole },
+ { tag: "Reset", standardButton: DialogButtonBox.Reset, buttonRole: DialogButtonBox.ResetRole },
+ { tag: "RestoreDefaults", standardButton: DialogButtonBox.RestoreDefaults, buttonRole: DialogButtonBox.ResetRole },
+ { tag: "Help", standardButton: DialogButtonBox.Help, buttonRole: DialogButtonBox.HelpRole, signalName: "helpRequested" },
+ { tag: "SaveAll", standardButton: DialogButtonBox.SaveAll, buttonRole: DialogButtonBox.AcceptRole, signalName: "accepted" },
+ { tag: "Yes", standardButton: DialogButtonBox.Yes, buttonRole: DialogButtonBox.YesRole, signalName: "accepted" },
+ { tag: "YesToAll", standardButton: DialogButtonBox.YesToAll, buttonRole: DialogButtonBox.YesRole, signalName: "accepted" },
+ { tag: "No", standardButton: DialogButtonBox.No, buttonRole: DialogButtonBox.NoRole, signalName: "rejected" },
+ { tag: "NoToAll", standardButton: DialogButtonBox.NoToAll, buttonRole: DialogButtonBox.NoRole, signalName: "rejected" },
+ { tag: "Abort", standardButton: DialogButtonBox.Abort, buttonRole: DialogButtonBox.RejectRole, signalName: "rejected" },
+ { tag: "Retry", standardButton: DialogButtonBox.Retry, buttonRole: DialogButtonBox.AcceptRole, signalName: "accepted" },
+ { tag: "Ignore", standardButton: DialogButtonBox.Ignore, buttonRole: DialogButtonBox.AcceptRole, signalName: "accepted" }
+ ]
+ }
+
+ function test_signals(data) {
+ var control = buttonBox.createObject(testCase)
+
+ control.standardButtons = data.standardButton
+ compare(control.count, 1)
+ var button = control.itemAt(0)
+ verify(button)
+ compare(button.DialogButtonBox.buttonRole, data.buttonRole)
+
+ var clickedSpy = signalSpy.createObject(control, {target: control, signalName: "clicked"})
+ verify(clickedSpy.valid)
+ var roleSpy = signalSpy.createObject(control, {target: control, signalName: data.signalName})
+ compare(roleSpy.valid, !!data.signalName)
+
+ button.clicked()
+ compare(clickedSpy.count, 1)
+ compare(clickedSpy.signalArguments[0][0], button)
+ compare(roleSpy.count, !!data.signalName ? 1 : 0)
+
+ control.destroy()
+ }
+}
diff --git a/tests/auto/controls/data/tst_drawer.qml b/tests/auto/controls/data/tst_drawer.qml
index 021afdb2..2e1f32dc 100644
--- a/tests/auto/controls/data/tst_drawer.qml
+++ b/tests/auto/controls/data/tst_drawer.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
diff --git a/tests/auto/controls/data/tst_frame.qml b/tests/auto/controls/data/tst_frame.qml
index a96397de..c64b0048 100644
--- a/tests/auto/controls/data/tst_frame.qml
+++ b/tests/auto/controls/data/tst_frame.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
diff --git a/tests/auto/controls/data/tst_groupbox.qml b/tests/auto/controls/data/tst_groupbox.qml
index 0181ea6b..41f1c780 100644
--- a/tests/auto/controls/data/tst_groupbox.qml
+++ b/tests/auto/controls/data/tst_groupbox.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
diff --git a/tests/auto/controls/data/tst_itemdelegate.qml b/tests/auto/controls/data/tst_itemdelegate.qml
index 37b0db2a..8eafad57 100644
--- a/tests/auto/controls/data/tst_itemdelegate.qml
+++ b/tests/auto/controls/data/tst_itemdelegate.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
diff --git a/tests/auto/controls/data/tst_label.qml b/tests/auto/controls/data/tst_label.qml
index 6dae0992..b3350cf5 100644
--- a/tests/auto/controls/data/tst_label.qml
+++ b/tests/auto/controls/data/tst_label.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
diff --git a/tests/auto/controls/data/tst_menuitem.qml b/tests/auto/controls/data/tst_menuitem.qml
index be0c0652..b5e08866 100644
--- a/tests/auto/controls/data/tst_menuitem.qml
+++ b/tests/auto/controls/data/tst_menuitem.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
diff --git a/tests/auto/controls/data/tst_page.qml b/tests/auto/controls/data/tst_page.qml
index bc7afa50..a1cdbf8e 100644
--- a/tests/auto/controls/data/tst_page.qml
+++ b/tests/auto/controls/data/tst_page.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
@@ -56,6 +56,40 @@ TestCase {
}
Component {
+ id: oneChildPage
+ Page {
+ Item {
+ implicitWidth: 100
+ implicitHeight: 30
+ }
+ }
+ }
+
+ Component {
+ id: twoChildrenPage
+ Page {
+ Item {
+ implicitWidth: 100
+ implicitHeight: 30
+ }
+ Item {
+ implicitWidth: 200
+ implicitHeight: 60
+ }
+ }
+ }
+
+ Component {
+ id: contentPage
+ Page {
+ contentItem: Item {
+ implicitWidth: 100
+ implicitHeight: 30
+ }
+ }
+ }
+
+ Component {
id: toolBar
ToolBar { }
}
@@ -71,6 +105,53 @@ TestCase {
control.destroy()
}
+ function test_empty() {
+ var control = page.createObject(testCase)
+ verify(control)
+
+ verify(control.contentItem)
+ compare(control.contentWidth, 0)
+ compare(control.contentHeight, 0)
+
+ control.destroy()
+ }
+
+ function test_oneChild() {
+ var control = oneChildPage.createObject(testCase)
+ verify(control)
+
+ compare(control.contentWidth, 100)
+ compare(control.contentHeight, 30)
+ compare(control.implicitWidth, 100 + control.leftPadding + control.rightPadding)
+ compare(control.implicitHeight, 30 + control.topPadding + control.bottomPadding)
+
+ control.destroy()
+ }
+
+ function test_twoChildren() {
+ var control = twoChildrenPage.createObject(testCase)
+ verify(control)
+
+ compare(control.contentWidth, 0)
+ compare(control.contentHeight, 0)
+ compare(control.implicitWidth, control.leftPadding + control.rightPadding)
+ compare(control.implicitHeight, control.topPadding + control.bottomPadding)
+
+ control.destroy()
+ }
+
+ function test_contentItem() {
+ var control = contentPage.createObject(testCase)
+ verify(control)
+
+ compare(control.contentWidth, 100)
+ compare(control.contentHeight, 30)
+ compare(control.implicitWidth, 100 + control.leftPadding + control.rightPadding)
+ compare(control.implicitHeight, 30 + control.topPadding + control.bottomPadding)
+
+ control.destroy()
+ }
+
function test_layout() {
var control = page.createObject(testCase, {width: 100, height: 100})
verify(control)
@@ -124,6 +205,25 @@ TestCase {
compare(control.contentItem.width, control.availableWidth)
compare(control.contentItem.height, control.availableHeight)
+ control.contentItem.implicitWidth = 50
+ control.contentItem.implicitHeight = 60
+ compare(control.implicitWidth, control.contentItem.implicitWidth + control.leftPadding + control.rightPadding)
+ compare(control.implicitHeight, control.contentItem.implicitHeight + control.topPadding + control.bottomPadding)
+
+ control.header.visible = true
+ compare(control.implicitHeight, control.contentItem.implicitHeight + control.topPadding + control.bottomPadding
+ + control.header.implicitHeight + control.spacing)
+
+ control.footer.visible = true
+ compare(control.implicitHeight, control.contentItem.implicitHeight + control.topPadding + control.bottomPadding
+ + control.header.implicitHeight + control.footer.implicitHeight + 2 * control.spacing)
+
+ control.header.implicitWidth = 150
+ compare(control.implicitWidth, control.header.implicitWidth + control.leftPadding + control.rightPadding)
+
+ control.footer.implicitWidth = 160
+ compare(control.implicitWidth, control.footer.implicitWidth + control.leftPadding + control.rightPadding)
+
control.destroy()
}
}
diff --git a/tests/auto/controls/data/tst_pageindicator.qml b/tests/auto/controls/data/tst_pageindicator.qml
index d1f1223a..a39265c3 100644
--- a/tests/auto/controls/data/tst_pageindicator.qml
+++ b/tests/auto/controls/data/tst_pageindicator.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
diff --git a/tests/auto/controls/data/tst_pane.qml b/tests/auto/controls/data/tst_pane.qml
index a0b8a5c8..2f5ddef3 100644
--- a/tests/auto/controls/data/tst_pane.qml
+++ b/tests/auto/controls/data/tst_pane.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
diff --git a/tests/auto/controls/data/tst_popup.qml b/tests/auto/controls/data/tst_popup.qml
index 82fcbf8b..c81c6341 100644
--- a/tests/auto/controls/data/tst_popup.qml
+++ b/tests/auto/controls/data/tst_popup.qml
@@ -40,13 +40,13 @@
import QtQuick 2.4
import QtTest 1.0
-import QtQuick.Controls 2.0
-import QtQuick.Templates 2.0 as T
+import QtQuick.Controls 2.1
+import QtQuick.Templates 2.1 as T
TestCase {
id: testCase
- width: 480
- height: 360
+ width: 400
+ height: 400
visible: true
when: windowShown
name: "Popup"
diff --git a/tests/auto/controls/data/tst_progressbar.qml b/tests/auto/controls/data/tst_progressbar.qml
index 5603c280..d7280503 100644
--- a/tests/auto/controls/data/tst_progressbar.qml
+++ b/tests/auto/controls/data/tst_progressbar.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
diff --git a/tests/auto/controls/data/tst_radiobutton.qml b/tests/auto/controls/data/tst_radiobutton.qml
index bd3850c8..94e3a2cb 100644
--- a/tests/auto/controls/data/tst_radiobutton.qml
+++ b/tests/auto/controls/data/tst_radiobutton.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
diff --git a/tests/auto/controls/data/tst_radiodelegate.qml b/tests/auto/controls/data/tst_radiodelegate.qml
index 1a424a32..66b47b3a 100644
--- a/tests/auto/controls/data/tst_radiodelegate.qml
+++ b/tests/auto/controls/data/tst_radiodelegate.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
diff --git a/tests/auto/controls/data/tst_rangeslider.qml b/tests/auto/controls/data/tst_rangeslider.qml
index 3167be0b..eb654bbc 100644
--- a/tests/auto/controls/data/tst_rangeslider.qml
+++ b/tests/auto/controls/data/tst_rangeslider.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
@@ -675,4 +675,31 @@ TestCase {
control.destroy()
}
+
+ function test_hover_data() {
+ return [
+ { tag: "first:true", node: "first", hoverEnabled: true },
+ { tag: "first:false", node: "first", hoverEnabled: false },
+ { tag: "second:true", node: "second", hoverEnabled: true },
+ { tag: "second:false", node: "second", hoverEnabled: false }
+ ]
+ }
+
+ function test_hover(data) {
+ var control = sliderComponent.createObject(testCase, {hoverEnabled: data.hoverEnabled})
+ verify(control)
+
+ var node = control[data.node]
+ compare(control.hovered, false)
+ compare(node.hovered, false)
+
+ mouseMove(control, node.handle.x + node.handle.width / 2, node.handle.y + node.handle.height / 2)
+ compare(control.hovered, data.hoverEnabled)
+ compare(node.hovered, data.hoverEnabled && node.handle.enabled)
+
+ mouseMove(control, node.handle.x - 1, node.handle.y - 1)
+ compare(node.hovered, false)
+
+ control.destroy()
+ }
}
diff --git a/tests/auto/controls/data/tst_roundbutton.qml b/tests/auto/controls/data/tst_roundbutton.qml
new file mode 100644
index 00000000..aa956776
--- /dev/null
+++ b/tests/auto/controls/data/tst_roundbutton.qml
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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.1
+
+TestCase {
+ id: testCase
+ width: 200
+ height: 200
+ visible: true
+ when: windowShown
+ name: "RoundButton"
+
+ Component {
+ id: roundButton
+ RoundButton { }
+ }
+
+ function test_radius() {
+ var control = roundButton.createObject(testCase);
+ verify(control);
+
+ var implicitRadius = control.radius;
+ compare(implicitRadius, Math.min(control.width, control.height) / 2);
+
+ control.radius = 10;
+ compare(control.radius, 10);
+
+ control.radius = undefined;
+ compare(control.radius, implicitRadius);
+
+ control.width = -1;
+ compare(control.radius, 0);
+
+ control.width = 10;
+ compare(control.radius, 5);
+
+ control.destroy();
+ }
+}
diff --git a/tests/auto/controls/data/tst_scrollbar.qml b/tests/auto/controls/data/tst_scrollbar.qml
index 1684ba51..15b4b3f0 100644
--- a/tests/auto/controls/data/tst_scrollbar.qml
+++ b/tests/auto/controls/data/tst_scrollbar.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
@@ -97,6 +97,13 @@ TestCase {
compare(vertical.y, 0)
verify(vertical.width > 0)
compare(vertical.height, container.height)
+ // vertical scroll bar follows flickable's width
+ container.width += 10
+ compare(vertical.x, container.width - vertical.width)
+ // ...unless explicitly positioned
+ vertical.x = 123
+ container.width += 10
+ compare(vertical.x, 123)
var horizontal = scrollBar.createObject()
verify(!horizontal.parent)
@@ -118,6 +125,13 @@ TestCase {
compare(horizontal.y, container.height - horizontal.height)
compare(horizontal.width, container.width)
verify(horizontal.height > 0)
+ // horizontal scroll bar follows flickable's height
+ container.height += 10
+ compare(horizontal.y, container.height - horizontal.height)
+ // ...unless explicitly positioned
+ horizontal.y = 123
+ container.height += 10
+ compare(horizontal.y, 123)
var velocity = container.maximumFlickVelocity
@@ -299,4 +313,28 @@ TestCase {
container.destroy()
}
+
+ function test_hover_data() {
+ return [
+ { tag: "enabled", hoverEnabled: true },
+ { tag: "disabled", hoverEnabled: false },
+ ]
+ }
+
+ function test_hover(data) {
+ var control = scrollBar.createObject(testCase, {hoverEnabled: data.hoverEnabled})
+ verify(control)
+
+ compare(control.hovered, false)
+
+ mouseMove(control)
+ compare(control.hovered, data.hoverEnabled)
+ compare(control.active, data.hoverEnabled)
+
+ mouseMove(control, -1, -1)
+ compare(control.hovered, false)
+ compare(control.active, false)
+
+ control.destroy()
+ }
}
diff --git a/tests/auto/controls/data/tst_scrollindicator.qml b/tests/auto/controls/data/tst_scrollindicator.qml
index 90d9287a..551247f6 100644
--- a/tests/auto/controls/data/tst_scrollindicator.qml
+++ b/tests/auto/controls/data/tst_scrollindicator.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
@@ -92,6 +92,13 @@ TestCase {
compare(vertical.y, 0)
verify(vertical.width > 0)
compare(vertical.height, container.height)
+ // vertical scroll indicator follows flickable's width
+ container.width += 10
+ compare(vertical.x, container.width - vertical.width)
+ // ...unless explicitly positioned
+ vertical.x = 123
+ container.width += 10
+ compare(vertical.x, 123)
var horizontal = scrollIndicator.createObject()
verify(!horizontal.parent)
@@ -113,6 +120,13 @@ TestCase {
compare(horizontal.y, container.height - horizontal.height)
compare(horizontal.width, container.width)
verify(horizontal.height > 0)
+ // horizontal scroll indicator follows flickable's height
+ container.height += 10
+ compare(horizontal.y, container.height - horizontal.height)
+ // ...unless explicitly positioned
+ horizontal.y = 123
+ container.height += 10
+ compare(horizontal.y, 123)
var velocity = container.maximumFlickVelocity
diff --git a/tests/auto/controls/data/tst_slider.qml b/tests/auto/controls/data/tst_slider.qml
index 4a698076..029aff14 100644
--- a/tests/auto/controls/data/tst_slider.qml
+++ b/tests/auto/controls/data/tst_slider.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
@@ -520,4 +520,24 @@ TestCase {
control.destroy()
}
+
+ function test_valueAt_data() {
+ return [
+ { tag: "0.0..1.0", from: 0.0, to: 1.0, values: [0.0, 0.2, 0.5, 1.0] },
+ { tag: "0..100", from: 0, to: 100, values: [0, 20, 50, 100] },
+ { tag: "100..-100", from: 100, to: -100, values: [100, 60, 0, -100] }
+ ]
+ }
+
+ function test_valueAt(data) {
+ var control = slider.createObject(testCase, {from: data.from, to: data.to})
+ verify(control)
+
+ compare(control.valueAt(0.0), data.values[0])
+ compare(control.valueAt(0.2), data.values[1])
+ compare(control.valueAt(0.5), data.values[2])
+ compare(control.valueAt(1.0), data.values[3])
+
+ control.destroy()
+ }
}
diff --git a/tests/auto/controls/data/tst_spinbox.qml b/tests/auto/controls/data/tst_spinbox.qml
index a62128d2..30db246f 100644
--- a/tests/auto/controls/data/tst_spinbox.qml
+++ b/tests/auto/controls/data/tst_spinbox.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
@@ -460,6 +460,35 @@ TestCase {
control.destroy()
}
+ function test_hover_data() {
+ return [
+ { tag: "up:true", button: "up", hoverEnabled: true, value: 50 },
+ { tag: "up:false", button: "up", hoverEnabled: false, value: 50 },
+ { tag: "up:max", button: "up", hoverEnabled: true, value: 99 },
+ { tag: "down:true", button: "down", hoverEnabled: true, value: 50 },
+ { tag: "down:false", button: "down", hoverEnabled: false, value: 50 },
+ { tag: "down:min", button: "down", hoverEnabled: true, value: 0 }
+ ]
+ }
+
+ function test_hover(data) {
+ var control = spinBox.createObject(testCase, {hoverEnabled: data.hoverEnabled, value: data.value})
+ verify(control)
+
+ var button = control[data.button]
+ compare(control.hovered, false)
+ compare(button.hovered, false)
+
+ mouseMove(control, button.indicator.x + button.indicator.width / 2, button.indicator.y + button.indicator.height / 2)
+ compare(control.hovered, data.hoverEnabled)
+ compare(button.hovered, data.hoverEnabled && button.indicator.enabled)
+
+ mouseMove(control, button.indicator.x - 1, button.indicator.y - 1)
+ compare(button.hovered, false)
+
+ control.destroy()
+ }
+
function test_valueFromText_data() {
return [
{ tag: "editable", editable: true },
diff --git a/tests/auto/controls/data/tst_stackview.qml b/tests/auto/controls/data/tst_stackview.qml
index 28a22306..b0e18389 100644
--- a/tests/auto/controls/data/tst_stackview.qml
+++ b/tests/auto/controls/data/tst_stackview.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
@@ -567,29 +567,60 @@ TestCase {
}
}
- function test_transitions() {
+ function test_transitions_data() {
+ return [
+ { tag: "undefined", operation: undefined,
+ pushEnterRuns: [0,1,1,1], pushExitRuns: [0,1,1,1], replaceEnterRuns: [0,0,1,1], replaceExitRuns: [0,0,1,1], popEnterRuns: [0,0,0,1], popExitRuns: [0,0,0,1] },
+ { tag: "immediate", operation: StackView.Immediate,
+ pushEnterRuns: [0,0,0,0], pushExitRuns: [0,0,0,0], replaceEnterRuns: [0,0,0,0], replaceExitRuns: [0,0,0,0], popEnterRuns: [0,0,0,0], popExitRuns: [0,0,0,0] },
+ { tag: "push", operation: StackView.PushTransition,
+ pushEnterRuns: [1,2,3,4], pushExitRuns: [0,1,2,3], replaceEnterRuns: [0,0,0,0], replaceExitRuns: [0,0,0,0], popEnterRuns: [0,0,0,0], popExitRuns: [0,0,0,0] },
+ { tag: "pop", operation: StackView.PopTransition,
+ pushEnterRuns: [0,0,0,0], pushExitRuns: [0,0,0,0], replaceEnterRuns: [0,0,0,0], replaceExitRuns: [0,0,0,0], popEnterRuns: [1,2,3,4], popExitRuns: [0,1,2,3] },
+ { tag: "replace", operation: StackView.ReplaceTransition,
+ pushEnterRuns: [0,0,0,0], pushExitRuns: [0,0,0,0], replaceEnterRuns: [1,2,3,4], replaceExitRuns: [0,1,2,3], popEnterRuns: [0,0,0,0], popExitRuns: [0,0,0,0] },
+ ]
+ }
+
+ function test_transitions(data) {
var control = transitionView.createObject(testCase)
verify(control)
- control.push(component)
- verify(!control.busy)
- compare(control.pushEnterRuns, 0)
- compare(control.pushExitRuns, 0)
-
- control.push(component)
+ control.push(component, data.operation)
+ tryCompare(control, "busy", false)
+ compare(control.pushEnterRuns, data.pushEnterRuns[0])
+ compare(control.pushExitRuns, data.pushExitRuns[0])
+ compare(control.replaceEnterRuns, data.replaceEnterRuns[0])
+ compare(control.replaceExitRuns, data.replaceExitRuns[0])
+ compare(control.popEnterRuns, data.popEnterRuns[0])
+ compare(control.popExitRuns, data.popExitRuns[0])
+
+ control.push(component, data.operation)
tryCompare(control, "busy", false)
- compare(control.pushEnterRuns, 1)
- compare(control.pushExitRuns, 1)
+ compare(control.pushEnterRuns, data.pushEnterRuns[1])
+ compare(control.pushExitRuns, data.pushExitRuns[1])
+ compare(control.replaceEnterRuns, data.replaceEnterRuns[1])
+ compare(control.replaceExitRuns, data.replaceExitRuns[1])
+ compare(control.popEnterRuns, data.popEnterRuns[1])
+ compare(control.popExitRuns, data.popExitRuns[1])
- control.replace(component)
+ control.replace(component, data.operation)
tryCompare(control, "busy", false)
- compare(control.replaceEnterRuns, 1)
- compare(control.replaceExitRuns, 1)
+ compare(control.pushEnterRuns, data.pushEnterRuns[2])
+ compare(control.pushExitRuns, data.pushExitRuns[2])
+ compare(control.replaceEnterRuns, data.replaceEnterRuns[2])
+ compare(control.replaceExitRuns, data.replaceExitRuns[2])
+ compare(control.popEnterRuns, data.popEnterRuns[2])
+ compare(control.popExitRuns, data.popExitRuns[2])
- control.pop()
+ control.pop(data.operation)
tryCompare(control, "busy", false)
- compare(control.popEnterRuns, 1)
- compare(control.popExitRuns, 1)
+ compare(control.pushEnterRuns, data.pushEnterRuns[3])
+ compare(control.pushExitRuns, data.pushExitRuns[3])
+ compare(control.replaceEnterRuns, data.replaceEnterRuns[3])
+ compare(control.replaceExitRuns, data.replaceExitRuns[3])
+ compare(control.popEnterRuns, data.popEnterRuns[3])
+ compare(control.popExitRuns, data.popExitRuns[3])
control.destroy()
}
@@ -644,6 +675,60 @@ TestCase {
}
Component {
+ id: removeComponent
+
+ Item {
+ objectName: "removeItem"
+ StackView.onRemoved: destroy()
+ }
+ }
+
+ function test_destroyOnRemoved() {
+ var control = stackView.createObject(testCase, { initialItem: component })
+ verify(control)
+
+ var item = removeComponent.createObject(control)
+ verify(item)
+
+ var removedSpy = signalSpy.createObject(control, { target: item.StackView, signalName: "removed" })
+ verify(removedSpy)
+ verify(removedSpy.valid)
+
+ var destructionSpy = signalSpy.createObject(control, { target: item.Component, signalName: "destruction" })
+ verify(destructionSpy)
+ verify(destructionSpy.valid)
+
+ // push-pop
+ control.push(item, StackView.Immediate)
+ compare(control.currentItem, item)
+ control.pop(StackView.Transition)
+ item = null
+ tryCompare(removedSpy, "count", 1)
+ tryCompare(destructionSpy, "count", 1)
+ compare(control.busy, false)
+
+ item = removeComponent.createObject(control)
+ verify(item)
+
+ removedSpy.target = item.StackView
+ verify(removedSpy.valid)
+
+ destructionSpy.target = item.Component
+ verify(destructionSpy.valid)
+
+ // push-replace
+ control.push(item, StackView.Immediate)
+ compare(control.currentItem, item)
+ control.replace(component, StackView.Transition)
+ item = null
+ tryCompare(removedSpy, "count", 2)
+ tryCompare(destructionSpy, "count", 2)
+ compare(control.busy, false)
+
+ control.destroy()
+ }
+
+ Component {
id: attachedItem
Item {
property int index: StackView.index
@@ -831,11 +916,11 @@ TestCase {
verify(control)
ignoreWarning("QQmlComponent: Component is not ready")
- ignoreWarning(Qt.resolvedUrl("non-existent.qml") + ":-1 File not found")
+ ignoreWarning(Qt.resolvedUrl("non-existent.qml") + ":-1 No such file or directory")
control.push(Qt.resolvedUrl("non-existent.qml"))
ignoreWarning("QQmlComponent: Component is not ready")
- ignoreWarning(Qt.resolvedUrl("non-existent.qml") + ":-1 File not found")
+ ignoreWarning(Qt.resolvedUrl("non-existent.qml") + ":-1 No such file or directory")
control.replace(Qt.resolvedUrl("non-existent.qml"))
control.pop()
@@ -862,6 +947,62 @@ TestCase {
control.destroy()
}
+ Component {
+ id: signalTest
+ Control {
+ id: ctrl
+ property SignalSpy activatedSpy: SignalSpy { target: ctrl.StackView; signalName: "activated" }
+ property SignalSpy activatingSpy: SignalSpy { target: ctrl.StackView; signalName: "activating" }
+ property SignalSpy deactivatedSpy: SignalSpy { target: ctrl.StackView; signalName: "deactivated" }
+ property SignalSpy deactivatingSpy: SignalSpy { target: ctrl.StackView; signalName: "deactivating" }
+ }
+ }
+
+ function test_signals() {
+ var control = stackView.createObject(testCase)
+ verify(control)
+
+ var item1 = signalTest.createObject(control)
+ compare(item1.StackView.status, StackView.Inactive)
+ control.push(item1)
+ compare(item1.StackView.status, StackView.Active)
+ compare(item1.activatedSpy.count, 1)
+ compare(item1.activatingSpy.count, 1)
+ compare(item1.deactivatedSpy.count, 0)
+ compare(item1.deactivatingSpy.count, 0)
+
+ var item2 = signalTest.createObject(control)
+ compare(item2.StackView.status, StackView.Inactive)
+ control.push(item2)
+ compare(item2.StackView.status, StackView.Activating)
+ compare(item2.activatedSpy.count, 0)
+ compare(item2.activatingSpy.count, 1)
+ compare(item2.deactivatedSpy.count, 0)
+ compare(item2.deactivatingSpy.count, 0)
+ compare(item1.StackView.status, StackView.Deactivating)
+ compare(item1.activatedSpy.count, 1)
+ compare(item1.activatingSpy.count, 1)
+ compare(item1.deactivatedSpy.count, 0)
+ compare(item1.deactivatingSpy.count, 1)
+ tryCompare(item2.activatedSpy, "count", 1)
+ tryCompare(item1.deactivatedSpy, "count", 1)
+
+ control.pop()
+ compare(item2.StackView.status, StackView.Deactivating)
+ compare(item2.activatedSpy.count, 1)
+ compare(item2.activatingSpy.count, 1)
+ compare(item2.deactivatedSpy.count, 0)
+ compare(item2.deactivatingSpy.count, 1)
+ compare(item1.StackView.status, StackView.Activating)
+ compare(item1.activatedSpy.count, 1)
+ compare(item1.activatingSpy.count, 2)
+ compare(item1.deactivatedSpy.count, 1)
+ compare(item1.deactivatingSpy.count, 1)
+ tryCompare(item1.activatedSpy, "count", 2)
+
+ control.destroy()
+ }
+
// QTBUG-56158
function test_repeatedPop() {
var control = stackView.createObject(testCase, {initialItem: component, width: testCase.width, height: testCase.height})
diff --git a/tests/auto/controls/data/tst_swipedelegate.qml b/tests/auto/controls/data/tst_swipedelegate.qml
index 21bb1a37..bcf25f28 100644
--- a/tests/auto/controls/data/tst_swipedelegate.qml
+++ b/tests/auto/controls/data/tst_swipedelegate.qml
@@ -40,7 +40,8 @@
import QtQuick 2.6
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Layouts 1.1
+import QtQuick.Controls 2.1
TestCase {
id: testCase
@@ -110,14 +111,14 @@ TestCase {
function test_horizontalAnchors_data() {
return [
- { tag: "background, fill", component: backgroundFillComponent, itemName: "background", warningLocation: ":58:25" },
- { tag: "background, centerIn", component: backgroundCenterInComponent, itemName: "background", warningLocation: ":65:25" },
- { tag: "background, left", component: backgroundLeftComponent, itemName: "background", warningLocation: ":72:25" },
- { tag: "background, right", component: backgroundRightComponent, itemName: "background", warningLocation: ":79:25" },
- { tag: "contentItem, fill", component: contentItemFillComponent, itemName: "contentItem", warningLocation: ":86:26" },
- { tag: "contentItem, centerIn", component: contentItemCenterInComponent, itemName: "contentItem", warningLocation: ":93:26" },
- { tag: "contentItem, left", component: contentItemLeftComponent, itemName: "contentItem", warningLocation: ":100:26" },
- { tag: "contentItem, right", component: contentItemRightComponent, itemName: "contentItem", warningLocation: ":107:26" }
+ { tag: "background, fill", component: backgroundFillComponent, itemName: "background", warningLocation: ":59:25" },
+ { tag: "background, centerIn", component: backgroundCenterInComponent, itemName: "background", warningLocation: ":66:25" },
+ { tag: "background, left", component: backgroundLeftComponent, itemName: "background", warningLocation: ":73:25" },
+ { tag: "background, right", component: backgroundRightComponent, itemName: "background", warningLocation: ":80:25" },
+ { tag: "contentItem, fill", component: contentItemFillComponent, itemName: "contentItem", warningLocation: ":87:26" },
+ { tag: "contentItem, centerIn", component: contentItemCenterInComponent, itemName: "contentItem", warningLocation: ":94:26" },
+ { tag: "contentItem, left", component: contentItemLeftComponent, itemName: "contentItem", warningLocation: ":101:26" },
+ { tag: "contentItem, right", component: contentItemRightComponent, itemName: "contentItem", warningLocation: ":108:26" }
];
}
@@ -166,6 +167,12 @@ TestCase {
}
Component {
+ id: signalSpyComponent
+
+ SignalSpy {}
+ }
+
+ Component {
id: itemComponent
Item {}
@@ -201,7 +208,7 @@ TestCase {
verify(control);
ignoreWarning(Qt.resolvedUrl("tst_swipedelegate.qml") +
- ":159:9: QML SwipeDelegate: cannot set both behind and left/right properties")
+ ":160:9: QML SwipeDelegate: cannot set both behind and left/right properties")
control.swipe.behind = itemComponent;
// Shouldn't be any warnings when unsetting delegates.
@@ -210,7 +217,7 @@ TestCase {
// right is still set.
ignoreWarning(Qt.resolvedUrl("tst_swipedelegate.qml") +
- ":159:9: QML SwipeDelegate: cannot set both behind and left/right properties")
+ ":160:9: QML SwipeDelegate: cannot set both behind and left/right properties")
control.swipe.behind = itemComponent;
control.swipe.right = null;
@@ -219,11 +226,11 @@ TestCase {
control.swipe.behind = itemComponent;
ignoreWarning(Qt.resolvedUrl("tst_swipedelegate.qml") +
- ":159:9: QML SwipeDelegate: cannot set both behind and left/right properties")
+ ":160:9: QML SwipeDelegate: cannot set both behind and left/right properties")
control.swipe.left = itemComponent;
ignoreWarning(Qt.resolvedUrl("tst_swipedelegate.qml") +
- ":159:9: QML SwipeDelegate: cannot set both behind and left/right properties")
+ ":160:9: QML SwipeDelegate: cannot set both behind and left/right properties")
control.swipe.right = itemComponent;
control.swipe.behind = null;
@@ -238,7 +245,7 @@ TestCase {
var oldLeft = control.swipe.left;
var oldLeftItem = control.swipe.leftItem;
ignoreWarning(Qt.resolvedUrl("tst_swipedelegate.qml") +
- ":159:9: QML SwipeDelegate: left/right/behind properties may only be set when swipe.position is 0")
+ ":160:9: QML SwipeDelegate: left/right/behind properties may only be set when swipe.position is 0")
control.swipe.left = null;
compare(control.swipe.left, oldLeft);
compare(control.swipe.leftItem, oldLeftItem);
@@ -249,7 +256,7 @@ TestCase {
var oldRight = control.swipe.right;
var oldRightItem = control.swipe.rightItem;
ignoreWarning(Qt.resolvedUrl("tst_swipedelegate.qml") +
- ":159:9: QML SwipeDelegate: left/right/behind properties may only be set when swipe.position is 0")
+ ":160:9: QML SwipeDelegate: left/right/behind properties may only be set when swipe.position is 0")
control.swipe.right = null;
compare(control.swipe.right, oldRight);
compare(control.swipe.rightItem, oldRightItem);
@@ -275,7 +282,7 @@ TestCase {
var oldBehind = control.swipe.behind;
var oldBehindItem = control.swipe.behindItem;
ignoreWarning(Qt.resolvedUrl("tst_swipedelegate.qml") +
- ":159:9: QML SwipeDelegate: left/right/behind properties may only be set when swipe.position is 0")
+ ":160:9: QML SwipeDelegate: left/right/behind properties may only be set when swipe.position is 0")
control.swipe.behind = null;
compare(control.swipe.behind, oldBehind);
compare(control.swipe.behindItem, oldBehindItem);
@@ -297,7 +304,7 @@ TestCase {
SignalSequenceSpy {
id: mouseSignalSequenceSpy
- signals: ["pressed", "released", "canceled", "clicked", "doubleClicked", "pressedChanged"]
+ signals: ["pressed", "released", "canceled", "clicked", "doubleClicked", "pressedChanged", "pressAndHold"]
}
function test_swipe() {
@@ -306,12 +313,17 @@ TestCase {
var overDragDistance = Math.round(dragDistance * 1.1);
+ var completedSpy = signalSpyComponent.createObject(control, { target: control.swipe, signalName: "completed" });
+ verify(completedSpy);
+ verify(completedSpy.valid);
+
mouseSignalSequenceSpy.target = control;
mouseSignalSequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true }], "pressed"];
mousePress(control, control.width / 2, control.height / 2);
verify(control.pressed);
compare(control.swipe.position, 0.0);
verify(!control.swipe.complete);
+ compare(completedSpy.count, 0);
verify(mouseSignalSequenceSpy.success);
verify(!control.swipe.leftItem);
verify(!control.swipe.rightItem);
@@ -321,6 +333,7 @@ TestCase {
verify(control.pressed);
compare(control.swipe.position, overDragDistance / control.width);
verify(!control.swipe.complete);
+ compare(completedSpy.count, 0);
verify(control.swipe.leftItem);
verify(control.swipe.leftItem.visible);
compare(control.swipe.leftItem.parent, control);
@@ -332,6 +345,7 @@ TestCase {
verify(control.pressed);
compare(control.swipe.position, 0.0);
verify(!control.swipe.complete);
+ compare(completedSpy.count, 0);
verify(control.swipe.leftItem);
verify(control.swipe.leftItem.visible);
compare(control.swipe.leftItem.parent, control);
@@ -344,6 +358,7 @@ TestCase {
verify(control.pressed);
compare(control.swipe.position, -overDragDistance / control.width);
verify(!control.swipe.complete);
+ compare(completedSpy.count, 0);
verify(control.swipe.leftItem);
verify(!control.swipe.leftItem.visible);
verify(control.swipe.rightItem);
@@ -356,6 +371,7 @@ TestCase {
verify(control.pressed);
compare(control.swipe.position, 0.6);
verify(!control.swipe.complete);
+ compare(completedSpy.count, 0);
verify(control.swipe.leftItem);
verify(control.swipe.leftItem.visible);
verify(control.swipe.rightItem);
@@ -366,6 +382,7 @@ TestCase {
verify(!control.pressed);
compare(control.swipe.position, 1.0);
verify(control.swipe.complete);
+ compare(completedSpy.count, 1);
verify(mouseSignalSequenceSpy.success);
verify(control.swipe.leftItem);
verify(control.swipe.leftItem.visible);
@@ -381,11 +398,13 @@ TestCase {
// complete should still be true, because we haven't moved yet, and hence
// haven't started grabbing behind's mouse events.
verify(control.swipe.complete);
+ compare(completedSpy.count, 1);
verify(mouseSignalSequenceSpy.success);
mouseMove(control, control.width / 2 - overDragDistance, control.height / 2);
verify(control.pressed);
verify(!control.swipe.complete);
+ compare(completedSpy.count, 1);
compare(control.swipe.position, 1.0 - overDragDistance / control.width);
mouseSignalSequenceSpy.expectedSequence = [["pressedChanged", { "pressed": false }], "released", "clicked"];
@@ -393,6 +412,7 @@ TestCase {
verify(!control.pressed);
compare(control.swipe.position, 1.0);
verify(control.swipe.complete);
+ compare(completedSpy.count, 2);
verify(mouseSignalSequenceSpy.success);
tryCompare(control.contentItem, "x", control.width + control.leftPadding);
@@ -402,11 +422,13 @@ TestCase {
verify(control.pressed);
compare(control.swipe.position, 1.0);
verify(control.swipe.complete);
+ compare(completedSpy.count, 2);
verify(mouseSignalSequenceSpy.success);
mouseMove(control, control.width * -0.1, control.height / 2);
verify(control.pressed);
verify(!control.swipe.complete);
+ compare(completedSpy.count, 2);
compare(control.swipe.position, 0.4);
mouseSignalSequenceSpy.expectedSequence = [["pressedChanged", { "pressed": false }], "released", "clicked"];
@@ -414,6 +436,7 @@ TestCase {
verify(!control.pressed);
compare(control.swipe.position, 0.0);
verify(!control.swipe.complete);
+ compare(completedSpy.count, 2);
verify(mouseSignalSequenceSpy.success);
tryCompare(control.contentItem, "x", control.leftPadding);
@@ -507,12 +530,6 @@ TestCase {
}
}
- Component {
- id: signalSpyComponent
-
- SignalSpy {}
- }
-
function test_eventsToLeftAndRight() {
var control = swipeDelegateWithButtonComponent.createObject(testCase);
verify(control);
@@ -607,6 +624,26 @@ TestCase {
mouseDoubleClickSequence(control, control.width / 2, control.height / 2, Qt.LeftButton);
verify(mouseSignalSequenceSpy.success);
+ // press and hold
+ var pressAndHoldSpy = signalSpyComponent.createObject(control, { target: control, signalName: "pressAndHold" });
+ verify(pressAndHoldSpy);
+ verify(pressAndHoldSpy.valid);
+
+ mouseSignalSequenceSpy.expectedSequence = [
+ ["pressedChanged", { "pressed": true }],
+ "pressed",
+ "pressAndHold",
+ ["pressedChanged", { "pressed": false }],
+ "released"
+ ];
+ mousePress(control);
+ compare(control.pressed, true);
+ tryCompare(pressAndHoldSpy, "count", 1);
+
+ mouseRelease(control);
+ compare(control.pressed, false);
+ verify(mouseSignalSequenceSpy.success);
+
control.destroy();
}
@@ -629,8 +666,6 @@ TestCase {
text: modelData
width: listView.width
- onClicked: if (swipe.complete) ListView.view.model.remove(index)
-
property alias removeAnimation: onRemoveAnimation
ListView.onRemove: SequentialAnimation {
@@ -655,9 +690,12 @@ TestCase {
}
swipe.left: Rectangle {
- color: rootDelegate.swipe.complete && rootDelegate.pressed ? "#333" : "#444"
+ objectName: "rectangle"
+ color: SwipeDelegate.pressed ? "#333" : "#444"
anchors.fill: parent
+ SwipeDelegate.onClicked: listView.model.remove(index)
+
Label {
objectName: "label"
text: "Remove"
@@ -680,11 +718,14 @@ TestCase {
verify(firstItem.pressed);
compare(firstItem.swipe.position, 0.0);
verify(!firstItem.swipe.complete);
+ verify(!firstItem.swipe.leftItem);
mouseMove(listView, firstItem.width * 1.1, firstItem.height / 2);
verify(firstItem.pressed);
compare(firstItem.swipe.position, 0.6);
verify(!firstItem.swipe.complete);
+ verify(firstItem.swipe.leftItem);
+ verify(!firstItem.swipe.leftItem.SwipeDelegate.pressed);
mouseRelease(listView, firstItem.width / 2, firstItem.height / 2);
verify(!firstItem.pressed);
@@ -695,9 +736,23 @@ TestCase {
// Wait for it to settle down.
tryCompare(firstItem.contentItem, "x", firstItem.leftPadding + firstItem.width);
- // Click the button to remove the item.
+ var leftClickedSpy = signalSpyComponent.createObject(firstItem.swipe.leftItem,
+ { target: firstItem.swipe.leftItem.SwipeDelegate, signalName: "clicked" });
+ verify(leftClickedSpy);
+ verify(leftClickedSpy.valid);
+
+ // Click the left item to remove the delegate from the list.
var contentItemX = firstItem.contentItem.x;
- mouseClick(listView, firstItem.width / 2, firstItem.height / 2);
+ mousePress(listView, firstItem.width / 2, firstItem.height / 2);
+ verify(firstItem.swipe.leftItem.SwipeDelegate.pressed);
+ compare(leftClickedSpy.count, 0);
+ verify(!firstItem.pressed);
+
+ mouseRelease(listView, firstItem.width / 2, firstItem.height / 2);
+ verify(!firstItem.swipe.leftItem.SwipeDelegate.pressed);
+ compare(leftClickedSpy.count, 1);
+ verify(!firstItem.pressed);
+ leftClickedSpy = null;
tryCompare(firstItem.removeAnimation, "running", true);
// There was a bug where the resizeContent() would be called because the height
// of the control was changing due to the animation. contentItem would then
@@ -992,6 +1047,160 @@ TestCase {
control.destroy();
}
+ Component {
+ id: closeSwipeDelegateComponent
+
+ SwipeDelegate {
+ text: "SwipeDelegate"
+ width: 150
+
+ onClicked: close()
+
+ swipe.right: Item {
+ width: parent.width
+ height: parent.height
+ }
+ }
+ }
+
+ function test_close() {
+ var control = swipeDelegateComponent.createObject(testCase);
+ verify(control);
+
+ swipe(control, 0.0, -1.0);
+ compare(control.swipe.rightItem.visible, true);
+ // Should animate, so it shouldn't change right away.
+ compare(control.swipe.rightItem.x, 0);
+ tryCompare(control.swipe.rightItem, "x", control.background.x + control.background.width);
+
+ control.destroy();
+ }
+
+ Component {
+ id: multiActionSwipeDelegateComponent
+
+ SwipeDelegate {
+ text: "SwipeDelegate"
+ width: 150
+
+ swipe.right: Item {
+ objectName: "rightItemRoot"
+ width: parent.width
+ height: parent.height
+
+ property alias firstAction: firstAction
+ property alias secondAction: secondAction
+
+ property int firstClickCount: 0
+ property int secondClickCount: 0
+
+ RowLayout {
+ anchors.fill: parent
+ anchors.margins: 5
+
+ Rectangle {
+ id: firstAction
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ color: "tomato"
+
+ SwipeDelegate.onClicked: ++firstClickCount
+ }
+ Rectangle {
+ id: secondAction
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ color: "navajowhite"
+
+ SwipeDelegate.onClicked: ++secondClickCount
+ }
+ }
+ }
+ }
+ }
+
+ // Tests that it's possible to have multiple non-interactive items in one delegate
+ // (e.g. left/right/behind) that can each receive clicks.
+ function test_multipleClickableActions() {
+ var control = multiActionSwipeDelegateComponent.createObject(testCase);
+ verify(control);
+
+ swipe(control, 0.0, -1.0);
+ verify(control.swipe.rightItem);
+ tryCompare(control.swipe, "complete", true);
+
+ var firstClickedSpy = signalSpyComponent.createObject(control,
+ { target: control.swipe.rightItem.firstAction.SwipeDelegate, signalName: "clicked" });
+ verify(firstClickedSpy);
+ verify(firstClickedSpy.valid);
+
+ // Clicked within rightItem, but not within an item using the attached properties.
+ mousePress(control, 2, 2);
+ compare(control.swipe.rightItem.firstAction.SwipeDelegate.pressed, false);
+ compare(firstClickedSpy.count, 0);
+
+ mouseRelease(control, 2, 2);
+ compare(control.swipe.rightItem.firstAction.SwipeDelegate.pressed, false);
+ compare(firstClickedSpy.count, 0);
+
+ // Click within the first item.
+ mousePress(control.swipe.rightItem.firstAction, 0, 0);
+ compare(control.swipe.rightItem.firstAction.SwipeDelegate.pressed, true);
+ compare(firstClickedSpy.count, 0);
+
+ mouseRelease(control.swipe.rightItem.firstAction, 0, 0);
+ compare(control.swipe.rightItem.firstAction.SwipeDelegate.pressed, false);
+ compare(firstClickedSpy.count, 1);
+ compare(control.swipe.rightItem.firstClickCount, 1);
+
+ var secondClickedSpy = signalSpyComponent.createObject(control,
+ { target: control.swipe.rightItem.secondAction.SwipeDelegate, signalName: "clicked" });
+ verify(secondClickedSpy);
+ verify(secondClickedSpy.valid);
+
+ // Click within the second item.
+ mousePress(control.swipe.rightItem.secondAction, 0, 0);
+ compare(control.swipe.rightItem.secondAction.SwipeDelegate.pressed, true);
+ compare(secondClickedSpy.count, 0);
+
+ mouseRelease(control.swipe.rightItem.secondAction, 0, 0);
+ compare(control.swipe.rightItem.secondAction.SwipeDelegate.pressed, false);
+ compare(secondClickedSpy.count, 1);
+ compare(control.swipe.rightItem.secondClickCount, 1);
+
+ control.destroy();
+ }
+
+ // Pressing on a "side action" and then dragging should eventually
+ // cause the ListView to grab the mouse and start changing its contentY.
+ // When this happens, it will grab the mouse and hence we must clear
+ // that action's pressed state so that it doesn't stay pressed after releasing.
+ function test_dragSideAction() {
+ var listView = removableDelegatesComponent.createObject(testCase);
+ verify(listView);
+
+ var control = listView.itemAt(0, 0);
+ verify(control);
+
+ // Expose the side action.
+ swipe(control, 0.0, 1.0);
+ verify(control.swipe.leftItem);
+ tryCompare(control.swipe, "complete", true);
+
+ var pressedSpy = signalSpyComponent.createObject(control,
+ { target: control.swipe.leftItem.SwipeDelegate, signalName: "pressedChanged" });
+ verify(pressedSpy);
+ verify(pressedSpy.valid);
+
+ mouseDrag(listView, 20, 20, 0, listView.height);
+ compare(pressedSpy.count, 2);
+ verify(listView.contentY !== 0);
+
+ compare(control.swipe.leftItem.SwipeDelegate.pressed, false);
+
+ listView.destroy();
+ }
+
// When the width of a SwipeDelegate changes (as it does upon portrait => landscape
// rotation, for example), the positions of the contentItem and background items
// should be updated accordingly.
diff --git a/tests/auto/controls/data/tst_swipeview.qml b/tests/auto/controls/data/tst_swipeview.qml
index 3afcdf16..2d5f413a 100644
--- a/tests/auto/controls/data/tst_swipeview.qml
+++ b/tests/auto/controls/data/tst_swipeview.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
@@ -103,6 +103,16 @@ TestCase {
compare(control.currentItem.text, "2")
compare(currentItemChangedSpy.count, 3);
+ control.decrementCurrentIndex()
+ compare(control.currentIndex, 1)
+ compare(control.currentItem.text, "1")
+ compare(currentItemChangedSpy.count, 4);
+
+ control.incrementCurrentIndex()
+ compare(control.currentIndex, 2)
+ compare(control.currentItem.text, "2")
+ compare(currentItemChangedSpy.count, 5);
+
control.destroy()
}
@@ -404,6 +414,8 @@ TestCase {
property int index: SwipeView.index
property SwipeView view: SwipeView.view
property bool isCurrentItem: SwipeView.isCurrentItem
+ property bool isNextItem: SwipeView.isNextItem
+ property bool isPreviousItem: SwipeView.isPreviousItem
}
}
@@ -424,11 +436,15 @@ TestCase {
compare(control.itemAt(i).text, titles[i])
compare(control.itemAt(i).SwipeView.index, i)
compare(control.itemAt(i).SwipeView.isCurrentItem, i === 0)
+ compare(control.itemAt(i).SwipeView.isNextItem, i === 1)
+ compare(control.itemAt(i).SwipeView.isPreviousItem, false)
}
control.currentIndex = data.currentBefore
for (i = 0; i < control.count; ++i) {
compare(control.itemAt(i).SwipeView.isCurrentItem, i === data.currentBefore)
+ compare(control.itemAt(i).SwipeView.isNextItem, i === data.currentBefore + 1)
+ compare(control.itemAt(i).SwipeView.isPreviousItem, i === data.currentBefore - 1)
}
control.moveItem(data.from, data.to)
@@ -445,6 +461,8 @@ TestCase {
compare(control.itemAt(i).text, titles[i])
compare(control.itemAt(i).SwipeView.index, i);
compare(control.itemAt(i).SwipeView.isCurrentItem, i === data.currentAfter)
+ compare(control.itemAt(i).SwipeView.isNextItem, i === data.currentAfter + 1)
+ compare(control.itemAt(i).SwipeView.isPreviousItem, i === data.currentAfter - 1)
}
control.destroy()
@@ -489,12 +507,16 @@ TestCase {
compare(page.view, null);
compare(page.index, -1);
compare(page.isCurrentItem, false);
+ compare(page.isNextItem, false);
+ compare(page.isPreviousItem, false);
page.destroy();
page = pageAttached.createObject(null);
compare(page.view, null);
compare(page.index, -1);
compare(page.isCurrentItem, false);
+ compare(page.isNextItem, false);
+ compare(page.isPreviousItem, false);
control.insertItem(0, page);
compare(control.count, 1);
@@ -502,6 +524,8 @@ TestCase {
compare(page.view, control);
compare(page.index, 0);
compare(page.isCurrentItem, true);
+ compare(page.isNextItem, false);
+ compare(page.isPreviousItem, false);
control.removeItem(0);
compare(control.count, 0);
@@ -509,6 +533,8 @@ TestCase {
compare(page.view, null);
compare(page.index, -1);
compare(page.isCurrentItem, false);
+ compare(page.isNextItem, false);
+ compare(page.isPreviousItem, false);
control.destroy();
}
diff --git a/tests/auto/controls/data/tst_switch.qml b/tests/auto/controls/data/tst_switch.qml
index 93773e0d..f3843cf7 100644
--- a/tests/auto/controls/data/tst_switch.qml
+++ b/tests/auto/controls/data/tst_switch.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
diff --git a/tests/auto/controls/data/tst_switchdelegate.qml b/tests/auto/controls/data/tst_switchdelegate.qml
index 8bc0e4c3..4a5d711f 100644
--- a/tests/auto/controls/data/tst_switchdelegate.qml
+++ b/tests/auto/controls/data/tst_switchdelegate.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
diff --git a/tests/auto/controls/data/tst_tabbar.qml b/tests/auto/controls/data/tst_tabbar.qml
index 9268f765..da0181a1 100644
--- a/tests/auto/controls/data/tst_tabbar.qml
+++ b/tests/auto/controls/data/tst_tabbar.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
@@ -134,6 +134,16 @@ TestCase {
compare(control.currentItem.text, "2")
compare(control.currentItem.checked, true)
+ control.decrementCurrentIndex()
+ compare(control.currentIndex, 1)
+ compare(control.currentItem.text, "1")
+ compare(control.currentItem.checked, true)
+
+ control.incrementCurrentIndex()
+ compare(control.currentIndex, 2)
+ compare(control.currentItem.text, "2")
+ compare(control.currentItem.checked, true)
+
control.destroy()
}
diff --git a/tests/auto/controls/data/tst_tabbutton.qml b/tests/auto/controls/data/tst_tabbutton.qml
index 4ab9d955..77d22a48 100644
--- a/tests/auto/controls/data/tst_tabbutton.qml
+++ b/tests/auto/controls/data/tst_tabbutton.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
diff --git a/tests/auto/controls/data/tst_textarea.qml b/tests/auto/controls/data/tst_textarea.qml
index bda0b3e3..5d3e8d55 100644
--- a/tests/auto/controls/data/tst_textarea.qml
+++ b/tests/auto/controls/data/tst_textarea.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
@@ -199,6 +199,196 @@ TestCase {
testCase.TextArea.flickable = null
}
+ function test_hover_data() {
+ return [
+ { tag: "enabled", hoverEnabled: true },
+ { tag: "disabled", hoverEnabled: false },
+ ]
+ }
+
+ function test_hover(data) {
+ var control = textArea.createObject(testCase, {text: "TextArea", hoverEnabled: data.hoverEnabled})
+ verify(control)
+
+ compare(control.hovered, false)
+
+ mouseMove(control)
+ compare(control.hovered, data.hoverEnabled)
+
+ mouseMove(control, -1, -1)
+ compare(control.hovered, false)
+
+ control.destroy()
+ }
+
+ function test_pressedReleased_data() {
+ return [
+ {
+ tag: "pressed outside", x: -1, y: -1, button: Qt.LeftButton,
+ controlPressEvent: null,
+ controlReleaseEvent: null,
+ parentPressEvent: {
+ x: 0, y: 0, button: Qt.LeftButton, buttons: Qt.LeftButton, modifiers: Qt.NoModifier, wasHeld: false, isClick: false
+ },
+ parentReleaseEvent: {
+ x: 0, y: 0, button: Qt.LeftButton, buttons: Qt.NoButton, modifiers: Qt.NoModifier, wasHeld: false, isClick: false
+ },
+ },
+ {
+ tag: "left click", x: 0, y: 0, button: Qt.LeftButton,
+ controlPressEvent: {
+ x: 0, y: 0, button: Qt.LeftButton, buttons: Qt.LeftButton, modifiers: Qt.NoModifier, wasHeld: false, isClick: false
+ },
+ controlReleaseEvent: {
+ x: 0, y: 0, button: Qt.LeftButton, buttons: Qt.NoButton, modifiers: Qt.NoModifier, wasHeld: false, isClick: false
+ },
+ parentPressEvent: null,
+ parentReleaseEvent: null,
+ },
+ {
+ tag: "right click", x: 0, y: 0, button: Qt.RightButton,
+ controlPressEvent: {
+ x: 0, y: 0, button: Qt.RightButton, buttons: Qt.RightButton, modifiers: Qt.NoModifier, wasHeld: false, isClick: false
+ },
+ controlReleaseEvent: {
+ x: 0, y: 0, button: Qt.RightButton, buttons: Qt.NoButton, modifiers: Qt.NoModifier, wasHeld: false, isClick: false
+ },
+ parentPressEvent: null,
+ parentReleaseEvent: null,
+ },
+ ];
+ }
+
+ Component {
+ id: mouseAreaComponent
+ MouseArea {
+ anchors.fill: parent
+ }
+ }
+
+ function checkMouseEvent(event, expectedEvent) {
+ compare(event.x, expectedEvent.x)
+ compare(event.y, expectedEvent.y)
+ compare(event.button, expectedEvent.button)
+ compare(event.buttons, expectedEvent.buttons)
+ }
+
+ function test_pressedReleased(data) {
+ var mouseArea = mouseAreaComponent.createObject(testCase)
+ verify(mouseArea)
+ var control = textArea.createObject(mouseArea, {text: "TextArea"})
+ verify(control)
+
+ // Give enough room to check presses outside of the control and on the parent.
+ control.x = 1;
+ control.y = 1;
+
+ function checkControlPressEvent(event) {
+ checkMouseEvent(event, data.controlPressEvent)
+ }
+ function checkControlReleaseEvent(event) {
+ checkMouseEvent(event, data.controlReleaseEvent)
+ }
+ function checkParentPressEvent(event) {
+ checkMouseEvent(event, data.parentPressEvent)
+ }
+ function checkParentReleaseEvent(event) {
+ checkMouseEvent(event, data.parentReleaseEvent)
+ }
+
+ // Can't use signalArguments, because the event won't live that long.
+ if (data.controlPressEvent)
+ control.onPressed.connect(checkControlPressEvent)
+ if (data.controlReleaseEvent)
+ control.onReleased.connect(checkControlReleaseEvent)
+ if (data.parentPressEvent)
+ control.onPressed.connect(checkParentPressEvent)
+ if (data.parentReleaseEvent)
+ control.onReleased.connect(checkParentReleaseEvent)
+
+ var controlPressedSpy = signalSpy.createObject(control, { target: control, signalName: "pressed" })
+ verify(controlPressedSpy.valid)
+ var controlReleasedSpy = signalSpy.createObject(control, { target: control, signalName: "released" })
+ verify(controlReleasedSpy.valid)
+ var parentPressedSpy = signalSpy.createObject(mouseArea, { target: mouseArea, signalName: "pressed" })
+ verify(parentPressedSpy.valid)
+ var parentReleasedSpy = signalSpy.createObject(mouseArea, { target: mouseArea, signalName: "released" })
+ verify(parentReleasedSpy.valid)
+
+ mousePress(control, data.x, data.y, data.button)
+ compare(controlPressedSpy.count, data.controlPressEvent ? 1 : 0)
+ compare(parentPressedSpy.count, data.parentPressEvent ? 1 : 0)
+ mouseRelease(control, data.x, data.y, data.button)
+ compare(controlReleasedSpy.count, data.controlReleaseEvent ? 1 : 0)
+ compare(parentReleasedSpy.count, data.parentReleaseEvent ? 1 : 0)
+
+ mouseArea.destroy()
+ }
+
+ Component {
+ id: ignoreTextArea
+
+ TextArea {
+ property bool ignorePress: false
+ property bool ignoreRelease: false
+
+ onPressed: if (ignorePress) event.accepted = false
+ onReleased: if (ignoreRelease) event.accepted = false
+ }
+ }
+
+ function checkEventAccepted(event) {
+ compare(event.accepted, true)
+ }
+
+ function checkEventIgnored(event) {
+ compare(event.accepted, false)
+ }
+
+ function test_ignorePressRelease() {
+ var mouseArea = mouseAreaComponent.createObject(testCase)
+ verify(mouseArea)
+ var control = ignoreTextArea.createObject(mouseArea)
+ verify(control)
+
+ var controlPressedSpy = signalSpy.createObject(control, { target: control, signalName: "pressed" })
+ verify(controlPressedSpy.valid)
+ var controlReleasedSpy = signalSpy.createObject(control, { target: control, signalName: "released" })
+ verify(controlReleasedSpy.valid)
+ var parentPressedSpy = signalSpy.createObject(mouseArea, { target: mouseArea, signalName: "pressed" })
+ verify(parentPressedSpy.valid)
+ var parentReleasedSpy = signalSpy.createObject(mouseArea, { target: mouseArea, signalName: "released" })
+ verify(parentReleasedSpy.valid)
+
+ // Ignore only press events.
+ control.onPressed.connect(checkEventIgnored)
+ control.ignorePress = true
+ mousePress(control, 0, 0, data.button)
+ // The control will still get the signal, it just won't accept the event.
+ compare(controlPressedSpy.count, 1)
+ compare(parentPressedSpy.count, 1)
+ mouseRelease(control, 0, 0, data.button)
+ compare(controlReleasedSpy.count, 0)
+ compare(parentReleasedSpy.count, 1)
+ control.onPressed.disconnect(checkEventIgnored)
+
+ // Ignore only release events.
+ control.onPressed.connect(checkEventAccepted)
+ control.onReleased.connect(checkEventIgnored)
+ control.ignorePress = false
+ control.ignoreRelease = true
+ mousePress(control, 0, 0, data.button)
+ compare(controlPressedSpy.count, 2)
+ compare(parentPressedSpy.count, 1)
+ mouseRelease(control, 0, 0, data.button)
+ compare(controlReleasedSpy.count, 1)
+ compare(parentReleasedSpy.count, 1)
+ control.onPressed.disconnect(checkEventAccepted)
+ control.onReleased.disconnect(checkEventIgnored)
+
+ mouseArea.destroy()
+ }
+
function test_multiClick() {
var control = textArea.createObject(testCase, {text: "Qt Quick Controls 2 TextArea", selectByMouse: true})
verify(control)
diff --git a/tests/auto/controls/data/tst_textfield.qml b/tests/auto/controls/data/tst_textfield.qml
index 959662ee..5dc93287 100644
--- a/tests/auto/controls/data/tst_textfield.qml
+++ b/tests/auto/controls/data/tst_textfield.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
@@ -164,6 +164,196 @@ TestCase {
control.destroy()
}
+ function test_hover_data() {
+ return [
+ { tag: "enabled", hoverEnabled: true },
+ { tag: "disabled", hoverEnabled: false },
+ ]
+ }
+
+ function test_hover(data) {
+ var control = textField.createObject(testCase, {hoverEnabled: data.hoverEnabled})
+ verify(control)
+
+ compare(control.hovered, false)
+
+ mouseMove(control)
+ compare(control.hovered, data.hoverEnabled)
+
+ mouseMove(control, -1, -1)
+ compare(control.hovered, false)
+
+ control.destroy()
+ }
+
+ function test_pressedReleased_data() {
+ return [
+ {
+ tag: "pressed outside", x: -1, y: -1, button: Qt.LeftButton,
+ controlPressEvent: null,
+ controlReleaseEvent: null,
+ parentPressEvent: {
+ x: 0, y: 0, button: Qt.LeftButton, buttons: Qt.LeftButton, modifiers: Qt.NoModifier, wasHeld: false, isClick: false
+ },
+ parentReleaseEvent: {
+ x: 0, y: 0, button: Qt.LeftButton, buttons: Qt.NoButton, modifiers: Qt.NoModifier, wasHeld: false, isClick: false
+ },
+ },
+ {
+ tag: "left click", x: 0, y: 0, button: Qt.LeftButton,
+ controlPressEvent: {
+ x: 0, y: 0, button: Qt.LeftButton, buttons: Qt.LeftButton, modifiers: Qt.NoModifier, wasHeld: false, isClick: false
+ },
+ controlReleaseEvent: {
+ x: 0, y: 0, button: Qt.LeftButton, buttons: Qt.NoButton, modifiers: Qt.NoModifier, wasHeld: false, isClick: false
+ },
+ parentPressEvent: null,
+ parentReleaseEvent: null,
+ },
+ {
+ tag: "right click", x: 0, y: 0, button: Qt.RightButton,
+ controlPressEvent: {
+ x: 0, y: 0, button: Qt.RightButton, buttons: Qt.RightButton, modifiers: Qt.NoModifier, wasHeld: false, isClick: false
+ },
+ controlReleaseEvent: {
+ x: 0, y: 0, button: Qt.RightButton, buttons: Qt.NoButton, modifiers: Qt.NoModifier, wasHeld: false, isClick: false
+ },
+ parentPressEvent: null,
+ parentReleaseEvent: null,
+ },
+ ];
+ }
+
+ Component {
+ id: mouseAreaComponent
+ MouseArea {
+ anchors.fill: parent
+ }
+ }
+
+ function checkMouseEvent(event, expectedEvent) {
+ compare(event.x, expectedEvent.x)
+ compare(event.y, expectedEvent.y)
+ compare(event.button, expectedEvent.button)
+ compare(event.buttons, expectedEvent.buttons)
+ }
+
+ function test_pressedReleased(data) {
+ var mouseArea = mouseAreaComponent.createObject(testCase)
+ verify(mouseArea)
+ var control = textField.createObject(mouseArea)
+ verify(control)
+
+ // Give enough room to check presses outside of the control and on the parent.
+ control.x = 1;
+ control.y = 1;
+
+ function checkControlPressEvent(event) {
+ checkMouseEvent(event, data.controlPressEvent)
+ }
+ function checkControlReleaseEvent(event) {
+ checkMouseEvent(event, data.controlReleaseEvent)
+ }
+ function checkParentPressEvent(event) {
+ checkMouseEvent(event, data.parentPressEvent)
+ }
+ function checkParentReleaseEvent(event) {
+ checkMouseEvent(event, data.parentReleaseEvent)
+ }
+
+ // Can't use signalArguments, because the event won't live that long.
+ if (data.controlPressEvent)
+ control.onPressed.connect(checkControlPressEvent)
+ if (data.controlReleaseEvent)
+ control.onReleased.connect(checkControlReleaseEvent)
+ if (data.parentPressEvent)
+ control.onPressed.connect(checkParentPressEvent)
+ if (data.parentReleaseEvent)
+ control.onReleased.connect(checkParentReleaseEvent)
+
+ var controlPressedSpy = signalSpy.createObject(control, { target: control, signalName: "pressed" })
+ verify(controlPressedSpy.valid)
+ var controlReleasedSpy = signalSpy.createObject(control, { target: control, signalName: "released" })
+ verify(controlReleasedSpy.valid)
+ var parentPressedSpy = signalSpy.createObject(mouseArea, { target: mouseArea, signalName: "pressed" })
+ verify(parentPressedSpy.valid)
+ var parentReleasedSpy = signalSpy.createObject(mouseArea, { target: mouseArea, signalName: "released" })
+ verify(parentReleasedSpy.valid)
+
+ mousePress(control, data.x, data.y, data.button)
+ compare(controlPressedSpy.count, data.controlPressEvent ? 1 : 0)
+ compare(parentPressedSpy.count, data.parentPressEvent ? 1 : 0)
+ mouseRelease(control, data.x, data.y, data.button)
+ compare(controlReleasedSpy.count, data.controlReleaseEvent ? 1 : 0)
+ compare(parentReleasedSpy.count, data.parentReleaseEvent ? 1 : 0)
+
+ mouseArea.destroy()
+ }
+
+ Component {
+ id: ignoreTextField
+
+ TextField {
+ property bool ignorePress: false
+ property bool ignoreRelease: false
+
+ onPressed: if (ignorePress) event.accepted = false
+ onReleased: if (ignoreRelease) event.accepted = false
+ }
+ }
+
+ function checkEventAccepted(event) {
+ compare(event.accepted, true)
+ }
+
+ function checkEventIgnored(event) {
+ compare(event.accepted, false)
+ }
+
+ function test_ignorePressRelease() {
+ var mouseArea = mouseAreaComponent.createObject(testCase)
+ verify(mouseArea)
+ var control = ignoreTextField.createObject(mouseArea)
+ verify(control)
+
+ var controlPressedSpy = signalSpy.createObject(control, { target: control, signalName: "pressed" })
+ verify(controlPressedSpy.valid)
+ var controlReleasedSpy = signalSpy.createObject(control, { target: control, signalName: "released" })
+ verify(controlReleasedSpy.valid)
+ var parentPressedSpy = signalSpy.createObject(mouseArea, { target: mouseArea, signalName: "pressed" })
+ verify(parentPressedSpy.valid)
+ var parentReleasedSpy = signalSpy.createObject(mouseArea, { target: mouseArea, signalName: "released" })
+ verify(parentReleasedSpy.valid)
+
+ // Ignore only press events.
+ control.onPressed.connect(checkEventIgnored)
+ control.ignorePress = true
+ mousePress(control, 0, 0, data.button)
+ // The control will still get the signal, it just won't accept the event.
+ compare(controlPressedSpy.count, 1)
+ compare(parentPressedSpy.count, 1)
+ mouseRelease(control, 0, 0, data.button)
+ compare(controlReleasedSpy.count, 0)
+ compare(parentReleasedSpy.count, 1)
+ control.onPressed.disconnect(checkEventIgnored)
+
+ // Ignore only release events.
+ control.onPressed.connect(checkEventAccepted)
+ control.onReleased.connect(checkEventIgnored)
+ control.ignorePress = false
+ control.ignoreRelease = true
+ mousePress(control, 0, 0, data.button)
+ compare(controlPressedSpy.count, 2)
+ compare(parentPressedSpy.count, 1)
+ mouseRelease(control, 0, 0, data.button)
+ compare(controlReleasedSpy.count, 1)
+ compare(parentReleasedSpy.count, 1)
+ control.onPressed.disconnect(checkEventAccepted)
+ control.onReleased.disconnect(checkEventIgnored)
+
+ mouseArea.destroy()
+ }
+
function test_multiClick() {
var control = textField.createObject(testCase, {text: "Qt Quick Controls 2 TextArea", selectByMouse: true})
verify(control)
diff --git a/tests/auto/controls/data/tst_toolbar.qml b/tests/auto/controls/data/tst_toolbar.qml
index b68f26e6..cc64383e 100644
--- a/tests/auto/controls/data/tst_toolbar.qml
+++ b/tests/auto/controls/data/tst_toolbar.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
diff --git a/tests/auto/controls/data/tst_toolbutton.qml b/tests/auto/controls/data/tst_toolbutton.qml
index 73431ca6..a59cff07 100644
--- a/tests/auto/controls/data/tst_toolbutton.qml
+++ b/tests/auto/controls/data/tst_toolbutton.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
diff --git a/tests/auto/controls/data/tst_toolseparator.qml b/tests/auto/controls/data/tst_toolseparator.qml
new file mode 100644
index 00000000..47eb933f
--- /dev/null
+++ b/tests/auto/controls/data/tst_toolseparator.qml
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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.8
+import QtTest 1.0
+import QtQuick.Controls 2.1
+
+TestCase {
+ id: testCase
+ width: 400
+ height: 400
+ visible: true
+ name: "ToolSeparator"
+
+ Component {
+ id: toolSeparator
+ ToolSeparator {}
+ }
+
+ function test_size() {
+ var control = toolSeparator.createObject(testCase);
+ verify(control);
+ verify(control.width > 1);
+ verify(control.height > 1);
+
+ control.destroy();
+ }
+
+ Component {
+ id: signalSpyComponent
+ SignalSpy {}
+ }
+
+ function test_orientation() {
+ var control = toolSeparator.createObject(testCase);
+ verify(control);
+ compare(control.horizontal, false);
+ compare(control.vertical, true);
+
+ var orientationSpy = signalSpyComponent.createObject(control, { target: control, signalName: "orientationChanged" });
+
+ var originalWidth = control.width;
+ var originalHeight = control.height;
+ control.orientation = Qt.Horizontal;
+ compare(control.orientation, Qt.Horizontal);
+ compare(control.width, originalHeight);
+ compare(control.height, originalWidth);
+ compare(control.horizontal, true);
+ compare(control.vertical, false);
+ compare(orientationSpy.count, 1);
+
+ control.orientation = Qt.Vertical;
+ compare(control.orientation, Qt.Vertical);
+ compare(control.width, originalWidth);
+ compare(control.height, originalHeight);
+ compare(control.horizontal, false);
+ compare(control.vertical, true);
+ compare(orientationSpy.count, 2);
+
+ control.destroy();
+ }
+}
diff --git a/tests/auto/controls/data/tst_tooltip.qml b/tests/auto/controls/data/tst_tooltip.qml
index c78a7770..d9c95dbf 100644
--- a/tests/auto/controls/data/tst_tooltip.qml
+++ b/tests/auto/controls/data/tst_tooltip.qml
@@ -40,7 +40,7 @@
import QtQuick 2.4
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
diff --git a/tests/auto/controls/data/tst_tumbler.qml b/tests/auto/controls/data/tst_tumbler.qml
index 2e0e3295..b3230ca4 100644
--- a/tests/auto/controls/data/tst_tumbler.qml
+++ b/tests/auto/controls/data/tst_tumbler.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.0
+import QtQuick.Controls 2.1
TestCase {
id: testCase
@@ -58,6 +58,16 @@ TestCase {
readonly property real implicitTumblerHeight: 200
readonly property real defaultImplicitDelegateHeight: implicitTumblerHeight / 3
readonly property real defaultListViewTumblerOffset: -defaultImplicitDelegateHeight
+ readonly property real tumblerDelegateHeight: tumbler ? tumbler.availableHeight / tumbler.visibleItemCount : 0
+ property Item tumblerView: null
+
+ Component {
+ id: tumblerComponent
+
+ Tumbler {
+ visibleItemCount: 3
+ }
+ }
Component {
id: itemComponent
@@ -85,6 +95,16 @@ TestCase {
wait(0)
}
+ function createTumbler(args) {
+ if (args === undefined)
+ tumbler = tumblerComponent.createObject(cleanupItem);
+ else
+ tumbler = tumblerComponent.createObject(cleanupItem, args);
+ verify(tumbler, "Tumbler: failed to create an instance");
+ tumblerView = findView(tumbler);
+ verify(tumblerView);
+ }
+
function tumblerXCenter() {
return tumbler.leftPadding + tumbler.width / 2;
}
@@ -95,26 +115,46 @@ TestCase {
// visualItemIndex is from 0 to the amount of visible items.
function itemCenterPos(visualItemIndex) {
- var halfDelegateHeight = tumbler.contentItem.delegateHeight / 2;
+ var halfDelegateHeight = tumblerDelegateHeight / 2;
var yCenter = tumbler.y + tumbler.topPadding + halfDelegateHeight
- + (tumbler.contentItem.delegateHeight * visualItemIndex);
+ + (tumblerDelegateHeight * visualItemIndex);
return Qt.point(tumblerXCenter(), yCenter);
}
function checkItemSizes() {
- var contentChildren = tumbler.contentItem.hasOwnProperty("contentItem")
- ? tumbler.contentItem.contentItem.children : tumbler.contentItem.children;
+ var contentChildren = tumbler.wrap ? tumblerView.children : tumblerView.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);
+ compare(contentChildren[i].width, tumbler.availableWidth);
+ compare(contentChildren[i].height, tumblerDelegateHeight);
}
}
- Component {
- id: tumblerComponent
+ function findView(parent) {
+ for (var i = 0; i < parent.children.length; ++i) {
+ var child = parent.children[i];
+ if (child.hasOwnProperty("currentIndex")) {
+ return child;
+ }
+
+ return findView(child);
+ }
+
+ return null;
+ }
+
+ property Component noAttachedPropertiesDelegate: Text {
+ text: modelData
+ }
+
+ function test_wrapWithoutAttachedProperties() {
+ createTumbler();
+ verify(tumbler.wrap);
- Tumbler {}
+ tumbler.delegate = noAttachedPropertiesDelegate;
+ // Shouldn't assert.
+ tumbler.wrap = false;
+ verify(findView(tumbler));
}
// TODO: test that currentIndex is maintained between contentItem changes...
@@ -122,8 +162,7 @@ TestCase {
// }
function test_currentIndex() {
- tumbler = tumblerComponent.createObject(cleanupItem);
- verify(tumbler);
+ createTumbler();
compare(tumbler.contentItem.parent, tumbler);
tumbler.model = 5;
@@ -133,75 +172,193 @@ TestCase {
// 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);
+ mouseDrag(tumbler, pos.x, pos.y, 0, tumbler.height / 3, Qt.LeftButton, Qt.NoModifier, 200);
+ tryCompare(tumblerView, "offset", 1);
+ compare(tumbler.currentIndex, 4);
+ compare(tumblerView.currentIndex, 4);
// Set it manually.
tumbler.currentIndex = 2;
tryCompare(tumbler, "currentIndex", 2);
- compare(tumbler.contentItem.currentIndex, 2);
+ compare(tumblerView.currentIndex, 2);
- // PathView has 0 as its currentIndex in this case for some reason.
tumbler.model = null;
- tryCompare(tumbler, "currentIndex", 0);
+ tryCompare(tumbler, "currentIndex", -1);
+ // PathView will only use 0 as the currentIndex when there are no items.
+ compare(tumblerView.currentIndex, 0);
tumbler.model = ["A", "B", "C"];
tryCompare(tumbler, "currentIndex", 0);
+
+ // Setting a negative current index should have no effect, because the model isn't empty.
+ tumbler.currentIndex = -1;
+ compare(tumbler.currentIndex, 0);
+
+ tumbler.model = 1;
+ compare(tumbler.currentIndex, 0);
+
+ tumbler.model = 5;
+ compare(tumbler.count, 5);
+ tumblerView = findView(tumbler);
+ tryCompare(tumblerView, "count", 5);
+ tumbler.currentIndex = 4;
+ compare(tumbler.currentIndex, 4);
+ compare(tumblerView.currentIndex, 4);
+
+ --tumbler.model;
+ compare(tumbler.count, 4);
+ compare(tumblerView.count, 4);
+ // Removing an item from an integer-based model will cause views to reset their currentIndex to 0.
+ compare(tumbler.currentIndex, 0);
+ compare(tumblerView.currentIndex, 0);
+
+ tumbler.model = 0;
+ compare(tumbler.currentIndex, -1);
}
- function test_keyboardNavigation() {
- tumbler = tumblerComponent.createObject(cleanupItem);
+ Component {
+ id: currentIndexTumbler
+
+ Tumbler {
+ model: 5
+ currentIndex: 2
+ visibleItemCount: 3
+ }
+ }
+
+ Component {
+ id: currentIndexTumblerNoWrap
+
+ Tumbler {
+ model: 5
+ currentIndex: 2
+ wrap: false
+ visibleItemCount: 3
+ }
+ }
+
+ Component {
+ id: currentIndexTumblerNoWrapReversedOrder
+
+ Tumbler {
+ model: 5
+ wrap: false
+ currentIndex: 2
+ visibleItemCount: 3
+ }
+ }
+
+ Component {
+ id: negativeCurrentIndexTumblerNoWrap
+
+ Tumbler {
+ model: 5
+ wrap: false
+ currentIndex: -1
+ visibleItemCount: 3
+ }
+ }
+
+ Component {
+ id: currentIndexTooLargeTumbler
+
+ Tumbler {
+ objectName: "currentIndexTooLargeTumbler"
+ model: 10
+ currentIndex: 10
+ }
+ }
+
+
+ function test_currentIndexAtCreation_data() {
+ return [
+ { tag: "wrap: implicit, expected currentIndex: 2", currentIndex: 2, wrap: true, component: currentIndexTumbler },
+ { tag: "wrap: false, expected currentIndex: 2", currentIndex: 2, wrap: false, component: currentIndexTumblerNoWrap },
+ // Order of property assignments shouldn't matter
+ { tag: "wrap: false, expected currentIndex: 2, reversed property assignment order",
+ currentIndex: 2, wrap: false, component: currentIndexTumblerNoWrapReversedOrder },
+ { tag: "wrap: false, expected currentIndex: 0", currentIndex: 0, wrap: false, component: negativeCurrentIndexTumblerNoWrap },
+ { tag: "wrap: implicit, expected currentIndex: 0", currentIndex: 0, wrap: true, component: currentIndexTooLargeTumbler }
+ ]
+ }
+
+ function test_currentIndexAtCreation(data) {
+ // Test setting currentIndex at creation time
+ tumbler = data.component.createObject(cleanupItem);
verify(tumbler);
+ // A "statically declared" currentIndex will be pending until the count has changed,
+ // which happens when the model is set, which happens on the TumblerView's next polish.
+ tryCompare(tumbler, "currentIndex", data.currentIndex);
+
+ tumblerView = findView(tumbler);
+ // TODO: replace once QTBUG-19708 is fixed.
+ for (var delay = 1000; delay >= 0; delay -= 50) {
+ if (tumblerView.currentItem)
+ break;
+ wait(50);
+ }
+ verify(tumblerView.currentItem);
+ compare(tumblerView.currentIndex, data.currentIndex);
+ compare(tumblerView.currentItem.text, data.currentIndex.toString());
+
+ var fuzz = 1;
+ if (data.wrap) {
+ fuzzyCompare(tumblerView.offset, data.currentIndex > 0 ? tumblerView.count - data.currentIndex : 0, fuzz);
+ } else {
+ fuzzyCompare(tumblerView.contentY, tumblerDelegateHeight * data.currentIndex - tumblerView.preferredHighlightBegin, fuzz);
+ }
+ }
+
+ function test_keyboardNavigation() {
+ createTumbler();
tumbler.model = 5;
tumbler.forceActiveFocus();
- tumbler.contentItem.highlightMoveDuration = 0;
+ tumblerView.highlightMoveDuration = 0;
// Navigate upwards through entire wheel.
for (var j = 0; j < tumbler.count - 1; ++j) {
keyClick(Qt.Key_Up, Qt.NoModifier);
- tryCompare(tumbler.contentItem, "offset", j + 1);
+ tryCompare(tumblerView, "offset", j + 1);
compare(tumbler.currentIndex, tumbler.count - 1 - j);
}
keyClick(Qt.Key_Up, Qt.NoModifier);
- tryCompare(tumbler.contentItem, "offset", 0);
+ tryCompare(tumblerView, "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);
- tryCompare(tumbler.contentItem, "offset", tumbler.count - 1 - j);
+ tryCompare(tumblerView, "offset", tumbler.count - 1 - j);
compare(tumbler.currentIndex, j + 1);
}
keyClick(Qt.Key_Down, Qt.NoModifier);
- tryCompare(tumbler.contentItem, "offset", 0);
+ tryCompare(tumblerView, "offset", 0);
compare(tumbler.currentIndex, 0);
}
function test_itemsCorrectlyPositioned() {
- tumbler = tumblerComponent.createObject(cleanupItem);
- verify(tumbler);
+ createTumbler();
tumbler.model = 4;
tumbler.height = 120;
- compare(tumbler.contentItem.delegateHeight, 40);
+ compare(tumblerDelegateHeight, 40);
checkItemSizes();
- wait(tumbler.contentItem.highlightMoveDuration);
+ wait(tumblerView.highlightMoveDuration);
var firstItemCenterPos = itemCenterPos(1);
- var firstItem = tumbler.contentItem.itemAt(firstItemCenterPos.x, firstItemCenterPos.y);
+ var firstItem = tumblerView.itemAt(firstItemCenterPos.x, firstItemCenterPos.y);
var actualPos = cleanupItem.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);
+ tryCompare(tumblerView, "offset", 3.0);
firstItemCenterPos = itemCenterPos(0);
- firstItem = tumbler.contentItem.itemAt(firstItemCenterPos.x, firstItemCenterPos.y);
+ firstItem = tumblerView.itemAt(firstItemCenterPos.x, firstItemCenterPos.y);
verify(firstItem);
// Test QTBUG-40298.
actualPos = cleanupItem.mapFromItem(firstItem, 0, 0);
@@ -209,12 +366,12 @@ TestCase {
compare(actualPos.y, tumbler.topPadding);
var secondItemCenterPos = itemCenterPos(1);
- var secondItem = tumbler.contentItem.itemAt(secondItemCenterPos.x, secondItemCenterPos.y);
+ var secondItem = tumblerView.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);
+ var thirdItem = tumblerView.itemAt(thirdItemCenterPos.x, thirdItemCenterPos.y);
verify(thirdItem);
verify(firstItem.y < thirdItem.y);
verify(secondItem.y < thirdItem.y);
@@ -241,18 +398,18 @@ TestCase {
tumbler = component.createObject(cleanupItem);
// Should not be any warnings.
- compare(tumbler.dayTumbler.currentIndex, 0);
+ tryCompare(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);
+ verify(findView(tumbler.dayTumbler).children.length >= tumbler.dayTumbler.visibleItemCount);
+ verify(findView(tumbler.monthTumbler).children.length >= tumbler.monthTumbler.visibleItemCount);
// TODO: do this properly somehow
wait(100);
- verify(tumbler.yearTumbler.contentItem.children.length >= tumbler.yearTumbler.visibleItemCount);
+ verify(findView(tumbler.yearTumbler).children.length >= tumbler.yearTumbler.visibleItemCount);
// March.
tumbler.monthTumbler.currentIndex = 2;
@@ -361,27 +518,106 @@ TestCase {
}
function test_displacement(data) {
- tumbler = tumblerComponent.createObject(cleanupItem);
- verify(tumbler);
+ createTumbler();
// TODO: test setting these in the opposite order (delegate after model
// doesn't seem to cause a change in delegates in PathView)
+ tumbler.wrap = true;
tumbler.delegate = displacementDelegate;
tumbler.model = data.count;
compare(tumbler.count, data.count);
- var delegate = findChild(tumbler.contentItem, "delegate" + data.index);
+ var delegate = findChild(tumblerView, "delegate" + data.index);
verify(delegate);
- tumbler.contentItem.offset = data.offset;
+ tumblerView.offset = data.offset;
compare(delegate.displacement, data.expectedDisplacement);
// test displacement after adding and removing items
}
+ function test_wrap() {
+ createTumbler();
+
+ tumbler.model = 5;
+ compare(tumbler.count, 5);
+
+ tumbler.currentIndex = 2;
+ compare(tumblerView.currentIndex, 2);
+
+ tumbler.wrap = false;
+ tumblerView = findView(tumbler);
+ compare(tumbler.count, 5);
+ compare(tumbler.currentIndex, 2);
+ // Tumbler's count hasn't changed (the model hasn't changed),
+ // but the new view needs time to instantiate its items.
+ tryCompare(tumblerView, "count", 5);
+ compare(tumblerView.currentIndex, 2);
+ }
+
+ Component {
+ id: twoItemTumbler
+
+ Tumbler {
+ model: 2
+ }
+ }
+
+ Component {
+ id: tenItemTumbler
+
+ Tumbler {
+ model: 10
+ }
+ }
+
+ function test_countWrap() {
+ tumbler = tumblerComponent.createObject(cleanupItem);
+ verify(tumbler);
+
+ // Check that a count that is less than visibleItemCount results in wrap being set to false.
+ verify(2 < tumbler.visibleItemCount);
+ tumbler.model = 2;
+ compare(tumbler.count, 2);
+ compare(tumbler.wrap, false);
+ }
+
+ function test_explicitlyNonwrapping() {
+ // Check that explicitly setting wrap to false works even when it was implicitly false.
+ var explicitlyNonWrapping = twoItemTumbler.createObject(cleanupItem);
+ verify(explicitlyNonWrapping);
+ tryCompare(explicitlyNonWrapping, "wrap", false);
+
+ explicitlyNonWrapping.wrap = false;
+ // wrap shouldn't be set to true now that there are more items than there are visible ones.
+ verify(10 > explicitlyNonWrapping.visibleItemCount);
+ explicitlyNonWrapping.model = 10;
+ compare(explicitlyNonWrapping.wrap, false);
+
+ // Test resetting wrap back to the default behavior.
+ explicitlyNonWrapping.wrap = undefined;
+ compare(explicitlyNonWrapping.wrap, true);
+ }
+
+ function test_explicitlyWrapping() {
+ // Check that explicitly setting wrap to true works even when it was implicitly true.
+ var explicitlyWrapping = tenItemTumbler.createObject(cleanupItem);
+ verify(explicitlyWrapping);
+ compare(explicitlyWrapping.wrap, true);
+
+ explicitlyWrapping.wrap = true;
+ // wrap shouldn't be set to false now that there are more items than there are visible ones.
+ explicitlyWrapping.model = 2;
+ compare(explicitlyWrapping.wrap, true);
+
+ // Test resetting wrap back to the default behavior.
+ explicitlyWrapping.wrap = undefined;
+ compare(explicitlyWrapping.wrap, false);
+ }
+
Component {
- id: listViewTumblerComponent
- //! [contentItem]
+ id: customListViewTumblerComponent
+
Tumbler {
id: listViewTumbler
@@ -397,7 +633,95 @@ TestCase {
clip: true
}
}
- //! [contentItem]
+ }
+
+ Component {
+ id: customPathViewTumblerComponent
+
+ Tumbler {
+ id: pathViewTumbler
+
+ contentItem: PathView {
+ id: pathView
+ model: pathViewTumbler.model
+ delegate: pathViewTumbler.delegate
+ clip: true
+ pathItemCount: pathViewTumbler.visibleItemCount + 1
+ preferredHighlightBegin: 0.5
+ preferredHighlightEnd: 0.5
+ dragMargin: width / 2
+
+ path: Path {
+ startX: pathView.width / 2
+ startY: -pathView.delegateHeight / 2
+ PathLine {
+ x: pathView.width / 2
+ y: pathView.pathItemCount * pathView.delegateHeight - pathView.delegateHeight / 2
+ }
+ }
+
+ property real delegateHeight: pathViewTumbler.availableHeight / pathViewTumbler.visibleItemCount
+ }
+ }
+ }
+
+ function test_customContentItemAtConstruction_data() {
+ return [
+ { tag: "ListView", component: customListViewTumblerComponent },
+ { tag: "PathView", component: customPathViewTumblerComponent }
+ ];
+ }
+
+ function test_customContentItemAtConstruction(data) {
+ var tumbler = data.component.createObject(cleanupItem);
+ // Shouldn't assert.
+
+ tumbler.model = 5;
+ compare(tumbler.count, 5);
+
+ tumbler.currentIndex = 2;
+ var tumblerView = findView(tumbler);
+ compare(tumblerView.currentIndex, 2);
+
+ tumblerView.incrementCurrentIndex();
+ compare(tumblerView.currentIndex, 3);
+ compare(tumbler.currentIndex, 3);
+
+ // Shouldn't have any affect.
+ tumbler.wrap = false;
+ compare(tumbler.count, 5);
+ compare(tumblerView.currentIndex, 3);
+ compare(tumbler.currentIndex, 3);
+ }
+
+ function test_customContentItemAfterConstruction_data() {
+ return [
+ { tag: "ListView", componentPath: "TumblerListView.qml" },
+ { tag: "PathView", componentPath: "TumblerPathView.qml" }
+ ];
+ }
+
+ function test_customContentItemAfterConstruction(data) {
+ createTumbler();
+
+ tumbler.model = 5;
+ compare(tumbler.count, 5);
+
+ tumbler.currentIndex = 2;
+ compare(tumblerView.currentIndex, 2);
+
+ var contentItemComponent = Qt.createComponent(data.componentPath);
+ compare(contentItemComponent.status, Component.Ready);
+
+ var customContentItem = contentItemComponent.createObject(tumbler);
+ tumbler.contentItem = customContentItem;
+ compare(tumbler.count, 5);
+ tumblerView = findView(tumbler);
+ compare(tumblerView.currentIndex, 2);
+
+ tumblerView.incrementCurrentIndex();
+ compare(tumblerView.currentIndex, 3);
+ compare(tumbler.currentIndex, 3);
}
function test_displacementListView_data() {
@@ -438,20 +762,18 @@ TestCase {
}
function test_displacementListView(data) {
- // Sanity check that they're aren't any children at this stage.
- tryCompare(cleanupItem.children, "length", 0);
-
- tumbler = listViewTumblerComponent.createObject(cleanupItem);
- verify(tumbler);
+ createTumbler();
+ tumbler.wrap = false;
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);
+ tumblerView = findView(tumbler);
+ compare(tumblerView.contentY, -defaultImplicitDelegateHeight);
var delegateCount = 0;
- var listView = tumbler.contentItem;
- var listViewContentItem = tumbler.contentItem.contentItem;
+ var listView = tumblerView;
+ var listViewContentItem = tumblerView.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
@@ -511,16 +833,17 @@ TestCase {
}
function test_listViewFlickAboveBounds(data) {
- tumbler = listViewTumblerComponent.createObject(cleanupItem);
- verify(tumbler);
+ createTumbler();
+ tumbler.wrap = false;
tumbler.delegate = displacementDelegate;
tumbler.model = data.model;
+ tumblerView = findView(tumbler);
mousePress(tumbler, tumblerXCenter(), tumblerYCenter());
// Ensure it's stationary.
- var listView = tumbler.contentItem;
+ var listView = tumblerView;
compare(listView.contentY, defaultListViewTumblerOffset);
// We could just move up until the contentY changed, but this is safer.
@@ -577,8 +900,7 @@ TestCase {
}
function test_visibleItemCount(data) {
- tumbler = tumblerComponent.createObject(cleanupItem);
- verify(tumbler);
+ createTumbler();
tumbler.delegate = objectNameDelegate;
tumbler.visibleItemCount = data.visibleItemCount;
@@ -588,9 +910,9 @@ TestCase {
for (var delegateIndex = 0; delegateIndex < data.visibleItemCount; ++delegateIndex) {
if (data.expectedYPositions.hasOwnProperty(delegateIndex)) {
- var delegate = findChild(tumbler.contentItem, "delegate" + delegateIndex);
+ var delegate = findChild(tumblerView, "delegate" + delegateIndex);
verify(delegate, "Delegate found at index " + delegateIndex);
- var expectedYPos = data.expectedYPositions[delegateIndex] * tumbler.contentItem.delegateHeight;
+ var expectedYPos = data.expectedYPositions[delegateIndex] * tumblerDelegateHeight;
compare(delegate.mapToItem(tumbler.contentItem, 0, 0).y, expectedYPos);
}
}
@@ -604,12 +926,6 @@ TestCase {
property real displacement: Tumbler.displacement
}
- property Component gridViewComponent: GridView {}
- property Component simpleDisplacementDelegate: Text {
- property real displacement: Tumbler.displacement
- property int index: -1
- }
-
function test_attachedProperties() {
tumbler = tumblerComponent.createObject(cleanupItem);
verify(tumbler);
@@ -621,19 +937,12 @@ TestCase {
// // 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");
+ ignoreWarning("Tumbler: attached properties must be accessed through 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(cleanupItem);
verify(object);
- 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(cleanupItem);
- object = simpleDisplacementDelegate.createObject(gridView);
- verify(object);
- object.destroy();
}
property Component paddingDelegate: Text {
@@ -680,8 +989,7 @@ TestCase {
}
function test_padding(data) {
- tumbler = tumblerComponent.createObject(cleanupItem);
- verify(tumbler);
+ createTumbler();
tumbler.delegate = paddingDelegate;
tumbler.model = 5;
@@ -733,8 +1041,8 @@ TestCase {
}
// Force new items to be created, as there was a bug where the path was correct until this happened.
- compare(tumbler.contentItem.offset, 0);
+ compare(tumblerView.offset, 0);
++tumbler.currentIndex;
- tryCompare(tumbler.contentItem, "offset", 4, tumbler.contentItem.highlightMoveDuration * 2);
+ tryCompare(tumblerView, "offset", 4, tumblerView.highlightMoveDuration * 2);
}
}