From 0b51afe21d6aa72b4b9faafc14f759d77f428e32 Mon Sep 17 00:00:00 2001 From: Mahmoud Badri Date: Wed, 25 May 2022 21:42:15 +0300 Subject: [PATCH] QmlDesigner: Implement "duplicate material" feature Fixes: QDS-7013 Change-Id: I28a11dbd9d6586631c0edcf8003e551917eaac98 Reviewed-by: Reviewed-by: Miikka Heikkinen Reviewed-by: Samuel Ghinet Reviewed-by: Thomas Hartmann --- .../MaterialBrowser.qml | 8 ++- .../materialbrowser/materialbrowsermodel.cpp | 11 ++-- .../materialbrowser/materialbrowsermodel.h | 2 + .../materialbrowser/materialbrowserview.cpp | 62 ++++++++----------- .../materialbrowser/materialbrowserview.h | 6 -- .../materialeditor/materialeditorview.cpp | 37 +++++++++++ .../materialeditor/materialeditorview.h | 1 + 7 files changed, 81 insertions(+), 46 deletions(-) diff --git a/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml b/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml index 77eedc67de1..ab061e4289c 100644 --- a/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml +++ b/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml @@ -102,6 +102,12 @@ Item { onTriggered: materialBrowserModel.applyToSelected(currentMaterial.materialInternalId, true) } + StudioControls.MenuItem { + text: qsTr("Duplicate") + enabled: currentMaterial + onTriggered: materialBrowserModel.duplicateMaterial(currentMaterialIdx) + } + StudioControls.MenuItem { text: qsTr("Rename") enabled: currentMaterial @@ -116,7 +122,7 @@ Item { text: qsTr("Delete") enabled: currentMaterial - onTriggered: materialBrowserModel.deleteMaterial(currentMaterial.materialInternalId) + onTriggered: materialBrowserModel.deleteMaterial(currentMaterialIdx) } StudioControls.MenuSeparator {} diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.cpp index d4bee4fcced..d0420163c3a 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.cpp +++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.cpp @@ -246,11 +246,14 @@ void MaterialBrowserModel::selectMaterial(int idx, bool force) } } -void MaterialBrowserModel::deleteMaterial(qint32 internalId) +void MaterialBrowserModel::duplicateMaterial(int idx) { - int idx = m_materialIndexHash.value(internalId); - if (isValidIndex(idx)) - m_materialList[idx].destroy(); + emit duplicateMaterialTriggered(m_materialList.at(idx)); +} + +void MaterialBrowserModel::deleteMaterial(int idx) +{ + m_materialList[idx].destroy(); } void MaterialBrowserModel::renameMaterial(int idx, const QString &newName) diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.h b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.h index 5f00596ef9e..32db357caeb 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.h +++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.h @@ -68,6 +68,7 @@ public: void resetModel(); Q_INVOKABLE void selectMaterial(int idx, bool force = false); + Q_INVOKABLE void duplicateMaterial(int idx); Q_INVOKABLE void deleteMaterial(int idx); Q_INVOKABLE void renameMaterial(int idx, const QString &newName); Q_INVOKABLE void addNewMaterial(); @@ -82,6 +83,7 @@ signals: 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); private: bool isMaterialVisible(int idx) const; diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp index 3239d2f302b..41186302144 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp +++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp @@ -54,16 +54,33 @@ WidgetInfo MaterialBrowserView::widgetInfo() { if (m_widget.isNull()) { m_widget = new MaterialBrowserWidget; - connect(m_widget->materialBrowserModel().data(), SIGNAL(selectedIndexChanged(int)), - this, SLOT(handleSelectedMaterialChanged(int))); - connect(m_widget->materialBrowserModel().data(), - SIGNAL(applyToSelectedTriggered(const QmlDesigner::ModelNode &, bool)), - this, SLOT(handleApplyToSelectedTriggered(const QmlDesigner::ModelNode &, bool))); - connect(m_widget->materialBrowserModel().data(), - SIGNAL(renameMaterialTriggered(const QmlDesigner::ModelNode &, const QString &)), - this, SLOT(handleRenameMaterial(const QmlDesigner::ModelNode &, const QString &))); - connect(m_widget->materialBrowserModel().data(), SIGNAL(addNewMaterialTriggered()), - this, SLOT(handleAddNewMaterial())); + MaterialBrowserModel *matBrowserModel = m_widget->materialBrowserModel().data(); + + // custom notifications below are sent to the MaterialEditor + + connect(matBrowserModel, &MaterialBrowserModel::selectedIndexChanged, this, [&] (int idx) { + ModelNode matNode = m_widget->materialBrowserModel()->materialAt(idx); + emitCustomNotification("selected_material_changed", {matNode}, {}); + }); + + connect(matBrowserModel, &MaterialBrowserModel::applyToSelectedTriggered, this, + [&] (const ModelNode &material, bool add) { + emitCustomNotification("apply_to_selected_triggered", {material}, {add}); + }); + + connect(matBrowserModel, &MaterialBrowserModel::renameMaterialTriggered, this, + [&] (const ModelNode &material, const QString &newName) { + emitCustomNotification("rename_material", {material}, {newName}); + }); + + connect(matBrowserModel, &MaterialBrowserModel::addNewMaterialTriggered, this, [&] { + emitCustomNotification("add_new_material"); + }); + + connect(matBrowserModel, &MaterialBrowserModel::duplicateMaterialTriggered, this, + [&] (const ModelNode &material) { + emitCustomNotification("duplicate_material", {material}); + }); } return createWidgetInfo(m_widget.data(), @@ -240,29 +257,4 @@ void MaterialBrowserView::customNotification(const AbstractView *view, const QSt } } -void MaterialBrowserView::handleSelectedMaterialChanged(int idx) -{ - ModelNode matNode = m_widget->materialBrowserModel()->materialAt(idx); - // to MaterialEditor... - emitCustomNotification("selected_material_changed", {matNode}, {}); -} - -void MaterialBrowserView::handleApplyToSelectedTriggered(const ModelNode &material, bool add) -{ - // to MaterialEditor... - emitCustomNotification("apply_to_selected_triggered", {material}, {add}); -} - -void MaterialBrowserView::handleRenameMaterial(const ModelNode &material, const QString &newName) -{ - // to MaterialEditor... - emitCustomNotification("rename_material", {material}, {newName}); -} - -void MaterialBrowserView::handleAddNewMaterial() -{ - // to MaterialEditor... - emitCustomNotification("add_new_material"); -} - } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.h b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.h index 28e4694cd65..e140eede136 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.h +++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.h @@ -68,12 +68,6 @@ private: QPointer m_widget; bool m_hasQuick3DImport = false; bool m_autoSelectModelMaterial = false; // TODO: wire this to some action - -private slots: - void handleSelectedMaterialChanged(int idx); - void handleApplyToSelectedTriggered(const QmlDesigner::ModelNode &material, bool add = false); - void handleRenameMaterial(const QmlDesigner::ModelNode &material, const QString &newName); - void handleAddNewMaterial(); }; } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp b/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp index c28152276c4..1b4ce59fb50 100644 --- a/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp +++ b/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp @@ -745,6 +745,41 @@ void MaterialEditorView::renameMaterial(ModelNode &material, const QString &newN }); } +void MaterialEditorView::duplicateMaterial(const ModelNode &material) +{ + QTC_ASSERT(material.isValid(), return); + + ensureMaterialLibraryNode(); + + TypeName matType = material.type(); + QmlObjectNode sourceMat(material); + + executeInTransaction(__FUNCTION__, [&] { + // create the duplicate material + NodeMetaInfo metaInfo = model()->metaInfo(matType); + QmlObjectNode duplicateMat = createModelNode(matType, metaInfo.majorVersion(), metaInfo.minorVersion()); + + // set name and id + QString newName = sourceMat.modelNode().variantProperty("objectName").value().toString() + " copy"; + duplicateMat.modelNode().variantProperty("objectName").setValue(newName); + duplicateMat.modelNode().setIdWithoutRefactoring(generateIdFromName(newName)); + + // sync properties + const QList props = material.properties(); + for (const AbstractProperty &prop : props) { + if (prop.name() == "objectName") + continue; + + if (prop.isVariantProperty()) + duplicateMat.setVariantProperty(prop.name(), prop.toVariantProperty().value()); + else if (prop.isBindingProperty()) + duplicateMat.setBindingProperty(prop.name(), prop.toBindingProperty().expression()); + } + + m_materialLibrary.defaultNodeListProperty().reparentHere(duplicateMat); + }); +} + void MaterialEditorView::customNotification(const AbstractView *view, const QString &identifier, const QList &nodeList, const QList &data) { @@ -758,6 +793,8 @@ void MaterialEditorView::customNotification(const AbstractView *view, const QStr renameMaterial(m_selectedMaterial, data.first().toString()); } else if (identifier == "add_new_material") { handleToolBarAction(MaterialEditorContextObject::AddNewMaterial); + } else if (identifier == "duplicate_material") { + duplicateMaterial(nodeList.first()); } } diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditorview.h b/src/plugins/qmldesigner/components/materialeditor/materialeditorview.h index 9d096064bc2..8ab30a63f44 100644 --- a/src/plugins/qmldesigner/components/materialeditor/materialeditorview.h +++ b/src/plugins/qmldesigner/components/materialeditor/materialeditorview.h @@ -106,6 +106,7 @@ private: void commitAuxValueToModel(const PropertyName &propertyName, const QVariant &value); void removePropertyFromModel(const PropertyName &propertyName); void renameMaterial(ModelNode &material, const QString &newName); + void duplicateMaterial(const ModelNode &material); bool noValidSelection() const;