2022-05-13 13:12:05 +00:00
|
|
|
// Copyright (C) 2017 The Qt Company Ltd.
|
2024-02-22 14:51:16 +00:00
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
2015-11-26 17:02:15 +00:00
|
|
|
|
2020-03-26 16:01:51 +00:00
|
|
|
import QtQuick
|
|
|
|
import QtQuick.Window
|
|
|
|
import QtTest
|
|
|
|
import QtQuick.Controls
|
2024-06-04 13:57:41 +00:00
|
|
|
import Qt.test.controls
|
2021-10-20 14:07:00 +00:00
|
|
|
import QtQuick.NativeStyle as NativeStyle
|
2015-11-26 17:02:15 +00:00
|
|
|
|
|
|
|
TestCase {
|
|
|
|
id: testCase
|
2017-04-04 08:47:50 +00:00
|
|
|
width: 400
|
|
|
|
height: 400
|
2016-03-18 10:34:10 +00:00
|
|
|
visible: true
|
|
|
|
when: windowShown
|
2015-11-26 17:02:15 +00:00
|
|
|
name: "ComboBox"
|
|
|
|
|
2016-10-01 21:02:43 +00:00
|
|
|
Component {
|
|
|
|
id: signalSpy
|
|
|
|
SignalSpy { }
|
|
|
|
}
|
|
|
|
|
2015-11-26 17:02:15 +00:00
|
|
|
Component {
|
|
|
|
id: comboBox
|
2016-10-01 21:02:43 +00:00
|
|
|
ComboBox { }
|
|
|
|
}
|
|
|
|
|
|
|
|
Component {
|
|
|
|
id: emptyBox
|
2015-11-26 17:02:15 +00:00
|
|
|
ComboBox {
|
|
|
|
delegate: ItemDelegate {
|
2016-11-04 15:45:17 +00:00
|
|
|
width: parent.width
|
2015-11-26 17:02:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-23 09:44:05 +00:00
|
|
|
Component {
|
|
|
|
id: mouseArea
|
|
|
|
MouseArea { }
|
|
|
|
}
|
|
|
|
|
2019-03-24 19:54:31 +00:00
|
|
|
Component {
|
|
|
|
id: customPopup
|
|
|
|
Popup {
|
|
|
|
width: 100
|
|
|
|
implicitHeight: contentItem.implicitHeight
|
|
|
|
contentItem: TextInput {
|
|
|
|
anchors.fill: parent
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-22 13:40:06 +00:00
|
|
|
Component {
|
|
|
|
id: comboBoxWithShaderEffect
|
|
|
|
ComboBox {
|
|
|
|
delegate: Rectangle {
|
|
|
|
Text {
|
|
|
|
id: txt
|
|
|
|
anchors.centerIn: parent
|
|
|
|
text: "item" + index
|
|
|
|
font.pixelSize: 20
|
|
|
|
color: "red"
|
|
|
|
}
|
|
|
|
id: rect
|
|
|
|
objectName: "rect"
|
|
|
|
width: parent.width
|
|
|
|
height: txt.implicitHeight
|
|
|
|
gradient: Gradient {
|
|
|
|
GradientStop { color: "lightsteelblue"; position: 0.0 }
|
|
|
|
GradientStop { color: "blue"; position: 1.0 }
|
|
|
|
}
|
|
|
|
layer.enabled: true
|
|
|
|
layer.effect: ShaderEffect {
|
|
|
|
objectName: "ShaderFX"
|
|
|
|
width: rect.width
|
|
|
|
height: rect.height
|
2024-08-12 07:24:10 +00:00
|
|
|
fragmentShader: "qrc:/data/combobox/shader.frag.qsb"
|
2019-05-22 13:40:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-04 07:36:56 +00:00
|
|
|
function init() {
|
2022-06-28 10:55:41 +00:00
|
|
|
// QTBUG-61225: Move the mouse away to avoid QQuickDeliveryAgentPrivate::flushFrameSynchronousEvents()
|
2017-06-04 07:36:56 +00:00
|
|
|
// delivering interfering hover events based on the last mouse position from earlier tests. For
|
|
|
|
// example, ComboBox::test_activation() kept receiving hover events for the last mouse position
|
|
|
|
// from CheckDelegate::test_checked().
|
|
|
|
mouseMove(testCase, testCase.width - 1, testCase.height - 1)
|
|
|
|
}
|
|
|
|
|
2015-11-26 17:02:15 +00:00
|
|
|
function test_defaults() {
|
2022-11-25 08:11:57 +00:00
|
|
|
failOnWarning(/.?/)
|
|
|
|
|
2016-12-21 10:22:25 +00:00
|
|
|
var control = createTemporaryObject(comboBox, testCase)
|
2015-11-26 17:02:15 +00:00
|
|
|
verify(control)
|
|
|
|
|
|
|
|
compare(control.count, 0)
|
|
|
|
compare(control.model, undefined)
|
2016-08-09 11:42:56 +00:00
|
|
|
compare(control.flat, false)
|
2015-11-26 17:02:15 +00:00
|
|
|
compare(control.pressed, false)
|
|
|
|
compare(control.currentIndex, -1)
|
|
|
|
compare(control.highlightedIndex, -1)
|
|
|
|
compare(control.currentText, "")
|
|
|
|
verify(control.delegate)
|
2021-08-30 14:13:06 +00:00
|
|
|
if (Qt.platform.pluginName !== "cocoa" && Qt.platform.pluginName !== "windows") {
|
|
|
|
// Only the non-native styles sets an indicator delegate. The native
|
|
|
|
// styles will instead draw the indicator as a part of the background.
|
|
|
|
verify(control.indicator)
|
|
|
|
}
|
2015-12-08 13:26:51 +00:00
|
|
|
verify(control.popup)
|
2021-06-11 12:06:57 +00:00
|
|
|
verify(control.acceptableInput)
|
2021-01-21 10:04:55 +00:00
|
|
|
compare(control.inputMethodHints, Qt.ImhNoPredictiveText)
|
2015-11-26 17:02:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function test_array() {
|
2016-12-21 10:22:25 +00:00
|
|
|
var control = createTemporaryObject(comboBox, testCase)
|
2015-11-26 17:02:15 +00:00
|
|
|
verify(control)
|
|
|
|
|
|
|
|
var items = [ "Banana", "Apple", "Coconut" ]
|
|
|
|
|
|
|
|
control.model = items
|
|
|
|
compare(control.model, items)
|
|
|
|
|
|
|
|
compare(control.count, 3)
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
compare(control.currentText, "Banana")
|
|
|
|
|
|
|
|
control.currentIndex = 2
|
|
|
|
compare(control.currentIndex, 2)
|
|
|
|
compare(control.currentText, "Coconut")
|
|
|
|
|
|
|
|
control.model = null
|
|
|
|
compare(control.model, null)
|
|
|
|
compare(control.count, 0)
|
|
|
|
compare(control.currentIndex, -1)
|
|
|
|
compare(control.currentText, "")
|
|
|
|
}
|
|
|
|
|
2016-01-25 16:06:30 +00:00
|
|
|
function test_objects() {
|
2016-12-21 10:22:25 +00:00
|
|
|
var control = createTemporaryObject(emptyBox, testCase)
|
2016-01-25 16:06:30 +00:00
|
|
|
verify(control)
|
|
|
|
|
|
|
|
var items = [
|
|
|
|
{ text: "Apple" },
|
|
|
|
{ text: "Orange" },
|
|
|
|
{ text: "Banana" }
|
|
|
|
]
|
|
|
|
|
|
|
|
control.model = items
|
|
|
|
compare(control.model, items)
|
|
|
|
|
|
|
|
compare(control.count, 3)
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
compare(control.currentText, "Apple")
|
|
|
|
|
|
|
|
control.currentIndex = 2
|
|
|
|
compare(control.currentIndex, 2)
|
|
|
|
compare(control.currentText, "Banana")
|
|
|
|
|
|
|
|
control.model = null
|
|
|
|
compare(control.model, null)
|
|
|
|
compare(control.count, 0)
|
|
|
|
compare(control.currentIndex, -1)
|
|
|
|
compare(control.currentText, "")
|
|
|
|
}
|
|
|
|
|
2017-06-12 09:11:38 +00:00
|
|
|
function test_qobjects() {
|
|
|
|
var control = createTemporaryObject(emptyBox, testCase, {textRole: "text"})
|
|
|
|
verify(control)
|
|
|
|
|
2020-03-26 16:01:51 +00:00
|
|
|
var obj1 = Qt.createQmlObject("import QtQml; QtObject { property string text: 'one' }", control)
|
|
|
|
var obj2 = Qt.createQmlObject("import QtQml; QtObject { property string text: 'two' }", control)
|
|
|
|
var obj3 = Qt.createQmlObject("import QtQml; QtObject { property string text: 'three' }", control)
|
2017-06-12 09:11:38 +00:00
|
|
|
|
|
|
|
control.model = [obj1, obj2, obj3]
|
|
|
|
|
|
|
|
compare(control.count, 3)
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
compare(control.currentText, "one")
|
|
|
|
|
|
|
|
control.currentIndex = 2
|
|
|
|
compare(control.currentIndex, 2)
|
|
|
|
compare(control.currentText, "three")
|
|
|
|
|
|
|
|
control.model = null
|
|
|
|
compare(control.model, null)
|
|
|
|
compare(control.count, 0)
|
|
|
|
compare(control.currentIndex, -1)
|
|
|
|
compare(control.currentText, "")
|
|
|
|
}
|
|
|
|
|
2015-11-26 17:02:15 +00:00
|
|
|
function test_number() {
|
2016-12-21 10:22:25 +00:00
|
|
|
var control = createTemporaryObject(comboBox, testCase)
|
2015-11-26 17:02:15 +00:00
|
|
|
verify(control)
|
|
|
|
|
|
|
|
control.model = 10
|
|
|
|
compare(control.model, 10)
|
|
|
|
|
|
|
|
compare(control.count, 10)
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
compare(control.currentText, "0")
|
|
|
|
|
|
|
|
control.currentIndex = 9
|
|
|
|
compare(control.currentIndex, 9)
|
|
|
|
compare(control.currentText, "9")
|
|
|
|
|
|
|
|
control.model = 0
|
|
|
|
compare(control.model, 0)
|
|
|
|
compare(control.count, 0)
|
|
|
|
compare(control.currentIndex, -1)
|
|
|
|
compare(control.currentText, "")
|
|
|
|
}
|
|
|
|
|
|
|
|
ListModel {
|
|
|
|
id: listmodel
|
|
|
|
ListElement { text: "First" }
|
|
|
|
ListElement { text: "Second" }
|
|
|
|
ListElement { text: "Third" }
|
|
|
|
ListElement { text: "Fourth" }
|
|
|
|
ListElement { text: "Fifth" }
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_listModel() {
|
2016-12-21 10:22:25 +00:00
|
|
|
var control = createTemporaryObject(comboBox, testCase)
|
2015-11-26 17:02:15 +00:00
|
|
|
verify(control)
|
|
|
|
|
|
|
|
control.model = listmodel
|
|
|
|
compare(control.model, listmodel)
|
|
|
|
|
|
|
|
compare(control.count, 5)
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
compare(control.currentText, "First")
|
|
|
|
|
|
|
|
control.currentIndex = 2
|
|
|
|
compare(control.currentIndex, 2)
|
|
|
|
compare(control.currentText, "Third")
|
|
|
|
|
|
|
|
control.model = undefined
|
|
|
|
compare(control.model, undefined)
|
|
|
|
compare(control.count, 0)
|
|
|
|
compare(control.currentIndex, -1)
|
|
|
|
compare(control.currentText, "")
|
|
|
|
}
|
|
|
|
|
|
|
|
ListModel {
|
|
|
|
id: fruitmodel
|
|
|
|
ListElement { name: "Apple"; color: "red" }
|
|
|
|
ListElement { name: "Orange"; color: "orange" }
|
|
|
|
ListElement { name: "Banana"; color: "yellow" }
|
|
|
|
}
|
|
|
|
|
2020-05-11 13:45:31 +00:00
|
|
|
Component {
|
|
|
|
id: fruitModelComponent
|
|
|
|
ListModel {
|
|
|
|
ListElement { name: "Apple"; color: "red" }
|
|
|
|
ListElement { name: "Orange"; color: "orange" }
|
|
|
|
ListElement { name: "Banana"; color: "yellow" }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-25 16:06:30 +00:00
|
|
|
property var fruitarray: [
|
|
|
|
{ name: "Apple", color: "red" },
|
|
|
|
{ name: "Orange", color: "orange" },
|
|
|
|
{ name: "Banana", color: "yellow" }
|
|
|
|
]
|
|
|
|
|
2020-05-11 13:45:31 +00:00
|
|
|
Component {
|
|
|
|
id: birdModelComponent
|
|
|
|
ListModel {
|
|
|
|
ListElement { name: "Galah"; color: "pink" }
|
|
|
|
ListElement { name: "Kookaburra"; color: "brown" }
|
|
|
|
ListElement { name: "Magpie"; color: "black" }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-25 16:06:30 +00:00
|
|
|
function test_textRole_data() {
|
|
|
|
return [
|
|
|
|
{ tag: "ListModel", model: fruitmodel },
|
|
|
|
{ tag: "ObjectArray", model: fruitarray }
|
|
|
|
]
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_textRole(data) {
|
2016-12-21 10:22:25 +00:00
|
|
|
var control = createTemporaryObject(emptyBox, testCase)
|
2015-11-26 17:02:15 +00:00
|
|
|
verify(control)
|
|
|
|
|
2016-01-25 16:06:30 +00:00
|
|
|
control.model = data.model
|
2015-11-26 17:02:15 +00:00
|
|
|
compare(control.count, 3)
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
compare(control.currentText, "")
|
|
|
|
|
|
|
|
control.textRole = "name"
|
|
|
|
compare(control.currentText, "Apple")
|
|
|
|
|
|
|
|
control.textRole = "color"
|
|
|
|
compare(control.currentText, "red")
|
|
|
|
|
|
|
|
control.currentIndex = 1
|
|
|
|
compare(control.currentIndex, 1)
|
|
|
|
compare(control.currentText, "orange")
|
|
|
|
|
|
|
|
control.textRole = "name"
|
|
|
|
compare(control.currentText, "Orange")
|
|
|
|
|
|
|
|
control.textRole = ""
|
|
|
|
compare(control.currentText, "")
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_textAt() {
|
2016-12-21 10:22:25 +00:00
|
|
|
var control = createTemporaryObject(comboBox, testCase)
|
2015-11-26 17:02:15 +00:00
|
|
|
verify(control)
|
|
|
|
|
|
|
|
control.model = ["Apple", "Orange", "Banana"]
|
|
|
|
compare(control.textAt(0), "Apple")
|
|
|
|
compare(control.textAt(1), "Orange")
|
|
|
|
compare(control.textAt(2), "Banana")
|
|
|
|
compare(control.textAt(-1), "") // TODO: null?
|
|
|
|
compare(control.textAt(5), "") // TODO: null?
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_find_data() {
|
|
|
|
return [
|
|
|
|
{ tag: "Banana (MatchExactly)", term: "Banana", flags: Qt.MatchExactly, index: 0 },
|
|
|
|
{ tag: "banana (MatchExactly)", term: "banana", flags: Qt.MatchExactly, index: 1 },
|
|
|
|
{ tag: "bananas (MatchExactly)", term: "bananas", flags: Qt.MatchExactly, index: -1 },
|
|
|
|
{ tag: "Cocomuffin (MatchExactly)", term: "Cocomuffin", flags: Qt.MatchExactly, index: 4 },
|
|
|
|
|
2020-03-18 15:49:13 +00:00
|
|
|
{ tag: "b(an)+a (MatchRegularExpression)", term: "B(an)+a", flags: Qt.MatchRegularExpression, index: 0 },
|
|
|
|
{ tag: "b(an)+a (MatchRegularExpression|MatchCaseSensitive)", term: "b(an)+a", flags: Qt.MatchRegularExpression | Qt.MatchCaseSensitive, index: 1 },
|
|
|
|
{ tag: "[coc]+\\w+ (MatchRegularExpression)", term: "[coc]+\\w+", flags: Qt.MatchRegularExpression, index: 2 },
|
2015-11-26 17:02:15 +00:00
|
|
|
|
|
|
|
{ tag: "?pp* (MatchWildcard)", term: "?pp*", flags: Qt.MatchWildcard, index: 3 },
|
|
|
|
{ tag: "app* (MatchWildcard|MatchCaseSensitive)", term: "app*", flags: Qt.MatchWildcard | Qt.MatchCaseSensitive, index: -1 },
|
|
|
|
|
|
|
|
{ tag: "Banana (MatchFixedString)", term: "Banana", flags: Qt.MatchFixedString, index: 0 },
|
|
|
|
{ tag: "banana (MatchFixedString|MatchCaseSensitive)", term: "banana", flags: Qt.MatchFixedString | Qt.MatchCaseSensitive, index: 1 },
|
|
|
|
|
|
|
|
{ tag: "coco (MatchStartsWith)", term: "coco", flags: Qt.MatchStartsWith, index: 2 },
|
|
|
|
{ tag: "coco (MatchStartsWith|MatchCaseSensitive)", term: "coco", flags: Qt.StartsWith | Qt.MatchCaseSensitive, index: -1 },
|
|
|
|
|
|
|
|
{ tag: "MUFFIN (MatchEndsWith)", term: "MUFFIN", flags: Qt.MatchEndsWith, index: 4 },
|
|
|
|
{ tag: "MUFFIN (MatchEndsWith|MatchCaseSensitive)", term: "MUFFIN", flags: Qt.MatchEndsWith | Qt.MatchCaseSensitive, index: -1 },
|
|
|
|
|
|
|
|
{ tag: "Con (MatchContains)", term: "Con", flags: Qt.MatchContains, index: 2 },
|
|
|
|
{ tag: "Con (MatchContains|MatchCaseSensitive)", term: "Con", flags: Qt.MatchContains | Qt.MatchCaseSensitive, index: -1 },
|
|
|
|
]
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_find(data) {
|
2016-12-21 10:22:25 +00:00
|
|
|
var control = createTemporaryObject(comboBox, testCase)
|
2015-11-26 17:02:15 +00:00
|
|
|
verify(control)
|
|
|
|
|
|
|
|
control.model = ["Banana", "banana", "Coconut", "Apple", "Cocomuffin"]
|
|
|
|
|
|
|
|
compare(control.find(data.term, data.flags), data.index)
|
|
|
|
}
|
|
|
|
|
Add valueRole API to ComboBox
This allows the user to conveniently manage data for a role associated with
the text role. A common example of this is an enum stored in a backend with
nicely formatted text displayed to the user. Before this patch, developers
would have to write code like this:
ComboBox {
textRole: "text"
onActivated: backend.modifier = model[currentIndex].value
Component.onCompleted: currentIndex = findValue(backend.modifier)
model: [
{ value: Qt.NoModifier, text: qsTr("No modifier") },
{ value: Qt.ShiftModifier, text: qsTr("Shift") },
{ value: Qt.ControlModifier, text: qsTr("Control") }
]
function findValue(value) {
for (var i = 0; i < model.length; ++i) {
if (model[i].value === value)
return i
}
return -1
}
}
With this patch, the code becomes much simpler:
ComboBox {
textRole: "text"
valueRole: "value"
onActivated: backend.modifier = currentValue
Component.onCompleted: currentIndex = indexOfValue(backend.modifier)
model: [
{ value: Qt.NoModifier, text: qsTr("No modifier") },
{ value: Qt.ShiftModifier, text: qsTr("Shift") },
{ value: Qt.ControlModifier, text: qsTr("Control") }
]
}
[ChangeLog][Controls][ComboBox] Added valueRole, currentValue and
indexOfValue(). These allow convenient management of data for a role
associated with the text role.
Change-Id: I0ed19bd0ba9cf6b044a8113ff1a8782d43065449
Fixes: QTBUG-73491
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
2019-03-04 10:12:05 +00:00
|
|
|
function test_valueRole_data() {
|
|
|
|
return [
|
|
|
|
{ tag: "ListModel", model: fruitmodel },
|
|
|
|
{ tag: "ObjectArray", model: fruitarray }
|
|
|
|
]
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_valueRole(data) {
|
|
|
|
var control = createTemporaryObject(emptyBox, testCase,
|
|
|
|
{ model: data.model, valueRole: "color" })
|
|
|
|
verify(control)
|
|
|
|
compare(control.count, 3)
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
compare(control.currentValue, "red")
|
|
|
|
|
|
|
|
control.valueRole = "name"
|
|
|
|
compare(control.currentValue, "Apple")
|
|
|
|
|
|
|
|
control.currentIndex = 1
|
|
|
|
compare(control.currentIndex, 1)
|
|
|
|
compare(control.currentValue, "Orange")
|
|
|
|
|
|
|
|
control.valueRole = "color"
|
|
|
|
compare(control.currentValue, "orange")
|
|
|
|
|
|
|
|
control.model = null
|
|
|
|
compare(control.currentIndex, -1)
|
|
|
|
// An invalid QVariant is represented as undefined.
|
|
|
|
compare(control.currentValue, undefined)
|
|
|
|
|
|
|
|
control.valueRole = ""
|
|
|
|
compare(control.currentValue, undefined)
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_valueAt() {
|
|
|
|
var control = createTemporaryObject(comboBox, testCase,
|
|
|
|
{ model: fruitmodel, textRole: "name", valueRole: "color" })
|
|
|
|
verify(control)
|
|
|
|
|
|
|
|
compare(control.valueAt(0), "red")
|
|
|
|
compare(control.valueAt(1), "orange")
|
|
|
|
compare(control.valueAt(2), "yellow")
|
|
|
|
compare(control.valueAt(-1), undefined)
|
|
|
|
compare(control.valueAt(5), undefined)
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_indexOfValue_data() {
|
|
|
|
return [
|
|
|
|
{ tag: "red", expectedIndex: 0 },
|
|
|
|
{ tag: "orange", expectedIndex: 1 },
|
|
|
|
{ tag: "yellow", expectedIndex: 2 },
|
|
|
|
{ tag: "brown", expectedIndex: -1 },
|
|
|
|
]
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_indexOfValue(data) {
|
|
|
|
var control = createTemporaryObject(comboBox, testCase,
|
|
|
|
{ model: fruitmodel, textRole: "name", valueRole: "color" })
|
|
|
|
verify(control)
|
|
|
|
|
|
|
|
compare(control.indexOfValue(data.tag), data.expectedIndex)
|
|
|
|
}
|
|
|
|
|
2020-05-11 13:45:31 +00:00
|
|
|
function test_currentValueAfterModelChanged() {
|
|
|
|
let fruitModel = createTemporaryObject(fruitModelComponent, testCase)
|
|
|
|
verify(fruitModel)
|
|
|
|
|
|
|
|
let control = createTemporaryObject(comboBox, testCase,
|
|
|
|
{ model: fruitModel, textRole: "name", valueRole: "color", currentIndex: 1 })
|
|
|
|
verify(control)
|
|
|
|
compare(control.currentText, "Orange")
|
|
|
|
compare(control.currentValue, "orange")
|
|
|
|
|
|
|
|
// Remove "Apple"; the current item should now be "Banana", so currentValue should be "yellow".
|
|
|
|
fruitModel.remove(0)
|
|
|
|
compare(control.currentText, "Banana")
|
|
|
|
compare(control.currentValue, "yellow")
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_currentValueAfterNewModelSet() {
|
|
|
|
let control = createTemporaryObject(comboBox, testCase,
|
|
|
|
{ model: fruitmodel, textRole: "name", valueRole: "color", currentIndex: 0 })
|
|
|
|
verify(control)
|
|
|
|
compare(control.currentText, "Apple")
|
|
|
|
compare(control.currentValue, "red")
|
|
|
|
|
|
|
|
// Swap the model out entirely. Since the currentIndex was 0 and
|
|
|
|
// is reset to 0 when a new model is set, it remains 0.
|
|
|
|
let birdModel = createTemporaryObject(birdModelComponent, testCase)
|
|
|
|
verify(birdModel)
|
|
|
|
control.model = birdModel
|
|
|
|
compare(control.currentText, "Galah")
|
|
|
|
compare(control.currentValue, "pink")
|
|
|
|
}
|
2016-01-31 07:32:42 +00:00
|
|
|
|
2016-03-18 10:34:10 +00:00
|
|
|
function test_arrowKeys() {
|
Add valueRole API to ComboBox
This allows the user to conveniently manage data for a role associated with
the text role. A common example of this is an enum stored in a backend with
nicely formatted text displayed to the user. Before this patch, developers
would have to write code like this:
ComboBox {
textRole: "text"
onActivated: backend.modifier = model[currentIndex].value
Component.onCompleted: currentIndex = findValue(backend.modifier)
model: [
{ value: Qt.NoModifier, text: qsTr("No modifier") },
{ value: Qt.ShiftModifier, text: qsTr("Shift") },
{ value: Qt.ControlModifier, text: qsTr("Control") }
]
function findValue(value) {
for (var i = 0; i < model.length; ++i) {
if (model[i].value === value)
return i
}
return -1
}
}
With this patch, the code becomes much simpler:
ComboBox {
textRole: "text"
valueRole: "value"
onActivated: backend.modifier = currentValue
Component.onCompleted: currentIndex = indexOfValue(backend.modifier)
model: [
{ value: Qt.NoModifier, text: qsTr("No modifier") },
{ value: Qt.ShiftModifier, text: qsTr("Shift") },
{ value: Qt.ControlModifier, text: qsTr("Control") }
]
}
[ChangeLog][Controls][ComboBox] Added valueRole, currentValue and
indexOfValue(). These allow convenient management of data for a role
associated with the text role.
Change-Id: I0ed19bd0ba9cf6b044a8113ff1a8782d43065449
Fixes: QTBUG-73491
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
2019-03-04 10:12:05 +00:00
|
|
|
var control = createTemporaryObject(comboBox, testCase,
|
|
|
|
{ model: fruitmodel, textRole: "name", valueRole: "color" })
|
2015-11-26 17:02:15 +00:00
|
|
|
verify(control)
|
|
|
|
|
2016-10-07 12:51:51 +00:00
|
|
|
var activatedSpy = signalSpy.createObject(control, {target: control, signalName: "activated"})
|
2015-11-26 17:02:15 +00:00
|
|
|
verify(activatedSpy.valid)
|
|
|
|
|
2016-10-07 12:51:51 +00:00
|
|
|
var highlightedSpy = signalSpy.createObject(control, {target: control, signalName: "highlighted"})
|
2015-11-26 17:02:15 +00:00
|
|
|
verify(highlightedSpy.valid)
|
|
|
|
|
2017-04-25 13:22:19 +00:00
|
|
|
var openedSpy = signalSpy.createObject(control, {target: control.popup, signalName: "opened"})
|
|
|
|
verify(openedSpy.valid)
|
|
|
|
|
|
|
|
var closedSpy = signalSpy.createObject(control, {target: control.popup, signalName: "closed"})
|
|
|
|
verify(closedSpy.valid)
|
2015-11-26 17:02:15 +00:00
|
|
|
|
|
|
|
control.forceActiveFocus()
|
|
|
|
verify(control.activeFocus)
|
|
|
|
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
compare(control.highlightedIndex, -1)
|
|
|
|
|
|
|
|
keyClick(Qt.Key_Down)
|
|
|
|
compare(control.currentIndex, 1)
|
|
|
|
compare(control.highlightedIndex, -1)
|
|
|
|
compare(highlightedSpy.count, 0)
|
|
|
|
compare(activatedSpy.count, 1)
|
|
|
|
compare(activatedSpy.signalArguments[0][0], 1)
|
|
|
|
activatedSpy.clear()
|
|
|
|
|
|
|
|
keyClick(Qt.Key_Down)
|
|
|
|
compare(control.currentIndex, 2)
|
|
|
|
compare(control.highlightedIndex, -1)
|
|
|
|
compare(highlightedSpy.count, 0)
|
|
|
|
compare(activatedSpy.count, 1)
|
|
|
|
compare(activatedSpy.signalArguments[0][0], 2)
|
|
|
|
activatedSpy.clear()
|
|
|
|
|
|
|
|
keyClick(Qt.Key_Down)
|
|
|
|
compare(control.currentIndex, 2)
|
|
|
|
compare(control.highlightedIndex, -1)
|
|
|
|
compare(highlightedSpy.count, 0)
|
|
|
|
compare(activatedSpy.count, 0)
|
|
|
|
|
|
|
|
keyClick(Qt.Key_Up)
|
|
|
|
compare(control.currentIndex, 1)
|
|
|
|
compare(control.highlightedIndex, -1)
|
|
|
|
compare(highlightedSpy.count, 0)
|
|
|
|
compare(activatedSpy.count, 1)
|
|
|
|
compare(activatedSpy.signalArguments[0][0], 1)
|
|
|
|
activatedSpy.clear()
|
|
|
|
|
|
|
|
keyClick(Qt.Key_Up)
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
compare(control.highlightedIndex, -1)
|
|
|
|
compare(highlightedSpy.count, 0)
|
|
|
|
compare(activatedSpy.count, 1)
|
|
|
|
compare(activatedSpy.signalArguments[0][0], 0)
|
|
|
|
activatedSpy.clear()
|
|
|
|
|
|
|
|
keyClick(Qt.Key_Up)
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
compare(control.highlightedIndex, -1)
|
|
|
|
compare(highlightedSpy.count, 0)
|
|
|
|
compare(activatedSpy.count, 0)
|
|
|
|
|
2015-12-08 13:26:51 +00:00
|
|
|
// show popup
|
2015-11-26 17:02:15 +00:00
|
|
|
keyClick(Qt.Key_Space)
|
2017-04-25 13:22:19 +00:00
|
|
|
openedSpy.wait()
|
|
|
|
compare(openedSpy.count, 1)
|
2015-11-26 17:02:15 +00:00
|
|
|
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
compare(control.highlightedIndex, 0)
|
|
|
|
|
|
|
|
keyClick(Qt.Key_Down)
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
compare(control.highlightedIndex, 1)
|
|
|
|
compare(activatedSpy.count, 0)
|
|
|
|
compare(highlightedSpy.count, 1)
|
|
|
|
compare(highlightedSpy.signalArguments[0][0], 1)
|
|
|
|
highlightedSpy.clear()
|
|
|
|
|
|
|
|
keyClick(Qt.Key_Down)
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
compare(control.highlightedIndex, 2)
|
|
|
|
compare(activatedSpy.count, 0)
|
|
|
|
compare(highlightedSpy.count, 1)
|
|
|
|
compare(highlightedSpy.signalArguments[0][0], 2)
|
|
|
|
highlightedSpy.clear()
|
|
|
|
|
|
|
|
keyClick(Qt.Key_Down)
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
compare(control.highlightedIndex, 2)
|
|
|
|
compare(activatedSpy.count, 0)
|
|
|
|
compare(highlightedSpy.count, 0)
|
|
|
|
|
|
|
|
keyClick(Qt.Key_Up)
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
compare(control.highlightedIndex, 1)
|
|
|
|
compare(activatedSpy.count, 0)
|
|
|
|
compare(highlightedSpy.count, 1)
|
|
|
|
compare(highlightedSpy.signalArguments[0][0], 1)
|
|
|
|
highlightedSpy.clear()
|
|
|
|
|
|
|
|
keyClick(Qt.Key_Up)
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
compare(control.highlightedIndex, 0)
|
|
|
|
compare(activatedSpy.count, 0)
|
|
|
|
compare(highlightedSpy.count, 1)
|
|
|
|
compare(highlightedSpy.signalArguments[0][0], 0)
|
|
|
|
highlightedSpy.clear()
|
|
|
|
|
|
|
|
keyClick(Qt.Key_Up)
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
compare(control.highlightedIndex, 0)
|
|
|
|
compare(activatedSpy.count, 0)
|
|
|
|
compare(highlightedSpy.count, 0)
|
|
|
|
|
|
|
|
keyClick(Qt.Key_Down)
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
compare(control.highlightedIndex, 1)
|
|
|
|
compare(activatedSpy.count, 0)
|
|
|
|
compare(highlightedSpy.count, 1)
|
|
|
|
compare(highlightedSpy.signalArguments[0][0], 1)
|
|
|
|
highlightedSpy.clear()
|
|
|
|
|
2015-12-08 13:26:51 +00:00
|
|
|
// hide popup
|
2015-11-26 17:02:15 +00:00
|
|
|
keyClick(Qt.Key_Space)
|
2017-04-25 13:22:19 +00:00
|
|
|
closedSpy.wait()
|
|
|
|
compare(closedSpy.count, 1)
|
2015-11-26 17:02:15 +00:00
|
|
|
|
|
|
|
compare(control.currentIndex, 1)
|
2017-04-25 13:22:19 +00:00
|
|
|
compare(control.highlightedIndex, -1)
|
2015-11-26 17:02:15 +00:00
|
|
|
}
|
|
|
|
|
2016-11-03 08:40:47 +00:00
|
|
|
function test_keys_space_enter_escape_data() {
|
2022-02-16 21:57:50 +00:00
|
|
|
// Not testing Key_Enter + Key_Enter and Key_Return + Key_Return because
|
|
|
|
// QGnomeTheme uses Key_Enter and Key_Return for pressing buttons/comboboxes
|
|
|
|
// and the CI uses the QGnomeTheme platform theme.
|
2015-11-26 17:02:15 +00:00
|
|
|
return [
|
2016-03-18 10:34:10 +00:00
|
|
|
{ tag: "space-space", key1: Qt.Key_Space, key2: Qt.Key_Space, showPopup: true, showPress: true, hidePopup: true, hidePress: true },
|
|
|
|
{ tag: "space-enter", key1: Qt.Key_Space, key2: Qt.Key_Enter, showPopup: true, showPress: true, hidePopup: true, hidePress: true },
|
|
|
|
{ tag: "space-return", key1: Qt.Key_Space, key2: Qt.Key_Return, showPopup: true, showPress: true, hidePopup: true, hidePress: true },
|
|
|
|
{ tag: "space-escape", key1: Qt.Key_Space, key2: Qt.Key_Escape, showPopup: true, showPress: true, hidePopup: true, hidePress: false },
|
|
|
|
{ tag: "space-0", key1: Qt.Key_Space, key2: Qt.Key_0, showPopup: true, showPress: true, hidePopup: false, hidePress: false },
|
|
|
|
{ tag: "escape-escape", key1: Qt.Key_Escape, key2: Qt.Key_Escape, showPopup: false, showPress: false, hidePopup: true, hidePress: false }
|
2015-11-26 17:02:15 +00:00
|
|
|
]
|
|
|
|
}
|
|
|
|
|
2016-11-03 08:40:47 +00:00
|
|
|
function test_keys_space_enter_escape(data) {
|
2016-12-21 10:22:25 +00:00
|
|
|
var control = createTemporaryObject(comboBox, testCase, {model: 3})
|
2015-11-26 17:02:15 +00:00
|
|
|
verify(control)
|
|
|
|
|
2017-04-25 13:22:19 +00:00
|
|
|
var openedSpy = signalSpy.createObject(control, {target: control.popup, signalName: "opened"})
|
|
|
|
verify(openedSpy.valid)
|
2016-01-31 07:32:42 +00:00
|
|
|
|
2015-11-26 17:02:15 +00:00
|
|
|
control.forceActiveFocus()
|
|
|
|
verify(control.activeFocus)
|
|
|
|
|
|
|
|
compare(control.pressed, false)
|
2015-12-08 13:26:51 +00:00
|
|
|
compare(control.popup.visible, false)
|
2015-11-26 17:02:15 +00:00
|
|
|
|
2015-12-08 13:26:51 +00:00
|
|
|
// show popup
|
2015-11-26 17:02:15 +00:00
|
|
|
keyPress(data.key1)
|
|
|
|
compare(control.pressed, data.showPress)
|
2015-12-08 13:26:51 +00:00
|
|
|
compare(control.popup.visible, false)
|
2015-11-26 17:02:15 +00:00
|
|
|
keyRelease(data.key1)
|
|
|
|
compare(control.pressed, false)
|
2015-12-08 13:26:51 +00:00
|
|
|
compare(control.popup.visible, data.showPopup)
|
2017-04-25 13:22:19 +00:00
|
|
|
if (data.showPopup)
|
|
|
|
openedSpy.wait()
|
2015-11-26 17:02:15 +00:00
|
|
|
|
2015-12-08 13:26:51 +00:00
|
|
|
// hide popup
|
2015-11-26 17:02:15 +00:00
|
|
|
keyPress(data.key2)
|
|
|
|
compare(control.pressed, data.hidePress)
|
|
|
|
keyRelease(data.key2)
|
|
|
|
compare(control.pressed, false)
|
2015-12-19 22:00:50 +00:00
|
|
|
tryCompare(control.popup, "visible", !data.hidePopup)
|
2015-11-26 17:02:15 +00:00
|
|
|
}
|
|
|
|
|
2016-11-03 08:40:47 +00:00
|
|
|
function test_keys_home_end() {
|
2016-12-21 10:22:25 +00:00
|
|
|
var control = createTemporaryObject(comboBox, testCase, {model: 5})
|
2016-11-03 08:40:47 +00:00
|
|
|
verify(control)
|
|
|
|
|
|
|
|
control.forceActiveFocus()
|
|
|
|
verify(control.activeFocus)
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
compare(control.highlightedIndex, -1)
|
|
|
|
|
|
|
|
var activatedCount = 0
|
|
|
|
var activatedSpy = signalSpy.createObject(control, {target: control, signalName: "activated"})
|
|
|
|
verify(activatedSpy.valid)
|
|
|
|
|
|
|
|
var highlightedCount = 0
|
|
|
|
var highlightedSpy = signalSpy.createObject(control, {target: control, signalName: "highlighted"})
|
|
|
|
verify(highlightedSpy.valid)
|
|
|
|
|
|
|
|
var currentIndexCount = 0
|
|
|
|
var currentIndexSpy = signalSpy.createObject(control, {target: control, signalName: "currentIndexChanged"})
|
|
|
|
verify(currentIndexSpy.valid)
|
|
|
|
|
|
|
|
var highlightedIndexCount = 0
|
|
|
|
var highlightedIndexSpy = signalSpy.createObject(control, {target: control, signalName: "highlightedIndexChanged"})
|
|
|
|
verify(highlightedIndexSpy.valid)
|
|
|
|
|
|
|
|
// end (popup closed)
|
|
|
|
keyClick(Qt.Key_End)
|
|
|
|
compare(control.currentIndex, 4)
|
|
|
|
compare(currentIndexSpy.count, ++currentIndexCount)
|
|
|
|
|
|
|
|
compare(control.highlightedIndex, -1)
|
|
|
|
compare(highlightedIndexSpy.count, highlightedIndexCount)
|
|
|
|
|
|
|
|
compare(activatedSpy.count, ++activatedCount)
|
|
|
|
compare(activatedSpy.signalArguments[activatedCount-1][0], 4)
|
|
|
|
|
|
|
|
compare(highlightedSpy.count, highlightedCount)
|
|
|
|
|
|
|
|
// repeat (no changes/signals)
|
|
|
|
keyClick(Qt.Key_End)
|
|
|
|
compare(currentIndexSpy.count, currentIndexCount)
|
|
|
|
compare(highlightedIndexSpy.count, highlightedIndexCount)
|
|
|
|
compare(activatedSpy.count, activatedCount)
|
|
|
|
compare(highlightedSpy.count, highlightedCount)
|
|
|
|
|
|
|
|
// home (popup closed)
|
|
|
|
keyClick(Qt.Key_Home)
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
compare(currentIndexSpy.count, ++currentIndexCount)
|
|
|
|
|
|
|
|
compare(control.highlightedIndex, -1)
|
|
|
|
compare(highlightedIndexSpy.count, highlightedIndexCount)
|
|
|
|
|
|
|
|
compare(activatedSpy.count, ++activatedCount)
|
|
|
|
compare(activatedSpy.signalArguments[activatedCount-1][0], 0)
|
|
|
|
|
|
|
|
compare(highlightedSpy.count, highlightedCount)
|
|
|
|
|
|
|
|
// repeat (no changes/signals)
|
|
|
|
keyClick(Qt.Key_Home)
|
|
|
|
compare(currentIndexSpy.count, currentIndexCount)
|
|
|
|
compare(highlightedIndexSpy.count, highlightedIndexCount)
|
|
|
|
compare(activatedSpy.count, activatedCount)
|
|
|
|
compare(highlightedSpy.count, highlightedCount)
|
|
|
|
|
|
|
|
control.popup.open()
|
|
|
|
compare(control.highlightedIndex, 0)
|
|
|
|
compare(highlightedIndexSpy.count, ++highlightedIndexCount)
|
|
|
|
compare(highlightedSpy.count, highlightedCount)
|
|
|
|
|
|
|
|
// end (popup open)
|
|
|
|
keyClick(Qt.Key_End)
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
compare(currentIndexSpy.count, currentIndexCount)
|
|
|
|
|
|
|
|
compare(control.highlightedIndex, 4)
|
|
|
|
compare(highlightedIndexSpy.count, ++highlightedIndexCount)
|
|
|
|
|
|
|
|
compare(activatedSpy.count, activatedCount)
|
|
|
|
|
|
|
|
compare(highlightedSpy.count, ++highlightedCount)
|
|
|
|
compare(highlightedSpy.signalArguments[highlightedCount-1][0], 4)
|
|
|
|
|
|
|
|
// repeat (no changes/signals)
|
|
|
|
keyClick(Qt.Key_End)
|
|
|
|
compare(currentIndexSpy.count, currentIndexCount)
|
|
|
|
compare(highlightedIndexSpy.count, highlightedIndexCount)
|
|
|
|
compare(activatedSpy.count, activatedCount)
|
|
|
|
compare(highlightedSpy.count, highlightedCount)
|
|
|
|
|
|
|
|
// home (popup open)
|
|
|
|
keyClick(Qt.Key_Home)
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
compare(currentIndexSpy.count, currentIndexCount)
|
|
|
|
|
|
|
|
compare(control.highlightedIndex, 0)
|
|
|
|
compare(highlightedIndexSpy.count, ++highlightedIndexCount)
|
|
|
|
|
|
|
|
compare(activatedSpy.count, activatedCount)
|
|
|
|
|
|
|
|
compare(highlightedSpy.count, ++highlightedCount)
|
|
|
|
compare(highlightedSpy.signalArguments[highlightedCount-1][0], 0)
|
|
|
|
|
|
|
|
// repeat (no changes/signals)
|
|
|
|
keyClick(Qt.Key_Home)
|
|
|
|
compare(currentIndexSpy.count, currentIndexCount)
|
|
|
|
compare(highlightedIndexSpy.count, highlightedIndexCount)
|
|
|
|
compare(activatedSpy.count, activatedCount)
|
|
|
|
compare(highlightedSpy.count, highlightedCount)
|
|
|
|
}
|
|
|
|
|
2016-11-03 09:07:50 +00:00
|
|
|
function test_keySearch() {
|
2016-12-21 10:22:25 +00:00
|
|
|
var control = createTemporaryObject(comboBox, testCase, {model: ["Banana", "Coco", "Coconut", "Apple", "Cocomuffin"]})
|
2016-11-03 09:07:50 +00:00
|
|
|
verify(control)
|
|
|
|
|
|
|
|
control.forceActiveFocus()
|
|
|
|
verify(control.activeFocus)
|
|
|
|
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
compare(control.currentText, "Banana")
|
2018-03-12 12:07:12 +00:00
|
|
|
compare(control.highlightedIndex, -1)
|
2016-11-03 09:07:50 +00:00
|
|
|
|
|
|
|
keyPress(Qt.Key_C)
|
|
|
|
compare(control.currentIndex, 1)
|
|
|
|
compare(control.currentText, "Coco")
|
2018-03-12 12:07:12 +00:00
|
|
|
compare(control.highlightedIndex, -1)
|
2016-11-03 09:07:50 +00:00
|
|
|
|
|
|
|
// no match
|
|
|
|
keyPress(Qt.Key_N)
|
|
|
|
compare(control.currentIndex, 1)
|
|
|
|
compare(control.currentText, "Coco")
|
2018-03-12 12:07:12 +00:00
|
|
|
compare(control.highlightedIndex, -1)
|
2016-11-03 09:07:50 +00:00
|
|
|
|
|
|
|
keyPress(Qt.Key_C)
|
|
|
|
compare(control.currentIndex, 2)
|
|
|
|
compare(control.currentText, "Coconut")
|
2018-03-12 12:07:12 +00:00
|
|
|
compare(control.highlightedIndex, -1)
|
2016-11-03 09:07:50 +00:00
|
|
|
|
|
|
|
keyPress(Qt.Key_C)
|
|
|
|
compare(control.currentIndex, 4)
|
|
|
|
compare(control.currentText, "Cocomuffin")
|
2018-03-12 12:07:12 +00:00
|
|
|
compare(control.highlightedIndex, -1)
|
2016-11-03 09:07:50 +00:00
|
|
|
|
|
|
|
// wrap
|
|
|
|
keyPress(Qt.Key_C)
|
|
|
|
compare(control.currentIndex, 1)
|
|
|
|
compare(control.currentText, "Coco")
|
2018-03-12 12:07:12 +00:00
|
|
|
compare(control.highlightedIndex, -1)
|
2016-11-03 09:07:50 +00:00
|
|
|
|
|
|
|
keyPress(Qt.Key_A)
|
|
|
|
compare(control.currentIndex, 3)
|
|
|
|
compare(control.currentText, "Apple")
|
2018-03-12 12:07:12 +00:00
|
|
|
compare(control.highlightedIndex, -1)
|
2016-11-03 09:07:50 +00:00
|
|
|
|
|
|
|
keyPress(Qt.Key_B)
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
compare(control.currentText, "Banana")
|
2018-03-12 12:07:12 +00:00
|
|
|
compare(control.highlightedIndex, -1)
|
|
|
|
|
|
|
|
// popup
|
|
|
|
control.popup.open()
|
|
|
|
tryCompare(control.popup, "opened", true)
|
|
|
|
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
compare(control.highlightedIndex, 0)
|
|
|
|
|
|
|
|
keyClick(Qt.Key_C)
|
|
|
|
compare(control.highlightedIndex, 1) // "Coco"
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
|
|
|
|
// no match
|
|
|
|
keyClick(Qt.Key_N)
|
|
|
|
compare(control.highlightedIndex, 1)
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
|
|
|
|
keyClick(Qt.Key_C)
|
|
|
|
compare(control.highlightedIndex, 2) // "Coconut"
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
|
|
|
|
keyClick(Qt.Key_C)
|
|
|
|
compare(control.highlightedIndex, 4) // "Cocomuffin"
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
|
|
|
|
// wrap
|
|
|
|
keyClick(Qt.Key_C)
|
|
|
|
compare(control.highlightedIndex, 1) // "Coco"
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
|
|
|
|
keyClick(Qt.Key_B)
|
|
|
|
compare(control.highlightedIndex, 0) // "Banana"
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
|
|
|
|
keyClick(Qt.Key_A)
|
|
|
|
compare(control.highlightedIndex, 3) // "Apple"
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
|
|
|
|
verify(control.popup.visible)
|
|
|
|
|
|
|
|
// accept
|
|
|
|
keyClick(Qt.Key_Return)
|
|
|
|
tryCompare(control.popup, "visible", false)
|
|
|
|
compare(control.currentIndex, 3)
|
|
|
|
compare(control.currentText, "Apple")
|
|
|
|
compare(control.highlightedIndex, -1)
|
2016-11-03 09:07:50 +00:00
|
|
|
}
|
|
|
|
|
2016-03-18 10:34:10 +00:00
|
|
|
function test_popup() {
|
2016-12-21 10:22:25 +00:00
|
|
|
var control = createTemporaryObject(comboBox, testCase, {model: 3})
|
2015-11-26 17:02:15 +00:00
|
|
|
verify(control)
|
|
|
|
|
|
|
|
// show below
|
|
|
|
mousePress(control)
|
|
|
|
compare(control.pressed, true)
|
2015-12-08 13:26:51 +00:00
|
|
|
compare(control.popup.visible, false)
|
2015-11-26 17:02:15 +00:00
|
|
|
mouseRelease(control)
|
|
|
|
compare(control.pressed, false)
|
2015-12-08 13:26:51 +00:00
|
|
|
compare(control.popup.visible, true)
|
|
|
|
verify(control.popup.contentItem.y >= control.y)
|
2015-11-26 17:02:15 +00:00
|
|
|
|
|
|
|
// hide
|
|
|
|
mouseClick(control)
|
|
|
|
compare(control.pressed, false)
|
2015-12-19 22:00:50 +00:00
|
|
|
tryCompare(control.popup, "visible", false)
|
2015-11-26 17:02:15 +00:00
|
|
|
|
|
|
|
// show above
|
2016-03-18 10:34:10 +00:00
|
|
|
control.y = control.Window.height - control.height
|
2015-11-26 17:02:15 +00:00
|
|
|
mousePress(control)
|
|
|
|
compare(control.pressed, true)
|
2015-12-08 13:26:51 +00:00
|
|
|
compare(control.popup.visible, false)
|
2015-11-26 17:02:15 +00:00
|
|
|
mouseRelease(control)
|
|
|
|
compare(control.pressed, false)
|
2015-12-08 13:26:51 +00:00
|
|
|
compare(control.popup.visible, true)
|
|
|
|
verify(control.popup.contentItem.y < control.y)
|
2015-11-26 17:02:15 +00:00
|
|
|
|
2020-08-06 11:20:07 +00:00
|
|
|
|
|
|
|
// Account for when a transition of a scale from 0.9-1.0 that it is placed above right away and not below
|
|
|
|
// first just because there is room at the 0.9 scale
|
|
|
|
if (control.popup.enter !== null) {
|
2024-06-04 13:57:41 +00:00
|
|
|
// test only if there is a scale animation
|
|
|
|
let scaleAnimation = control.popup.enter.animations.some((animation) => {
|
|
|
|
return (animation instanceof PropertyAnimation && animation.property === "scale")
|
|
|
|
});
|
|
|
|
if (scaleAnimation) {
|
|
|
|
// hide
|
|
|
|
mouseClick(control)
|
|
|
|
compare(control.pressed, false)
|
|
|
|
tryCompare(control.popup, "visible", false)
|
|
|
|
control.y = control.Window.height - (control.popup.contentItem.height * 0.99)
|
|
|
|
var popupYSpy = createTemporaryObject(signalSpy, testCase, {target: control.popup, signalName: "yChanged"})
|
|
|
|
verify(popupYSpy.valid)
|
|
|
|
mousePress(control)
|
|
|
|
compare(control.pressed, true)
|
|
|
|
compare(control.popup.visible, false)
|
|
|
|
mouseRelease(control)
|
|
|
|
compare(control.pressed, false)
|
|
|
|
tryCompare(control.popup, "opened", true)
|
|
|
|
verify(control.popup.contentItem.y < control.y)
|
|
|
|
verify(popupYSpy.count === 1)
|
|
|
|
}
|
2020-08-06 11:20:07 +00:00
|
|
|
}
|
|
|
|
|
2021-10-20 15:28:06 +00:00
|
|
|
var leftLayoutMargin = control.background.layoutMargins === undefined ? 0 : control.popup.layoutMargins.left
|
2016-05-09 14:09:07 +00:00
|
|
|
// follow the control outside the horizontal window bounds
|
2024-07-11 09:35:02 +00:00
|
|
|
const prevX = control.popup.contentItem.parent.mapToGlobal(0, 0).x
|
2016-05-09 14:09:07 +00:00
|
|
|
control.x = -control.width / 2
|
|
|
|
compare(control.x, -control.width / 2)
|
2024-07-11 09:35:02 +00:00
|
|
|
|
|
|
|
if(control.popup.popupType === Popup.Item) {
|
|
|
|
compare(control.popup.contentItem.parent.x, -control.width / 2 + leftLayoutMargin)
|
|
|
|
} else if (control.popup.popupType === Popup.Window) {
|
|
|
|
const x = control.popup.contentItem.parent.mapToGlobal(0, 0).x
|
|
|
|
compare(x - prevX, -control.width / 2 + leftLayoutMargin)
|
|
|
|
}
|
|
|
|
|
2016-05-09 14:09:07 +00:00
|
|
|
control.x = testCase.width - control.width / 2
|
|
|
|
compare(control.x, testCase.width - control.width / 2)
|
2024-07-11 09:35:02 +00:00
|
|
|
|
|
|
|
if (control.popup.popupType === Popup.Item) {
|
|
|
|
compare(control.popup.contentItem.parent.x, testCase.width - control.width / 2 + leftLayoutMargin)
|
|
|
|
} else if (control.popup.popupType === Popup.Window) {
|
|
|
|
const x = control.popup.contentItem.parent.mapToGlobal(0, 0).x
|
|
|
|
compare(x - prevX, testCase.width - control.width / 2 + leftLayoutMargin)
|
|
|
|
}
|
2018-04-23 10:45:24 +00:00
|
|
|
|
|
|
|
// close the popup when hidden (QTBUG-67684)
|
|
|
|
control.popup.open()
|
|
|
|
tryCompare(control.popup, "opened", true)
|
|
|
|
control.visible = false
|
|
|
|
tryCompare(control.popup, "visible", false)
|
2015-11-26 17:02:15 +00:00
|
|
|
}
|
|
|
|
|
2020-10-19 09:52:42 +00:00
|
|
|
Component {
|
|
|
|
id: reopenCombo
|
|
|
|
Window {
|
|
|
|
property alias innerCombo: innerCombo
|
|
|
|
visible: true
|
|
|
|
width: 300
|
|
|
|
height: 300
|
|
|
|
ComboBox {
|
|
|
|
id: innerCombo
|
|
|
|
model: 10
|
|
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// This test checks that when reopening the combobox that it is still appears at the same y position as
|
|
|
|
// previously
|
|
|
|
function test_reopen_popup() {
|
|
|
|
var control = createTemporaryObject(reopenCombo, testCase)
|
|
|
|
verify(control)
|
|
|
|
var y = 0;
|
|
|
|
for (var i = 0; i < 2; ++i) {
|
|
|
|
tryCompare(control.innerCombo.popup, "visible", false)
|
|
|
|
control.innerCombo.y = control.height - (control.innerCombo.popup.contentItem.height * 0.99)
|
|
|
|
var popupYSpy = createTemporaryObject(signalSpy, testCase, {target: control.innerCombo.popup, signalName: "yChanged"})
|
|
|
|
verify(popupYSpy.valid)
|
|
|
|
mousePress(control.innerCombo)
|
|
|
|
compare(control.innerCombo.pressed, true)
|
|
|
|
compare(control.innerCombo.popup.visible, false)
|
|
|
|
mouseRelease(control.innerCombo)
|
|
|
|
compare(control.innerCombo.pressed, false)
|
|
|
|
compare(control.innerCombo.popup.visible, true)
|
|
|
|
if (control.innerCombo.popup.enter)
|
|
|
|
tryCompare(control.innerCombo.popup.enter, "running", false)
|
|
|
|
// Check on the second opening that it has the same y position as before
|
|
|
|
if (i !== 0) {
|
|
|
|
// y should not have changed again
|
2024-06-04 13:57:41 +00:00
|
|
|
if (StyleInfo.styleName !== "FluentWinUI3") // the popup y in FluentWinUI3 depends on the implicitHeight
|
|
|
|
verify(popupYSpy.count === 0)
|
2020-10-19 09:52:42 +00:00
|
|
|
verify(y === control.innerCombo.popup.y)
|
|
|
|
} else {
|
|
|
|
// In some cases on the initial show, y changes more than once
|
2024-07-10 12:19:58 +00:00
|
|
|
tryVerify(function(){ return popupYSpy.count >= 1 })
|
2020-10-19 09:52:42 +00:00
|
|
|
y = control.innerCombo.popup.y
|
|
|
|
mouseClick(control.innerCombo)
|
|
|
|
compare(control.innerCombo.pressed, false)
|
|
|
|
tryCompare(control.innerCombo.popup, "visible", false)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-18 10:34:10 +00:00
|
|
|
function test_mouse() {
|
2017-10-02 12:52:31 +00:00
|
|
|
var control = createTemporaryObject(comboBox, testCase, {model: 3, hoverEnabled: false})
|
2015-11-26 17:02:15 +00:00
|
|
|
verify(control)
|
|
|
|
|
2016-10-07 12:51:51 +00:00
|
|
|
var activatedSpy = signalSpy.createObject(control, {target: control, signalName: "activated"})
|
2015-11-26 17:02:15 +00:00
|
|
|
verify(activatedSpy.valid)
|
|
|
|
|
|
|
|
mouseClick(control)
|
2015-12-08 13:26:51 +00:00
|
|
|
compare(control.popup.visible, true)
|
2015-11-26 17:02:15 +00:00
|
|
|
|
2015-12-08 13:26:51 +00:00
|
|
|
var content = control.popup.contentItem
|
2015-11-26 17:02:15 +00:00
|
|
|
waitForRendering(content)
|
|
|
|
|
|
|
|
// press - move - release outside - not activated - not closed
|
|
|
|
mousePress(content)
|
|
|
|
compare(activatedSpy.count, 0)
|
|
|
|
mouseMove(content, content.width * 2)
|
|
|
|
compare(activatedSpy.count, 0)
|
|
|
|
mouseRelease(content, content.width * 2)
|
|
|
|
compare(activatedSpy.count, 0)
|
2015-12-08 13:26:51 +00:00
|
|
|
compare(control.popup.visible, true)
|
2015-11-26 17:02:15 +00:00
|
|
|
|
|
|
|
// press - move - release inside - activated - closed
|
|
|
|
mousePress(content)
|
|
|
|
compare(activatedSpy.count, 0)
|
|
|
|
mouseMove(content, content.width / 2 + 1, content.height / 2 + 1)
|
|
|
|
compare(activatedSpy.count, 0)
|
|
|
|
mouseRelease(content)
|
|
|
|
compare(activatedSpy.count, 1)
|
2015-12-19 22:00:50 +00:00
|
|
|
tryCompare(control.popup, "visible", false)
|
2015-11-26 17:02:15 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 11:39:41 +00:00
|
|
|
function test_touch() {
|
|
|
|
var control = createTemporaryObject(comboBox, testCase, {model: 3})
|
|
|
|
verify(control)
|
|
|
|
|
|
|
|
var touch = touchEvent(control)
|
|
|
|
|
|
|
|
var activatedSpy = signalSpy.createObject(control, {target: control, signalName: "activated"})
|
|
|
|
verify(activatedSpy.valid)
|
|
|
|
|
|
|
|
var highlightedSpy = signalSpy.createObject(control, {target: control, signalName: "highlighted"})
|
|
|
|
verify(highlightedSpy.valid)
|
|
|
|
|
|
|
|
touch.press(0, control).commit()
|
|
|
|
touch.release(0, control).commit()
|
|
|
|
compare(control.popup.visible, true)
|
|
|
|
|
|
|
|
var content = control.popup.contentItem
|
|
|
|
waitForRendering(content)
|
|
|
|
|
|
|
|
// press - move - release outside - not activated - not closed
|
|
|
|
touch.press(0, control).commit()
|
|
|
|
compare(activatedSpy.count, 0)
|
|
|
|
compare(highlightedSpy.count, 0)
|
|
|
|
touch.move(0, control, control.width * 2, control.height / 2).commit()
|
|
|
|
compare(activatedSpy.count, 0)
|
|
|
|
compare(highlightedSpy.count, 0)
|
|
|
|
touch.release(0, control, control.width * 2, control.height / 2).commit()
|
|
|
|
compare(activatedSpy.count, 0)
|
|
|
|
compare(highlightedSpy.count, 0)
|
|
|
|
compare(control.popup.visible, true)
|
2024-06-04 13:57:41 +00:00
|
|
|
tryCompare(control.popup, "opened", true)
|
2017-04-19 11:39:41 +00:00
|
|
|
|
|
|
|
// press - move - release inside - activated - closed
|
|
|
|
touch.press(0, content).commit()
|
|
|
|
compare(activatedSpy.count, 0)
|
|
|
|
compare(highlightedSpy.count, 0)
|
|
|
|
touch.move(0, content, content.width / 2 + 1, content.height / 2 + 1).commit()
|
|
|
|
compare(activatedSpy.count, 0)
|
|
|
|
compare(highlightedSpy.count, 0)
|
|
|
|
touch.release(0, content).commit()
|
|
|
|
compare(activatedSpy.count, 1)
|
|
|
|
compare(highlightedSpy.count, 1)
|
|
|
|
tryCompare(control.popup, "visible", false)
|
|
|
|
}
|
|
|
|
|
2016-11-04 11:54:38 +00:00
|
|
|
function test_down() {
|
2016-12-21 10:22:25 +00:00
|
|
|
var control = createTemporaryObject(comboBox, testCase, {model: 3})
|
2016-11-04 11:54:38 +00:00
|
|
|
verify(control)
|
|
|
|
|
|
|
|
// some styles position the popup over the combo button. move it out
|
|
|
|
// of the way to avoid stealing mouse presses. we want to test the
|
|
|
|
// combinations of the button being pressed and the popup being visible.
|
|
|
|
control.popup.y = control.height
|
|
|
|
|
|
|
|
var downSpy = signalSpy.createObject(control, {target: control, signalName: "downChanged"})
|
|
|
|
verify(downSpy.valid)
|
|
|
|
|
|
|
|
var pressedSpy = signalSpy.createObject(control, {target: control, signalName: "pressedChanged"})
|
|
|
|
verify(pressedSpy.valid)
|
|
|
|
|
|
|
|
mousePress(control)
|
|
|
|
compare(control.popup.visible, false)
|
|
|
|
compare(control.pressed, true)
|
|
|
|
compare(control.down, true)
|
|
|
|
compare(downSpy.count, 1)
|
|
|
|
compare(pressedSpy.count, 1)
|
|
|
|
|
|
|
|
mouseRelease(control)
|
|
|
|
compare(control.popup.visible, true)
|
|
|
|
compare(control.pressed, false)
|
|
|
|
compare(control.down, true)
|
|
|
|
compare(downSpy.count, 3)
|
|
|
|
compare(pressedSpy.count, 2)
|
2024-07-05 09:38:33 +00:00
|
|
|
tryCompare(control.popup, "y", control.height)
|
2017-04-04 08:47:50 +00:00
|
|
|
|
2016-11-04 11:54:38 +00:00
|
|
|
control.down = false
|
|
|
|
compare(control.down, false)
|
|
|
|
compare(downSpy.count, 4)
|
|
|
|
|
|
|
|
mousePress(control)
|
|
|
|
compare(control.popup.visible, true)
|
|
|
|
compare(control.pressed, true)
|
|
|
|
compare(control.down, false) // explicit false
|
|
|
|
compare(downSpy.count, 4)
|
|
|
|
compare(pressedSpy.count, 3)
|
|
|
|
|
|
|
|
control.down = undefined
|
|
|
|
compare(control.down, true)
|
|
|
|
compare(downSpy.count, 5)
|
|
|
|
|
|
|
|
mouseRelease(control)
|
|
|
|
tryCompare(control.popup, "visible", false)
|
|
|
|
compare(control.pressed, false)
|
|
|
|
compare(control.down, false)
|
|
|
|
compare(downSpy.count, 6)
|
|
|
|
compare(pressedSpy.count, 4)
|
|
|
|
|
|
|
|
control.popup.open()
|
|
|
|
compare(control.popup.visible, true)
|
|
|
|
compare(control.pressed, false)
|
|
|
|
compare(control.down, true)
|
|
|
|
compare(downSpy.count, 7)
|
|
|
|
compare(pressedSpy.count, 4)
|
|
|
|
|
|
|
|
control.popup.close()
|
|
|
|
tryCompare(control.popup, "visible", false)
|
|
|
|
compare(control.pressed, false)
|
|
|
|
compare(control.down, false)
|
|
|
|
compare(downSpy.count, 8)
|
|
|
|
compare(pressedSpy.count, 4)
|
|
|
|
}
|
|
|
|
|
2016-03-18 10:34:10 +00:00
|
|
|
function test_focus() {
|
2016-12-21 10:22:25 +00:00
|
|
|
var control = createTemporaryObject(comboBox, testCase, {model: 3})
|
2015-11-26 17:02:15 +00:00
|
|
|
verify(control)
|
|
|
|
|
2017-04-25 13:22:19 +00:00
|
|
|
var openedSpy = signalSpy.createObject(control, {target: control.popup, signalName: "opened"})
|
|
|
|
verify(openedSpy.valid)
|
|
|
|
|
|
|
|
var closedSpy = signalSpy.createObject(control, {target: control.popup, signalName: "closed"})
|
|
|
|
verify(openedSpy.valid)
|
2016-01-31 07:32:42 +00:00
|
|
|
|
2015-12-08 13:26:51 +00:00
|
|
|
// click - gain focus - show popup
|
2015-11-26 17:02:15 +00:00
|
|
|
mouseClick(control)
|
|
|
|
verify(control.activeFocus)
|
2017-04-25 13:22:19 +00:00
|
|
|
openedSpy.wait()
|
|
|
|
compare(openedSpy.count, 1)
|
2015-12-08 13:26:51 +00:00
|
|
|
compare(control.popup.visible, true)
|
2015-11-26 17:02:15 +00:00
|
|
|
|
2015-12-08 13:26:51 +00:00
|
|
|
// lose focus - hide popup
|
2016-01-31 07:32:42 +00:00
|
|
|
control.focus = false
|
2015-11-26 17:02:15 +00:00
|
|
|
verify(!control.activeFocus)
|
2017-04-25 13:22:19 +00:00
|
|
|
closedSpy.wait()
|
|
|
|
compare(closedSpy.count, 1)
|
|
|
|
compare(control.popup.visible, false)
|
2015-11-26 17:02:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function test_baseline() {
|
2016-12-21 10:22:25 +00:00
|
|
|
var control = createTemporaryObject(comboBox, testCase)
|
2015-11-26 17:02:15 +00:00
|
|
|
verify(control)
|
|
|
|
compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset)
|
|
|
|
}
|
2015-12-23 13:32:12 +00:00
|
|
|
|
|
|
|
Component {
|
|
|
|
id: displayBox
|
|
|
|
ComboBox {
|
|
|
|
textRole: "key"
|
|
|
|
model: ListModel {
|
|
|
|
ListElement { key: "First"; value: 123 }
|
|
|
|
ListElement { key: "Second"; value: 456 }
|
|
|
|
ListElement { key: "Third"; value: 789 }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_displayText() {
|
2016-12-21 10:22:25 +00:00
|
|
|
var control = createTemporaryObject(displayBox, testCase)
|
2015-12-23 13:32:12 +00:00
|
|
|
verify(control)
|
|
|
|
|
|
|
|
compare(control.displayText, "First")
|
|
|
|
control.currentIndex = 1
|
|
|
|
compare(control.displayText, "Second")
|
|
|
|
control.textRole = "value"
|
|
|
|
compare(control.displayText, "456")
|
|
|
|
control.displayText = "Display"
|
|
|
|
compare(control.displayText, "Display")
|
|
|
|
control.currentIndex = 2
|
|
|
|
compare(control.displayText, "Display")
|
|
|
|
control.displayText = undefined
|
|
|
|
compare(control.displayText, "789")
|
|
|
|
}
|
2016-02-11 12:09:48 +00:00
|
|
|
|
|
|
|
Component {
|
|
|
|
id: component
|
|
|
|
Pane {
|
|
|
|
id: panel
|
|
|
|
property alias button: _button;
|
|
|
|
property alias combobox: _combobox;
|
|
|
|
font.pixelSize: 30
|
|
|
|
Column {
|
|
|
|
Button {
|
|
|
|
id: _button
|
|
|
|
text: "Button"
|
|
|
|
font.pixelSize: 20
|
|
|
|
}
|
|
|
|
ComboBox {
|
|
|
|
id: _combobox
|
|
|
|
model: ["ComboBox", "With"]
|
|
|
|
delegate: ItemDelegate {
|
|
|
|
width: _combobox.width
|
|
|
|
text: _combobox.textRole ? (Array.isArray(_combobox.model) ? modelData[_combobox.textRole] : model[_combobox.textRole]) : modelData
|
|
|
|
objectName: "delegate"
|
|
|
|
autoExclusive: true
|
|
|
|
checked: _combobox.currentIndex === index
|
|
|
|
highlighted: _combobox.highlightedIndex === index
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function getChild(control, objname, idx) {
|
|
|
|
var index = idx
|
|
|
|
for (var i = index+1; i < control.children.length; i++)
|
|
|
|
{
|
|
|
|
if (control.children[i].objectName === objname) {
|
|
|
|
index = i
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return index
|
|
|
|
}
|
|
|
|
|
2016-03-10 16:29:29 +00:00
|
|
|
function test_font() { // QTBUG_50984, QTBUG-51696
|
2016-12-21 10:22:25 +00:00
|
|
|
var control = createTemporaryObject(component, testCase)
|
2016-02-11 12:09:48 +00:00
|
|
|
verify(control)
|
|
|
|
verify(control.button)
|
|
|
|
verify(control.combobox)
|
|
|
|
|
2022-12-20 10:54:29 +00:00
|
|
|
var expectedComboBoxFontPixelSize = 30
|
2016-02-11 12:09:48 +00:00
|
|
|
compare(control.font.pixelSize, 30)
|
|
|
|
compare(control.button.font.pixelSize, 20)
|
2021-10-20 14:07:00 +00:00
|
|
|
compare(control.combobox.font.pixelSize, expectedComboBoxFontPixelSize)
|
2016-02-11 12:09:48 +00:00
|
|
|
|
2016-03-18 10:34:10 +00:00
|
|
|
// verify(control.combobox.popup)
|
|
|
|
// var popup = control.combobox.popup
|
|
|
|
// popup.open()
|
2016-02-11 12:09:48 +00:00
|
|
|
|
2016-03-18 10:34:10 +00:00
|
|
|
// verify(popup.contentItem)
|
2016-02-11 12:09:48 +00:00
|
|
|
|
2016-03-18 10:34:10 +00:00
|
|
|
// var listview = popup.contentItem
|
|
|
|
// verify(listview.contentItem)
|
|
|
|
// waitForRendering(listview)
|
2016-02-11 12:09:48 +00:00
|
|
|
|
2016-03-18 10:34:10 +00:00
|
|
|
// var idx1 = getChild(listview.contentItem, "delegate", -1)
|
|
|
|
// compare(listview.contentItem.children[idx1].font.pixelSize, 25)
|
|
|
|
// var idx2 = getChild(listview.contentItem, "delegate", idx1)
|
|
|
|
// compare(listview.contentItem.children[idx2].font.pixelSize, 25)
|
2016-03-10 16:29:29 +00:00
|
|
|
|
2016-03-18 10:34:10 +00:00
|
|
|
// compare(listview.contentItem.children[idx1].font.pixelSize, 25)
|
|
|
|
// compare(listview.contentItem.children[idx2].font.pixelSize, 25)
|
2016-02-11 12:09:48 +00:00
|
|
|
|
|
|
|
control.font.pixelSize = control.font.pixelSize + 10
|
2022-12-20 10:54:29 +00:00
|
|
|
expectedComboBoxFontPixelSize += 10
|
2021-10-20 14:07:00 +00:00
|
|
|
compare(control.combobox.font.pixelSize, expectedComboBoxFontPixelSize)
|
2016-03-18 10:34:10 +00:00
|
|
|
// waitForRendering(listview)
|
|
|
|
// compare(listview.contentItem.children[idx1].font.pixelSize, 25)
|
|
|
|
// compare(listview.contentItem.children[idx2].font.pixelSize, 25)
|
2016-02-11 12:09:48 +00:00
|
|
|
|
|
|
|
control.combobox.font.pixelSize = control.combobox.font.pixelSize + 5
|
2022-12-20 10:54:29 +00:00
|
|
|
compare(control.combobox.font.pixelSize, 45)
|
2016-03-18 10:34:10 +00:00
|
|
|
// waitForRendering(listview)
|
2016-02-11 12:09:48 +00:00
|
|
|
|
2016-03-18 10:34:10 +00:00
|
|
|
// idx1 = getChild(listview.contentItem, "delegate", -1)
|
|
|
|
// compare(listview.contentItem.children[idx1].font.pixelSize, 25)
|
|
|
|
// idx2 = getChild(listview.contentItem, "delegate", idx1)
|
|
|
|
// compare(listview.contentItem.children[idx2].font.pixelSize, 25)
|
2016-02-11 12:09:48 +00:00
|
|
|
}
|
2016-03-03 13:19:45 +00:00
|
|
|
|
2016-03-18 10:34:10 +00:00
|
|
|
function test_wheel() {
|
2018-03-23 09:44:05 +00:00
|
|
|
var ma = createTemporaryObject(mouseArea, testCase, {width: 100, height: 100})
|
|
|
|
verify(ma)
|
|
|
|
|
|
|
|
var control = comboBox.createObject(ma, {model: 2, wheelEnabled: true})
|
2016-03-03 13:19:45 +00:00
|
|
|
verify(control)
|
|
|
|
|
|
|
|
var delta = 120
|
|
|
|
|
2018-03-23 09:44:05 +00:00
|
|
|
var spy = signalSpy.createObject(ma, {target: ma, signalName: "wheel"})
|
|
|
|
verify(spy.valid)
|
|
|
|
|
2016-03-03 13:19:45 +00:00
|
|
|
mouseWheel(control, control.width / 2, control.height / 2, -delta, -delta)
|
|
|
|
compare(control.currentIndex, 1)
|
2018-03-23 09:44:05 +00:00
|
|
|
compare(spy.count, 0) // no propagation
|
2016-03-03 13:19:45 +00:00
|
|
|
|
|
|
|
// reached bounds -> no change
|
|
|
|
mouseWheel(control, control.width / 2, control.height / 2, -delta, -delta)
|
|
|
|
compare(control.currentIndex, 1)
|
2018-03-23 09:44:05 +00:00
|
|
|
compare(spy.count, 0) // no propagation
|
2016-03-03 13:19:45 +00:00
|
|
|
|
|
|
|
mouseWheel(control, control.width / 2, control.height / 2, delta, delta)
|
|
|
|
compare(control.currentIndex, 0)
|
2018-03-23 09:44:05 +00:00
|
|
|
compare(spy.count, 0) // no propagation
|
2016-03-03 13:19:45 +00:00
|
|
|
|
|
|
|
// reached bounds -> no change
|
|
|
|
mouseWheel(control, control.width / 2, control.height / 2, delta, delta)
|
|
|
|
compare(control.currentIndex, 0)
|
2018-03-23 09:44:05 +00:00
|
|
|
compare(spy.count, 0) // no propagation
|
2016-03-03 13:19:45 +00:00
|
|
|
}
|
2016-03-08 20:52:42 +00:00
|
|
|
|
2016-03-04 15:03:14 +00:00
|
|
|
function test_activation_data() {
|
|
|
|
return [
|
|
|
|
{ tag: "open:enter", key: Qt.Key_Enter, open: true },
|
|
|
|
{ tag: "open:return", key: Qt.Key_Return, open: true },
|
|
|
|
{ tag: "closed:enter", key: Qt.Key_Enter, open: false },
|
|
|
|
{ tag: "closed:return", key: Qt.Key_Return, open: false }
|
|
|
|
]
|
|
|
|
}
|
|
|
|
|
|
|
|
// QTBUG-51645
|
|
|
|
function test_activation(data) {
|
2016-12-21 10:22:25 +00:00
|
|
|
var control = createTemporaryObject(comboBox, testCase, {currentIndex: 1, model: ["Apple", "Orange", "Banana"]})
|
2016-03-04 15:03:14 +00:00
|
|
|
verify(control)
|
|
|
|
|
|
|
|
control.forceActiveFocus()
|
|
|
|
verify(control.activeFocus)
|
|
|
|
|
2017-04-25 13:22:19 +00:00
|
|
|
if (data.open) {
|
|
|
|
var openedSpy = signalSpy.createObject(control, {target: control.popup, signalName: "opened"})
|
|
|
|
verify(openedSpy.valid)
|
|
|
|
|
2016-03-04 15:03:14 +00:00
|
|
|
keyClick(Qt.Key_Space)
|
2017-04-25 13:22:19 +00:00
|
|
|
openedSpy.wait()
|
|
|
|
compare(openedSpy.count, 1)
|
|
|
|
}
|
2016-03-04 15:03:14 +00:00
|
|
|
compare(control.popup.visible, data.open)
|
|
|
|
|
|
|
|
compare(control.currentIndex, 1)
|
|
|
|
compare(control.currentText, "Orange")
|
|
|
|
compare(control.displayText, "Orange")
|
|
|
|
|
|
|
|
keyClick(data.key)
|
|
|
|
|
|
|
|
compare(control.currentIndex, 1)
|
|
|
|
compare(control.currentText, "Orange")
|
|
|
|
compare(control.displayText, "Orange")
|
|
|
|
}
|
2016-03-23 09:44:08 +00:00
|
|
|
|
|
|
|
Component {
|
|
|
|
id: asyncLoader
|
|
|
|
Loader {
|
|
|
|
active: false
|
|
|
|
asynchronous: true
|
|
|
|
sourceComponent: ComboBox {
|
|
|
|
model: ["First", "Second", "Third"]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// QTBUG-51972
|
|
|
|
function test_async() {
|
2016-12-21 10:22:25 +00:00
|
|
|
var loader = createTemporaryObject(asyncLoader, testCase)
|
2016-03-23 09:44:08 +00:00
|
|
|
verify(loader)
|
|
|
|
|
|
|
|
loader.active = true
|
|
|
|
tryCompare(loader, "status", Loader.Ready)
|
|
|
|
verify(loader.item)
|
|
|
|
compare(loader.item.currentText, "First")
|
|
|
|
compare(loader.item.displayText, "First")
|
|
|
|
}
|
2016-04-17 17:28:17 +00:00
|
|
|
|
|
|
|
// QTBUG-52615
|
|
|
|
function test_currentIndex() {
|
2016-12-21 10:22:25 +00:00
|
|
|
var control = createTemporaryObject(comboBox, testCase, {currentIndex: -1, model: 3})
|
2016-04-17 17:28:17 +00:00
|
|
|
verify(control)
|
|
|
|
|
|
|
|
compare(control.currentIndex, -1)
|
|
|
|
}
|
2016-07-05 14:57:12 +00:00
|
|
|
|
|
|
|
ListModel {
|
|
|
|
id: resetmodel
|
|
|
|
ListElement { text: "First" }
|
|
|
|
ListElement { text: "Second" }
|
|
|
|
ListElement { text: "Third" }
|
|
|
|
}
|
|
|
|
|
|
|
|
// QTBUG-54573
|
|
|
|
function test_modelReset() {
|
2016-12-21 10:22:25 +00:00
|
|
|
var control = createTemporaryObject(comboBox, testCase, {model: resetmodel})
|
2016-07-05 14:57:12 +00:00
|
|
|
verify(control)
|
|
|
|
control.popup.open()
|
|
|
|
|
|
|
|
var listview = control.popup.contentItem
|
|
|
|
verify(listview)
|
|
|
|
|
2016-12-13 12:56:45 +00:00
|
|
|
tryCompare(listview.contentItem.children, "length", resetmodel.count + 1) // + highlight item
|
2016-07-05 14:57:12 +00:00
|
|
|
|
|
|
|
resetmodel.clear()
|
|
|
|
resetmodel.append({text: "Fourth"})
|
|
|
|
resetmodel.append({text: "Fifth"})
|
|
|
|
|
2016-12-13 12:56:45 +00:00
|
|
|
tryCompare(listview.contentItem.children, "length", resetmodel.count + 1) // + highlight item
|
2016-07-05 14:57:12 +00:00
|
|
|
}
|
2016-08-08 22:13:30 +00:00
|
|
|
|
|
|
|
// QTBUG-55118
|
|
|
|
function test_currentText() {
|
2016-12-21 10:22:25 +00:00
|
|
|
var control = createTemporaryObject(comboBox, testCase, {model: listmodel})
|
2016-08-08 22:13:30 +00:00
|
|
|
verify(control)
|
|
|
|
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
compare(control.currentText, "First")
|
|
|
|
|
|
|
|
listmodel.setProperty(0, "text", "1st")
|
|
|
|
compare(control.currentText, "1st")
|
|
|
|
|
|
|
|
control.currentIndex = 1
|
|
|
|
compare(control.currentText, "Second")
|
|
|
|
|
|
|
|
listmodel.setProperty(0, "text", "First")
|
|
|
|
compare(control.currentText, "Second")
|
|
|
|
}
|
2016-10-01 21:02:43 +00:00
|
|
|
|
|
|
|
// QTBUG-55030
|
|
|
|
function test_highlightRange() {
|
2016-12-21 10:22:25 +00:00
|
|
|
var control = createTemporaryObject(comboBox, testCase, {model: 100})
|
2016-10-01 21:02:43 +00:00
|
|
|
verify(control)
|
|
|
|
|
|
|
|
control.currentIndex = 50
|
|
|
|
compare(control.currentIndex, 50)
|
|
|
|
compare(control.highlightedIndex, -1)
|
|
|
|
|
|
|
|
var openedSpy = signalSpy.createObject(control, {target: control.popup, signalName: "opened"})
|
|
|
|
verify(openedSpy.valid)
|
|
|
|
|
|
|
|
control.popup.open()
|
|
|
|
compare(control.highlightedIndex, 50)
|
|
|
|
tryCompare(openedSpy, "count", 1)
|
|
|
|
|
|
|
|
var listview = control.popup.contentItem
|
|
|
|
verify(listview)
|
|
|
|
|
|
|
|
var first = listview.itemAt(0, listview.contentY)
|
|
|
|
verify(first)
|
|
|
|
compare(first.text, "50")
|
|
|
|
|
|
|
|
var closedSpy = signalSpy.createObject(control, {target: control.popup, signalName: "closed"})
|
|
|
|
verify(closedSpy.valid)
|
|
|
|
|
|
|
|
control.popup.close()
|
|
|
|
tryCompare(closedSpy, "count", 1)
|
|
|
|
compare(control.highlightedIndex, -1)
|
|
|
|
|
|
|
|
control.currentIndex = 99
|
|
|
|
compare(control.currentIndex, 99)
|
|
|
|
compare(control.highlightedIndex, -1)
|
|
|
|
|
|
|
|
control.popup.open()
|
|
|
|
compare(control.highlightedIndex, 99)
|
|
|
|
tryCompare(openedSpy, "count", 2)
|
2017-05-22 10:34:03 +00:00
|
|
|
tryVerify(function() { return listview.height > 0 })
|
2016-10-01 21:02:43 +00:00
|
|
|
|
|
|
|
var last = listview.itemAt(0, listview.contentY + listview.height - 1)
|
|
|
|
verify(last)
|
|
|
|
compare(last.text, "99")
|
|
|
|
|
|
|
|
openedSpy.target = null
|
|
|
|
closedSpy.target = null
|
|
|
|
}
|
2016-10-01 19:08:09 +00:00
|
|
|
|
2017-05-16 13:51:40 +00:00
|
|
|
function test_mouseHighlight() {
|
2017-06-05 09:48:40 +00:00
|
|
|
if ((Qt.platform.pluginName === "offscreen")
|
2017-12-15 10:44:26 +00:00
|
|
|
|| (Qt.platform.pluginName === "minimal"))
|
2017-06-05 09:48:40 +00:00
|
|
|
skip("Mouse highlight not functional on offscreen/minimal platforms")
|
2017-05-16 13:51:40 +00:00
|
|
|
var control = createTemporaryObject(comboBox, testCase, {model: 20})
|
|
|
|
verify(control)
|
|
|
|
|
|
|
|
compare(control.highlightedIndex, -1)
|
|
|
|
|
|
|
|
var openedSpy = signalSpy.createObject(control, {target: control.popup, signalName: "opened"})
|
|
|
|
verify(openedSpy.valid)
|
|
|
|
|
|
|
|
control.popup.open()
|
|
|
|
compare(control.highlightedIndex, 0)
|
|
|
|
tryCompare(openedSpy, "count", 1)
|
|
|
|
|
|
|
|
var listview = control.popup.contentItem
|
|
|
|
verify(listview)
|
|
|
|
waitForRendering(listview)
|
|
|
|
|
|
|
|
// hover-highlight through all visible list items one by one
|
|
|
|
var hoverIndex = -1
|
|
|
|
var prevHoverItem = null
|
|
|
|
for (var y = 0; y < listview.height; ++y) {
|
|
|
|
var hoverItem = listview.itemAt(0, listview.contentY + y)
|
|
|
|
if (!hoverItem || !hoverItem.visible || hoverItem === prevHoverItem)
|
|
|
|
continue
|
|
|
|
mouseMove(hoverItem, 0, 0)
|
|
|
|
tryCompare(control, "highlightedIndex", ++hoverIndex)
|
|
|
|
prevHoverItem = hoverItem
|
|
|
|
}
|
|
|
|
|
|
|
|
mouseMove(listview, listview.width / 2, listview.height / 2)
|
|
|
|
|
|
|
|
// wheel-highlight the rest of the items
|
|
|
|
var delta = 120
|
|
|
|
var prevWheelItem = null
|
|
|
|
while (!listview.atYEnd) {
|
|
|
|
var prevContentY = listview.contentY
|
|
|
|
mouseWheel(listview, listview.width / 2, listview.height / 2, -delta, -delta)
|
|
|
|
tryCompare(listview, "moving", false)
|
|
|
|
verify(listview.contentY > prevContentY)
|
|
|
|
|
|
|
|
var wheelItem = listview.itemAt(listview.width / 2, listview.contentY + listview.height / 2)
|
|
|
|
if (!wheelItem || !wheelItem.visible || wheelItem === prevWheelItem)
|
|
|
|
continue
|
|
|
|
|
|
|
|
tryCompare(control, "highlightedIndex", parseInt(wheelItem.text))
|
|
|
|
prevWheelItem = wheelItem
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-18 15:49:13 +00:00
|
|
|
RegularExpressionValidator {
|
2016-10-01 19:08:09 +00:00
|
|
|
id: regExpValidator
|
2020-03-18 15:49:13 +00:00
|
|
|
regularExpression: /(red|blue|green)?/
|
2016-10-01 19:08:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function test_validator() {
|
2016-12-21 10:22:25 +00:00
|
|
|
var control = createTemporaryObject(comboBox, testCase, {editable: true, validator: regExpValidator})
|
2016-10-01 19:08:09 +00:00
|
|
|
|
|
|
|
control.editText = "blu"
|
|
|
|
compare(control.acceptableInput, false)
|
|
|
|
control.editText = "blue"
|
|
|
|
compare(control.acceptableInput, true)
|
|
|
|
control.editText = "bluee"
|
|
|
|
compare(control.acceptableInput, false)
|
|
|
|
control.editText = ""
|
|
|
|
compare(control.acceptableInput, true)
|
|
|
|
control.editText = ""
|
2021-01-21 08:52:45 +00:00
|
|
|
control.contentItem.forceActiveFocus()
|
2016-10-01 19:08:09 +00:00
|
|
|
keyPress(Qt.Key_A)
|
|
|
|
compare(control.editText, "")
|
|
|
|
keyPress(Qt.Key_A)
|
|
|
|
compare(control.editText, "")
|
|
|
|
keyPress(Qt.Key_R)
|
|
|
|
compare(control.editText, "r")
|
|
|
|
keyPress(Qt.Key_A)
|
|
|
|
compare(control.editText, "r")
|
|
|
|
compare(control.acceptableInput, false)
|
|
|
|
keyPress(Qt.Key_E)
|
|
|
|
compare(control.editText, "re")
|
|
|
|
compare(control.acceptableInput, false)
|
|
|
|
keyPress(Qt.Key_D)
|
|
|
|
compare(control.editText, "red")
|
|
|
|
compare(control.acceptableInput, true)
|
|
|
|
}
|
|
|
|
|
|
|
|
Component {
|
|
|
|
id: appendFindBox
|
|
|
|
ComboBox {
|
|
|
|
editable: true
|
|
|
|
model: ListModel {
|
|
|
|
ListElement { text:"first" }
|
|
|
|
}
|
|
|
|
onAccepted: {
|
|
|
|
if (find(editText) === -1)
|
|
|
|
model.append({text: editText})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_append_find() {
|
2016-12-21 10:22:25 +00:00
|
|
|
var control = createTemporaryObject(appendFindBox, testCase)
|
2016-10-01 19:08:09 +00:00
|
|
|
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
compare(control.currentText, "first")
|
2021-01-21 08:52:45 +00:00
|
|
|
control.contentItem.forceActiveFocus()
|
2016-10-01 19:08:09 +00:00
|
|
|
compare(control.activeFocus, true)
|
|
|
|
|
|
|
|
control.selectAll()
|
|
|
|
keyPress(Qt.Key_T)
|
|
|
|
keyPress(Qt.Key_H)
|
|
|
|
keyPress(Qt.Key_I)
|
|
|
|
keyPress(Qt.Key_R)
|
|
|
|
keyPress(Qt.Key_D)
|
|
|
|
compare(control.count, 1)
|
|
|
|
compare(control.currentText, "first")
|
|
|
|
compare(control.editText, "third")
|
|
|
|
|
|
|
|
keyPress(Qt.Key_Enter)
|
|
|
|
compare(control.count, 2)
|
|
|
|
compare(control.currentIndex, 1)
|
|
|
|
compare(control.currentText, "third")
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_editable() {
|
2016-12-21 10:22:25 +00:00
|
|
|
var control = createTemporaryObject(comboBox, testCase, {editable: true, model: ["Banana", "Coco", "Coconut", "Apple", "Cocomuffin"]})
|
2016-10-01 19:08:09 +00:00
|
|
|
verify(control)
|
|
|
|
|
2021-01-21 08:52:45 +00:00
|
|
|
control.contentItem.forceActiveFocus()
|
2016-10-01 19:08:09 +00:00
|
|
|
verify(control.activeFocus)
|
|
|
|
|
|
|
|
var acceptCount = 0
|
|
|
|
|
|
|
|
var acceptSpy = signalSpy.createObject(control, {target: control, signalName: "accepted"})
|
|
|
|
verify(acceptSpy.valid)
|
|
|
|
|
|
|
|
compare(control.editText, "Banana")
|
|
|
|
compare(control.currentText, "Banana")
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
compare(acceptSpy.count, 0)
|
|
|
|
control.editText = ""
|
|
|
|
|
|
|
|
keyPress(Qt.Key_C)
|
|
|
|
compare(control.editText, "coco")
|
|
|
|
compare(control.currentText, "Banana")
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
|
|
|
|
keyPress(Qt.Key_Right)
|
|
|
|
keyPress(Qt.Key_N)
|
|
|
|
compare(control.editText, "coconut")
|
|
|
|
compare(control.currentText, "Banana")
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
|
|
|
|
keyPress(Qt.Key_Enter) // Accept
|
|
|
|
compare(control.editText, "Coconut")
|
|
|
|
compare(control.currentText, "Coconut")
|
|
|
|
compare(control.currentIndex, 2)
|
|
|
|
compare(acceptSpy.count, ++acceptCount)
|
|
|
|
|
|
|
|
keyPress(Qt.Key_Backspace)
|
|
|
|
keyPress(Qt.Key_Backspace)
|
|
|
|
keyPress(Qt.Key_Backspace)
|
|
|
|
keyPress(Qt.Key_M)
|
|
|
|
compare(control.editText, "Cocomuffin")
|
|
|
|
compare(control.currentText, "Coconut")
|
|
|
|
compare(control.currentIndex, 2)
|
|
|
|
|
|
|
|
keyPress(Qt.Key_Enter) // Accept
|
|
|
|
compare(control.editText, "Cocomuffin")
|
|
|
|
compare(control.currentText, "Cocomuffin")
|
|
|
|
compare(control.currentIndex, 4)
|
|
|
|
compare(acceptSpy.count, ++acceptCount)
|
|
|
|
|
|
|
|
keyPress(Qt.Key_Return) // Accept
|
|
|
|
compare(control.editText, "Cocomuffin")
|
|
|
|
compare(control.currentText, "Cocomuffin")
|
|
|
|
compare(control.currentIndex, 4)
|
|
|
|
compare(acceptSpy.count, ++acceptCount)
|
|
|
|
|
|
|
|
control.editText = ""
|
|
|
|
compare(control.editText, "")
|
|
|
|
compare(control.currentText, "Cocomuffin")
|
|
|
|
compare(control.currentIndex, 4)
|
|
|
|
|
|
|
|
keyPress(Qt.Key_A)
|
|
|
|
compare(control.editText, "apple")
|
|
|
|
compare(control.currentText, "Cocomuffin")
|
|
|
|
compare(control.currentIndex, 4)
|
|
|
|
|
|
|
|
keyPress(Qt.Key_Return) // Accept
|
|
|
|
compare(control.editText, "Apple")
|
|
|
|
compare(control.currentText, "Apple")
|
|
|
|
compare(control.currentIndex, 3)
|
|
|
|
compare(acceptSpy.count, ++acceptCount)
|
|
|
|
|
|
|
|
control.editText = ""
|
|
|
|
keyPress(Qt.Key_A)
|
|
|
|
keyPress(Qt.Key_B)
|
|
|
|
compare(control.editText, "ab")
|
|
|
|
compare(control.currentText, "Apple")
|
|
|
|
compare(control.currentIndex, 3)
|
|
|
|
|
|
|
|
keyPress(Qt.Key_Return) // Accept
|
|
|
|
compare(control.editText, "ab")
|
|
|
|
compare(control.currentText, "")
|
|
|
|
compare(control.currentIndex, -1)
|
|
|
|
compare(acceptSpy.count, ++acceptCount)
|
|
|
|
|
|
|
|
control.editText = ""
|
|
|
|
compare(control.editText, "")
|
|
|
|
compare(control.currentText, "")
|
|
|
|
compare(control.currentIndex, -1)
|
|
|
|
|
|
|
|
keyPress(Qt.Key_C)
|
|
|
|
keyPress(Qt.Key_Return) // Accept
|
|
|
|
compare(control.editText, "Coco")
|
|
|
|
compare(control.currentText, "Coco")
|
|
|
|
compare(control.currentIndex, 1)
|
|
|
|
compare(acceptSpy.count, ++acceptCount)
|
|
|
|
|
|
|
|
keyPress(Qt.Key_Down)
|
|
|
|
compare(control.editText, "Coconut")
|
|
|
|
compare(control.currentText, "Coconut")
|
|
|
|
compare(control.currentIndex, 2)
|
|
|
|
|
|
|
|
keyPress(Qt.Key_Up)
|
|
|
|
compare(control.editText, "Coco")
|
|
|
|
compare(control.currentText, "Coco")
|
|
|
|
compare(control.currentIndex, 1)
|
|
|
|
|
|
|
|
control.editText = ""
|
|
|
|
compare(control.editText, "")
|
|
|
|
compare(control.currentText, "Coco")
|
|
|
|
compare(control.currentIndex, 1)
|
|
|
|
|
|
|
|
keyPress(Qt.Key_C)
|
|
|
|
keyPress(Qt.Key_O)
|
|
|
|
keyPress(Qt.Key_C) // autocompletes "coco"
|
|
|
|
keyPress(Qt.Key_Backspace)
|
|
|
|
keyPress(Qt.Key_Return) // Accept "coc"
|
|
|
|
compare(control.editText, "coc")
|
|
|
|
compare(control.currentText, "")
|
|
|
|
compare(control.currentIndex, -1)
|
|
|
|
compare(acceptSpy.count, ++acceptCount)
|
|
|
|
|
|
|
|
control.editText = ""
|
|
|
|
compare(control.editText, "")
|
|
|
|
compare(control.currentText, "")
|
|
|
|
compare(control.currentIndex, -1)
|
|
|
|
|
|
|
|
keyPress(Qt.Key_C)
|
|
|
|
keyPress(Qt.Key_O)
|
|
|
|
keyPress(Qt.Key_C) // autocompletes "coc"
|
|
|
|
keyPress(Qt.Key_Space)
|
|
|
|
keyPress(Qt.Key_Return) // Accept "coc "
|
|
|
|
compare(control.editText, "coc ")
|
|
|
|
compare(control.currentText, "")
|
|
|
|
compare(control.currentIndex, -1)
|
|
|
|
compare(acceptSpy.count, ++acceptCount)
|
|
|
|
}
|
|
|
|
|
|
|
|
Component {
|
|
|
|
id: keysAttachedBox
|
|
|
|
ComboBox {
|
|
|
|
editable: true
|
|
|
|
property bool gotit: false
|
2023-06-19 20:29:50 +00:00
|
|
|
Keys.onPressed: function (event) {
|
2016-10-01 19:08:09 +00:00
|
|
|
if (!gotit && event.key === Qt.Key_B) {
|
|
|
|
gotit = true
|
|
|
|
event.accepted = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_keys_attached() {
|
2016-12-21 10:22:25 +00:00
|
|
|
var control = createTemporaryObject(keysAttachedBox, testCase)
|
2016-10-01 19:08:09 +00:00
|
|
|
verify(control)
|
|
|
|
|
2021-01-21 08:52:45 +00:00
|
|
|
control.contentItem.forceActiveFocus()
|
2016-10-01 19:08:09 +00:00
|
|
|
verify(control.activeFocus)
|
|
|
|
|
|
|
|
verify(!control.gotit)
|
|
|
|
compare(control.editText, "")
|
|
|
|
|
|
|
|
keyPress(Qt.Key_A)
|
|
|
|
verify(control.activeFocus)
|
|
|
|
verify(!control.gotit)
|
|
|
|
compare(control.editText, "a")
|
|
|
|
|
|
|
|
keyPress(Qt.Key_B)
|
|
|
|
verify(control.activeFocus)
|
|
|
|
verify(control.gotit)
|
|
|
|
compare(control.editText, "a")
|
|
|
|
|
|
|
|
keyPress(Qt.Key_B)
|
|
|
|
verify(control.activeFocus)
|
|
|
|
verify(control.gotit)
|
|
|
|
compare(control.editText, "ab")
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_minusOneIndexResetsSelection_QTBUG_35794_data() {
|
|
|
|
return [
|
|
|
|
{ tag: "editable", editable: true },
|
|
|
|
{ tag: "non-editable", editable: false }
|
|
|
|
]
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_minusOneIndexResetsSelection_QTBUG_35794(data) {
|
2016-12-21 10:22:25 +00:00
|
|
|
var control = createTemporaryObject(comboBox, testCase, {editable: data.editable, model: ["A", "B", "C"]})
|
2016-10-01 19:08:09 +00:00
|
|
|
verify(control)
|
|
|
|
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
compare(control.currentText, "A")
|
|
|
|
control.currentIndex = -1
|
|
|
|
compare(control.currentIndex, -1)
|
|
|
|
compare(control.currentText, "")
|
|
|
|
control.currentIndex = 1
|
|
|
|
compare(control.currentIndex, 1)
|
|
|
|
compare(control.currentText, "B")
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_minusOneToZeroSelection_QTBUG_38036() {
|
2016-12-21 10:22:25 +00:00
|
|
|
var control = createTemporaryObject(comboBox, testCase, {model: ["A", "B", "C"]})
|
2016-10-01 19:08:09 +00:00
|
|
|
verify(control)
|
|
|
|
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
compare(control.currentText, "A")
|
|
|
|
control.currentIndex = -1
|
|
|
|
compare(control.currentIndex, -1)
|
|
|
|
compare(control.currentText, "")
|
|
|
|
control.currentIndex = 0
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
compare(control.currentText, "A")
|
|
|
|
}
|
ComboBox: fix empty popup being shown after model is cleared
Currently, ComboBox's popup is sized vertically in this way:
implicitHeight: contentItem.implicitHeight
Adding an item to a ComboBox with an empty model and then opening
the popup results in the implicitHeight being used in the line below
(in QQuickPopupPositioner::reposition()):
QRectF rect(p->allowHorizontalMove ? p->x : popupItem->x(),
p->allowVerticalMove ? p->y : popupItem->y(),
!p->hasWidth && iw > 0 ? iw : w,
!p->hasHeight && ih > 0 ? ih : h);
An explicit height was never set on the popup, and ih (the
implicitHeight of the popupItem) is greater than 0. This is fine.
However, when a ComboBox's popup item grows large enough that it has to
be resized to fit within the window, its explicit height is set. The
problem occurs when the model is then cleared, as the implicit height
of the popup item becomes 0. So, while "!p->hasHeight" is still true,
"ih > 0" is not, and the explicit height of the popup item is used,
which is still the previous "let's fill the entire height of the
window" size.
To fix this, we bind the height of the popup to a different expression:
height: Math.min(contentItem.implicitHeight,
control.Window.height - topMargin - bottomMargin)
This ensures that the popup has a zero height when the ListView's
implicitHeight is zero (i.e the model is empty), and a height
that fits within the window in all other cases.
Ideally, we'd have a maximumHeight property that controls this, but
for 5.9, we have to fix it this way.
Task-number: QTBUG-60684
Change-Id: Ied94c79bb7b0e693be34e9c7282d991f6f704770
Reviewed-by: J-P Nurmi <jpnurmi@qt.io>
2017-05-31 15:14:49 +00:00
|
|
|
|
|
|
|
function test_emptyPopupAfterModelCleared() {
|
|
|
|
var control = createTemporaryObject(comboBox, testCase, { model: 1 })
|
|
|
|
verify(control)
|
|
|
|
compare(control.popup.implicitHeight, 0)
|
|
|
|
|
|
|
|
// Ensure that it's open so that the popup's implicitHeight changes when we increase the model count.
|
|
|
|
control.popup.open()
|
2024-06-04 13:57:41 +00:00
|
|
|
tryCompare(control.popup, "opened", true)
|
ComboBox: fix empty popup being shown after model is cleared
Currently, ComboBox's popup is sized vertically in this way:
implicitHeight: contentItem.implicitHeight
Adding an item to a ComboBox with an empty model and then opening
the popup results in the implicitHeight being used in the line below
(in QQuickPopupPositioner::reposition()):
QRectF rect(p->allowHorizontalMove ? p->x : popupItem->x(),
p->allowVerticalMove ? p->y : popupItem->y(),
!p->hasWidth && iw > 0 ? iw : w,
!p->hasHeight && ih > 0 ? ih : h);
An explicit height was never set on the popup, and ih (the
implicitHeight of the popupItem) is greater than 0. This is fine.
However, when a ComboBox's popup item grows large enough that it has to
be resized to fit within the window, its explicit height is set. The
problem occurs when the model is then cleared, as the implicit height
of the popup item becomes 0. So, while "!p->hasHeight" is still true,
"ih > 0" is not, and the explicit height of the popup item is used,
which is still the previous "let's fill the entire height of the
window" size.
To fix this, we bind the height of the popup to a different expression:
height: Math.min(contentItem.implicitHeight,
control.Window.height - topMargin - bottomMargin)
This ensures that the popup has a zero height when the ListView's
implicitHeight is zero (i.e the model is empty), and a height
that fits within the window in all other cases.
Ideally, we'd have a maximumHeight property that controls this, but
for 5.9, we have to fix it this way.
Task-number: QTBUG-60684
Change-Id: Ied94c79bb7b0e693be34e9c7282d991f6f704770
Reviewed-by: J-P Nurmi <jpnurmi@qt.io>
2017-05-31 15:14:49 +00:00
|
|
|
|
|
|
|
// Add lots of items to the model. The popup should take up the entire height of the window.
|
|
|
|
control.model = 100
|
|
|
|
compare(control.popup.height, control.Window.height - control.popup.topMargin - control.popup.bottomMargin)
|
|
|
|
|
|
|
|
control.popup.close()
|
|
|
|
|
|
|
|
// Clearing the model should result in a zero height.
|
|
|
|
control.model = 0
|
|
|
|
control.popup.open()
|
|
|
|
tryCompare(control.popup, "visible", true)
|
2024-06-04 13:57:41 +00:00
|
|
|
if (control.popup.enter !== null)
|
|
|
|
tryCompare(control.popup.enter, "running", false)
|
2017-06-06 18:40:54 +00:00
|
|
|
compare(control.popup.height, control.popup.topPadding + control.popup.bottomPadding)
|
ComboBox: fix empty popup being shown after model is cleared
Currently, ComboBox's popup is sized vertically in this way:
implicitHeight: contentItem.implicitHeight
Adding an item to a ComboBox with an empty model and then opening
the popup results in the implicitHeight being used in the line below
(in QQuickPopupPositioner::reposition()):
QRectF rect(p->allowHorizontalMove ? p->x : popupItem->x(),
p->allowVerticalMove ? p->y : popupItem->y(),
!p->hasWidth && iw > 0 ? iw : w,
!p->hasHeight && ih > 0 ? ih : h);
An explicit height was never set on the popup, and ih (the
implicitHeight of the popupItem) is greater than 0. This is fine.
However, when a ComboBox's popup item grows large enough that it has to
be resized to fit within the window, its explicit height is set. The
problem occurs when the model is then cleared, as the implicit height
of the popup item becomes 0. So, while "!p->hasHeight" is still true,
"ih > 0" is not, and the explicit height of the popup item is used,
which is still the previous "let's fill the entire height of the
window" size.
To fix this, we bind the height of the popup to a different expression:
height: Math.min(contentItem.implicitHeight,
control.Window.height - topMargin - bottomMargin)
This ensures that the popup has a zero height when the ListView's
implicitHeight is zero (i.e the model is empty), and a height
that fits within the window in all other cases.
Ideally, we'd have a maximumHeight property that controls this, but
for 5.9, we have to fix it this way.
Task-number: QTBUG-60684
Change-Id: Ied94c79bb7b0e693be34e9c7282d991f6f704770
Reviewed-by: J-P Nurmi <jpnurmi@qt.io>
2017-05-31 15:14:49 +00:00
|
|
|
}
|
2018-04-23 12:05:25 +00:00
|
|
|
|
|
|
|
Component {
|
|
|
|
id: keysMonitor
|
|
|
|
Item {
|
|
|
|
property int pressedKeys: 0
|
|
|
|
property int releasedKeys: 0
|
|
|
|
property int lastPressedKey: 0
|
|
|
|
property int lastReleasedKey: 0
|
|
|
|
property alias comboBox: comboBox
|
|
|
|
|
|
|
|
width: 200
|
|
|
|
height: 200
|
|
|
|
|
2022-02-25 07:38:53 +00:00
|
|
|
Keys.onPressed: (event) => { ++pressedKeys; lastPressedKey = event.key }
|
|
|
|
Keys.onReleased: (event) => { ++releasedKeys; lastReleasedKey = event.key }
|
2018-04-23 12:05:25 +00:00
|
|
|
|
|
|
|
ComboBox {
|
|
|
|
id: comboBox
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_keyClose_data() {
|
|
|
|
return [
|
|
|
|
{ tag: "Escape", key: Qt.Key_Escape },
|
|
|
|
{ tag: "Back", key: Qt.Key_Back }
|
|
|
|
]
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_keyClose(data) {
|
|
|
|
var container = createTemporaryObject(keysMonitor, testCase)
|
|
|
|
verify(container)
|
|
|
|
|
|
|
|
var control = comboBox.createObject(container)
|
|
|
|
verify(control)
|
|
|
|
|
|
|
|
control.forceActiveFocus()
|
|
|
|
verify(control.activeFocus)
|
|
|
|
|
|
|
|
var pressedKeys = 0
|
|
|
|
var releasedKeys = 0
|
|
|
|
|
|
|
|
// popup not visible -> propagates
|
|
|
|
keyPress(data.key)
|
|
|
|
compare(container.pressedKeys, ++pressedKeys)
|
|
|
|
compare(container.lastPressedKey, data.key)
|
|
|
|
|
|
|
|
keyRelease(data.key)
|
|
|
|
compare(container.releasedKeys, ++releasedKeys)
|
|
|
|
compare(container.lastReleasedKey, data.key)
|
|
|
|
|
|
|
|
verify(control.activeFocus)
|
|
|
|
|
|
|
|
// popup visible -> handled -> does not propagate
|
|
|
|
control.popup.open()
|
|
|
|
tryCompare(control.popup, "opened", true)
|
|
|
|
|
|
|
|
keyPress(data.key)
|
|
|
|
compare(container.pressedKeys, pressedKeys)
|
|
|
|
|
|
|
|
keyRelease(data.key)
|
|
|
|
compare(container.releasedKeys, releasedKeys)
|
|
|
|
|
|
|
|
tryCompare(control.popup, "visible", false)
|
|
|
|
verify(control.activeFocus)
|
|
|
|
|
|
|
|
// popup not visible -> propagates
|
|
|
|
keyPress(data.key)
|
|
|
|
compare(container.pressedKeys, ++pressedKeys)
|
|
|
|
compare(container.lastPressedKey, data.key)
|
|
|
|
|
|
|
|
keyRelease(data.key)
|
|
|
|
compare(container.releasedKeys, ++releasedKeys)
|
|
|
|
compare(container.lastReleasedKey, data.key)
|
|
|
|
}
|
2019-03-24 19:54:31 +00:00
|
|
|
|
|
|
|
function test_popupFocus_QTBUG_74661() {
|
|
|
|
var control = createTemporaryObject(comboBox, testCase)
|
|
|
|
verify(control)
|
|
|
|
|
|
|
|
var popup = createTemporaryObject(customPopup, testCase)
|
|
|
|
verify(popup)
|
|
|
|
|
|
|
|
control.popup = popup
|
|
|
|
|
|
|
|
var openedSpy = signalSpy.createObject(control, {target: popup, signalName: "opened"})
|
|
|
|
verify(openedSpy.valid)
|
|
|
|
|
|
|
|
var closedSpy = signalSpy.createObject(control, {target: popup, signalName: "closed"})
|
|
|
|
verify(closedSpy.valid)
|
|
|
|
|
|
|
|
control.forceActiveFocus()
|
|
|
|
verify(control.activeFocus)
|
|
|
|
|
|
|
|
// show popup
|
|
|
|
keyClick(Qt.Key_Space)
|
|
|
|
openedSpy.wait()
|
|
|
|
compare(openedSpy.count, 1)
|
|
|
|
|
|
|
|
popup.contentItem.forceActiveFocus()
|
|
|
|
verify(popup.contentItem.activeFocus)
|
|
|
|
|
|
|
|
// type something in the text field
|
|
|
|
keyClick(Qt.Key_Space)
|
|
|
|
keyClick(Qt.Key_H)
|
|
|
|
keyClick(Qt.Key_I)
|
|
|
|
compare(popup.contentItem.text, " hi")
|
|
|
|
|
|
|
|
compare(closedSpy.count, 0)
|
|
|
|
|
|
|
|
// hide popup
|
|
|
|
keyClick(Qt.Key_Escape)
|
|
|
|
closedSpy.wait()
|
|
|
|
compare(closedSpy.count, 1)
|
|
|
|
}
|
2019-05-22 13:40:06 +00:00
|
|
|
|
|
|
|
function test_comboBoxWithShaderEffect() {
|
|
|
|
var control = createTemporaryObject(comboBoxWithShaderEffect, testCase, {model: 9})
|
|
|
|
verify(control)
|
|
|
|
waitForRendering(control)
|
|
|
|
control.forceActiveFocus()
|
|
|
|
var openedSpy = signalSpy.createObject(control, {target: control.popup, signalName: "opened"})
|
|
|
|
verify(openedSpy.valid)
|
|
|
|
|
|
|
|
var closedSpy = signalSpy.createObject(control, {target: control.popup, signalName: "closed"})
|
|
|
|
verify(closedSpy.valid)
|
|
|
|
|
|
|
|
control.popup.open()
|
|
|
|
openedSpy.wait()
|
|
|
|
compare(openedSpy.count, 1)
|
|
|
|
control.popup.close()
|
|
|
|
closedSpy.wait()
|
|
|
|
compare(closedSpy.count, 1)
|
|
|
|
}
|
2019-12-11 15:38:14 +00:00
|
|
|
|
|
|
|
function test_comboBoxSelectTextByMouse() {
|
|
|
|
let control = createTemporaryObject(comboBox, testCase,
|
|
|
|
{ editable: true, selectTextByMouse: true, model: [ "Some text" ], width: parent.width })
|
|
|
|
verify(control)
|
|
|
|
waitForRendering(control)
|
|
|
|
control.forceActiveFocus()
|
|
|
|
|
|
|
|
// Position the text cursor at the beginning of the text.
|
|
|
|
mouseClick(control, control.leftPadding, control.height / 2)
|
|
|
|
// Select all of the text.
|
|
|
|
mousePress(control, control.leftPadding, control.height / 2)
|
|
|
|
mouseMove(control, control.leftPadding + control.contentItem.width, control.height / 2)
|
|
|
|
mouseRelease(control, control.leftPadding + control.contentItem.width, control.height / 2)
|
|
|
|
compare(control.contentItem.selectedText, "Some text")
|
|
|
|
}
|
2019-12-30 10:44:50 +00:00
|
|
|
|
2019-12-06 12:13:51 +00:00
|
|
|
// QTBUG-78885: When the edit text is changed on an editable ComboBox,
|
|
|
|
// and then that ComboBox loses focus, its currentIndex should change
|
|
|
|
// to the index of the edit text (assuming a match is found).
|
|
|
|
function test_currentIndexChangeOnLostFocus() {
|
2024-06-20 06:58:33 +00:00
|
|
|
if (Application.styleHints.tabFocusBehavior !== Qt.TabFocusAllControls)
|
2019-12-06 12:13:51 +00:00
|
|
|
skip("This platform only allows tab focus for text controls")
|
|
|
|
|
|
|
|
let theModel = []
|
|
|
|
for (let i = 0; i < 10; ++i)
|
|
|
|
theModel.push("Item " + (i + 1))
|
|
|
|
|
|
|
|
let comboBox1 = createTemporaryObject(comboBox, testCase,
|
|
|
|
{ objectName: "comboBox1", editable: true, model: theModel })
|
|
|
|
verify(comboBox1)
|
|
|
|
compare(comboBox1.currentIndex, 0)
|
|
|
|
|
|
|
|
let comboBox2 = createTemporaryObject(comboBox, testCase, { objectName: "comboBox2" })
|
|
|
|
verify(comboBox2)
|
|
|
|
|
|
|
|
// Give the first ComboBox focus and type in 0 to select "Item 10" (default is "Item 1").
|
|
|
|
waitForRendering(comboBox1)
|
2021-01-21 08:52:45 +00:00
|
|
|
comboBox1.contentItem.forceActiveFocus()
|
2019-12-06 12:13:51 +00:00
|
|
|
verify(comboBox1.activeFocus)
|
|
|
|
keyClick(Qt.Key_0)
|
|
|
|
compare(comboBox1.editText, "Item 10")
|
|
|
|
|
|
|
|
let currentIndexSpy = signalSpy.createObject(comboBox1,
|
|
|
|
{ target: comboBox1, signalName: "currentIndexChanged" })
|
|
|
|
verify(currentIndexSpy.valid)
|
|
|
|
|
|
|
|
// Give focus to the other ComboBox so that the first one loses it.
|
|
|
|
// The first ComboBox's currentIndex should change to that of "Item 10".
|
|
|
|
keyClick(Qt.Key_Tab)
|
|
|
|
verify(comboBox2.activeFocus)
|
|
|
|
compare(comboBox1.currentIndex, 9)
|
|
|
|
compare(currentIndexSpy.count, 1)
|
|
|
|
|
|
|
|
// Give focus back to the first ComboBox, and try the same thing except
|
|
|
|
// with non-existing text; the currentIndex should not change.
|
2021-01-21 08:52:45 +00:00
|
|
|
comboBox1.contentItem.forceActiveFocus()
|
2019-12-06 12:13:51 +00:00
|
|
|
verify(comboBox1.activeFocus)
|
|
|
|
keySequence(StandardKey.SelectAll)
|
|
|
|
compare(comboBox1.contentItem.selectedText, "Item 10")
|
|
|
|
keyClick(Qt.Key_N)
|
|
|
|
keyClick(Qt.Key_O)
|
|
|
|
keyClick(Qt.Key_P)
|
|
|
|
keyClick(Qt.Key_E)
|
|
|
|
compare(comboBox1.editText, "nope")
|
|
|
|
compare(comboBox1.currentIndex, 9)
|
|
|
|
compare(currentIndexSpy.count, 1)
|
|
|
|
}
|
2020-02-27 14:36:20 +00:00
|
|
|
|
2024-05-21 06:43:24 +00:00
|
|
|
readonly property font testFont: ({
|
|
|
|
family: "Arial",
|
|
|
|
pixelSize: 12
|
|
|
|
})
|
|
|
|
|
2020-02-27 14:36:20 +00:00
|
|
|
Component {
|
2024-05-21 06:43:24 +00:00
|
|
|
id: fixedFontTextFieldComponent
|
2020-02-27 14:36:20 +00:00
|
|
|
TextField {
|
|
|
|
objectName: "appFontTextField"
|
2024-05-21 06:43:24 +00:00
|
|
|
font: testCase.testFont
|
2020-02-27 14:36:20 +00:00
|
|
|
// We don't want the background's implicit width to interfere with our tests,
|
|
|
|
// which are about implicit width of the contentItem of ComboBox, which is by default TextField.
|
|
|
|
background: null
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Component {
|
2024-05-21 06:43:24 +00:00
|
|
|
id: fixedFontContentItemComboBoxComponent
|
2020-02-27 14:36:20 +00:00
|
|
|
ComboBox {
|
|
|
|
// Override the contentItem so that the font doesn't vary between styles.
|
|
|
|
contentItem: TextField {
|
|
|
|
objectName: "appFontContentItemTextField"
|
|
|
|
// We do this just to be extra sure that the font never comes from the control,
|
2024-05-21 06:43:24 +00:00
|
|
|
// as we want it to match that of the TextField in the fixedFontTextFieldComponent.
|
|
|
|
font: testCase.testFont
|
2020-02-27 14:36:20 +00:00
|
|
|
background: null
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Component {
|
|
|
|
id: twoItemListModelComponent
|
|
|
|
|
|
|
|
ListModel {
|
|
|
|
ListElement { display: "Short" }
|
|
|
|
ListElement { display: "Kinda long" }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function appendedToModel(model, item) {
|
|
|
|
if (Array.isArray(model)) {
|
|
|
|
let newModel = model
|
|
|
|
newModel.push(item)
|
|
|
|
return newModel
|
|
|
|
}
|
|
|
|
|
|
|
|
if (model.hasOwnProperty("append")) {
|
|
|
|
model.append({ display: item })
|
|
|
|
// To account for the fact that changes to a JS array are not seen by the QML engine,
|
|
|
|
// we need to reassign the entire model and hence return it. For simplicity in the
|
|
|
|
// calling code, we do it for the ListModel code path too. It should be a no-op.
|
|
|
|
return model
|
|
|
|
}
|
|
|
|
|
|
|
|
console.warn("appendedToModel: unrecognised model")
|
|
|
|
return undefined
|
|
|
|
}
|
|
|
|
|
|
|
|
function removedFromModel(model, index, count) {
|
|
|
|
if (Array.isArray(model)) {
|
|
|
|
let newModel = model
|
|
|
|
newModel.splice(index, count)
|
|
|
|
return newModel
|
|
|
|
}
|
|
|
|
|
|
|
|
if (model.hasOwnProperty("remove")) {
|
|
|
|
model.remove(index, count)
|
|
|
|
return model
|
|
|
|
}
|
|
|
|
|
|
|
|
console.warn("removedFromModel: unrecognised model")
|
|
|
|
return undefined
|
|
|
|
}
|
|
|
|
|
|
|
|
// We don't use a data-driven test for the policy because the checks vary a lot based on which enum we're testing.
|
|
|
|
function test_implicitContentWidthPolicy_ContentItemImplicitWidth() {
|
|
|
|
// Set ContentItemImplicitWidth and ensure that implicitContentWidth is as wide as the current item
|
|
|
|
// by comparing it against the implicitWidth of an identical TextField
|
2024-05-21 06:43:24 +00:00
|
|
|
let control = createTemporaryObject(fixedFontContentItemComboBoxComponent, testCase, {
|
2020-02-27 14:36:20 +00:00
|
|
|
model: ["Short", "Kinda long"],
|
|
|
|
implicitContentWidthPolicy: ComboBox.ContentItemImplicitWidth
|
|
|
|
})
|
|
|
|
verify(control)
|
|
|
|
compare(control.implicitContentWidthPolicy, ComboBox.ContentItemImplicitWidth)
|
|
|
|
|
2024-05-21 06:43:24 +00:00
|
|
|
let textField = createTemporaryObject(fixedFontTextFieldComponent, testCase)
|
2020-02-27 14:36:20 +00:00
|
|
|
verify(textField)
|
|
|
|
// Don't set any text on textField because we're not accounting for the widest
|
|
|
|
// text here, so we want to compare it against an empty TextField.
|
|
|
|
compare(control.implicitContentWidth, textField.implicitWidth)
|
|
|
|
|
|
|
|
textField.font.pixelSize *= 2
|
|
|
|
control.font.pixelSize *= 2
|
|
|
|
compare(control.implicitContentWidth, textField.implicitWidth)
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_implicitContentWidthPolicy_WidestText_data() {
|
|
|
|
return [
|
|
|
|
{ tag: "Array", model: ["Short", "Kinda long"] },
|
|
|
|
{ tag: "ListModel", model: twoItemListModelComponent.createObject(testCase) },
|
|
|
|
]
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_implicitContentWidthPolicy_WidestText(data) {
|
2024-05-21 06:43:24 +00:00
|
|
|
let control = createTemporaryObject(fixedFontContentItemComboBoxComponent, testCase, {
|
2020-02-27 14:36:20 +00:00
|
|
|
model: data.model,
|
|
|
|
implicitContentWidthPolicy: ComboBox.WidestText
|
|
|
|
})
|
|
|
|
verify(control)
|
|
|
|
compare(control.implicitContentWidthPolicy, ComboBox.WidestText)
|
|
|
|
|
2024-05-21 06:43:24 +00:00
|
|
|
let textField = createTemporaryObject(fixedFontTextFieldComponent, testCase)
|
2020-02-27 14:36:20 +00:00
|
|
|
verify(textField)
|
|
|
|
textField.text = "Kinda long"
|
|
|
|
// Note that we don't need to change the current index here, as the implicitContentWidth
|
|
|
|
// is set to the implicitWidth of the TextField within the ComboBox as if it had the largest
|
|
|
|
// text from the model set on it.
|
|
|
|
// We use Math.ceil because TextInput uses qCeil internally, whereas the implicitWidth
|
|
|
|
// binding for TextField does not.
|
|
|
|
compare(Math.ceil(control.implicitContentWidth), Math.ceil(textField.implicitWidth))
|
|
|
|
|
|
|
|
// Add a longer item; it should affect the implicit content width.
|
|
|
|
let modifiedModel = appendedToModel(data.model, "Moderately long")
|
|
|
|
control.model = modifiedModel
|
|
|
|
textField.text = "Moderately long"
|
|
|
|
compare(Math.ceil(control.implicitContentWidth), Math.ceil(textField.implicitWidth))
|
|
|
|
|
|
|
|
// Remove the last two items; it should use the only remaining item's width.
|
|
|
|
modifiedModel = removedFromModel(data.model, 1, 2)
|
|
|
|
control.model = modifiedModel
|
|
|
|
compare(control.count, 1)
|
|
|
|
compare(control.currentText, "Short")
|
|
|
|
textField.text = "Short"
|
|
|
|
compare(Math.ceil(control.implicitContentWidth), Math.ceil(textField.implicitWidth))
|
|
|
|
|
|
|
|
// Changes in font should result in the implicitContentWidth being updated.
|
|
|
|
textField.font.pixelSize *= 2
|
|
|
|
// We have to change the contentItem's font size manually since we break the
|
2024-05-21 06:43:24 +00:00
|
|
|
// style's binding to the control's font when we set the fixed font on it.
|
2020-02-27 14:36:20 +00:00
|
|
|
control.contentItem.font.pixelSize *= 2
|
|
|
|
control.font.pixelSize *= 2
|
|
|
|
compare(Math.ceil(control.implicitContentWidth), Math.ceil(textField.implicitWidth))
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_implicitContentWidthPolicy_WidestTextWhenCompleted_data() {
|
|
|
|
return test_implicitContentWidthPolicy_WidestText_data()
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_implicitContentWidthPolicy_WidestTextWhenCompleted(data) {
|
2024-05-21 06:43:24 +00:00
|
|
|
let control = createTemporaryObject(fixedFontContentItemComboBoxComponent, testCase, {
|
2020-02-27 14:36:20 +00:00
|
|
|
model: data.model,
|
|
|
|
implicitContentWidthPolicy: ComboBox.WidestTextWhenCompleted
|
|
|
|
})
|
|
|
|
verify(control)
|
|
|
|
compare(control.implicitContentWidthPolicy, ComboBox.WidestTextWhenCompleted)
|
|
|
|
|
2024-05-21 06:43:24 +00:00
|
|
|
let textField = createTemporaryObject(fixedFontTextFieldComponent, testCase)
|
2020-02-27 14:36:20 +00:00
|
|
|
verify(textField)
|
|
|
|
textField.text = "Kinda long"
|
|
|
|
compare(Math.ceil(control.implicitContentWidth), Math.ceil(textField.implicitWidth))
|
|
|
|
|
|
|
|
// Add a longer item; it should not affect the implicit content width
|
|
|
|
// since we've already accounted for it once.
|
|
|
|
let modifiedModel = appendedToModel(data.model, "Moderately long")
|
|
|
|
control.model = modifiedModel
|
|
|
|
compare(Math.ceil(control.implicitContentWidth), Math.ceil(textField.implicitWidth))
|
|
|
|
|
|
|
|
// Remove the last two items; it should still not affect the implicit content width.
|
|
|
|
modifiedModel = removedFromModel(data.model, 1, 2)
|
|
|
|
control.model = modifiedModel
|
|
|
|
compare(control.count, 1)
|
|
|
|
compare(control.currentText, "Short")
|
|
|
|
compare(Math.ceil(control.implicitContentWidth), Math.ceil(textField.implicitWidth))
|
|
|
|
|
|
|
|
// Changes in font should not result in the implicitContentWidth being updated.
|
|
|
|
let oldTextFieldImplicitWidth = textField.implicitWidth
|
|
|
|
// Changes in font should result in the implicitContentWidth being updated.
|
|
|
|
textField.font.pixelSize *= 2
|
|
|
|
control.contentItem.font.pixelSize *= 2
|
|
|
|
control.font.pixelSize *= 2
|
|
|
|
compare(Math.ceil(control.implicitContentWidth), Math.ceil(oldTextFieldImplicitWidth))
|
|
|
|
}
|
2021-01-21 08:52:45 +00:00
|
|
|
|
|
|
|
// QTBUG-61021: text line should not be focused by default
|
|
|
|
// It causes (e.g. on Android) showing virtual keyboard when it is not needed
|
|
|
|
function test_doNotFocusTextLineByDefault() {
|
|
|
|
var control = createTemporaryObject(comboBox, testCase)
|
|
|
|
// Focus not set after creating combobox
|
|
|
|
verify(!control.activeFocus)
|
|
|
|
verify(!control.contentItem.focus)
|
|
|
|
|
|
|
|
// After setting focus on combobox, text line should not be focused
|
|
|
|
control.forceActiveFocus()
|
|
|
|
verify(control.activeFocus)
|
|
|
|
verify(!control.contentItem.focus)
|
|
|
|
|
|
|
|
// Text line is focused after intentional setting focus on it
|
|
|
|
control.contentItem.forceActiveFocus()
|
|
|
|
verify(control.activeFocus)
|
|
|
|
verify(control.contentItem.focus)
|
|
|
|
}
|
2021-06-11 12:06:57 +00:00
|
|
|
|
|
|
|
Component {
|
|
|
|
id: intValidatorComponent
|
|
|
|
IntValidator {
|
|
|
|
bottom: 0
|
|
|
|
top: 255
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_acceptableInput_QTBUG_94307() {
|
|
|
|
let items = [
|
|
|
|
{ text: "A" },
|
|
|
|
{ text: "2" },
|
|
|
|
{ text: "3" }
|
|
|
|
]
|
|
|
|
let control = createTemporaryObject(comboBox, testCase, {model: items, editable: true})
|
|
|
|
verify(control)
|
|
|
|
|
|
|
|
verify(control.acceptableInput)
|
|
|
|
compare(control.displayText, "A")
|
|
|
|
|
|
|
|
let acceptableInputSpy = signalSpy.createObject(control, {target: control, signalName: "acceptableInputChanged"})
|
|
|
|
verify(acceptableInputSpy.valid)
|
|
|
|
|
|
|
|
let intValidator = intValidatorComponent.createObject(testCase)
|
|
|
|
verify(intValidator)
|
|
|
|
|
|
|
|
control.validator = intValidator
|
|
|
|
|
|
|
|
compare(acceptableInputSpy.count, 1)
|
|
|
|
compare(control.displayText, "A")
|
|
|
|
compare(control.acceptableInput, false)
|
|
|
|
|
|
|
|
control.currentIndex = 1
|
|
|
|
|
|
|
|
compare(acceptableInputSpy.count, 2)
|
|
|
|
compare(control.displayText, "2")
|
|
|
|
compare(control.acceptableInput, true)
|
|
|
|
}
|
2022-04-27 13:12:33 +00:00
|
|
|
|
|
|
|
function test_selectionCleared() {
|
|
|
|
const model = [
|
|
|
|
{ text: "Apple" },
|
|
|
|
{ text: "Banana" },
|
|
|
|
{ text: "Coconut" }
|
|
|
|
]
|
|
|
|
let control = createTemporaryObject(comboBox, testCase, { model: model, editable: true })
|
|
|
|
verify(control)
|
|
|
|
|
|
|
|
compare(control.displayText, "Apple")
|
|
|
|
compare(control.editText, "Apple")
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
|
|
|
|
// Give the TextField focus and select the text.
|
|
|
|
let textField = control.contentItem
|
|
|
|
textField.forceActiveFocus()
|
|
|
|
textField.selectAll()
|
|
|
|
compare(textField.selectedText, "Apple")
|
|
|
|
|
|
|
|
// Type "B" so that Banana is selected.
|
|
|
|
keyPress(Qt.Key_Shift)
|
|
|
|
keyClick(Qt.Key_B)
|
|
|
|
keyRelease(Qt.Key_Shift)
|
|
|
|
compare(control.displayText, "Apple")
|
|
|
|
expectFail("", "QTBUG-102950")
|
|
|
|
compare(control.editText, "Banana")
|
|
|
|
compare(textField.selectedText, "anana")
|
|
|
|
compare(control.currentIndex, 0)
|
|
|
|
|
|
|
|
// Select Banana by pressing enter.
|
|
|
|
keyClick(Qt.Key_Return)
|
|
|
|
compare(control.displayText, "Banana")
|
|
|
|
compare(control.editText, "Banana")
|
|
|
|
compare(textField.selectedText, "")
|
|
|
|
compare(control.currentIndex, 1)
|
|
|
|
}
|
2022-05-06 07:57:07 +00:00
|
|
|
|
2023-04-17 19:11:16 +00:00
|
|
|
// QTBUG-109721 - verify that an eaten press event for the space key
|
|
|
|
// doesn't open the popup when the key is released.
|
|
|
|
Component {
|
|
|
|
id: comboboxEatsSpace
|
|
|
|
ComboBox {
|
|
|
|
id: nonEditableComboBox
|
|
|
|
editable: false
|
|
|
|
model: ["NonEditable", "Delta", "Echo", "Foxtrot"]
|
|
|
|
Keys.onSpacePressed: (event) => event.accept
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_spacePressEaten() {
|
|
|
|
let control = createTemporaryObject(comboboxEatsSpace, testCase)
|
|
|
|
verify(control)
|
|
|
|
control.forceActiveFocus()
|
|
|
|
|
|
|
|
var visibleChangedSpy = signalSpy.createObject(control, {target: control.popup, signalName: "visibleChanged"})
|
|
|
|
verify(visibleChangedSpy.valid)
|
|
|
|
|
|
|
|
// press doesn't open
|
|
|
|
keyPress(Qt.Key_Space)
|
|
|
|
verify(!control.pressed)
|
|
|
|
compare(visibleChangedSpy.count, 0)
|
|
|
|
// neither does release
|
|
|
|
keyRelease(Qt.Key_Space)
|
|
|
|
compare(visibleChangedSpy.count, 0)
|
|
|
|
}
|
|
|
|
|
2022-05-06 07:57:07 +00:00
|
|
|
Component {
|
|
|
|
id: listOfGadgets
|
|
|
|
QtObject {
|
|
|
|
property list<rect> rects: [Qt.rect(1, 2, 3, 4), Qt.rect(5, 6, 7, 8)]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_listOfGadgetsWithRole() {
|
|
|
|
let model = listOfGadgets.createObject(testCase);
|
|
|
|
let control = createTemporaryObject(
|
|
|
|
comboBox, testCase, {model: model.rects, textRole: "width"});
|
|
|
|
verify(control);
|
|
|
|
compare(control.currentIndex, 0);
|
|
|
|
compare(control.displayText, "3");
|
|
|
|
|
|
|
|
control.currentIndex = 1;
|
|
|
|
compare(control.displayText, "7");
|
|
|
|
}
|
2023-04-26 07:14:37 +00:00
|
|
|
|
|
|
|
function test_contextObject() {
|
2023-02-28 11:27:15 +00:00
|
|
|
// We use the default delegate with required properties and pass
|
|
|
|
// an array of objects as model. This should work despite
|
|
|
|
// ComboBox setting itself as model object for the delegate.
|
|
|
|
|
|
|
|
let control = createTemporaryObject(
|
|
|
|
comboBox, testCase, {model: fruitarray, textRole: "color"});
|
|
|
|
verify(control);
|
|
|
|
compare(control.popup.contentItem.itemAtIndex(0).text, "red");
|
|
|
|
|
2023-04-26 07:14:37 +00:00
|
|
|
// Now we pass an AbstractItemModel with 2 roles. Since we use required properties
|
|
|
|
// the model object should still have the anonymous property, and it should be a
|
|
|
|
// QQmlDMAbstractItemModelData.
|
|
|
|
|
2023-02-28 11:27:15 +00:00
|
|
|
control = createTemporaryObject(comboBox, testCase, { model: fruitmodel });
|
2023-04-26 07:14:37 +00:00
|
|
|
verify(control);
|
|
|
|
for (var i = 0; i < 3; ++i)
|
|
|
|
ignoreWarning(/ComboBox\.qml\:[0-9]+\:[0-9]+\: Unable to assign QQmlDMAbstractItemModelData to QString/);
|
|
|
|
compare(control.popup.contentItem.itemAtIndex(0).text, "");
|
|
|
|
}
|
2015-11-26 17:02:15 +00:00
|
|
|
}
|