diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick3D/Material/Toolbar.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick3D/Material/Toolbar.qml index b3e5a7e147c..5cb89f91b97 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick3D/Material/Toolbar.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick3D/Material/Toolbar.qml @@ -23,6 +23,7 @@ Rectangle { style: StudioTheme.Values.viewBarButtonStyle buttonIcon: StudioTheme.Constants.apply_medium tooltip: qsTr("Apply material to selected model.") + enabled: has3DModelSelected onClicked: root.backend.toolBarAction(QmlMaterialNodeProxy.ApplyToSelected) } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComponentSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComponentSection.qml index f3b460e0994..d41b225af75 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComponentSection.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComponentSection.qml @@ -164,7 +164,7 @@ Section { id: toolTipArea enabled: !modelNodeBackend.multiSelection && anchorBackend.hasParent anchors.fill: parent - onClicked: toogleExportAlias() + onClicked: toggleExportAlias() tooltip: qsTr("Exports this component as an alias property of the root component.") } } diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditorqmlbackend.cpp b/src/plugins/qmldesigner/components/materialeditor/materialeditorqmlbackend.cpp index 89fd07b96a8..c71ac819ca7 100644 --- a/src/plugins/qmldesigner/components/materialeditor/materialeditorqmlbackend.cpp +++ b/src/plugins/qmldesigner/components/materialeditor/materialeditorqmlbackend.cpp @@ -222,7 +222,7 @@ void MaterialEditorQmlBackend::setup(const QmlObjectNode &selectedMaterialNode, } // model node - m_backendModelNode.setup(selectedMaterialNode.modelNode()); + m_backendModelNode.setup(selectedMaterialNode); context()->setContextProperty("modelNodeBackend", &m_backendModelNode); context()->setContextProperty("hasMaterial", QVariant(true)); diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.cpp index df9c8cc8ece..effb5ace520 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.cpp @@ -138,7 +138,7 @@ QStringList PropertyEditorContextObject::autoComplete(const QString &text, int p return {}; } -void PropertyEditorContextObject::toogleExportAlias() +void PropertyEditorContextObject::toggleExportAlias() { QTC_ASSERT(m_model && m_model->rewriterView(), return); @@ -156,13 +156,13 @@ void PropertyEditorContextObject::toogleExportAlias() PropertyName modelNodeId = selectedNode.id().toUtf8(); ModelNode rootModelNode = rewriterView->rootModelNode(); - rewriterView->executeInTransaction("PropertyEditorContextObject:toogleExportAlias", [&objectNode, &rootModelNode, modelNodeId](){ - if (!objectNode.isAliasExported()) - objectNode.ensureAliasExport(); - else - if (rootModelNode.hasProperty(modelNodeId)) - rootModelNode.removeProperty(modelNodeId); - }); + rewriterView->executeInTransaction("PropertyEditorContextObject:toggleExportAlias", + [&objectNode, &rootModelNode, modelNodeId]() { + if (!objectNode.isAliasExported()) + objectNode.ensureAliasExport(); + else if (rootModelNode.hasProperty(modelNodeId)) + rootModelNode.removeProperty(modelNodeId); + }); } } @@ -294,7 +294,7 @@ void PropertyEditorContextObject::changeTypeName(const QString &typeName) try { auto transaction = RewriterTransaction(rewriterView, "PropertyEditorContextObject:changeTypeName"); - ModelNodes selectedNodes = rewriterView->selectedModelNodes(); // TODO: replace it by PropertyEditorView::currentNodes() + ModelNodes selectedNodes = m_editorNodes; for (ModelNode &selectedNode : selectedNodes) changeNodeTypeName(selectedNode); @@ -489,9 +489,9 @@ bool PropertyEditorContextObject::hasQuick3DImport() const return m_hasQuick3DImport; } -void PropertyEditorContextObject::setSelectedNode(const ModelNode &node) +void PropertyEditorContextObject::setEditorNodes(const ModelNodes &nodes) { - m_selectedNode = node; + m_editorNodes = nodes; } void PropertyEditorContextObject::setHasQuick3DImport(bool value) @@ -531,18 +531,18 @@ void PropertyEditorContextObject::setIsQt6Project(bool value) emit isQt6ProjectChanged(); } -bool PropertyEditorContextObject::has3DModelSelection() const +bool PropertyEditorContextObject::has3DModelSelected() const { - return m_has3DModelSelection; + return m_has3DModelSelected; } -void PropertyEditorContextObject::set3DHasModelSelection(bool value) +void PropertyEditorContextObject::setHas3DModelSelected(bool value) { - if (value == m_has3DModelSelection) + if (value == m_has3DModelSelected) return; - m_has3DModelSelection = value; - emit has3DModelSelectionChanged(); + m_has3DModelSelected = value; + emit has3DModelSelectedChanged(); } void PropertyEditorContextObject::setSpecificsUrl(const QUrl &newSpecificsUrl) diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.h b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.h index ff20e5b7105..650f2bbbae8 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.h +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.h @@ -57,7 +57,7 @@ class PropertyEditorContextObject : public QObject Q_PROPERTY(bool hasQuick3DImport READ hasQuick3DImport NOTIFY hasQuick3DImportChanged) Q_PROPERTY(bool hasMaterialLibrary READ hasMaterialLibrary NOTIFY hasMaterialLibraryChanged) Q_PROPERTY(bool isQt6Project READ isQt6Project NOTIFY isQt6ProjectChanged) - Q_PROPERTY(bool has3DModelSelection READ has3DModelSelection NOTIFY has3DModelSelectionChanged) + Q_PROPERTY(bool has3DModelSelected READ has3DModelSelected NOTIFY has3DModelSelectedChanged) public: PropertyEditorContextObject(QQuickWidget *widget, QObject *parent = nullptr); @@ -78,7 +78,7 @@ public: Q_INVOKABLE QStringList autoComplete(const QString &text, int pos, bool explicitComplete, bool filter); - Q_INVOKABLE void toogleExportAlias(); + Q_INVOKABLE void toggleExportAlias(); Q_INVOKABLE void goIntoComponent(); @@ -142,10 +142,10 @@ public: bool isQt6Project() const; void setIsQt6Project(bool value); - bool has3DModelSelection() const; - void set3DHasModelSelection(bool value); + bool has3DModelSelected() const; + void setHas3DModelSelected(bool value); - void setSelectedNode(const ModelNode &node); + void setEditorNodes(const ModelNodes &nodes); void setIsSelectionLocked(bool lock); bool isSelectionLocked() const; @@ -169,7 +169,7 @@ signals: void hasMultiSelectionChanged(); void hasQuick3DImportChanged(); void hasMaterialLibraryChanged(); - void has3DModelSelectionChanged(); + void has3DModelSelectedChanged(); void isQt6ProjectChanged(); void isSelectionLockedChanged(); @@ -217,7 +217,7 @@ private: bool m_hasQuick3DImport = false; bool m_hasMaterialLibrary = false; - bool m_has3DModelSelection = false; + bool m_has3DModelSelected = false; bool m_isQt6Project = false; QQmlComponent *m_qmlComponent; @@ -240,7 +240,7 @@ private: bool m_insightEnabled = false; QStringList m_insightCategories; - ModelNode m_selectedNode; + ModelNodes m_editorNodes; // Nodes that are being edited by PropertyEditor }; class EasingCurveEditor : public QObject diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp index 362efce6cf9..410a34be74e 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp @@ -375,6 +375,12 @@ void PropertyEditorQmlBackend::handleModelNodePreviewPixmapChanged(const ModelNo refreshPreview(); } +void PropertyEditorQmlBackend::handleModelSelectedNodesChanged(PropertyEditorView *propertyEditor) +{ + contextObject()->setHas3DModelSelected(!Utils3D::getSelectedModels(propertyEditor).isEmpty()); + m_backendTextureNode.updateSelectionDetails(); +} + void PropertyEditorQmlBackend::createPropertyEditorValue(const QmlObjectNode &qmlObjectNode, PropertyNameView name, const QVariant &value, @@ -566,108 +572,107 @@ void PropertyEditorQmlBackend::updateInstanceImage() refreshPreview(); } -void PropertyEditorQmlBackend::setup(const QmlObjectNode &qmlObjectNode, const QString &stateName, const QUrl &qmlSpecificsFile, PropertyEditorView *propertyEditor) +void PropertyEditorQmlBackend::setup(const ModelNodes &editorNodes, + const QString &stateName, + const QUrl &qmlSpecificsFile, + PropertyEditorView *propertyEditor) { - if (qmlObjectNode.isValid()) { - m_contextObject->setModel(propertyEditor->model()); + QmlObjectNode qmlObjectNode(editorNodes.isEmpty() ? ModelNode{} : editorNodes.first()); + if (!qmlObjectNode.isValid()) { + qWarning() << "PropertyEditor: invalid node for setup"; + return; + } - qCInfo(propertyEditorBenchmark) << Q_FUNC_INFO; + m_contextObject->setModel(propertyEditor->model()); - QElapsedTimer time; - if (propertyEditorBenchmark().isInfoEnabled()) - time.start(); + qCInfo(propertyEditorBenchmark) << Q_FUNC_INFO; - createPropertyEditorValues(qmlObjectNode, propertyEditor); - setupLayoutAttachedProperties(qmlObjectNode, propertyEditor); - setupInsightAttachedProperties(qmlObjectNode, propertyEditor); - setupAuxiliaryProperties(qmlObjectNode, propertyEditor); + QElapsedTimer time; + if (propertyEditorBenchmark().isInfoEnabled()) + time.start(); - // model node - m_backendModelNode.setup(qmlObjectNode.modelNode()); - context()->setContextProperty("modelNodeBackend", &m_backendModelNode); + createPropertyEditorValues(qmlObjectNode, propertyEditor); + setupLayoutAttachedProperties(qmlObjectNode, propertyEditor); + setupInsightAttachedProperties(qmlObjectNode, propertyEditor); + setupAuxiliaryProperties(qmlObjectNode, propertyEditor); - m_backendMaterialNode.setup(qmlObjectNode); - m_backendTextureNode.setup(qmlObjectNode); + // model node + m_backendModelNode.setup(editorNodes); + context()->setContextProperty("modelNodeBackend", &m_backendModelNode); - insertValue(Constants::PROPERTY_EDITOR_CLASSNAME_PROPERTY, - m_backendModelNode.simplifiedTypeName(), - qmlObjectNode.modelNode()); + m_backendMaterialNode.setup(editorNodes); + m_backendTextureNode.setup(qmlObjectNode); - insertValue("id"_L1, m_backendModelNode.nodeId()); - insertValue("objectName"_L1, m_backendModelNode.nodeObjectName()); + insertValue(Constants::PROPERTY_EDITOR_CLASSNAME_PROPERTY, + m_backendModelNode.simplifiedTypeName(), + qmlObjectNode.modelNode()); - QmlItemNode itemNode(qmlObjectNode.modelNode()); + insertValue("id"_L1, m_backendModelNode.nodeId()); + insertValue("objectName"_L1, m_backendModelNode.nodeObjectName()); - // anchors - m_backendAnchorBinding.setup(qmlObjectNode.modelNode()); - setupContextProperties(); + QmlItemNode itemNode(qmlObjectNode.modelNode()); - contextObject()->setHasMultiSelection( - !qmlObjectNode.view()->singleSelectedModelNode().isValid()); + // anchors + m_backendAnchorBinding.setup(qmlObjectNode.modelNode()); + setupContextProperties(); - qCInfo(propertyEditorBenchmark) << "anchors:" << time.elapsed(); + contextObject()->setHasMultiSelection(m_backendModelNode.multiSelection()); - qCInfo(propertyEditorBenchmark) << "context:" << time.elapsed(); + qCInfo(propertyEditorBenchmark) << "anchors:" << time.elapsed(); - contextObject()->setSpecificsUrl(qmlSpecificsFile); + qCInfo(propertyEditorBenchmark) << "context:" << time.elapsed(); - qCInfo(propertyEditorBenchmark) << "specifics:" << time.elapsed(); + contextObject()->setSpecificsUrl(qmlSpecificsFile); - contextObject()->setStateName(stateName); - if (!qmlObjectNode.isValid()) - return; + qCInfo(propertyEditorBenchmark) << "specifics:" << time.elapsed(); - context()->setContextProperty(QLatin1String("propertyCount"), - QVariant(qmlObjectNode.modelNode().properties().size())); + contextObject()->setStateName(stateName); - QStringList stateNames = qmlObjectNode.allStateNames(); - stateNames.prepend("base state"); - contextObject()->setAllStateNames(stateNames); + context()->setContextProperty(QLatin1String("propertyCount"), + QVariant(qmlObjectNode.modelNode().properties().size())); - contextObject()->setIsBaseState(qmlObjectNode.isInBaseState()); + QStringList stateNames = qmlObjectNode.allStateNames(); + stateNames.prepend("base state"); + contextObject()->setAllStateNames(stateNames); - contextObject()->setHasAliasExport(qmlObjectNode.isAliasExported()); + contextObject()->setIsBaseState(qmlObjectNode.isInBaseState()); - contextObject()->setHasActiveTimeline(QmlTimeline::hasActiveTimeline(qmlObjectNode.view())); + contextObject()->setHasAliasExport(qmlObjectNode.isAliasExported()); - contextObject()->setSelectionChanged(false); + contextObject()->setHasActiveTimeline(QmlTimeline::hasActiveTimeline(qmlObjectNode.view())); - contextObject()->setSelectionChanged(false); + contextObject()->setSelectionChanged(false); - NodeMetaInfo metaInfo = qmlObjectNode.modelNode().metaInfo(); + NodeMetaInfo metaInfo = qmlObjectNode.modelNode().metaInfo(); #ifdef QDS_USE_PROJECTSTORAGE + contextObject()->setMajorVersion(-1); + contextObject()->setMinorVersion(-1); + contextObject()->setMajorQtQuickVersion(-1); + contextObject()->setMinorQtQuickVersion(-1); +#else + if (metaInfo.isValid()) { + contextObject()->setMajorVersion(metaInfo.majorVersion()); + contextObject()->setMinorVersion(metaInfo.minorVersion()); + } else { contextObject()->setMajorVersion(-1); contextObject()->setMinorVersion(-1); contextObject()->setMajorQtQuickVersion(-1); contextObject()->setMinorQtQuickVersion(-1); -#else - if (metaInfo.isValid()) { - contextObject()->setMajorVersion(metaInfo.majorVersion()); - contextObject()->setMinorVersion(metaInfo.minorVersion()); - } else { - contextObject()->setMajorVersion(-1); - contextObject()->setMinorVersion(-1); - contextObject()->setMajorQtQuickVersion(-1); - contextObject()->setMinorQtQuickVersion(-1); - } -#endif - contextObject()->setMajorQtQuickVersion(qmlObjectNode.view()->majorQtQuickVersion()); - contextObject()->setMinorQtQuickVersion(qmlObjectNode.view()->minorQtQuickVersion()); - - contextObject()->setHasMaterialLibrary(Utils3D::materialLibraryNode(propertyEditor).isValid()); - contextObject()->setIsQt6Project(propertyEditor->externalDependencies().isQt6Project()); - contextObject()->set3DHasModelSelection(!Utils3D::getSelectedModels(propertyEditor).isEmpty()); - contextObject()->setSelectedNode(qmlObjectNode); - contextObject()->setHasQuick3DImport(propertyEditor->model()->hasImport("QtQuick3D")); - - m_view->instanceImageProvider()->setModelNode(propertyEditor->firstSelectedModelNode()); - updateInstanceImage(); - - qCInfo(propertyEditorBenchmark) << "final:" << time.elapsed(); - } else { - qWarning() << "PropertyEditor: invalid node for setup"; } +#endif + contextObject()->setMajorQtQuickVersion(qmlObjectNode.view()->majorQtQuickVersion()); + contextObject()->setMinorQtQuickVersion(qmlObjectNode.view()->minorQtQuickVersion()); + + contextObject()->setHasMaterialLibrary(Utils3D::materialLibraryNode(propertyEditor).isValid()); + contextObject()->setIsQt6Project(propertyEditor->externalDependencies().isQt6Project()); + contextObject()->setEditorNodes(editorNodes); + contextObject()->setHasQuick3DImport(propertyEditor->model()->hasImport("QtQuick3D")); + + m_view->instanceImageProvider()->setModelNode(m_backendModelNode.singleSelectedNode()); + updateInstanceImage(); + + qCInfo(propertyEditorBenchmark) << "final:" << time.elapsed(); } QString PropertyEditorQmlBackend::propertyEditorResourcesPath() @@ -960,35 +965,6 @@ QString PropertyEditorQmlBackend::resourcesPath(const QString &dir) return Core::ICore::resourcePath("qmldesigner/" + dir).toUrlishString(); } -static NodeMetaInfo findCommonSuperClass(const NodeMetaInfo &first, const NodeMetaInfo &second) -{ - auto commonBase = first.commonBase(second); - - return commonBase.isValid() ? commonBase : first; -} - -NodeMetaInfo PropertyEditorQmlBackend::findCommonAncestor(const ModelNode &node) -{ - if (!node.isValid()) - return node.metaInfo(); - - AbstractView *view = node.view(); - - const QList &selectedNodes = view->selectedModelNodes(); - if (selectedNodes.size() > 1) { - NodeMetaInfo commonClass = node.metaInfo(); - - for (const ModelNode &selectedNode : selectedNodes) { - const NodeMetaInfo &nodeMetaInfo = selectedNode.metaInfo(); - if (nodeMetaInfo.isValid() && !nodeMetaInfo.isBasedOn(commonClass)) - commonClass = findCommonSuperClass(nodeMetaInfo, commonClass); - } - return commonClass; - } - - return node.metaInfo(); -} - void PropertyEditorQmlBackend::refreshBackendModel() { m_backendModelNode.refresh(); @@ -1064,7 +1040,6 @@ bool PropertyEditorQmlBackend::checkIfUrlExists(const QUrl &url) void PropertyEditorQmlBackend::emitSelectionToBeChanged() { m_backendModelNode.emitSelectionToBeChanged(); - m_backendTextureNode.updateSelectionDetails(); } void PropertyEditorQmlBackend::emitSelectionChanged() diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.h b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.h index d4304b3d8ab..19abd1d757b 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.h +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.h @@ -40,7 +40,10 @@ public: class AsynchronousImageCache &imageCache); ~PropertyEditorQmlBackend(); - void setup(const QmlObjectNode &fxObjectNode, const QString &stateName, const QUrl &qmlSpecificsFile, PropertyEditorView *propertyEditor); + void setup(const ModelNodes &editorNodes, + const QString &stateName, + const QUrl &qmlSpecificsFile, + PropertyEditorView *propertyEditor); void setValue(const QmlObjectNode &fxObjectNode, PropertyNameView name, const QVariant &value); void setExpression(PropertyNameView propName, const QString &exp); @@ -94,8 +97,7 @@ public: void handleModelNodePreviewPixmapChanged(const ModelNode &node, const QPixmap &pixmap, const QByteArray &requestId); - - static NodeMetaInfo findCommonAncestor(const ModelNode &node); + void handleModelSelectedNodesChanged(PropertyEditorView *propertyEditor); void refreshBackendModel(); void refreshPreview(); diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp index 86ee06fec7e..6244e1d005c 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp @@ -61,6 +61,13 @@ static bool propertyIsAttachedInsightProperty(PropertyNameView propertyName) return propertyName.contains("InsightCategory."); } +static NodeMetaInfo findCommonSuperClass(const NodeMetaInfo &first, const NodeMetaInfo &second) +{ + auto commonBase = first.commonBase(second); + + return commonBase.isValid() ? commonBase : first; +} + PropertyEditorView::PropertyEditorView(AsynchronousImageCache &imageCache, ExternalDependenciesInterface &externalDependencies) : AbstractView(externalDependencies) @@ -428,6 +435,26 @@ PropertyEditorView *PropertyEditorView::instance() return s_instance; } +NodeMetaInfo PropertyEditorView::findCommonAncestor(const ModelNode &node) +{ + if (!node.isValid()) + return node.metaInfo(); + + const QList allNodes = currentNodes(); + if (allNodes.size() > 1) { + NodeMetaInfo commonClass = node.metaInfo(); + + for (const ModelNode &selectedNode : allNodes) { + const NodeMetaInfo &nodeMetaInfo = selectedNode.metaInfo(); + if (nodeMetaInfo.isValid() && !nodeMetaInfo.isBasedOn(commonClass)) + commonClass = findCommonSuperClass(nodeMetaInfo, commonClass); + } + return commonClass; + } + + return node.metaInfo(); +} + void PropertyEditorView::updateSize() { if (!m_qmlBackEndForCurrentType) @@ -542,7 +569,7 @@ PropertyEditorQmlBackend *getQmlBackend(QHashcontextObject()->setSpecificQmlData(specificQmlData); - currentQmlBackend->setup(qmlObjectNode, currentStateName, qmlSpecificsFile, propertyEditorView); + currentQmlBackend->setup(editorNodes, currentStateName, qmlSpecificsFile, propertyEditorView); currentQmlBackend->contextObject()->setSpecificQmlData(specificQmlData); } @@ -634,7 +660,7 @@ void PropertyEditorView::handleToolBarAction(int action) void PropertyEditorView::setupQmlBackend() { #ifdef QDS_USE_PROJECTSTORAGE - const NodeMetaInfo commonAncestor = PropertyEditorQmlBackend::findCommonAncestor(activeNode()); + const NodeMetaInfo commonAncestor = findCommonAncestor(activeNode()); auto selfAndPrototypes = commonAncestor.selfAndPrototypes(); bool isEditableComponent = activeNode().isComponent() && !QmlItemNode(activeNode()).isEffectItem(); @@ -648,7 +674,7 @@ void PropertyEditorView::setupQmlBackend() m_stackedWidget, this); setupCurrentQmlBackend(currentQmlBackend, - activeNode(), + currentNodes(), QUrl::fromLocalFile(QString{specificsPath}), currentStateNode(), this, @@ -660,7 +686,7 @@ void PropertyEditorView::setupQmlBackend() setupInsight(rootModelNode(), currentQmlBackend); #else - const NodeMetaInfo commonAncestor = PropertyEditorQmlBackend::findCommonAncestor(activeNode()); + const NodeMetaInfo commonAncestor = findCommonAncestor(activeNode()); // qmlFileUrl is panel url. and specifics is its metainfo const auto [qmlFileUrl, specificsClassMetaInfo] = PropertyEditorQmlBackend::getQmlUrlForMetaInfo( @@ -681,7 +707,7 @@ void PropertyEditorView::setupQmlBackend() this); setupCurrentQmlBackend(currentQmlBackend, - activeNode(), + currentNodes(), qmlSpecificsFile, currentStateNode(), this, @@ -788,10 +814,12 @@ QList PropertyEditorView::currentNodes() const void PropertyEditorView::selectedNodesChanged(const QList &, const QList &) { - if (m_isSelectionLocked) - return; + if (!m_isSelectionLocked) + select(); - select(); + // Notify model selection changes to backend regardless of being locked + if (m_qmlBackEndForCurrentType) + m_qmlBackEndForCurrentType->handleModelSelectedNodesChanged(this); } bool PropertyEditorView::isNodeOrChildSelected(const ModelNode &node) const diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.h b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.h index f3fd2d60709..ee1f6ad5a76 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.h +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.h @@ -143,6 +143,8 @@ private: //functions static PropertyEditorView *instance(); + NodeMetaInfo findCommonAncestor(const ModelNode &node); + private: //variables AsynchronousImageCache &m_imageCache; ModelNode m_activeNode; diff --git a/src/plugins/qmldesigner/components/propertyeditor/qmlmaterialnodeproxy.cpp b/src/plugins/qmldesigner/components/propertyeditor/qmlmaterialnodeproxy.cpp index d2011e8e087..16ef8604969 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/qmlmaterialnodeproxy.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/qmlmaterialnodeproxy.cpp @@ -41,11 +41,13 @@ QmlMaterialNodeProxy::QmlMaterialNodeProxy() QmlMaterialNodeProxy::~QmlMaterialNodeProxy() = default; -void QmlMaterialNodeProxy::setup(const QmlObjectNode &objectNode) +void QmlMaterialNodeProxy::setup(const ModelNodes &editorNodes) { + QmlObjectNode objectNode = editorNodes.isEmpty() ? ModelNode{} : editorNodes.first(); const QmlObjectNode material = objectNode.metaInfo().isQtQuick3DMaterial() ? objectNode : QmlObjectNode{}; setMaterialNode(material); + setEditorNodes(editorNodes); updatePossibleTypes(); updatePreviewModel(); } @@ -55,6 +57,11 @@ ModelNode QmlMaterialNodeProxy::materialNode() const return m_materialNode; } +ModelNodes QmlMaterialNodeProxy::editorNodes() const +{ + return m_editorNodes; +} + void QmlMaterialNodeProxy::setPossibleTypes(const QStringList &types) { if (types == m_possibleTypes) @@ -81,7 +88,7 @@ void QmlMaterialNodeProxy::updatePossibleTypes() } const QString &matType = materialNode().simplifiedTypeName(); - const ModelNodes selectedNodes = materialView()->selectedModelNodes(); // TODO: replace it by PropertyEditorView::currentNodes() + const ModelNodes selectedNodes = editorNodes(); bool allAreBasic = Utils::allOf(selectedNodes, [&](const ModelNode &node) { return basicTypes.contains(node.simplifiedTypeName()); }); @@ -275,6 +282,11 @@ void QmlMaterialNodeProxy::setMaterialNode(const QmlObjectNode &material) emit materialNodeChanged(); } +void QmlMaterialNodeProxy::setEditorNodes(const ModelNodes &editorNodes) +{ + m_editorNodes = editorNodes; +} + bool QmlMaterialNodeProxy::hasQuick3DImport() const { return materialNode().isValid() && materialNode().model()->hasImport("QtQuick3D"_L1); diff --git a/src/plugins/qmldesigner/components/propertyeditor/qmlmaterialnodeproxy.h b/src/plugins/qmldesigner/components/propertyeditor/qmlmaterialnodeproxy.h index 58bf8935970..b4bd7fb6ddb 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/qmlmaterialnodeproxy.h +++ b/src/plugins/qmldesigner/components/propertyeditor/qmlmaterialnodeproxy.h @@ -35,11 +35,12 @@ public: explicit QmlMaterialNodeProxy(); ~QmlMaterialNodeProxy() override; - void setup(const QmlObjectNode &objectNode); + void setup(const ModelNodes &editorNodes); QStringList possibleTypes() const { return m_possibleTypes; } ModelNode materialNode() const; + ModelNodes editorNodes() const; int possibleTypeIndex() const { return m_possibleTypeIndex; } @@ -67,15 +68,15 @@ private: // Methods void updatePossibleTypeIndex(); void updatePreviewModel(); void setMaterialNode(const QmlObjectNode &material); + void setEditorNodes(const ModelNodes &editorNodes); bool hasQuick3DImport() const; AbstractView *materialView() const; private: - bool m_has3DModelSelection = false; - QmlObjectNode m_materialNode; + ModelNodes m_editorNodes; QStringList m_possibleTypes; int m_possibleTypeIndex = -1; diff --git a/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.cpp b/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.cpp index 1e6fe6a1e3e..07c7537c852 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.cpp @@ -22,9 +22,15 @@ QmlModelNodeProxy::QmlModelNodeProxy(QObject *parent) : { } -void QmlModelNodeProxy::setup(const QmlObjectNode &objectNode) +void QmlModelNodeProxy::setup(const ModelNode &node) { - m_qmlObjectNode = objectNode; + setup(ModelNodes{node}); +} + +void QmlModelNodeProxy::setup(const ModelNodes &editorNodes) +{ + m_qmlObjectNode = editorNodes.isEmpty() ? ModelNode{} : editorNodes.first(); + m_editorNodes = editorNodes; m_subselection.clear(); @@ -61,12 +67,22 @@ ModelNode QmlModelNodeProxy::modelNode() const return m_qmlObjectNode.modelNode(); } +ModelNodes QmlModelNodeProxy::editorNodes() const +{ + return m_editorNodes; +} + +ModelNode QmlModelNodeProxy::singleSelectedNode() const +{ + return multiSelection() ? ModelNode{} : modelNode(); +} + bool QmlModelNodeProxy::multiSelection() const { if (!m_qmlObjectNode.isValid()) return false; - return m_qmlObjectNode.view()->selectedModelNodes().size() > 1; + return editorNodes().size() > 1; } QString QmlModelNodeProxy::nodeId() const diff --git a/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.h b/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.h index 207594b15b3..c61c9d2bcd0 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.h +++ b/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.h @@ -22,7 +22,8 @@ class QMLDESIGNER_EXPORT QmlModelNodeProxy : public QObject public: explicit QmlModelNodeProxy(QObject *parent = nullptr); - void setup(const QmlObjectNode &objectNode); + void setup(const ModelNode &node); + void setup(const ModelNodes &editorNodes); static void registerDeclarativeType(); @@ -33,6 +34,8 @@ public: QmlObjectNode qmlObjectNode() const; ModelNode modelNode() const; + ModelNodes editorNodes() const; + ModelNode singleSelectedNode() const; bool multiSelection() const; @@ -81,6 +84,7 @@ private: PropertyEditorSubSelectionWrapper *findWrapper(int internalId) const; QmlObjectNode m_qmlObjectNode; + ModelNodes m_editorNodes; QList> m_subselection; }; diff --git a/src/plugins/qmldesigner/components/textureeditor/textureeditorqmlbackend.cpp b/src/plugins/qmldesigner/components/textureeditor/textureeditorqmlbackend.cpp index af56832ea38..f2b88649694 100644 --- a/src/plugins/qmldesigner/components/textureeditor/textureeditorqmlbackend.cpp +++ b/src/plugins/qmldesigner/components/textureeditor/textureeditorqmlbackend.cpp @@ -211,7 +211,7 @@ void TextureEditorQmlBackend::setup(const QmlObjectNode &selectedTextureNode, co } // model node - m_backendModelNode.setup(selectedTextureNode.modelNode()); + m_backendModelNode.setup(selectedTextureNode); context()->setContextProperty("modelNodeBackend", &m_backendModelNode); context()->setContextProperty("hasTexture", QVariant(true));