QmlDesigner: Separate property view dynamic properties handling

Now property view and connections view have separate dynamic property
handling. This allows property view to change dynamic properties when
connections view is detached, and also will better support the upcoming
selection locking feature in property view.

Fixes: QDS-14891
Change-Id: Ic1a03a635ec595800f995ac5920b7e94f7dc0ab9
Reviewed-by: Ali Kianian <ali.kianian@qt.io>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
This commit is contained in:
Miikka Heikkinen
2025-03-10 16:21:37 +02:00
parent 30c62e3a32
commit fd258651bd
11 changed files with 150 additions and 8 deletions

View File

@@ -20,7 +20,7 @@ PropertyEditorPane {
} }
DynamicPropertiesSection { DynamicPropertiesSection {
propertiesModel: SelectionDynamicPropertiesModel {} propertiesModel: PropertyEditorDynamicPropertiesModel {}
visible: !hasMultiSelection visible: !hasMultiSelection
} }

View File

@@ -12,7 +12,7 @@ PropertyEditorPane {
ComponentSection {} ComponentSection {}
DynamicPropertiesSection { DynamicPropertiesSection {
propertiesModel: SelectionDynamicPropertiesModel {} propertiesModel: PropertyEditorDynamicPropertiesModel {}
visible: !hasMultiSelection visible: !hasMultiSelection
} }

View File

@@ -82,7 +82,7 @@ Item {
} }
DynamicPropertiesSection { DynamicPropertiesSection {
propertiesModel: SelectionDynamicPropertiesModel {} propertiesModel: PropertyEditorDynamicPropertiesModel {}
visible: !hasMultiSelection visible: !hasMultiSelection
} }

View File

