From 94b019dbe05ef7639ffea8e09b5974d89d75adaa Mon Sep 17 00:00:00 2001 From: Henning Gruendl Date: Fri, 5 May 2023 17:08:45 +0200 Subject: [PATCH] QmlDesigner: Add duplicate control Add a setting/property to the EditableListView in order to control if it allows duplicates or not. If duplicates are not allowed it will disable the items in the ComboBox which are already applied to the assigned backend property. Task-number: QDS-6730 Change-Id: I31776fdfb14858c431b40d264e8e709009c517b3 Reviewed-by: Thomas Hartmann Reviewed-by: Ali Kianian Reviewed-by: Mahmoud Badri Reviewed-by: --- .../HelperWidgets/EditableListView.qml | 22 +++++--- .../HelperWidgets/ListViewComboBox.qml | 14 ++---- .../propertyeditor/itemfiltermodel.cpp | 50 ++++++++++--------- .../propertyeditor/itemfiltermodel.h | 20 ++++---- 4 files changed, 56 insertions(+), 50 deletions(-) diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/EditableListView.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/EditableListView.qml index 1536afdb06e..b8792c71ea6 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/EditableListView.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/EditableListView.qml @@ -1,8 +1,9 @@ // Copyright (C) 2021 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 -import QtQuick 2.15 -import QtQuick.Layouts 1.15 +import QtQuick +import QtQuick.Layouts +import HelperWidgets 2.0 as HelperWidgets import StudioControls 1.0 as StudioControls import StudioTheme 1.0 as StudioTheme @@ -23,11 +24,12 @@ Item { property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth property real __actionIndicatorHeight: StudioTheme.Values.height property string typeFilter: "QtQuick3D.Material" - property string textRole: "IdAndNameRole" - property string valueRole: "IdRole" + property string textRole: "idAndName" + property string valueRole: "id" property int activatedReason: ComboBox.ActivatedReason.Other property bool delegateHover: false + property bool allowDuplicates: true property string extraButtonIcon: "" // setting this will show an extra button property string extraButtonToolTip: "" @@ -40,11 +42,19 @@ Item { Layout.preferredWidth: StudioTheme.Values.height * 10 Layout.preferredHeight: myColumn.height + HelperWidgets.ItemFilterModel { + id: itemFilterModel + typeFilter: root.typeFilter + modelNodeBackendProperty: modelNodeBackend + selectedItems: root.allowDuplicates ? [] : root.model + } + Component { id: myDelegate Row { property alias comboBox: itemFilterComboBox + ListViewComboBox { id: itemFilterComboBox @@ -54,7 +64,7 @@ Item { validator: RegExpValidator { regExp: /(^[a-z_]\w*|^[A-Z]\w*\.{1}([a-z_]\w*\.?)+)/ } actionIndicatorVisible: false - typeFilter: root.typeFilter + model: itemFilterModel initialModelData: modelData textRole: root.textRole valueRole: root.valueRole @@ -188,7 +198,7 @@ Item { visible: myRepeater.count === 0 validator: RegExpValidator { regExp: /(^[a-z_]\w*|^[A-Z]\w*\.{1}([a-z_]\w*\.?)+)/ } actionIndicatorVisible: false - typeFilter: root.typeFilter + model: itemFilterModel textRole: root.textRole valueRole: root.valueRole implicitWidth: StudioTheme.Values.singleControlColumnWidth diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ListViewComboBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ListViewComboBox.qml index 4be51733016..1f8dbbb3d41 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ListViewComboBox.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ListViewComboBox.qml @@ -1,27 +1,19 @@ // Copyright (C) 2021 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only -import QtQuick 2.15 +import QtQuick import HelperWidgets 2.0 as HelperWidgets import StudioControls 1.0 as StudioControls StudioControls.ComboBox { id: root - property alias typeFilter: itemFilterModel.typeFilter - property var initialModelData property bool __isCompleted: false editable: true - model: itemFilterModel - textRole: "IdRole" - valueRole: "IdRole" - - HelperWidgets.ItemFilterModel { - id: itemFilterModel - modelNodeBackendProperty: modelNodeBackend - } + textRole: "id" + valueRole: "id" Component.onCompleted: { root.__isCompleted = true diff --git a/src/plugins/qmldesigner/components/propertyeditor/itemfiltermodel.cpp b/src/plugins/qmldesigner/components/propertyeditor/itemfiltermodel.cpp index 19a697e7024..c5d9a23d7ea 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/itemfiltermodel.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/itemfiltermodel.cpp @@ -15,20 +15,11 @@ using namespace QmlDesigner; -QHash ItemFilterModel::m_roles; - ItemFilterModel::ItemFilterModel(QObject *parent) : QAbstractListModel(parent) , m_typeFilter("QtQuick.Item") , m_selectionOnly(false) -{ - if (m_roles.empty()) { - m_roles = QAbstractListModel::roleNames(); - const QMetaEnum roleEnum = QMetaEnum::fromType(); - for (int i = 0; i < roleEnum.keyCount(); i++) - m_roles.insert(roleEnum.value(i), roleEnum.key(i)); - } -} +{} void ItemFilterModel::setModelNodeBackend(const QVariant &modelNodeBackend) { @@ -64,6 +55,12 @@ void ItemFilterModel::setSelectionOnly(bool value) emit selectionOnlyChanged(); } +void ItemFilterModel::setSelectedItems(const QStringList &selectedItems) +{ + m_selectedItems = selectedItems; + emit selectedItemsChanged(); +} + QString ItemFilterModel::typeFilter() const { return m_typeFilter; @@ -74,6 +71,11 @@ bool ItemFilterModel::selectionOnly() const return m_selectionOnly; } +QStringList ItemFilterModel::selectedItems() const +{ + return m_selectedItems; +} + void ItemFilterModel::registerDeclarativeType() { qmlRegisterType("HelperWidgets", 2, 0, "ItemFilterModel"); @@ -86,34 +88,34 @@ int ItemFilterModel::rowCount(const QModelIndex &) const QVariant ItemFilterModel::data(const QModelIndex &index, int role) const { - if (!index.isValid()) + if (!index.isValid() || index.row() >= rowCount()) return {}; const ModelNode node = modelNodeForRow(index.row()); - QVariant value; switch (role) { case IdRole: - value = node.id(); - break; + return node.id(); case NameRole: - value = node.variantProperty("objectName").value(); - break; + return node.variantProperty("objectName").value(); case IdAndNameRole: - value = QString("%1 [%2]").arg(node.variantProperty("objectName").value().toString(), - node.id()); - break; + return QString("%1 [%2]").arg(node.variantProperty("objectName").value().toString(), + node.id()); + case EnabledRole: + return !m_selectedItems.contains(node.id()); default: - value = node.id(); - break; + return {}; } - - return value; } QHash ItemFilterModel::roleNames() const { - return m_roles; + static QHash roleNames{{IdRole, "id"}, + {NameRole, "name"}, + {IdAndNameRole, "idAndName"}, + {EnabledRole, "enabled"}}; + + return roleNames; } QVariant ItemFilterModel::modelNodeBackend() const diff --git a/src/plugins/qmldesigner/components/propertyeditor/itemfiltermodel.h b/src/plugins/qmldesigner/components/propertyeditor/itemfiltermodel.h index e69269ddd95..cb7ae131778 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/itemfiltermodel.h +++ b/src/plugins/qmldesigner/components/propertyeditor/itemfiltermodel.h @@ -17,25 +17,26 @@ class ItemFilterModel : public QAbstractListModel Q_OBJECT 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(bool selectionOnly READ selectionOnly WRITE setSelectionOnly NOTIFY selectionOnlyChanged) + Q_PROPERTY( + bool selectionOnly READ selectionOnly WRITE setSelectionOnly NOTIFY selectionOnlyChanged) + Q_PROPERTY(QStringList selectedItems READ selectedItems WRITE setSelectedItems NOTIFY + selectedItemsChanged) public: - enum Roles { - IdRole = Qt::UserRole + 1, - NameRole, - IdAndNameRole - }; - Q_ENUM(Roles) + enum { IdRole = Qt::DisplayRole, NameRole = Qt::UserRole, IdAndNameRole, EnabledRole }; explicit ItemFilterModel(QObject *parent = nullptr); void setModelNodeBackend(const QVariant &modelNodeBackend); void setTypeFilter(const QString &typeFilter); void setSelectionOnly(bool value); + void setSelectedItems(const QStringList &selectedItems); QString typeFilter() const; bool selectionOnly() const; + QStringList selectedItems() const; void setupModel(); QStringList itemModel() const; @@ -51,6 +52,7 @@ signals: void modelNodeBackendChanged(); void itemModelChanged(); void selectionOnlyChanged(); + void selectedItemsChanged(); private: QVariant modelNodeBackend() const; @@ -61,7 +63,7 @@ private: QList m_modelInternalIds; QmlDesigner::ModelNode m_modelNode; bool m_selectionOnly; - static QHash m_roles; + QStringList m_selectedItems; }; QML_DECLARE_TYPE(ItemFilterModel)