aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/qmldesigner
diff options
context:
space:
mode:
authorMarco Bubke <marco.bubke@qt.io>2023-08-23 23:45:52 +0200
committerMarco Bubke <marco.bubke@qt.io>2023-10-02 20:22:10 +0000
commit1177bb4b1f3f913006d5ff0f2f05dfef2dc3a1de (patch)
tree64eea90c2a96037a9c13d3094d653397ebb1173f /src/plugins/qmldesigner
parent3a0eff9e7959c53a0d068497ce645df387dab93b (diff)
QmlDesigner: Add PropertyComponentGenerator
Task-number: QDS-10578 Change-Id: I2c20f5aaa6ebfe7736012a02d4c4596589007866 Reviewed-by: Qt CI Patch Build Bot <ci_patchbuild_bot@qt.io> Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io> Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Diffstat (limited to 'src/plugins/qmldesigner')
-rw-r--r--src/plugins/qmldesigner/CMakeLists.txt1
-rw-r--r--src/plugins/qmldesigner/components/componentcore/propertycomponentgenerator.cpp272
-rw-r--r--src/plugins/qmldesigner/components/componentcore/propertycomponentgenerator.h53
-rw-r--r--src/plugins/qmldesigner/components/componentcore/propertycomponentgeneratorinterface.h46
-rw-r--r--src/plugins/qmldesigner/components/componentcore/propertyeditorcomponentgenerator.cpp177
-rw-r--r--src/plugins/qmldesigner/components/componentcore/propertyeditorcomponentgenerator.h29
-rw-r--r--src/plugins/qmldesigner/designercore/include/model.h6
-rw-r--r--src/plugins/qmldesigner/designercore/include/module.h35
-rw-r--r--src/plugins/qmldesigner/designercore/model/model.cpp19
9 files changed, 638 insertions, 0 deletions
diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt
index 8ea79bcdcf8..6df5a632472 100644
--- a/src/plugins/qmldesigner/CMakeLists.txt
+++ b/src/plugins/qmldesigner/CMakeLists.txt
@@ -238,6 +238,7 @@ extend_qtc_library(QmlDesignerCore
modelmerger.h
modelnode.h
modelnodepositionstorage.h
+ module.h
nodeabstractproperty.h
nodeinstance.h
nodelistproperty.h
diff --git a/src/plugins/qmldesigner/components/componentcore/propertycomponentgenerator.cpp b/src/plugins/qmldesigner/components/componentcore/propertycomponentgenerator.cpp
new file mode 100644
index 00000000000..7e5487909a8
--- /dev/null
+++ b/src/plugins/qmldesigner/components/componentcore/propertycomponentgenerator.cpp
@@ -0,0 +1,272 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "propertycomponentgenerator.h"
+
+#include <utils/algorithm.h>
+#include <utils/environment.h>
+
+#include <model.h>
+
+#include <QFile>
+#include <QString>
+
+#include <memory>
+
+using namespace Qt::StringLiterals;
+
+namespace QmlDesigner {
+
+namespace {
+
+QmlJS::SimpleReaderNode::Ptr createTemplateConfiguration(const QString &propertyEditorResourcesPath)
+{
+ QmlJS::SimpleReader reader;
+ const QString fileName = propertyEditorResourcesPath + u"/PropertyTemplates/TemplateTypes.qml";
+ auto templateConfiguration = reader.readFile(fileName);
+
+ if (!templateConfiguration)
+ qWarning().nospace() << "template definitions:" << reader.errors();
+
+ return templateConfiguration;
+}
+
+template<typename Type>
+Type getProperty(const QmlJS::SimpleReaderNode *node, const QString &name)
+{
+ if (auto property = node->property(name)) {
+ const auto &value = property.value;
+ if (value.type() == QVariant::List) {
+ auto list = value.toList();
+ if (list.size())
+ return list.front().value<Type>();
+ } else {
+ return property.value.value<Type>();
+ }
+ }
+
+ return {};
+}
+
+QString getContent(const QString &path)
+{
+ QFile file{path};
+
+ if (file.open(QIODevice::ReadOnly))
+ return QString::fromUtf8(file.readAll());
+
+ return {};
+}
+
+QString generateComponentText(Utils::SmallStringView propertyName,
+ QStringView source,
+ Utils::SmallStringView typeName,
+ bool needsTypeArg)
+{
+ QString underscoreName{propertyName};
+ underscoreName.replace('.', '_');
+ if (needsTypeArg)
+ return source.arg(QString{propertyName}, underscoreName, QString{typeName});
+
+ return source.arg(QString{propertyName}, underscoreName);
+}
+
+PropertyComponentGenerator::Property generate(const PropertyMetaInfo &property,
+ const PropertyComponentGenerator::Entry &entry)
+{
+ auto propertyName = property.name();
+ auto component = generateComponentText(propertyName,
+ entry.propertyTemplate,
+ entry.typeName,
+ entry.needsTypeArg);
+
+ if (entry.separateSection)
+ return PropertyComponentGenerator::ComplexProperty{propertyName, component};
+
+ return PropertyComponentGenerator::BasicProperty{propertyName, component};
+}
+
+auto getRandomExportedName(const NodeMetaInfo &metaInfo)
+{
+ const auto &names = metaInfo.allExportedTypeNames();
+
+ using Result = decltype(names.front().name);
+
+ if (!names.empty())
+ return names.front().name;
+
+ return Result{};
+}
+
+} // namespace
+
+QString PropertyComponentGenerator::generateSubComponentText(Utils::SmallStringView propertyBaseName,
+ const PropertyMetaInfo &subProperty) const
+{
+ auto propertyType = subProperty.propertyType();
+ if (auto entry = findEntry(propertyType)) {
+ auto propertyName = Utils::SmallString::join({propertyBaseName, subProperty.name()});
+ return generateComponentText(propertyName,
+ entry->propertyTemplate,
+ entry->typeName,
+ entry->needsTypeArg);
+ }
+
+ return {};
+}
+
+QString PropertyComponentGenerator::generateComplexComponentText(Utils::SmallStringView propertyName,
+ const NodeMetaInfo &propertyType) const
+{
+ auto subProperties = propertyType.properties();
+
+ if (std::empty(subProperties))
+ return {};
+
+ auto propertyTypeName = getRandomExportedName(propertyType);
+ static QString templateText = QStringLiteral(
+ R"xy(
+ Section {
+ caption: %1 - %2
+ anchors.left: parent.left
+ anchors.right: parent.right
+ leftPadding: 8
+ rightPadding: 0
+ expanded: false
+ level: 1
+ SectionLayout {
+ )xy");
+
+ auto component = templateText.arg(QString{propertyName}, QString{propertyTypeName});
+
+ auto propertyBaseName = Utils::SmallString::join({propertyName, "."});
+
+ bool subPropertiesHaveContent = false;
+ for (const auto &subProperty : propertyType.properties()) {
+ auto subPropertyContent = generateSubComponentText(propertyBaseName, subProperty);
+ subPropertiesHaveContent = subPropertiesHaveContent || subPropertyContent.size();
+ component += subPropertyContent;
+ }
+
+ component += "}\n}\n"_L1;
+
+ if (subPropertiesHaveContent)
+ return component;
+
+ return {};
+}
+
+PropertyComponentGenerator::Property PropertyComponentGenerator::generateComplexComponent(
+ const PropertyMetaInfo &property, const NodeMetaInfo &propertyType) const
+{
+ auto propertyName = property.name();
+ auto component = generateComplexComponentText(propertyName, propertyType);
+
+ if (component.isEmpty())
+ return {};
+
+ return ComplexProperty{propertyName, component};
+}
+
+namespace {
+
+std::optional<PropertyComponentGenerator::Entry> createEntry(QmlJS::SimpleReaderNode *node,
+ Model *model,
+ const QString &templatesPath)
+{
+ auto moduleName = getProperty<QByteArray>(node, "module");
+ if (moduleName.isEmpty())
+ return {};
+
+ auto module = model->module(moduleName);
+
+ auto typeName = getProperty<QByteArray>(node, "typeNames");
+
+ auto type = model->metaInfo(module, typeName);
+ if (!type)
+ return {};
+
+ auto path = getProperty<QString>(node, "sourceFile");
+ if (path.isEmpty())
+ return {};
+
+ auto content = getContent(templatesPath + path);
+ if (content.isEmpty())
+ return {};
+
+ bool needsTypeArg = getProperty<bool>(node, "needsTypeArg");
+
+ bool separateSection = getProperty<bool>(node, "separateSection");
+
+ return PropertyComponentGenerator::Entry{std::move(type),
+ std::move(typeName),
+ std::move(content),
+ separateSection,
+ needsTypeArg};
+}
+
+PropertyComponentGenerator::Entries createEntries(QmlJS::SimpleReaderNode::Ptr templateConfiguration,
+ Model *model,
+ const QString &templatesPath)
+{
+ PropertyComponentGenerator::Entries entries;
+ entries.reserve(32);
+
+ const auto &nodes = templateConfiguration->children();
+ for (const QmlJS::SimpleReaderNode::Ptr &node : nodes) {
+ if (auto entry = createEntry(node.get(), model, templatesPath))
+ entries.push_back(*entry);
+ }
+
+ return entries;
+}
+
+QStringList createImports(QmlJS::SimpleReaderNode::Ptr templateConfiguration)
+{
+ auto property = templateConfiguration->property("imports");
+ return Utils::transform<QStringList>(property.value.toList(),
+ [](const auto &entry) { return entry.toString(); });
+}
+
+} // namespace
+
+PropertyComponentGenerator::PropertyComponentGenerator(const QString &propertyEditorResourcesPath,
+ Model *model)
+ : m_entries(createEntries(createTemplateConfiguration(propertyEditorResourcesPath),
+ model,
+ propertyEditorResourcesPath + "/PropertyTemplates/"))
+{
+ auto templateConfiguration = createTemplateConfiguration(propertyEditorResourcesPath);
+
+ m_entries = createEntries(templateConfiguration,
+ model,
+ propertyEditorResourcesPath + "/PropertyTemplates/");
+
+ m_imports = createImports(templateConfiguration);
+}
+
+PropertyComponentGenerator::Property PropertyComponentGenerator::create(const PropertyMetaInfo &property) const
+{
+ auto propertyType = property.propertyType();
+ if (auto entry = findEntry(propertyType))
+ return generate(property, *entry);
+
+ if (property.isWritable() && property.isPointer())
+ return {};
+
+ return generateComplexComponent(property, propertyType);
+}
+
+const PropertyComponentGenerator::Entry *PropertyComponentGenerator::findEntry(const NodeMetaInfo &type) const
+{
+ auto found = std::find_if(m_entries.begin(), m_entries.end(), [&](const auto &entry) {
+ return entry.type == type;
+ });
+
+ if (found != m_entries.end())
+ return std::addressof(*found);
+
+ return nullptr;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/componentcore/propertycomponentgenerator.h b/src/plugins/qmldesigner/components/componentcore/propertycomponentgenerator.h
new file mode 100644
index 00000000000..67239c16a70
--- /dev/null
+++ b/src/plugins/qmldesigner/components/componentcore/propertycomponentgenerator.h
@@ -0,0 +1,53 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#pragma once
+
+#include "propertycomponentgeneratorinterface.h"
+
+#include <modelfwd.h>
+#include <nodemetainfo.h>
+
+#include <qmljs/qmljssimplereader.h>
+
+#include <optional>
+#include <variant>
+#include <vector>
+
+namespace QmlDesigner {
+
+class PropertyComponentGenerator final : public PropertyComponentGeneratorInterface
+{
+public:
+ PropertyComponentGenerator(const QString &propertyEditorResourcesPath, Model *model);
+
+ Property create(const PropertyMetaInfo &property) const override;
+
+ struct Entry
+ {
+ NodeMetaInfo type;
+ Utils::SmallString typeName;
+ QString propertyTemplate;
+ bool separateSection = false;
+ bool needsTypeArg = false;
+ };
+
+ using Entries = std::vector<Entry>;
+
+ QStringList imports() const override { return m_imports; }
+
+private:
+ const Entry *findEntry(const NodeMetaInfo &type) const;
+ QString generateSubComponentText(Utils::SmallStringView propertyBaseName,
+ const PropertyMetaInfo &subProperty) const;
+ QString generateComplexComponentText(Utils::SmallStringView propertyName,
+ const NodeMetaInfo &propertyType) const;
+ Property generateComplexComponent(const PropertyMetaInfo &property,
+ const NodeMetaInfo &propertyType) const;
+
+private:
+ Entries m_entries;
+ QStringList m_imports;
+};
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/componentcore/propertycomponentgeneratorinterface.h b/src/plugins/qmldesigner/components/componentcore/propertycomponentgeneratorinterface.h
new file mode 100644
index 00000000000..ab4047c957b
--- /dev/null
+++ b/src/plugins/qmldesigner/components/componentcore/propertycomponentgeneratorinterface.h
@@ -0,0 +1,46 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#pragma once
+
+#include <modelfwd.h>
+#include <nodemetainfo.h>
+
+#include <qmljs/qmljssimplereader.h>
+
+#include <optional>
+#include <variant>
+#include <vector>
+
+namespace QmlDesigner {
+
+class PropertyComponentGeneratorInterface
+{
+public:
+ PropertyComponentGeneratorInterface() = default;
+ PropertyComponentGeneratorInterface(const PropertyComponentGeneratorInterface &) = delete;
+ PropertyComponentGeneratorInterface &operator=(const PropertyComponentGeneratorInterface &) = delete;
+
+ struct BasicProperty
+ {
+ Utils::SmallString propertyName;
+ QString component;
+ };
+
+ struct ComplexProperty
+ {
+ Utils::SmallString propertyName;
+ QString component;
+ };
+
+ using Property = std::variant<std::monostate, BasicProperty, ComplexProperty>;
+
+ virtual Property create(const PropertyMetaInfo &property) const = 0;
+
+ virtual QStringList imports() const = 0;
+
+protected:
+ ~PropertyComponentGeneratorInterface() = default;
+};
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/componentcore/propertyeditorcomponentgenerator.cpp b/src/plugins/qmldesigner/components/componentcore/propertyeditorcomponentgenerator.cpp
new file mode 100644
index 00000000000..272130b8f33
--- /dev/null
+++ b/src/plugins/qmldesigner/components/componentcore/propertyeditorcomponentgenerator.cpp
@@ -0,0 +1,177 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "propertyeditorcomponentgenerator.h"
+
+#include <utils/environment.h>
+#include <utils/span.h>
+
+#include <modelnode.h>
+
+namespace QmlDesigner {
+
+namespace {
+
+using GeneratorProperty = PropertyComponentGeneratorInterface::Property;
+using BasicProperty = PropertyComponentGeneratorInterface::BasicProperty;
+using ComplexProperty = PropertyComponentGeneratorInterface::ComplexProperty;
+using GeneratorProperties = std::vector<GeneratorProperty>;
+
+QString createImports(const QStringList &imports)
+{
+ QString importsContent;
+ importsContent.reserve(512);
+
+ for (const QString &import : imports) {
+ importsContent += import;
+ importsContent += '\n';
+ }
+
+ return importsContent;
+}
+
+QString componentButton(bool isComponent)
+{
+ if (isComponent)
+ return "ComponentButton {}";
+
+ return {};
+}
+
+void createBasicPropertySections(QString &components,
+ Utils::span<GeneratorProperty> generatorProperties)
+{
+ components += R"xy(
+ Column {
+ width: parent.width
+ leftPadding: 8
+ bottomPadding: 10
+ SectionLayout {)xy";
+
+ for (const auto &generatorProperty : generatorProperties)
+ components += std::get_if<BasicProperty>(&generatorProperty)->component;
+
+ components += R"xy(
+ }
+ })xy";
+}
+
+void createComplexPropertySections(QString &components,
+ Utils::span<GeneratorProperty> generatorProperties)
+{
+ for (const auto &generatorProperty : generatorProperties)
+ components += std::get_if<ComplexProperty>(&generatorProperty)->component;
+}
+
+Utils::SmallStringView propertyName(const GeneratorProperty &property)
+{
+ return std::visit(
+ [](const auto &p) -> Utils::SmallStringView {
+ if constexpr (!std::is_same_v<std::decay_t<decltype(p)>, std::monostate>)
+ return p.propertyName;
+ else
+ return {};
+ },
+ property);
+}
+
+PropertyMetaInfos getUnmangedProperties(const NodeMetaInfo &nodeInfo)
+{
+ PropertyMetaInfos properties;
+ properties.reserve(128);
+
+ auto prototypes = nodeInfo.selfAndPrototypes();
+
+ for (const auto &prototype : prototypes) {
+ if (prototype.propertyEditorPathId())
+ break;
+
+ auto localProperties = prototype.localProperties();
+
+ properties.insert(properties.end(), localProperties.begin(), localProperties.end());
+ }
+
+ return properties;
+}
+
+GeneratorProperties createSortedGeneratorProperties(
+ const PropertyMetaInfos &properties, const PropertyComponentGeneratorType &propertyGenerator)
+{
+ GeneratorProperties generatorProperties;
+ generatorProperties.reserve(properties.size());
+
+ for (const auto &property : properties) {
+ auto generatedProperty = propertyGenerator.create(property);
+ if (!std::holds_alternative<std::monostate>(generatedProperty))
+ generatorProperties.push_back(std::move(generatedProperty));
+ }
+ std::sort(generatorProperties.begin(),
+ generatorProperties.end(),
+ [](const auto &first, const auto &second) {
+ // this is sensitive to the order of the variant types but the test should catch any error
+ return std::forward_as_tuple(first.index(), propertyName(first))
+ < std::forward_as_tuple(second.index(), propertyName(second));
+ });
+
+ return generatorProperties;
+}
+
+QString createPropertySections(const PropertyComponentGeneratorType &propertyGenerator,
+ const NodeMetaInfo &nodeInfo)
+{
+ QString propertyComponents;
+ propertyComponents.reserve(100000);
+
+ auto generatorProperties = createSortedGeneratorProperties(getUnmangedProperties(nodeInfo),
+ propertyGenerator);
+
+ const auto begin = generatorProperties.begin();
+ const auto end = generatorProperties.end();
+
+ auto point = std::partition_point(begin, end, [](const auto &p) {
+ return !std::holds_alternative<ComplexProperty>(p);
+ });
+
+ if (begin != point)
+ createBasicPropertySections(propertyComponents, Utils::span<GeneratorProperty>{begin, point});
+
+ if (point != end)
+ createComplexPropertySections(propertyComponents, Utils::span<GeneratorProperty>{point, end});
+
+ return propertyComponents;
+}
+
+} // namespace
+
+PropertyEditorTemplateGenerator::PropertyEditorTemplateGenerator(
+ const PropertyComponentGeneratorType &propertyGenerator)
+ : m_propertyGenerator{propertyGenerator}
+{}
+
+QString PropertyEditorTemplateGenerator::create(const NodeMetaInfo &nodeInfo, bool isComponent)
+{
+ return QString{R"xy(
+ %1
+ Column {
+ width: parent.width
+ %2
+ Section {
+ caption: "%3"
+ anchors.left: parent.left
+ anchors.right: parent.right
+ leftPadding: 0
+ rightPadding: 0
+ bottomPadding: 0
+ Column {
+ width: parent.width
+ %4
+ }
+ }
+ })xy"}
+ .arg(createImports(m_propertyGenerator.imports()),
+ componentButton(isComponent),
+ QObject::tr("Exposed Custom Properties"),
+ createPropertySections(m_propertyGenerator, nodeInfo));
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/componentcore/propertyeditorcomponentgenerator.h b/src/plugins/qmldesigner/components/componentcore/propertyeditorcomponentgenerator.h
new file mode 100644
index 00000000000..37dd824d43f
--- /dev/null
+++ b/src/plugins/qmldesigner/components/componentcore/propertyeditorcomponentgenerator.h
@@ -0,0 +1,29 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#pragma once
+
+#include "propertycomponentgenerator.h"
+
+#include <nodemetainfo.h>
+
+namespace QmlDesigner {
+
+#ifdef UNIT_TESTS
+using PropertyComponentGeneratorType = PropertyComponentGeneratorInterface;
+#else
+using PropertyComponentGeneratorType = PropertyComponentGenerator;
+#endif
+class PropertyEditorTemplateGenerator
+{
+
+public:
+ PropertyEditorTemplateGenerator(const PropertyComponentGeneratorType &propertyGenerator);
+
+ QString create(const NodeMetaInfo &nodeInfo, bool isComponent);
+
+private:
+ const PropertyComponentGeneratorType &m_propertyGenerator;
+};
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/include/model.h b/src/plugins/qmldesigner/designercore/include/model.h
index c404525a9c0..ac8182c0760 100644
--- a/src/plugins/qmldesigner/designercore/include/model.h
+++ b/src/plugins/qmldesigner/designercore/include/model.h
@@ -7,7 +7,9 @@
#include <documentmessage.h>
#include <model/modelresourcemanagementinterface.h>
+#include <module.h>
#include <projectstorage/projectstoragefwd.h>
+#include <projectstorage/projectstorageinfotypes.h>
#include <projectstorageids.h>
#include <QMimeData>
@@ -125,7 +127,11 @@ public:
const MetaInfo metaInfo() const;
MetaInfo metaInfo();
+ Module module(Utils::SmallStringView moduleName);
NodeMetaInfo metaInfo(const TypeName &typeName, int majorVersion = -1, int minorVersion = -1) const;
+ NodeMetaInfo metaInfo(Module module,
+ Utils::SmallStringView typeName,
+ Storage::Version version = Storage::Version{}) const;
bool hasNodeMetaInfo(const TypeName &typeName, int majorVersion = -1, int minorVersion = -1) const;
void setMetaInfo(const MetaInfo &metaInfo);
diff --git a/src/plugins/qmldesigner/designercore/include/module.h b/src/plugins/qmldesigner/designercore/include/module.h
new file mode 100644
index 00000000000..5078f3ff8f5
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/include/module.h
@@ -0,0 +1,35 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#pragma once
+
+#include <modelfwd.h>
+#include <projectstorageids.h>
+
+namespace QmlDesigner {
+
+class Module
+{
+public:
+ Module() = default;
+
+ Module(ModuleId moduleId, NotNullPointer<const ProjectStorageType> projectStorage)
+ : m_projectStorage{projectStorage}
+ , m_id{moduleId}
+ {}
+
+ ModuleId id() const { return m_id; }
+
+ bool isValid() const { return bool(m_id); }
+
+ explicit operator bool() const { return isValid(); }
+
+ const ProjectStorageType &projectStorage() const { return *m_projectStorage; }
+
+ friend bool operator==(Module first, Module second) { return first.m_id == second.m_id; }
+
+private:
+ NotNullPointer<const ProjectStorageType> m_projectStorage = {};
+ ModuleId m_id;
+};
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/model/model.cpp b/src/plugins/qmldesigner/designercore/model/model.cpp
index 74afaaad86d..c0393d524c1 100644
--- a/src/plugins/qmldesigner/designercore/model/model.cpp
+++ b/src/plugins/qmldesigner/designercore/model/model.cpp
@@ -2436,6 +2436,16 @@ NodeMetaInfo Model::metaInfo(const TypeName &typeName, int majorVersion, int min
}
}
+NodeMetaInfo Model::metaInfo(Module module, Utils::SmallStringView typeName, Storage::Version version) const
+{
+ if constexpr (useProjectStorage()) {
+ return NodeMetaInfo(d->projectStorage->typeId(module.id(), typeName, version),
+ d->projectStorage);
+ } else {
+ return {};
+ }
+}
+
/*!
\brief Returns list of QML types available within the model.
*/
@@ -2444,6 +2454,15 @@ MetaInfo Model::metaInfo()
return d->metaInfo();
}
+Module Model::module(Utils::SmallStringView moduleName)
+{
+ if constexpr (useProjectStorage()) {
+ return Module(d->projectStorage->moduleId(moduleName), d->projectStorage);
+ }
+
+ return {};
+}
+
/*! \name View related functions
*/
//\{