diff options
author | Miikka Heikkinen <miikka.heikkinen@qt.io> | 2022-09-27 15:05:26 +0300 |
---|---|---|
committer | Miikka Heikkinen <miikka.heikkinen@qt.io> | 2022-10-10 13:53:03 +0000 |
commit | b8f4cd97d1bd495f04167e845ba049e54ad68f05 (patch) | |
tree | 09a31f04d2ed9e08b5c6ae0bb7a1d2ac64381127 | |
parent | b0fa74756504e83b690ca737c6a67de1de8e32ba (diff) |
Fix copying dynamic properties on materials
Fixes: QDS-7803
Change-Id: I24c8cd269965552a62fbbbc521efbff00811fa43
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
6 files changed, 87 insertions, 28 deletions
diff --git a/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml b/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml index 1e50f3f99b..2fecc7582a 100644 --- a/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml +++ b/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml @@ -125,7 +125,10 @@ Item { width: parent.width onAboutToShow: { - root.matSectionsModel = ["All"]; + if (root.currentMaterial.hasDynamicProperties) + root.matSectionsModel = ["All", "Custom"]; + else + root.matSectionsModel = ["All"]; switch (root.currentMaterial.materialType) { case "DefaultMaterial": diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.cpp index e9af23eb80..cb3a295259 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.cpp +++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.cpp @@ -73,6 +73,9 @@ QVariant MaterialBrowserModel::data(const QModelIndex &index, int role) const return matType; } + if (roleName == "hasDynamicProperties") + return !m_materialList.at(index.row()).dynamicProperties().isEmpty(); + return {}; } @@ -143,7 +146,8 @@ QHash<int, QByteArray> MaterialBrowserModel::roleNames() const {Qt::UserRole + 1, "materialName"}, {Qt::UserRole + 2, "materialInternalId"}, {Qt::UserRole + 3, "materialVisible"}, - {Qt::UserRole + 4, "materialType"} + {Qt::UserRole + 4, "materialType"}, + {Qt::UserRole + 5, "hasDynamicProperties"} }; return roles; } @@ -360,33 +364,47 @@ void MaterialBrowserModel::copyMaterialProperties(int idx, const QString §io setCopiedMaterialType(matType); m_allPropsCopied = section == "All"; + bool dynamicPropsCopied = section == "Custom"; QmlObjectNode mat(m_copiedMaterial); QSet<PropertyName> validProps; + QHash<PropertyName, TypeName> dynamicProps; PropertyNameList copiedProps; - // Base state properties are always valid - const auto baseProps = m_copiedMaterial.propertyNames(); - for (const auto &baseProp : baseProps) - validProps.insert(baseProp); - - if (!mat.isInBaseState()) { - QmlPropertyChanges changes = mat.propertyChangeForCurrentState(); - if (changes.isValid()) { - const QList<AbstractProperty> changedProps = changes.targetProperties(); - for (const auto &changedProp : changedProps) - validProps.insert(changedProp.name()); + if (dynamicPropsCopied || m_allPropsCopied) { + // Dynamic properties must always be set in base state + const QList<AbstractProperty> dynProps = m_copiedMaterial.dynamicProperties(); + for (const auto &prop : dynProps) { + dynamicProps.insert(prop.name(), prop.dynamicTypeName()); + validProps.insert(prop.name()); } } - if (mat.timelineIsActive()) { - const QList<QmlTimelineKeyframeGroup> keyframeGroups - = mat.currentTimeline().keyframeGroupsForTarget(m_copiedMaterial); - for (const auto &kfg : keyframeGroups) - validProps.insert(kfg.propertyName()); + if (!dynamicPropsCopied) { + // Base state properties are always valid + const auto baseProps = m_copiedMaterial.propertyNames(); + for (const auto &baseProp : baseProps) + validProps.insert(baseProp); + + if (!mat.isInBaseState()) { + QmlPropertyChanges changes = mat.propertyChangeForCurrentState(); + if (changes.isValid()) { + const QList<AbstractProperty> changedProps = changes.targetProperties(); + for (const auto &changedProp : changedProps) + validProps.insert(changedProp.name()); + } + } + + if (mat.timelineIsActive()) { + const QList<QmlTimelineKeyframeGroup> keyframeGroups + = mat.currentTimeline().keyframeGroupsForTarget(m_copiedMaterial); + for (const auto &kfg : keyframeGroups) + validProps.insert(kfg.propertyName()); + } } + validProps.remove("objectName"); - if (m_allPropsCopied || m_propertyGroupsObj.empty()) { + if (m_allPropsCopied || dynamicPropsCopied || m_propertyGroupsObj.empty()) { copiedProps = validProps.values(); } else { QJsonObject propsSpecObj = m_propertyGroupsObj.value(m_copiedMaterialType).toObject(); @@ -411,8 +429,10 @@ void MaterialBrowserModel::copyMaterialProperties(int idx, const QString §io PropertyCopyData data; data.name = propName; data.isValid = m_allPropsCopied || validProps.contains(propName); - data.isBinding = mat.hasBindingProperty(propName); if (data.isValid) { + if (dynamicProps.contains(propName)) + data.dynamicTypeName = dynamicProps[propName]; + data.isBinding = mat.hasBindingProperty(propName); if (data.isBinding) data.value = mat.expression(propName); else diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.h b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.h index c054d07527..3cd8b65a41 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.h +++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.h @@ -97,6 +97,7 @@ public: struct PropertyCopyData { PropertyName name; + TypeName dynamicTypeName; QVariant value; bool isBinding = false; bool isValid = false; diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp index 01ee657f84..94c75d93a7 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp +++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp @@ -25,6 +25,7 @@ #include "materialbrowserview.h" +#include "bindingproperty.h" #include "bundlematerial.h" #include "materialbrowserwidget.h" #include "materialbrowsermodel.h" @@ -105,13 +106,19 @@ WidgetInfo MaterialBrowserView::widgetInfo() // remove current properties PropertyNameList propNames; if (mat.isInBaseState()) { - propNames = material.propertyNames(); + const QList<AbstractProperty> baseProps = material.properties(); + for (const auto &baseProp : baseProps) { + if (!baseProp.isDynamic()) + propNames.append(baseProp.name()); + } } else { QmlPropertyChanges changes = mat.propertyChangeForCurrentState(); if (changes.isValid()) { const QList<AbstractProperty> changedProps = changes.targetProperties(); - for (const auto &changedProp : changedProps) - propNames.append(changedProp.name()); + for (const auto &changedProp : changedProps) { + if (!changedProp.isDynamic()) + propNames.append(changedProp.name()); + } } } for (const PropertyName &propName : qAsConst(propNames)) { @@ -122,14 +129,29 @@ WidgetInfo MaterialBrowserView::widgetInfo() // apply pasted properties for (const QmlDesigner::MaterialBrowserModel::PropertyCopyData &propData : propDatas) { - if (propData.name == "objectName") - continue; - if (propData.isValid) { - if (propData.isBinding) + const bool isDynamic = !propData.dynamicTypeName.isEmpty(); + const bool isBaseState = currentState().isBaseState(); + const bool hasProperty = mat.hasProperty(propData.name); + if (propData.isBinding) { + if (isDynamic && (!hasProperty || isBaseState)) { + mat.modelNode().bindingProperty(propData.name) + .setDynamicTypeNameAndExpression( + propData.dynamicTypeName, propData.value.toString()); + continue; + } mat.setBindingProperty(propData.name, propData.value.toString()); - else + } else { + const bool isRecording = mat.timelineIsActive() + && mat.currentTimeline().isRecording(); + if (isDynamic && (!hasProperty || (isBaseState && !isRecording))) { + mat.modelNode().variantProperty(propData.name) + .setDynamicTypeNameAndValue( + propData.dynamicTypeName, propData.value); + continue; + } mat.setVariantProperty(propData.name, propData.value); + } } else { mat.removeProperty(propData.name); } diff --git a/src/plugins/qmldesigner/designercore/include/modelnode.h b/src/plugins/qmldesigner/designercore/include/modelnode.h index def083f02f..e44234fffb 100644 --- a/src/plugins/qmldesigner/designercore/include/modelnode.h +++ b/src/plugins/qmldesigner/designercore/include/modelnode.h @@ -145,6 +145,7 @@ public: QList<NodeListProperty> nodeListProperties() const; QList<BindingProperty> bindingProperties() const; QList<SignalHandlerProperty> signalProperties() const; + QList<AbstractProperty> dynamicProperties() const; PropertyNameList propertyNames() const; bool hasProperties() const; diff --git a/src/plugins/qmldesigner/designercore/model/modelnode.cpp b/src/plugins/qmldesigner/designercore/model/modelnode.cpp index 913c67b1a2..c221215acc 100644 --- a/src/plugins/qmldesigner/designercore/model/modelnode.cpp +++ b/src/plugins/qmldesigner/designercore/model/modelnode.cpp @@ -691,6 +691,18 @@ QList<SignalHandlerProperty> ModelNode::signalProperties() const return propertyList; } +QList<AbstractProperty> ModelNode::dynamicProperties() const +{ + QList<AbstractProperty> propertyList; + + const QList<AbstractProperty> abstractProperties = properties(); + for (const AbstractProperty &abstractProperty : abstractProperties) { + if (abstractProperty.isDynamic()) + propertyList.append(abstractProperty); + } + return propertyList; +} + /*! \brief removes a property from this node \param name name of the property |