@@ -18,7 +18,7 @@ PropertyEditorPane {
anchors.right: parent.right anchors.right: parent.right
DynamicPropertiesSection { DynamicPropertiesSection {
propertiesModel: SelectionDynamicPropertiesModel {} propertiesModel: PropertyEditorDynamicPropertiesModel {}
visible: !hasMultiSelection visible: !hasMultiSelection
} }

View File

@@ -45,7 +45,7 @@ Rectangle {
Layout.fillHeight: true Layout.fillHeight: true
DynamicPropertiesSection { DynamicPropertiesSection {
propertiesModel: SelectionDynamicPropertiesModel {} propertiesModel: PropertyEditorDynamicPropertiesModel {}
visible: !hasMultiSelection visible: !hasMultiSelection
} }

View File

@@ -423,6 +423,7 @@ extend_qtc_plugin(QmlDesigner
gradientpresetlistmodel.cpp gradientpresetlistmodel.h gradientpresetlistmodel.cpp gradientpresetlistmodel.h
instanceimageprovider.cpp instanceimageprovider.h instanceimageprovider.cpp instanceimageprovider.h
propertyeditorcontextobject.cpp propertyeditorcontextobject.h propertyeditorcontextobject.cpp propertyeditorcontextobject.h
propertyeditordynamicpropertiesproxymodel.cpp propertyeditordynamicpropertiesproxymodel.h
propertyeditorqmlbackend.cpp propertyeditorqmlbackend.h propertyeditorqmlbackend.cpp propertyeditorqmlbackend.h
propertyeditortransaction.cpp propertyeditortransaction.h propertyeditortransaction.cpp propertyeditortransaction.h
propertyeditorvalue.cpp propertyeditorvalue.h propertyeditorvalue.cpp propertyeditorvalue.h

View File

@@ -0,0 +1,47 @@
/****************************************************************************
**
** Copyright (C) 2025 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "propertyeditordynamicpropertiesproxymodel.h"
#include <dynamicpropertiesmodel.h>
#include <propertyeditorview.h>
namespace QmlDesigner {
PropertyEditorDynamicPropertiesProxyModel::PropertyEditorDynamicPropertiesProxyModel(QObject *parent)
: DynamicPropertiesProxyModel(parent)
{
if (PropertyEditorView::instance())
initModel(PropertyEditorView::instance()->dynamicPropertiesModel());
}
void PropertyEditorDynamicPropertiesProxyModel::registerDeclarativeType()
{
DynamicPropertiesProxyModel::registerDeclarativeType();
qmlRegisterType<PropertyEditorDynamicPropertiesProxyModel>("HelperWidgets", 2, 0, "PropertyEditorDynamicPropertiesModel");
}
} // namespace QmlDesigner

View File

@@ -0,0 +1,41 @@
/****************************************************************************
**
** Copyright (C) 2025 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "dynamicpropertiesproxymodel.h"
namespace QmlDesigner {
class PropertyEditorDynamicPropertiesProxyModel : public DynamicPropertiesProxyModel
{
Q_OBJECT
public:
explicit PropertyEditorDynamicPropertiesProxyModel(QObject *parent = nullptr);
static void registerDeclarativeType();
};
} // namespace QmlDesigner

View File

@@ -10,8 +10,10 @@
#include <asset.h> #include <asset.h>
#include <auxiliarydataproperties.h> #include <auxiliarydataproperties.h>
#include <dynamicpropertiesmodel.h>
#include <nodemetainfo.h> #include <nodemetainfo.h>
#include <qmldesignerconstants.h> #include <qmldesignerconstants.h>
#include "qmldesignerplugin.h"
#include <qmltimeline.h> #include <qmltimeline.h>
#include <rewritingexception.h> #include <rewritingexception.h>
@@ -69,7 +71,7 @@ PropertyEditorView::PropertyEditorView(AsynchronousImageCache &imageCache,
, m_qmlBackEndForCurrentType(nullptr) , m_qmlBackEndForCurrentType(nullptr)
, m_propertyComponentGenerator{PropertyEditorQmlBackend::propertyEditorResourcesPath(), model()} , m_propertyComponentGenerator{PropertyEditorQmlBackend::propertyEditorResourcesPath(), model()}
, m_locked(false) , m_locked(false)
, m_dynamicPropertiesModel(new DynamicPropertiesModel(true, this))
{ {
m_qmlDir = PropertyEditorQmlBackend::propertyEditorResourcesPath(); m_qmlDir = PropertyEditorQmlBackend::propertyEditorResourcesPath();
@@ -290,6 +292,11 @@ void PropertyEditorView::refreshMetaInfos(const TypeIds &deletedTypeIds)
m_propertyComponentGenerator.refreshMetaInfos(deletedTypeIds); m_propertyComponentGenerator.refreshMetaInfos(deletedTypeIds);
} }
DynamicPropertiesModel *PropertyEditorView::dynamicPropertiesModel() const
{
return m_dynamicPropertiesModel;
}
void PropertyEditorView::setExpressionOnObjectNode(const QmlObjectNode &constObjectNode, void PropertyEditorView::setExpressionOnObjectNode(const QmlObjectNode &constObjectNode,
PropertyNameView name, PropertyNameView name,
const QString &newExpression) const QString &newExpression)
@@ -392,6 +399,24 @@ void PropertyEditorView::removeAliasForProperty(const ModelNode &modelNode, cons
} }
} }
PropertyEditorView *PropertyEditorView::instance()
{
static PropertyEditorView *s_instance = nullptr;
if (s_instance)
return s_instance;
const QList<AbstractView *> views = QmlDesignerPlugin::instance()->viewManager().views();
for (AbstractView *view : views) {
PropertyEditorView *propView = qobject_cast<PropertyEditorView *>(view);
if (propView)
s_instance = propView;
}
QTC_ASSERT(s_instance, return nullptr);
return s_instance;
}
void PropertyEditorView::updateSize() void PropertyEditorView::updateSize()
{ {
if (!m_qmlBackEndForCurrentType) if (!m_qmlBackEndForCurrentType)
@@ -632,6 +657,8 @@ void PropertyEditorView::setupQmlBackend()
setupInsight(rootModelNode(), currentQmlBackend); setupInsight(rootModelNode(), currentQmlBackend);
#endif // QDS_USE_PROJECTSTORAGE #endif // QDS_USE_PROJECTSTORAGE
m_dynamicPropertiesModel->setSelectedNode(m_selectedNode);
} }
void PropertyEditorView::commitVariantValueToModel(PropertyNameView propertyName, const QVariant &value) void PropertyEditorView::commitVariantValueToModel(PropertyNameView propertyName, const QVariant &value)
@@ -750,6 +777,7 @@ void PropertyEditorView::modelAboutToBeDetached(Model *model)
m_qmlBackEndForCurrentType->propertyEditorTransaction()->end(); m_qmlBackEndForCurrentType->propertyEditorTransaction()->end();
resetView(); resetView();
m_dynamicPropertiesModel->reset();
} }
void PropertyEditorView::propertiesRemoved(const QList<AbstractProperty> &propertyList) void PropertyEditorView::propertiesRemoved(const QList<AbstractProperty> &propertyList)
@@ -818,12 +846,20 @@ void PropertyEditorView::propertiesRemoved(const QList<AbstractProperty> &proper
if (propertyName.contains("anchor")) if (propertyName.contains("anchor"))
m_qmlBackEndForCurrentType->backendAnchorBinding().invalidate(m_selectedNode); m_qmlBackEndForCurrentType->backendAnchorBinding().invalidate(m_selectedNode);
dynamicPropertiesModel()->dispatchPropertyChanges(property);
} }
} }
if (changed) if (changed)
m_qmlBackEndForCurrentType->updateInstanceImage(); m_qmlBackEndForCurrentType->updateInstanceImage();
} }
void PropertyEditorView::propertiesAboutToBeRemoved(const QList<AbstractProperty> &propertyList)
{
for (const auto &property : propertyList)
m_dynamicPropertiesModel->removeItem(property);
}
void PropertyEditorView::variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags /*propertyChange*/) void PropertyEditorView::variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags /*propertyChange*/)
{ {
if (noValidSelection()) if (noValidSelection())
@@ -850,6 +886,8 @@ void PropertyEditorView::variantPropertiesChanged(const QList<VariantProperty>&
property.name()); property.name());
if (node == m_selectedNode || QmlObjectNode(m_selectedNode).propertyChangeForCurrentState() == node) { if (node == m_selectedNode || QmlObjectNode(m_selectedNode).propertyChangeForCurrentState() == node) {
if (property.isDynamic())
m_dynamicPropertiesModel->updateItem(property);
if ( QmlObjectNode(m_selectedNode).modelNode().property(property.name()).isBindingProperty()) if ( QmlObjectNode(m_selectedNode).modelNode().property(property.name()).isBindingProperty())
setValue(m_selectedNode, property.name(), QmlObjectNode(m_selectedNode).instanceValue(property.name())); setValue(m_selectedNode, property.name(), QmlObjectNode(m_selectedNode).instanceValue(property.name()));
else else
@@ -865,6 +903,7 @@ void PropertyEditorView::variantPropertiesChanged(const QList<VariantProperty>&
changed = true; changed = true;
} }
} }
m_dynamicPropertiesModel->dispatchPropertyChanges(property);
} }
if (changed) if (changed)
@@ -895,6 +934,8 @@ void PropertyEditorView::bindingPropertiesChanged(const QList<BindingProperty> &
m_qmlBackEndForCurrentType->contextObject()->setHasAliasExport(QmlObjectNode(m_selectedNode).isAliasExported()); m_qmlBackEndForCurrentType->contextObject()->setHasAliasExport(QmlObjectNode(m_selectedNode).isAliasExported());
if (node == m_selectedNode || QmlObjectNode(m_selectedNode).propertyChangeForCurrentState() == node) { if (node == m_selectedNode || QmlObjectNode(m_selectedNode).propertyChangeForCurrentState() == node) {
if (property.isDynamic())
m_dynamicPropertiesModel->updateItem(property);
if (property.name().contains("anchor")) if (property.name().contains("anchor"))
m_qmlBackEndForCurrentType->backendAnchorBinding().invalidate(m_selectedNode); m_qmlBackEndForCurrentType->backendAnchorBinding().invalidate(m_selectedNode);
@@ -904,6 +945,7 @@ void PropertyEditorView::bindingPropertiesChanged(const QList<BindingProperty> &
m_locked = false; m_locked = false;
changed = true; changed = true;
} }
m_dynamicPropertiesModel->dispatchPropertyChanges(property);
} }
if (changed) if (changed)
@@ -961,6 +1003,8 @@ void PropertyEditorView::nodeIdChanged(const ModelNode &node, const QString &new
if (!QmlObjectNode(m_selectedNode).isValid()) if (!QmlObjectNode(m_selectedNode).isValid())
return; return;
m_dynamicPropertiesModel->reset();
if (m_qmlBackEndForCurrentType) { if (m_qmlBackEndForCurrentType) {
if (newId == Constants::MATERIAL_LIB_ID) if (newId == Constants::MATERIAL_LIB_ID)
m_qmlBackEndForCurrentType->contextObject()->setHasMaterialLibrary(true); m_qmlBackEndForCurrentType->contextObject()->setHasMaterialLibrary(true);

View File

@@ -21,6 +21,7 @@ QT_END_NAMESPACE
namespace QmlDesigner { namespace QmlDesigner {
class CollapseButton; class CollapseButton;
class DynamicPropertiesModel;
class ModelNode; class ModelNode;
class PropertyEditorQmlBackend; class PropertyEditorQmlBackend;
class PropertyEditorView; class PropertyEditorView;
@@ -46,6 +47,7 @@ public:
const NodeAbstractProperty &parentProperty, const NodeAbstractProperty &parentProperty,
PropertyChangeFlags propertyChange) override; PropertyChangeFlags propertyChange) override;
void propertiesRemoved(const QList<AbstractProperty>& propertyList) override; void propertiesRemoved(const QList<AbstractProperty>& propertyList) override;
void propertiesAboutToBeRemoved(const QList<AbstractProperty> &propertyList) override;
void modelAttached(Model *model) override; void modelAttached(Model *model) override;
@@ -93,6 +95,8 @@ public:
void refreshMetaInfos(const TypeIds &deletedTypeIds) override; void refreshMetaInfos(const TypeIds &deletedTypeIds) override;
DynamicPropertiesModel *dynamicPropertiesModel() const;
static void setExpressionOnObjectNode(const QmlObjectNode &objectNode, static void setExpressionOnObjectNode(const QmlObjectNode &objectNode,
PropertyNameView name, PropertyNameView name,
const QString &expression); const QString &expression);
@@ -124,6 +128,8 @@ private: //functions
bool noValidSelection() const; bool noValidSelection() const;
void highlightTextureProperties(bool highlight = true); void highlightTextureProperties(bool highlight = true);
static PropertyEditorView *instance();
private: //variables private: //variables
AsynchronousImageCache &m_imageCache; AsynchronousImageCache &m_imageCache;
ModelNode m_selectedNode; ModelNode m_selectedNode;
@@ -137,6 +143,9 @@ private: //variables
PropertyEditorComponentGenerator m_propertyEditorComponentGenerator{m_propertyComponentGenerator}; PropertyEditorComponentGenerator m_propertyEditorComponentGenerator{m_propertyComponentGenerator};
bool m_locked; bool m_locked;
bool m_textureAboutToBeRemoved = false; bool m_textureAboutToBeRemoved = false;
DynamicPropertiesModel *m_dynamicPropertiesModel = nullptr;
friend class PropertyEditorDynamicPropertiesProxyModel;
}; };
} //QmlDesigner } //QmlDesigner

