aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJ-P Nurmi <jpnurmi@theqtcompany.com>2015-11-26 18:02:15 +0100
committerJ-P Nurmi <jpnurmi@theqtcompany.com>2015-12-04 07:55:39 +0000
commit4ecb85d4468782378c091e42d5733a976a3e0307 (patch)
tree19b2dd4df95fad193ec5691a8cef1c7abb90bc27
parent7dd751c0ad4d8a4c1f4827cc9ae587f69d48807e (diff)
Add ComboBox
Change-Id: I4cfc2367db92786097a1ce66bd4b5a2f71322a2e Reviewed-by: Mitch Curtis <mitch.curtis@theqtcompany.com>
-rw-r--r--src/imports/controls/ComboBox.qml133
-rw-r--r--src/imports/controls/controls.pri1
-rw-r--r--src/imports/controls/doc/images/qtlabscontrols-combobox-background.pngbin0 -> 2903 bytes
-rw-r--r--src/imports/controls/doc/images/qtlabscontrols-combobox-contentItem.pngbin0 -> 2913 bytes
-rw-r--r--src/imports/controls/doc/images/qtlabscontrols-combobox-delegate.pngbin0 -> 5012 bytes
-rw-r--r--src/imports/controls/doc/images/qtlabscontrols-combobox-panel.pngbin0 -> 4969 bytes
-rw-r--r--src/imports/controls/doc/images/qtlabscontrols-combobox.pngbin0 -> 4993 bytes
-rw-r--r--src/imports/controls/doc/snippets/qtlabscontrols-combobox-background.qml38
-rw-r--r--src/imports/controls/doc/snippets/qtlabscontrols-combobox-contentItem.qml38
-rw-r--r--src/imports/controls/doc/snippets/qtlabscontrols-combobox-delegate.qml54
-rw-r--r--src/imports/controls/doc/snippets/qtlabscontrols-combobox-panel.qml47
-rw-r--r--src/imports/controls/doc/snippets/qtlabscontrols-combobox.qml43
-rw-r--r--src/imports/controls/doc/src/qtlabscontrols-customize.qdoc32
-rw-r--r--src/imports/controls/doc/src/qtlabscontrols-index.qdoc3
-rw-r--r--src/imports/controls/doc/src/qtlabscontrols-input.qdoc6
-rw-r--r--src/imports/controls/images/drop-indicator.pngbin0 -> 2873 bytes
-rw-r--r--src/imports/controls/images/drop-indicator@2x.pngbin0 -> 2942 bytes
-rw-r--r--src/imports/controls/images/drop-indicator@3x.pngbin0 -> 3013 bytes
-rw-r--r--src/imports/controls/images/drop-indicator@4x.pngbin0 -> 3125 bytes
-rw-r--r--src/imports/controls/material/ComboBox.qml154
-rw-r--r--src/imports/controls/material/images/drop-indicator.pngbin0 -> 342 bytes
-rw-r--r--src/imports/controls/material/images/drop-indicator@2x.pngbin0 -> 273 bytes
-rw-r--r--src/imports/controls/material/images/drop-indicator@3x.pngbin0 -> 406 bytes
-rw-r--r--src/imports/controls/material/images/drop-indicator@4x.pngbin0 -> 520 bytes
-rw-r--r--src/imports/controls/material/material.pri1
-rw-r--r--src/imports/controls/material/qquickmaterialstyle.cpp5
-rw-r--r--src/imports/controls/material/qquickmaterialstyle_p.h2
-rw-r--r--src/imports/controls/material/qtlabsmaterialstyleplugin.qrc4
-rw-r--r--src/imports/controls/qtlabscontrolsplugin.cpp1
-rw-r--r--src/imports/controls/qtlabscontrolsplugin.qrc4
-rw-r--r--src/imports/controls/universal/ComboBox.qml142
-rw-r--r--src/imports/controls/universal/images/downarrow.pngbin0 -> 200 bytes
-rw-r--r--src/imports/controls/universal/images/downarrow@2x.pngbin0 -> 263 bytes
-rw-r--r--src/imports/controls/universal/images/downarrow@3x.pngbin0 -> 329 bytes
-rw-r--r--src/imports/controls/universal/images/downarrow@4x.pngbin0 -> 358 bytes
-rw-r--r--src/imports/controls/universal/qtlabsuniversalstyleplugin.qrc4
-rw-r--r--src/imports/controls/universal/universal.pri1
-rw-r--r--src/imports/templates/qtlabstemplatesplugin.cpp2
-rw-r--r--src/templates/qquickcombobox.cpp795
-rw-r--r--src/templates/qquickcombobox_p.h146
-rw-r--r--src/templates/templates.pri2
-rw-r--r--tests/auto/controls/data/tst_combobox.qml553
-rw-r--r--tests/auto/sanity/BLACKLIST6
-rw-r--r--tests/manual/testbench/main.qml34
44 files changed, 2251 insertions, 0 deletions
diff --git a/src/imports/controls/ComboBox.qml b/src/imports/controls/ComboBox.qml
new file mode 100644
index 00000000..7f2adcb0
--- /dev/null
+++ b/src/imports/controls/ComboBox.qml
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Labs Controls module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtQuick.Window 2.2
+import Qt.labs.templates 1.0 as T
+
+T.ComboBox {
+ id: control
+
+ implicitWidth: Math.max(background ? background.implicitWidth : 0,
+ contentItem.implicitWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(background ? background.implicitHeight : 0,
+ contentItem.implicitHeight + topPadding + bottomPadding)
+ baselineOffset: contentItem.y + contentItem.baselineOffset
+
+ spacing: 8
+ padding: 6
+ leftPadding: 8
+ rightPadding: 8
+
+ //! [delegate]
+ delegate: ItemDelegate {
+ width: control.width
+ text: control.textRole ? model[control.textRole] : modelData
+ checkable: true
+ autoExclusive: true
+ checked: control.currentIndex === index
+ highlighted: control.highlightedIndex === index
+ pressed: highlighted && control.pressed
+ }
+ //! [delegate]
+
+ //! [contentItem]
+ contentItem: Text {
+ text: control.displayText
+ font: control.font
+ color: "#ffffff"
+ horizontalAlignment: Text.AlignLeft
+ verticalAlignment: Text.AlignVCenter
+ elide: Text.ElideRight
+ rightPadding: 18 + control.spacing
+ }
+ //! [contentItem]
+
+ //! [background]
+ background: Item {
+ implicitWidth: 120
+ implicitHeight: 40
+
+ Rectangle {
+ width: parent.width
+ height: parent.height
+ opacity: control.enabled ? 1.0 : 0.2
+ color: control.pressed || panel.visible ? "#585A5C" : "#353637"
+ }
+
+ Image {
+ x: parent.width - width - control.rightPadding
+ y: (parent.height - height) / 2
+ source: "qrc:/images/drop-indicator.png"
+ }
+ }
+ //! [background]
+
+ //! [panel]
+ panel: T.Panel {
+ id: popup
+ contentItem: Rectangle {
+ // TODO: Panel::anchors
+ readonly property var above: popup.visible ? control.mapToItem(null, 0, -height + 1) : Qt.point(0, 0)
+ readonly property var below: popup.visible ? control.mapToItem(null, 0, control.height - 1) : Qt.point(0, 0)
+
+ x: below.x
+ y: above.y >= 0 && below.y + height > control.Window.height ? above.y : below.y
+ width: control.width
+ height: listview.height
+
+ ListView {
+ id: listview
+ width: control.width
+ height: Math.min(200, contentHeight)
+
+ clip: true
+ model: control.delegateModel
+ currentIndex: control.highlightedIndex
+
+// ScrollIndicator.vertical: ScrollIndicator { }
+ }
+
+ Rectangle {
+ width: parent.width
+ height: parent.height
+ color: "transparent"
+ border.color: "#353637"
+ }
+ }
+ }
+ //! [panel]
+}
diff --git a/src/imports/controls/controls.pri b/src/imports/controls/controls.pri
index 78c9a1d0..63e3373e 100644
--- a/src/imports/controls/controls.pri
+++ b/src/imports/controls/controls.pri
@@ -3,6 +3,7 @@ QML_FILES = \
BusyIndicator.qml \
Button.qml \
CheckBox.qml \
+ ComboBox.qml \
Dial.qml \
Drawer.qml \
Frame.qml \
diff --git a/src/imports/controls/doc/images/qtlabscontrols-combobox-background.png b/src/imports/controls/doc/images/qtlabscontrols-combobox-background.png
new file mode 100644
index 00000000..fa296270
--- /dev/null
+++ b/src/imports/controls/doc/images/qtlabscontrols-combobox-background.png
Binary files differ
diff --git a/src/imports/controls/doc/images/qtlabscontrols-combobox-contentItem.png b/src/imports/controls/doc/images/qtlabscontrols-combobox-contentItem.png
new file mode 100644
index 00000000..9b8e8175
--- /dev/null
+++ b/src/imports/controls/doc/images/qtlabscontrols-combobox-contentItem.png
Binary files differ
diff --git a/src/imports/controls/doc/images/qtlabscontrols-combobox-delegate.png b/src/imports/controls/doc/images/qtlabscontrols-combobox-delegate.png
new file mode 100644
index 00000000..88462185
--- /dev/null
+++ b/src/imports/controls/doc/images/qtlabscontrols-combobox-delegate.png
Binary files differ
diff --git a/src/imports/controls/doc/images/qtlabscontrols-combobox-panel.png b/src/imports/controls/doc/images/qtlabscontrols-combobox-panel.png
new file mode 100644
index 00000000..0e9eacbf
--- /dev/null
+++ b/src/imports/controls/doc/images/qtlabscontrols-combobox-panel.png
Binary files differ
diff --git a/src/imports/controls/doc/images/qtlabscontrols-combobox.png b/src/imports/controls/doc/images/qtlabscontrols-combobox.png
new file mode 100644
index 00000000..69fc9c95
--- /dev/null
+++ b/src/imports/controls/doc/images/qtlabscontrols-combobox.png
Binary files differ
diff --git a/src/imports/controls/doc/snippets/qtlabscontrols-combobox-background.qml b/src/imports/controls/doc/snippets/qtlabscontrols-combobox-background.qml
new file mode 100644
index 00000000..d6715f07
--- /dev/null
+++ b/src/imports/controls/doc/snippets/qtlabscontrols-combobox-background.qml
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import Qt.labs.controls 1.0
+
+ComboBox {
+ model: ["ComboBox"]
+ Rectangle {
+ anchors.fill: background
+ color: 'transparent'
+ border.color: 'red'
+ }
+}
diff --git a/src/imports/controls/doc/snippets/qtlabscontrols-combobox-contentItem.qml b/src/imports/controls/doc/snippets/qtlabscontrols-combobox-contentItem.qml
new file mode 100644
index 00000000..08523088
--- /dev/null
+++ b/src/imports/controls/doc/snippets/qtlabscontrols-combobox-contentItem.qml
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import Qt.labs.controls 1.0
+
+ComboBox {
+ model: ["ComboBox"]
+ Rectangle {
+ anchors.fill: contentItem
+ color: 'transparent'
+ border.color: 'red'
+ }
+}
diff --git a/src/imports/controls/doc/snippets/qtlabscontrols-combobox-delegate.qml b/src/imports/controls/doc/snippets/qtlabscontrols-combobox-delegate.qml
new file mode 100644
index 00000000..47c4f606
--- /dev/null
+++ b/src/imports/controls/doc/snippets/qtlabscontrols-combobox-delegate.qml
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import Qt.labs.controls 1.0
+
+Item {
+ id: root
+ width: combo.width
+ height: combo.height + combo.panel.contentItem.height
+ ComboBox {
+ id: combo
+ model: ["First", "Second", "Third"]
+ panel.contentItem.parent: root
+ panel.contentItem.y: combo.height
+ delegate: ItemDelegate {
+ width: combo.width
+ text: modelData
+ checkable: true
+ autoExclusive: true
+ checked: combo.currentIndex === index
+ Rectangle {
+ visible: index === 0
+ anchors.fill: parent
+ color: 'transparent'
+ border.color: 'red'
+ }
+ }
+ }
+}
diff --git a/src/imports/controls/doc/snippets/qtlabscontrols-combobox-panel.qml b/src/imports/controls/doc/snippets/qtlabscontrols-combobox-panel.qml
new file mode 100644
index 00000000..d1788d55
--- /dev/null
+++ b/src/imports/controls/doc/snippets/qtlabscontrols-combobox-panel.qml
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import Qt.labs.controls 1.0
+
+Item {
+ id: root
+ width: combo.width
+ height: combo.height + combo.panel.contentItem.height
+ ComboBox {
+ id: combo
+ model: ["First", "Second", "Third"]
+ panel.contentItem.parent: root
+ panel.contentItem.y: combo.height
+ }
+ Rectangle {
+ parent: combo.panel.contentItem
+ anchors.fill: parent
+ color: 'transparent'
+ border.color: 'red'
+ }
+}
diff --git a/src/imports/controls/doc/snippets/qtlabscontrols-combobox.qml b/src/imports/controls/doc/snippets/qtlabscontrols-combobox.qml
new file mode 100644
index 00000000..bac6136d
--- /dev/null
+++ b/src/imports/controls/doc/snippets/qtlabscontrols-combobox.qml
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import Qt.labs.controls 1.0
+
+Item {
+ id: root
+ width: combo.width
+ height: combo.height + combo.panel.contentItem.height
+ //! [1]
+ ComboBox {
+ id: combo
+ model: ["First", "Second", "Third"]
+ panel.contentItem.parent: root
+ panel.contentItem.y: combo.height
+ }
+ //! [1]
+}
diff --git a/src/imports/controls/doc/src/qtlabscontrols-customize.qdoc b/src/imports/controls/doc/src/qtlabscontrols-customize.qdoc
index a7bd7d8b..eb1dc71d 100644
--- a/src/imports/controls/doc/src/qtlabscontrols-customize.qdoc
+++ b/src/imports/controls/doc/src/qtlabscontrols-customize.qdoc
@@ -95,6 +95,38 @@
\snippet CheckBox.qml indicator
+
+ \section1 Customizing ComboBox
+
+ ComboBox consists of \l {Control::background}{background},
+ \l {Control::contentItem}{content item}, \l {ComboBox::panel}{panel},
+ and \l {ComboBox::delegate}{delegate}.
+
+ \section3 Background
+
+ \image qtlabscontrols-combobox-background.png
+
+ \snippet ComboBox.qml background
+
+ \section3 Content item
+
+ \image qtlabscontrols-combobox-contentItem.png
+
+ \snippet ComboBox.qml contentItem
+
+ \section3 Panel
+
+ \image qtlabscontrols-combobox-panel.png
+
+ \snippet ComboBox.qml panel
+
+ \section3 Delegate
+
+ \image qtlabscontrols-combobox-delegate.png
+
+ \snippet ComboBox.qml delegate
+
+
\section1 Customizing Dial
Dial consists of two visual items: \l {Control::background}{background}
diff --git a/src/imports/controls/doc/src/qtlabscontrols-index.qdoc b/src/imports/controls/doc/src/qtlabscontrols-index.qdoc
index 936e65e8..6e486ff0 100644
--- a/src/imports/controls/doc/src/qtlabscontrols-index.qdoc
+++ b/src/imports/controls/doc/src/qtlabscontrols-index.qdoc
@@ -219,6 +219,9 @@
\li \l [QtQuickControls] {CheckBox}
\li \l [QtLabsControls] {CheckBox}
\row
+ \li \l [QtQuickControls] {ComboBox}
+ \li \l [QtLabsControls] {ComboBox}
+ \row
\li \l [QtQuickControls] {ExclusiveGroup}
\li \l [QtLabsControls] {ButtonGroup}
\row
diff --git a/src/imports/controls/doc/src/qtlabscontrols-input.qdoc b/src/imports/controls/doc/src/qtlabscontrols-input.qdoc
index 130ca83d..06c0b40d 100644
--- a/src/imports/controls/doc/src/qtlabscontrols-input.qdoc
+++ b/src/imports/controls/doc/src/qtlabscontrols-input.qdoc
@@ -38,6 +38,12 @@
following sections offer guidelines for choosing the appropriate type
of input control, depending on the use case.
+ \section1 ComboBox Control
+
+ \image qtlabscontrols-combobox.png
+
+ \l ComboBox is used to select a value from a drop-down list.
+
\section1 Dial Control
\image qtlabscontrols-dial.png
diff --git a/src/imports/controls/images/drop-indicator.png b/src/imports/controls/images/drop-indicator.png
new file mode 100644
index 00000000..77359311
--- /dev/null
+++ b/src/imports/controls/images/drop-indicator.png
Binary files differ
diff --git a/src/imports/controls/images/drop-indicator@2x.png b/src/imports/controls/images/drop-indicator@2x.png
new file mode 100644
index 00000000..54d23b4b
--- /dev/null
+++ b/src/imports/controls/images/drop-indicator@2x.png
Binary files differ
diff --git a/src/imports/controls/images/drop-indicator@3x.png b/src/imports/controls/images/drop-indicator@3x.png
new file mode 100644
index 00000000..22c6d010
--- /dev/null
+++ b/src/imports/controls/images/drop-indicator@3x.png
Binary files differ
diff --git a/src/imports/controls/images/drop-indicator@4x.png b/src/imports/controls/images/drop-indicator@4x.png
new file mode 100644
index 00000000..7ab1eb86
--- /dev/null
+++ b/src/imports/controls/images/drop-indicator@4x.png
Binary files differ
diff --git a/src/imports/controls/material/ComboBox.qml b/src/imports/controls/material/ComboBox.qml
new file mode 100644
index 00000000..035863f6
--- /dev/null
+++ b/src/imports/controls/material/ComboBox.qml
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Labs Controls module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtQuick.Window 2.2
+import Qt.labs.templates 1.0 as T
+import Qt.labs.controls.material 1.0
+import QtGraphicalEffects 1.0
+
+T.ComboBox {
+ id: control
+
+ implicitWidth: Math.max(background ? background.implicitWidth : 0,
+ contentItem.implicitWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(background ? background.implicitHeight : 0,
+ contentItem.implicitHeight + topPadding + bottomPadding)
+ baselineOffset: contentItem.y + contentItem.baselineOffset
+
+ spacing: 6
+ padding: 12
+
+ //! [delegate]
+ delegate: ItemDelegate {
+ width: control.width
+ text: control.textRole ? model[control.textRole] : modelData
+ highlighted: control.highlightedIndex === index
+ pressed: highlighted && control.pressed
+ }
+ //! [delegate]
+
+ //! [contentItem]
+ contentItem: Text {
+ text: control.displayText
+ font: control.font
+ color: control.enabled ? control.Material.primaryTextColor : control.Material.hintTextColor
+ horizontalAlignment: Text.AlignLeft
+ verticalAlignment: Text.AlignVCenter
+ elide: Text.ElideRight
+ rightPadding: 14 + control.spacing
+ }
+ //! [contentItem]
+
+ //! [background]
+ background: Rectangle {
+ implicitWidth: 120
+ implicitHeight: 32
+
+ radius: 2
+ color: control.Material.comboBoxColor
+
+ Behavior on color {
+ ColorAnimation {
+ duration: 400
+ }
+ }
+
+ layer.enabled: control.enabled
+ layer.effect: DropShadow {
+ verticalOffset: 1
+ color: control.Material.dropShadowColor
+ samples: control.pressed ? 15 : 9
+ spread: 0.5
+
+ // TODO: Doesn't work because of QTBUG-49072
+ Behavior on radius {
+ NumberAnimation { duration: 1000 }
+ }
+ }
+
+ Image {
+ x: parent.width - width - control.rightPadding
+ y: (parent.height - height) / 2
+ opacity: !control.enabled ? 0.5 : 1.0
+ source: "qrc:/qt-project.org/imports/Qt/labs/controls/material/images/drop-indicator.png"
+ }
+ }
+ //! [background]
+
+ //! [panel]
+ panel: T.Panel {
+ id: popup
+ contentItem: Rectangle {
+ // TODO: Panel::anchors
+ readonly property var above: popup.visible ? control.mapToItem(null, 0, -height) : Qt.point(0, 0)
+ readonly property var below: popup.visible ? control.mapToItem(null, 0, control.height) : Qt.point(0, 0)
+
+ x: below.x
+ y: above.y >= 0 && below.y + height > control.Window.height ? above.y : below.y
+ width: control.width
+ height: listview.height
+
+ color: control.Material.comboBoxColor
+
+ layer.enabled: control.enabled
+ layer.effect: DropShadow {
+ verticalOffset: 1
+ color: control.Material.dropShadowColor
+ samples: 15
+ spread: 0.5
+
+ // TODO: Doesn't work because of QTBUG-49072
+ Behavior on radius {
+ NumberAnimation { duration: 1000 }
+ }
+ }
+
+ ListView {
+ id: listview
+ width: control.width
+ height: Math.min(200, contentHeight) // TODO: 396
+
+ clip: true
+ model: control.delegateModel
+ currentIndex: control.highlightedIndex
+
+// ScrollIndicator.vertical: ScrollIndicator { }
+ }
+ }
+ }
+ //! [panel]
+}
diff --git a/src/imports/controls/material/images/drop-indicator.png b/src/imports/controls/material/images/drop-indicator.png
new file mode 100644
index 00000000..b4396ec6
--- /dev/null
+++ b/src/imports/controls/material/images/drop-indicator.png
Binary files differ
diff --git a/src/imports/controls/material/images/drop-indicator@2x.png b/src/imports/controls/material/images/drop-indicator@2x.png
new file mode 100644
index 00000000..1c711bc2
--- /dev/null
+++ b/src/imports/controls/material/images/drop-indicator@2x.png
Binary files differ
diff --git a/src/imports/controls/material/images/drop-indicator@3x.png b/src/imports/controls/material/images/drop-indicator@3x.png
new file mode 100644
index 00000000..06dd8bd2
--- /dev/null
+++ b/src/imports/controls/material/images/drop-indicator@3x.png
Binary files differ
diff --git a/src/imports/controls/material/images/drop-indicator@4x.png b/src/imports/controls/material/images/drop-indicator@4x.png
new file mode 100644
index 00000000..b2157c30
--- /dev/null
+++ b/src/imports/controls/material/images/drop-indicator@4x.png
Binary files differ
diff --git a/src/imports/controls/material/material.pri b/src/imports/controls/material/material.pri
index a238dcfe..1c71b9fa 100644
--- a/src/imports/controls/material/material.pri
+++ b/src/imports/controls/material/material.pri
@@ -13,6 +13,7 @@ QML_FILES += \
$$PWD/BusyIndicator.qml \
$$PWD/Button.qml \
$$PWD/CheckBox.qml \
+ $$PWD/ComboBox.qml \
$$PWD/Dial.qml \
$$PWD/Drawer.qml \
$$PWD/Frame.qml \
diff --git a/src/imports/controls/material/qquickmaterialstyle.cpp b/src/imports/controls/material/qquickmaterialstyle.cpp
index a3d2329a..bce5db21 100644
--- a/src/imports/controls/material/qquickmaterialstyle.cpp
+++ b/src/imports/controls/material/qquickmaterialstyle.cpp
@@ -724,6 +724,11 @@ QColor QQuickMaterialStyle::drawerBackgroundColor() const
return dividerTextColorLight;
}
+QColor QQuickMaterialStyle::comboBoxColor() const
+{
+ return m_theme == Light ? "#ffffff" : backgroundColorDark;
+}
+
QColor QQuickMaterialStyle::color(QQuickMaterialStyle::Color color, QQuickMaterialStyle::Shade shade) const
{
int count = sizeof(colors) / sizeof(colors[0]);
diff --git a/src/imports/controls/material/qquickmaterialstyle_p.h b/src/imports/controls/material/qquickmaterialstyle_p.h
index 69891b9c..e657fd57 100644
--- a/src/imports/controls/material/qquickmaterialstyle_p.h
+++ b/src/imports/controls/material/qquickmaterialstyle_p.h
@@ -92,6 +92,7 @@ class QQuickMaterialStyle : public QQuickStyle
Q_PROPERTY(QColor scrollBarColor READ scrollBarColor NOTIFY paletteChanged FINAL)
Q_PROPERTY(QColor scrollBarPressedColor READ scrollBarPressedColor NOTIFY paletteChanged FINAL)
Q_PROPERTY(QColor drawerBackgroundColor READ drawerBackgroundColor NOTIFY paletteChanged FINAL)
+ Q_PROPERTY(QColor comboBoxColor READ comboBoxColor NOTIFY paletteChanged FINAL)
public:
enum Theme {
@@ -199,6 +200,7 @@ public:
QColor scrollBarColor() const;
QColor scrollBarPressedColor() const;
QColor drawerBackgroundColor() const;
+ QColor comboBoxColor() const;
Q_INVOKABLE QColor color(Color color, Shade shade) const;
diff --git a/src/imports/controls/material/qtlabsmaterialstyleplugin.qrc b/src/imports/controls/material/qtlabsmaterialstyleplugin.qrc
index 6c7b65f1..8398d505 100644
--- a/src/imports/controls/material/qtlabsmaterialstyleplugin.qrc
+++ b/src/imports/controls/material/qtlabsmaterialstyleplugin.qrc
@@ -4,5 +4,9 @@
<file>images/check@2x.png</file>
<file>images/check@3x.png</file>
<file>images/check@4x.png</file>
+ <file>images/drop-indicator.png</file>
+ <file>images/drop-indicator@2x.png</file>
+ <file>images/drop-indicator@3x.png</file>
+ <file>images/drop-indicator@4x.png</file>
</qresource>
</RCC>
diff --git a/src/imports/controls/qtlabscontrolsplugin.cpp b/src/imports/controls/qtlabscontrolsplugin.cpp
index 079d843d..2d71284e 100644
--- a/src/imports/controls/qtlabscontrolsplugin.cpp
+++ b/src/imports/controls/qtlabscontrolsplugin.cpp
@@ -71,6 +71,7 @@ void QtLabsControlsPlugin::registerTypes(const char *uri)
qmlRegisterType(selector->select(QStringLiteral("/BusyIndicator.qml")), uri, 1, 0, "BusyIndicator");
qmlRegisterType(selector->select(QStringLiteral("/Button.qml")), uri, 1, 0, "Button");
qmlRegisterType(selector->select(QStringLiteral("/CheckBox.qml")), uri, 1, 0, "CheckBox");
+ qmlRegisterType(selector->select(QStringLiteral("/ComboBox.qml")), uri, 1, 0, "ComboBox");
qmlRegisterType(selector->select(QStringLiteral("/Dial.qml")), uri, 1, 0, "Dial");
qmlRegisterType(selector->select(QStringLiteral("/Drawer.qml")), uri, 1, 0, "Drawer");
qmlRegisterType(selector->select(QStringLiteral("/Frame.qml")), uri, 1, 0, "Frame");
diff --git a/src/imports/controls/qtlabscontrolsplugin.qrc b/src/imports/controls/qtlabscontrolsplugin.qrc
index c54083ed..bebbe570 100644
--- a/src/imports/controls/qtlabscontrolsplugin.qrc
+++ b/src/imports/controls/qtlabscontrolsplugin.qrc
@@ -11,5 +11,9 @@
<file>images/dial-indicator@2x.png</file>
<file>images/dial-indicator@3x.png</file>
<file>images/dial-indicator@4x.png</file>
+ <file>images/drop-indicator.png</file>
+ <file>images/drop-indicator@2x.png</file>
+ <file>images/drop-indicator@3x.png</file>
+ <file>images/drop-indicator@4x.png</file>
</qresource>
</RCC>
diff --git a/src/imports/controls/universal/ComboBox.qml b/src/imports/controls/universal/ComboBox.qml
new file mode 100644
index 00000000..0fdcb894
--- /dev/null
+++ b/src/imports/controls/universal/ComboBox.qml
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Labs Controls module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtQuick.Window 2.2
+import Qt.labs.templates 1.0 as T
+import Qt.labs.controls.universal 1.0
+
+T.ComboBox {
+ id: control
+
+ implicitWidth: Math.max(background ? background.implicitWidth : 0,
+ contentItem.implicitWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(background ? background.implicitHeight : 0,
+ contentItem.implicitHeight + topPadding + bottomPadding)
+ baselineOffset: contentItem.y + contentItem.baselineOffset
+
+ spacing: 10
+ topPadding: 5
+ leftPadding: 12
+ rightPadding: 10
+ bottomPadding: 7
+
+ font.pixelSize: Universal.fontSize
+ font.family: Universal.fontFamily
+
+ //! [delegate]
+ delegate: ItemDelegate {
+ width: control.width
+ text: control.textRole ? model[control.textRole] : modelData
+ highlighted: control.highlightedIndex === index
+ pressed: highlighted && control.pressed
+ }
+ //! [delegate]
+
+ //! [contentItem]
+ contentItem: Text {
+ text: control.displayText
+ font: control.font
+ color: !control.enabled ? control.Universal.baseLowColor : control.Universal.baseHighColor
+ horizontalAlignment: Text.AlignLeft
+ verticalAlignment: Text.AlignVCenter
+ renderType: Text.NativeRendering
+ elide: Text.ElideRight
+ rightPadding: 12 + control.spacing
+ }
+ //! [contentItem]
+
+ //! [background]
+ background: Rectangle {
+ implicitWidth: 120
+ implicitHeight: 32
+
+ border.width: 2 // ComboBoxBorderThemeThickness
+ border.color: !control.enabled ? control.Universal.baseLowColor :
+ control.pressed || panel.visible ? control.Universal.baseMediumLowColor : control.Universal.baseMediumLowColor
+ color: !control.enabled ? control.Universal.baseLowColor :
+ control.pressed || panel.visible ? control.Universal.listMediumColor : control.Universal.altMediumLowColor
+
+ Rectangle {
+ x: 2
+ y: 2
+ width: parent.width - 4
+ height: parent.height - 4
+
+ visible: control.activeFocus
+ color: control.Universal.accentColor
+ opacity: control.Universal.theme === Universal.Light ? 0.4 : 0.6
+ }
+
+ Image {
+ id: checkmark
+ x: parent.width - width - control.rightPadding
+ y: (parent.height - height) / 2
+ source: "image://universal/downarrow/" + (!control.enabled ? control.Universal.baseLowColor : control.Universal.baseMediumHighColor)
+ }
+ }
+ //! [background]
+
+ //! [panel]
+ panel: T.Panel {
+ id: popup
+ contentItem: Rectangle {
+ // TODO: Panel::anchors
+ readonly property var above: popup.visible ? control.mapToItem(null, 0, control.height - height) : Qt.point(0, 0)
+ readonly property var below: popup.visible ? control.mapToItem(null, 0, 0) : Qt.point(0, 0)
+
+ x: below.x
+ y: above.y >= 0 && below.y + height > control.Window.height ? above.y : below.y
+ width: control.width
+ height: listview.height
+
+ color: control.Universal.chromeMediumLowColor
+
+ ListView {
+ id: listview
+ width: control.width
+ height: Math.min(200, contentHeight) // TODO: 396
+
+ clip: true
+ model: control.delegateModel
+ currentIndex: control.highlightedIndex
+
+// ScrollIndicator.vertical: ScrollIndicator { }
+ }
+ }
+ }
+ //! [panel]
+}
diff --git a/src/imports/controls/universal/images/downarrow.png b/src/imports/controls/universal/images/downarrow.png
new file mode 100644
index 00000000..fef7b0f2
--- /dev/null
+++ b/src/imports/controls/universal/images/downarrow.png
Binary files differ
diff --git a/src/imports/controls/universal/images/downarrow@2x.png b/src/imports/controls/universal/images/downarrow@2x.png
new file mode 100644
index 00000000..eabf658a
--- /dev/null
+++ b/src/imports/controls/universal/images/downarrow@2x.png
Binary files differ
diff --git a/src/imports/controls/universal/images/downarrow@3x.png b/src/imports/controls/universal/images/downarrow@3x.png
new file mode 100644
index 00000000..f9d39a2c
--- /dev/null
+++ b/src/imports/controls/universal/images/downarrow@3x.png
Binary files differ
diff --git a/src/imports/controls/universal/images/downarrow@4x.png b/src/imports/controls/universal/images/downarrow@4x.png
new file mode 100644
index 00000000..b252b588
--- /dev/null
+++ b/src/imports/controls/universal/images/downarrow@4x.png
Binary files differ
diff --git a/src/imports/controls/universal/qtlabsuniversalstyleplugin.qrc b/src/imports/controls/universal/qtlabsuniversalstyleplugin.qrc
index 6cd57f89..5edda119 100644
--- a/src/imports/controls/universal/qtlabsuniversalstyleplugin.qrc
+++ b/src/imports/controls/universal/qtlabsuniversalstyleplugin.qrc
@@ -4,6 +4,10 @@
<file>images/checkmark@2x.png</file>
<file>images/checkmark@3x.png</file>
<file>images/checkmark@4x.png</file>
+ <file>images/downarrow.png</file>
+ <file>images/downarrow@2x.png</file>
+ <file>images/downarrow@3x.png</file>
+ <file>images/downarrow@4x.png</file>
<file>images/leftarrow.png</file>
<file>images/leftarrow@2x.png</file>
<file>images/leftarrow@3x.png</file>
diff --git a/src/imports/controls/universal/universal.pri b/src/imports/controls/universal/universal.pri
index 4865e499..7348ac84 100644
--- a/src/imports/controls/universal/universal.pri
+++ b/src/imports/controls/universal/universal.pri
@@ -3,6 +3,7 @@ QML_FILES += \
$$PWD/BusyIndicator.qml \
$$PWD/Button.qml \
$$PWD/CheckBox.qml \
+ $$PWD/ComboBox.qml \
$$PWD/Dial.qml \
$$PWD/Frame.qml \
$$PWD/GroupBox.qml \
diff --git a/src/imports/templates/qtlabstemplatesplugin.cpp b/src/imports/templates/qtlabstemplatesplugin.cpp
index 721e4cab..5e4877f8 100644
--- a/src/imports/templates/qtlabstemplatesplugin.cpp
+++ b/src/imports/templates/qtlabstemplatesplugin.cpp
@@ -41,6 +41,7 @@
#include <QtLabsTemplates/private/qquickbusyindicator_p.h>
#include <QtLabsTemplates/private/qquickbutton_p.h>
#include <QtLabsTemplates/private/qquickcheckbox_p.h>
+#include <QtLabsTemplates/private/qquickcombobox_p.h>
#include <QtLabsTemplates/private/qquickcontrol_p.h>
#include <QtLabsTemplates/private/qquickcontainer_p.h>
#include <QtLabsTemplates/private/qquickdial_p.h>
@@ -90,6 +91,7 @@ void QtLabsTemplatesPlugin::registerTypes(const char *uri)
qmlRegisterType<QQuickBusyIndicator>(uri, 1, 0, "BusyIndicator");
qmlRegisterType<QQuickButton>(uri, 1, 0, "Button");
qmlRegisterType<QQuickCheckBox>(uri, 1, 0, "CheckBox");
+ qmlRegisterType<QQuickComboBox>(uri, 1, 0, "ComboBox");
qmlRegisterType<QQuickContainer>(uri, 1, 0, "Container");
qmlRegisterType<QQuickControl>(uri, 1, 0, "Control");
qmlRegisterType<QQuickDial>(uri, 1, 0, "Dial");
diff --git a/src/templates/qquickcombobox.cpp b/src/templates/qquickcombobox.cpp
new file mode 100644
index 00000000..0f56567e
--- /dev/null
+++ b/src/templates/qquickcombobox.cpp
@@ -0,0 +1,795 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Labs Templates module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickcombobox_p.h"
+#include "qquickcontrol_p_p.h"
+#include "qquickabstractbutton_p.h"
+#include "qquickpanel_p.h"
+
+#include <QtCore/qregexp.h>
+#include <QtQml/qjsvalue.h>
+#include <QtQml/qqmlcontext.h>
+#include <QtQml/private/qqmldelegatemodel_p.h>
+#include <QtQuick/private/qquickevents_p_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype ComboBox
+ \inherits Control
+ \instantiates QQuickComboBox
+ \inqmlmodule Qt.labs.controls
+ \ingroup qtlabscontrols-input
+ \brief A combo box control.
+
+ \image qtlabscontrols-combobox.png
+
+ ComboBox is a combined button and popup list. It provides a means of
+ presenting a list of options to the user in a way that takes up the
+ minimum amount of screen space.
+
+ ComboBox is populated with a data model. The data model is commonly
+ a JavaScript array, a \l ListModel or an integer, but also other types
+ of \l {qml-data-models}{data models} are supported.
+
+ \code
+ ComboBox {
+ model: ["First", "Second", "Third"]
+ }
+ \endcode
+
+ ComboBox is able to visualize standard \l {qml-data-models}{data models}
+ that provide the \c modelData role:
+ \list
+ \li models that have only one role
+ \li models that do not have named roles (JavaScript array, integer)
+ \endlist
+
+ When using models that have multiple named roles, ComboBox must be configured
+ to use a specific \l {textRole}{text role} for its \l {displayText}{display text}
+ and \l delegate instances.
+
+ \code
+ ComboBox {
+ textRole: "key"
+ model: ListModel {
+ ListElement { key: "First"; value: 123 }
+ ListElement { key: "Second"; value: 456 }
+ ListElement { key: "Third"; value: 789 }
+ }
+ }
+ \endcode
+
+ \note If ComboBox is assigned a data model that has multiple named roles, but
+ \l textRole is not defined, ComboBox is unable to visualize it and throws a
+ \c {ReferenceError: modelData is not defined}.
+
+ \sa {Customizing ComboBox}, {Input Controls}
+*/
+
+/*!
+ \qmlsignal void Qt.labs.controls::ComboBox::activated(int index)
+
+ This signal is emitted when the item at \a index is activated by the user.
+
+ \sa currentIndex
+*/
+
+/*!
+ \qmlsignal void Qt.labs.controls::ComboBox::highlighted(int index)
+
+ This signal is emitted when the item at \a index in the popup list is highlighted by the user.
+
+ \sa highlightedIndex
+*/
+
+class QQuickComboBoxPrivate : public QQuickControlPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickComboBox)
+
+public:
+ QQuickComboBoxPrivate() : pressed(false), ownModel(false), hasDisplayText(false),
+ hideTimer(0), highlightedIndex(-1), currentIndex(-1), delegateModel(Q_NULLPTR),
+ delegate(Q_NULLPTR), panel(Q_NULLPTR) { }
+
+ bool isPanelVisible() const;
+ void showPanel();
+ void hidePanel(bool accept);
+ void togglePanel(bool accept);
+
+ void pressedOutside();
+ void itemClicked();
+
+ void initItem(int index, QObject *object);
+ void countChanged();
+ void updateCurrentText();
+ void increase();
+ void decrease();
+ void setHighlightedIndex(int index);
+
+ void createDelegateModel();
+
+ bool pressed;
+ bool ownModel;
+ bool hasDisplayText;
+ int hideTimer;
+ int highlightedIndex;
+ int currentIndex;
+ QVariant model;
+ QString textRole;
+ QString currentText;
+ QString displayText;
+ QQuickItem *pressedItem;
+ QQmlInstanceModel *delegateModel;
+ QQmlComponent *delegate;
+ QQuickPanel *panel;
+};
+
+bool QQuickComboBoxPrivate::isPanelVisible() const
+{
+ return panel && panel->isVisible();
+}
+
+void QQuickComboBoxPrivate::showPanel()
+{
+ if (panel && !panel->isVisible())
+ panel->show();
+ setHighlightedIndex(currentIndex);
+}
+
+void QQuickComboBoxPrivate::hidePanel(bool accept)
+{
+ Q_Q(QQuickComboBox);
+ if (panel && panel->isVisible())
+ panel->hide();
+ if (accept) {
+ q->setCurrentIndex(highlightedIndex);
+ emit q->activated(currentIndex);
+ }
+ setHighlightedIndex(-1);
+}
+
+void QQuickComboBoxPrivate::togglePanel(bool accept)
+{
+ if (!panel)
+ return;
+
+ if (panel->isVisible())
+ hidePanel(accept);
+ else
+ showPanel();
+}
+
+void QQuickComboBoxPrivate::pressedOutside()
+{
+ Q_Q(QQuickComboBox);
+ if (hideTimer <= 0)
+ hideTimer = q->startTimer(0);
+}
+
+void QQuickComboBoxPrivate::itemClicked()
+{
+ Q_Q(QQuickComboBox);
+ int index = delegateModel->indexOf(q->sender(), Q_NULLPTR);
+ if (index != -1) {
+ setHighlightedIndex(index);
+ emit q->highlighted(index);
+ hidePanel(true);
+ }
+}
+
+void QQuickComboBoxPrivate::initItem(int index, QObject *object)
+{
+ QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(object);
+ if (button)
+ connect(button, &QQuickAbstractButton::clicked, this, &QQuickComboBoxPrivate::itemClicked);
+
+ if (index == currentIndex)
+ updateCurrentText();
+}
+
+void QQuickComboBoxPrivate::countChanged()
+{
+ Q_Q(QQuickComboBox);
+ if (q->count() == 0)
+ q->setCurrentIndex(-1);
+ emit q->countChanged();
+}
+
+void QQuickComboBoxPrivate::updateCurrentText()
+{
+ Q_Q(QQuickComboBox);
+ QString text = q->textAt(currentIndex);
+ if (currentText != text) {
+ currentText = text;
+ emit q->currentTextChanged();
+ }
+ if (!hasDisplayText && displayText != text) {
+ displayText = text;
+ emit q->displayTextChanged();
+ }
+}
+
+void QQuickComboBoxPrivate::increase()
+{
+ Q_Q(QQuickComboBox);
+ if (isPanelVisible()) {
+ if (highlightedIndex < q->count() - 1) {
+ setHighlightedIndex(highlightedIndex + 1);
+ emit q->highlighted(highlightedIndex);
+ }
+ } else {
+ if (currentIndex < q->count() - 1) {
+ q->setCurrentIndex(currentIndex + 1);
+ emit q->activated(currentIndex);
+ }
+ }
+}
+
+void QQuickComboBoxPrivate::decrease()
+{
+ Q_Q(QQuickComboBox);
+ if (isPanelVisible()) {
+ if (highlightedIndex > 0) {
+ setHighlightedIndex(highlightedIndex - 1);
+ emit q->highlighted(highlightedIndex);
+ }
+ } else {
+ if (currentIndex > 0) {
+ q->setCurrentIndex(currentIndex - 1);
+ emit q->activated(currentIndex);
+ }
+ }
+}
+
+void QQuickComboBoxPrivate::setHighlightedIndex(int index)
+{
+ Q_Q(QQuickComboBox);
+ if (highlightedIndex != index) {
+ highlightedIndex = index;
+ emit q->highlightedIndexChanged();
+ }
+}
+
+void QQuickComboBoxPrivate::createDelegateModel()
+{
+ Q_Q(QQuickComboBox);
+ if (delegateModel) {
+ if (ownModel) {
+ delete delegateModel;
+ } else {
+ disconnect(delegateModel, &QQmlInstanceModel::countChanged, this, &QQuickComboBoxPrivate::countChanged);
+ disconnect(delegateModel, &QQmlInstanceModel::modelUpdated, this, &QQuickComboBoxPrivate::updateCurrentText);
+ disconnect(delegateModel, &QQmlInstanceModel::initItem, this, &QQuickComboBoxPrivate::initItem);
+ }
+ }
+
+ ownModel = false;
+ delegateModel = model.value<QQmlInstanceModel *>();
+
+ if (!delegateModel && model.isValid()) {
+ QQmlDelegateModel *dataModel = new QQmlDelegateModel(qmlContext(q), q);
+ dataModel->setModel(model);
+ dataModel->setDelegate(delegate);
+ if (q->isComponentComplete())
+ dataModel->componentComplete();
+
+ ownModel = true;
+ delegateModel = dataModel;
+ }
+
+ if (delegateModel) {
+ connect(delegateModel, &QQmlInstanceModel::countChanged, this, &QQuickComboBoxPrivate::countChanged);
+ connect(delegateModel, &QQmlInstanceModel::modelUpdated, this, &QQuickComboBoxPrivate::updateCurrentText);
+ connect(delegateModel, &QQmlInstanceModel::initItem, this, &QQuickComboBoxPrivate::initItem);
+ }
+
+ emit q->delegateModelChanged();
+}
+
+QQuickComboBox::QQuickComboBox(QQuickItem *parent) :
+ QQuickControl(*(new QQuickComboBoxPrivate), parent)
+{
+ setActiveFocusOnTab(true);
+ setFlag(QQuickItem::ItemIsFocusScope);
+ setAcceptedMouseButtons(Qt::LeftButton);
+}
+
+/*!
+ \readonly
+ \qmlproperty int Qt.labs.controls::ComboBox::count
+
+ This property holds the number of items in the combo box.
+*/
+int QQuickComboBox::count() const
+{
+ Q_D(const QQuickComboBox);
+ return d->delegateModel ? d->delegateModel->count() : 0;
+}
+
+/*!
+ \qmlproperty model Qt.labs.controls::ComboBox::model
+
+ This property holds the model providing data for the combo box.
+
+ \code
+ ComboBox {
+ textRole: "key"
+ model: ListModel {
+ ListElement { key: "First"; value: 123 }
+ ListElement { key: "Second"; value: 456 }
+ ListElement { key: "Third"; value: 789 }
+ }
+ }
+ \endcode
+
+ \sa textRole, {qml-data-models}{Data Models}
+*/
+QVariant QQuickComboBox::model() const
+{
+ Q_D(const QQuickComboBox);
+ return d->model;
+}
+
+void QQuickComboBox::setModel(const QVariant& m)
+{
+ Q_D(QQuickComboBox);
+ QVariant model = m;
+ if (model.userType() == qMetaTypeId<QJSValue>())
+ model = model.value<QJSValue>().toVariant();
+
+ if (d->model != model) {
+ d->model = model;
+ d->createDelegateModel();
+ if (isComponentComplete()) {
+ setCurrentIndex(count() > 0 ? 0 : -1);
+ d->updateCurrentText();
+ }
+ emit modelChanged();
+ }
+}
+
+/*!
+ \internal
+ \qmlproperty model Qt.labs.controls::ComboBox::delegateModel
+
+ This property holds the model providing delegate instances for the combo box.
+*/
+QQmlInstanceModel *QQuickComboBox::delegateModel() const
+{
+ Q_D(const QQuickComboBox);
+ return d->delegateModel;
+}
+
+/*!
+ \qmlproperty bool Qt.labs.controls::ComboBox::pressed
+
+ This property holds whether the combo box button is pressed.
+*/
+bool QQuickComboBox::isPressed() const
+{
+ Q_D(const QQuickComboBox);
+ return d->pressed;
+}
+
+void QQuickComboBox::setPressed(bool pressed)
+{
+ Q_D(QQuickComboBox);
+ if (d->pressed != pressed) {
+ d->pressed = pressed;
+ emit pressedChanged();
+ }
+}
+
+/*!
+ \qmlproperty int Qt.labs.controls::ComboBox::highlightedIndex
+
+ This property holds the index of the highlighted item in the combo box popup list.
+
+ \sa highlighted(), currentIndex
+*/
+int QQuickComboBox::highlightedIndex() const
+{
+ Q_D(const QQuickComboBox);
+ return d->highlightedIndex;
+}
+
+/*!
+ \qmlproperty int Qt.labs.controls::ComboBox::currentIndex
+
+ This property holds the index of the current item in the combo box.
+
+ \sa activated(), currentText
+*/
+int QQuickComboBox::currentIndex() const
+{
+ Q_D(const QQuickComboBox);
+ return d->currentIndex;
+}
+
+void QQuickComboBox::setCurrentIndex(int index)
+{
+ Q_D(QQuickComboBox);
+ if (d->currentIndex != index) {
+ d->currentIndex = index;
+ emit currentIndexChanged();
+ if (isComponentComplete())
+ d->updateCurrentText();
+ }
+}
+
+/*!
+ \readonly
+ \qmlproperty string Qt.labs.controls::ComboBox::currentText
+
+ This property holds the text of the current item in the combo box.
+
+ \sa currentIndex, displayText, textRole
+*/
+QString QQuickComboBox::currentText() const
+{
+ Q_D(const QQuickComboBox);
+ return d->currentText;
+}
+
+/*!
+ \qmlproperty string Qt.labs.controls::ComboBox::displayText
+
+ This property holds the text that is displayed on the combo box button.
+
+ By default, the display text presents the current selection. That is,
+ it follows the text of the current item. However, the default display
+ text can be overridden with a custom value.
+
+ \code
+ ComboBox {
+ currentIndex: 1
+ displayText: "Size: " + currentText
+ model: ["S", "M", "L"]
+ }
+ \endcode
+
+ \sa currentText, textRole
+*/
+QString QQuickComboBox::displayText() const
+{
+ Q_D(const QQuickComboBox);
+ return d->displayText;
+}
+
+void QQuickComboBox::setDisplayText(const QString &text)
+{
+ Q_D(QQuickComboBox);
+ d->hasDisplayText = true;
+ if (d->displayText != text) {
+ d->displayText = text;
+ emit displayTextChanged();
+ }
+}
+
+void QQuickComboBox::resetDisplayText()
+{
+ Q_D(QQuickComboBox);
+ if (d->hasDisplayText) {
+ d->hasDisplayText = false;
+ d->updateCurrentText();
+ }
+}
+
+/*!
+ \qmlproperty string Qt.labs.controls::ComboBox::textRole
+
+ This property holds the model role used for populating the combo box.
+
+ \sa model, currentText, displayText
+*/
+QString QQuickComboBox::textRole() const
+{
+ Q_D(const QQuickComboBox);
+ return d->textRole;
+}
+
+void QQuickComboBox::setTextRole(const QString &role)
+{
+ Q_D(QQuickComboBox);
+ if (d->textRole != role) {
+ d->textRole = role;
+ if (isComponentComplete())
+ d->updateCurrentText();
+ emit textRoleChanged();
+ }
+}
+
+/*!
+ \qmlproperty Component Qt.labs.controls::ComboBox::delegate
+
+ This property holds a delegate that presents an item in the combo box popup.
+
+ \sa ItemDelegate, {Customizing ComboBox}
+*/
+QQmlComponent *QQuickComboBox::delegate() const
+{
+ Q_D(const QQuickComboBox);
+ return d->delegate;
+}
+
+void QQuickComboBox::setDelegate(QQmlComponent* delegate)
+{
+ Q_D(QQuickComboBox);
+ if (d->delegate != delegate) {
+ delete d->delegate;
+ d->delegate = delegate;
+ QQmlDelegateModel *delegateModel = qobject_cast<QQmlDelegateModel*>(d->delegateModel);
+ if (delegateModel)
+ delegateModel->setDelegate(d->delegate);
+ emit delegateChanged();
+ }
+}
+
+/*!
+ \qmlproperty Panel Qt.labs.controls::ComboBox::panel
+
+ This property holds the popup panel.
+
+ \sa {Customizing ComboBox}
+*/
+QQuickPanel *QQuickComboBox::panel() const
+{
+ Q_D(const QQuickComboBox);
+ return d->panel;
+}
+
+void QQuickComboBox::setPanel(QQuickPanel *panel)
+{
+ Q_D(QQuickComboBox);
+ if (d->panel != panel) {
+ delete d->panel;
+ if (panel)
+ QObjectPrivate::connect(panel, &QQuickPanel::pressedOutside, d, &QQuickComboBoxPrivate::pressedOutside);
+ d->panel = panel;
+ emit panelChanged();
+ }
+}
+
+/*!
+ \qmlmethod string Qt.labs.controls::ComboBox::textAt(int index)
+
+ Returns the text for the specified \a index, or an empty string
+ if the index is out of bounds.
+
+ \sa textRole
+*/
+QString QQuickComboBox::textAt(int index) const
+{
+ Q_D(const QQuickComboBox);
+ if (!d->delegateModel || index < 0 || index >= d->delegateModel->count())
+ return QString();
+ return d->delegateModel->stringValue(index, d->textRole.isEmpty() ? QStringLiteral("modelData") : d->textRole);
+}
+
+/*!
+ \qmlmethod int Qt.labs.controls::ComboBox::find(string text, flags = Qt.MatchExactly)
+
+ Returns the index of the specified \a text, or \c -1 if no match is found.
+
+ The way the search is performed is defined by the specified match \a flags. By default,
+ combo box performs case sensitive exact matching (\c Qt.MatchExactly). All other match
+ types are case-insensitive unless the \c Qt.MatchCaseSensitive flag is also specified.
+
+ \value Qt.MatchExactly The search term matches exactly (default).
+ \value Qt.MatchRegExp The search term matches as a regular expression.
+ \value Qt.MatchWildcard The search term matches using wildcards.
+ \value Qt.MatchFixedString The search term matches as a fixed string.
+ \value Qt.MatchStartsWith The search term matches the start of the item.
+ \value Qt.MatchEndsWidth The search term matches the end of the item.
+ \value Qt.MatchContains The search term is contained in the item.
+ \value Qt.MatchCaseSensitive The search is case sensitive.
+
+ \sa textRole
+*/
+int QQuickComboBox::find(const QString &text, Qt::MatchFlags flags) const
+{
+ int itemCount = count();
+ uint matchType = flags & 0x0F;
+ Qt::CaseSensitivity cs = flags & Qt::MatchCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
+
+ for (int idx = 0; idx < itemCount; ++idx) {
+ QString t = textAt(idx);
+ switch (matchType) {
+ case Qt::MatchExactly:
+ if (t == text)
+ return idx;
+ break;
+ case Qt::MatchRegExp:
+ if (QRegExp(text, cs).exactMatch(t))
+ return idx;
+ break;
+ case Qt::MatchWildcard:
+ if (QRegExp(text, cs, QRegExp::Wildcard).exactMatch(t))
+ return idx;
+ break;
+ case Qt::MatchStartsWith:
+ if (t.startsWith(text, cs))
+ return idx;
+ break;
+ case Qt::MatchEndsWith:
+ if (t.endsWith(text, cs))
+ return idx;
+ break;
+ case Qt::MatchFixedString:
+ if (t.compare(text, cs) == 0)
+ return idx;
+ break;
+ case Qt::MatchContains:
+ default:
+ if (t.contains(text, cs))
+ return idx;
+ break;
+ }
+ }
+ return -1;
+}
+
+void QQuickComboBox::focusOutEvent(QFocusEvent *event)
+{
+ Q_D(QQuickComboBox);
+ QQuickItem::focusOutEvent(event);
+ d->hidePanel(false);
+ setPressed(false);
+}
+
+void QQuickComboBox::keyPressEvent(QKeyEvent *event)
+{
+ Q_D(QQuickComboBox);
+ QQuickControl::keyPressEvent(event);
+ if (!d->panel)
+ return;
+
+ switch (event->key()) {
+ case Qt::Key_Space:
+ if (!event->isAutoRepeat())
+ setPressed(true);
+ event->accept();
+ break;
+ case Qt::Key_Enter:
+ case Qt::Key_Return:
+ if (d->isPanelVisible())
+ setPressed(true);
+ event->accept();
+ break;
+ case Qt::Key_Up:
+ d->decrease();
+ event->accept();
+ break;
+ case Qt::Key_Down:
+ d->increase();
+ event->accept();
+ break;
+ case Qt::Key_Escape:
+ event->accept();
+ default:
+ break;
+ }
+}
+
+void QQuickComboBox::keyReleaseEvent(QKeyEvent *event)
+{
+ Q_D(QQuickComboBox);
+ QQuickControl::keyReleaseEvent(event);
+ if (!d->panel || event->isAutoRepeat())
+ return;
+
+ switch (event->key()) {
+ case Qt::Key_Space:
+ d->togglePanel(true);
+ setPressed(false);
+ event->accept();
+ break;
+ case Qt::Key_Enter:
+ case Qt::Key_Return:
+ d->hidePanel(true);
+ setPressed(false);
+ event->accept();
+ break;
+ case Qt::Key_Escape:
+ d->hidePanel(false);
+ setPressed(false);
+ event->accept();
+ break;
+ default:
+ break;
+ }
+}
+
+void QQuickComboBox::mousePressEvent(QMouseEvent *event)
+{
+ QQuickControl::mousePressEvent(event);
+ setPressed(true);
+}
+
+void QQuickComboBox::mouseMoveEvent(QMouseEvent* event)
+{
+ QQuickControl::mouseMoveEvent(event);
+ setPressed(contains(event->pos()));
+}
+
+void QQuickComboBox::mouseReleaseEvent(QMouseEvent *event)
+{
+ Q_D(QQuickComboBox);
+ QQuickControl::mouseReleaseEvent(event);
+ if (d->pressed) {
+ setPressed(false);
+ if (!d->isPanelVisible())
+ forceActiveFocus(Qt::MouseFocusReason);
+ d->togglePanel(false);
+ }
+}
+
+void QQuickComboBox::mouseUngrabEvent()
+{
+ QQuickControl::mouseUngrabEvent();
+ setPressed(false);
+}
+
+void QQuickComboBox::timerEvent(QTimerEvent *event)
+{
+ Q_D(QQuickComboBox);
+ QQuickControl::timerEvent(event);
+ if (event->timerId() == d->hideTimer) {
+ killTimer(d->hideTimer);
+ d->hideTimer = 0;
+ if (!d->pressed)
+ d->hidePanel(false);
+ }
+}
+
+void QQuickComboBox::componentComplete()
+{
+ Q_D(QQuickComboBox);
+ QQuickControl::componentComplete();
+
+ if (d->delegateModel && d->ownModel)
+ static_cast<QQmlDelegateModel *>(d->delegateModel)->componentComplete();
+
+ if (count() > 0) {
+ if (d->currentIndex == -1)
+ setCurrentIndex(0);
+ else
+ d->updateCurrentText();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/templates/qquickcombobox_p.h b/src/templates/qquickcombobox_p.h
new file mode 100644
index 00000000..6c80edc8
--- /dev/null
+++ b/src/templates/qquickcombobox_p.h
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Labs Templates module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKCOMBOBOX_P_H
+#define QQUICKCOMBOBOX_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtLabsTemplates/private/qquickcontrol_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickPanel;
+class QQmlInstanceModel;
+class QQuickComboBoxPrivate;
+
+class Q_LABSTEMPLATES_EXPORT QQuickComboBox : public QQuickControl
+{
+ Q_OBJECT
+ Q_PROPERTY(int count READ count NOTIFY countChanged FINAL)
+ Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged FINAL)
+ Q_PROPERTY(QQmlInstanceModel *delegateModel READ delegateModel NOTIFY delegateModelChanged FINAL)
+ Q_PROPERTY(bool pressed READ isPressed WRITE setPressed NOTIFY pressedChanged FINAL)
+ Q_PROPERTY(int highlightedIndex READ highlightedIndex NOTIFY highlightedIndexChanged FINAL)
+ Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged FINAL)
+ Q_PROPERTY(QString currentText READ currentText NOTIFY currentTextChanged FINAL)
+ Q_PROPERTY(QString displayText READ displayText WRITE setDisplayText RESET resetDisplayText NOTIFY displayTextChanged FINAL)
+ Q_PROPERTY(QString textRole READ textRole WRITE setTextRole NOTIFY textRoleChanged FINAL)
+ Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged FINAL)
+ Q_PROPERTY(QQuickPanel *panel READ panel WRITE setPanel NOTIFY panelChanged FINAL)
+
+public:
+ explicit QQuickComboBox(QQuickItem *parent = Q_NULLPTR);
+
+ int count() const;
+
+ QVariant model() const;
+ void setModel(const QVariant &model);
+ QQmlInstanceModel *delegateModel() const;
+
+ bool isPressed() const;
+ void setPressed(bool pressed);
+
+ int highlightedIndex() const;
+
+ int currentIndex() const;
+ void setCurrentIndex(int index);
+
+ QString currentText() const;
+
+ QString displayText() const;
+ void setDisplayText(const QString &text);
+ void resetDisplayText();
+
+ QString textRole() const;
+ void setTextRole(const QString &role);
+
+ QQmlComponent *delegate() const;
+ void setDelegate(QQmlComponent *delegate);
+
+ QQuickPanel *panel() const;
+ void setPanel(QQuickPanel *panel);
+
+ Q_INVOKABLE QString textAt(int index) const;
+ Q_INVOKABLE int find(const QString &text, Qt::MatchFlags flags = Qt::MatchExactly) const;
+
+Q_SIGNALS:
+ void countChanged();
+ void modelChanged();
+ void delegateModelChanged();
+ void pressedChanged();
+ void highlightedIndexChanged();
+ void currentIndexChanged();
+ void currentTextChanged();
+ void displayTextChanged();
+ void textRoleChanged();
+ void delegateChanged();
+ void panelChanged();
+
+ void activated(int index);
+ void highlighted(int index);
+
+protected:
+ void focusOutEvent(QFocusEvent *event) Q_DECL_OVERRIDE;
+ void keyPressEvent(QKeyEvent *event) Q_DECL_OVERRIDE;
+ void keyReleaseEvent(QKeyEvent *event) Q_DECL_OVERRIDE;
+ void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
+ void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
+ void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
+ void mouseUngrabEvent() Q_DECL_OVERRIDE;
+ void timerEvent(QTimerEvent *event) Q_DECL_OVERRIDE;
+
+ void componentComplete() Q_DECL_OVERRIDE;
+
+private:
+ Q_DISABLE_COPY(QQuickComboBox)
+ Q_DECLARE_PRIVATE(QQuickComboBox)
+};
+
+Q_DECLARE_TYPEINFO(QQuickComboBox, Q_COMPLEX_TYPE);
+
+QT_END_NAMESPACE
+
+#endif // QQUICKCOMBOBOX_P_H
diff --git a/src/templates/templates.pri b/src/templates/templates.pri
index 22fad255..82e1af9e 100644
--- a/src/templates/templates.pri
+++ b/src/templates/templates.pri
@@ -8,6 +8,7 @@ HEADERS += \
$$PWD/qquickbutton_p.h \
$$PWD/qquickbuttongroup_p.h \
$$PWD/qquickcheckbox_p.h \
+ $$PWD/qquickcombobox_p.h \
$$PWD/qquickcontainer_p.h \
$$PWD/qquickcontainer_p_p.h \
$$PWD/qquickcontrol_p.h \
@@ -56,6 +57,7 @@ SOURCES += \
$$PWD/qquickbutton.cpp \
$$PWD/qquickbuttongroup.cpp \
$$PWD/qquickcheckbox.cpp \
+ $$PWD/qquickcombobox.cpp \
$$PWD/qquickcontainer.cpp \
$$PWD/qquickcontrol.cpp \
$$PWD/qquickdial.cpp \
diff --git a/tests/auto/controls/data/tst_combobox.qml b/tests/auto/controls/data/tst_combobox.qml
new file mode 100644
index 00000000..a0798842
--- /dev/null
+++ b/tests/auto/controls/data/tst_combobox.qml
@@ -0,0 +1,553 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+import Qt.labs.controls 1.0
+
+TestCase {
+ id: testCase
+ name: "ComboBox"
+
+ ApplicationWindow {
+ id: window
+ visible: true
+ width: 400
+ height: 400
+ }
+
+ SignalSpy {
+ id: activatedSpy
+ signalName: "activated"
+ }
+
+ SignalSpy {
+ id: highlightedSpy
+ signalName: "highlighted"
+ }
+
+ Component {
+ id: comboBox
+ ComboBox {
+ delegate: ItemDelegate {
+ width: parent.width
+ }
+ }
+ }
+
+ function initTestCase() {
+ window.requestActivate()
+ tryCompare(window, "active", true)
+ }
+
+ function init() {
+ verify(!activatedSpy.target)
+ compare(activatedSpy.count, 0)
+
+ verify(!highlightedSpy.target)
+ compare(highlightedSpy.count, 0)
+ }
+
+ function cleanup() {
+ activatedSpy.target = null
+ activatedSpy.clear()
+
+ highlightedSpy.target = null
+ highlightedSpy.clear()
+ }
+
+ function test_defaults() {
+ var control = comboBox.createObject(window.contentItem)
+ verify(control)
+
+ compare(control.count, 0)
+ compare(control.model, undefined)
+ compare(control.pressed, false)
+ compare(control.currentIndex, -1)
+ compare(control.highlightedIndex, -1)
+ compare(control.currentText, "")
+ verify(control.delegate)
+ verify(control.panel)
+
+ control.destroy()
+ }
+
+ function test_array() {
+ var control = comboBox.createObject(window.contentItem)
+ 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, "")
+
+ control.destroy()
+ }
+
+ function test_number() {
+ var control = comboBox.createObject(window.contentItem)
+ 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, "")
+
+ control.destroy()
+ }
+
+ ListModel {
+ id: listmodel
+ ListElement { text: "First" }
+ ListElement { text: "Second" }
+ ListElement { text: "Third" }
+ ListElement { text: "Fourth" }
+ ListElement { text: "Fifth" }
+ }
+
+ function test_listModel() {
+ var control = comboBox.createObject(window.contentItem)
+ 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, "")
+
+ control.destroy()
+ }
+
+ ListModel {
+ id: fruitmodel
+ ListElement { name: "Apple"; color: "red" }
+ ListElement { name: "Orange"; color: "orange" }
+ ListElement { name: "Banana"; color: "yellow" }
+ }
+
+ function test_textRole() {
+ var control = comboBox.createObject(window.contentItem)
+ verify(control)
+
+ control.model = fruitmodel
+ 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, "")
+
+ control.destroy()
+ }
+
+ function test_textAt() {
+ var control = comboBox.createObject(window.contentItem)
+ 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?
+
+ control.destroy()
+ }
+
+ 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 },
+
+ { tag: "b(an)+a (MatchRegExp)", term: "B(an)+a", flags: Qt.MatchRegExp, index: 0 },
+ { tag: "b(an)+a (MatchRegExp|MatchCaseSensitive)", term: "b(an)+a", flags: Qt.MatchRegExp | Qt.MatchCaseSensitive, index: 1 },
+ { tag: "[coc]+\\w+ (MatchRegExp)", term: "[coc]+\\w+", flags: Qt.MatchRegExp, index: 2 },
+
+ { 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) {
+ var control = comboBox.createObject(window.contentItem)
+ verify(control)
+
+ control.model = ["Banana", "banana", "Coconut", "Apple", "Cocomuffin"]
+
+ compare(control.find(data.term, data.flags), data.index)
+
+ control.destroy()
+ }
+
+ function test_arrowKeys() {
+ var control = comboBox.createObject(window.contentItem, {model: 3})
+ verify(control)
+
+ activatedSpy.target = control
+ verify(activatedSpy.valid)
+
+ highlightedSpy.target = control
+ verify(highlightedSpy.valid)
+
+ waitForRendering(control)
+
+ 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)
+
+ // show panel
+ keyClick(Qt.Key_Space)
+
+ 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()
+
+ // hide panel
+ keyClick(Qt.Key_Space)
+
+ compare(control.currentIndex, 1)
+ compare(control.highlightedIndex, -1)
+
+ control.destroy()
+ }
+
+ function test_keys_data() {
+ return [
+ { 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: "enter-enter", key1: Qt.Key_Enter, key2: Qt.Key_Enter, showPopup: false, showPress: false, hidePopup: true, hidePress: false },
+ { tag: "return-return", key1: Qt.Key_Return, key2: Qt.Key_Return, showPopup: false, showPress: false, hidePopup: true, hidePress: false },
+ { tag: "escape-escape", key1: Qt.Key_Escape, key2: Qt.Key_Escape, showPopup: false, showPress: false, hidePopup: true, hidePress: false },
+ ]
+ }
+
+ function test_keys(data) {
+ var control = comboBox.createObject(window.contentItem, {model: 3})
+ verify(control)
+
+ control.forceActiveFocus()
+ verify(control.activeFocus)
+
+ compare(control.pressed, false)
+ compare(control.panel.visible, false)
+
+ // show panel
+ keyPress(data.key1)
+ compare(control.pressed, data.showPress)
+ compare(control.panel.visible, false)
+ keyRelease(data.key1)
+ compare(control.pressed, false)
+ compare(control.panel.visible, data.showPopup)
+
+ // hide panel
+ keyPress(data.key2)
+ compare(control.pressed, data.hidePress)
+ compare(control.panel.visible, data.showPopup)
+ keyRelease(data.key2)
+ compare(control.pressed, false)
+ compare(control.panel.visible, !data.hidePopup)
+
+ control.destroy()
+ }
+
+ function test_panel() {
+ var control = comboBox.createObject(window.contentItem, {model: 3})
+ verify(control)
+
+ // show below
+ mousePress(control)
+ compare(control.pressed, true)
+ compare(control.panel.visible, false)
+ mouseRelease(control)
+ compare(control.pressed, false)
+ compare(control.panel.visible, true)
+ verify(control.panel.contentItem.y >= control.y)
+
+ // hide
+ mouseClick(control)
+ compare(control.pressed, false)
+ compare(control.panel.visible, false)
+
+ // show above
+ control.y = window.height - control.height
+ mousePress(control)
+ compare(control.pressed, true)
+ compare(control.panel.visible, false)
+ mouseRelease(control)
+ compare(control.pressed, false)
+ compare(control.panel.visible, true)
+ verify(control.panel.contentItem.y < control.y)
+
+ control.destroy()
+ }
+
+ function test_mouse() {
+ var control = comboBox.createObject(window.contentItem, {model: 3})
+ verify(control)
+
+ activatedSpy.target = control
+ verify(activatedSpy.valid)
+
+ highlightedSpy.target = control
+ verify(highlightedSpy.valid)
+
+ mouseClick(control)
+ compare(control.panel.visible, true)
+
+ var content = control.panel.contentItem
+ waitForRendering(content)
+
+ // press - move - release outside - not activated - not closed
+ mousePress(content)
+ compare(activatedSpy.count, 0)
+ compare(highlightedSpy.count, 0)
+ mouseMove(content, content.width * 2)
+ compare(activatedSpy.count, 0)
+ compare(highlightedSpy.count, 0)
+ mouseRelease(content, content.width * 2)
+ compare(activatedSpy.count, 0)
+ compare(highlightedSpy.count, 0)
+ compare(control.panel.visible, true)
+
+ // press - move - release inside - activated - closed
+ mousePress(content)
+ compare(activatedSpy.count, 0)
+ compare(highlightedSpy.count, 0)
+ mouseMove(content, content.width / 2 + 1, content.height / 2 + 1)
+ compare(activatedSpy.count, 0)
+ compare(highlightedSpy.count, 0)
+ mouseRelease(content)
+ compare(activatedSpy.count, 1)
+ compare(highlightedSpy.count, 1)
+ compare(control.panel.visible, false)
+
+ control.destroy()
+ }
+
+ function test_focus() {
+ var control = comboBox.createObject(window.contentItem, {model: 3})
+ verify(control)
+
+ // click - gain focus - show panel
+ mouseClick(control)
+ verify(control.activeFocus)
+ compare(control.panel.visible, true)
+
+ // lose focus - hide panel
+ window.contentItem.forceActiveFocus()
+ verify(window.contentItem.activeFocus)
+ verify(!control.activeFocus)
+ compare(control.panel.visible, false)
+
+ control.destroy()
+ }
+
+ function test_baseline() {
+ var control = comboBox.createObject(testCase)
+ verify(control)
+ compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset)
+ control.destroy()
+ }
+}
diff --git a/tests/auto/sanity/BLACKLIST b/tests/auto/sanity/BLACKLIST
index 02e9a5f9..5a000c5c 100644
--- a/tests/auto/sanity/BLACKLIST
+++ b/tests/auto/sanity/BLACKLIST
@@ -2,3 +2,9 @@
*
[signalHandlers:material/TextField.qml]
*
+[attachedObjects:controls/ComboBox.qml]
+*
+[attachedObjects:material/ComboBox.qml]
+*
+[attachedObjects:universal/ComboBox.qml]
+*
diff --git a/tests/manual/testbench/main.qml b/tests/manual/testbench/main.qml
index 679c8a1c..54e0ae34 100644
--- a/tests/manual/testbench/main.qml
+++ b/tests/manual/testbench/main.qml
@@ -406,6 +406,40 @@ ApplicationWindow {
}
RowLayout {
+ Item {
+ implicitWidth: normalGroupBox.implicitWidth
+ implicitHeight: normalComboBox.implicitHeight
+
+ ComboBox {
+ id: normalComboBox
+ model: 5
+ }
+ }
+
+ Item {
+ implicitWidth: normalGroupBox.implicitWidth
+ implicitHeight: normalComboBox.implicitHeight
+
+ ComboBox {
+ pressed: true
+ model: ListModel {
+ ListElement { text: "Pressed" }
+ }
+ }
+ }
+
+ Item {
+ implicitWidth: normalGroupBox.implicitWidth
+ implicitHeight: normalComboBox.implicitHeight
+
+ ComboBox {
+ enabled: false
+ model: ["Disabled"]
+ }
+ }
+ }
+
+ RowLayout {
GroupBox {
id: normalGroupBox
title: "Normal"