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
labelColor: edit && !colorLogic.errorState ? StudioTheme.Values.themeTextColor
: colorLogic.textColor
labelColor: comboBox.edit && !colorLogic.errorState ? StudioTheme.Values.themeTextColor
: colorLogic.textColor
property string scope: "Qt"
enum ValueType { String, Integer, Enum }
@@ -74,7 +74,6 @@ StudioControls.ComboBox {
comboBox.backendValue.commitDrop(dropArea.dropData)
comboBox.hasActiveHoverDrag = false
}
}
ExtendedFunctionLogic {
@@ -102,6 +101,16 @@ StudioControls.ComboBox {
if (comboBox.manualMapping) {
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 {
switch (comboBox.valueType) {
case ComboBox.ValueType.String:
@@ -147,14 +156,10 @@ StudioControls.ComboBox {
return
let inputText = comboBox.editText
let inputValue = inputText;
let inputValue = inputText
let index = comboBox.find(inputText)
if (index !== -1) {
let modelIdx = comboBox.model.index(index)
inputValue = comboBox.valueRole
? comboBox.model.data(modelIdx, comboBox.valueRole)
: comboBox.textAt(index)
}
if (index !== -1)
inputValue = comboBox.valueRole ? comboBox.valueAt(index) : comboBox.textAt(index)
comboBox.backendValue.value = inputValue
@@ -175,24 +180,31 @@ StudioControls.ComboBox {
let inputText = comboBox.currentText
let inputValue = comboBox.currentValue
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) {
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)
if (index !== -1)
inputValue = comboBox.valueAt(index)
switch (comboBox.valueType) {
case ComboBox.ValueType.Enum:
comboBox.backendValue.setEnumeration(comboBox.scope, inputValue)
break
case ComboBox.ValueType.String:
case ComboBox.ValueType.Integer:
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
onClicked: root.extraButtonClicked(index)
visible: root.extraButtonIcon !== ""
enabled: root.model[index]
enabled: root.model[index] ?? false
}
IconIndicator {

View File

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

View File

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

View File

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