QmlDesigner: Lock node in properties view

Task-number: QDS-14557
Change-Id: I0b9bf07fe95f6ae85b8bf81eec29c09ab0aa5531
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Karol Herda
2025-03-13 12:24:28 +01:00
parent 58662eb626
commit 82ef60ac42
8 changed files with 231 additions and 82 deletions

View File

@@ -57,8 +57,17 @@ Rectangle {
HeaderBackground{} HeaderBackground{}
} }
PropertyEditorToolBar {
id: toolbar
anchors.top: dockedHeaderLoader.bottom
width: parent.width
onToolBarAction: action => handleToolBarAction(action)
}
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: mainScrollView
onClicked: itemPane.forceActiveFocus() onClicked: itemPane.forceActiveFocus()
} }
@@ -111,7 +120,7 @@ Rectangle {
clip: true clip: true
anchors { anchors {
top: dockedHeaderLoader.bottom top: toolbar.bottom
bottom: itemPane.bottom bottom: itemPane.bottom
left: itemPane.left left: itemPane.left
right: itemPane.right right: itemPane.right

View File

@@ -0,0 +1,32 @@
// Copyright (C) 2025 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import HelperWidgets as HelperWidgets
import StudioTheme as StudioTheme
import PropertyToolBarAction
Rectangle {
id: root
signal toolBarAction(int action)
color: StudioTheme.Values.themeToolbarBackground
height: StudioTheme.Values.toolbarHeight
HelperWidgets.AbstractButton {
id: lockButton
anchors.right: parent.right
anchors.rightMargin: StudioTheme.Values.toolbarHorizontalMargin
anchors.verticalCenter: parent.verticalCenter
buttonIcon: lockButton.checked ? StudioTheme.Constants.lockOn : StudioTheme.Constants.lockOff
checkable: true
checked: isSelectionLocked ?? false
enabled: !(hasMultiSelection ?? false)
style: StudioTheme.Values.viewBarButtonStyle
tooltip: qsTr("Lock current node")
onClicked: root.toolBarAction(lockButton.checked ? ToolBarAction.SelectionLock : ToolBarAction.SelectionUnlock)
}
}

View File

@@ -54,6 +54,7 @@ OriginIndicator 2.0 OriginIndicator.qml
OriginSelector 2.0 OriginSelector.qml OriginSelector 2.0 OriginSelector.qml
PopupLabel 2.0 PopupLabel.qml PopupLabel 2.0 PopupLabel.qml
PropertyEditorPane 2.0 PropertyEditorPane.qml PropertyEditorPane 2.0 PropertyEditorPane.qml
PropertyEditorToolBar 2.0 PropertyEditorToolBar.qml
PropertyLabel 2.0 PropertyLabel.qml PropertyLabel 2.0 PropertyLabel.qml
PaddingSection 2.0 PaddingSection.qml PaddingSection 2.0 PaddingSection.qml
RoundedPanel 2.0 RoundedPanel.qml RoundedPanel 2.0 RoundedPanel.qml

View File

@@ -443,6 +443,20 @@ void PropertyEditorContextObject::setHasMultiSelection(bool b)
emit hasMultiSelectionChanged(); emit hasMultiSelectionChanged();
} }
bool PropertyEditorContextObject::isSelectionLocked() const
{
return m_isSelectionLocked;
}
void PropertyEditorContextObject::setIsSelectionLocked(bool lock)
{
if (lock == m_isSelectionLocked)
return;
m_isSelectionLocked = lock;
emit isSelectionLockedChanged();
}
void PropertyEditorContextObject::setInsightEnabled(bool value) void PropertyEditorContextObject::setInsightEnabled(bool value)
{ {
if (value != m_insightEnabled) { if (value != m_insightEnabled) {
@@ -696,6 +710,11 @@ QPoint PropertyEditorContextObject::globalPos(const QPoint &point) const
return point; return point;
} }
void PropertyEditorContextObject::handleToolBarAction(int action)
{
emit toolBarAction(action);
}
void EasingCurveEditor::registerDeclarativeType() void EasingCurveEditor::registerDeclarativeType()
{ {
qmlRegisterType<EasingCurveEditor>("HelperWidgets", 2, 0, "EasingCurveEditor"); qmlRegisterType<EasingCurveEditor>("HelperWidgets", 2, 0, "EasingCurveEditor");

View File

@@ -49,6 +49,8 @@ class PropertyEditorContextObject : public QObject
Q_PROPERTY(bool hasMultiSelection READ hasMultiSelection WRITE setHasMultiSelection NOTIFY Q_PROPERTY(bool hasMultiSelection READ hasMultiSelection WRITE setHasMultiSelection NOTIFY
hasMultiSelectionChanged) hasMultiSelectionChanged)
Q_PROPERTY(bool isSelectionLocked READ isSelectionLocked WRITE setIsSelectionLocked NOTIFY isSelectionLockedChanged)
Q_PROPERTY(bool insightEnabled MEMBER m_insightEnabled NOTIFY insightEnabledChanged) Q_PROPERTY(bool insightEnabled MEMBER m_insightEnabled NOTIFY insightEnabledChanged)
Q_PROPERTY(QStringList insightCategories MEMBER m_insightCategories NOTIFY insightCategoriesChanged) Q_PROPERTY(QStringList insightCategories MEMBER m_insightCategories NOTIFY insightCategoriesChanged)
@@ -100,6 +102,11 @@ public:
Q_INVOKABLE QRect screenRect() const; Q_INVOKABLE QRect screenRect() const;
Q_INVOKABLE QPoint globalPos(const QPoint &point) const; Q_INVOKABLE QPoint globalPos(const QPoint &point) const;
Q_INVOKABLE void handleToolBarAction(int action);
enum ToolBarAction { SelectionLock, SelectionUnlock };
Q_ENUM(ToolBarAction)
QString activeDragSuffix() const; QString activeDragSuffix() const;
void setActiveDragSuffix(const QString &suffix); void setActiveDragSuffix(const QString &suffix);
@@ -140,6 +147,9 @@ public:
void setSelectedNode(const ModelNode &node); void setSelectedNode(const ModelNode &node);
void setIsSelectionLocked(bool lock);
bool isSelectionLocked() const;
signals: signals:
void specificsUrlChanged(); void specificsUrlChanged();
void specificQmlDataChanged(); void specificQmlDataChanged();
@@ -161,9 +171,11 @@ signals:
void hasMaterialLibraryChanged(); void hasMaterialLibraryChanged();
void has3DModelSelectionChanged(); void has3DModelSelectionChanged();
void isQt6ProjectChanged(); void isQt6ProjectChanged();
void isSelectionLockedChanged();
void insightEnabledChanged(); void insightEnabledChanged();
void insightCategoriesChanged(); void insightCategoriesChanged();
void toolBarAction(int action);
public slots: public slots:
@@ -223,6 +235,7 @@ private:
QString m_activeDragSuffix; QString m_activeDragSuffix;
bool m_hasMultiSelection = false; bool m_hasMultiSelection = false;
bool m_isSelectionLocked = false;
bool m_insightEnabled = false; bool m_insightEnabled = false;
QStringList m_insightCategories; QStringList m_insightCategories;

View File

@@ -66,7 +66,6 @@ PropertyEditorView::PropertyEditorView(AsynchronousImageCache &imageCache,
: AbstractView(externalDependencies) : AbstractView(externalDependencies)
, m_imageCache(imageCache) , m_imageCache(imageCache)
, m_updateShortcut(nullptr) , m_updateShortcut(nullptr)
, m_timerId(0)
, m_stackedWidget(new PropertyEditorWidget()) , m_stackedWidget(new PropertyEditorWidget())
, m_qmlBackEndForCurrentType(nullptr) , m_qmlBackEndForCurrentType(nullptr)
, m_propertyComponentGenerator{PropertyEditorQmlBackend::propertyEditorResourcesPath(), model()} , m_propertyComponentGenerator{PropertyEditorQmlBackend::propertyEditorResourcesPath(), model()}
@@ -117,15 +116,15 @@ void PropertyEditorView::changeValue(const QString &name)
PropertyEditorValue *value = m_qmlBackEndForCurrentType->propertyValueForName(QString::fromUtf8(propertyName)); PropertyEditorValue *value = m_qmlBackEndForCurrentType->propertyValueForName(QString::fromUtf8(propertyName));
const QString newId = value->value().toString(); const QString newId = value->value().toString();
if (newId == m_selectedNode.id()) if (newId == activeNode().id())
return; return;
if (QmlDesigner::ModelNode::isValidId(newId) && !hasId(newId)) { if (QmlDesigner::ModelNode::isValidId(newId) && !hasId(newId)) {
executeInTransaction("PropertyEditorView::changeId", executeInTransaction("PropertyEditorView::changeId",
[this, newId] { m_selectedNode.setIdWithRefactoring(newId); }); [&] { activeNode().setIdWithRefactoring(newId); });
} else { } else {
m_locked = true; m_locked = true;
value->setValue(m_selectedNode.id()); value->setValue(activeNode().id());
m_locked = false; m_locked = false;
QString errMsg = QmlDesigner::ModelNode::getIdValidityErrorMessage(newId); QString errMsg = QmlDesigner::ModelNode::getIdValidityErrorMessage(newId);
if (!errMsg.isEmpty()) if (!errMsg.isEmpty())
@@ -148,7 +147,7 @@ void PropertyEditorView::changeValue(const QString &name)
return; return;
} }
const NodeMetaInfo metaInfo = QmlObjectNode(m_selectedNode).modelNode().metaInfo(); const NodeMetaInfo metaInfo = QmlObjectNode(activeNode()).modelNode().metaInfo();
QVariant castedValue; QVariant castedValue;
@@ -230,7 +229,7 @@ void PropertyEditorView::changeExpression(const QString &propertyName)
PropertyName underscoreName(name); PropertyName underscoreName(name);
underscoreName.replace('.', '_'); underscoreName.replace('.', '_');
QmlObjectNode qmlObjectNode{m_selectedNode}; QmlObjectNode qmlObjectNode{activeNode()};
PropertyEditorValue *value = m_qmlBackEndForCurrentType->propertyValueForName( PropertyEditorValue *value = m_qmlBackEndForCurrentType->propertyValueForName(
QString::fromUtf8(underscoreName)); QString::fromUtf8(underscoreName));
@@ -259,7 +258,7 @@ void PropertyEditorView::exportPropertyAsAlias(const QString &name)
return; return;
executeInTransaction("PropertyEditorView::exportPropertyAsAlias", executeInTransaction("PropertyEditorView::exportPropertyAsAlias",
[this, name]() { generateAliasForProperty(m_selectedNode, name); }); [&]() { generateAliasForProperty(activeNode(), name); });
} }
void PropertyEditorView::removeAliasExport(const QString &name) void PropertyEditorView::removeAliasExport(const QString &name)
@@ -274,7 +273,7 @@ void PropertyEditorView::removeAliasExport(const QString &name)
return; return;
executeInTransaction("PropertyEditorView::exportPropertyAsAlias", executeInTransaction("PropertyEditorView::exportPropertyAsAlias",
[this, name]() { removeAliasForProperty(m_selectedNode, name); }); [&]() { removeAliasForProperty(activeNode(), name); });
} }
bool PropertyEditorView::locked() const bool PropertyEditorView::locked() const
@@ -431,19 +430,13 @@ void PropertyEditorView::resetView()
if (model() == nullptr) if (model() == nullptr)
return; return;
setSelelectedModelNode(); setActiveNodeToSelection();
m_locked = true; m_locked = true;
if (debug) if (debug)
qDebug() << "________________ RELOADING PROPERTY EDITOR QML _______________________"; qDebug() << "________________ RELOADING PROPERTY EDITOR QML _______________________";
if (m_timerId)
killTimer(m_timerId);
if (m_selectedNode.isValid() && model() != m_selectedNode.model())
m_selectedNode = ModelNode();
setupQmlBackend(); setupQmlBackend();
if (m_qmlBackEndForCurrentType) { if (m_qmlBackEndForCurrentType) {
@@ -453,12 +446,20 @@ void PropertyEditorView::resetView()
m_locked = false; m_locked = false;
if (m_timerId)
m_timerId = 0;
updateSize(); updateSize();
} }
void PropertyEditorView::setIsSelectionLocked(bool locked)
{
m_isSelectionLocked = locked;
if (m_qmlBackEndForCurrentType)
m_qmlBackEndForCurrentType->contextObject()->setIsSelectionLocked(locked);
// Show current selection on unlock
if (!m_locked && !m_isSelectionLocked)
select();
}
namespace { namespace {
#ifndef QDS_USE_PROJECTSTORAGE #ifndef QDS_USE_PROJECTSTORAGE
@@ -597,13 +598,27 @@ void setupWidget(PropertyEditorQmlBackend *currentQmlBackend,
} // namespace } // namespace
void PropertyEditorView::handleToolBarAction(int action)
{
switch (action) {
case PropertyEditorContextObject::SelectionLock: {
setIsSelectionLocked(true);
break;
}
case PropertyEditorContextObject::SelectionUnlock: {
setIsSelectionLocked(false);
break;
}
}
}
void PropertyEditorView::setupQmlBackend() void PropertyEditorView::setupQmlBackend()
{ {
#ifdef QDS_USE_PROJECTSTORAGE #ifdef QDS_USE_PROJECTSTORAGE
const NodeMetaInfo commonAncestor = PropertyEditorQmlBackend::findCommonAncestor(m_selectedNode); const NodeMetaInfo commonAncestor = PropertyEditorQmlBackend::findCommonAncestor(activeNode());
auto selfAndPrototypes = commonAncestor.selfAndPrototypes(); auto selfAndPrototypes = commonAncestor.selfAndPrototypes();
bool isEditableComponent = m_selectedNode.isComponent() bool isEditableComponent = activeNode().isComponent()
&& !QmlItemNode(m_selectedNode).isEffectItem(); && !QmlItemNode(activeNode()).isEffectItem();
auto specificQmlData = m_propertyEditorComponentGenerator.create(selfAndPrototypes, auto specificQmlData = m_propertyEditorComponentGenerator.create(selfAndPrototypes,
isEditableComponent); isEditableComponent);
auto [panePath, specificsPath] = findPaneAndSpecificsPath(selfAndPrototypes, model()->pathCache()); auto [panePath, specificsPath] = findPaneAndSpecificsPath(selfAndPrototypes, model()->pathCache());
@@ -614,7 +629,7 @@ void PropertyEditorView::setupQmlBackend()
m_stackedWidget, m_stackedWidget,
this); this);
setupCurrentQmlBackend(currentQmlBackend, setupCurrentQmlBackend(currentQmlBackend,
m_selectedNode, activeNode(),
QUrl::fromLocalFile(QString{specificsPath}), QUrl::fromLocalFile(QString{specificsPath}),
currentStateNode(), currentStateNode(),
this, this,
@@ -626,7 +641,7 @@ void PropertyEditorView::setupQmlBackend()
setupInsight(rootModelNode(), currentQmlBackend); setupInsight(rootModelNode(), currentQmlBackend);
#else #else
const NodeMetaInfo commonAncestor = PropertyEditorQmlBackend::findCommonAncestor(m_selectedNode); const NodeMetaInfo commonAncestor = PropertyEditorQmlBackend::findCommonAncestor(activeNode());
// qmlFileUrl is panel url. and specifics is its metainfo // qmlFileUrl is panel url. and specifics is its metainfo
const auto [qmlFileUrl, specificsClassMetaInfo] = PropertyEditorQmlBackend::getQmlUrlForMetaInfo( const auto [qmlFileUrl, specificsClassMetaInfo] = PropertyEditorQmlBackend::getQmlUrlForMetaInfo(
@@ -638,7 +653,7 @@ void PropertyEditorView::setupQmlBackend()
if (qmlFileUrl.toLocalFile().endsWith("TexturePane.qml")) if (qmlFileUrl.toLocalFile().endsWith("TexturePane.qml"))
qmlSpecificsFile = QUrl{}; qmlSpecificsFile = QUrl{};
QString specificQmlData = getSpecificQmlData(commonAncestor, m_selectedNode, diffClassMetaInfo); QString specificQmlData = getSpecificQmlData(commonAncestor, activeNode(), diffClassMetaInfo);
PropertyEditorQmlBackend *currentQmlBackend = getQmlBackend(m_qmlBackendHash, PropertyEditorQmlBackend *currentQmlBackend = getQmlBackend(m_qmlBackendHash,
qmlFileUrl, qmlFileUrl,
@@ -647,7 +662,7 @@ void PropertyEditorView::setupQmlBackend()
this); this);
setupCurrentQmlBackend(currentQmlBackend, setupCurrentQmlBackend(currentQmlBackend,
m_selectedNode, activeNode(),
qmlSpecificsFile, qmlSpecificsFile,
currentStateNode(), currentStateNode(),
this, this,
@@ -660,7 +675,9 @@ void PropertyEditorView::setupQmlBackend()
setupInsight(rootModelNode(), currentQmlBackend); setupInsight(rootModelNode(), currentQmlBackend);
#endif // QDS_USE_PROJECTSTORAGE #endif // QDS_USE_PROJECTSTORAGE
m_dynamicPropertiesModel->setSelectedNode(m_selectedNode); m_dynamicPropertiesModel->setSelectedNode(activeNode());
QObject::connect(m_qmlBackEndForCurrentType->contextObject(), SIGNAL(toolBarAction(int)), this, SLOT(handleToolBarAction(int)));
} }
void PropertyEditorView::commitVariantValueToModel(PropertyNameView propertyName, const QVariant &value) void PropertyEditorView::commitVariantValueToModel(PropertyNameView propertyName, const QVariant &value)
@@ -669,7 +686,8 @@ void PropertyEditorView::commitVariantValueToModel(PropertyNameView propertyName
try { try {
RewriterTransaction transaction = beginRewriterTransaction("PropertyEditorView::commitVariantValueToMode"); RewriterTransaction transaction = beginRewriterTransaction("PropertyEditorView::commitVariantValueToMode");
for (const ModelNode &node : m_selectedNode.view()->selectedModelNodes()) { const QList<ModelNode> nodes = currentNodes();
for (const ModelNode &node : nodes) {
if (auto qmlObjectNode = QmlObjectNode(node)) if (auto qmlObjectNode = QmlObjectNode(node))
qmlObjectNode.setVariantProperty(propertyName, value); qmlObjectNode.setVariantProperty(propertyName, value);
} }
@@ -689,16 +707,15 @@ void PropertyEditorView::commitAuxValueToModel(PropertyNameView propertyName, co
name.chop(5); name.chop(5);
try { try {
const QList<ModelNode> nodes = currentNodes();
if (value.isValid()) { if (value.isValid()) {
for (const ModelNode &node : m_selectedNode.view()->selectedModelNodes()) { for (const ModelNode &node : nodes)
node.setAuxiliaryData(AuxiliaryDataType::Document, name, value); node.setAuxiliaryData(AuxiliaryDataType::Document, name, value);
}
} else { } else {
for (const ModelNode &node : m_selectedNode.view()->selectedModelNodes()) { for (const ModelNode &node : nodes)
node.removeAuxiliaryData(AuxiliaryDataType::Document, name); node.removeAuxiliaryData(AuxiliaryDataType::Document, name);
} }
} }
}
catch (const Exception &e) { catch (const Exception &e) {
e.showException(); e.showException();
} }
@@ -711,7 +728,8 @@ void PropertyEditorView::removePropertyFromModel(PropertyNameView propertyName)
try { try {
RewriterTransaction transaction = beginRewriterTransaction("PropertyEditorView::removePropertyFromModel"); RewriterTransaction transaction = beginRewriterTransaction("PropertyEditorView::removePropertyFromModel");
for (const ModelNode &node : m_selectedNode.view()->selectedModelNodes()) { const QList<ModelNode> nodes = currentNodes();
for (const ModelNode &node : nodes) {
if (QmlObjectNode::isValidQmlObjectNode(node)) if (QmlObjectNode::isValidQmlObjectNode(node))
QmlObjectNode(node).removeProperty(propertyName); QmlObjectNode(node).removeProperty(propertyName);
} }
@@ -727,19 +745,62 @@ void PropertyEditorView::removePropertyFromModel(PropertyNameView propertyName)
bool PropertyEditorView::noValidSelection() const bool PropertyEditorView::noValidSelection() const
{ {
QTC_ASSERT(m_qmlBackEndForCurrentType, return true); QTC_ASSERT(m_qmlBackEndForCurrentType, return true);
return !QmlObjectNode::isValidQmlObjectNode(m_selectedNode); return !QmlObjectNode::isValidQmlObjectNode(activeNode());
}
ModelNode PropertyEditorView::activeNode() const
{
return m_activeNode;
}
void PropertyEditorView::setActiveNode(const ModelNode &node)
{
m_activeNode = node;
}
QList<ModelNode> PropertyEditorView::currentNodes() const
{
if (m_isSelectionLocked)
return {m_activeNode};
return selectedModelNodes();
} }
void PropertyEditorView::selectedNodesChanged(const QList<ModelNode> &, void PropertyEditorView::selectedNodesChanged(const QList<ModelNode> &,
const QList<ModelNode> &) const QList<ModelNode> &)
{ {
if (m_isSelectionLocked)
return;
select(); select();
} }
bool PropertyEditorView::isNodeOrChildSelected(const ModelNode &node) const
{
if (activeNode().isValid() && node.isValid()) {
const ModelNodes &nodeList = node.allSubModelNodesAndThisNode();
return nodeList.contains(activeNode());
}
return false;
}
void PropertyEditorView::resetSelectionLocked()
{
if (m_isSelectionLocked)
setIsSelectionLocked(false);
}
void PropertyEditorView::resetIfNodeIsRemoved(const ModelNode &removedNode)
{
if (isNodeOrChildSelected(removedNode)) {
resetSelectionLocked();
select();
}
}
void PropertyEditorView::nodeAboutToBeRemoved(const ModelNode &removedNode) void PropertyEditorView::nodeAboutToBeRemoved(const ModelNode &removedNode)
{ {
if (m_selectedNode.isValid() && removedNode.isValid() && m_selectedNode == removedNode) resetIfNodeIsRemoved(removedNode);
select();
const ModelNodes &allRemovedNodes = removedNode.allSubModelNodesAndThisNode(); const ModelNodes &allRemovedNodes = removedNode.allSubModelNodesAndThisNode();
@@ -795,10 +856,10 @@ void PropertyEditorView::propertiesRemoved(const QList<AbstractProperty> &proper
ModelNode node(property.parentModelNode()); ModelNode node(property.parentModelNode());
if (node.isRootNode() && !m_selectedNode.isRootNode()) if (node.isRootNode() && !activeNode().isRootNode())
m_qmlBackEndForCurrentType->contextObject()->setHasAliasExport(QmlObjectNode(m_selectedNode).isAliasExported()); m_qmlBackEndForCurrentType->contextObject()->setHasAliasExport(QmlObjectNode(activeNode()).isAliasExported());
if (node == m_selectedNode || QmlObjectNode(m_selectedNode).propertyChangeForCurrentState() == node) { if (node == activeNode() || QmlObjectNode(activeNode()).propertyChangeForCurrentState() == node) {
m_locked = true; m_locked = true;
changed = true; changed = true;
@@ -813,41 +874,41 @@ void PropertyEditorView::propertiesRemoved(const QList<AbstractProperty> &proper
if (value) { if (value) {
value->resetValue(); value->resetValue();
m_qmlBackEndForCurrentType m_qmlBackEndForCurrentType
->setValue(m_selectedNode, ->setValue(activeNode(),
propertyName, propertyName,
QmlObjectNode(m_selectedNode).instanceValue(propertyName)); QmlObjectNode(activeNode()).instanceValue(propertyName));
} }
m_locked = false; m_locked = false;
if (propertyIsAttachedLayoutProperty(propertyName)) { if (propertyIsAttachedLayoutProperty(propertyName)) {
m_qmlBackEndForCurrentType->setValueforLayoutAttachedProperties(m_selectedNode, m_qmlBackEndForCurrentType->setValueforLayoutAttachedProperties(activeNode(),
propertyName); propertyName);
if (propertyName == "Layout.margins") { if (propertyName == "Layout.margins") {
m_qmlBackEndForCurrentType m_qmlBackEndForCurrentType
->setValueforLayoutAttachedProperties(m_selectedNode, "Layout.topMargin"); ->setValueforLayoutAttachedProperties(activeNode(), "Layout.topMargin");
m_qmlBackEndForCurrentType m_qmlBackEndForCurrentType
->setValueforLayoutAttachedProperties(m_selectedNode, "Layout.bottomMargin"); ->setValueforLayoutAttachedProperties(activeNode(), "Layout.bottomMargin");
m_qmlBackEndForCurrentType m_qmlBackEndForCurrentType
->setValueforLayoutAttachedProperties(m_selectedNode, "Layout.leftMargin"); ->setValueforLayoutAttachedProperties(activeNode(), "Layout.leftMargin");
m_qmlBackEndForCurrentType m_qmlBackEndForCurrentType
->setValueforLayoutAttachedProperties(m_selectedNode, "Layout.rightMargin"); ->setValueforLayoutAttachedProperties(activeNode(), "Layout.rightMargin");
} }
} }
if (propertyIsAttachedInsightProperty(propertyName)) { if (propertyIsAttachedInsightProperty(propertyName)) {
m_qmlBackEndForCurrentType->setValueforInsightAttachedProperties(m_selectedNode, m_qmlBackEndForCurrentType->setValueforInsightAttachedProperties(activeNode(),
propertyName); propertyName);
} }
if ("width" == propertyName || "height" == propertyName) { if ("width" == propertyName || "height" == propertyName) {
const QmlItemNode qmlItemNode = m_selectedNode; const QmlItemNode qmlItemNode = activeNode();
if (qmlItemNode.isInLayout()) if (qmlItemNode.isInLayout())
resetPuppet(); resetPuppet();
} }
if (propertyName.contains("anchor")) if (propertyName.contains("anchor"))
m_qmlBackEndForCurrentType->backendAnchorBinding().invalidate(m_selectedNode); m_qmlBackEndForCurrentType->backendAnchorBinding().invalidate(activeNode());
dynamicPropertiesModel()->dispatchPropertyChanges(property); dynamicPropertiesModel()->dispatchPropertyChanges(property);
} }
@@ -871,8 +932,8 @@ void PropertyEditorView::variantPropertiesChanged(const QList<VariantProperty>&
bool changed = false; bool changed = false;
bool selectedNodeIsMaterial = m_selectedNode.metaInfo().isQtQuick3DMaterial(); bool selectedNodeIsMaterial = activeNode().metaInfo().isQtQuick3DMaterial();
bool selectedNodeHasBindingProperties = !m_selectedNode.bindingProperties().isEmpty(); bool selectedNodeHasBindingProperties = !activeNode().bindingProperties().isEmpty();
for (const VariantProperty &property : propertyList) { for (const VariantProperty &property : propertyList) {
m_qmlBackEndForCurrentType->handleVariantPropertyChangedInModelNodeProxy(property); m_qmlBackEndForCurrentType->handleVariantPropertyChangedInModelNodeProxy(property);
@@ -880,20 +941,20 @@ void PropertyEditorView::variantPropertiesChanged(const QList<VariantProperty>&
ModelNode node(property.parentModelNode()); ModelNode node(property.parentModelNode());
if (propertyIsAttachedLayoutProperty(property.name())) if (propertyIsAttachedLayoutProperty(property.name()))
m_qmlBackEndForCurrentType->setValueforLayoutAttachedProperties(m_selectedNode, m_qmlBackEndForCurrentType->setValueforLayoutAttachedProperties(activeNode(),
property.name()); property.name());
if (propertyIsAttachedInsightProperty(property.name())) if (propertyIsAttachedInsightProperty(property.name()))
m_qmlBackEndForCurrentType->setValueforInsightAttachedProperties(m_selectedNode, m_qmlBackEndForCurrentType->setValueforInsightAttachedProperties(activeNode(),
property.name()); property.name());
if (node == m_selectedNode || QmlObjectNode(m_selectedNode).propertyChangeForCurrentState() == node) { if (node == activeNode() || QmlObjectNode(activeNode()).propertyChangeForCurrentState() == node) {
if (property.isDynamic()) if (property.isDynamic())
m_dynamicPropertiesModel->updateItem(property); m_dynamicPropertiesModel->updateItem(property);
if ( QmlObjectNode(m_selectedNode).modelNode().property(property.name()).isBindingProperty()) if ( QmlObjectNode(activeNode()).modelNode().property(property.name()).isBindingProperty())
setValue(m_selectedNode, property.name(), QmlObjectNode(m_selectedNode).instanceValue(property.name())); setValue(activeNode(), property.name(), QmlObjectNode(activeNode()).instanceValue(property.name()));
else else
setValue(m_selectedNode, property.name(), QmlObjectNode(m_selectedNode).modelValue(property.name())); setValue(activeNode(), property.name(), QmlObjectNode(activeNode()).modelValue(property.name()));
changed = true; changed = true;
} }
@@ -933,16 +994,16 @@ void PropertyEditorView::bindingPropertiesChanged(const QList<BindingProperty> &
ModelNode node(property.parentModelNode()); ModelNode node(property.parentModelNode());
if (property.isAliasExport()) if (property.isAliasExport())
m_qmlBackEndForCurrentType->contextObject()->setHasAliasExport(QmlObjectNode(m_selectedNode).isAliasExported()); m_qmlBackEndForCurrentType->contextObject()->setHasAliasExport(QmlObjectNode(activeNode()).isAliasExported());
if (node == m_selectedNode || QmlObjectNode(m_selectedNode).propertyChangeForCurrentState() == node) { if (node == activeNode() || QmlObjectNode(activeNode()).propertyChangeForCurrentState() == node) {
if (property.isDynamic()) if (property.isDynamic())
m_dynamicPropertiesModel->updateItem(property); m_dynamicPropertiesModel->updateItem(property);
if (property.name().contains("anchor")) if (property.name().contains("anchor"))
m_qmlBackEndForCurrentType->backendAnchorBinding().invalidate(m_selectedNode); m_qmlBackEndForCurrentType->backendAnchorBinding().invalidate(activeNode());
m_locked = true; m_locked = true;
QString exp = QmlObjectNode(m_selectedNode).bindingProperty(property.name()).expression(); QString exp = QmlObjectNode(activeNode()).bindingProperty(property.name()).expression();
m_qmlBackEndForCurrentType->setExpression(property.name(), exp); m_qmlBackEndForCurrentType->setExpression(property.name(), exp);
m_locked = false; m_locked = false;
changed = true; changed = true;
@@ -966,7 +1027,7 @@ void PropertyEditorView::auxiliaryDataChanged(const ModelNode &node,
QScopeGuard rootGuard([this, node, key, &saved] { QScopeGuard rootGuard([this, node, key, &saved] {
if (node.isRootNode()) { if (node.isRootNode()) {
if (!saved) if (!saved)
m_qmlBackEndForCurrentType->setValueforAuxiliaryProperties(m_selectedNode, key); m_qmlBackEndForCurrentType->setValueforAuxiliaryProperties(activeNode(), key);
m_qmlBackEndForCurrentType->handleAuxiliaryDataChanges(node, key); m_qmlBackEndForCurrentType->handleAuxiliaryDataChanges(node, key);
} }
}); });
@@ -974,7 +1035,7 @@ void PropertyEditorView::auxiliaryDataChanged(const ModelNode &node,
if (!node.isSelected()) if (!node.isSelected())
return; return;
m_qmlBackEndForCurrentType->setValueforAuxiliaryProperties(m_selectedNode, key); m_qmlBackEndForCurrentType->setValueforAuxiliaryProperties(activeNode(), key);
saved = true; saved = true;
if (key == insightEnabledProperty) if (key == insightEnabledProperty)
@@ -990,10 +1051,10 @@ void PropertyEditorView::instanceInformationsChanged(const QMultiHash<ModelNode,
return; return;
m_locked = true; m_locked = true;
QList<InformationName> informationNameList = informationChangedHash.values(m_selectedNode); QList<InformationName> informationNameList = informationChangedHash.values(activeNode());
if (informationNameList.contains(Anchor) if (informationNameList.contains(Anchor)
|| informationNameList.contains(HasAnchor)) || informationNameList.contains(HasAnchor))
m_qmlBackEndForCurrentType->backendAnchorBinding().setup(QmlItemNode(m_selectedNode)); m_qmlBackEndForCurrentType->backendAnchorBinding().setup(QmlItemNode(activeNode()));
m_locked = false; m_locked = false;
} }
@@ -1002,7 +1063,7 @@ void PropertyEditorView::nodeIdChanged(const ModelNode &node, const QString &new
if (noValidSelection()) if (noValidSelection())
return; return;
if (!QmlObjectNode(m_selectedNode).isValid()) if (!QmlObjectNode(activeNode()).isValid())
return; return;
m_dynamicPropertiesModel->reset(); m_dynamicPropertiesModel->reset();
@@ -1013,7 +1074,7 @@ void PropertyEditorView::nodeIdChanged(const ModelNode &node, const QString &new
else if (oldId == Constants::MATERIAL_LIB_ID) else if (oldId == Constants::MATERIAL_LIB_ID)
m_qmlBackEndForCurrentType->contextObject()->setHasMaterialLibrary(false); m_qmlBackEndForCurrentType->contextObject()->setHasMaterialLibrary(false);
if (node == m_selectedNode) if (node == activeNode())
setValue(node, "id", newId); setValue(node, "id", newId);
if (node.metaInfo().isQtQuick3DTexture()) if (node.metaInfo().isQtQuick3DTexture())
m_qmlBackEndForCurrentType->refreshBackendModel(); m_qmlBackEndForCurrentType->refreshBackendModel();
@@ -1028,11 +1089,11 @@ void PropertyEditorView::select()
resetView(); resetView();
} }
void PropertyEditorView::setSelelectedModelNode() void PropertyEditorView::setActiveNodeToSelection()
{ {
const auto selectedNodeList = selectedModelNodes(); const auto selectedNodeList = currentNodes();
m_selectedNode = ModelNode(); setActiveNode(ModelNode());
if (selectedNodeList.isEmpty()) if (selectedNodeList.isEmpty())
return; return;
@@ -1040,7 +1101,7 @@ void PropertyEditorView::setSelelectedModelNode()
const ModelNode node = selectedNodeList.constFirst(); const ModelNode node = selectedNodeList.constFirst();
if (QmlObjectNode(node).isValid()) if (QmlObjectNode(node).isValid())
m_selectedNode = node; setActiveNode(node);
} }
bool PropertyEditorView::hasWidget() const bool PropertyEditorView::hasWidget() const
@@ -1068,7 +1129,7 @@ void PropertyEditorView::currentStateChanged(const ModelNode &node)
void PropertyEditorView::instancePropertyChanged(const QList<QPair<ModelNode, PropertyName> > &propertyList) void PropertyEditorView::instancePropertyChanged(const QList<QPair<ModelNode, PropertyName> > &propertyList)
{ {
if (!m_selectedNode.isValid()) if (!activeNode().isValid())
return; return;
QTC_ASSERT(m_qmlBackEndForCurrentType, return ); QTC_ASSERT(m_qmlBackEndForCurrentType, return );
@@ -1084,7 +1145,7 @@ void PropertyEditorView::instancePropertyChanged(const QList<QPair<ModelNode, Pr
m_qmlBackEndForCurrentType->handleInstancePropertyChangedInModelNodeProxy(modelNode, m_qmlBackEndForCurrentType->handleInstancePropertyChangedInModelNodeProxy(modelNode,
propertyName); propertyName);
if (qmlObjectNode.isValid() && modelNode == m_selectedNode if (qmlObjectNode.isValid() && modelNode == activeNode()
&& qmlObjectNode.currentState().isValid()) { && qmlObjectNode.currentState().isValid()) {
const AbstractProperty property = modelNode.property(propertyName); const AbstractProperty property = modelNode.property(propertyName);
if (!modelNode.hasProperty(propertyName) || property.isBindingProperty()) if (!modelNode.hasProperty(propertyName) || property.isBindingProperty())
@@ -1110,7 +1171,7 @@ void PropertyEditorView::rootNodeTypeChanged(const QString &/*type*/, int /*majo
void PropertyEditorView::nodeTypeChanged(const ModelNode &node, const TypeName &, int, int) void PropertyEditorView::nodeTypeChanged(const ModelNode &node, const TypeName &, int, int)
{ {
if (node == m_selectedNode) if (node == activeNode())
resetView(); resetView();
} }
@@ -1119,8 +1180,8 @@ void PropertyEditorView::nodeReparented(const ModelNode &node,
const NodeAbstractProperty & /*oldPropertyParent*/, const NodeAbstractProperty & /*oldPropertyParent*/,
AbstractView::PropertyChangeFlags /*propertyChange*/) AbstractView::PropertyChangeFlags /*propertyChange*/)
{ {
if (node == m_selectedNode) if (node == activeNode())
m_qmlBackEndForCurrentType->backendAnchorBinding().setup(QmlItemNode(m_selectedNode)); m_qmlBackEndForCurrentType->backendAnchorBinding().setup(QmlItemNode(activeNode()));
const ModelNodes &allNodes = node.allSubModelNodesAndThisNode(); const ModelNodes &allNodes = node.allSubModelNodesAndThisNode();
if (Utils::contains(allNodes, model()->qtQuick3DTextureMetaInfo(), &ModelNode::metaInfo)) if (Utils::contains(allNodes, model()->qtQuick3DTextureMetaInfo(), &ModelNode::metaInfo))
@@ -1147,7 +1208,7 @@ void PropertyEditorView::modelNodePreviewPixmapChanged(const ModelNode &node,
const QPixmap &pixmap, const QPixmap &pixmap,
const QByteArray &requestId) const QByteArray &requestId)
{ {
if (node != m_selectedNode) if (node != activeNode())
return; return;
if (m_qmlBackEndForCurrentType) if (m_qmlBackEndForCurrentType)
@@ -1156,7 +1217,7 @@ void PropertyEditorView::modelNodePreviewPixmapChanged(const ModelNode &node,
void PropertyEditorView::highlightTextureProperties(bool highlight) void PropertyEditorView::highlightTextureProperties(bool highlight)
{ {
NodeMetaInfo metaInfo = m_selectedNode.metaInfo(); NodeMetaInfo metaInfo = activeNode().metaInfo();
QTC_ASSERT(metaInfo.isValid(), return); QTC_ASSERT(metaInfo.isValid(), return);
DesignerPropertyMap &propMap = m_qmlBackEndForCurrentType->backendValuesPropertyMap(); DesignerPropertyMap &propMap = m_qmlBackEndForCurrentType->backendValuesPropertyMap();

View File

@@ -107,6 +107,9 @@ public:
static void removeAliasForProperty(const ModelNode &modelNode, static void removeAliasForProperty(const ModelNode &modelNode,
const QString &propertyName); const QString &propertyName);
public slots:
void handleToolBarAction(int action);
protected: protected:
void setValue(const QmlObjectNode &fxObjectNode, PropertyNameView name, const QVariant &value); void setValue(const QmlObjectNode &fxObjectNode, PropertyNameView name, const QVariant &value);
bool eventFilter(QObject *obj, QEvent *event) override; bool eventFilter(QObject *obj, QEvent *event) override;
@@ -116,7 +119,7 @@ private: //functions
void updateSize(); void updateSize();
void select(); void select();
void setSelelectedModelNode(); void setActiveNodeToSelection();
void delayedResetView(); void delayedResetView();
void setupQmlBackend(); void setupQmlBackend();
@@ -128,13 +131,22 @@ private: //functions
bool noValidSelection() const; bool noValidSelection() const;
void highlightTextureProperties(bool highlight = true); void highlightTextureProperties(bool highlight = true);
ModelNode activeNode() const;
void setActiveNode(const ModelNode &node);
QList<ModelNode> currentNodes() const;
void resetSelectionLocked();
void setIsSelectionLocked(bool locked);
bool isNodeOrChildSelected(const ModelNode &node) const;
void resetIfNodeIsRemoved(const ModelNode &removedNode);
static PropertyEditorView *instance(); static PropertyEditorView *instance();
private: //variables private: //variables
AsynchronousImageCache &m_imageCache; AsynchronousImageCache &m_imageCache;
ModelNode m_selectedNode; ModelNode m_activeNode;
QShortcut *m_updateShortcut; QShortcut *m_updateShortcut;
int m_timerId;
PropertyEditorWidget* m_stackedWidget; PropertyEditorWidget* m_stackedWidget;
QString m_qmlDir; QString m_qmlDir;
QHash<QString, PropertyEditorQmlBackend *> m_qmlBackendHash; QHash<QString, PropertyEditorQmlBackend *> m_qmlBackendHash;
@@ -143,6 +155,7 @@ 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;
bool m_isSelectionLocked = false;
DynamicPropertiesModel *m_dynamicPropertiesModel = nullptr; DynamicPropertiesModel *m_dynamicPropertiesModel = nullptr;
friend class PropertyEditorDynamicPropertiesProxyModel; friend class PropertyEditorDynamicPropertiesProxyModel;

View File

@@ -87,6 +87,7 @@ void Quick2PropertyEditorView::registerQmlTypes()
QUrl regExpUrl = QUrl::fromLocalFile(resourcePath + "/RegExpValidator.qml"); QUrl regExpUrl = QUrl::fromLocalFile(resourcePath + "/RegExpValidator.qml");
qmlRegisterType(regExpUrl, "HelperWidgets", 2, 0, "RegExpValidator"); qmlRegisterType(regExpUrl, "HelperWidgets", 2, 0, "RegExpValidator");
qmlRegisterUncreatableType<PropertyEditorContextObject>("PropertyToolBarAction", 2, 0, "ToolBarAction", "Enum type");
} }
} }