diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp index eaa5ef95738..045a622f2c8 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp @@ -955,19 +955,22 @@ void PropertyEditorQmlBackend::setValueforAuxiliaryProperties(const QmlObjectNod setValue(qmlObjectNode, propertyName, qmlObjectNode.modelNode().auxiliaryDataWithDefault(key)); } -QUrl PropertyEditorQmlBackend::getQmlUrlForMetaInfo(const NodeMetaInfo &metaInfo, TypeName &className) +std::tuple PropertyEditorQmlBackend::getQmlUrlForMetaInfo(const NodeMetaInfo &metaInfo) { + QString className; if (metaInfo.isValid()) { const NodeMetaInfos hierarchy = metaInfo.selfAndPrototypes(); for (const NodeMetaInfo &info : hierarchy) { QUrl fileUrl = fileToUrl(locateQmlFile(info, QString::fromUtf8(qmlFileName(info)))); if (fileUrl.isValid()) { - className = info.typeName(); - return fileUrl; + return {fileUrl, info}; } } } - return fileToUrl(QDir(propertyEditorResourcesPath()).filePath(QLatin1String("QtQuick/emptyPane.qml"))); + + return {fileToUrl( + QDir(propertyEditorResourcesPath()).filePath(QLatin1String("QtQuick/emptyPane.qml"))), + {}}; } QString PropertyEditorQmlBackend::locateQmlFile(const NodeMetaInfo &info, const QString &relativePath) diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.h b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.h index 092d411dfac..2b5e324ff2c 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.h +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.h @@ -51,7 +51,7 @@ public: static QString templateGeneration(const NodeMetaInfo &type, const NodeMetaInfo &superType, const QmlObjectNode &node); static QUrl getQmlFileUrl(const TypeName &relativeTypeName, const NodeMetaInfo &info); - static QUrl getQmlUrlForMetaInfo(const NodeMetaInfo &modelNode, TypeName &className); + static std::tuple getQmlUrlForMetaInfo(const NodeMetaInfo &modelNode); static bool checkIfUrlExists(const QUrl &url); diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp index ba6078a778a..bf35e2512eb 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp @@ -437,80 +437,130 @@ void PropertyEditorView::resetView() updateSize(); } +namespace { -void PropertyEditorView::setupQmlBackend() +std::tuple diffType(const NodeMetaInfo &commonAncestor, + const NodeMetaInfo &specificsClassMetaInfo) { - TypeName specificsClassName; - - const NodeMetaInfo commonAncestor = PropertyEditorQmlBackend::findCommonAncestor(m_selectedNode); - - const QUrl qmlFile(PropertyEditorQmlBackend::getQmlUrlForMetaInfo(commonAncestor, specificsClassName)); + NodeMetaInfo diffClassMetaInfo; QUrl qmlSpecificsFile; - TypeName diffClassName; if (commonAncestor.isValid()) { - diffClassName = commonAncestor.typeName(); + diffClassMetaInfo = commonAncestor; const NodeMetaInfos hierarchy = commonAncestor.selfAndPrototypes(); for (const NodeMetaInfo &metaInfo : hierarchy) { if (PropertyEditorQmlBackend::checkIfUrlExists(qmlSpecificsFile)) break; - qmlSpecificsFile = PropertyEditorQmlBackend::getQmlFileUrl(metaInfo.typeName() + "Specifics", metaInfo); - diffClassName = metaInfo.typeName(); + qmlSpecificsFile = PropertyEditorQmlBackend::getQmlFileUrl(metaInfo.typeName() + "Specifics", + metaInfo); + diffClassMetaInfo = metaInfo; } } if (!PropertyEditorQmlBackend::checkIfUrlExists(qmlSpecificsFile)) - diffClassName = specificsClassName; + diffClassMetaInfo = specificsClassMetaInfo; - QString specificQmlData; + return {diffClassMetaInfo, qmlSpecificsFile}; +} - if (commonAncestor.isValid() && m_selectedNode.metaInfo().isValid() && diffClassName != m_selectedNode.type()) - specificQmlData = PropertyEditorQmlBackend::templateGeneration(commonAncestor, model()->metaInfo(diffClassName), m_selectedNode); +QString getSpecificQmlData(const NodeMetaInfo &commonAncestor, + const ModelNode &selectedNode, + const NodeMetaInfo &diffClassMetaInfo) +{ + if (commonAncestor.isValid() && diffClassMetaInfo != selectedNode.metaInfo()) + return PropertyEditorQmlBackend::templateGeneration(commonAncestor, + diffClassMetaInfo, + selectedNode); - PropertyEditorQmlBackend *currentQmlBackend = m_qmlBackendHash.value(qmlFile.toString()); + return {}; +} - QString currentStateName = currentState().isBaseState() ? currentState().name() : QStringLiteral("invalid state"); +PropertyEditorQmlBackend *getQmlBackend(QHash &qmlBackendHash, + const QUrl &qmlFileUrl, + AsynchronousImageCache &imageCache, + PropertyEditorWidget *stackedWidget, + PropertyEditorView *propertyEditorView) +{ + auto qmlFileName = qmlFileUrl.toString(); + PropertyEditorQmlBackend *currentQmlBackend = qmlBackendHash.value(qmlFileName); if (!currentQmlBackend) { - currentQmlBackend = new PropertyEditorQmlBackend(this, m_imageCache); + currentQmlBackend = new PropertyEditorQmlBackend(propertyEditorView, imageCache); - m_stackedWidget->addWidget(currentQmlBackend->widget()); - m_qmlBackendHash.insert(qmlFile.toString(), currentQmlBackend); + stackedWidget->addWidget(currentQmlBackend->widget()); + qmlBackendHash.insert(qmlFileName, currentQmlBackend); - if (m_selectedNode.isValid()) { - QmlObjectNode qmlObjectNode{m_selectedNode}; - Q_ASSERT(qmlObjectNode.isValid()); - currentQmlBackend->setup(qmlObjectNode, currentStateName, qmlSpecificsFile, this); - } - - if (specificQmlData.isEmpty()) - currentQmlBackend->contextObject()->setSpecificQmlData(specificQmlData); - - currentQmlBackend->contextObject()->setSpecificQmlData(specificQmlData); - currentQmlBackend->setSource(qmlFile); - } else { - QmlObjectNode qmlObjectNode{m_selectedNode}; - - if (specificQmlData.isEmpty()) - currentQmlBackend->contextObject()->setSpecificQmlData(specificQmlData); - currentQmlBackend->setup(qmlObjectNode, currentStateName, qmlSpecificsFile, this); - currentQmlBackend->contextObject()->setSpecificQmlData(specificQmlData); + currentQmlBackend->setSource(qmlFileUrl); } - currentQmlBackend->widget()->installEventFilter(this); - m_stackedWidget->setCurrentWidget(currentQmlBackend->widget()); + return currentQmlBackend; +} +void setupCurrentQmlBackend(PropertyEditorQmlBackend *currentQmlBackend, + const ModelNode &selectedNode, + const QUrl &qmlSpecificsFile, + const QmlModelState ¤tState, + PropertyEditorView *propertyEditorView, + const QString &specificQmlData) +{ + QString currentStateName = currentState.isBaseState() ? currentState.name() + : QStringLiteral("invalid state"); + + QmlObjectNode qmlObjectNode{selectedNode}; + if (specificQmlData.isEmpty()) + currentQmlBackend->contextObject()->setSpecificQmlData(specificQmlData); + currentQmlBackend->setup(qmlObjectNode, currentStateName, qmlSpecificsFile, propertyEditorView); + currentQmlBackend->contextObject()->setSpecificQmlData(specificQmlData); +} + +void setupInsight(const ModelNode &rootModelNode, PropertyEditorQmlBackend *currentQmlBackend) +{ + if (rootModelNode.hasAuxiliaryData(insightEnabledProperty)) { + currentQmlBackend->contextObject()->setInsightEnabled( + rootModelNode.auxiliaryData(insightEnabledProperty)->toBool()); + } + + if (rootModelNode.hasAuxiliaryData(insightCategoriesProperty)) { + currentQmlBackend->contextObject()->setInsightCategories( + rootModelNode.auxiliaryData(insightCategoriesProperty)->toStringList()); + } +} + +void setupWidget(PropertyEditorQmlBackend *currentQmlBackend, + PropertyEditorView *propertyEditorView, + QStackedWidget *stackedWidget) +{ + currentQmlBackend->widget()->installEventFilter(propertyEditorView); + stackedWidget->setCurrentWidget(currentQmlBackend->widget()); currentQmlBackend->contextObject()->triggerSelectionChanged(); +} +} // namespace + +void PropertyEditorView::setupQmlBackend() +{ + const NodeMetaInfo commonAncestor = PropertyEditorQmlBackend::findCommonAncestor(m_selectedNode); + + const auto [qmlFileUrl, specificsClassMetaInfo] = PropertyEditorQmlBackend::getQmlUrlForMetaInfo( + commonAncestor); + + auto [diffClassMetaInfo, qmlSpecificsFile] = diffType(commonAncestor, specificsClassMetaInfo); + + QString specificQmlData = getSpecificQmlData(commonAncestor, m_selectedNode, diffClassMetaInfo); + + PropertyEditorQmlBackend *currentQmlBackend = getQmlBackend(m_qmlBackendHash, + qmlFileUrl, + m_imageCache, + m_stackedWidget, + this); + + setupCurrentQmlBackend( + currentQmlBackend, m_selectedNode, qmlSpecificsFile, currentState(), this, specificQmlData); + + setupWidget(currentQmlBackend, this, m_stackedWidget); m_qmlBackEndForCurrentType = currentQmlBackend; - if (rootModelNode().hasAuxiliaryData(insightEnabledProperty)) - m_qmlBackEndForCurrentType->contextObject()->setInsightEnabled( - rootModelNode().auxiliaryData(insightEnabledProperty)->toBool()); - - if (rootModelNode().hasAuxiliaryData(insightCategoriesProperty)) - m_qmlBackEndForCurrentType->contextObject()->setInsightCategories( - rootModelNode().auxiliaryData(insightCategoriesProperty)->toStringList()); + setupInsight(rootModelNode(), currentQmlBackend); } void PropertyEditorView::commitVariantValueToModel(const PropertyName &propertyName, const QVariant &value) diff --git a/src/plugins/qmldesigner/designercore/include/nodemetainfo.h b/src/plugins/qmldesigner/designercore/include/nodemetainfo.h index 3736079cdc2..c782c47bc4c 100644 --- a/src/plugins/qmldesigner/designercore/include/nodemetainfo.h +++ b/src/plugins/qmldesigner/designercore/include/nodemetainfo.h @@ -204,6 +204,11 @@ public: return first.m_privateData == second.m_privateData; } + friend bool operator!=(const NodeMetaInfo &first, const NodeMetaInfo &second) + { + return !(first == second); + } + private: const Storage::Info::Type &typeData() const; bool isSubclassOf(const TypeName &type, int majorVersion = -1, int minorVersion = -1) const;