QmlDesigner: Add support for valueRole in ComboBox

- Add support for valueRole in HelperWidget.ComboBox in order to allow
  for custom JS arrays that define value and text role
- Replace specialized invokables in item filter model which are only
  available in that particular model with general purpose functionality
  provided by QML ComboBox
- Remove unnecessary functions from item filter model

Task-number: QDS-8737
Change-Id: I58bd3fed395961ac4495a0c6e9ff47c9b87e0de2
Reviewed-by: Ali Kianian <ali.kianian@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
This commit is contained in:
Henning Gruendl
2023-04-25 15:43:24 +02:00
committed by Henning Gründl
parent 6eccd82515
commit 3b8c38c7f0
5 changed files with 64 additions and 73 deletions

View File

@@ -10,8 +10,8 @@ StudioControls.ComboBox {
property variant backendValue property variant backendValue
labelColor: edit && !colorLogic.errorState ? StudioTheme.Values.themeTextColor labelColor: comboBox.edit && !colorLogic.errorState ? StudioTheme.Values.themeTextColor
: colorLogic.textColor : colorLogic.textColor
property string scope: "Qt" property string scope: "Qt"
enum ValueType { String, Integer, Enum } enum ValueType { String, Integer, Enum }
@@ -74,7 +74,6 @@ StudioControls.ComboBox {
comboBox.backendValue.commitDrop(dropArea.dropData) comboBox.backendValue.commitDrop(dropArea.dropData)
comboBox.hasActiveHoverDrag = false comboBox.hasActiveHoverDrag = false
} }
} }
ExtendedFunctionLogic { ExtendedFunctionLogic {
@@ -102,6 +101,16 @@ StudioControls.ComboBox {
if (comboBox.manualMapping) { if (comboBox.manualMapping) {
comboBox.valueFromBackendChanged() comboBox.valueFromBackendChanged()
} else if (comboBox.valueRole && comboBox.textRole !== comboBox.valueRole) {
switch (comboBox.valueType) {
case ComboBox.ValueType.Enum:
comboBox.currentIndex = comboBox.indexOfValue(comboBox.backendValue.enumeration)
break
case ComboBox.ValueType.String:
case ComboBox.ValueType.Integer:
default:
comboBox.currentIndex = comboBox.indexOfValue(comboBox.backendValue.value)
}
} else { } else {
switch (comboBox.valueType) { switch (comboBox.valueType) {
case ComboBox.ValueType.String: case ComboBox.ValueType.String:
@@ -147,14 +156,10 @@ StudioControls.ComboBox {
return return
let inputText = comboBox.editText let inputText = comboBox.editText
let inputValue = inputText; let inputValue = inputText
let index = comboBox.find(inputText) let index = comboBox.find(inputText)
if (index !== -1) { if (index !== -1)
let modelIdx = comboBox.model.index(index) inputValue = comboBox.valueRole ? comboBox.valueAt(index) : comboBox.textAt(index)
inputValue = comboBox.valueRole
? comboBox.model.data(modelIdx, comboBox.valueRole)
: comboBox.textAt(index)
}
comboBox.backendValue.value = inputValue comboBox.backendValue.value = inputValue
@@ -175,24 +180,31 @@ StudioControls.ComboBox {
let inputText = comboBox.currentText let inputText = comboBox.currentText
let inputValue = comboBox.currentValue let inputValue = comboBox.currentValue
let index = comboBox.find(inputText) let index = comboBox.find(inputText)
if (index !== -1) {
let modelIdx = comboBox.model.index(index)
inputValue = comboBox.model.data(modelIdx, comboBox.valueRole)
}
comboBox.backendValue.value = inputValue
return
}
switch (comboBox.valueType) { if (index !== -1)
case ComboBox.ValueType.String: inputValue = comboBox.valueAt(index)
comboBox.backendValue.value = comboBox.currentText
break switch (comboBox.valueType) {
case ComboBox.ValueType.Integer: case ComboBox.ValueType.Enum:
comboBox.backendValue.value = comboBox.currentIndex comboBox.backendValue.setEnumeration(comboBox.scope, inputValue)
break break
case ComboBox.ValueType.Enum: case ComboBox.ValueType.String:
default: case ComboBox.ValueType.Integer:
comboBox.backendValue.setEnumeration(comboBox.scope, comboBox.currentText) default:
comboBox.backendValue.value = inputValue
}
} else {
switch (comboBox.valueType) {
case ComboBox.ValueType.String:
comboBox.backendValue.value = comboBox.currentText
break
case ComboBox.ValueType.Integer:
comboBox.backendValue.value = comboBox.currentIndex
break
case ComboBox.ValueType.Enum:
default:
comboBox.backendValue.setEnumeration(comboBox.scope, comboBox.currentText)
}
} }
} }

View File

@@ -96,7 +96,7 @@ Item {
tooltip: root.extraButtonToolTip tooltip: root.extraButtonToolTip
onClicked: root.extraButtonClicked(index) onClicked: root.extraButtonClicked(index)
visible: root.extraButtonIcon !== "" visible: root.extraButtonIcon !== ""
enabled: root.model[index] enabled: root.model[index] ?? false
} }
IconIndicator { IconIndicator {

View File

@@ -42,9 +42,7 @@ StudioControls.ComboBox {
currentSelectedDataIndex = root.find(root.initialModelData) currentSelectedDataIndex = root.find(root.initialModelData)
} else { } else {
for (let i = 0; i < root.count; ++i) { for (let i = 0; i < root.count; ++i) {
let movingModelIndex = root.model.index(i) if (root.valueAt(i) === root.initialModelData) {
let movingModelValueData = root.model.data(movingModelIndex, root.valueRole)
if (movingModelValueData === root.initialModelData) {
currentSelectedDataIndex = i currentSelectedDataIndex = i
break break
} }
@@ -55,14 +53,6 @@ StudioControls.ComboBox {
root.editText = root.initialModelData root.editText = root.initialModelData
} }
function currentData(role = root.valueRole) {
if (root.currentIndex !== -1) {
let currentModelIndex = root.model.index(root.currentIndex)
return root.model.data(currentModelIndex, role)
}
return root.editText
}
function availableValue() { function availableValue() {
if (root.currentIndex !== -1 && root.currentValue !== "") if (root.currentIndex !== -1 && root.currentValue !== "")
return root.currentValue return root.currentValue

View File

@@ -7,7 +7,7 @@
#include <model.h> #include <model.h>
#include <nodemetainfo.h> #include <nodemetainfo.h>
#include <qmlmodelnodeproxy.h> #include <qmlmodelnodeproxy.h>
#include "variantproperty.h" #include <variantproperty.h>
#include <QFileDialog> #include <QFileDialog>
#include <QDirIterator> #include <QDirIterator>
@@ -24,7 +24,7 @@ ItemFilterModel::ItemFilterModel(QObject *parent)
{ {
if (m_roles.empty()) { if (m_roles.empty()) {
m_roles = QAbstractListModel::roleNames(); m_roles = QAbstractListModel::roleNames();
QMetaEnum roleEnum = QMetaEnum::fromType<Roles>(); const QMetaEnum roleEnum = QMetaEnum::fromType<Roles>();
for (int i = 0; i < roleEnum.keyCount(); i++) for (int i = 0; i < roleEnum.keyCount(); i++)
m_roles.insert(roleEnum.value(i), roleEnum.key(i)); m_roles.insert(roleEnum.value(i), roleEnum.key(i));
} }
@@ -32,7 +32,6 @@ ItemFilterModel::ItemFilterModel(QObject *parent)
void ItemFilterModel::setModelNodeBackend(const QVariant &modelNodeBackend) void ItemFilterModel::setModelNodeBackend(const QVariant &modelNodeBackend)
{ {
auto modelNodeBackendObject = modelNodeBackend.value<QObject*>(); auto modelNodeBackendObject = modelNodeBackend.value<QObject*>();
const auto backendObjectCasted = const auto backendObjectCasted =
@@ -47,18 +46,22 @@ void ItemFilterModel::setModelNodeBackend(const QVariant &modelNodeBackend)
void ItemFilterModel::setTypeFilter(const QString &filter) void ItemFilterModel::setTypeFilter(const QString &filter)
{ {
if (m_typeFilter != filter) { if (m_typeFilter == filter)
m_typeFilter = filter; return;
setupModel();
} m_typeFilter = filter;
setupModel();
emit typeFilterChanged();
} }
void ItemFilterModel::setSelectionOnly(bool value) void ItemFilterModel::setSelectionOnly(bool value)
{ {
if (m_selectionOnly != value) { if (m_selectionOnly == value)
m_selectionOnly = value; return;
setupModel();
} m_selectionOnly = value;
setupModel();
emit selectionOnlyChanged();
} }
QString ItemFilterModel::typeFilter() const QString ItemFilterModel::typeFilter() const
@@ -73,12 +76,7 @@ bool ItemFilterModel::selectionOnly() const
void ItemFilterModel::registerDeclarativeType() void ItemFilterModel::registerDeclarativeType()
{ {
qmlRegisterType<ItemFilterModel>("HelperWidgets",2,0,"ItemFilterModel"); qmlRegisterType<ItemFilterModel>("HelperWidgets", 2, 0, "ItemFilterModel");
}
QModelIndex ItemFilterModel::index(int row, int column, const QModelIndex &parent) const
{
return QAbstractListModel::index(row, column, parent);
} }
int ItemFilterModel::rowCount(const QModelIndex &) const int ItemFilterModel::rowCount(const QModelIndex &) const
@@ -91,7 +89,7 @@ QVariant ItemFilterModel::data(const QModelIndex &index, int role) const
if (!index.isValid()) if (!index.isValid())
return {}; return {};
ModelNode node = modelNodeForRow(index.row()); const ModelNode node = modelNodeForRow(index.row());
QVariant value; QVariant value;
switch (role) { switch (role) {
@@ -102,9 +100,8 @@ QVariant ItemFilterModel::data(const QModelIndex &index, int role) const
value = node.variantProperty("objectName").value(); value = node.variantProperty("objectName").value();
break; break;
case IdAndNameRole: case IdAndNameRole:
value = QString("%1 [%2]").arg( value = QString("%1 [%2]").arg(node.variantProperty("objectName").value().toString(),
node.variantProperty("objectName").value().toString() node.id());
,node.id());
break; break;
default: default:
value = node.id(); value = node.id();
@@ -114,12 +111,6 @@ QVariant ItemFilterModel::data(const QModelIndex &index, int role) const
return value; return value;
} }
// TODO: Handle model data manipulation here.
bool ItemFilterModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
return QAbstractListModel::setData(index, value, role);
}
QHash<int, QByteArray> ItemFilterModel::roleNames() const QHash<int, QByteArray> ItemFilterModel::roleNames() const
{ {
return m_roles; return m_roles;

View File

@@ -16,7 +16,7 @@ class ItemFilterModel : public QAbstractListModel
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QString typeFilter READ typeFilter WRITE setTypeFilter) Q_PROPERTY(QString typeFilter READ typeFilter WRITE setTypeFilter NOTIFY typeFilterChanged)
Q_PROPERTY(QVariant modelNodeBackendProperty READ modelNodeBackend WRITE setModelNodeBackend NOTIFY modelNodeBackendChanged) Q_PROPERTY(QVariant modelNodeBackendProperty READ modelNodeBackend WRITE setModelNodeBackend NOTIFY modelNodeBackendChanged)
Q_PROPERTY(QStringList itemModel READ itemModel NOTIFY itemModelChanged) Q_PROPERTY(QStringList itemModel READ itemModel NOTIFY itemModelChanged)
Q_PROPERTY(bool selectionOnly READ selectionOnly WRITE setSelectionOnly NOTIFY selectionOnlyChanged) Q_PROPERTY(bool selectionOnly READ selectionOnly WRITE setSelectionOnly NOTIFY selectionOnlyChanged)
@@ -41,15 +41,13 @@ public:
static void registerDeclarativeType(); static void registerDeclarativeType();
// Make index accessible for Qml side since it's not accessible by default in QAbstractListModel virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override;
Q_INVOKABLE QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const override; virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
Q_INVOKABLE virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override;
Q_INVOKABLE virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
Q_INVOKABLE virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
virtual QHash<int,QByteArray> roleNames() const override; virtual QHash<int, QByteArray> roleNames() const override;
signals: signals:
void typeFilterChanged();
void modelNodeBackendChanged(); void modelNodeBackendChanged();
void itemModelChanged(); void itemModelChanged();
void selectionOnlyChanged(); void selectionOnlyChanged();