DynamicPropertiesModel: handle instance property changes

Instance property changes are now taken into account for dynamic properties.
This avoids situations where the property value is cleared unintentionally.

Task-number: QDS-13513
Change-Id: I2b52ae2db721bf09b2310ba7c5bd4b3e0de3fab2
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Rafal Stawarski
2025-03-11 12:16:11 +01:00
parent e51925e4e1
commit 58662eb626
6 changed files with 66 additions and 28 deletions

View File

@@ -19,7 +19,8 @@ QHash<int, QByteArray> DynamicPropertiesItem::roleNames()
return {{TargetNameRole, "target"},
{PropertyNameRole, "name"},
{PropertyTypeRole, "type"},
{PropertyValueRole, "value"}};
{PropertyValueRole, "value"},
{InstancePropertyValueRole, "instanceValue"}};
}
QStringList DynamicPropertiesItem::headerLabels()
@@ -58,6 +59,9 @@ void DynamicPropertiesItem::updateProperty(const AbstractProperty &property)
setData(property.name().toByteArray(), PropertyNameRole);
setData(property.dynamicTypeName(), PropertyTypeRole);
const auto qmlObjectNode = QmlObjectNode(property.parentModelNode());
setData(qmlObjectNode.instanceValue(property.name()), InstancePropertyValueRole);
if (property.isVariantProperty()) {
if (std::optional<const QmlObjectNode> nodeInState = parentIfNotDefaultState(property))
setData(nodeInState->modelValue(property.name()), PropertyValueRole);

View File

@@ -18,7 +18,8 @@ public:
TargetNameRole,
PropertyNameRole,
PropertyTypeRole,
PropertyValueRole
PropertyValueRole,
InstancePropertyValueRole
};
static QHash<int, QByteArray> roleNames();

View File

@@ -355,6 +355,21 @@ void DynamicPropertiesModel::dispatchPropertyChanges(const AbstractProperty &abs
}
}
void DynamicPropertiesModel::handleInstancePropertyChanged(const ModelNode &modelNode,
PropertyNameView propertyName)
{
if (modelNode != singleSelectedNode())
return;
QmlObjectNode qmlObjectNode(modelNode);
if (qmlObjectNode.isValid() && qmlObjectNode.currentState().isValid()) {
const AbstractProperty property = modelNode.property(propertyName);
if (property.isDynamic()) {
updateItem(property);
}
}
}
const QList<ModelNode> DynamicPropertiesModel::selectedNodes() const
{
if (m_explicitSelection)

View File

@@ -57,6 +57,8 @@ public:
void dispatchPropertyChanges(const AbstractProperty &abstractProperty);
void handleInstancePropertyChanged(const ModelNode &modelNode, PropertyNameView propertyName);
protected:
QHash<int, QByteArray> roleNames() const override;

View File

@@ -71,8 +71,10 @@ void DynamicPropertiesProxyModel::initModel(DynamicPropertiesModel *model)
connect(m_model, &QAbstractItemModel::rowsInserted,
this, &QAbstractItemModel::rowsInserted);
connect(m_model, &QAbstractItemModel::dataChanged,
this, [this](const QModelIndex &topLeft, const QModelIndex &, const QList<int> &) {
connect(m_model,
&QAbstractItemModel::dataChanged,
this,
[this](const QModelIndex &topLeft, const QModelIndex &, const QList<int> &) {
emit dataChanged(index(topLeft.row(), 0),
index(topLeft.row(), 0),
{ propertyNameRole, propertyTypeRole,
@@ -302,19 +304,28 @@ void DynamicPropertyRow::setupBackendValue()
if (node != m_backendValue->modelNode())
m_backendValue->setModelNode(node);
QVariant modelValue = QmlObjectNode{property.parentModelNode()}.modelValue(property.name());
m_backendValue->setValue({});
const bool isBound = QmlObjectNode{property.parentModelNode()}.hasBindingProperty(property.name());
auto qmlObjectNode = QmlObjectNode{property.parentModelNode()};
auto propertyName = property.name();
if (modelValue != m_backendValue->value()) {
m_backendValue->setValue({});
m_backendValue->setValue(modelValue);
}
if (qmlObjectNode.propertyAffectedByCurrentState(propertyName)
&& !(qmlObjectNode.hasBindingProperty(propertyName))) {
m_backendValue->setValue(qmlObjectNode.modelValue(propertyName));
} else
m_backendValue->setValue(qmlObjectNode.instanceValue(propertyName));
if (isBound) {
QString expression = QmlObjectNode{property.parentModelNode()}.expression(property.name());
if (m_backendValue->expression() != expression)
m_backendValue->setExpression(expression);
if (qmlObjectNode.currentState().isBaseState()
&& qmlObjectNode.modelNode().property(propertyName).isBindingProperty()) {
m_backendValue->setExpression(
qmlObjectNode.modelNode().bindingProperty(propertyName).expression());
} else {
if (qmlObjectNode.hasBindingProperty(propertyName)
&& !qmlObjectNode.expression(propertyName).isEmpty()) {
m_backendValue->setExpression(qmlObjectNode.expression(propertyName));
} else {
m_backendValue->setExpression(qmlObjectNode.instanceValue(propertyName).toString());
}
}
emit m_backendValue->isBoundChanged();
@@ -342,22 +353,25 @@ void DynamicPropertyRow::commitValue(const QVariant &value)
auto view = propertiesModel->view();
RewriterTransaction transaction = view->beginRewriterTransaction(__FUNCTION__);
try {
if (property.isBindingProperty()) {
convertBindingToVariantProperty(property.toBindingProperty(), value);
} else if (property.isVariantProperty()) {
VariantProperty variantProperty = property.toVariantProperty();
QmlObjectNode objectNode = variantProperty.parentModelNode();
if (QmlModelState::isBaseState(view->currentStateNode())
&& !(objectNode.timelineIsActive() && objectNode.currentTimeline().isRecording())) {
if (variantProperty.value() != value)
variantProperty.setDynamicTypeNameAndValue(variantProperty.dynamicTypeName(), value);
} else {
QTC_CHECK(objectNode.isValid());
PropertyNameView name = variantProperty.name();
if (objectNode.isValid() && objectNode.modelValue(name) != value)
objectNode.setVariantProperty(name, value);
QmlObjectNode objectNode = property.parentModelNode();
if (QmlModelState::isBaseState(view->currentStateNode())
&& !(objectNode.timelineIsActive() && objectNode.currentTimeline().isRecording())) {
if (property.isBindingProperty()) {
convertBindingToVariantProperty(property.toBindingProperty(), value);
} else if (property.isVariantProperty()) {
VariantProperty variantProperty = property.toVariantProperty();
if (variantProperty.value() != value) {
variantProperty.setDynamicTypeNameAndValue(variantProperty.dynamicTypeName(),
value);
}
}
} else {
QTC_CHECK(objectNode.isValid());
PropertyNameView name = property.name();
if (objectNode.isValid() && objectNode.modelValue(name) != value)
objectNode.setVariantProperty(name, value);
}
transaction.commit(); // committing in the try block
} catch (Exception &e) {

View File

@@ -1093,6 +1093,8 @@ void PropertyEditorView::instancePropertyChanged(const QList<QPair<ModelNode, Pr
setValue(modelNode, property.name(), qmlObjectNode.modelValue(property.name()));
changed = true;
}
m_dynamicPropertiesModel->handleInstancePropertyChanged(modelNode, propertyName);
}
if (changed)