View File

@@ -29,7 +29,7 @@
#include "qmlmaterialnodeproxy.h" #include "qmlmaterialnodeproxy.h"
#include "qmltexturenodeproxy.h" #include "qmltexturenodeproxy.h"
#include "richtexteditor/richtexteditorproxy.h" #include "richtexteditor/richtexteditorproxy.h"
#include "selectiondynamicpropertiesproxymodel.h" #include "propertyeditordynamicpropertiesproxymodel.h"
#include "theme.h" #include "theme.h"
#include "tooltip.h" #include "tooltip.h"
@@ -76,7 +76,7 @@ void Quick2PropertyEditorView::registerQmlTypes()
Tooltip::registerDeclarativeType(); Tooltip::registerDeclarativeType();
EasingCurveEditor::registerDeclarativeType(); EasingCurveEditor::registerDeclarativeType();
RichTextEditorProxy::registerDeclarativeType(); RichTextEditorProxy::registerDeclarativeType();
SelectionDynamicPropertiesProxyModel::registerDeclarativeType(); PropertyEditorDynamicPropertiesProxyModel::registerDeclarativeType();
DynamicPropertyRow::registerDeclarativeType(); DynamicPropertyRow::registerDeclarativeType();
PropertyChangesModel::registerDeclarativeType(); PropertyChangesModel::registerDeclarativeType();
PropertyModel::registerDeclarativeType(); PropertyModel::registerDeclarativeType();