aboutsummaryrefslogtreecommitdiffstats
path: root/src/quicktemplates2/qquickcombobox.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quicktemplates2/qquickcombobox.cpp')
-rw-r--r--src/quicktemplates2/qquickcombobox.cpp141
1 files changed, 119 insertions, 22 deletions
diff --git a/src/quicktemplates2/qquickcombobox.cpp b/src/quicktemplates2/qquickcombobox.cpp
index 8dc70934..60526a0a 100644
--- a/src/quicktemplates2/qquickcombobox.cpp
+++ b/src/quicktemplates2/qquickcombobox.cpp
@@ -49,7 +49,7 @@
#include <QtQml/qjsvalue.h>
#include <QtQml/qqmlcontext.h>
#include <QtQml/private/qlazilyallocated_p.h>
-#include <QtQml/private/qqmldelegatemodel_p.h>
+#include <private/qqmldelegatemodel_p.h>
#include <QtQuick/private/qquickevents_p_p.h>
#include <QtQuick/private/qquicktextinput_p.h>
#include <QtQuick/private/qquickitemview_p.h>
@@ -103,18 +103,14 @@ QT_BEGIN_NAMESPACE
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.
+ and \l delegate instances. If you want to use a role of the model item
+ that corresponds to the text role, set \l valueRole. The \l currentValue
+ property and \l indexOfValue() method can then be used to get information
+ about those values.
- \code
- ComboBox {
- textRole: "key"
- model: ListModel {
- ListElement { key: "First"; value: 123 }
- ListElement { key: "Second"; value: 456 }
- ListElement { key: "Third"; value: 789 }
- }
- }
- \endcode
+ For example:
+
+ \snippet qtquickcontrols2-combobox-valuerole.qml file
\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
@@ -183,7 +179,7 @@ class QQuickComboBoxDelegateModel : public QQmlDelegateModel
{
public:
explicit QQuickComboBoxDelegateModel(QQuickComboBox *combo);
- QString stringValue(int index, const QString &role) override;
+ QVariant variantValue(int index, const QString &role) override;
private:
QQuickComboBox *combo = nullptr;
@@ -195,23 +191,23 @@ QQuickComboBoxDelegateModel::QQuickComboBoxDelegateModel(QQuickComboBox *combo)
{
}
-QString QQuickComboBoxDelegateModel::stringValue(int index, const QString &role)
+QVariant QQuickComboBoxDelegateModel::variantValue(int index, const QString &role)
{
- QVariant model = combo->model();
+ const QVariant model = combo->model();
if (model.userType() == QMetaType::QVariantList) {
QVariant object = model.toList().value(index);
if (object.userType() == QMetaType::QVariantMap) {
const QVariantMap data = object.toMap();
if (data.count() == 1 && role == QLatin1String("modelData"))
- return data.first().toString();
- return data.value(role).toString();
+ return data.first();
+ return data.value(role);
} else if (object.userType() == QMetaType::QObjectStar) {
const QObject *data = object.value<QObject *>();
if (data && role != QLatin1String("modelData"))
- return data->property(role.toUtf8()).toString();
+ return data->property(role.toUtf8());
}
}
- return QQmlDelegateModel::stringValue(index, role);
+ return QQmlDelegateModel::variantValue(index, role);
}
class QQuickComboBoxPrivate : public QQuickControlPrivate
@@ -234,6 +230,7 @@ public:
void updateEditText();
void updateCurrentText();
+ void updateCurrentValue();
void acceptInput();
QString tryComplete(const QString &inputText);
@@ -277,6 +274,8 @@ public:
QString textRole;
QString currentText;
QString displayText;
+ QString valueRole;
+ QVariant currentValue;
QQuickItem *pressedItem = nullptr;
QQmlInstanceModel *delegateModel = nullptr;
QQmlComponent *delegate = nullptr;
@@ -452,6 +451,17 @@ void QQuickComboBoxPrivate::updateCurrentText()
q->setEditText(currentText);
}
+void QQuickComboBoxPrivate::updateCurrentValue()
+{
+ Q_Q(QQuickComboBox);
+ const QVariant value = q->valueAt(currentIndex);
+ if (currentValue == value)
+ return;
+
+ currentValue = value;
+ emit q->currentValueChanged();
+}
+
void QQuickComboBoxPrivate::acceptInput()
{
Q_Q(QQuickComboBox);
@@ -498,8 +508,10 @@ void QQuickComboBoxPrivate::setCurrentIndex(int index, Activation activate)
currentIndex = index;
emit q->currentIndexChanged();
- if (componentComplete)
+ if (componentComplete) {
updateCurrentText();
+ updateCurrentValue();
+ }
if (activate)
emit q->activated(index);
@@ -1008,6 +1020,35 @@ void QQuickComboBox::setTextRole(const QString &role)
}
/*!
+ \since QtQuick.Controls 2.14 (Qt 5.14)
+ \qmlproperty string QtQuick.Controls::ComboBox::valueRole
+
+ This property holds the model role used for storing the value associated
+ with each item in the model.
+
+ For an example of how to use this property, see \l {ComboBox Model Roles}.
+
+ \sa model, currentValue
+*/
+QString QQuickComboBox::valueRole() const
+{
+ Q_D(const QQuickComboBox);
+ return d->valueRole;
+}
+
+void QQuickComboBox::setValueRole(const QString &role)
+{
+ Q_D(QQuickComboBox);
+ if (d->valueRole == role)
+ return;
+
+ d->valueRole = role;
+ if (isComponentComplete())
+ d->updateCurrentValue();
+ emit valueRoleChanged();
+}
+
+/*!
\qmlproperty Component QtQuick.Controls::ComboBox::delegate
This property holds a delegate that presents an item in the combo box popup.
@@ -1445,6 +1486,60 @@ qreal QQuickComboBox::implicitIndicatorHeight() const
}
/*!
+ \readonly
+ \since QtQuick.Controls 2.14 (Qt 5.14)
+ \qmlproperty string QtQuick.Controls::ComboBox::currentValue
+
+ This property holds the value of the current item in the combo box.
+
+ For an example of how to use this property, see \l {ComboBox Model Roles}.
+
+ \sa currentIndex, currentText, valueRole
+*/
+QVariant QQuickComboBox::currentValue() const
+{
+ Q_D(const QQuickComboBox);
+ return d->currentValue;
+}
+
+QVariant QQuickComboBox::valueAt(int index) const
+{
+ Q_D(const QQuickComboBox);
+ if (!d->delegateModel || index < 0 || index >= d->delegateModel->count())
+ return QVariant();
+
+ // We use QVariant because the model API uses QVariant.
+ QVariant value;
+ QObject *object = d->delegateModel->object(index);
+ if (object) {
+ const QString role = d->valueRole.isEmpty() ? QStringLiteral("modelData") : d->valueRole;
+ value = d->delegateModel->variantValue(index, role);
+ d->delegateModel->release(object);
+ }
+ return value;
+}
+
+/*!
+ \since QtQuick.Controls 2.14 (Qt 5.14)
+ \qmlmethod int QtQuick.Controls::ComboBox::indexOfValue(object value)
+
+ Returns the index of the specified \a value, or \c -1 if no match is found.
+
+ For an example of how to use this method, see \l {ComboBox Model Roles}.
+
+ \sa find(), currentValue, currentIndex, valueRole
+*/
+int QQuickComboBox::indexOfValue(const QVariant &value) const
+{
+ for (int i = 0; i < count(); ++i) {
+ const QVariant ourValue = valueAt(i);
+ if (value == ourValue)
+ return i;
+ }
+ return -1;
+}
+
+/*!
\qmlmethod string QtQuick.Controls::ComboBox::textAt(int index)
Returns the text for the specified \a index, or an empty string
@@ -1728,10 +1823,12 @@ void QQuickComboBox::componentComplete()
static_cast<QQmlDelegateModel *>(d->delegateModel)->componentComplete();
if (count() > 0) {
- if (!d->hasCurrentIndex && d->currentIndex == -1)
+ if (!d->hasCurrentIndex && d->currentIndex == -1) {
setCurrentIndex(0);
- else
+ } else {
d->updateCurrentText();
+ d->updateCurrentValue();
+ }
}
}