From 38b215097032f4d19831ccaeae14dc4ef5da070e Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Wed, 11 Sep 2024 17:15:06 +0200 Subject: [PATCH] QmlDesigner: Integrate Model::singletonMetaInfos() THe backend model is removed because it is not anymore used. Task-number: QDS-13603 Change-Id: I9e9857e8698d450e81246009d6f463c50d4ae392 Reviewed-by: Tim Jenssen --- src/plugins/qmldesigner/CMakeLists.txt | 1 - .../components/bindingeditor/actioneditor.cpp | 37 +- .../bindingeditor/bindingeditor.cpp | 24 +- .../connectioneditor/backendmodel.cpp | 318 ------------------ .../connectioneditor/backendmodel.h | 48 --- .../connectioneditorutils.cpp | 66 +++- .../connectioneditor/connectioneditorutils.h | 2 + .../connectioneditor/connectionmodel.cpp | 212 +++++++----- .../connectioneditor/connectionview.cpp | 18 - .../connectioneditor/connectionview.h | 4 - .../instances/nodeinstanceview.cpp | 2 + .../libs/designercore/include/nodemetainfo.h | 2 +- .../libs/designercore/include/rewriterview.h | 2 + .../designercore/metainfo/nodemetainfo.cpp | 2 +- .../designercore/rewriter/rewriterview.cpp | 2 + 15 files changed, 256 insertions(+), 484 deletions(-) delete mode 100644 src/plugins/qmldesigner/components/connectioneditor/backendmodel.cpp delete mode 100644 src/plugins/qmldesigner/components/connectioneditor/backendmodel.h diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt index e6081e954de..6ec60cc2159 100644 --- a/src/plugins/qmldesigner/CMakeLists.txt +++ b/src/plugins/qmldesigner/CMakeLists.txt @@ -558,7 +558,6 @@ extend_qtc_plugin(QmlDesigner SOURCES_PREFIX components/connectioneditor SOURCES addnewbackenddialog.cpp addnewbackenddialog.h addnewbackenddialog.ui - backendmodel.cpp backendmodel.h bindingmodel.cpp bindingmodel.h bindingmodelitem.cpp bindingmodelitem.h connectioneditor.qrc diff --git a/src/plugins/qmldesigner/components/bindingeditor/actioneditor.cpp b/src/plugins/qmldesigner/components/bindingeditor/actioneditor.cpp index bd63742d5e7..f226fa0798e 100644 --- a/src/plugins/qmldesigner/components/bindingeditor/actioneditor.cpp +++ b/src/plugins/qmldesigner/components/bindingeditor/actioneditor.cpp @@ -305,6 +305,31 @@ void ActionEditor::prepareConnections() } // Singletons +#ifdef QDS_USE_PROJECTSTORAGE + if (auto model = m_modelNode.model()) { + for (const auto &metaInfo : model->singletonMetaInfos()) { + if (metaInfo.isValid()) { + ActionEditorDialog::SingletonOption singelton; + for (const auto &property : metaInfo.properties()) { + if (isSkippedType(property.propertyType())) + continue; + auto exportedTypeName = model + ->exportedTypeNameForMetaInfo(property.propertyType()) + .name.toQByteArray(); + singelton.properties.append( + ActionEditorDialog::PropertyOption(QString::fromUtf8(property.name()), + exportedTypeName, + property.isWritable())); + } + + if (!singelton.properties.isEmpty()) { + singelton.item = metaInfo.displayName(); + singletons.append(singelton); + } + } + } + } +#else if (RewriterView *rv = m_modelNode.view()->rewriterView()) { for (const QmlTypeData &data : rv->getQMLTypes()) { if (!data.typeName.isEmpty()) { @@ -314,21 +339,10 @@ void ActionEditor::prepareConnections() for (const auto &property : metaInfo.properties()) { if (isSkippedType(property.propertyType())) continue; -#ifdef QDS_USE_PROJECTSTORAGE - auto exportedTypeName = model - ->exportedTypeNameForMetaInfo( - property.propertyType()) - .name.toQByteArray(); - singelton.properties.append( - ActionEditorDialog::PropertyOption(QString::fromUtf8(property.name()), - exportedTypeName, - property.isWritable())); -#else singelton.properties.append(ActionEditorDialog::PropertyOption( QString::fromUtf8(property.name()), skipCpp(property.propertyType().typeName()), property.isWritable())); -#endif } if (!singelton.properties.isEmpty()) { @@ -339,6 +353,7 @@ void ActionEditor::prepareConnections() } } } +#endif // States for (const QmlModelState &state : QmlItemNode(m_modelNode.view()->rootModelNode()).states().allStates()) diff --git a/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.cpp b/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.cpp index 6a77b6235eb..bb98db869c4 100644 --- a/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.cpp +++ b/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.cpp @@ -246,6 +246,26 @@ void BindingEditor::prepareBindings() } //singletons: +#ifdef QDS_USE_PROJECTSTORAGE + if (auto model = m_modelNode.view()->model()) { + for (const auto &metaInfo : model->singletonMetaInfos()) { + BindingEditorDialog::BindingOption binding; + + for (const auto &property : metaInfo.properties()) { + const auto propertyType = property.propertyType(); + + if (compareTypes(m_backendValueType, propertyType)) { + binding.properties.append(QString::fromUtf8(property.name())); + } + } + + if (!binding.properties.isEmpty()) { + binding.item = metaInfo.displayName(); + bindings.append(binding); + } + } + } +#else if (RewriterView *rv = m_modelNode.view()->rewriterView()) { for (const QmlTypeData &data : rv->getQMLTypes()) { if (!data.typeName.isEmpty()) { @@ -270,7 +290,7 @@ void BindingEditor::prepareBindings() } } } - +#endif if (!bindings.isEmpty() && m_dialog) m_dialog->setAllBindings(bindings, m_backendValueType); } @@ -289,7 +309,7 @@ void BindingEditor::updateWindowName() } else { #ifdef QDS_USE_PROJECTSTORAGE targetString = " [" + (m_targetName.isEmpty() ? QString() : (m_targetName + ": ")) - + QString::fromUtf8(m_backendValueType.displayName()) + "]"; + + m_backendValueType.displayName() + "]"; #else targetString = " [" + (m_targetName.isEmpty() ? QString() : (m_targetName + ": ")) + QString::fromUtf8(m_backendValueType.simplifiedTypeName()) + "]"; diff --git a/src/plugins/qmldesigner/components/connectioneditor/backendmodel.cpp b/src/plugins/qmldesigner/components/connectioneditor/backendmodel.cpp deleted file mode 100644 index 398fa968e45..00000000000 --- a/src/plugins/qmldesigner/components/connectioneditor/backendmodel.cpp +++ /dev/null @@ -1,318 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include - -#include "backendmodel.h" - -#include "bindingproperty.h" -#include "connectioneditorutils.h" -#include "connectionview.h" -#include "exception.h" -#include "nodemetainfo.h" -#include "nodeproperty.h" -#include "rewriterview.h" - -#include "addnewbackenddialog.h" - -#include -#include - -namespace QmlDesigner { - -BackendModel::BackendModel(ConnectionView *view) - : m_connectionView(view) -{ - connect(this, &QStandardItemModel::dataChanged, this, &BackendModel::handleDataChanged); -} - -ConnectionView *BackendModel::connectionView() const -{ - return m_connectionView; -} - -void BackendModel::resetModel() -{ - if (!m_connectionView->model()) - return; - - RewriterView *rewriterView = m_connectionView->model()->rewriterView(); - - m_lock = true; - - beginResetModel(); - clear(); - - setHorizontalHeaderLabels(QStringList({ tr("Type"), tr("Name"), tr("Singleton"), tr("Local") })); - - ModelNode rootNode = connectionView()->rootModelNode(); - - static const PropertyTypeList simpleTypes = {"int", "real", "color", "string"}; - - if (rewriterView) - for (const QmlTypeData &cppTypeData : rewriterView->getQMLTypes()) - if (cppTypeData.isSingleton) { - NodeMetaInfo metaInfo = m_connectionView->model()->metaInfo( - cppTypeData.typeName.toUtf8()); - if (metaInfo.isValid() && !metaInfo.isQtQuickItem()) { - auto type = new QStandardItem(cppTypeData.typeName); - type->setData(cppTypeData.typeName, Qt::UserRole + 1); - type->setData(true, Qt::UserRole + 2); - type->setEditable(false); - - auto name = new QStandardItem(cppTypeData.typeName); - name->setEditable(false); - - QStandardItem *singletonItem = new QStandardItem(""); - singletonItem->setCheckState(Qt::Checked); - - singletonItem->setCheckable(true); - singletonItem->setEnabled(false); - - QStandardItem *inlineItem = new QStandardItem(""); - - inlineItem->setCheckState(Qt::Unchecked); - - inlineItem->setCheckable(true); - inlineItem->setEnabled(false); - - appendRow({type, name, singletonItem, inlineItem}); - } - } - - if (rootNode.isValid()) { - const QList properties = rootNode.properties(); - for (const AbstractProperty &property : properties) - if (property.isDynamic() && !simpleTypes.contains(property.dynamicTypeName())) { - - NodeMetaInfo metaInfo = m_connectionView->model()->metaInfo(property.dynamicTypeName()); - if (metaInfo.isValid() && !metaInfo.isQtQuickItem()) { - QStandardItem *type = new QStandardItem(QString::fromUtf8(property.dynamicTypeName())); - type->setEditable(false); - - type->setData(QString::fromUtf8(property.name()), Qt::UserRole + 1); - type->setData(false, Qt::UserRole + 2); - QStandardItem *name = new QStandardItem(QString::fromUtf8(property.name())); - - QStandardItem *singletonItem = new QStandardItem(""); - singletonItem->setCheckState(Qt::Unchecked); - - singletonItem->setCheckable(true); - singletonItem->setEnabled(false); - - QStandardItem *inlineItem = new QStandardItem(""); - - inlineItem->setCheckState(property.isNodeProperty() ? Qt::Checked : Qt::Unchecked); - - inlineItem->setCheckable(true); - inlineItem->setEnabled(false); - - appendRow({ type, name, singletonItem, inlineItem }); - } - } - } - - m_lock = false; - - endResetModel(); -} - -QStringList BackendModel::possibleCppTypes() const -{ - RewriterView *rewriterView = m_connectionView->model()->rewriterView(); - - QStringList list; - - if (rewriterView) { - const QList cppTypes = rewriterView->getQMLTypes(); - for (const QmlTypeData &cppTypeData : cppTypes) - list.append(cppTypeData.typeName); - } - - return list; -} - -QmlTypeData BackendModel::cppTypeDataForType(const QString &typeName) const -{ - RewriterView *rewriterView = m_connectionView->model()->rewriterView(); - - if (!rewriterView) - return QmlTypeData(); - - return Utils::findOr(rewriterView->getQMLTypes(), QmlTypeData(), [&typeName](const QmlTypeData &data) { - return typeName == data.typeName; - }); -} - -void BackendModel::deletePropertyByRow(int rowNumber) -{ - Model *model = m_connectionView->model(); - if (!model) - return; - - /* singleton case remove the import */ - if (data(index(rowNumber, 0), Qt::UserRole + 1).toBool()) { - const QString typeName = data(index(rowNumber, 0), Qt::UserRole + 1).toString(); - QmlTypeData cppTypeData = cppTypeDataForType(typeName); - - if (cppTypeData.isSingleton) { - - Import import = Import::createLibraryImport(cppTypeData.importUrl, cppTypeData.versionString); - - try { - if (model->hasImport(import)) - model->changeImports({}, {import}); - } catch (const Exception &e) { - e.showException(); - } - } - } else { - const QString propertyName = data(index(rowNumber, 0), Qt::UserRole + 1).toString(); - - ModelNode modelNode = connectionView()->rootModelNode(); - - try { - modelNode.removeProperty(propertyName.toUtf8()); - } catch (const Exception &e) { - e.showException(); - } - } - - resetModel(); -} - -void BackendModel::addNewBackend() -{ - Model *model = m_connectionView->model(); - if (!model) - return; - - AddNewBackendDialog dialog(Core::ICore::dialogParent()); - - RewriterView *rewriterView = model->rewriterView(); - - QStringList availableTypes; - - if (rewriterView) - dialog.setupPossibleTypes(Utils::filtered(rewriterView->getQMLTypes(), [model](const QmlTypeData &cppTypeData) { - return !cppTypeData.isSingleton || !model->metaInfo(cppTypeData.typeName.toUtf8()).isValid(); - /* Only show singletons if the import is missing */ - })); - - dialog.exec(); - - if (dialog.applied()) { - QStringList importSplit = dialog.importString().split(" "); - if (importSplit.size() != 2) { - qCWarning(ConnectionEditorLog) << __FUNCTION__ << "invalid import" << importSplit; - QTC_ASSERT(false, return); - } - - QString typeName = dialog.type(); - - Import import = Import::createLibraryImport(importSplit.constFirst(), importSplit.constLast()); - - /* We cannot add an import and add a node from that import in a single transaction. - * We need the import to have the meta info available. - */ - - if (!model->hasImport(import)) - model->changeImports({import}, {}); - - QString propertyName = m_connectionView->model()->generateNewId(typeName); - - NodeMetaInfo metaInfo = model->metaInfo(typeName.toUtf8()); - - QTC_ASSERT(metaInfo.isValid(), return); - - /* Add a property for non singleton types. For singletons just adding the import is enough. */ - if (!dialog.isSingleton()) { - m_connectionView->executeInTransaction("BackendModel::addNewBackend", - [this, metaInfo, typeName, propertyName, &dialog] { - - if (dialog.localDefinition()) { -#ifdef QDS_USE_PROJECTSTORAGE - ModelNode newNode = m_connectionView->createModelNode(typeName.toUtf8()); -#else - int minorVersion = metaInfo.minorVersion(); - int majorVersion = metaInfo.majorVersion(); - ModelNode newNode = m_connectionView->createModelNode(metaInfo.typeName(), - majorVersion, - minorVersion); -#endif - m_connectionView->rootModelNode().nodeProperty(propertyName.toUtf8()).setDynamicTypeNameAndsetModelNode( - typeName.toUtf8(), newNode); - } else { - m_connectionView->rootModelNode().bindingProperty( - propertyName.toUtf8()).setDynamicTypeNameAndExpression(typeName.toUtf8(), "null"); - } - }); - } - } - resetModel(); -} - -void BackendModel::updatePropertyName(int rowNumber) -{ - const PropertyName newName = data(index(rowNumber, 1)).toString().toUtf8(); - const PropertyName oldName = data(index(rowNumber, 0), Qt::UserRole + 1).toString().toUtf8(); - - m_connectionView->executeInTransaction("BackendModel::updatePropertyName", [this, newName, oldName](){ - - ModelNode rootModelNode = m_connectionView->rootModelNode(); - if (rootModelNode.property(oldName).isNodeProperty()) { - - const TypeName typeName = rootModelNode.nodeProperty(oldName).dynamicTypeName(); - const ModelNode targetModelNode = rootModelNode.nodeProperty(oldName).modelNode(); - const TypeName fullTypeName = targetModelNode.type(); - const int majorVersion = targetModelNode.majorVersion(); - const int minorVersion = targetModelNode.minorVersion(); - - rootModelNode.removeProperty(oldName); - ModelNode newNode = m_connectionView->createModelNode(fullTypeName, majorVersion, minorVersion); - m_connectionView->rootModelNode().nodeProperty(newName).setDynamicTypeNameAndsetModelNode(typeName, newNode); - - } else if (rootModelNode.property(oldName).isBindingProperty()) { - const QString expression = rootModelNode.bindingProperty(oldName).expression(); - const TypeName typeName = rootModelNode.bindingProperty(oldName).dynamicTypeName(); - - rootModelNode.removeProperty(oldName); - rootModelNode.bindingProperty(newName).setDynamicTypeNameAndExpression(typeName, expression); - } else { - qCWarning(ConnectionEditorLog) << __FUNCTION__ << oldName << newName << "failed..."; - QTC_ASSERT(false, return); - } - }); -} - -void BackendModel::handleDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) -{ - if (m_lock) - return; - - if (topLeft != bottomRight) { - qCWarning(ConnectionEditorLog) << __FUNCTION__ << "multi edit?"; - return; - } - - m_lock = true; - - int currentColumn = topLeft.column(); - int currentRow = topLeft.row(); - - switch (currentColumn) { - case 0: { - //updating user data - } break; - case 1: { - updatePropertyName(currentRow); - } break; - - default: - qCWarning(ConnectionEditorLog) << __FUNCTION__ << "column" << currentColumn; - } - - m_lock = false; -} - -} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/connectioneditor/backendmodel.h b/src/plugins/qmldesigner/components/connectioneditor/backendmodel.h deleted file mode 100644 index 9feaff91943..00000000000 --- a/src/plugins/qmldesigner/components/connectioneditor/backendmodel.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#pragma once -#include - -#include "rewriterview.h" - -namespace QmlDesigner { - -class ConnectionView; - -class BackendModel : public QStandardItemModel -{ - Q_OBJECT -public: - enum ColumnRoles { - TypeNameColumn = 0, - PropertyNameColumn = 1, - IsSingletonColumn = 2, - IsLocalColumn = 3, - }; - - BackendModel(ConnectionView *view); - - ConnectionView *connectionView() const; - - void resetModel(); - - QStringList possibleCppTypes() const; - QmlTypeData cppTypeDataForType(const QString &typeName) const; - - void deletePropertyByRow(int rowNumber); - - void addNewBackend(); - -protected: - void updatePropertyName(int rowNumber); - -private: - void handleDataChanged(const QModelIndex &topLeft, const QModelIndex& bottomRight); - -private: - ConnectionView *m_connectionView; - bool m_lock = false; -}; - -} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectioneditorutils.cpp b/src/plugins/qmldesigner/components/connectioneditor/connectioneditorutils.cpp index b96e000f8cd..fcedbc9876c 100644 --- a/src/plugins/qmldesigner/components/connectioneditor/connectioneditorutils.cpp +++ b/src/plugins/qmldesigner/components/connectioneditor/connectioneditorutils.cpp @@ -277,12 +277,12 @@ std::pair splitExpression(const QString &expression) return {sourceNode, propertyName}; } +#ifndef QDS_USE_PROJECTSTORAGE QStringList singletonsFromView(AbstractView *view) { RewriterView *rv = view->rewriterView(); if (!rv) return {}; - QStringList out; for (const QmlTypeData &data : rv->getQMLTypes()) { if (data.isSingleton && !data.typeName.isEmpty()) @@ -301,6 +301,7 @@ std::vector propertiesFromSingleton(const QString &name, Abstr return {}; } +#endif QList dynamicPropertiesFromNode(const ModelNode &node) { @@ -317,9 +318,30 @@ QList dynamicPropertiesFromNode(const ModelNode &node) return dynamicProperties; } +#ifdef QDS_USE_PROJECTSTORAGE +QStringList availableSources(AbstractView *view) +{ + if (!view->isAttached()) + return {}; + + QStringList sourceNodes; + + for (const auto &metaInfo : view->model()->singletonMetaInfos()) + sourceNodes.push_back(metaInfo.displayName()); + + for (const ModelNode &modelNode : view->allModelNodes()) { + if (auto id = modelNode.id(); !id.isEmpty()) + sourceNodes.append(id); + } + + std::sort(sourceNodes.begin(), sourceNodes.end()); + return sourceNodes; +} +#else QStringList availableSources(AbstractView *view) { QStringList sourceNodes; + for (const ModelNode &modelNode : view->allModelNodes()) { if (!modelNode.id().isEmpty()) sourceNodes.append(modelNode.id()); @@ -327,6 +349,7 @@ QStringList availableSources(AbstractView *view) std::sort(sourceNodes.begin(), sourceNodes.end()); return singletonsFromView(view) + sourceNodes; } +#endif QStringList availableTargetProperties(const BindingProperty &bindingProperty) { @@ -351,6 +374,8 @@ QStringList availableTargetProperties(const BindingProperty &bindingProperty) return {}; } +namespace { + ModelNode getNodeByIdOrParent(AbstractView *view, const QString &id, const ModelNode &targetNode) { if (id != QLatin1String("parent")) @@ -362,6 +387,35 @@ ModelNode getNodeByIdOrParent(AbstractView *view, const QString &id, const Model return {}; } +#ifdef QDS_USE_PROJECTSTORAGE +NodeMetaInfo singletonMetaInfoForId(const QString &id, AbstractView *view) +{ + using Storage::Info::ExportedTypeName; + const auto model = view->model(); + + if (!model) + return {}; + + const Utils::SmallString name = id; + + const auto singletonMetaInfos = model->singletonMetaInfos(); + + const auto sourceId = model->fileUrlSourceId(); + + auto found = std::ranges::find_if(singletonMetaInfos, [&](const auto &metaInfo) { + auto exportedTypeNames = metaInfo.exportedTypeNamesForSourceId(sourceId); + return std::ranges::find(exportedTypeNames, name, &ExportedTypeName::name) + != exportedTypeNames.end(); + }); + + if (found == singletonMetaInfos.end()) + return {}; + + return *found; +} +#endif +} // namespace + QStringList availableSourceProperties(const QString &id, const BindingProperty &targetProperty, AbstractView *view) @@ -378,6 +432,15 @@ QStringList availableSourceProperties(const QString &id, QStringList possibleProperties; if (!modelNode.isValid()) { +#ifdef QDS_USE_PROJECTSTORAGE + if (auto singletonMetaInfo = singletonMetaInfoForId(id, view)) { + for (const auto &property : singletonMetaInfo.properties()) { + if (metaInfoIsCompatible(targetType, property)) + possibleProperties.push_back(QString::fromUtf8(property.name())); + } + return possibleProperties; + } +#else QStringList singletons = singletonsFromView(view); if (singletons.contains(id)) { for (const auto &property : propertiesFromSingleton(id, view)) { @@ -386,6 +449,7 @@ QStringList availableSourceProperties(const QString &id, } return possibleProperties; } +#endif qCWarning(ConnectionEditorLog) << __FUNCTION__ << "invalid model node:" << id; return {}; } diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectioneditorutils.h b/src/plugins/qmldesigner/components/connectioneditor/connectioneditorutils.h index 501968a642a..220fdc9e11d 100644 --- a/src/plugins/qmldesigner/components/connectioneditor/connectioneditorutils.h +++ b/src/plugins/qmldesigner/components/connectioneditor/connectioneditorutils.h @@ -40,8 +40,10 @@ QVariant defaultValueForType(const TypeName &type); QString defaultExpressionForType(const TypeName &type); std::pair splitExpression(const QString &expression); +#ifndef QDS_USE_PROJECTSTORAGE QStringList singletonsFromView(AbstractView *view); std::vector propertiesFromSingleton(const QString &name, AbstractView *view); +#endif QList dynamicPropertiesFromNode(const ModelNode &node); QStringList availableSources(AbstractView *view); diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp b/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp index 5d94ca85867..6fd43f9c37f 100644 --- a/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp +++ b/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp @@ -40,10 +40,10 @@ const char defaultCondition[] = "condition"; QStringList propertyNameListToStringList(const QmlDesigner::PropertyNameList &propertyNameList) { QStringList stringList; + stringList.reserve(propertyNameList.size()); for (const QmlDesigner::PropertyName &propertyName : propertyNameList) - stringList << QString::fromUtf8(propertyName); + stringList.push_back(QString::fromUtf8(propertyName)); - stringList.removeDuplicates(); return stringList; } @@ -206,6 +206,62 @@ void ConnectionModel::updateSignalName(int rowNumber) } } +namespace { +#ifdef QDS_USE_PROJECTSTORAGE +bool isSingleton(AbstractView *view, bool isAlias, QStringView newTarget) +{ + using Storage::Info::ExportedTypeName; + + auto model = view->model(); + + if (!model) + return false; + + const auto sourceId = model->fileUrlSourceId(); + const Utils::SmallString name = newTarget; + const Utils::SmallString aliasName = newTarget.split(u'.').front(); + auto hasTargetExportedTypeName = [&](const auto &metaInfo) { + const auto exportedTypeNames = metaInfo.exportedTypeNamesForSourceId(sourceId); + if (std::ranges::find(exportedTypeNames, name, &ExportedTypeName::name) + != exportedTypeNames.end()) + return true; + if (isAlias) { + if (std::ranges::find(exportedTypeNames, aliasName, &ExportedTypeName::name) + != exportedTypeNames.end()) + return true; + } + return false; + }; + + auto singletonMetaInfos = model->singletonMetaInfos(); + return std::ranges::find_if(singletonMetaInfos, hasTargetExportedTypeName) + != singletonMetaInfos.end(); +} +#else +bool isSingleton(AbstractView *view, bool isAlias, const QString &newTarget) +{ + if (RewriterView *rv = view->rewriterView()) { + for (const QmlTypeData &data : rv->getQMLTypes()) { + if (!data.typeName.isEmpty()) { + if (data.typeName == newTarget) { + if (view->model()->metaInfo(data.typeName.toUtf8()).isValid()) + return true; + + } else if (isAlias) { + if (data.typeName == newTarget.split(".").constFirst()) { + if (view->model()->metaInfo(data.typeName.toUtf8()).isValid()) + return true; + } + } + } + } + } + + return false; +} +#endif +} // namespace + void ConnectionModel::updateTargetNode(int rowNumber) { SignalHandlerProperty signalHandlerProperty = signalHandlerPropertyForRow(rowNumber); @@ -213,27 +269,7 @@ void ConnectionModel::updateTargetNode(int rowNumber) ModelNode connectionNode = signalHandlerProperty.parentModelNode(); const bool isAlias = newTarget.contains("."); - bool isSingleton = false; - - if (RewriterView* rv = connectionView()->rewriterView()) { - for (const QmlTypeData &data : rv->getQMLTypes()) { - if (!data.typeName.isEmpty()) { - if (data.typeName == newTarget) { - if (connectionView()->model()->metaInfo(data.typeName.toUtf8()).isValid()) { - isSingleton = true; - break; - } - } else if (isAlias) { - if (data.typeName == newTarget.split(".").constFirst()) { - if (connectionView()->model()->metaInfo(data.typeName.toUtf8()).isValid()) { - isSingleton = true; - break; - } - } - } - } - } - } + bool isSingleton = QmlDesigner::isSingleton(m_connectionView, isAlias, newTarget); if (!newTarget.isEmpty()) { //if it's a singleton, then let's reparent connections to rootNode, @@ -595,78 +631,96 @@ QStringList ConnectionModel::getflowActionTriggerForRow(int row) const return stringList; } +namespace {} + QStringList ConnectionModel::getPossibleSignalsForConnection(const ModelNode &connection) const { + if (!connection) + return {}; + QStringList stringList; - auto getAliasMetaSignals = [&](QString aliasPart, NodeMetaInfo metaInfo) { - if (metaInfo.isValid() && metaInfo.hasProperty(aliasPart.toUtf8())) { - NodeMetaInfo propertyMetaInfo = metaInfo.property(aliasPart.toUtf8()).propertyType(); - if (propertyMetaInfo.isValid()) { - return propertyNameListToStringList(propertyMetaInfo.signalNames()); - } - } - return QStringList(); + auto getAliasMetaSignals = [&](PropertyNameView aliasPart, NodeMetaInfo metaInfo) -> QStringList { + if (NodeMetaInfo propertyMetaInfo = metaInfo.property(aliasPart).propertyType()) + return propertyNameListToStringList(propertyMetaInfo.signalNames()); + + return {}; }; - if (connection.isValid()) { - //separate check for singletons - if (connection.hasBindingProperty("target")) { - const BindingProperty bp = connection.bindingProperty("target"); + //separate check for singletons + if (const BindingProperty bp = connection.bindingProperty("target")) { +#ifdef QDS_USE_PROJECTSTORAGE + if (auto model = m_connectionView->model()) { + const Utils::SmallString bindExpression = bp.expression(); + using Storage::Info::ExportedTypeName; + const auto sourceId = model->fileUrlSourceId(); + for (const auto &metaInfo : model->singletonMetaInfos()) { + const auto exportedTypeNames = metaInfo.exportedTypeNamesForSourceId(sourceId); + if (std::ranges::find(exportedTypeNames, bindExpression, &ExportedTypeName::name) + != exportedTypeNames.end()) { + stringList.append(propertyNameListToStringList(metaInfo.signalNames())); + } else { + std::string_view expression = bindExpression; + auto index = expression.find('.'); + if (index == std::string_view::npos) + continue; - if (bp.isValid()) { - const QString bindExpression = bp.expression(); + expression.remove_prefix(index); - if (const RewriterView * const rv = connectionView()->rewriterView()) { - for (const QmlTypeData &data : rv->getQMLTypes()) { - if (!data.typeName.isEmpty()) { - if (data.typeName == bindExpression) { - NodeMetaInfo metaInfo = connectionView()->model()->metaInfo(data.typeName.toUtf8()); - if (metaInfo.isValid()) { - stringList << propertyNameListToStringList(metaInfo.signalNames()); - break; - } - } else if (bindExpression.contains(".")) { - //if it doesn't fit the same name, maybe it's an alias? - QStringList expression = bindExpression.split("."); - if ((expression.size() > 1) && (expression.constFirst() == data.typeName)) { - expression.removeFirst(); + stringList.append(getAliasMetaSignals(expression, metaInfo)); + } + } + } +#else + const QString bindExpression = bp.expression(); - stringList << getAliasMetaSignals( - expression.join("."), - connectionView()->model()->metaInfo(data.typeName.toUtf8())); - break; - } - } + if (const RewriterView *const rv = connectionView()->rewriterView()) { + for (const QmlTypeData &data : rv->getQMLTypes()) { + if (!data.typeName.isEmpty()) { + if (data.typeName == bindExpression) { + NodeMetaInfo metaInfo = connectionView()->model()->metaInfo( + data.typeName.toUtf8()); + if (metaInfo.isValid()) { + stringList << propertyNameListToStringList(metaInfo.signalNames()); + break; + } + } else if (bindExpression.contains(".")) { + //if it doesn't fit the same name, maybe it's an alias? + QStringList expression = bindExpression.split("."); + if ((expression.size() > 1) && (expression.constFirst() == data.typeName)) { + expression.removeFirst(); + + stringList << getAliasMetaSignals(expression.join(".").toUtf8(), + connectionView()->model()->metaInfo( + data.typeName.toUtf8())); + break; } } } } } +#endif + std::ranges::sort(stringList); + stringList.erase(std::ranges::unique(stringList).begin(), stringList.end()); + } - ModelNode targetNode = getTargetNodeForConnection(connection); - if (targetNode.isValid() && targetNode.metaInfo().isValid()) { - stringList.append(propertyNameListToStringList(targetNode.metaInfo().signalNames())); - } else { - //most likely it's component's internal alias: + ModelNode targetNode = getTargetNodeForConnection(connection); + if (auto metaInfo = targetNode.metaInfo()) { + stringList.append(propertyNameListToStringList(metaInfo.signalNames())); + } else { + //most likely it's component's internal alias: - if (connection.hasBindingProperty("target")) { - const BindingProperty bp = connection.bindingProperty("target"); - - if (bp.isValid()) { - QStringList expression = bp.expression().split("."); - if (expression.size() > 1) { - const QString itemId = expression.constFirst(); - if (connectionView()->hasId(itemId)) { - ModelNode parentItem = connectionView()->modelNodeForId(itemId); - if (parentItem.isValid() - && parentItem.hasMetaInfo() - && parentItem.metaInfo().isValid()) { - expression.removeFirst(); - stringList << getAliasMetaSignals(expression.join("."), - parentItem.metaInfo()); - } - } + if (const BindingProperty bp = connection.bindingProperty("target")) { + QStringList expression = bp.expression().split("."); + if (expression.size() > 1) { + const QString itemId = expression.constFirst(); + if (connectionView()->hasId(itemId)) { + ModelNode parentItem = connectionView()->modelNodeForId(itemId); + if (parentItem.isValid() && parentItem.hasMetaInfo() + && parentItem.metaInfo().isValid()) { + expression.removeFirst(); + stringList << getAliasMetaSignals(expression.join(".").toUtf8(), + parentItem.metaInfo()); } } } diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectionview.cpp b/src/plugins/qmldesigner/components/connectioneditor/connectionview.cpp index 8f0c9ebe62e..47d70395ba7 100644 --- a/src/plugins/qmldesigner/components/connectioneditor/connectionview.cpp +++ b/src/plugins/qmldesigner/components/connectioneditor/connectionview.cpp @@ -3,7 +3,6 @@ #include "connectionview.h" -#include "backendmodel.h" #include "bindingmodel.h" #include "connectionmodel.h" #include "dynamicpropertiesmodel.h" @@ -146,7 +145,6 @@ struct ConnectionView::ConnectionViewData : connectionModel{view} , bindingModel{view} , dynamicPropertiesModel{false, view} - , backendModel{view} , propertyTreeModel{view} , connectionViewQuickWidget{Utils::makeUniqueObjectPtr( view, &connectionModel, &bindingModel, &dynamicPropertiesModel)} @@ -155,7 +153,6 @@ struct ConnectionView::ConnectionViewData ConnectionModel connectionModel; BindingModel bindingModel; DynamicPropertiesModel dynamicPropertiesModel; - BackendModel backendModel; PropertyTreeModel propertyTreeModel; int currentIndex = 0; @@ -177,7 +174,6 @@ void ConnectionView::modelAttached(Model *model) d->bindingModel.reset(); d->dynamicPropertiesModel.reset(); d->connectionModel.resetModel(); - d->backendModel.resetModel(); } void ConnectionView::modelAboutToBeDetached(Model *model) @@ -249,8 +245,6 @@ void ConnectionView::variantPropertiesChanged(const QList &prop for (const VariantProperty &variantProperty : propertyList) { if (variantProperty.isDynamic()) d->dynamicPropertiesModel.updateItem(variantProperty); - if (variantProperty.isDynamic() && variantProperty.parentModelNode().isRootNode()) - d->backendModel.resetModel(); d->connectionModel.variantPropertyChanged(variantProperty); @@ -265,8 +259,6 @@ void ConnectionView::bindingPropertiesChanged(const QList &prop d->bindingModel.updateItem(bindingProperty); if (bindingProperty.isDynamic()) d->dynamicPropertiesModel.updateItem(bindingProperty); - if (bindingProperty.isDynamic() && bindingProperty.parentModelNode().isRootNode()) - d->backendModel.resetModel(); d->connectionModel.bindingPropertyChanged(bindingProperty); @@ -288,11 +280,6 @@ void ConnectionView::selectedNodesChanged(const QList & selectedNodeL d->dynamicPropertiesModel.reset(); } -void ConnectionView::importsChanged(const Imports & /*addedImports*/, const Imports & /*removedImports*/) -{ - d->backendModel.resetModel(); -} - void ConnectionView::currentStateChanged(const ModelNode &) { d->dynamicPropertiesModel.reset(); @@ -332,11 +319,6 @@ DynamicPropertiesModel *ConnectionView::dynamicPropertiesModel() const return &d->dynamicPropertiesModel; } -BackendModel *ConnectionView::backendModel() const -{ - return &d->backendModel; -} - int ConnectionView::currentIndex() const { return d->currentIndex; diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectionview.h b/src/plugins/qmldesigner/components/connectioneditor/connectionview.h index 1cf3aa26dd1..debf78ae2e7 100644 --- a/src/plugins/qmldesigner/components/connectioneditor/connectionview.h +++ b/src/plugins/qmldesigner/components/connectioneditor/connectionview.h @@ -21,7 +21,6 @@ class ConnectionViewWidget; class BindingModel; class ConnectionModel; class DynamicPropertiesModel; -class BackendModel; class ConnectionViewQuickWidget; class PropertyTreeModel; class PropertyListProxyModel; @@ -55,8 +54,6 @@ public: void selectedNodesChanged(const QList &selectedNodeList, const QList &lastSelectedNodeList) override; - void importsChanged(const Imports &addedImports, const Imports &removedImports) override; - void currentStateChanged(const ModelNode &node) override; WidgetInfo widgetInfo() override; @@ -67,7 +64,6 @@ public: ConnectionModel *connectionModel() const; BindingModel *bindingModel() const; - BackendModel *backendModel() const; int currentIndex() const; void setCurrentIndex(int i); diff --git a/src/plugins/qmldesigner/instances/nodeinstanceview.cpp b/src/plugins/qmldesigner/instances/nodeinstanceview.cpp index 60802c95aa3..cb2f5b3420d 100644 --- a/src/plugins/qmldesigner/instances/nodeinstanceview.cpp +++ b/src/plugins/qmldesigner/instances/nodeinstanceview.cpp @@ -1208,6 +1208,7 @@ CreateSceneCommand NodeInstanceView::createCreateSceneCommand() QVector mockupTypesVector; +#ifndef QDS_USE_PROJECTSTORAGE for (const QmlTypeData &cppTypeData : model()->rewriterView()->getQMLTypes()) { const QString versionString = cppTypeData.versionString; int majorVersion = -1; @@ -1242,6 +1243,7 @@ CreateSceneCommand NodeInstanceView::createCreateSceneCommand() mockupTypesVector.append(mockupType); } } +#endif QString lastUsedLanguage; if (auto multiLanguageAspect = QmlProjectManager::QmlMultiLanguageAspect::current(m_currentTarget)) diff --git a/src/plugins/qmldesigner/libs/designercore/include/nodemetainfo.h b/src/plugins/qmldesigner/libs/designercore/include/nodemetainfo.h index 149adfc37e9..fdb29cb10f3 100644 --- a/src/plugins/qmldesigner/libs/designercore/include/nodemetainfo.h +++ b/src/plugins/qmldesigner/libs/designercore/include/nodemetainfo.h @@ -117,7 +117,7 @@ public: bool defaultPropertyIsComponent() const; - TypeName displayName() const; + QString displayName() const; DEPRECATED_TYPENAME TypeName typeName() const; DEPRECATED_TYPENAME TypeName simplifiedTypeName() const; DEPRECATED_VERSION_NUMBER int majorVersion() const; diff --git a/src/plugins/qmldesigner/libs/designercore/include/rewriterview.h b/src/plugins/qmldesigner/libs/designercore/include/rewriterview.h index 81c2a057380..1fdb6837238 100644 --- a/src/plugins/qmldesigner/libs/designercore/include/rewriterview.h +++ b/src/plugins/qmldesigner/libs/designercore/include/rewriterview.h @@ -143,7 +143,9 @@ public: QStringList autoComplete(const QString &text, int pos, bool explicitComplete = true); +#ifndef QDS_USE_PROJECTSTORAGE QList getQMLTypes() const; +#endif void setWidgetStatusCallback(std::function setWidgetStatusCallback); diff --git a/src/plugins/qmldesigner/libs/designercore/metainfo/nodemetainfo.cpp b/src/plugins/qmldesigner/libs/designercore/metainfo/nodemetainfo.cpp index d276f555337..e340bc2c357 100644 --- a/src/plugins/qmldesigner/libs/designercore/metainfo/nodemetainfo.cpp +++ b/src/plugins/qmldesigner/libs/designercore/metainfo/nodemetainfo.cpp @@ -2106,7 +2106,7 @@ bool NodeMetaInfo::defaultPropertyIsComponent() const } } -TypeName NodeMetaInfo::displayName() const +QString NodeMetaInfo::displayName() const { return {}; } diff --git a/src/plugins/qmldesigner/libs/designercore/rewriter/rewriterview.cpp b/src/plugins/qmldesigner/libs/designercore/rewriter/rewriterview.cpp index b79ddcbe087..dd55bd2ef67 100644 --- a/src/plugins/qmldesigner/libs/designercore/rewriter/rewriterview.cpp +++ b/src/plugins/qmldesigner/libs/designercore/rewriter/rewriterview.cpp @@ -1102,6 +1102,7 @@ QStringList RewriterView::autoComplete(const QString &text, int pos, bool explic return list; } +#ifndef QDS_USE_PROJECTSTORAGE QList RewriterView::getQMLTypes() const { QList qmlDataList; @@ -1127,6 +1128,7 @@ QList RewriterView::getQMLTypes() const return qmlDataList; } +#endif void RewriterView::setWidgetStatusCallback(std::function setWidgetStatusCallback) {