forked from qt-creator/qt-creator
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 <thomas.hartmann@qt.io> Reviewed-by: Ali Kianian <ali.kianian@qt.io> Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io> Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
This commit is contained in:
committed by
Henning Gründl
parent
c4ff1921ee
commit
94b019dbe0
@@ -1,8 +1,9 @@
|
|||||||
// Copyright (C) 2021 The Qt Company Ltd.
|
// Copyright (C) 2021 The Qt Company Ltd.
|
||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
import QtQuick 2.15
|
import QtQuick
|
||||||
import QtQuick.Layouts 1.15
|
import QtQuick.Layouts
|
||||||
|
import HelperWidgets 2.0 as HelperWidgets
|
||||||
import StudioControls 1.0 as StudioControls
|
import StudioControls 1.0 as StudioControls
|
||||||
import StudioTheme 1.0 as StudioTheme
|
import StudioTheme 1.0 as StudioTheme
|
||||||
|
|
||||||
@@ -23,11 +24,12 @@ Item {
|
|||||||
property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth
|
property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth
|
||||||
property real __actionIndicatorHeight: StudioTheme.Values.height
|
property real __actionIndicatorHeight: StudioTheme.Values.height
|
||||||
property string typeFilter: "QtQuick3D.Material"
|
property string typeFilter: "QtQuick3D.Material"
|
||||||
property string textRole: "IdAndNameRole"
|
property string textRole: "idAndName"
|
||||||
property string valueRole: "IdRole"
|
property string valueRole: "id"
|
||||||
property int activatedReason: ComboBox.ActivatedReason.Other
|
property int activatedReason: ComboBox.ActivatedReason.Other
|
||||||
|
|
||||||
property bool delegateHover: false
|
property bool delegateHover: false
|
||||||
|
property bool allowDuplicates: true
|
||||||
|
|
||||||
property string extraButtonIcon: "" // setting this will show an extra button
|
property string extraButtonIcon: "" // setting this will show an extra button
|
||||||
property string extraButtonToolTip: ""
|
property string extraButtonToolTip: ""
|
||||||
@@ -40,11 +42,19 @@ Item {
|
|||||||
Layout.preferredWidth: StudioTheme.Values.height * 10
|
Layout.preferredWidth: StudioTheme.Values.height * 10
|
||||||
Layout.preferredHeight: myColumn.height
|
Layout.preferredHeight: myColumn.height
|
||||||
|
|
||||||
|
HelperWidgets.ItemFilterModel {
|
||||||
|
id: itemFilterModel
|
||||||
|
typeFilter: root.typeFilter
|
||||||
|
modelNodeBackendProperty: modelNodeBackend
|
||||||
|
selectedItems: root.allowDuplicates ? [] : root.model
|
||||||
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: myDelegate
|
id: myDelegate
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
property alias comboBox: itemFilterComboBox
|
property alias comboBox: itemFilterComboBox
|
||||||
|
|
||||||
ListViewComboBox {
|
ListViewComboBox {
|
||||||
id: itemFilterComboBox
|
id: itemFilterComboBox
|
||||||
|
|
||||||
@@ -54,7 +64,7 @@ Item {
|
|||||||
validator: RegExpValidator { regExp: /(^[a-z_]\w*|^[A-Z]\w*\.{1}([a-z_]\w*\.?)+)/ }
|
validator: RegExpValidator { regExp: /(^[a-z_]\w*|^[A-Z]\w*\.{1}([a-z_]\w*\.?)+)/ }
|
||||||
|
|
||||||
actionIndicatorVisible: false
|
actionIndicatorVisible: false
|
||||||
typeFilter: root.typeFilter
|
model: itemFilterModel
|
||||||
initialModelData: modelData
|
initialModelData: modelData
|
||||||
textRole: root.textRole
|
textRole: root.textRole
|
||||||
valueRole: root.valueRole
|
valueRole: root.valueRole
|
||||||
@@ -188,7 +198,7 @@ Item {
|
|||||||
visible: myRepeater.count === 0
|
visible: myRepeater.count === 0
|
||||||
validator: RegExpValidator { regExp: /(^[a-z_]\w*|^[A-Z]\w*\.{1}([a-z_]\w*\.?)+)/ }
|
validator: RegExpValidator { regExp: /(^[a-z_]\w*|^[A-Z]\w*\.{1}([a-z_]\w*\.?)+)/ }
|
||||||
actionIndicatorVisible: false
|
actionIndicatorVisible: false
|
||||||
typeFilter: root.typeFilter
|
model: itemFilterModel
|
||||||
textRole: root.textRole
|
textRole: root.textRole
|
||||||
valueRole: root.valueRole
|
valueRole: root.valueRole
|
||||||
implicitWidth: StudioTheme.Values.singleControlColumnWidth
|
implicitWidth: StudioTheme.Values.singleControlColumnWidth
|
||||||
|
|||||||
@@ -1,27 +1,19 @@
|
|||||||
// Copyright (C) 2021 The Qt Company Ltd.
|
// Copyright (C) 2021 The Qt Company Ltd.
|
||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
||||||
|
|
||||||
import QtQuick 2.15
|
import QtQuick
|
||||||
import HelperWidgets 2.0 as HelperWidgets
|
import HelperWidgets 2.0 as HelperWidgets
|
||||||
import StudioControls 1.0 as StudioControls
|
import StudioControls 1.0 as StudioControls
|
||||||
|
|
||||||
StudioControls.ComboBox {
|
StudioControls.ComboBox {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property alias typeFilter: itemFilterModel.typeFilter
|
|
||||||
|
|
||||||
property var initialModelData
|
property var initialModelData
|
||||||
property bool __isCompleted: false
|
property bool __isCompleted: false
|
||||||
|
|
||||||
editable: true
|
editable: true
|
||||||
model: itemFilterModel
|
textRole: "id"
|
||||||
textRole: "IdRole"
|
valueRole: "id"
|
||||||
valueRole: "IdRole"
|
|
||||||
|
|
||||||
HelperWidgets.ItemFilterModel {
|
|
||||||
id: itemFilterModel
|
|
||||||
modelNodeBackendProperty: modelNodeBackend
|
|
||||||
}
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
root.__isCompleted = true
|
root.__isCompleted = true
|
||||||
|
|||||||
@@ -15,20 +15,11 @@
|
|||||||
|
|
||||||
using namespace QmlDesigner;
|
using namespace QmlDesigner;
|
||||||
|
|
||||||
QHash<int, QByteArray> ItemFilterModel::m_roles;
|
|
||||||
|
|
||||||
ItemFilterModel::ItemFilterModel(QObject *parent)
|
ItemFilterModel::ItemFilterModel(QObject *parent)
|
||||||
: QAbstractListModel(parent)
|
: QAbstractListModel(parent)
|
||||||
, m_typeFilter("QtQuick.Item")
|
, m_typeFilter("QtQuick.Item")
|
||||||
, m_selectionOnly(false)
|
, m_selectionOnly(false)
|
||||||
{
|
{}
|
||||||
if (m_roles.empty()) {
|
|
||||||
m_roles = QAbstractListModel::roleNames();
|
|
||||||
const QMetaEnum roleEnum = QMetaEnum::fromType<Roles>();
|
|
||||||
for (int i = 0; i < roleEnum.keyCount(); i++)
|
|
||||||
m_roles.insert(roleEnum.value(i), roleEnum.key(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ItemFilterModel::setModelNodeBackend(const QVariant &modelNodeBackend)
|
void ItemFilterModel::setModelNodeBackend(const QVariant &modelNodeBackend)
|
||||||
{
|
{
|
||||||
@@ -64,6 +55,12 @@ void ItemFilterModel::setSelectionOnly(bool value)
|
|||||||
emit selectionOnlyChanged();
|
emit selectionOnlyChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ItemFilterModel::setSelectedItems(const QStringList &selectedItems)
|
||||||
|
{
|
||||||
|
m_selectedItems = selectedItems;
|
||||||
|
emit selectedItemsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
QString ItemFilterModel::typeFilter() const
|
QString ItemFilterModel::typeFilter() const
|
||||||
{
|
{
|
||||||
return m_typeFilter;
|
return m_typeFilter;
|
||||||
@@ -74,6 +71,11 @@ bool ItemFilterModel::selectionOnly() const
|
|||||||
return m_selectionOnly;
|
return m_selectionOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList ItemFilterModel::selectedItems() const
|
||||||
|
{
|
||||||
|
return m_selectedItems;
|
||||||
|
}
|
||||||
|
|
||||||
void ItemFilterModel::registerDeclarativeType()
|
void ItemFilterModel::registerDeclarativeType()
|
||||||
{
|
{
|
||||||
qmlRegisterType<ItemFilterModel>("HelperWidgets", 2, 0, "ItemFilterModel");
|
qmlRegisterType<ItemFilterModel>("HelperWidgets", 2, 0, "ItemFilterModel");
|
||||||
@@ -86,34 +88,34 @@ int ItemFilterModel::rowCount(const QModelIndex &) const
|
|||||||
|
|
||||||
QVariant ItemFilterModel::data(const QModelIndex &index, int role) const
|
QVariant ItemFilterModel::data(const QModelIndex &index, int role) const
|
||||||
{
|
{
|
||||||
if (!index.isValid())
|
if (!index.isValid() || index.row() >= rowCount())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
const ModelNode node = modelNodeForRow(index.row());
|
const ModelNode node = modelNodeForRow(index.row());
|
||||||
|
|
||||||
QVariant value;
|
|
||||||
switch (role) {
|
switch (role) {
|
||||||
case IdRole:
|
case IdRole:
|
||||||
value = node.id();
|
return node.id();
|
||||||
break;
|
|
||||||
case NameRole:
|
case NameRole:
|
||||||
value = node.variantProperty("objectName").value();
|
return node.variantProperty("objectName").value();
|
||||||
break;
|
|
||||||
case IdAndNameRole:
|
case IdAndNameRole:
|
||||||
value = QString("%1 [%2]").arg(node.variantProperty("objectName").value().toString(),
|
return QString("%1 [%2]").arg(node.variantProperty("objectName").value().toString(),
|
||||||
node.id());
|
node.id());
|
||||||
break;
|
case EnabledRole:
|
||||||
|
return !m_selectedItems.contains(node.id());
|
||||||
default:
|
default:
|
||||||
value = node.id();
|
return {};
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QHash<int, QByteArray> ItemFilterModel::roleNames() const
|
QHash<int, QByteArray> ItemFilterModel::roleNames() const
|
||||||
{
|
{
|
||||||
return m_roles;
|
static QHash<int, QByteArray> roleNames{{IdRole, "id"},
|
||||||
|
{NameRole, "name"},
|
||||||
|
{IdAndNameRole, "idAndName"},
|
||||||
|
{EnabledRole, "enabled"}};
|
||||||
|
|
||||||
|
return roleNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant ItemFilterModel::modelNodeBackend() const
|
QVariant ItemFilterModel::modelNodeBackend() const
|
||||||
|
|||||||
@@ -17,25 +17,26 @@ class ItemFilterModel : public QAbstractListModel
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
Q_PROPERTY(QString typeFilter READ typeFilter WRITE setTypeFilter NOTIFY typeFilterChanged)
|
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)
|
||||||
|
Q_PROPERTY(QStringList selectedItems READ selectedItems WRITE setSelectedItems NOTIFY
|
||||||
|
selectedItemsChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum Roles {
|
enum { IdRole = Qt::DisplayRole, NameRole = Qt::UserRole, IdAndNameRole, EnabledRole };
|
||||||
IdRole = Qt::UserRole + 1,
|
|
||||||
NameRole,
|
|
||||||
IdAndNameRole
|
|
||||||
};
|
|
||||||
Q_ENUM(Roles)
|
|
||||||
|
|
||||||
explicit ItemFilterModel(QObject *parent = nullptr);
|
explicit ItemFilterModel(QObject *parent = nullptr);
|
||||||
|
|
||||||
void setModelNodeBackend(const QVariant &modelNodeBackend);
|
void setModelNodeBackend(const QVariant &modelNodeBackend);
|
||||||
void setTypeFilter(const QString &typeFilter);
|
void setTypeFilter(const QString &typeFilter);
|
||||||
void setSelectionOnly(bool value);
|
void setSelectionOnly(bool value);
|
||||||
|
void setSelectedItems(const QStringList &selectedItems);
|
||||||
QString typeFilter() const;
|
QString typeFilter() const;
|
||||||
bool selectionOnly() const;
|
bool selectionOnly() const;
|
||||||
|
QStringList selectedItems() const;
|
||||||
void setupModel();
|
void setupModel();
|
||||||
QStringList itemModel() const;
|
QStringList itemModel() const;
|
||||||
|
|
||||||
@@ -51,6 +52,7 @@ signals:
|
|||||||
void modelNodeBackendChanged();
|
void modelNodeBackendChanged();
|
||||||
void itemModelChanged();
|
void itemModelChanged();
|
||||||
void selectionOnlyChanged();
|
void selectionOnlyChanged();
|
||||||
|
void selectedItemsChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QVariant modelNodeBackend() const;
|
QVariant modelNodeBackend() const;
|
||||||
@@ -61,7 +63,7 @@ private:
|
|||||||
QList<qint32> m_modelInternalIds;
|
QList<qint32> m_modelInternalIds;
|
||||||
QmlDesigner::ModelNode m_modelNode;
|
QmlDesigner::ModelNode m_modelNode;
|
||||||
bool m_selectionOnly;
|
bool m_selectionOnly;
|
||||||
static QHash<int, QByteArray> m_roles;
|
QStringList m_selectedItems;
|
||||||
};
|
};
|
||||||
|
|
||||||
QML_DECLARE_TYPE(ItemFilterModel)
|
QML_DECLARE_TYPE(ItemFilterModel)
|
||||||
|
|||||||
Reference in New Issue
Block a user