aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMahmoud Badri <mahmoud.badri@qt.io>2022-08-09 12:56:47 +0300
committerMahmoud Badri <mahmoud.badri@qt.io>2022-08-18 09:12:10 +0000
commitd4cc3fddc908bc87d806796f426ac91e5ee34f30 (patch)
treebbe1476d0059af1c0a9ebed2bbb800576a5a7561
parentec733999e1d5c31e75e5aa950f75bd41c136554b (diff)
QmlDesigner: Implement copy/paste material properties
Fixes: QDS-7014 Change-Id: I2a8b779f97de353836a4d506b715720b490c349f Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: Samuel Ghinet <samuel.ghinet@qt.io> Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
-rw-r--r--share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml41
-rw-r--r--src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.cpp50
-rw-r--r--src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.h12
-rw-r--r--src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp29
4 files changed, 111 insertions, 21 deletions
diff --git a/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml b/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml
index 0419b945b9..bc8582d359 100644
--- a/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml
+++ b/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml
@@ -92,27 +92,48 @@ Item {
StudioControls.MenuItem {
text: qsTr("Apply to selected (replace)")
- enabled: currentMaterial && materialBrowserModel.hasModelSelection
- onTriggered: materialBrowserModel.applyToSelected(currentMaterial.materialInternalId, false)
+ enabled: root.currentMaterial && materialBrowserModel.hasModelSelection
+ onTriggered: materialBrowserModel.applyToSelected(root.currentMaterial.materialInternalId, false)
}
StudioControls.MenuItem {
text: qsTr("Apply to selected (add)")
- enabled: currentMaterial && materialBrowserModel.hasModelSelection
- onTriggered: materialBrowserModel.applyToSelected(currentMaterial.materialInternalId, true)
+ enabled: root.currentMaterial && materialBrowserModel.hasModelSelection
+ onTriggered: materialBrowserModel.applyToSelected(root.currentMaterial.materialInternalId, true)
+ }
+
+ StudioControls.MenuSeparator {
+ height: StudioTheme.Values.border
+ }
+
+ StudioControls.MenuItem {
+ text: qsTr("Copy properties")
+ enabled: root.currentMaterial
+ onTriggered: materialBrowserModel.copyMaterialProperties(root.currentMaterialIdx)
+ }
+
+ StudioControls.MenuItem {
+ text: qsTr("Paste properties")
+ enabled: root.currentMaterial && root.currentMaterial.materialType.toString()
+ === materialBrowserModel.copiedMaterialType.toString()
+ onTriggered: materialBrowserModel.pasteMaterialProperties(root.currentMaterialIdx)
+ }
+
+ StudioControls.MenuSeparator {
+ height: StudioTheme.Values.border
}
StudioControls.MenuItem {
text: qsTr("Duplicate")
- enabled: currentMaterial
- onTriggered: materialBrowserModel.duplicateMaterial(currentMaterialIdx)
+ enabled: root.currentMaterial
+ onTriggered: materialBrowserModel.duplicateMaterial(root.currentMaterialIdx)
}
StudioControls.MenuItem {
text: qsTr("Rename")
- enabled: currentMaterial
+ enabled: root.currentMaterial
onTriggered: {
- var item = gridRepeater.itemAt(currentMaterialIdx);
+ var item = gridRepeater.itemAt(root.currentMaterialIdx);
if (item)
item.startRename();
}
@@ -120,9 +141,9 @@ Item {
StudioControls.MenuItem {
text: qsTr("Delete")
- enabled: currentMaterial
+ enabled: root.currentMaterial
- onTriggered: materialBrowserModel.deleteMaterial(currentMaterialIdx)
+ onTriggered: materialBrowserModel.deleteMaterial(root.currentMaterialIdx)
}
StudioControls.MenuSeparator {}
diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.cpp
index af74c1489d..2998cc38c8 100644
--- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.cpp
+++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.cpp
@@ -24,9 +24,13 @@
****************************************************************************/
#include "materialbrowsermodel.h"
-#include "variantproperty.h"
+
+#include <bindingproperty.h>
#include <designmodewidget.h>
#include <qmldesignerplugin.h>
+#include <qmlobjectnode.h>
+#include "variantproperty.h"
+#include "utils/qtcassert.h"
namespace QmlDesigner {
@@ -46,24 +50,23 @@ int MaterialBrowserModel::rowCount(const QModelIndex &) const
QVariant MaterialBrowserModel::data(const QModelIndex &index, int role) const
{
- if (!index.isValid() || index.row() >= m_materialList.count()) {
- qWarning() << Q_FUNC_INFO << "invalid index requested";
- return {};
- }
+ QTC_ASSERT(index.isValid() && index.row() < m_materialList.count(), return {});
+ QTC_ASSERT(roleNames().contains(role), return {});
- if (roleNames().value(role) == "materialName") {
+ QByteArray roleName = roleNames().value(role);
+ if (roleName == "materialName") {
QVariant objName = m_materialList.at(index.row()).variantProperty("objectName").value();
return objName.isValid() ? objName : "";
}
- if (roleNames().value(role) == "materialInternalId")
+ if (roleName == "materialInternalId")
return m_materialList.at(index.row()).internalId();
- if (roleNames().value(role) == "materialVisible")
+ if (roleName == "materialVisible")
return isMaterialVisible(index.row());
- if (!roleNames().contains(role))
- qWarning() << Q_FUNC_INFO << "invalid role requested";
+ if (roleName == "materialType")
+ return m_materialList.at(index.row()).type();
return {};
}
@@ -88,6 +91,7 @@ QHash<int, QByteArray> MaterialBrowserModel::roleNames() const
{Qt::UserRole + 1, "materialName"},
{Qt::UserRole + 2, "materialInternalId"},
{Qt::UserRole + 3, "materialVisible"},
+ {Qt::UserRole + 4, "materialType"}
};
return roles;
}
@@ -120,6 +124,20 @@ void MaterialBrowserModel::setHasModelSelection(bool b)
emit hasModelSelectionChanged();
}
+TypeName MaterialBrowserModel::copiedMaterialType() const
+{
+ return m_copiedMaterialType;
+}
+
+void MaterialBrowserModel::setCopiedMaterialType(const TypeName &matType)
+{
+ if (matType == m_copiedMaterialType)
+ return;
+
+ m_copiedMaterialType = matType;
+ emit copiedMaterialTypeChanged();
+}
+
QList<ModelNode> MaterialBrowserModel::materials() const
{
return m_materialList;
@@ -262,6 +280,18 @@ void MaterialBrowserModel::duplicateMaterial(int idx)
emit duplicateMaterialTriggered(m_materialList.at(idx));
}
+void MaterialBrowserModel::copyMaterialProperties(int idx)
+{
+ ModelNode mat = m_materialList.at(idx);
+ m_copiedMaterialProps = mat.properties();
+ setCopiedMaterialType(mat.type());
+}
+
+void MaterialBrowserModel::pasteMaterialProperties(int idx)
+{
+ emit pasteMaterialPropertiesTriggered(m_materialList.at(idx), m_copiedMaterialProps);
+}
+
void MaterialBrowserModel::deleteMaterial(int idx)
{
m_materialList[idx].destroy();
diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.h b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.h
index eb258b1efe..cb40ecd9d5 100644
--- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.h
+++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.h
@@ -26,6 +26,7 @@
#pragma once
#include <modelnode.h>
+#include <qmlobjectnode.h>
#include <QAbstractListModel>
#include <QObject>
@@ -41,6 +42,7 @@ class MaterialBrowserModel : public QAbstractListModel
Q_PROPERTY(int selectedIndex MEMBER m_selectedIndex NOTIFY selectedIndexChanged)
Q_PROPERTY(bool hasQuick3DImport READ hasQuick3DImport WRITE setHasQuick3DImport NOTIFY hasQuick3DImportChanged)
Q_PROPERTY(bool hasModelSelection READ hasModelSelection WRITE setHasModelSelection NOTIFY hasModelSelectionChanged)
+ Q_PROPERTY(TypeName copiedMaterialType READ copiedMaterialType WRITE setCopiedMaterialType NOTIFY copiedMaterialTypeChanged)
public:
MaterialBrowserModel(QObject *parent = nullptr);
@@ -58,6 +60,9 @@ public:
bool hasModelSelection() const;
void setHasModelSelection(bool b);
+ TypeName copiedMaterialType() const;
+ void setCopiedMaterialType(const TypeName &matType);
+
QList<ModelNode> materials() const;
void setMaterials(const QList<ModelNode> &materials, bool hasQuick3DImport);
void removeMaterial(const ModelNode &material);
@@ -71,6 +76,8 @@ public:
Q_INVOKABLE void selectMaterial(int idx, bool force = false);
Q_INVOKABLE void duplicateMaterial(int idx);
+ Q_INVOKABLE void copyMaterialProperties(int idx);
+ Q_INVOKABLE void pasteMaterialProperties(int idx);
Q_INVOKABLE void deleteMaterial(int idx);
Q_INVOKABLE void renameMaterial(int idx, const QString &newName);
Q_INVOKABLE void addNewMaterial();
@@ -81,11 +88,14 @@ signals:
void isEmptyChanged();
void hasQuick3DImportChanged();
void hasModelSelectionChanged();
+ void copiedMaterialTypeChanged();
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);
private:
bool isMaterialVisible(int idx) const;
@@ -93,12 +103,14 @@ private:
QString m_searchText;
QList<ModelNode> m_materialList;
+ QList<AbstractProperty> m_copiedMaterialProps;
QHash<qint32, int> m_materialIndexHash; // internalId -> index
int m_selectedIndex = 0;
bool m_isEmpty = true;
bool m_hasQuick3DImport = false;
bool m_hasModelSelection = false;
+ TypeName m_copiedMaterialType;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp
index ebb9671e50..c8b788ea3a 100644
--- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp
+++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp
@@ -24,15 +24,18 @@
****************************************************************************/
#include "materialbrowserview.h"
+
+#include "bindingproperty.h"
#include "materialbrowserwidget.h"
#include "materialbrowsermodel.h"
#include "nodeabstractproperty.h"
#include "qmlobjectnode.h"
#include "variantproperty.h"
+
#include <coreplugin/icore.h>
+#include <designmodecontext.h>
#include <nodeinstanceview.h>
#include <qmldesignerconstants.h>
-#include <designmodecontext.h>
#include <QQuickItem>
@@ -86,6 +89,30 @@ WidgetInfo MaterialBrowserView::widgetInfo()
[&] (const ModelNode &material) {
emitCustomNotification("duplicate_material", {material});
});
+
+ connect(matBrowserModel, &MaterialBrowserModel::pasteMaterialPropertiesTriggered, this,
+ [&] (const ModelNode &material, const QList<AbstractProperty> &props) {
+ QmlObjectNode mat(material);
+ executeInTransaction(__FUNCTION__, [&] {
+ // remove current properties
+ const PropertyNameList propNames = material.propertyNames();
+ for (const PropertyName &propName : propNames) {
+ if (propName != "objectName")
+ mat.removeProperty(propName);
+ }
+
+ // apply pasted properties
+ for (const AbstractProperty &prop : props) {
+ if (prop.name() == "objectName")
+ continue;
+
+ if (prop.isVariantProperty())
+ mat.setVariantProperty(prop.name(), prop.toVariantProperty().value());
+ else if (prop.isBindingProperty())
+ mat.setBindingProperty(prop.name(), prop.toBindingProperty().expression());
+ }
+ });
+ });
}
return createWidgetInfo(m_widget.data(),