forked from qt-creator/qt-creator
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:
@@ -19,7 +19,8 @@ QHash<int, QByteArray> DynamicPropertiesItem::roleNames()
|
|||||||
return {{TargetNameRole, "target"},
|
return {{TargetNameRole, "target"},
|
||||||
{PropertyNameRole, "name"},
|
{PropertyNameRole, "name"},
|
||||||
{PropertyTypeRole, "type"},
|
{PropertyTypeRole, "type"},
|
||||||
{PropertyValueRole, "value"}};
|
{PropertyValueRole, "value"},
|
||||||
|
{InstancePropertyValueRole, "instanceValue"}};
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList DynamicPropertiesItem::headerLabels()
|
QStringList DynamicPropertiesItem::headerLabels()
|
||||||
@@ -58,6 +59,9 @@ void DynamicPropertiesItem::updateProperty(const AbstractProperty &property)
|
|||||||
setData(property.name().toByteArray(), PropertyNameRole);
|
setData(property.name().toByteArray(), PropertyNameRole);
|
||||||
setData(property.dynamicTypeName(), PropertyTypeRole);
|
setData(property.dynamicTypeName(), PropertyTypeRole);
|
||||||
|
|
||||||
|
const auto qmlObjectNode = QmlObjectNode(property.parentModelNode());
|
||||||
|
setData(qmlObjectNode.instanceValue(property.name()), InstancePropertyValueRole);
|
||||||
|
|
||||||
if (property.isVariantProperty()) {
|
if (property.isVariantProperty()) {
|
||||||
if (std::optional<const QmlObjectNode> nodeInState = parentIfNotDefaultState(property))
|
if (std::optional<const QmlObjectNode> nodeInState = parentIfNotDefaultState(property))
|
||||||
setData(nodeInState->modelValue(property.name()), PropertyValueRole);
|
setData(nodeInState->modelValue(property.name()), PropertyValueRole);
|
||||||
|
@@ -18,7 +18,8 @@ public:
|
|||||||
TargetNameRole,
|
TargetNameRole,
|
||||||
PropertyNameRole,
|
PropertyNameRole,
|
||||||
PropertyTypeRole,
|
PropertyTypeRole,
|
||||||
PropertyValueRole
|
PropertyValueRole,
|
||||||
|
InstancePropertyValueRole
|
||||||
};
|
};
|
||||||
|
|
||||||
static QHash<int, QByteArray> roleNames();
|
static QHash<int, QByteArray> roleNames();
|
||||||
|
@@ -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
|
const QList<ModelNode> DynamicPropertiesModel::selectedNodes() const
|
||||||
{
|
{
|
||||||
if (m_explicitSelection)
|
if (m_explicitSelection)
|
||||||
|
@@ -57,6 +57,8 @@ public:
|
|||||||
|
|
||||||
void dispatchPropertyChanges(const AbstractProperty &abstractProperty);
|
void dispatchPropertyChanges(const AbstractProperty &abstractProperty);
|
||||||
|
|
||||||
|
void handleInstancePropertyChanged(const ModelNode &modelNode, PropertyNameView propertyName);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QHash<int, QByteArray> roleNames() const override;
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
|
@@ -71,8 +71,10 @@ void DynamicPropertiesProxyModel::initModel(DynamicPropertiesModel *model)
|
|||||||
connect(m_model, &QAbstractItemModel::rowsInserted,
|
connect(m_model, &QAbstractItemModel::rowsInserted,
|
||||||
this, &QAbstractItemModel::rowsInserted);
|
this, &QAbstractItemModel::rowsInserted);
|
||||||
|
|
||||||
connect(m_model, &QAbstractItemModel::dataChanged,
|
connect(m_model,
|
||||||
this, [this](const QModelIndex &topLeft, const QModelIndex &, const QList<int> &) {
|
&QAbstractItemModel::dataChanged,
|
||||||
|
this,
|
||||||
|
[this](const QModelIndex &topLeft, const QModelIndex &, const QList<int> &) {
|
||||||
emit dataChanged(index(topLeft.row(), 0),
|
emit dataChanged(index(topLeft.row(), 0),
|
||||||
index(topLeft.row(), 0),
|
index(topLeft.row(), 0),
|
||||||
{ propertyNameRole, propertyTypeRole,
|
{ propertyNameRole, propertyTypeRole,
|
||||||
@@ -302,19 +304,28 @@ void DynamicPropertyRow::setupBackendValue()
|
|||||||
if (node != m_backendValue->modelNode())
|
if (node != m_backendValue->modelNode())
|
||||||
m_backendValue->setModelNode(node);
|
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()) {
|
if (qmlObjectNode.propertyAffectedByCurrentState(propertyName)
|
||||||
m_backendValue->setValue({});
|
&& !(qmlObjectNode.hasBindingProperty(propertyName))) {
|
||||||
m_backendValue->setValue(modelValue);
|
m_backendValue->setValue(qmlObjectNode.modelValue(propertyName));
|
||||||
}
|
} else
|
||||||
|
m_backendValue->setValue(qmlObjectNode.instanceValue(propertyName));
|
||||||
|
|
||||||
if (isBound) {
|
if (qmlObjectNode.currentState().isBaseState()
|
||||||
QString expression = QmlObjectNode{property.parentModelNode()}.expression(property.name());
|
&& qmlObjectNode.modelNode().property(propertyName).isBindingProperty()) {
|
||||||
if (m_backendValue->expression() != expression)
|
m_backendValue->setExpression(
|
||||||
m_backendValue->setExpression(expression);
|
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();
|
emit m_backendValue->isBoundChanged();
|
||||||
@@ -342,22 +353,25 @@ void DynamicPropertyRow::commitValue(const QVariant &value)
|
|||||||
|
|
||||||
auto view = propertiesModel->view();
|
auto view = propertiesModel->view();
|
||||||
RewriterTransaction transaction = view->beginRewriterTransaction(__FUNCTION__);
|
RewriterTransaction transaction = view->beginRewriterTransaction(__FUNCTION__);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (property.isBindingProperty()) {
|
QmlObjectNode objectNode = property.parentModelNode();
|
||||||
convertBindingToVariantProperty(property.toBindingProperty(), value);
|
if (QmlModelState::isBaseState(view->currentStateNode())
|
||||||
} else if (property.isVariantProperty()) {
|
&& !(objectNode.timelineIsActive() && objectNode.currentTimeline().isRecording())) {
|
||||||
VariantProperty variantProperty = property.toVariantProperty();
|
if (property.isBindingProperty()) {
|
||||||
QmlObjectNode objectNode = variantProperty.parentModelNode();
|
convertBindingToVariantProperty(property.toBindingProperty(), value);
|
||||||
if (QmlModelState::isBaseState(view->currentStateNode())
|
} else if (property.isVariantProperty()) {
|
||||||
&& !(objectNode.timelineIsActive() && objectNode.currentTimeline().isRecording())) {
|
VariantProperty variantProperty = property.toVariantProperty();
|
||||||
if (variantProperty.value() != value)
|
if (variantProperty.value() != value) {
|
||||||
variantProperty.setDynamicTypeNameAndValue(variantProperty.dynamicTypeName(), value);
|
variantProperty.setDynamicTypeNameAndValue(variantProperty.dynamicTypeName(),
|
||||||
} else {
|
value);
|
||||||
QTC_CHECK(objectNode.isValid());
|
}
|
||||||
PropertyNameView name = variantProperty.name();
|
|
||||||
if (objectNode.isValid() && objectNode.modelValue(name) != value)
|
|
||||||
objectNode.setVariantProperty(name, 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
|
transaction.commit(); // committing in the try block
|
||||||
} catch (Exception &e) {
|
} catch (Exception &e) {
|
||||||
|
@@ -1093,6 +1093,8 @@ void PropertyEditorView::instancePropertyChanged(const QList<QPair<ModelNode, Pr
|
|||||||
setValue(modelNode, property.name(), qmlObjectNode.modelValue(property.name()));
|
setValue(modelNode, property.name(), qmlObjectNode.modelValue(property.name()));
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_dynamicPropertiesModel->handleInstancePropertyChanged(modelNode, propertyName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changed)
|
if (changed)
|
||||||
|
Reference in New Issue
Block a user