diff options
author | Mahmoud Badri <mahmoud.badri@qt.io> | 2022-08-12 11:47:36 +0300 |
---|---|---|
committer | Mahmoud Badri <mahmoud.badri@qt.io> | 2022-08-18 15:11:18 +0000 |
commit | 2d86c290ce52953dbb723017b8b226b8599bbeed (patch) | |
tree | 5a5cfdbeb283285012b5c1bfd6130bb61aa4dcab | |
parent | c7f742a54603b77b9ad34da299996122b970574b (diff) | |
download | qt-creator-2d86c290ce52953dbb723017b8b226b8599bbeed.tar.gz |
QmlDesigner: Implement copying specific material properties section
Change-Id: I34bed00c89018e86941c4e5a7ddeae44c06f850d
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
4 files changed, 147 insertions, 26 deletions
diff --git a/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml b/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml index 468b4fb424..a8692f3ef9 100644 --- a/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml +++ b/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml @@ -39,6 +39,8 @@ Item { property var currentMaterial: null property int currentMaterialIdx: 0 + property var matSectionsModel: [] + // Called also from C++ to close context menu on focus out function closeContextMenu() { @@ -108,16 +110,45 @@ Item { height: StudioTheme.Values.border } - StudioControls.MenuItem { - text: qsTr("Copy properties") + StudioControls.Menu { + title: qsTr("Copy properties") enabled: root.currentMaterial - onTriggered: materialBrowserModel.copyMaterialProperties(root.currentMaterialIdx) + + width: parent.width + + onAboutToShow: { + root.matSectionsModel = ["All"]; + + switch (root.currentMaterial.materialType) { + case "DefaultMaterial": + root.matSectionsModel = root.matSectionsModel.concat(materialBrowserModel.defaultMaterialSections); + break; + + case "PrincipledMaterial": + root.matSectionsModel = root.matSectionsModel.concat(materialBrowserModel.principledMaterialSections); + break; + + case "CustomMaterial": + root.matSectionsModel = root.matSectionsModel.concat(materialBrowserModel.customMaterialSections); + break; + } + } + + Repeater { + model: root.matSectionsModel + + StudioControls.MenuItem { + text: modelData + enabled: root.currentMaterial + onTriggered: materialBrowserModel.copyMaterialProperties(root.currentMaterialIdx, modelData) + } + } } StudioControls.MenuItem { text: qsTr("Paste properties") - enabled: root.currentMaterial && root.currentMaterial.materialType.toString() - === materialBrowserModel.copiedMaterialType.toString() + enabled: root.currentMaterial && root.currentMaterial.materialType + === materialBrowserModel.copiedMaterialType onTriggered: materialBrowserModel.pasteMaterialProperties(root.currentMaterialIdx) } diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.cpp index 78c25d2c2b..4027a1c75a 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.cpp +++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.cpp @@ -65,8 +65,12 @@ QVariant MaterialBrowserModel::data(const QModelIndex &index, int role) const if (roleName == "materialVisible") return isMaterialVisible(index.row()); - if (roleName == "materialType") - return m_materialList.at(index.row()).type(); + if (roleName == "materialType") { + QString matType = QString::fromLatin1(m_materialList.at(index.row()).type()); + if (matType.startsWith("QtQuick3D.")) + matType.remove("QtQuick3D."); + return matType; + } return {}; } @@ -85,6 +89,50 @@ bool MaterialBrowserModel::isValidIndex(int idx) const return idx > -1 && idx < rowCount(); } +/** + * @brief Loads and parses propertyGroups.json from QtQuick3D module's designer folder + * + * propertyGroups.json contains lists of QtQuick3D objects' properties grouped by sections + * + * @param path path to propertyGroups.json file + */ +void MaterialBrowserModel::loadPropertyGroups(const QString &path) +{ + bool ok = true; + + if (m_propertyGroupsObj.isEmpty()) { + QFile matPropsFile(path); + + if (!matPropsFile.open(QIODevice::ReadOnly)) { + qWarning("Couldn't open propertyGroups.json"); + ok = false; + } + + if (ok) { + QJsonDocument matPropsJsonDoc = QJsonDocument::fromJson(matPropsFile.readAll()); + if (matPropsJsonDoc.isNull()) { + qWarning("Invalid propertyGroups.json file"); + ok = false; + } else { + m_propertyGroupsObj = matPropsJsonDoc.object(); + } + } + } + + m_defaultMaterialSections.clear(); + m_principledMaterialSections.clear(); + m_customMaterialSections.clear(); + if (ok) { + m_defaultMaterialSections.append(m_propertyGroupsObj.value("DefaultMaterial").toObject().keys()); + m_principledMaterialSections.append(m_propertyGroupsObj.value("PrincipledMaterial").toObject().keys()); + + QStringList customMatSections = m_propertyGroupsObj.value("CustomMaterial").toObject().keys(); + if (customMatSections.size() > 1) // as of now custom material has only 1 section, so we don't add it + m_customMaterialSections.append(customMatSections); + } + emit materialSectionsChanged(); +} + QHash<int, QByteArray> MaterialBrowserModel::roleNames() const { static const QHash<int, QByteArray> roles { @@ -138,12 +186,12 @@ void MaterialBrowserModel::setHasMaterialRoot(bool b) emit hasMaterialRootChanged(); } -TypeName MaterialBrowserModel::copiedMaterialType() const +QString MaterialBrowserModel::copiedMaterialType() const { return m_copiedMaterialType; } -void MaterialBrowserModel::setCopiedMaterialType(const TypeName &matType) +void MaterialBrowserModel::setCopiedMaterialType(const QString &matType) { if (matType == m_copiedMaterialType) return; @@ -294,16 +342,40 @@ void MaterialBrowserModel::duplicateMaterial(int idx) emit duplicateMaterialTriggered(m_materialList.at(idx)); } -void MaterialBrowserModel::copyMaterialProperties(int idx) +void MaterialBrowserModel::copyMaterialProperties(int idx, const QString §ion) { ModelNode mat = m_materialList.at(idx); - m_copiedMaterialProps = mat.properties(); - setCopiedMaterialType(mat.type()); + QString matType = QString::fromLatin1(mat.type()); + + if (matType.startsWith("QtQuick3D.")) + matType.remove("QtQuick3D."); + + setCopiedMaterialType(matType); + m_allPropsCopied = section == "All"; + + if (m_allPropsCopied || m_propertyGroupsObj.empty()) { + m_copiedMaterialProps = mat.properties(); + } else { + QJsonObject propsSpecObj = m_propertyGroupsObj.value(m_copiedMaterialType).toObject(); + if (propsSpecObj.contains(section)) { // should always be true + m_copiedMaterialProps.clear(); + const QJsonArray propNames = propsSpecObj.value(section).toArray(); + for (const QJsonValueRef &propName : propNames) + m_copiedMaterialProps.append(mat.property(propName.toString().toLatin1())); + + if (section == "Base") { // add QtQuick3D.Material base props as well + QJsonObject propsMatObj = m_propertyGroupsObj.value("Material").toObject(); + const QJsonArray propNames = propsMatObj.value("Base").toArray(); + for (const QJsonValueRef &propName : propNames) + m_copiedMaterialProps.append(mat.property(propName.toString().toLatin1())); + } + } + } } void MaterialBrowserModel::pasteMaterialProperties(int idx) { - emit pasteMaterialPropertiesTriggered(m_materialList.at(idx), m_copiedMaterialProps); + emit pasteMaterialPropertiesTriggered(m_materialList.at(idx), m_copiedMaterialProps, m_allPropsCopied); } void MaterialBrowserModel::deleteMaterial(int idx) diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.h b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.h index bafcdc1fa8..5f38e7488e 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.h +++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.h @@ -25,6 +25,7 @@ #pragma once +#include "qjsonobject.h" #include <modelnode.h> #include <qmlobjectnode.h> @@ -43,7 +44,10 @@ class MaterialBrowserModel : public QAbstractListModel Q_PROPERTY(bool hasQuick3DImport READ hasQuick3DImport WRITE setHasQuick3DImport NOTIFY hasQuick3DImportChanged) Q_PROPERTY(bool hasModelSelection READ hasModelSelection WRITE setHasModelSelection NOTIFY hasModelSelectionChanged) Q_PROPERTY(bool hasMaterialRoot READ hasMaterialRoot WRITE setHasMaterialRoot NOTIFY hasMaterialRootChanged) - Q_PROPERTY(TypeName copiedMaterialType READ copiedMaterialType WRITE setCopiedMaterialType NOTIFY copiedMaterialTypeChanged) + Q_PROPERTY(QString copiedMaterialType READ copiedMaterialType WRITE setCopiedMaterialType NOTIFY copiedMaterialTypeChanged) + Q_PROPERTY(QStringList defaultMaterialSections MEMBER m_defaultMaterialSections NOTIFY materialSectionsChanged) + Q_PROPERTY(QStringList principledMaterialSections MEMBER m_principledMaterialSections NOTIFY materialSectionsChanged) + Q_PROPERTY(QStringList customMaterialSections MEMBER m_customMaterialSections NOTIFY materialSectionsChanged) public: MaterialBrowserModel(QObject *parent = nullptr); @@ -64,8 +68,8 @@ public: bool hasMaterialRoot() const; void setHasMaterialRoot(bool b); - TypeName copiedMaterialType() const; - void setCopiedMaterialType(const TypeName &matType); + QString copiedMaterialType() const; + void setCopiedMaterialType(const QString &matType); QList<ModelNode> materials() const; void setMaterials(const QList<ModelNode> &materials, bool hasQuick3DImport); @@ -75,12 +79,13 @@ public: void updateSelectedMaterial(); int materialIndex(const ModelNode &material) const; ModelNode materialAt(int idx) const; + void loadPropertyGroups(const QString &path); void resetModel(); Q_INVOKABLE void selectMaterial(int idx, bool force = false); Q_INVOKABLE void duplicateMaterial(int idx); - Q_INVOKABLE void copyMaterialProperties(int idx); + Q_INVOKABLE void copyMaterialProperties(int idx, const QString §ion); Q_INVOKABLE void pasteMaterialProperties(int idx); Q_INVOKABLE void deleteMaterial(int idx); Q_INVOKABLE void renameMaterial(int idx, const QString &newName); @@ -94,13 +99,15 @@ signals: void hasModelSelectionChanged(); void hasMaterialRootChanged(); void copiedMaterialTypeChanged(); + void materialSectionsChanged(); void selectedIndexChanged(int idx); void renameMaterialTriggered(const QmlDesigner::ModelNode &material, const QString &newName); void applyToSelectedTriggered(const QmlDesigner::ModelNode &material, bool add = false); void addNewMaterialTriggered(); void duplicateMaterialTriggered(const QmlDesigner::ModelNode &material); void pasteMaterialPropertiesTriggered(const QmlDesigner::ModelNode &material, - const QList<QmlDesigner::AbstractProperty> &props); + const QList<QmlDesigner::AbstractProperty> &props, + bool all); private: bool isMaterialVisible(int idx) const; @@ -108,15 +115,20 @@ private: QString m_searchText; QList<ModelNode> m_materialList; + QStringList m_defaultMaterialSections; + QStringList m_principledMaterialSections; + QStringList m_customMaterialSections; QList<AbstractProperty> m_copiedMaterialProps; QHash<qint32, int> m_materialIndexHash; // internalId -> index + QJsonObject m_propertyGroupsObj; int m_selectedIndex = 0; bool m_isEmpty = true; bool m_hasQuick3DImport = false; bool m_hasModelSelection = false; bool m_hasMaterialRoot = false; - TypeName m_copiedMaterialType; + bool m_allPropsCopied = true; + QString m_copiedMaterialType; }; } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp index ac792f6470..0d05b12d6a 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp +++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp @@ -29,6 +29,7 @@ #include "materialbrowserwidget.h" #include "materialbrowsermodel.h" #include "nodeabstractproperty.h" +#include "nodemetainfo.h" #include "qmlobjectnode.h" #include "variantproperty.h" @@ -43,7 +44,6 @@ namespace QmlDesigner { MaterialBrowserView::MaterialBrowserView(QObject *parent) : AbstractView(parent) - {} MaterialBrowserView::~MaterialBrowserView() @@ -91,14 +91,16 @@ WidgetInfo MaterialBrowserView::widgetInfo() }); connect(matBrowserModel, &MaterialBrowserModel::pasteMaterialPropertiesTriggered, this, - [&] (const ModelNode &material, const QList<AbstractProperty> &props) { + [&] (const ModelNode &material, const QList<AbstractProperty> &props, bool all) { QmlObjectNode mat(material); executeInTransaction(__FUNCTION__, [&] { - // remove current properties - const PropertyNameList propNames = material.propertyNames(); - for (const PropertyName &propName : propNames) { - if (propName != "objectName") - mat.removeProperty(propName); + if (all) { // all material properties copied + // remove current properties + const PropertyNameList propNames = material.propertyNames(); + for (const PropertyName &propName : propNames) { + if (propName != "objectName") + mat.removeProperty(propName); + } } // apply pasted properties @@ -126,6 +128,10 @@ void MaterialBrowserView::modelAttached(Model *model) { AbstractView::modelAttached(model); + QString matPropsPath = model->metaInfo("QtQuick3D.Material").importDirectoryPath() + + "/designer/propertyGroups.json"; + m_widget->materialBrowserModel()->loadPropertyGroups(matPropsPath); + m_widget->clearSearchFilter(); m_widget->materialBrowserModel()->setHasMaterialRoot(rootModelNode().isSubclassOf("QtQuick3D.Material")); m_hasQuick3DImport = model->hasImport("QtQuick3D"); |