aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorTim Jenssen <tim.jenssen@qt.io>2023-07-20 22:41:50 +0200
committerTim Jenssen <tim.jenssen@qt.io>2023-07-21 10:20:45 +0000
commit7df557c0babb11f0c94ca118cfdec7cf8c142f71 (patch)
treefa8bf8c56c044438ebe11254e4d62230fcdebb59 /src/plugins
parent012f926f7c28e34eadfe93f1365d63f0a11b4c80 (diff)
parent655ec9d94880cb7f3c5ff3bf4917705f7629b0d3 (diff)
Merge remote-tracking branch 'origin/qds/dev'
Conflicts: tests/unit/tests/printers/gtest-creator-printing.cpp Change-Id: I5f791161ca1a2966e98a3ca55bc60e5bcbb8f58f
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/qmldesigner/CMakeLists.txt42
-rw-r--r--src/plugins/qmldesigner/assetexporterplugin/assetexporter.cpp24
-rw-r--r--src/plugins/qmldesigner/assetexporterplugin/componentexporter.cpp2
-rw-r--r--src/plugins/qmldesigner/components/bindingeditor/bindingeditor.cpp120
-rw-r--r--src/plugins/qmldesigner/components/bindingeditor/bindingeditor.h4
-rw-r--r--src/plugins/qmldesigner/components/bindingeditor/bindingeditordialog.cpp4
-rw-r--r--src/plugins/qmldesigner/components/bindingeditor/bindingeditordialog.h6
-rw-r--r--src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.cpp17
-rw-r--r--src/plugins/qmldesigner/components/componentcore/theme.h2
-rw-r--r--src/plugins/qmldesigner/components/componentcore/viewmanager.cpp5
-rw-r--r--src/plugins/qmldesigner/components/componentcore/viewmanager.h1
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/bindingmodel.cpp207
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/bindingmodel.h74
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp31
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/connectionmodel.h9
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/connectionview.cpp140
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/connectionview.h15
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.cpp18
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.cpp264
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.h83
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibrarybundleimporter.cpp2
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/curveeditorview.cpp24
-rw-r--r--src/plugins/qmldesigner/components/debugview/debugview.cpp10
-rw-r--r--src/plugins/qmldesigner/components/edit3d/bakelights.cpp44
-rw-r--r--src/plugins/qmldesigner/components/formeditor/backgroundaction.cpp12
-rw-r--r--src/plugins/qmldesigner/components/formeditor/backgroundaction.h8
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.cpp39
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.h4
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditorview.cpp16
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditorview.h1
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditorwidget.cpp56
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditorwidget.h5
-rw-r--r--src/plugins/qmldesigner/components/integration/designdocument.cpp4
-rw-r--r--src/plugins/qmldesigner/components/integration/designdocument.h4
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp17
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp2
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp4
-rw-r--r--src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp2
-rw-r--r--src/plugins/qmldesigner/components/navigator/choosefrompropertylistdialog.cpp5
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatorsearchwidget.cpp28
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatorsearchwidget.h4
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatorview.cpp30
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp2
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp2
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp2
-rw-r--r--src/plugins/qmldesigner/components/resources/dockwidgets.css191
-rw-r--r--src/plugins/qmldesigner/components/texteditor/texteditorview.cpp12
-rw-r--r--src/plugins/qmldesigner/components/textureeditor/textureeditorview.cpp2
-rw-r--r--src/plugins/qmldesigner/components/toolbar/toolbarbackend.cpp38
-rw-r--r--src/plugins/qmldesigner/designercore/include/auxiliarydataproperties.h2
-rw-r--r--src/plugins/qmldesigner/designercore/include/import.h33
-rw-r--r--src/plugins/qmldesigner/designercore/include/model.h34
-rw-r--r--src/plugins/qmldesigner/designercore/include/modelfwd.h11
-rw-r--r--src/plugins/qmldesigner/designercore/include/modelnode.h5
-rw-r--r--src/plugins/qmldesigner/designercore/include/nodemetainfo.h15
-rw-r--r--src/plugins/qmldesigner/designercore/include/projectstorageids.h3
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp139
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/nodehints.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp247
-rw-r--r--src/plugins/qmldesigner/designercore/model/abstractview.cpp9
-rw-r--r--src/plugins/qmldesigner/designercore/model/bindingproperty.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/model/import.cpp73
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalnode_p.h4
-rw-r--r--src/plugins/qmldesigner/designercore/model/model.cpp260
-rw-r--r--src/plugins/qmldesigner/designercore/model/model_p.h13
-rw-r--r--src/plugins/qmldesigner/designercore/model/modelnode.cpp19
-rw-r--r--src/plugins/qmldesigner/designercore/model/modelutils.cpp27
-rw-r--r--src/plugins/qmldesigner/designercore/model/modelutils.h4
-rw-r--r--src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp1
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/commontypecache.h41
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/filesystem.h4
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h101
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstoragefwd.h1
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorageinfotypes.h113
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h11
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstoragetypes.h106
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.cpp33
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h2
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparserinterface.h2
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.cpp8
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h2
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/qmltypesparserinterface.h2
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/sourcepathcache.h24
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/sourcepathcacheinterface.h44
-rw-r--r--src/plugins/qmldesigner/designmodewidget.cpp50
-rw-r--r--src/plugins/qmldesigner/documentmanager.cpp20
-rw-r--r--src/plugins/qmldesigner/qmldesignerplugin.cpp78
-rw-r--r--src/plugins/qmldesigner/qmldesignerplugin.h3
-rw-r--r--src/plugins/qmldesigner/qmldesignerprojectmanager.cpp14
-rw-r--r--src/plugins/qmldesigner/qmldesignerprojectmanager.h3
-rw-r--r--src/plugins/qmldesignerbase/studio/studioquickwidget.h121
-rw-r--r--src/plugins/qmldesignerbase/studio/studiostyle.cpp13
-rw-r--r--src/plugins/qmlpreview/qmlpreviewplugin.cpp6
-rw-r--r--src/plugins/studiowelcome/stylemodel.cpp23
-rw-r--r--src/plugins/studiowelcome/stylemodel.h2
96 files changed, 2665 insertions, 705 deletions
diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt
index b6d9f10bfb6..405ad5c00a3 100644
--- a/src/plugins/qmldesigner/CMakeLists.txt
+++ b/src/plugins/qmldesigner/CMakeLists.txt
@@ -82,7 +82,6 @@ if(TARGET QmlDesignerCore)
add_feature_info("ProjectStorage" ${USE_PROJECTSTORAGE} "")
endif()
-
extend_qtc_library(QmlDesignerCore
CONDITION ENABLE_COMPILE_WARNING_AS_ERROR
PROPERTIES COMPILE_WARNING_AS_ERROR ON
@@ -186,23 +185,40 @@ extend_qtc_library(QmlDesignerCore
extend_qtc_library(QmlDesignerCore
SOURCES_PREFIX ${CMAKE_CURRENT_LIST_DIR}/designercore/include
SOURCES
- abstractproperty.h
abstractview.h
+ basetexteditmodifier.h
+ bytearraymodifier.h
+ componenttextmodifier.h
+ forwardview.h
+ itemlibraryinfo.h
+ metainforeader.h
+ model.h
+ nodehints.h
+ plaintexteditmodifier.h
+ nodeinstanceview.h
+ propertyparser.h
+ rewriterview.h
+ subcomponentmanager.h
+ textmodifier.h
+)
+
+extend_qtc_library(QmlDesignerCore
+ SOURCES_PROPERTIES SKIP_AUTOGEN ON
+ SOURCES_PREFIX ${CMAKE_CURRENT_LIST_DIR}/designercore/include
+ SOURCES
+ abstractproperty.h
anchorline.h
annotation.h
asynchronousexplicitimagecache.h
asynchronousimagecache.h
auxiliarydata.h
auxiliarydataproperties.h
- basetexteditmodifier.h
bindingproperty.h
- componenttextmodifier.h
customnotifications.h
documentmessage.h
enumerationmetainfo.h
exception.h
externaldependenciesinterface.h
- forwardview.h
imagecacheauxiliarydata.h
import.h
invalidargumentexception.h
@@ -214,33 +230,26 @@ extend_qtc_library(QmlDesignerCore
invalidqmlsourceexception.h
invalidreparentingexception.h
invalidslideindexexception.h
- itemlibraryinfo.h
mathutils.h
metainfo.h
- metainforeader.h
- model.h
modelfwd.h
modelmerger.h
modelnode.h
modelnodepositionstorage.h
nodeabstractproperty.h
- nodehints.h
nodeinstance.h
- nodeinstanceview.h
nodelistproperty.h
nodemetainfo.h
nodeproperty.h
notimplementedexception.h
- plaintexteditmodifier.h
propertycontainer.h
propertymetainfo.h
propertynode.h
- propertyparser.h
qmlanchors.h
qmlchangeset.h
qmlconnections.h
- qmldesignercorelib_global.h
qmldesignercorelib_exports.h
+ qmldesignercorelib_global.h
qmlitemnode.h
qmlmodelnodefacade.h
qmlobjectnode.h
@@ -248,14 +257,11 @@ extend_qtc_library(QmlDesignerCore
qmltimeline.h
qmltimelinekeyframegroup.h
removebasestateexception.h
- rewriterview.h
rewritingexception.h
signalhandlerproperty.h
stringutils.h
stylesheetmerger.h
- subcomponentmanager.h
synchronousimagecache.h
- textmodifier.h
variantproperty.h
)
@@ -382,7 +388,7 @@ extend_qtc_library(QmlDesignerCore
extend_qtc_library(QmlDesignerCore
SOURCES_PREFIX designercore/projectstorage
PUBLIC_INCLUDES designercore/projectstorage
- SOURCES_PROPERTIES SKIP_AUTOMOC ON
+ SOURCES_PROPERTIES SKIP_AUTOGEN ON
SOURCES
commontypecache.h
directorypathcompressor.h
@@ -407,7 +413,7 @@ extend_qtc_library(QmlDesignerCore
projectstorage.cpp projectstorage.h
sourcepath.h
sourcepathcache.h
- sourcepathcache.h
+ sourcepathcacheinterface.h
sourcepathcachetypes.h
sourcepathview.h
storagecache.h
diff --git a/src/plugins/qmldesigner/assetexporterplugin/assetexporter.cpp b/src/plugins/qmldesigner/assetexporterplugin/assetexporter.cpp
index 7b0604c19a8..2cc6606efa1 100644
--- a/src/plugins/qmldesigner/assetexporterplugin/assetexporter.cpp
+++ b/src/plugins/qmldesigner/assetexporterplugin/assetexporter.cpp
@@ -4,12 +4,13 @@
#include "componentexporter.h"
#include "exportnotification.h"
-#include "designdocument.h"
-#include "nodemetainfo.h"
-#include "qmldesignerplugin.h"
-#include "rewriterview.h"
-#include "qmlitemnode.h"
-#include "qmlobjectnode.h"
+#include <designdocument.h>
+#include <model/modelutils.h>
+#include <nodemetainfo.h>
+#include <qmldesignerplugin.h>
+#include <qmlitemnode.h>
+#include <qmlobjectnode.h>
+#include <rewriterview.h>
#include <coreplugin/editormanager/editormanager.h>
#include <projectexplorer/project.h>
@@ -340,12 +341,11 @@ QString AssetExporter::componentUuid(const ModelNode &instance) const
// Returns the UUID of the component's root node
// Empty string is returned if the node is not an instance of a component within
// the project.
- NodeMetaInfo metaInfo = instance.metaInfo();
- if (!metaInfo.isValid())
- return {};
- const QString path = metaInfo.componentFileName();
- if (m_componentUuidCache.contains(path))
- return m_componentUuidCache[path];
+ if (instance) {
+ const QString path = ModelUtils::componentFilePath(instance);
+ return m_componentUuidCache.value(path);
+ }
+
return {};
}
diff --git a/src/plugins/qmldesigner/assetexporterplugin/componentexporter.cpp b/src/plugins/qmldesigner/assetexporterplugin/componentexporter.cpp
index 7ec9841198a..701e9fdd244 100644
--- a/src/plugins/qmldesigner/assetexporterplugin/componentexporter.cpp
+++ b/src/plugins/qmldesigner/assetexporterplugin/componentexporter.cpp
@@ -28,7 +28,7 @@ static QByteArrayList populateLineage(const QmlDesigner::ModelNode &node)
if (!node.isValid() || node.type().isEmpty())
return {};
- for (auto &info : node.metaInfo().superClasses())
+ for (auto &info : node.metaInfo().prototypes())
lineage.append(info.typeName());
return lineage;
diff --git a/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.cpp b/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.cpp
index 8c8d0911793..10e8181d8d5 100644
--- a/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.cpp
+++ b/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.cpp
@@ -91,10 +91,7 @@ void BindingEditor::setBackendValue(const QVariant &backendValue)
const ModelNode node = propertyEditorValue->modelNode();
if (node.isValid()) {
- m_backendValueTypeName = node.metaInfo()
- .property(propertyEditorValue->name())
- .propertyType()
- .simplifiedTypeName();
+ m_backendValueType = node.metaInfo().property(propertyEditorValue->name()).propertyType();
QString nodeId = node.id();
if (nodeId.isEmpty())
@@ -102,9 +99,11 @@ void BindingEditor::setBackendValue(const QVariant &backendValue)
m_targetName = nodeId + "." + propertyEditorValue->name();
- if (m_backendValueTypeName == "alias" || m_backendValueTypeName == "unknown")
+ if (!m_backendValueType || m_backendValueType.isAlias()) {
if (QmlObjectNode::isValidQmlObjectNode(node))
- m_backendValueTypeName = QmlObjectNode(node).instanceType(propertyEditorValue->name());
+ m_backendValueType = node.model()->metaInfo(
+ QmlObjectNode(node).instanceType(propertyEditorValue->name()));
+ }
}
emit backendValueChanged();
@@ -135,7 +134,7 @@ void BindingEditor::setStateModelNode(const QVariant &stateModelNode)
m_modelNode = m_stateModelNode.value<QmlDesigner::ModelNode>();
if (m_modelNode.isValid())
- m_backendValueTypeName = "bool";
+ m_backendValueType = m_modelNode.model()->boolMetaInfo();
emit stateModelNodeChanged();
}
@@ -153,9 +152,9 @@ void BindingEditor::setModelNode(const ModelNode &modelNode)
m_modelNode = modelNode;
}
-void BindingEditor::setBackendValueTypeName(const TypeName &backendValueTypeName)
+void BindingEditor::setBackendValueType(const NodeMetaInfo &backendValueType)
{
- m_backendValueTypeName = backendValueTypeName;
+ m_backendValueType = backendValueType;
emit backendValueChanged();
}
@@ -165,65 +164,80 @@ void BindingEditor::setTargetName(const QString &target)
m_targetName = target;
}
+namespace {
+template<typename Tuple>
+bool isType(const Tuple &types, const TypeName &compareType)
+{
+ return std::apply([&](const auto &...type) { return ((type == compareType) || ...); }, types);
+}
+
+template<typename... Tuple>
+bool isType(const TypeName &first, const TypeName &second, const Tuple &...types)
+{
+ return ((types == first) || ...) && ((types == second) || ...);
+}
+
+bool compareTypes(const NodeMetaInfo &sourceType, const NodeMetaInfo &targetType)
+{
+ if constexpr (useProjectStorage()) {
+ return targetType.isVariant() || sourceType.isVariant() || targetType == sourceType
+ || (targetType.isNumber() && sourceType.isNumber())
+ || (targetType.isColor() && sourceType.isColor())
+ || (targetType.isString() && sourceType.isString());
+ } else {
+ const TypeName source = sourceType.simplifiedTypeName();
+ const TypeName target = targetType.simplifiedTypeName();
+
+ static constexpr auto variantTypes = std::make_tuple("alias", "unknown", "variant", "var");
+
+ return isType(variantTypes, target) || isType(variantTypes, source)
+ || targetType == sourceType || isType(target, source, "double", "real", "int")
+ || isType(target, source, "QColor", "color")
+ || isType(target, source, "QString", "string");
+ }
+}
+} // namespace
+
void BindingEditor::prepareBindings()
{
- if (!m_modelNode.isValid() || m_backendValueTypeName.isEmpty())
+ if (!m_modelNode.isValid() || !m_backendValueType) {
return;
+ }
const QList<QmlDesigner::ModelNode> allNodes = m_modelNode.view()->allModelNodes();
QList<BindingEditorDialog::BindingOption> bindings;
- const QVarLengthArray<TypeName> variantTypes = {"alias", "unknown", "variant", "var"};
- const QVarLengthArray<TypeName> numericTypes = {"double", "real", "int"};
- const QVarLengthArray<TypeName> colorTypes = {"QColor", "color"};
- const QVarLengthArray<TypeName> stringTypes = {"QString", "string"};
-
- auto isVariant = [&variantTypes](const TypeName &compareType) {
- return variantTypes.contains(compareType);
- };
- auto isNumeric = [&numericTypes](const TypeName &compareType) {
- return numericTypes.contains(compareType);
- };
- auto isColor = [&colorTypes](const TypeName &compareType) {
- return colorTypes.contains(compareType);
- };
- auto isString = [&stringTypes](const TypeName &compareType) {
- return stringTypes.contains(compareType);
- };
-
- auto compareTypes = [&](const TypeName &targetType, const TypeName &sourceType) {
- return isVariant(targetType) || isVariant(sourceType) || (targetType == sourceType)
- || (isNumeric(targetType) && isNumeric(sourceType))
- || (isColor(targetType) && isColor(sourceType))
- || (isString(targetType) && isString(sourceType));
- };
-
for (const auto &objnode : allNodes) {
BindingEditorDialog::BindingOption binding;
for (const auto &property : objnode.metaInfo().properties()) {
- const TypeName &propertyTypeName = property.propertyType().simplifiedTypeName();
+ const auto &propertyType = property.propertyType();
- if (compareTypes(m_backendValueTypeName, propertyTypeName))
+ if (compareTypes(m_backendValueType, propertyType)) {
binding.properties.append(QString::fromUtf8(property.name()));
+ }
}
//dynamic properties:
for (const BindingProperty &bindingProperty : objnode.bindingProperties()) {
if (bindingProperty.isValid()) {
if (bindingProperty.isDynamic()) {
- const TypeName dynamicTypeName = bindingProperty.dynamicTypeName();
- if (compareTypes(m_backendValueTypeName, dynamicTypeName))
+ auto model = bindingProperty.model();
+ const auto dynamicType = model->metaInfo(bindingProperty.dynamicTypeName());
+ if (compareTypes(m_backendValueType, dynamicType)) {
binding.properties.append(QString::fromUtf8(bindingProperty.name()));
+ }
}
}
}
for (const VariantProperty &variantProperty : objnode.variantProperties()) {
if (variantProperty.isValid()) {
if (variantProperty.isDynamic()) {
- const TypeName dynamicTypeName = variantProperty.dynamicTypeName();
- if (compareTypes(m_backendValueTypeName, dynamicTypeName))
+ auto model = variantProperty.model();
+ const auto dynamicType = model->metaInfo(variantProperty.dynamicTypeName());
+ if (compareTypes(m_backendValueType, dynamicType)) {
binding.properties.append(QString::fromUtf8(variantProperty.name()));
+ }
}
}
}
@@ -244,10 +258,11 @@ void BindingEditor::prepareBindings()
BindingEditorDialog::BindingOption binding;
for (const auto &property : metaInfo.properties()) {
- const TypeName propertyTypeName = property.propertyType().typeName();
+ const auto propertyType = property.propertyType();
- if (compareTypes(m_backendValueTypeName, propertyTypeName))
+ if (compareTypes(m_backendValueType, propertyType)) {
binding.properties.append(QString::fromUtf8(property.name()));
+ }
}
if (!binding.properties.isEmpty()) {
@@ -260,15 +275,24 @@ void BindingEditor::prepareBindings()
}
if (!bindings.isEmpty() && !m_dialog.isNull())
- m_dialog->setAllBindings(bindings, m_backendValueTypeName);
+ m_dialog->setAllBindings(bindings, m_backendValueType);
}
void BindingEditor::updateWindowName()
{
- if (!m_dialog.isNull() && !m_backendValueTypeName.isEmpty()) {
- const QString targetString = " ["
- + (m_targetName.isEmpty() ? QString() : (m_targetName + ": "))
- + QString::fromUtf8(m_backendValueTypeName) + "]";
+ if (!m_dialog.isNull() && m_backendValueType) {
+ QString targetString;
+ if constexpr (useProjectStorage()) {
+ auto exportedTypeNames = m_backendValueType.exportedTypeNamesForSourceId(
+ m_modelNode.model()->fileUrlSourceId());
+ if (exportedTypeNames.size()) {
+ targetString = " [" + (m_targetName.isEmpty() ? QString() : (m_targetName + ": "))
+ + exportedTypeNames.front().name.toQString() + "]";
+ }
+ } else {
+ targetString = " [" + (m_targetName.isEmpty() ? QString() : (m_targetName + ": "))
+ + QString::fromUtf8(m_backendValueType.simplifiedTypeName()) + "]";
+ }
m_dialog->setWindowTitle(m_dialog->defaultTitle() + targetString);
}
diff --git a/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.h b/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.h
index 59ce036c18c..52aa0884f69 100644
--- a/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.h
+++ b/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.h
@@ -49,7 +49,7 @@ public:
//3. modelnode + backend value type name + optional target name
void setModelNode(const ModelNode &modelNode);
- void setBackendValueTypeName(const TypeName &backendValueTypeName);
+ void setBackendValueType(const NodeMetaInfo &backendValueType);
void setTargetName(const QString &target);
Q_INVOKABLE void prepareBindings();
@@ -77,7 +77,7 @@ private:
QVariant m_modelNodeBackend;
QVariant m_stateModelNode;
QmlDesigner::ModelNode m_modelNode;
- TypeName m_backendValueTypeName;
+ NodeMetaInfo m_backendValueType;
QString m_targetName;
};
diff --git a/src/plugins/qmldesigner/components/bindingeditor/bindingeditordialog.cpp b/src/plugins/qmldesigner/components/bindingeditor/bindingeditordialog.cpp
index 0cb178603f3..ac5dd615337 100644
--- a/src/plugins/qmldesigner/components/bindingeditor/bindingeditordialog.cpp
+++ b/src/plugins/qmldesigner/components/bindingeditor/bindingeditordialog.cpp
@@ -79,7 +79,7 @@ void BindingEditorDialog::adjustProperties()
m_comboBoxProperty->setCurrentText(property);
}
-void BindingEditorDialog::setAllBindings(const QList<BindingOption> &bindings, const TypeName &type)
+void BindingEditorDialog::setAllBindings(const QList<BindingOption> &bindings, const NodeMetaInfo &type)
{
m_lock = true;
@@ -118,7 +118,7 @@ void BindingEditorDialog::setupComboBoxes()
void BindingEditorDialog::setupCheckBox()
{
- const bool visible = (m_type == "bool");
+ const bool visible = m_type.isBool();
m_checkBoxNot->setVisible(visible);
}
diff --git a/src/plugins/qmldesigner/components/bindingeditor/bindingeditordialog.h b/src/plugins/qmldesigner/components/bindingeditor/bindingeditordialog.h
index ba14a0ee38d..f2995f0a1bf 100644
--- a/src/plugins/qmldesigner/components/bindingeditor/bindingeditordialog.h
+++ b/src/plugins/qmldesigner/components/bindingeditor/bindingeditordialog.h
@@ -6,6 +6,8 @@
#include <bindingeditor/abstracteditordialog.h>
+#include <nodemetainfo.h>
+
QT_BEGIN_NAMESPACE
class QComboBox;
class QCheckBox;
@@ -35,7 +37,7 @@ public:
void adjustProperties() override;
- void setAllBindings(const QList<BindingOption> &bindings, const TypeName &type);
+ void setAllBindings(const QList<BindingOption> &bindings, const NodeMetaInfo &type);
private:
void setupUIComponents();
@@ -53,7 +55,7 @@ private:
QCheckBox *m_checkBoxNot = nullptr;
QList<BindingOption> m_bindings;
- TypeName m_type;
+ NodeMetaInfo m_type;
};
}
diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.cpp b/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.cpp
index 7ff4e6f8722..75976fd7210 100644
--- a/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.cpp
@@ -3,13 +3,14 @@
#include "modelnodecontextmenu_helper.h"
-#include <nodemetainfo.h>
-#include <modelnode.h>
-#include <qmlitemnode.h>
#include <bindingproperty.h>
+#include <model/modelutils.h>
+#include <modelnode.h>
+#include <nodemetainfo.h>
#include <nodeproperty.h>
-#include <qmldesignerplugin.h>
#include <qmldesignerconstants.h>
+#include <qmldesignerplugin.h>
+#include <qmlitemnode.h>
#include <QFile>
@@ -76,10 +77,11 @@ bool selectionHasSameParent(const SelectionContext &selectionState)
bool fileComponentExists(const ModelNode &modelNode)
{
- if (!modelNode.metaInfo().isFileComponent())
+ if (!modelNode.metaInfo().isFileComponent()) {
return true;
+ }
- const QString fileName = modelNode.metaInfo().componentFileName();
+ const QString fileName = ModelUtils::componentFilePath(modelNode);
if (fileName.contains("qml/QtQuick"))
return false;
@@ -97,7 +99,8 @@ bool selectionIsImported3DAsset(const SelectionContext &selectionState)
{
ModelNode node = selectionState.currentSingleSelectedNode();
if (selectionState.view() && node.hasMetaInfo()) {
- QString fileName = node.metaInfo().componentFileName(); // absolute path
+ QString fileName = ModelUtils::componentFilePath(node);
+
if (fileName.isEmpty()) {
// Node is not a file component, so we have to check if the current doc itself is
fileName = node.model()->fileUrl().toLocalFile();
diff --git a/src/plugins/qmldesigner/components/componentcore/theme.h b/src/plugins/qmldesigner/components/componentcore/theme.h
index a565ae03fcf..fba2f25a05c 100644
--- a/src/plugins/qmldesigner/components/componentcore/theme.h
+++ b/src/plugins/qmldesigner/components/componentcore/theme.h
@@ -187,6 +187,7 @@ public:
materialPreviewEnvironment,
materialPreviewModel,
material_medium,
+ maxBar_small,
mergeCells,
merge_small,
minus,
@@ -200,6 +201,7 @@ public:
move_medium,
newMaterial,
nextFile_large,
+ normalBar_small,
openLink,
openMaterialBrowser,
orientation,
diff --git a/src/plugins/qmldesigner/components/componentcore/viewmanager.cpp b/src/plugins/qmldesigner/components/componentcore/viewmanager.cpp
index 29bee73620a..fc30ab99f9d 100644
--- a/src/plugins/qmldesigner/components/componentcore/viewmanager.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/viewmanager.cpp
@@ -480,6 +480,11 @@ void ViewManager::exportAsImage()
d->formEditorView.exportAsImage();
}
+QImage ViewManager::takeFormEditorScreenshot()
+{
+ return d->formEditorView.takeFormEditorScreenshot();
+}
+
void ViewManager::reformatFileUsingTextEditorView()
{
d->textEditorView.reformatFile();
diff --git a/src/plugins/qmldesigner/components/componentcore/viewmanager.h b/src/plugins/qmldesigner/components/componentcore/viewmanager.h
index 4201065f99f..a3cacbe907e 100644
--- a/src/plugins/qmldesigner/components/componentcore/viewmanager.h
+++ b/src/plugins/qmldesigner/components/componentcore/viewmanager.h
@@ -74,6 +74,7 @@ public:
const AbstractView *view() const;
void exportAsImage();
+ QImage takeFormEditorScreenshot();
void reformatFileUsingTextEditorView();
QWidgetAction *componentViewAction() const;
diff --git a/src/plugins/qmldesigner/components/connectioneditor/bindingmodel.cpp b/src/plugins/qmldesigner/components/connectioneditor/bindingmodel.cpp
index 191900d5e9d..2b2025ed83a 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/bindingmodel.cpp
+++ b/src/plugins/qmldesigner/components/connectioneditor/bindingmodel.cpp
@@ -13,14 +13,16 @@
#include <rewritertransaction.h>
#include <rewriterview.h>
+#include <utils/qtcassert.h>
+
#include <QMessageBox>
#include <QTimer>
namespace QmlDesigner {
BindingModel::BindingModel(ConnectionView *parent)
- : QStandardItemModel(parent)
- , m_connectionView(parent)
+ : QStandardItemModel(parent), m_connectionView(parent),
+ m_delegate(new BindingModelBackendDelegate(this))
{
connect(this, &QStandardItemModel::dataChanged, this, &BindingModel::handleDataChanged);
}
@@ -40,6 +42,31 @@ void BindingModel::resetModel()
endResetModel();
}
+void BindingModel::add()
+{
+ addBindingForCurrentNode();
+}
+
+void BindingModel::remove(int row)
+{
+ deleteBindindByRow(row);
+}
+
+int BindingModel::currentIndex() const
+{
+ return m_currentIndex;
+}
+
+void BindingModel::setCurrentIndex(int i)
+{
+ if (m_currentIndex == i)
+ return;
+
+ m_currentIndex = i;
+
+ emit currentIndexChanged();
+}
+
void BindingModel::bindingChanged(const BindingProperty &bindingProperty)
{
m_handleDataChanged = false;
@@ -232,6 +259,19 @@ void BindingModel::addBindingForCurrentNode()
}
}
+static void updateDisplayRoles(QStandardItem *item, const BindingProperty &property)
+{
+ item->setData(property.parentModelNode().id(), BindingModel::TargetNameRole);
+ item->setData(property.name(), BindingModel::TargetPropertyNameRole);
+
+ const AbstractProperty source = property.resolveToProperty();
+
+ if (source.isValid()) {
+ item->setData(source.parentModelNode().id(), BindingModel::SourceNameRole);
+ item->setData(source.name(), BindingModel::SourcePropertyNameRole);
+ }
+}
+
void BindingModel::addBindingProperty(const BindingProperty &property)
{
QStandardItem *idItem;
@@ -248,6 +288,7 @@ void BindingModel::addBindingProperty(const BindingProperty &property)
QList<QStandardItem*> items;
items.append(idItem);
+ updateDisplayRoles(idItem, property);
items.append(targetPropertyNameItem);
QString sourceNodeName;
@@ -267,6 +308,10 @@ void BindingModel::updateBindingProperty(int rowNumber)
BindingProperty bindingProperty = bindingPropertyForRow(rowNumber);
if (bindingProperty.isValid()) {
+ QStandardItem *idItem = item(rowNumber, 0);
+ if (idItem)
+ updateDisplayRoles(idItem, bindingProperty);
+
QString targetPropertyName = QString::fromUtf8(bindingProperty.name());
updateDisplayRole(rowNumber, TargetPropertyNameRow, targetPropertyName);
QString sourceNodeName;
@@ -355,6 +400,7 @@ void BindingModel::updateCustomData(QStandardItem *item, const BindingProperty &
{
item->setData(bindingProperty.parentModelNode().internalId(), Qt::UserRole + 1);
item->setData(bindingProperty.name(), Qt::UserRole + 2);
+ updateDisplayRoles(item, bindingProperty);
}
int BindingModel::findRowForBinding(const BindingProperty &bindingProperty)
@@ -369,6 +415,8 @@ int BindingModel::findRowForBinding(const BindingProperty &bindingProperty)
bool BindingModel::getExpressionStrings(const BindingProperty &bindingProperty, QString *sourceNode, QString *sourceProperty)
{
+ //TODO reimplement using existing helper functions
+
//### todo we assume no expressions yet
const QString expression = bindingProperty.expression();
@@ -438,4 +486,159 @@ void BindingModel::handleException()
resetModel();
}
+QHash<int, QByteArray> BindingModel::roleNames() const
+{
+ static QHash<int, QByteArray> roleNames{{TargetNameRole, "target"},
+ {TargetPropertyNameRole, "targetProperty"},
+ {SourceNameRole, "source"},
+ {SourcePropertyNameRole, "sourceProperty"}};
+
+ return roleNames;
+}
+
+BindingModelBackendDelegate *BindingModel::delegate() const
+{
+ return m_delegate;
+}
+
+BindingModelBackendDelegate::BindingModelBackendDelegate(BindingModel *parent) : QObject(parent)
+{
+ connect(&m_sourceNode, &StudioQmlComboBoxBackend::activated, this, [this]() {
+ handleSourceNodeChanged();
+ });
+
+ connect(&m_sourceNodeProperty, &StudioQmlComboBoxBackend::activated, this, [this]() {
+ handleSourcePropertyChanged();
+ });
+}
+
+int BindingModelBackendDelegate::currentRow() const
+{
+ return m_currentRow;
+}
+
+void BindingModelBackendDelegate::setCurrentRow(int i)
+{
+ // See BindingDelegate::createEditor
+
+ if (m_currentRow == i)
+ return;
+
+ m_currentRow = i;
+
+ //setup
+
+ BindingModel *model = qobject_cast<BindingModel *>(parent());
+
+ QTC_ASSERT(model, return );
+
+ BindingProperty bindingProperty = model->bindingPropertyForRow(currentRow());
+
+ QString idLabel = bindingProperty.parentModelNode().id();
+ if (idLabel.isEmpty())
+ idLabel = bindingProperty.parentModelNode().simplifiedTypeName();
+
+ m_targetNode = idLabel;
+
+ emit targetNodeChanged();
+
+ m_property.setModel(model->possibleTargetProperties(bindingProperty));
+ m_property.setCurrentText(QString::fromUtf8(bindingProperty.name()));
+
+ QStringList sourceNodes;
+
+ for (const ModelNode &modelNode : model->connectionView()->allModelNodes()) {
+ if (!modelNode.id().isEmpty())
+ sourceNodes.append(modelNode.id());
+ }
+
+ std::sort(sourceNodes.begin(), sourceNodes.end());
+ m_sourceNode.setModel(sourceNodes);
+
+ QString sourceNodeName;
+ QString sourcePropertyName;
+ model->getExpressionStrings(bindingProperty, &sourceNodeName, &sourcePropertyName);
+
+ m_sourceNode.setCurrentText(sourceNodeName);
+
+ m_sourceNodeProperty.setModel(model->possibleSourceProperties(bindingProperty));
+ m_sourceNodeProperty.setCurrentText(sourcePropertyName);
+}
+
+void BindingModelBackendDelegate::handleException()
+{
+ QMessageBox::warning(nullptr, tr("Error"), m_exceptionError);
+ //reset
+}
+
+QString BindingModelBackendDelegate::targetNode() const
+{
+ return m_targetNode;
+}
+
+StudioQmlComboBoxBackend *BindingModelBackendDelegate::property()
+{
+ return &m_property;
+}
+
+StudioQmlComboBoxBackend *BindingModelBackendDelegate::sourceNode()
+{
+ return &m_sourceNode;
+}
+
+StudioQmlComboBoxBackend *BindingModelBackendDelegate::sourceProperty()
+{
+ return &m_sourceNodeProperty;
+}
+
+void BindingModelBackendDelegate::handleSourceNodeChanged()
+{
+ BindingModel *model = qobject_cast<BindingModel *>(parent());
+
+ QTC_ASSERT(model, return );
+ QTC_ASSERT(model->connectionView(), return );
+
+ const QString sourceNode = m_sourceNode.currentText();
+ const QString sourceProperty = m_sourceNodeProperty.currentText();
+
+ QString expression;
+ if (sourceProperty.isEmpty()) {
+ expression = sourceNode;
+ } else {
+ expression = sourceNode + QLatin1String(".") + sourceProperty;
+ }
+
+ BindingProperty bindingProperty = model->bindingPropertyForRow(currentRow());
+ model->connectionView()->executeInTransaction("BindingModel::updateExpression",
+ [&bindingProperty, expression]() {
+ bindingProperty.setExpression(
+ expression.trimmed());
+ });
+}
+
+void BindingModelBackendDelegate::handleSourcePropertyChanged()
+{
+ BindingModel *model = qobject_cast<BindingModel *>(parent());
+
+ QTC_ASSERT(model, return );
+ QTC_ASSERT(model->connectionView(), return );
+
+ const QString sourceNode = m_sourceNode.currentText();
+ const QString sourceProperty = m_sourceNodeProperty.currentText();
+
+ QString expression;
+ if (sourceProperty.isEmpty()) {
+ expression = sourceNode;
+ } else {
+ expression = sourceNode + QLatin1String(".") + sourceProperty;
+ }
+
+ BindingProperty bindingProperty = model->bindingPropertyForRow(currentRow());
+ model->connectionView()->executeInTransaction("BindingModel::updateExpression",
+ [&bindingProperty, expression]() {
+ bindingProperty.setExpression(
+ expression.trimmed());
+ });
+}
+
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/connectioneditor/bindingmodel.h b/src/plugins/qmldesigner/components/connectioneditor/bindingmodel.h
index 12685679e94..1f469876852 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/bindingmodel.h
+++ b/src/plugins/qmldesigner/components/connectioneditor/bindingmodel.h
@@ -7,16 +7,22 @@
#include <bindingproperty.h>
#include <variantproperty.h>
+#include <studioquickwidget.h>
+
#include <QStandardItemModel>
namespace QmlDesigner {
class ConnectionView;
+class BindingModelBackendDelegate;
class BindingModel : public QStandardItemModel
{
Q_OBJECT
+ Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
+ Q_PROPERTY(BindingModelBackendDelegate *delegate READ delegate CONSTANT)
+
public:
enum ColumnRoles {
TargetModelNodeRow = 0,
@@ -24,6 +30,15 @@ public:
SourceModelNodeRow = 2,
SourcePropertyNameRow = 3
};
+
+ enum UserRoles {
+ InternalIdRole = Qt::UserRole + 2,
+ TargetNameRole,
+ TargetPropertyNameRole,
+ SourceNameRole,
+ SourcePropertyNameRole
+ };
+
BindingModel(ConnectionView *parent = nullptr);
void bindingChanged(const BindingProperty &bindingProperty);
void bindingRemoved(const BindingProperty &bindingProperty);
@@ -37,6 +52,18 @@ public:
void addBindingForCurrentNode();
void resetModel();
+ Q_INVOKABLE void add();
+ Q_INVOKABLE void remove(int row);
+
+ int currentIndex() const;
+ void setCurrentIndex(int i);
+ bool getExpressionStrings(const BindingProperty &bindingProperty,
+ QString *sourceNode,
+ QString *sourceProperty);
+
+signals:
+ void currentIndexChanged();
+
protected:
void addBindingProperty(const BindingProperty &property);
void updateBindingProperty(int rowNumber);
@@ -46,11 +73,11 @@ protected:
ModelNode getNodeByIdOrParent(const QString &id, const ModelNode &targetNode) const;
void updateCustomData(QStandardItem *item, const BindingProperty &bindingProperty);
int findRowForBinding(const BindingProperty &bindingProperty);
-
- bool getExpressionStrings(const BindingProperty &bindingProperty, QString *sourceNode, QString *sourceProperty);
-
void updateDisplayRole(int row, int columns, const QString &string);
+ QHash<int, QByteArray> roleNames() const override;
+ BindingModelBackendDelegate *delegate() const;
+
private:
void handleDataChanged(const QModelIndex &topLeft, const QModelIndex& bottomRight);
void handleException();
@@ -60,7 +87,48 @@ private:
bool m_lock = false;
bool m_handleDataChanged = false;
QString m_exceptionError;
+ int m_currentIndex = 0;
+ BindingModelBackendDelegate *m_delegate = nullptr;
+};
+
+class BindingModelBackendDelegate : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int currentRow READ currentRow WRITE setCurrentRow NOTIFY currentRowChanged)
+
+ Q_PROPERTY(QString targetNode READ targetNode NOTIFY targetNodeChanged)
+ Q_PROPERTY(StudioQmlComboBoxBackend *property READ property CONSTANT)
+ Q_PROPERTY(StudioQmlComboBoxBackend *sourceNode READ sourceNode CONSTANT)
+ Q_PROPERTY(StudioQmlComboBoxBackend *sourceProperty READ sourceProperty CONSTANT)
+
+public:
+ BindingModelBackendDelegate(BindingModel *parent = nullptr);
+
+signals:
+ void currentRowChanged();
+ //void nameChanged();
+ void targetNodeChanged();
+private:
+ int currentRow() const;
+ void setCurrentRow(int i);
+ void handleException();
+ QString targetNode() const;
+
+ StudioQmlComboBoxBackend *property();
+ StudioQmlComboBoxBackend *sourceNode();
+ StudioQmlComboBoxBackend *sourceProperty();
+
+ void handleSourceNodeChanged();
+ void handleSourcePropertyChanged();
+
+ StudioQmlComboBoxBackend m_property;
+ StudioQmlComboBoxBackend m_sourceNode;
+ StudioQmlComboBoxBackend m_sourceNodeProperty;
+ QString m_exceptionError;
+ int m_currentRow = -1;
+ QString m_targetNode;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp b/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp
index 4abb7b21376..6fe8af59eb7 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp
+++ b/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp
@@ -252,6 +252,19 @@ void ConnectionModel::updateCustomData(QStandardItem *item, const SignalHandlerP
{
item->setData(signalHandlerProperty.parentModelNode().internalId(), UserRoles::InternalIdRole);
item->setData(signalHandlerProperty.name(), UserRoles::TargetPropertyNameRole);
+ item->setData(signalHandlerProperty.parentModelNode()
+ .bindingProperty("target")
+ .resolveToModelNode()
+ .id(),
+ UserRoles::TargetNameRole);
+
+ // TODO signalHandlerProperty.source() contains a statement that defines the type.
+ // foo.bar() <- function call
+ // foo.state = "literal" //state change
+ //anything else is assignment
+ // e.g. foo.bal = foo2.bula ; foo.bal = "literal" ; goo.gal = true
+
+ item->setData("Assignment", UserRoles::ActionTypeRole);
}
ModelNode ConnectionModel::getTargetNodeForConnection(const ModelNode &connection) const
@@ -370,6 +383,16 @@ void ConnectionModel::removeRowFromTable(const SignalHandlerProperty &property)
}
}
+void ConnectionModel::add()
+{
+ addConnection();
+}
+
+void ConnectionModel::remove(int row)
+{
+ deleteConnectionByRow(row);
+}
+
void ConnectionModel::handleException()
{
QMessageBox::warning(nullptr, tr("Error"), m_exceptionError);
@@ -522,4 +545,12 @@ QStringList ConnectionModel::getPossibleSignalsForConnection(const ModelNode &co
return stringList;
}
+QHash<int, QByteArray> ConnectionModel::roleNames() const
+{
+ static QHash<int, QByteArray> roleNames{{TargetPropertyNameRole, "signal"},
+ {TargetNameRole, "target"},
+ {ActionTypeRole, "action"}};
+ return roleNames;
+}
+
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.h b/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.h
index 42cbe33fc77..fc1108d4035 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.h
+++ b/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.h
@@ -26,7 +26,9 @@ public:
};
enum UserRoles {
InternalIdRole = Qt::UserRole + 1,
- TargetPropertyNameRole
+ TargetPropertyNameRole,
+ TargetNameRole,
+ ActionTypeRole
};
ConnectionModel(ConnectionView *parent = nullptr);
@@ -49,6 +51,9 @@ public:
void deleteConnectionByRow(int currentRow);
void removeRowFromTable(const SignalHandlerProperty &property);
+ Q_INVOKABLE void add();
+ Q_INVOKABLE void remove(int row);
+
protected:
void addModelNode(const ModelNode &modelNode);
void addConnection(const ModelNode &modelNode);
@@ -61,6 +66,8 @@ protected:
void updateCustomData(QStandardItem *item, const SignalHandlerProperty &signalHandlerProperty);
QStringList getPossibleSignalsForConnection(const ModelNode &connection) const;
+ QHash<int, QByteArray> roleNames() const override;
+
private:
void handleDataChanged(const QModelIndex &topLeft, const QModelIndex& bottomRight);
void handleException();
diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectionview.cpp b/src/plugins/qmldesigner/components/connectioneditor/connectionview.cpp
index d8f84f3e0fc..9da3fcc7be4 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/connectionview.cpp
+++ b/src/plugins/qmldesigner/components/connectioneditor/connectionview.cpp
@@ -8,6 +8,7 @@
#include "bindingmodel.h"
#include "connectionmodel.h"
#include "dynamicpropertiesmodel.h"
+#include "theme.h"
#include <bindingproperty.h>
#include <nodeabstractproperty.h>
@@ -16,19 +17,116 @@
#include <qmldesignerplugin.h>
#include <viewmanager.h>
+#include <studioquickwidget.h>
+
+#include <coreplugin/icore.h>
+#include <coreplugin/messagebox.h>
+
#include <utils/qtcassert.h>
+#include <QQmlEngine>
+#include <QShortcut>
#include <QTableView>
namespace QmlDesigner {
+static QString propertyEditorResourcesPath()
+{
+#ifdef SHARE_QML_PATH
+ if (qEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
+ return QLatin1String(SHARE_QML_PATH) + "/propertyEditorQmlSources";
+#endif
+ return Core::ICore::resourcePath("qmldesigner/propertyEditorQmlSources").toString();
+}
+
+class ConnectionViewQuickWidget : public StudioQuickWidget
+{
+ // Q_OBJECT carefull
+
+public:
+ ConnectionViewQuickWidget(ConnectionView *connectionEditorView)
+ : m_connectionEditorView(connectionEditorView)
+
+ {
+ engine()->addImportPath(qmlSourcesPath());
+ engine()->addImportPath(propertyEditorResourcesPath() + "/imports");
+ engine()->addImportPath(qmlSourcesPath() + "/imports");
+
+ m_qmlSourceUpdateShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_F12), this);
+ connect(m_qmlSourceUpdateShortcut,
+ &QShortcut::activated,
+ this,
+ &ConnectionViewQuickWidget::reloadQmlSource);
+
+ //setObjectName(Constants::OBJECT_NAME_STATES_EDITOR);
+ setResizeMode(QQuickWidget::SizeRootObjectToView);
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+
+ auto map = registerPropertyMap("ConnectionsEditorEditorBackend");
+ qmlRegisterAnonymousType<DynamicPropertiesModel>("ConnectionsEditorEditorBackend", 1);
+ qmlRegisterAnonymousType<DynamicPropertiesModelBackendDelegate>(
+ "ConnectionsEditorEditorBackend", 1);
+
+ map->setProperties(
+ {{"connectionModel", QVariant::fromValue(m_connectionEditorView->connectionModel())}});
+
+ map->setProperties(
+ {{"bindingModel", QVariant::fromValue(m_connectionEditorView->bindingModel())}});
+
+ map->setProperties(
+ {{"dynamicPropertiesModel",
+ QVariant::fromValue(m_connectionEditorView->dynamicPropertiesModel())}});
+
+ Theme::setupTheme(engine());
+
+ setMinimumWidth(195);
+ setMinimumHeight(195);
+
+ // init the first load of the QML UI elements
+ reloadQmlSource();
+ }
+ ~ConnectionViewQuickWidget() = default;
+
+ static QString qmlSourcesPath()
+ {
+#ifdef SHARE_QML_PATH
+ if (qEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
+ return QLatin1String(SHARE_QML_PATH) + "/connectionseditor";
+#endif
+ return Core::ICore::resourcePath("qmldesigner/connectionseditor").toString();
+ }
+
+private:
+ void reloadQmlSource()
+ {
+ QString connectionEditorQmlFilePath = qmlSourcesPath() + QStringLiteral("/Main.qml");
+ QTC_ASSERT(QFileInfo::exists(connectionEditorQmlFilePath), return );
+ setSource(QUrl::fromLocalFile(connectionEditorQmlFilePath));
+
+ if (!rootObject()) {
+ QString errorString;
+ for (const QQmlError &error : errors())
+ errorString += "\n" + error.toString();
+
+ Core::AsynchronousMessageBox::warning(
+ tr("Cannot Create QtQuick View"),
+ tr("ConnectionsEditorWidget: %1 cannot be created.%2")
+ .arg(qmlSourcesPath(), errorString));
+ return;
+ }
+ }
+
+private:
+ QPointer<ConnectionView> m_connectionEditorView;
+ QShortcut *m_qmlSourceUpdateShortcut;
+};
+
ConnectionView::ConnectionView(ExternalDependenciesInterface &externalDependencies)
- : AbstractView{externalDependencies}
- , m_connectionViewWidget(new ConnectionViewWidget())
- , m_connectionModel(new ConnectionModel(this))
- , m_bindingModel(new BindingModel(this))
- , m_dynamicPropertiesModel(new DynamicPropertiesModel(false, this))
- , m_backendModel(new BackendModel(this))
+ : AbstractView{externalDependencies}, m_connectionViewWidget(new ConnectionViewWidget()),
+ m_connectionModel(new ConnectionModel(this)), m_bindingModel(new BindingModel(this)),
+ m_dynamicPropertiesModel(new DynamicPropertiesModel(false, this)),
+ m_backendModel(new BackendModel(this)),
+ m_connectionViewQuickWidget(new ConnectionViewQuickWidget(this))
{
connectionViewWidget()->setBindingModel(m_bindingModel);
connectionViewWidget()->setConnectionModel(m_connectionModel);
@@ -36,8 +134,11 @@ ConnectionView::ConnectionView(ExternalDependenciesInterface &externalDependenci
connectionViewWidget()->setBackendModel(m_backendModel);
}
-ConnectionView::~ConnectionView() = default;
-
+ConnectionView::~ConnectionView()
+{
+ // Ensure that QML is deleted first to avoid calling back to C++.
+ delete m_connectionViewQuickWidget.data();
+}
void ConnectionView::modelAttached(Model *model)
{
AbstractView::modelAttached(model);
@@ -195,7 +296,14 @@ void ConnectionView::currentStateChanged(const ModelNode &)
WidgetInfo ConnectionView::widgetInfo()
{
- return createWidgetInfo(m_connectionViewWidget.data(),
+ /* Enable new connection editor here */
+ const bool newEditor = false;
+
+ QWidget *widget = m_connectionViewWidget.data();
+ if (newEditor)
+ widget = m_connectionViewQuickWidget.data();
+
+ return createWidgetInfo(widget,
QLatin1String("ConnectionView"),
WidgetInfo::LeftPane,
0,
@@ -257,6 +365,20 @@ BackendModel *ConnectionView::backendModel() const
return m_backendModel;
}
+int ConnectionView::currentIndex() const
+{
+ return m_currentIndex;
+}
+
+void ConnectionView::setCurrentIndex(int i)
+{
+ if (m_currentIndex == i)
+ return;
+
+ m_currentIndex = i;
+ emit currentIndexChanged();
+}
+
ConnectionView *ConnectionView::instance()
{
diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectionview.h b/src/plugins/qmldesigner/components/connectioneditor/connectionview.h
index 89c6c489105..5997f230ad8 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/connectionview.h
+++ b/src/plugins/qmldesigner/components/connectioneditor/connectionview.h
@@ -20,11 +20,14 @@ class BindingModel;
class ConnectionModel;
class DynamicPropertiesModel;
class BackendModel;
+class ConnectionViewQuickWidget;
-class ConnectionView : public AbstractView
+class ConnectionView : public AbstractView
{
Q_OBJECT
+ Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
+
public:
ConnectionView(ExternalDependenciesInterface &externalDependencies);
~ConnectionView() override;
@@ -70,14 +73,24 @@ public:
BindingModel *bindingModel() const;
BackendModel *backendModel() const;
+ int currentIndex() const;
+ void setCurrentIndex(int i);
+
static ConnectionView *instance();
+signals:
+ void currentIndexChanged();
+
private: //variables
QPointer<ConnectionViewWidget> m_connectionViewWidget;
+
ConnectionModel *m_connectionModel;
BindingModel *m_bindingModel;
DynamicPropertiesModel *m_dynamicPropertiesModel;
BackendModel *m_backendModel;
+ int m_currentIndex = 0;
+
+ QPointer<ConnectionViewQuickWidget> m_connectionViewQuickWidget;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.cpp b/src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.cpp
index edade6ae400..8a8845b47fd 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.cpp
+++ b/src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.cpp
@@ -90,6 +90,8 @@ ConnectionViewWidget::ConnectionViewWidget(QWidget *parent) :
this, &ConnectionViewWidget::handleTabChanged);
ui->stackedWidget->setCurrentIndex(0);
+
+ ui->stackedWidget->parentWidget()->hide();
}
ConnectionViewWidget::~ConnectionViewWidget()
@@ -192,18 +194,17 @@ void ConnectionViewWidget::contextMenuEvent(QContextMenuEvent *event)
return;
const ModelNode node = property.parentModelNode();
- const TypeName typeName = property.isDynamic() ? property.dynamicTypeName()
- : node.metaInfo()
- .property(property.name())
- .propertyType()
- .typeName();
+ auto model = node.model();
+ const auto type = property.isDynamic()
+ ? model->metaInfo(property.dynamicTypeName())
+ : node.metaInfo().property(property.name()).propertyType();
const QString targetName = node.displayName() + "." + property.name();
m_bindingEditor->showWidget();
m_bindingEditor->setBindingValue(property.expression());
m_bindingEditor->setModelNode(node);
- m_bindingEditor->setBackendValueTypeName(typeName);
+ m_bindingEditor->setBackendValueType(type);
m_bindingEditor->setTargetName(targetName);
m_bindingEditor->prepareBindings();
m_bindingEditor->updateWindowName();
@@ -240,11 +241,12 @@ void ConnectionViewWidget::contextMenuEvent(QContextMenuEvent *event)
return;
const QString targetName = node.displayName() + "." + abstractProperty.name();
-
+ auto model = node.model();
m_dynamicEditor->showWidget();
m_dynamicEditor->setBindingValue(newExpression);
m_dynamicEditor->setModelNode(node);
- m_dynamicEditor->setBackendValueTypeName(abstractProperty.dynamicTypeName());
+ m_dynamicEditor->setBackendValueType(
+ model->metaInfo(abstractProperty.dynamicTypeName()));
m_dynamicEditor->setTargetName(targetName);
m_dynamicEditor->prepareBindings();
m_dynamicEditor->updateWindowName();
diff --git a/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.cpp b/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.cpp
index 4faf5d23f17..eb0976eaed9 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.cpp
+++ b/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.cpp
@@ -152,10 +152,34 @@ QString DynamicPropertiesModel::defaultExpressionForType(const TypeName &type)
return expression;
}
+void DynamicPropertiesModel::add()
+{
+ addDynamicPropertyForCurrentNode();
+}
+
+void DynamicPropertiesModel::remove(int row)
+{
+ deleteDynamicPropertyByRow(row);
+}
+
+int DynamicPropertiesModel::currentIndex() const
+{
+ return m_currentIndex;
+}
+
+void DynamicPropertiesModel::setCurrentIndex(int i)
+{
+ if (m_currentIndex == i)
+ return;
+
+ m_currentIndex = i;
+
+ emit currentIndexChanged();
+}
+
DynamicPropertiesModel::DynamicPropertiesModel(bool explicitSelection, AbstractView *parent)
- : QStandardItemModel(parent)
- , m_view(parent)
- , m_explicitSelection(explicitSelection)
+ : QStandardItemModel(parent), m_view(parent), m_explicitSelection(explicitSelection),
+ m_delegate(new DynamicPropertiesModelBackendDelegate(this))
{
connect(this, &QStandardItemModel::dataChanged, this, &DynamicPropertiesModel::handleDataChanged);
}
@@ -163,6 +187,7 @@ DynamicPropertiesModel::DynamicPropertiesModel(bool explicitSelection, AbstractV
void DynamicPropertiesModel::resetModel()
{
beginResetModel();
+ const int backIndex = m_currentIndex;
clear();
setHorizontalHeaderLabels({tr("Item"), tr("Property"), tr("Property Type"), tr("Property Value")});
@@ -172,7 +197,9 @@ void DynamicPropertiesModel::resetModel()
addModelNode(modelNode);
}
+ emit currentIndexChanged();
endResetModel();
+ m_currentIndex = backIndex;
}
@@ -344,6 +371,8 @@ void DynamicPropertiesModel::bindingRemoved(const BindingProperty &bindingProper
removeRow(rowNumber);
}
+ emit currentIndexChanged();
+
m_handleDataChanged = true;
}
@@ -360,6 +389,8 @@ void DynamicPropertiesModel::variantRemoved(const VariantProperty &variantProper
removeRow(rowNumber);
}
+ emit currentIndexChanged();
+
m_handleDataChanged = true;
}
@@ -368,6 +399,7 @@ void DynamicPropertiesModel::reset()
m_handleDataChanged = false;
resetModel();
m_handleDataChanged = true;
+ emit currentIndexChanged();
}
void DynamicPropertiesModel::setSelectedNode(const ModelNode &node)
@@ -597,6 +629,8 @@ void DynamicPropertiesModel::updateBindingProperty(int rowNumber)
BindingProperty bindingProperty = bindingPropertyForRow(rowNumber);
if (bindingProperty.isValid()) {
+ updateCustomData(rowNumber, bindingProperty);
+
QString propertyName = QString::fromUtf8(bindingProperty.name());
updateDisplayRole(rowNumber, PropertyNameRow, propertyName);
QString value = bindingProperty.expression();
@@ -617,6 +651,7 @@ void DynamicPropertiesModel::updateVariantProperty(int rowNumber)
VariantProperty variantProperty = variantPropertyForRow(rowNumber);
if (variantProperty.isValid()) {
+ updateCustomData(rowNumber, variantProperty);
QString propertyName = QString::fromUtf8(variantProperty.name());
updateDisplayRole(rowNumber, PropertyNameRow, propertyName);
QVariant value = variantProperty.value();
@@ -787,6 +822,16 @@ void DynamicPropertiesModel::updateCustomData(QStandardItem *item, const Abstrac
{
item->setData(property.parentModelNode().internalId(), Qt::UserRole + 1);
item->setData(property.name(), Qt::UserRole + 2);
+
+ item->setData(property.parentModelNode().id(), TargetNameRole);
+ item->setData(property.name(), PropertyNameRole);
+ item->setData(property.parentModelNode().id(), TargetNameRole);
+ item->setData(property.dynamicTypeName(), PropertyTypeRole);
+
+ if (property.isVariantProperty())
+ item->setData(property.toVariantProperty().value(), PropertyValueRole);
+ if (property.isBindingProperty())
+ item->setData(property.toBindingProperty().expression(), PropertyValueRole);
}
void DynamicPropertiesModel::updateCustomData(int row, const AbstractProperty &property)
@@ -924,4 +969,217 @@ const ModelNode DynamicPropertiesModel::singleSelectedNode() const
return m_view->singleSelectedModelNode();
}
+QHash<int, QByteArray> DynamicPropertiesModel::roleNames() const
+{
+ static QHash<int, QByteArray> roleNames{{TargetNameRole, "target"},
+ {PropertyNameRole, "name"},
+ {PropertyTypeRole, "type"},
+ {PropertyValueRole, "value"}};
+
+ return roleNames;
+}
+
+DynamicPropertiesModelBackendDelegate *DynamicPropertiesModel::delegate() const
+{
+ return m_delegate;
+}
+
+DynamicPropertiesModelBackendDelegate::DynamicPropertiesModelBackendDelegate(
+ DynamicPropertiesModel *parent)
+ : QObject(parent)
+{
+ m_type.setModel({"int", "bool", "var", "real", "string", "url", "color"});
+
+ connect(&m_type, &StudioQmlComboBoxBackend::activated, this, [this]() { handleTypeChanged(); });
+ connect(&m_name, &StudioQmlTextBackend::activated, this, [this]() { handleNameChanged(); });
+ connect(&m_value, &StudioQmlTextBackend::activated, this, [this]() { handleValueChanged(); });
+}
+
+int DynamicPropertiesModelBackendDelegate::currentRow() const
+{
+ return m_currentRow;
+}
+
+void DynamicPropertiesModelBackendDelegate::setCurrentRow(int i)
+{
+ if (m_currentRow == i)
+ return;
+
+ m_currentRow = i;
+
+ //setup
+
+ DynamicPropertiesModel *model = qobject_cast<DynamicPropertiesModel *>(parent());
+
+ QTC_ASSERT(model, return );
+
+ AbstractProperty property = model->abstractPropertyForRow(i);
+
+ m_type.setCurrentText(QString::fromUtf8(property.dynamicTypeName()));
+ m_name.setText(QString::fromUtf8(property.name()));
+
+ if (property.isVariantProperty())
+ m_value.setText(property.toVariantProperty().value().toString());
+ else if (property.isBindingProperty())
+ m_value.setText(property.toBindingProperty().expression());
+}
+
+void DynamicPropertiesModelBackendDelegate::handleTypeChanged()
+{
+ //void DynamicPropertiesModel::updatePropertyType(int rowNumber)
+ const TypeName type = m_type.currentText().toUtf8();
+
+ DynamicPropertiesModel *model = qobject_cast<DynamicPropertiesModel *>(parent());
+
+ QTC_ASSERT(model, return );
+ QTC_ASSERT(model->view(), return );
+
+ BindingProperty bindingProperty = model->bindingPropertyForRow(currentRow());
+
+ VariantProperty variantProperty = model->variantPropertyForRow(currentRow());
+
+ RewriterTransaction transaction = model->view()->beginRewriterTransaction(__FUNCTION__);
+
+ try {
+ if (bindingProperty.isBindingProperty() || type == "var") { //var is always a binding
+ const QString expression = bindingProperty.expression();
+ variantProperty.parentModelNode().removeProperty(variantProperty.name());
+ bindingProperty.setDynamicTypeNameAndExpression(type, expression);
+ } else if (variantProperty.isVariantProperty()) {
+ variantProperty.parentModelNode().removeProperty(variantProperty.name());
+ variantProperty.setDynamicTypeNameAndValue(type, variantValue());
+ }
+ transaction.commit(); // committing in the try block
+ } catch (Exception &e) {
+ m_exceptionError = e.description();
+ QTimer::singleShot(200, this, &DynamicPropertiesModelBackendDelegate::handleException);
+ }
+}
+
+void DynamicPropertiesModelBackendDelegate::handleNameChanged()
+{
+ //see DynamicPropertiesModel::updatePropertyName
+
+ const PropertyName newName = m_name.text().toUtf8();
+ QTC_ASSERT(!newName.isEmpty(), return );
+
+ DynamicPropertiesModel *model = qobject_cast<DynamicPropertiesModel *>(parent());
+
+ QTC_ASSERT(model, return );
+ QTC_ASSERT(model->view(), return );
+
+ BindingProperty bindingProperty = model->bindingPropertyForRow(currentRow());
+
+ ModelNode targetNode = bindingProperty.parentModelNode();
+
+ if (bindingProperty.isBindingProperty()) {
+ model->view()->executeInTransaction(__FUNCTION__, [bindingProperty, newName, &targetNode]() {
+ const QString expression = bindingProperty.expression();
+ const PropertyName dynamicPropertyType = bindingProperty.dynamicTypeName();
+
+ targetNode.bindingProperty(newName).setDynamicTypeNameAndExpression(dynamicPropertyType,
+ expression);
+ targetNode.removeProperty(bindingProperty.name());
+ });
+
+ return;
+ }
+
+ VariantProperty variantProperty = model->variantPropertyForRow(currentRow());
+
+ if (variantProperty.isVariantProperty()) {
+ const QVariant value = variantProperty.value();
+ const PropertyName dynamicPropertyType = variantProperty.dynamicTypeName();
+ ModelNode targetNode = variantProperty.parentModelNode();
+
+ model->view()->executeInTransaction(__FUNCTION__, [=]() {
+ targetNode.variantProperty(newName).setDynamicTypeNameAndValue(dynamicPropertyType,
+ value);
+ targetNode.removeProperty(variantProperty.name());
+ });
+ }
+
+ AbstractProperty property = targetNode.property(newName);
+
+ //order might have changed because of name change we have to select the correct row
+ int newRow = model->findRowForProperty(property);
+ model->setCurrentIndex(newRow);
+ setCurrentRow(newRow);
+}
+
+void DynamicPropertiesModelBackendDelegate::handleValueChanged()
+{
+ //see void DynamicPropertiesModel::updateValue(int row)
+
+ DynamicPropertiesModel *model = qobject_cast<DynamicPropertiesModel *>(parent());
+
+ QTC_ASSERT(model, return );
+ QTC_ASSERT(model->view(), return );
+
+ BindingProperty bindingProperty = model->bindingPropertyForRow(currentRow());
+
+ if (bindingProperty.isBindingProperty()) {
+ const QString expression = m_value.text();
+
+ RewriterTransaction transaction = model->view()->beginRewriterTransaction(__FUNCTION__);
+ try {
+ bindingProperty.setDynamicTypeNameAndExpression(bindingProperty.dynamicTypeName(),
+ expression);
+ transaction.commit(); // committing in the try block
+ } catch (Exception &e) {
+ m_exceptionError = e.description();
+ QTimer::singleShot(200, this, &DynamicPropertiesModelBackendDelegate::handleException);
+ }
+ return;
+ }
+
+ VariantProperty variantProperty = model->variantPropertyForRow(currentRow());
+
+ if (variantProperty.isVariantProperty()) {
+ RewriterTransaction transaction = model->view()->beginRewriterTransaction(__FUNCTION__);
+ try {
+ variantProperty.setDynamicTypeNameAndValue(variantProperty.dynamicTypeName(),
+ variantValue());
+ transaction.commit(); // committing in the try block
+ } catch (Exception &e) {
+ m_exceptionError = e.description();
+ QTimer::singleShot(200, this, &DynamicPropertiesModelBackendDelegate::handleException);
+ }
+ }
+}
+
+void DynamicPropertiesModelBackendDelegate::handleException()
+{
+ QMessageBox::warning(nullptr, tr("Error"), m_exceptionError);
+ //reset
+}
+
+QVariant DynamicPropertiesModelBackendDelegate::variantValue() const
+{
+ //improve
+ const QString type = m_type.currentText();
+ if (type == "real" || type == "int")
+ return m_value.text().toFloat();
+
+ if (type == "bool")
+ return m_value.text() == "true";
+
+ return m_value.text();
+}
+
+StudioQmlComboBoxBackend *DynamicPropertiesModelBackendDelegate::type()
+{
+ return &m_type;
+}
+
+StudioQmlTextBackend *DynamicPropertiesModelBackendDelegate::name()
+{
+ return &m_name;
+}
+
+StudioQmlTextBackend *DynamicPropertiesModelBackendDelegate::value()
+{
+ return &m_value;
+}
+
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.h b/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.h
index f094516e635..c41875dfc09 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.h
+++ b/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.h
@@ -5,6 +5,8 @@
#include <nodeinstanceglobal.h>
+#include <studioquickwidget.h>
+
#include <QStandardItemModel>
namespace QmlDesigner {
@@ -15,6 +17,8 @@ class BindingProperty;
class ModelNode;
class VariantProperty;
+class DynamicPropertiesModelBackendDelegate;
+
class DynamicPropertiesModel : public QStandardItemModel
{
Q_OBJECT
@@ -22,11 +26,22 @@ class DynamicPropertiesModel : public QStandardItemModel
public:
enum ColumnRoles {
TargetModelNodeRow = 0,
- PropertyNameRow = 1,
- PropertyTypeRow = 2,
- PropertyValueRow = 3
+ PropertyNameRow = 1,
+ PropertyTypeRow = 2,
+ PropertyValueRow = 3
+ };
+
+ enum UserRoles {
+ InternalIdRole = Qt::UserRole + 2,
+ TargetNameRole,
+ PropertyNameRole,
+ PropertyTypeRole,
+ PropertyValueRole
};
+ Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
+ Q_PROPERTY(DynamicPropertiesModelBackendDelegate *delegate READ delegate CONSTANT)
+
DynamicPropertiesModel(bool explicitSelection, AbstractView *parent);
void bindingPropertyChanged(const BindingProperty &bindingProperty);
@@ -62,6 +77,17 @@ public:
static QVariant defaultValueForType(const TypeName &type);
static QString defaultExpressionForType(const TypeName &type);
+ Q_INVOKABLE void add();
+ Q_INVOKABLE void remove(int row);
+
+ int currentIndex() const;
+ void setCurrentIndex(int i);
+
+ int findRowForProperty(const AbstractProperty &abstractProperty) const;
+
+signals:
+ void currentIndexChanged();
+
protected:
void addProperty(const QVariant &propertyValue,
const QString &propertyType,
@@ -79,12 +105,17 @@ protected:
void updateCustomData(int row, const AbstractProperty &property);
int findRowForBindingProperty(const BindingProperty &bindingProperty) const;
int findRowForVariantProperty(const VariantProperty &variantProperty) const;
- int findRowForProperty(const AbstractProperty &abstractProperty) const;
- bool getExpressionStrings(const BindingProperty &bindingProperty, QString *sourceNode, QString *sourceProperty);
+ bool getExpressionStrings(const BindingProperty &bindingProperty,
+ QString *sourceNode,
+ QString *sourceProperty);
void updateDisplayRole(int row, int columns, const QString &string);
+ QHash<int, QByteArray> roleNames() const override;
+
+ DynamicPropertiesModelBackendDelegate *delegate() const;
+
private:
void handleDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
void handleException();
@@ -95,6 +126,48 @@ private:
QString m_exceptionError;
QList<ModelNode> m_selectedNodes;
bool m_explicitSelection = false;
+ int m_currentIndex = 0;
+
+ DynamicPropertiesModelBackendDelegate *m_delegate = nullptr;
+};
+
+class DynamicPropertiesModelBackendDelegate : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(StudioQmlComboBoxBackend *type READ type CONSTANT)
+ Q_PROPERTY(int currentRow READ currentRow WRITE setCurrentRow NOTIFY currentRowChanged)
+ Q_PROPERTY(StudioQmlTextBackend *name READ name CONSTANT)
+ Q_PROPERTY(StudioQmlTextBackend *value READ value CONSTANT)
+ //Q_PROPERTY(QString value READ value WRITE setValue NOTIFY valueChanged)
+
+public:
+ DynamicPropertiesModelBackendDelegate(DynamicPropertiesModel *parent = nullptr);
+
+signals:
+ void currentRowChanged();
+ void nameChanged();
+ void valueChanged();
+
+private:
+ int currentRow() const;
+ void setCurrentRow(int i);
+ void handleTypeChanged();
+ void handleNameChanged();
+ void handleValueChanged();
+ void handleException();
+ QVariant variantValue() const;
+
+ StudioQmlComboBoxBackend *type();
+
+ StudioQmlTextBackend *name();
+ StudioQmlTextBackend *value();
+
+ StudioQmlComboBoxBackend m_type;
+ StudioQmlTextBackend m_name;
+ StudioQmlTextBackend m_value;
+ int m_currentRow = -1;
+ QString m_exceptionError;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarybundleimporter.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarybundleimporter.cpp
index c31f844e5e2..59ec457d071 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarybundleimporter.cpp
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarybundleimporter.cpp
@@ -205,7 +205,7 @@ void ContentLibraryBundleImporter::handleImportTimer()
for (const QString &pendingType : pendingTypes) {
NodeMetaInfo metaInfo = model->metaInfo(pendingType.toUtf8());
const bool isImport = m_pendingTypes[pendingType];
- const bool typeComplete = metaInfo.isValid() && !metaInfo.superClasses().empty();
+ const bool typeComplete = metaInfo.isValid() && !metaInfo.prototypes().empty();
if (isImport == typeComplete) {
m_pendingTypes.remove(pendingType);
if (isImport)
diff --git a/src/plugins/qmldesigner/components/curveeditor/curveeditorview.cpp b/src/plugins/qmldesigner/components/curveeditor/curveeditorview.cpp
index 1d0b38b3f15..e7395c66625 100644
--- a/src/plugins/qmldesigner/components/curveeditor/curveeditorview.cpp
+++ b/src/plugins/qmldesigner/components/curveeditor/curveeditorview.cpp
@@ -68,8 +68,9 @@ void CurveEditorView::modelAboutToBeDetached(Model *model)
bool dirtyfiesView(const ModelNode &node)
{
- return QmlTimeline::isValidQmlTimeline(node)
- || QmlTimelineKeyframeGroup::isValidQmlTimelineKeyframeGroup(node);
+ return (node.type() == "QtQuick.Timeline.Keyframe" && node.hasParentProperty())
+ || QmlTimeline::isValidQmlTimeline(node)
+ || QmlTimelineKeyframeGroup::isValidQmlTimelineKeyframeGroup(node);
}
void CurveEditorView::nodeRemoved([[maybe_unused]] const ModelNode &removedNode,
@@ -143,13 +144,8 @@ void CurveEditorView::variantPropertiesChanged([[maybe_unused]] const QList<Vari
[[maybe_unused]] PropertyChangeFlags propertyChange)
{
for (const auto &property : propertyList) {
- if ((property.name() == "frame" || property.name() == "value")
- && property.parentModelNode().type() == "QtQuick.Timeline.Keyframe"
- && property.parentModelNode().hasParentProperty()) {
- const ModelNode framesNode = property.parentModelNode().parentProperty().parentModelNode();
- if (QmlTimelineKeyframeGroup::isValidQmlTimelineKeyframeGroup(framesNode))
- updateKeyframes();
- }
+ if (dirtyfiesView(property.parentModelNode()))
+ updateKeyframes();
}
}
@@ -157,20 +153,16 @@ void CurveEditorView::bindingPropertiesChanged([[maybe_unused]] const QList<Bind
[[maybe_unused]] PropertyChangeFlags propertyChange)
{
for (const auto &property : propertyList) {
- if (property.name() == "easing.bezierCurve") {
+ if (dirtyfiesView(property.parentModelNode()))
updateKeyframes();
- }
}
}
void CurveEditorView::propertiesRemoved([[maybe_unused]] const QList<AbstractProperty> &propertyList)
{
for (const auto &property : propertyList) {
- if (property.name() == "keyframes") {
- ModelNode parent = property.parentModelNode();
- if (dirtyfiesView(parent))
- updateKeyframes();
- }
+ if (dirtyfiesView(property.parentModelNode()))
+ updateKeyframes();
}
}
diff --git a/src/plugins/qmldesigner/components/debugview/debugview.cpp b/src/plugins/qmldesigner/components/debugview/debugview.cpp
index 2a62d7a6b2b..64f85915f16 100644
--- a/src/plugins/qmldesigner/components/debugview/debugview.cpp
+++ b/src/plugins/qmldesigner/components/debugview/debugview.cpp
@@ -7,6 +7,7 @@
#include <qmldesignerplugin.h>
#include <bindingproperty.h>
+#include <model/modelutils.h>
#include <nodeabstractproperty.h>
#include <nodelistproperty.h>
#include <nodemetainfo.h>
@@ -93,9 +94,9 @@ void DebugView::nodeCreated(const ModelNode &createdNode)
message << createdNode.majorVersion() << "." << createdNode.minorVersion();
message << createdNode.nodeSource();
message << "MetaInfo " << createdNode.metaInfo().isValid() << " ";
- if (createdNode.metaInfo().isValid()) {
- message << createdNode.metaInfo().majorVersion() << "." << createdNode.metaInfo().minorVersion();
- message << createdNode.metaInfo().componentFileName();
+ if (auto metaInfo = createdNode.metaInfo()) {
+ message << metaInfo.majorVersion() << "." << metaInfo.minorVersion();
+ message << ModelUtils::componentFilePath(createdNode);
}
log("::nodeCreated:", message.readAll());
}
@@ -282,9 +283,10 @@ void DebugView::selectedNodesChanged(const QList<ModelNode> &selectedNodes /*sel
message << lineBreak;
if (selectedNode.metaInfo().isValid()) {
- for (const NodeMetaInfo &metaInfo : selectedNode.metaInfo().classHierarchy())
+ for (const NodeMetaInfo &metaInfo : selectedNode.metaInfo().selfAndPrototypes()) {
message << metaInfo.typeName() << " " << metaInfo.majorVersion() << "."
<< metaInfo.minorVersion() << lineBreak;
+ }
message << lineBreak;
message << selectedNode.metaInfo().typeName();
diff --git a/src/plugins/qmldesigner/components/edit3d/bakelights.cpp b/src/plugins/qmldesigner/components/edit3d/bakelights.cpp
index c0ff5de2af3..88e7ad379d5 100644
--- a/src/plugins/qmldesigner/components/edit3d/bakelights.cpp
+++ b/src/plugins/qmldesigner/components/edit3d/bakelights.cpp
@@ -3,19 +3,20 @@
#include "bakelights.h"
-#include "abstractview.h"
-#include "auxiliarydataproperties.h"
-#include "bakelightsdatamodel.h"
-#include "bakelightsconnectionmanager.h"
-#include "bindingproperty.h"
-#include "documentmanager.h"
-#include "modelnode.h"
-#include "nodeabstractproperty.h"
-#include "nodeinstanceview.h"
-#include "nodemetainfo.h"
-#include "plaintexteditmodifier.h"
-#include "rewriterview.h"
-#include "variantproperty.h"
+#include <abstractview.h>
+#include <auxiliarydataproperties.h>
+#include <bakelightsconnectionmanager.h>
+#include <bakelightsdatamodel.h>
+#include <bindingproperty.h>
+#include <documentmanager.h>
+#include <model/modelutils.h>
+#include <modelnode.h>
+#include <nodeabstractproperty.h>
+#include <nodeinstanceview.h>
+#include <nodemetainfo.h>
+#include <plaintexteditmodifier.h>
+#include <rewriterview.h>
+#include <variantproperty.h>
#include <coreplugin/icore.h>
@@ -240,18 +241,21 @@ void BakeLights::rebake()
void BakeLights::exposeModelsAndLights(const QString &nodeId)
{
ModelNode compNode = m_view->modelNodeForId(nodeId);
- if (!compNode.isValid() || !compNode.isComponent()
- || compNode.metaInfo().componentFileName().isEmpty()) {
+ if (!compNode.isValid() || !compNode.isComponent()) {
+ return;
+ }
+
+ auto componentFilePath = ModelUtils::componentFilePath(compNode);
+ if (componentFilePath.isEmpty()) {
return;
}
RewriterView rewriter{m_view->externalDependencies(), RewriterView::Amend};
ModelPointer compModel = QmlDesigner::Model::create("QtQuick/Item", 2, 1);
- const QString compFile = compNode.metaInfo().componentFileName();
- const Utils::FilePath compFilePath = Utils::FilePath::fromString(compFile);
+ const Utils::FilePath compFilePath = Utils::FilePath::fromString(componentFilePath);
QByteArray src = compFilePath.fileContents().value();
- compModel->setFileUrl(QUrl::fromLocalFile(compFile));
+ compModel->setFileUrl(QUrl::fromLocalFile(componentFilePath));
auto textDocument = std::make_unique<QTextDocument>(QString::fromUtf8(src));
auto modifier = std::make_unique<IndentingTextEditModifier>(
@@ -295,12 +299,12 @@ void BakeLights::exposeModelsAndLights(const QString &nodeId)
QString newText = modifier->text();
if (newText != originalText) {
- QSaveFile saveFile(compFile);
+ QSaveFile saveFile(componentFilePath);
if (saveFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
saveFile.write(newText.toUtf8());
saveFile.commit();
} else {
- qWarning() << __FUNCTION__ << "Failed to save changes to:" << compFile;
+ qWarning() << __FUNCTION__ << "Failed to save changes to:" << componentFilePath;
}
}
diff --git a/src/plugins/qmldesigner/components/formeditor/backgroundaction.cpp b/src/plugins/qmldesigner/components/formeditor/backgroundaction.cpp
index 37dfafad9a2..07a16de7bbd 100644
--- a/src/plugins/qmldesigner/components/formeditor/backgroundaction.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/backgroundaction.cpp
@@ -3,6 +3,8 @@
#include "backgroundaction.h"
+#include <theme.h>
+
#include <utils/stylehelper.h>
#include <QComboBox>
@@ -28,6 +30,14 @@ QIcon iconForColor(const QColor &color) {
image.fill(0);
QPainter p(&image);
+ if (color == BackgroundAction::ContextImage) {
+ const QString unicode = Theme::getIconUnicode(Theme::Icon::textures_medium);
+ const QString fontName = "qtds_propertyIconFont.ttf";
+ QIcon icon = Utils::StyleHelper::getIconFromIconFont(fontName, unicode, 10, 10, Qt::white);
+
+ return icon;
+ }
+
p.fillRect(2, 2, size - 4, size - 4, Qt::black);
if (color.alpha() == 0) {
@@ -70,13 +80,13 @@ QList<QColor> BackgroundAction::colors()
{
static QColor alphaZero(Qt::transparent);
static QList<QColor> colorList = {alphaZero,
+ QColor(BackgroundAction::ContextImage),
QColor(Qt::black),
QColor(0x4c4e50),
QColor(Qt::darkGray),
QColor(Qt::lightGray),
QColor(Qt::white)};
-
return colorList;
}
diff --git a/src/plugins/qmldesigner/components/formeditor/backgroundaction.h b/src/plugins/qmldesigner/components/formeditor/backgroundaction.h
index 34bd4cd3229..c6eeb212fe4 100644
--- a/src/plugins/qmldesigner/components/formeditor/backgroundaction.h
+++ b/src/plugins/qmldesigner/components/formeditor/backgroundaction.h
@@ -11,14 +11,12 @@ namespace QmlDesigner {
class BackgroundAction : public QWidgetAction
{
- enum BackgroundType {
- CheckboardBackground,
- WhiteBackground,
- BlackBackground
- };
+ enum BackgroundType { CheckboardBackground, WhiteBackground, BlackBackground };
Q_OBJECT
public:
+ enum SpecialColor { ContextImage = Qt::yellow };
+
explicit BackgroundAction(QObject *parent);
void setColor(const QColor &color);
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.cpp
index 1e67884ad8d..9549ce9dd46 100644
--- a/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.cpp
@@ -2,9 +2,13 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "formeditorgraphicsview.h"
+#include "backgroundaction.h"
#include "formeditoritem.h"
#include "formeditorwidget.h"
#include "navigation2d.h"
+
+#include <theme.h>
+
#include <utils/hostosinfo.h>
#include <QAction>
@@ -198,10 +202,28 @@ void FormEditorGraphicsView::drawBackground(QPainter *painter, const QRectF &rec
painter->save();
painter->setBrushOrigin(0, 0);
- painter->fillRect(rectangle.intersected(rootItemRect()), backgroundBrush());
// paint rect around editable area
- painter->setPen(Qt::black);
- painter->drawRect(rootItemRect());
+
+ if (backgroundBrush().color() == BackgroundAction::ContextImage) {
+ painter->fillRect(rectangle.intersected(rootItemRect()), Qt::gray);
+ painter->setOpacity(0.5);
+ if (!m_backgroundImage.isNull())
+ painter->drawImage(rootItemRect().topLeft() + m_backgroundImage.offset(),
+ m_backgroundImage);
+ painter->setOpacity(1.0);
+ } else {
+ painter->fillRect(rectangle.intersected(rootItemRect()), backgroundBrush());
+ }
+
+ QPen pen(Utils::creatorTheme()->color(Utils::Theme::QmlDesigner_FormEditorSelectionColor));
+
+ pen.setStyle(Qt::DotLine);
+ pen.setWidth(1);
+
+ painter->setPen(pen);
+
+ painter->drawRect(rootItemRect().adjusted(-1, -1, 0, 0));
+
painter->restore();
}
@@ -210,6 +232,17 @@ void FormEditorGraphicsView::frame(const QRectF &boundingRect)
fitInView(boundingRect, Qt::KeepAspectRatio);
}
+void FormEditorGraphicsView::setBackgoundImage(const QImage &image)
+{
+ m_backgroundImage = image;
+ update();
+}
+
+QImage FormEditorGraphicsView::backgroundImage() const
+{
+ return m_backgroundImage;
+}
+
void FormEditorGraphicsView::setZoomFactor(double zoom)
{
resetTransform();
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.h b/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.h
index 28a49b00466..60e02582cd1 100644
--- a/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.h
+++ b/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.h
@@ -28,6 +28,9 @@ public:
void setZoomFactor(double zoom);
void frame(const QRectF &bbox);
+ void setBackgoundImage(const QImage &image);
+ QImage backgroundImage() const;
+
protected:
bool eventFilter(QObject *watched, QEvent *event) override;
void wheelEvent(QWheelEvent *event) override;
@@ -45,6 +48,7 @@ private:
Panning m_isPanning = Panning::NotStarted;
QPoint m_panningStartPosition;
QRectF m_rootItemRect;
+ QImage m_backgroundImage;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp
index 5661e4ff793..6b580a7d5f3 100644
--- a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp
@@ -63,6 +63,8 @@ void FormEditorView::modelAttached(Model *model)
if (!isEnabled())
return;
+ m_formEditorWidget->setBackgoundImage({});
+
temporaryBlockView();
setupFormEditorWidget();
@@ -649,6 +651,10 @@ void FormEditorView::auxiliaryDataChanged(const ModelNode &node,
if (FormEditorItem *editorItem = scene()->itemForQmlItemNode(item))
editorItem->setFrameColor(data.value<QColor>());
}
+
+ if (key == contextImageProperty) {
+ m_formEditorWidget->setBackgoundImage(data.value<QImage>());
+ }
}
static void updateTransitions(FormEditorScene *scene, const QmlItemNode &qmlItemNode)
@@ -784,6 +790,11 @@ void FormEditorView::exportAsImage()
m_formEditorWidget->exportAsImage(m_scene->rootFormEditorItem()->boundingRect());
}
+QImage FormEditorView::takeFormEditorScreenshot()
+{
+ return m_formEditorWidget->takeFormEditorScreenshot();
+}
+
QPicture FormEditorView::renderToPicture() const
{
return m_formEditorWidget->renderToPicture();
@@ -954,6 +965,11 @@ void FormEditorView::setupRootItemSize()
formEditorWidget()->setRootItemRect(rootQmlNode.instanceBoundingRect());
formEditorWidget()->centerScene();
+
+ auto contextImage = rootModelNode().auxiliaryData(contextImageProperty);
+
+ if (contextImage)
+ m_formEditorWidget->setBackgoundImage(contextImage.value().value<QImage>());
}
}
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorview.h b/src/plugins/qmldesigner/components/formeditor/formeditorview.h
index f97959acb37..1a9f15d016e 100644
--- a/src/plugins/qmldesigner/components/formeditor/formeditorview.h
+++ b/src/plugins/qmldesigner/components/formeditor/formeditorview.h
@@ -117,6 +117,7 @@ public:
void setGotoErrorCallback(std::function<void(int, int)> gotoErrorCallback);
void exportAsImage();
+ QImage takeFormEditorScreenshot();
QPicture renderToPicture() const;
void setupFormEditorWidget();
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorwidget.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorwidget.cpp
index bfc03d2b237..ef7ed1d52d4 100644
--- a/src/plugins/qmldesigner/components/formeditor/formeditorwidget.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/formeditorwidget.cpp
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "formeditorwidget.h"
+#include "backgroundaction.h"
#include "designeractionmanager.h"
#include "designericons.h"
#include "designersettings.h"
@@ -332,11 +333,13 @@ void FormEditorWidget::changeBackgound(const QColor &color)
if (color.alpha() == 0) {
m_graphicsView->activateCheckboardBackground();
if (m_formEditorView->rootModelNode().hasAuxiliaryData(formeditorColorProperty)) {
- m_formEditorView->rootModelNode().setAuxiliaryData(formeditorColorProperty, {});
+ m_formEditorView->rootModelNode().setAuxiliaryDataWithoutLock(formeditorColorProperty,
+ {});
}
} else {
m_graphicsView->activateColoredBackground(color);
- m_formEditorView->rootModelNode().setAuxiliaryData(formeditorColorProperty, color);
+ m_formEditorView->rootModelNode().setAuxiliaryDataWithoutLock(formeditorColorProperty,
+ color);
}
}
@@ -397,6 +400,10 @@ void FormEditorWidget::updateActions()
} else {
m_backgroundAction->setColor(Qt::transparent);
}
+
+ if (m_formEditorView->rootModelNode().hasAuxiliaryData(contextImageProperty))
+ m_backgroundAction->setColor(BackgroundAction::ContextImage);
+
} else {
m_rootWidthAction->clearLineEditText();
m_rootHeightAction->clearLineEditText();
@@ -540,6 +547,40 @@ void FormEditorWidget::exportAsImage(const QRectF &boundingRect)
}
}
+QImage FormEditorWidget::takeFormEditorScreenshot()
+{
+ const QRectF boundingRect = m_formEditorView->scene()->rootFormEditorItem()->boundingRect();
+
+ m_formEditorView->scene()->manipulatorLayerItem()->setVisible(false);
+ QImage image(boundingRect.size().toSize(), QImage::Format_ARGB32);
+
+ if (!m_graphicsView->backgroundImage().isNull()) {
+ image = m_graphicsView->backgroundImage();
+ const QPoint offset = m_graphicsView->backgroundImage().offset();
+
+ QPainter painter(&image);
+ QTransform viewportTransform = m_graphicsView->viewportTransform();
+
+ m_graphicsView->render(&painter,
+ QRectF(-offset, boundingRect.size()),
+ viewportTransform.mapRect(boundingRect).toRect());
+
+ image.setOffset(offset);
+
+ } else {
+ QPainter painter(&image);
+ QTransform viewportTransform = m_graphicsView->viewportTransform();
+
+ m_graphicsView->render(&painter,
+ QRectF(0, 0, image.width(), image.height()),
+ viewportTransform.mapRect(boundingRect).toRect());
+ }
+
+ m_formEditorView->scene()->manipulatorLayerItem()->setVisible(true);
+
+ return image;
+}
+
QPicture FormEditorWidget::renderToPicture() const
{
QPicture picture;
@@ -568,6 +609,17 @@ bool FormEditorWidget::errorMessageBoxIsVisible() const
return m_documentErrorWidget && m_documentErrorWidget->isVisible();
}
+void FormEditorWidget::setBackgoundImage(const QImage &image)
+{
+ m_graphicsView->setBackgoundImage(image);
+ updateActions();
+}
+
+QImage FormEditorWidget::backgroundImage() const
+{
+ return m_graphicsView->backgroundImage();
+}
+
DocumentWarningWidget *FormEditorWidget::errorWidget()
{
if (m_documentErrorWidget.isNull()) {
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorwidget.h b/src/plugins/qmldesigner/components/formeditor/formeditorwidget.h
index 5e4e29d1553..8135ce81393 100644
--- a/src/plugins/qmldesigner/components/formeditor/formeditorwidget.h
+++ b/src/plugins/qmldesigner/components/formeditor/formeditorwidget.h
@@ -63,12 +63,17 @@ public:
void showWarningMessageBox(const QList<DocumentMessage> &warnings);
void exportAsImage(const QRectF &boundingRect);
+
+ QImage takeFormEditorScreenshot();
QPicture renderToPicture() const;
FormEditorGraphicsView *graphicsView() const;
bool errorMessageBoxIsVisible() const;
+ void setBackgoundImage(const QImage &image);
+ QImage backgroundImage() const;
+
protected:
QActionGroup *toolActionGroup() const;
DocumentWarningWidget *errorWidget();
diff --git a/src/plugins/qmldesigner/components/integration/designdocument.cpp b/src/plugins/qmldesigner/components/integration/designdocument.cpp
index 089efb87cdd..7bbbac5b253 100644
--- a/src/plugins/qmldesigner/components/integration/designdocument.cpp
+++ b/src/plugins/qmldesigner/components/integration/designdocument.cpp
@@ -61,7 +61,7 @@ namespace QmlDesigner {
DesignDocument acts as a facade to a model representing a qml document,
and the different views/widgets accessing it.
*/
-DesignDocument::DesignDocument(ProjectStorage<Sqlite::Database> &projectStorage,
+DesignDocument::DesignDocument(ProjectStorageDependencies projectStorageDependencies,
ExternalDependenciesInterface &externalDependencies)
: m_documentModel(
Model::create("QtQuick.Item", 1, 0, nullptr, std::make_unique<ModelResourceManagement>()))
@@ -69,7 +69,7 @@ DesignDocument::DesignDocument(ProjectStorage<Sqlite::Database> &projectStorage,
, m_rewriterView(new RewriterView(externalDependencies, RewriterView::Amend))
, m_documentLoaded(false)
, m_currentTarget(nullptr)
- , m_projectStorage(projectStorage)
+ , m_projectStorageDependencies(projectStorageDependencies)
, m_externalDependencies{externalDependencies}
{
}
diff --git a/src/plugins/qmldesigner/components/integration/designdocument.h b/src/plugins/qmldesigner/components/integration/designdocument.h
index 2fbc9060e45..7c0fe3941f8 100644
--- a/src/plugins/qmldesigner/components/integration/designdocument.h
+++ b/src/plugins/qmldesigner/components/integration/designdocument.h
@@ -39,7 +39,7 @@ class QMLDESIGNERCOMPONENTS_EXPORT DesignDocument : public QObject
Q_OBJECT
public:
- DesignDocument(ProjectStorage<Sqlite::Database> &projectStorage,
+ DesignDocument(ProjectStorageDependencies projectStorageDependencies,
ExternalDependenciesInterface &externalDependencies);
~DesignDocument() override;
@@ -143,7 +143,7 @@ private: // variables
QScopedPointer<RewriterView> m_rewriterView;
bool m_documentLoaded;
ProjectExplorer::Target *m_currentTarget;
- ProjectStorage<Sqlite::Database> &m_projectStorage;
+ ProjectStorageDependencies m_projectStorageDependencies;
ExternalDependenciesInterface &m_externalDependencies;
};
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp
index f8a9fd97718..29fff4b359a 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp
@@ -4,14 +4,15 @@
#include "itemlibraryassetimportdialog.h"
#include "ui_itemlibraryassetimportdialog.h"
-#include "qmldesignerplugin.h"
-#include "qmldesignerconstants.h"
-#include "model.h"
-#include "nodemetainfo.h"
-#include "variantproperty.h"
+#include <model.h>
+#include <model/modelutils.h>
+#include <nodemetainfo.h>
+#include <qmldesignerconstants.h>
+#include <qmldesignerplugin.h>
+#include <variantproperty.h>
-#include "utils/outputformatter.h"
-#include "theme.h"
+#include <theme.h>
+#include <utils/outputformatter.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectmanager.h>
@@ -283,7 +284,7 @@ void ItemLibraryAssetImportDialog::updateImport(const ModelNode &updateNode,
QString errorMsg;
const ModelNode &node = updateNode;
if (node.hasMetaInfo()) {
- QString compFileName = node.metaInfo().componentFileName(); // absolute path
+ QString compFileName = ModelUtils::componentFilePath(node); // absolute path
bool preselectNodeSource = false;
if (compFileName.isEmpty()) {
// Node is not a file component, so we have to check if the current doc itself is
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp
index d370f6d4547..3082ee442ac 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp
@@ -62,7 +62,7 @@ void ItemLibraryView::modelAttached(Model *model)
m_widget->setModel(model);
updateImports();
if (model)
- m_widget->updatePossibleImports(difference(model->possibleImports(), model->imports()));
+ m_widget->updatePossibleImports(set_difference(model->possibleImports(), model->imports()));
m_hasErrors = !rewriterView()->errors().isEmpty();
m_widget->setFlowMode(QmlItemNode(rootModelNode()).isFlowView());
}
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp
index 1cbde45ba0b..d2435fbf15a 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp
@@ -338,7 +338,7 @@ void ItemLibraryWidget::updateModel()
void ItemLibraryWidget::updatePossibleImports(const Imports &possibleImports)
{
- m_addModuleModel->update(difference(possibleImports, m_model->imports()));
+ m_addModuleModel->update(set_difference(possibleImports, m_model->imports()));
delayedUpdateModel();
}
@@ -358,7 +358,7 @@ void ItemLibraryWidget::handlePriorityImportsChanged()
{
if (!m_itemLibraryInfo.isNull()) {
m_addModuleModel->setPriorityImports(m_itemLibraryInfo->priorityImports());
- m_addModuleModel->update(difference(m_model->possibleImports(), m_model->imports()));
+ m_addModuleModel->update(set_difference(m_model->possibleImports(), m_model->imports()));
}
}
diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp b/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp
index 933686febda..7d3eb7efe6d 100644
--- a/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp
+++ b/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp
@@ -548,7 +548,7 @@ void MaterialEditorView::setupQmlBackend()
TypeName diffClassName;
if (NodeMetaInfo metaInfo = m_selectedMaterial.metaInfo()) {
diffClassName = metaInfo.typeName();
- for (const NodeMetaInfo &metaInfo : metaInfo.classHierarchy()) {
+ for (const NodeMetaInfo &metaInfo : metaInfo.selfAndPrototypes()) {
if (PropertyEditorQmlBackend::checkIfUrlExists(qmlSpecificsUrl))
break;
qmlSpecificsUrl = PropertyEditorQmlBackend::getQmlFileUrl(metaInfo.typeName()
diff --git a/src/plugins/qmldesigner/components/navigator/choosefrompropertylistdialog.cpp b/src/plugins/qmldesigner/components/navigator/choosefrompropertylistdialog.cpp
index 304ff91fcda..04c2ebd9e65 100644
--- a/src/plugins/qmldesigner/components/navigator/choosefrompropertylistdialog.cpp
+++ b/src/plugins/qmldesigner/components/navigator/choosefrompropertylistdialog.cpp
@@ -90,7 +90,7 @@ ChooseFromPropertyListFilter::ChooseFromPropertyListFilter(const NodeMetaInfo &i
} else if (insertInfo.isQtQuick3DParticles3DParticle3D()) {
if (parentInfo.isQtQuick3DParticles3DParticleEmitter3D())
propertyList.append("particle");
- } else if (insertInfo.isQtQuick3DParticleAbstractShape()) {
+ } else if (insertInfo.isQtQuick3DParticlesAbstractShape()) {
if (parentInfo.isQtQuick3DParticles3DParticleEmitter3D()
|| parentInfo.isQtQuick3DParticles3DAttractor3D())
propertyList.append("shape");
@@ -100,9 +100,6 @@ ChooseFromPropertyListFilter::ChooseFromPropertyListFilter(const NodeMetaInfo &i
} else if (insertInfo.typeName().startsWith("ComponentBundles.MaterialBundle")) {
if (parentInfo.isQtQuick3DModel())
propertyList.append("materials");
- } else if (insertInfo.isEffectMaker()) {
- if (parentInfo.isQtQuickItem())
- propertyList.append("effect");
} else if (insertInfo.isQtQuick3DBakedLightmap()) {
if (parentInfo.isQtQuick3DModel())
propertyList.append("bakedLightmap");
diff --git a/src/plugins/qmldesigner/components/navigator/navigatorsearchwidget.cpp b/src/plugins/qmldesigner/components/navigator/navigatorsearchwidget.cpp
index 360c893c2d7..24d4377ef29 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatorsearchwidget.cpp
+++ b/src/plugins/qmldesigner/components/navigator/navigatorsearchwidget.cpp
@@ -8,6 +8,7 @@
#include <QAction>
#include <QBoxLayout>
+#include <QKeyEvent>
#include <QLabel>
#include <QStyle>
#include <QToolButton>
@@ -71,7 +72,7 @@ LineEdit::LineEdit(QWidget *parent)
setFixedHeight(29);
}
-void LineEdit::resizeEvent(QResizeEvent *)
+void LineEdit::resizeEvent([[maybe_unused]] QResizeEvent *event)
{
QSize hint = clearButton->sizeHint();
int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
@@ -80,6 +81,31 @@ void LineEdit::resizeEvent(QResizeEvent *)
(rect().bottom() + 1 - hint.height()) / 2);
}
+void LineEdit::keyPressEvent(QKeyEvent *event)
+{
+ if (event->key() == Qt::Key_Escape && event->modifiers() == Qt::NoModifier) {
+ clear();
+ event->accept();
+ return;
+ }
+ QLineEdit::keyPressEvent(event);
+}
+
+void LineEdit::paintEvent(QPaintEvent *event)
+{
+ if (text().isEmpty()) {
+ QPalette p(palette());
+ p.setColor(QPalette::Active,
+ QPalette::PlaceholderText,
+ Utils::creatorTheme()->color(Utils::Theme::DSplaceholderTextColor));
+ p.setColor(QPalette::Inactive,
+ QPalette::PlaceholderText,
+ Utils::creatorTheme()->color(Utils::Theme::DSplaceholderTextColor));
+ setPalette(p);
+ }
+ QLineEdit::paintEvent(event);
+}
+
void LineEdit::updateClearButton(const QString& text)
{
clearButton->setVisible(!text.isEmpty());
diff --git a/src/plugins/qmldesigner/components/navigator/navigatorsearchwidget.h b/src/plugins/qmldesigner/components/navigator/navigatorsearchwidget.h
index 8b6da49cb3f..6cc375fd552 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatorsearchwidget.h
+++ b/src/plugins/qmldesigner/components/navigator/navigatorsearchwidget.h
@@ -19,7 +19,9 @@ public:
LineEdit(QWidget *parent = nullptr);
protected:
- void resizeEvent(QResizeEvent *);
+ void resizeEvent(QResizeEvent *event) override;
+ void keyPressEvent(QKeyEvent *event) override;
+ void paintEvent(QPaintEvent *event) override;
private slots:
void updateClearButton(const QString &text);
diff --git a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
index ceccf25554c..456f44e43c6 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
+++ b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
@@ -2,28 +2,29 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "navigatorview.h"
-#include "navigatortreemodel.h"
-#include "navigatorwidget.h"
-#include "qmldesignerconstants.h"
-#include "qmldesignericons.h"
-#include "qmldesignerplugin.h"
-#include "assetslibrarywidget.h"
-#include "commontypecache.h"
-#include "nameitemdelegate.h"
#include "iconcheckboxitemdelegate.h"
+#include "nameitemdelegate.h"
+#include "navigatortreemodel.h"
+#include "navigatorwidget.h"
+#include <assetslibrarywidget.h>
#include <bindingproperty.h>
-#include <designmodecontext.h>
+#include <commontypecache.h>
#include <designersettings.h>
+#include <designmodecontext.h>
#include <itemlibraryinfo.h>
-#include <nodeproperty.h>
+#include <model/modelutils.h>
+#include <nodeinstanceview.h>
#include <nodelistproperty.h>
-#include <variantproperty.h>
+#include <nodeproperty.h>
+#include <qmldesignerconstants.h>
+#include <qmldesignericons.h>
+#include <qmldesignerplugin.h>
#include <qmlitemnode.h>
#include <rewritingexception.h>
-#include <nodeinstanceview.h>
#include <theme.h>
+#include <variantproperty.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/icore.h>
@@ -286,7 +287,6 @@ void NavigatorView::dragStarted(QMimeData *mimeData)
if (assetType == Constants::MIME_TYPE_ASSET_EFFECT) {
// We use arbitrary type name because at this time we don't have effect maker
// specific type
- m_widget->setDragType(Storage::Info::EffectMaker);
m_widget->update();
} else if (assetType == Constants::MIME_TYPE_ASSET_TEXTURE3D) {
m_widget->setDragType(Constants::MIME_TYPE_ASSET_TEXTURE3D);
@@ -450,7 +450,7 @@ void NavigatorView::changeToComponent(const QModelIndex &index)
const ModelNode doubleClickNode = modelNodeForIndex(index);
if (doubleClickNode.metaInfo().isFileComponent())
Core::EditorManager::openEditor(Utils::FilePath::fromString(
- doubleClickNode.metaInfo().componentFileName()),
+ ModelUtils::componentFilePath(doubleClickNode)),
Utils::Id(),
Core::EditorManager::DoNotMakeVisible);
}
@@ -468,7 +468,7 @@ QAbstractItemModel *NavigatorView::currentModel() const
const ProjectExplorer::FileNode *NavigatorView::fileNodeForModelNode(const ModelNode &node) const
{
- QString filename = node.metaInfo().componentFileName();
+ QString filename = ModelUtils::componentFilePath(node);
Utils::FilePath filePath = Utils::FilePath::fromString(filename);
ProjectExplorer::Project *currentProject = ProjectExplorer::ProjectManager::projectForFile(
filePath);
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp
index 3b991a5f622..eaa5ef95738 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp
@@ -958,7 +958,7 @@ void PropertyEditorQmlBackend::setValueforAuxiliaryProperties(const QmlObjectNod
QUrl PropertyEditorQmlBackend::getQmlUrlForMetaInfo(const NodeMetaInfo &metaInfo, TypeName &className)
{
if (metaInfo.isValid()) {
- const NodeMetaInfos hierarchy = metaInfo.classHierarchy();
+ const NodeMetaInfos hierarchy = metaInfo.selfAndPrototypes();
for (const NodeMetaInfo &info : hierarchy) {
QUrl fileUrl = fileToUrl(locateQmlFile(info, QString::fromUtf8(qmlFileName(info))));
if (fileUrl.isValid()) {
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp
index 3f3ddaaf162..f042df5241b 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp
@@ -339,7 +339,7 @@ void PropertyEditorValue::resetValue()
void PropertyEditorValue::setEnumeration(const QString &scope, const QString &name)
{
- Enumeration newEnumeration(scope, name);
+ Enumeration newEnumeration(scope.toUtf8(), name.toUtf8());
setValueWithEmit(QVariant::fromValue(newEnumeration));
}
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp
index 5d00f373c49..ba6078a778a 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp
@@ -450,7 +450,7 @@ void PropertyEditorView::setupQmlBackend()
TypeName diffClassName;
if (commonAncestor.isValid()) {
diffClassName = commonAncestor.typeName();
- const NodeMetaInfos hierarchy = commonAncestor.classHierarchy();
+ const NodeMetaInfos hierarchy = commonAncestor.selfAndPrototypes();
for (const NodeMetaInfo &metaInfo : hierarchy) {
if (PropertyEditorQmlBackend::checkIfUrlExists(qmlSpecificsFile))
break;
diff --git a/src/plugins/qmldesigner/components/resources/dockwidgets.css b/src/plugins/qmldesigner/components/resources/dockwidgets.css
index 4ff1b46f52d..2fc05b6014f 100644
--- a/src/plugins/qmldesigner/components/resources/dockwidgets.css
+++ b/src/plugins/qmldesigner/components/resources/dockwidgets.css
@@ -93,6 +93,20 @@ ADS--TitleBarButton:press {
background: creatorTheme.DStitleBarButtonPress;
}
+#floatingTitleMaxButton {
+ margin: 1px;
+ background: none;
+ border: none;
+}
+
+#floatingTitleMaxButton:hover {
+ background: creatorTheme.DStitleBarButtonHover;
+}
+
+#floatingTitleMaxButton:pressed {
+ background: creatorTheme.DStitleBarButtonPress;
+}
+
QScrollArea#dockWidgetScrollArea {
background-color: creatorTheme.DSpanelBackground;
padding: 0px;
@@ -139,3 +153,180 @@ ADS--DockAreaTitleBar {
ADS--DockAreaWidget[focused="true"] ADS--DockAreaTitleBar {
border-bottom-color: creatorTheme.DStabFocusBackground;
}
+
+ADS--AutoHideTab {
+ qproperty-iconSize: 16px 16px; /* this is optional in case you would like to change icon size */
+ background: none;
+ border: none;
+ padding-left: 2px;
+ padding-right: 0px;
+ text-align: center;
+ min-height: 20px;
+ padding-bottom: 2px;
+}
+
+ADS--AutoHideTab:hover {
+ color: creatorTheme.DSinteraction;
+}
+
+ADS--AutoHideTab[iconOnly="false"][sideBarLocation="0"],
+ADS--AutoHideTab[iconOnly="false"][sideBarLocation="2"] {
+ border-top: 6px solid rgba(0, 0, 0, 48);
+}
+
+ADS--AutoHideTab[iconOnly="false"][sideBarLocation="1"],
+ADS--AutoHideTab[iconOnly="false"][sideBarLocation="3"] {
+ border-bottom: 6px solid rgba(0, 0, 0, 48);
+}
+
+ADS--AutoHideTab:hover[iconOnly="false"][sideBarLocation="0"],
+ADS--AutoHideTab:hover[iconOnly="false"][sideBarLocation="2"],
+ADS--AutoHideTab[iconOnly="false"][sideBarLocation="0"][activeTab="true"],
+ADS--AutoHideTab[iconOnly="false"][sideBarLocation="2"][activeTab="true"] {
+ border-top: 6px solid creatorTheme.DSinteraction;
+}
+
+ADS--AutoHideTab:hover[iconOnly="false"][sideBarLocation="1"],
+ADS--AutoHideTab:hover[iconOnly="false"][sideBarLocation="3"],
+ADS--AutoHideTab[iconOnly="false"][sideBarLocation="1"][activeTab="true"],
+ADS--AutoHideTab[iconOnly="false"][sideBarLocation="3"][activeTab="true"] {
+ border-bottom: 6px solid creatorTheme.DSinteraction;
+}
+
+/* Auto hide tabs with icon only */
+ADS--AutoHideTab[iconOnly="true"][sideBarLocation="0"] {
+ border-top: 6px solid rgba(0, 0, 0, 48);
+}
+
+ADS--AutoHideTab[iconOnly="true"][sideBarLocation="1"] {
+ border-left: 6px solid rgba(0, 0, 0, 48);
+}
+
+ADS--AutoHideTab[iconOnly="true"][sideBarLocation="2"] {
+ border-right: 6px solid rgba(0, 0, 0, 48);
+}
+
+ADS--AutoHideTab[iconOnly="true"][sideBarLocation="3"] {
+ border-bottom: 6px solid rgba(0, 0, 0, 48);
+}
+
+/* Auto hide tabs with icon only hover */
+ADS--AutoHideTab:hover[iconOnly="true"][sideBarLocation="0"],
+ADS--AutoHideTab[iconOnly="true"][sideBarLocation="0"][activeTab="true"] {
+ border-top: 6px solid creatorTheme.DSinteraction;
+}
+
+ADS--AutoHideTab:hover[iconOnly="true"][sideBarLocation="1"],
+ADS--AutoHideTab[iconOnly="true"][sideBarLocation="1"][activeTab="true"] {
+ border-left: 6px solid creatorTheme.DSinteraction;
+}
+
+ADS--AutoHideTab:hover[iconOnly="true"][sideBarLocation="2"],
+ADS--AutoHideTab[iconOnly="true"][sideBarLocation="2"][activeTab="true"] {
+ border-right: 6px solid creatorTheme.DSinteraction;
+}
+
+ADS--AutoHideTab:hover[iconOnly="true"][sideBarLocation="3"],
+ADS--AutoHideTab[iconOnly="true"][sideBarLocation="3"][activeTab="true"] {
+ border-bottom: 6px solid creatorTheme.DSinteraction;
+}
+
+/* AutoHideSideBar */
+ADS--AutoHideSideBar {
+ background: palette(window);
+ border: none;
+ qproperty-spacing: 12;
+}
+
+#sideTabsContainerWidget {
+ background: transparent;
+}
+
+ADS--AutoHideSideBar[sideBarLocation="0"] {
+ border-bottom: 1px solid palette(dark);
+}
+
+ADS--AutoHideSideBar[sideBarLocation="1"] {
+ border-right: 1px solid palette(dark);
+}
+
+ADS--AutoHideSideBar[sideBarLocation="2"] {
+ border-left: 1px solid palette(dark);
+}
+
+ADS--AutoHideSideBar[sideBarLocation="3"] {
+ border-top: 1px solid palette(dark);
+}
+
+/* AutoHideDockContainer */
+ADS--AutoHideDockContainer {
+ background: palette(window);
+}
+
+ADS--AutoHideDockContainer ADS--DockAreaTitleBar {
+ background: creatorTheme.DSinteraction;
+ padding: 0px;
+ border: none;
+}
+
+/*
+ * This is required because the ADS--DockAreaWidget[focused="true"] will
+ * overwrite the ADS--AutoHideDockContainer ADS--DockAreaTitleBar rule
+ */
+ADS--AutoHideDockContainer ADS--DockAreaWidget[focused="true"] ADS--DockAreaTitleBar {
+ background: creatorTheme.DSinteraction;
+ padding: 0px;
+ border: none;
+}
+
+#autoHideTitleLabel {
+ padding-left: 4px;
+ color: palette(light);
+}
+
+/* AutoHideDockContainer titlebar buttons */
+#dockAreaAutoHideButton {
+ /*qproperty-icon: url(:/ads/images/vs-pin-button.svg);*/
+ qproperty-iconSize: 16px;
+}
+
+ADS--AutoHideDockContainer #dockAreaAutoHideButton {
+ /*qproperty-icon: url(:/ads/images/vs-pin-button-pinned-focused.svg);*/
+ qproperty-iconSize: 16px;
+}
+
+ADS--AutoHideDockContainer #dockAreaCloseButton{
+ /*qproperty-icon: url(:/ads/images/close-button-focused.svg)*/
+}
+
+ADS--AutoHideDockContainer ADS--TitleBarButton:hover {
+ background: rgba(255, 255, 255, 48);
+}
+
+ads--CAutoHideDockContainer ADS--TitleBarButton:pressed {
+ background: rgba(255, 255, 255, 96);
+}
+
+/* AutoHideDockContainer Titlebar and Buttons */
+
+/* ResizeHandle */
+ADS--ResizeHandle {
+ background: palette(window);
+}
+
+
+ADS--AutoHideDockContainer[sideBarLocation="0"] ADS--ResizeHandle {
+ border-top: 1px solid palette(dark);
+}
+
+ADS--AutoHideDockContainer[sideBarLocation="1"] ADS--ResizeHandle {
+ border-left: 1px solid palette(dark);
+}
+
+ADS--AutoHideDockContainer[sideBarLocation="2"] ADS--ResizeHandle {
+ border-right: 1px solid palette(dark);
+}
+
+ADS--AutoHideDockContainer[sideBarLocation="3"] ADS--ResizeHandle {
+ border-top: 1px solid palette(dark);
+}
diff --git a/src/plugins/qmldesigner/components/texteditor/texteditorview.cpp b/src/plugins/qmldesigner/components/texteditor/texteditorview.cpp
index 6c6102036ac..0826df54848 100644
--- a/src/plugins/qmldesigner/components/texteditor/texteditorview.cpp
+++ b/src/plugins/qmldesigner/components/texteditor/texteditorview.cpp
@@ -16,12 +16,13 @@
#include <nodelistproperty.h>
#include <qmldesignerplugin.h>
-#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
+#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/icore.h>
+#include <coreplugin/modemanager.h>
#include <texteditor/texteditor.h>
#include <texteditor/texteditorconstants.h>
@@ -97,9 +98,12 @@ void TextEditorView::modelAboutToBeDetached(Model *model)
m_widget->setTextEditor(nullptr);
// in case the user closed it explicit we do not want to do anything with the editor
- if (TextEditor::BaseTextEditor *textEditor =
- QmlDesignerPlugin::instance()->currentDesignDocument()->textEditor()) {
- QmlDesignerPlugin::instance()->emitCurrentTextEditorChanged(textEditor);
+ if (Core::ModeManager::currentModeId() == Core::Constants::MODE_DESIGN) {
+ if (TextEditor::BaseTextEditor *textEditor = QmlDesignerPlugin::instance()
+ ->currentDesignDocument()
+ ->textEditor()) {
+ QmlDesignerPlugin::instance()->emitCurrentTextEditorChanged(textEditor);
+ }
}
}
diff --git a/src/plugins/qmldesigner/components/textureeditor/textureeditorview.cpp b/src/plugins/qmldesigner/components/textureeditor/textureeditorview.cpp
index 98601ce45ed..73c3c65f30e 100644
--- a/src/plugins/qmldesigner/components/textureeditor/textureeditorview.cpp
+++ b/src/plugins/qmldesigner/components/textureeditor/textureeditorview.cpp
@@ -416,7 +416,7 @@ void TextureEditorView::setupQmlBackend()
TypeName diffClassName;
if (NodeMetaInfo metaInfo = m_selectedTexture.metaInfo()) {
diffClassName = metaInfo.typeName();
- for (const NodeMetaInfo &metaInfo : metaInfo.classHierarchy()) {
+ for (const NodeMetaInfo &metaInfo : metaInfo.selfAndPrototypes()) {
if (PropertyEditorQmlBackend::checkIfUrlExists(qmlSpecificsUrl))
break;
qmlSpecificsUrl = PropertyEditorQmlBackend::getQmlFileUrl(metaInfo.typeName()
diff --git a/src/plugins/qmldesigner/components/toolbar/toolbarbackend.cpp b/src/plugins/qmldesigner/components/toolbar/toolbarbackend.cpp
index c917dfe8a84..99c46b43b33 100644
--- a/src/plugins/qmldesigner/components/toolbar/toolbarbackend.cpp
+++ b/src/plugins/qmldesigner/components/toolbar/toolbarbackend.cpp
@@ -132,17 +132,21 @@ void CrumbleBarModel::onCrumblePathElementClicked(int i)
WorkspaceModel::WorkspaceModel(QObject *)
{
- connect(designModeWidget(), &Internal::DesignModeWidget::initialized, this, [this]() {
+ auto connectDockManager = [this]() -> bool {
const auto dockManager = designModeWidget()->dockManager();
+ if (!dockManager)
+ return false;
connect(dockManager, &ADS::DockManager::workspaceListChanged, this, [this]() {
beginResetModel();
endResetModel();
});
-
beginResetModel();
endResetModel();
- });
+ return true;
+ };
+ if (!connectDockManager())
+ connect(designModeWidget(), &Internal::DesignModeWidget::initialized, this, connectDockManager);
}
int WorkspaceModel::rowCount(const QModelIndex &) const
@@ -288,19 +292,25 @@ ToolBarBackend::ToolBarBackend(QObject *parent)
this,
&ToolBarBackend::currentStyleChanged);
- connect(designModeWidget(), &Internal::DesignModeWidget::initialized, this, [this]() {
+ auto connectDockManager = [this]() -> bool {
const auto dockManager = designModeWidget()->dockManager();
-
- connect(dockManager, &ADS::DockManager::workspaceLoaded, this, [this](const QString &) {
- emit currentWorkspaceChanged();
- });
-
- connect(dockManager, &ADS::DockManager::workspaceListChanged, this, [this]() {
- emit currentWorkspaceChanged();
- });
-
+ if (!dockManager)
+ return false;
+
+ connect(dockManager,
+ &ADS::DockManager::workspaceLoaded,
+ this,
+ &ToolBarBackend::currentWorkspaceChanged);
+ connect(dockManager,
+ &ADS::DockManager::workspaceListChanged,
+ this,
+ &ToolBarBackend::currentWorkspaceChanged);
emit currentWorkspaceChanged();
- });
+ return true;
+ };
+
+ if (!connectDockManager())
+ connect(designModeWidget(), &Internal::DesignModeWidget::initialized, this, connectDockManager);
auto editorManager = Core::EditorManager::instance();
diff --git a/src/plugins/qmldesigner/designercore/include/auxiliarydataproperties.h b/src/plugins/qmldesigner/designercore/include/auxiliarydataproperties.h
index 4c12af14fef..b93626a331b 100644
--- a/src/plugins/qmldesigner/designercore/include/auxiliarydataproperties.h
+++ b/src/plugins/qmldesigner/designercore/include/auxiliarydataproperties.h
@@ -108,6 +108,8 @@ inline constexpr AuxiliaryDataKeyView rotBlockProperty{AuxiliaryDataType::NodeIn
inline constexpr AuxiliaryDataKeyView languageProperty{AuxiliaryDataType::Temporary, "language"};
inline constexpr AuxiliaryDataKeyView bakeLightsManualProperty{AuxiliaryDataType::Document,
"bakeLightsManual"};
+inline constexpr AuxiliaryDataKeyView contextImageProperty{AuxiliaryDataType::Temporary,
+ "contextImage"};
// Most material preview aux properties are duplicated as document and instance types, as they
// are both required to be persistent and used at runtime to control material preview rendering
diff --git a/src/plugins/qmldesigner/designercore/include/import.h b/src/plugins/qmldesigner/designercore/include/import.h
index f0a5b8e7700..5dbab393d21 100644
--- a/src/plugins/qmldesigner/designercore/include/import.h
+++ b/src/plugins/qmldesigner/designercore/include/import.h
@@ -44,6 +44,11 @@ public:
class QMLDESIGNERCORE_EXPORT Import
{
+ using Imports = QList<Import>;
+ QMLDESIGNERCORE_EXPORT friend Imports set_strict_difference(const Imports &first,
+ const Imports &second);
+ enum class Type { Empty, Library, File };
+
public:
Import() = default;
@@ -51,14 +56,14 @@ public:
static Import createFileImport(const QString &file, const QString &version = QString(), const QString &alias = QString(), const QStringList &importPaths = QStringList());
static Import empty();
- bool isEmpty() const { return m_url.isEmpty() && m_file.isEmpty(); }
- bool isFileImport() const { return m_url.isEmpty() && !m_file.isEmpty(); }
- bool isLibraryImport() const { return !m_url.isEmpty() && m_file.isEmpty(); }
+ bool isEmpty() const { return m_type == Type::Empty; }
+ bool isFileImport() const { return m_type == Type::File; }
+ bool isLibraryImport() const { return m_type == Type::Library; }
bool hasVersion() const { return !m_version.isEmpty(); }
bool hasAlias() const { return !m_alias.isEmpty(); }
- const QString &url() const { return m_url; }
- const QString &file() const { return m_file; }
+ const QString &url() const { return m_type == Type::Library ? m_url : emptyString; }
+ const QString &file() const { return m_type == Type::File ? m_url : emptyString; }
const QString &version() const { return m_version; }
const QString &alias() const { return m_alias; }
const QStringList &importPaths() const { return m_importPathList; }
@@ -76,32 +81,40 @@ public:
friend bool operator==(const Import &first, const Import &second)
{
- return first.m_url == second.m_url && first.m_file == second.m_file
+ return first.m_url == second.m_url && first.m_type == second.m_type
&& (first.m_version == second.m_version || first.m_version.isEmpty()
|| second.m_version.isEmpty());
}
friend bool operator<(const Import &first, const Import &second)
{
- return std::tie(first.m_url, first.m_file) < std::tie(second.m_url, second.m_file);
+ return std::tie(first.m_url, first.m_type) < std::tie(second.m_url, second.m_type);
}
private:
- Import(const QString &url, const QString &file, const QString &version, const QString &alias, const QStringList &importPaths);
+ Import(const QString &url,
+ const QString &version,
+ const QString &alias,
+ const QStringList &importPaths,
+ Type type);
private:
+ inline static const QString emptyString;
QString m_url;
- QString m_file;
QString m_version;
QString m_alias;
QStringList m_importPathList;
+ Type m_type = Type::Empty;
};
QMLDESIGNERCORE_EXPORT size_t qHash(const Import &import);
using Imports = QList<Import>;
-QMLDESIGNERCORE_EXPORT Imports difference(const Imports &first, const Imports &second);
+QMLDESIGNERCORE_EXPORT Imports set_difference(const Imports &first, const Imports &second);
+QMLDESIGNERCORE_EXPORT Imports set_stict_difference(const Imports &first, const Imports &second);
+QMLDESIGNERCORE_EXPORT Imports set_union(const Imports &first, const Imports &second);
+QMLDESIGNERCORE_EXPORT Imports set_intersection(const Imports &first, const Imports &second);
template<typename Callable>
void differenceCall(const Imports &first, const Imports &second, Callable callable)
diff --git a/src/plugins/qmldesigner/designercore/include/model.h b/src/plugins/qmldesigner/designercore/include/model.h
index 3dbb0cceac2..1577fc24319 100644
--- a/src/plugins/qmldesigner/designercore/include/model.h
+++ b/src/plugins/qmldesigner/designercore/include/model.h
@@ -8,6 +8,7 @@
#include <documentmessage.h>
#include <model/modelresourcemanagementinterface.h>
#include <projectstorage/projectstoragefwd.h>
+#include <projectstorageids.h>
#include <QMimeData>
#include <QObject>
@@ -62,12 +63,16 @@ class QMLDESIGNERCORE_EXPORT Model : public QObject
public:
enum ViewNotification { NotifyView, DoNotNotifyView };
- Model(ProjectStorageType &projectStorage,
+ Model(ProjectStorageDependencies projectStorageDependencies,
const TypeName &type,
int major = 1,
int minor = 1,
Model *metaInfoProxyModel = nullptr,
std::unique_ptr<ModelResourceManagementInterface> resourceManagement = {});
+ Model(ProjectStorageDependencies projectStorageDependencies,
+ Utils::SmallStringView typeName,
+ Imports imports,
+ const QUrl &fileUrl);
Model(const TypeName &typeName,
int major = 1,
int minor = 1,
@@ -86,17 +91,29 @@ public:
new Model(typeName, major, minor, metaInfoProxyModel, std::move(resourceManagement)));
}
- static ModelPointer create(ProjectStorageType &projectStorage,
+ static ModelPointer create(ProjectStorageDependencies projectStorageDependencies,
+ Utils::SmallStringView typeName,
+ Imports imports,
+ const QUrl &fileUrl)
+ {
+ return ModelPointer(new Model(projectStorageDependencies, typeName, imports, fileUrl));
+ }
+ static ModelPointer create(ProjectStorageDependencies m_projectStorageDependencies,
const TypeName &typeName,
int major = 1,
int minor = 1,
std::unique_ptr<ModelResourceManagementInterface> resourceManagement = {})
{
- return ModelPointer(
- new Model(projectStorage, typeName, major, minor, nullptr, std::move(resourceManagement)));
+ return ModelPointer(new Model(m_projectStorageDependencies,
+ typeName,
+ major,
+ minor,
+ nullptr,
+ std::move(resourceManagement)));
}
QUrl fileUrl() const;
+ SourceId fileUrlSourceId() const;
void setFileUrl(const QUrl &url);
const MetaInfo metaInfo() const;
@@ -105,12 +122,16 @@ public:
bool hasNodeMetaInfo(const TypeName &typeName, int majorVersion = -1, int minorVersion = -1) const;
void setMetaInfo(const MetaInfo &metaInfo);
+ NodeMetaInfo boolMetaInfo() const;
NodeMetaInfo flowViewFlowActionAreaMetaInfo() const;
NodeMetaInfo flowViewFlowDecisionMetaInfo() const;
NodeMetaInfo flowViewFlowItemMetaInfo() const;
NodeMetaInfo flowViewFlowTransitionMetaInfo() const;
NodeMetaInfo flowViewFlowWildcardMetaInfo() const;
NodeMetaInfo fontMetaInfo() const;
+ NodeMetaInfo qmlQtObjectMetaInfo() const;
+ NodeMetaInfo qtQmlModelsListModelMetaInfo() const;
+ NodeMetaInfo qtQmlModelsListElementMetaInfo() const;
NodeMetaInfo qtQuick3DBakedLightmapMetaInfo() const;
NodeMetaInfo qtQuick3DDefaultMaterialMetaInfo() const;
NodeMetaInfo qtQuick3DMaterialMetaInfo() const;
@@ -145,6 +166,7 @@ public:
QHash<QStringView, ModelNode> idModelNodeDict();
ModelNode createModelNode(const TypeName &typeName);
+ void changeRootNodeType(const TypeName &type);
void removeModelNodes(ModelNodes nodes,
BypassModelResourceManagement = BypassModelResourceManagement::No);
@@ -157,7 +179,7 @@ public:
const Imports &imports() const;
const Imports &possibleImports() const;
const Imports &usedImports() const;
- void changeImports(const Imports &importsToBeAdded, const Imports &importsToBeRemoved);
+ void changeImports(Imports importsToBeAdded, Imports importsToBeRemoved);
void setPossibleImports(Imports possibleImports);
void setUsedImports(Imports usedImports);
bool hasImport(const Import &import, bool ignoreAlias = true, bool allowHigherVersion = false) const;
@@ -196,6 +218,8 @@ public:
void endDrag();
NotNullPointer<const ProjectStorageType> projectStorage() const;
+ const PathCacheType &pathCache() const;
+ PathCacheType &pathCache();
private:
template<const auto &moduleName, const auto &typeName>
diff --git a/src/plugins/qmldesigner/designercore/include/modelfwd.h b/src/plugins/qmldesigner/designercore/include/modelfwd.h
index 44154ce10b1..2483893d9a8 100644
--- a/src/plugins/qmldesigner/designercore/include/modelfwd.h
+++ b/src/plugins/qmldesigner/designercore/include/modelfwd.h
@@ -16,6 +16,9 @@ using PropertyTypeList = QList<PropertyName>;
using IdName = QByteArray;
class Model;
class ModelNode;
+class NonLockingMutex;
+template<typename ProjectStorage, typename Mutex = NonLockingMutex>
+class SourcePathCache;
struct ModelDeleter
{
@@ -35,10 +38,18 @@ constexpr bool useProjectStorage()
#ifdef QDS_MODEL_USE_PROJECTSTORAGEINTERFACE
using ProjectStorageType = ProjectStorageInterface;
+using PathCacheType = SourcePathCacheInterface;
#else
using ProjectStorageType = ProjectStorage<Sqlite::Database>;
+using PathCacheType = SourcePathCache<ProjectStorageType, NonLockingMutex>;
#endif
+struct ProjectStorageDependencies
+{
+ ProjectStorageType &storage;
+ PathCacheType &cache;
+};
+
enum class PropertyType {
None,
Variant,
diff --git a/src/plugins/qmldesigner/designercore/include/modelnode.h b/src/plugins/qmldesigner/designercore/include/modelnode.h
index 657093b0ac0..9c4b8fb4efe 100644
--- a/src/plugins/qmldesigner/designercore/include/modelnode.h
+++ b/src/plugins/qmldesigner/designercore/include/modelnode.h
@@ -81,7 +81,7 @@ public:
ModelNode &operator=(const ModelNode &) = default;
ModelNode(ModelNode &&) = default;
ModelNode &operator=(ModelNode &&) noexcept = default;
- ~ModelNode();
+ ~ModelNode() = default;
TypeName type() const;
QString simplifiedTypeName() const;
@@ -182,6 +182,7 @@ public:
QVariant auxiliaryDataWithDefault(AuxiliaryDataKeyView key) const;
QVariant auxiliaryDataWithDefault(AuxiliaryDataKeyDefaultValue key) const;
void setAuxiliaryData(AuxiliaryDataKeyView key, const QVariant &data) const;
+ void setAuxiliaryDataWithoutLock(AuxiliaryDataKeyView key, const QVariant &data) const;
void setAuxiliaryData(AuxiliaryDataType type, Utils::SmallStringView name, const QVariant &data) const;
void setAuxiliaryDataWithoutLock(AuxiliaryDataType type,
Utils::SmallStringView name,
@@ -267,7 +268,7 @@ public:
}
private: // functions
- Internal::InternalNodePointer internalNode() const;
+ Internal::InternalNodePointer internalNode() const { return m_internalNode; }
bool hasLocked() const;
diff --git a/src/plugins/qmldesigner/designercore/include/nodemetainfo.h b/src/plugins/qmldesigner/designercore/include/nodemetainfo.h
index 55ce166d904..0ee4e19fe37 100644
--- a/src/plugins/qmldesigner/designercore/include/nodemetainfo.h
+++ b/src/plugins/qmldesigner/designercore/include/nodemetainfo.h
@@ -53,6 +53,8 @@ public:
TypeId id() const { return m_typeId; }
bool isFileComponent() const;
+ bool isProjectComponent() const;
+ bool isInProjectModule() const;
bool hasProperty(::Utils::SmallStringView propertyName) const;
PropertyMetaInfos properties() const;
PropertyMetaInfos localProperties() const;
@@ -63,8 +65,8 @@ public:
PropertyMetaInfo defaultProperty() const;
bool hasDefaultProperty() const;
- std::vector<NodeMetaInfo> classHierarchy() const;
- std::vector<NodeMetaInfo> superClasses() const;
+ std::vector<NodeMetaInfo> selfAndPrototypes() const;
+ std::vector<NodeMetaInfo> prototypes() const;
NodeMetaInfo commonBase(const NodeMetaInfo &metaInfo) const;
bool defaultPropertyIsComponent() const;
@@ -74,6 +76,10 @@ public:
int majorVersion() const;
int minorVersion() const;
+ Storage::Info::ExportedTypeNames allExportedTypeNames() const;
+ Storage::Info::ExportedTypeNames exportedTypeNamesForSourceId(SourceId sourceId) const;
+
+ SourceId sourceId() const;
QString componentFileName() const;
bool isBasedOn(const NodeMetaInfo &metaInfo) const;
@@ -107,7 +113,6 @@ public:
bool isAlias() const;
bool isBool() const;
bool isColor() const;
- bool isEffectMaker() const;
bool isFloat() const;
bool isFlowViewFlowActionArea() const;
bool isFlowViewFlowDecision() const;
@@ -121,10 +126,10 @@ public:
bool isInteger() const;
bool isLayoutable() const;
bool isListOrGridView() const;
+ bool isNumber() const;
bool isQmlComponent() const;
bool isQtMultimediaSoundEffect() const;
bool isQtObject() const;
- bool isQtQuick3D() const;
bool isQtQuick3DBakedLightmap() const;
bool isQtQuick3DBuffer() const;
bool isQtQuick3DCamera() const;
@@ -137,7 +142,7 @@ public:
bool isQtQuick3DMaterial() const;
bool isQtQuick3DModel() const;
bool isQtQuick3DNode() const;
- bool isQtQuick3DParticleAbstractShape() const;
+ bool isQtQuick3DParticlesAbstractShape() const;
bool isQtQuick3DParticles3DAffector3D() const;
bool isQtQuick3DParticles3DAttractor3D() const;
bool isQtQuick3DParticles3DParticle3D() const;
diff --git a/src/plugins/qmldesigner/designercore/include/projectstorageids.h b/src/plugins/qmldesigner/designercore/include/projectstorageids.h
index b4e4aa11f82..bc66e0d2b20 100644
--- a/src/plugins/qmldesigner/designercore/include/projectstorageids.h
+++ b/src/plugins/qmldesigner/designercore/include/projectstorageids.h
@@ -5,6 +5,8 @@
#include <sqlite/sqliteids.h>
+#include <utils/span.h>
+
namespace QmlDesigner {
enum class BasicIdType {
@@ -48,6 +50,7 @@ using SourceIds = std::vector<SourceId>;
using ModuleId = Sqlite::BasicId<BasicIdType::Module, int>;
using ModuleIds = std::vector<ModuleId>;
+using ModuleIdSpan = Utils::span<ModuleId>;
using ProjectPartId = Sqlite::BasicId<BasicIdType::ProjectPartId>;
using ProjectPartIds = std::vector<ProjectPartId>;
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
index fee28a9dd3a..bdbb2b7ee7b 100644
--- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
@@ -3,66 +3,67 @@
#include "nodeinstanceview.h"
-#include "abstractproperty.h"
-#include "bindingproperty.h"
-#include "captureddatacommand.h"
-#include "changeauxiliarycommand.h"
-#include "changebindingscommand.h"
-#include "changefileurlcommand.h"
-#include "changeidscommand.h"
-#include "changelanguagecommand.h"
-#include "changenodesourcecommand.h"
-#include "changepreviewimagesizecommand.h"
-#include "changeselectioncommand.h"
-#include "changestatecommand.h"
-#include "changevaluescommand.h"
-#include "childrenchangedcommand.h"
-#include "clearscenecommand.h"
-#include "completecomponentcommand.h"
-#include "componentcompletedcommand.h"
-#include "connectionmanagerinterface.h"
-#include "createinstancescommand.h"
-#include "createscenecommand.h"
-#include "debugoutputcommand.h"
-#include "informationchangedcommand.h"
-#include "imageutils.h"
-#include "inputeventcommand.h"
-#include "nodeabstractproperty.h"
-#include "nodeinstanceserverproxy.h"
-#include "nodelistproperty.h"
-#include "pixmapchangedcommand.h"
-#include "puppettocreatorcommand.h"
-#include "qml3dnode.h"
-#include "qmlchangeset.h"
-#include "qmldesignerconstants.h"
-#include "qmlstate.h"
-#include "qmltimeline.h"
-#include "qmltimelinekeyframegroup.h"
-#include "qmlvisualnode.h"
-#include "removeinstancescommand.h"
-#include "removepropertiescommand.h"
-#include "removesharedmemorycommand.h"
-#include "reparentinstancescommand.h"
-#include "scenecreatedcommand.h"
-#include "statepreviewimagechangedcommand.h"
-#include "tokencommand.h"
-#include "update3dviewstatecommand.h"
-#include "valueschangedcommand.h"
-#include "variantproperty.h"
-#include "view3dactioncommand.h"
-#include "requestmodelnodepreviewimagecommand.h"
-#include "nanotracecommand.h"
-#include "nanotrace/nanotrace.h"
+#include <abstractproperty.h>
+#include <bindingproperty.h>
+#include <captureddatacommand.h>
+#include <changeauxiliarycommand.h>
+#include <changebindingscommand.h>
+#include <changefileurlcommand.h>
+#include <changeidscommand.h>
+#include <changelanguagecommand.h>
+#include <changenodesourcecommand.h>
+#include <changepreviewimagesizecommand.h>
+#include <changeselectioncommand.h>
+#include <changestatecommand.h>
+#include <changevaluescommand.h>
+#include <childrenchangedcommand.h>
+#include <clearscenecommand.h>
+#include <completecomponentcommand.h>
+#include <componentcompletedcommand.h>
+#include <connectionmanagerinterface.h>
+#include <createinstancescommand.h>
+#include <createscenecommand.h>
+#include <debugoutputcommand.h>
+#include <imageutils.h>
+#include <informationchangedcommand.h>
+#include <inputeventcommand.h>
+#include <nanotrace/nanotrace.h>
+#include <nanotracecommand.h>
+#include <nodeabstractproperty.h>
+#include <nodeinstanceserverproxy.h>
+#include <nodelistproperty.h>
+#include <pixmapchangedcommand.h>
+#include <puppettocreatorcommand.h>
+#include <qml3dnode.h>
+#include <qmlchangeset.h>
+#include <qmldesignerconstants.h>
+#include <qmlstate.h>
+#include <qmltimeline.h>
+#include <qmltimelinekeyframegroup.h>
+#include <qmlvisualnode.h>
+#include <removeinstancescommand.h>
+#include <removepropertiescommand.h>
+#include <removesharedmemorycommand.h>
+#include <reparentinstancescommand.h>
+#include <requestmodelnodepreviewimagecommand.h>
+#include <scenecreatedcommand.h>
+#include <statepreviewimagechangedcommand.h>
+#include <tokencommand.h>
+#include <update3dviewstatecommand.h>
+#include <valueschangedcommand.h>
+#include <variantproperty.h>
+#include <view3dactioncommand.h>
#include <auxiliarydataproperties.h>
#include <designersettings.h>
#include <externaldependenciesinterface.h>
#include <metainfo.h>
#include <model.h>
+#include <model/modelutils.h>
#include <modelnode.h>
#include <nodehints.h>
-#include <rewriterview.h>
#include <qmlitemnode.h>
+#include <rewriterview.h>
#include <utils/hdrimage.h>
@@ -1077,18 +1078,20 @@ CreateSceneCommand NodeInstanceView::createCreateSceneCommand()
if (parentTakesOverRendering(instance.modelNode()))
nodeFlags |= InstanceContainer::ParentTakesOverRendering;
+ const auto modelNode = instance.modelNode();
InstanceContainer container(instance.instanceId(),
- instance.modelNode().type(),
- instance.modelNode().majorVersion(),
- instance.modelNode().minorVersion(),
- instance.modelNode().metaInfo().componentFileName(),
- instance.modelNode().nodeSource(),
+ modelNode.type(),
+ modelNode.majorVersion(),
+ modelNode.minorVersion(),
+ ModelUtils::componentFilePath(modelNode),
+ modelNode.nodeSource(),
nodeSourceType,
nodeMetaType,
nodeFlags);
- if (!parentIsBehavior(instance.modelNode()))
+ if (!parentIsBehavior(modelNode)) {
instanceContainerList.append(container);
+ }
}
QVector<ReparentContainer> reparentContainerList;
@@ -1243,12 +1246,13 @@ CreateInstancesCommand NodeInstanceView::createCreateInstancesCommand(const QLis
if (parentTakesOverRendering(instance.modelNode()))
nodeFlags |= InstanceContainer::ParentTakesOverRendering;
+ const auto modelNode = instance.modelNode();
InstanceContainer container(instance.instanceId(),
- instance.modelNode().type(),
- instance.modelNode().majorVersion(),
- instance.modelNode().minorVersion(),
- instance.modelNode().metaInfo().componentFileName(),
- instance.modelNode().nodeSource(),
+ modelNode.type(),
+ modelNode.majorVersion(),
+ modelNode.minorVersion(),
+ ModelUtils::componentFilePath(modelNode),
+ modelNode.nodeSource(),
nodeSourceType,
nodeMetaType,
nodeFlags);
@@ -1303,17 +1307,20 @@ ChangeValuesCommand NodeInstanceView::createChangeValueCommand(const QList<Varia
{
QVector<PropertyValueContainer> containerList;
- const bool reflectionFlag = m_puppetTransaction.isValid() && (!currentTimeline().isValid() || !currentTimeline().isRecording());
+ bool reflectionFlag = m_puppetTransaction.isValid()
+ && (!currentTimeline().isValid() || !currentTimeline().isRecording());
for (const VariantProperty &property : propertyList) {
ModelNode node = property.parentModelNode();
+ if (QmlPropertyChanges::isValidQmlPropertyChanges(node))
+ reflectionFlag = false;
+
if (node.isValid() && hasInstanceForModelNode(node)) {
NodeInstance instance = instanceForModelNode(node);
PropertyValueContainer container(instance.instanceId(), property.name(), property.value(), property.dynamicTypeName());
container.setReflectionFlag(reflectionFlag);
containerList.append(container);
}
-
}
return ChangeValuesCommand(containerList);
@@ -1783,9 +1790,9 @@ void NodeInstanceView::requestModelNodePreviewImage(const ModelNode &node,
if (renderInstance.isValid())
renderItemId = renderInstance.instanceId();
if (renderNode.isComponent())
- componentPath = renderNode.metaInfo().componentFileName();
+ componentPath = ModelUtils::componentFilePath(renderNode);
} else if (node.isComponent()) {
- componentPath = node.metaInfo().componentFileName();
+ componentPath = ModelUtils::componentFilePath(node);
}
const double ratio = m_externalDependencies.formEditorDevicePixelRatio();
const int dim = Constants::MODELNODE_PREVIEW_IMAGE_DIMENSIONS * ratio;
diff --git a/src/plugins/qmldesigner/designercore/metainfo/nodehints.cpp b/src/plugins/qmldesigner/designercore/metainfo/nodehints.cpp
index ece5b4bf6f1..8cdc590135f 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/nodehints.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/nodehints.cpp
@@ -80,7 +80,7 @@ QmlDesigner::NodeHints::NodeHints(const ModelNode &node) : m_modelNode(node)
if (!itemLibraryEntryList.isEmpty())
m_hints = itemLibraryEntryList.constFirst().hints();
} else { /* If we have meta information we run the complete type hierarchy and check for hints */
- const auto classHierarchy = m_modelNode.metaInfo().classHierarchy();
+ const auto classHierarchy = m_modelNode.metaInfo().selfAndPrototypes();
for (const NodeMetaInfo &metaInfo : classHierarchy) {
QList <ItemLibraryEntry> itemLibraryEntryList = libraryInfo->entriesForType(
metaInfo.typeName(), metaInfo.majorVersion(), metaInfo.minorVersion());
diff --git a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp
index fd25d9c450d..5121e6a663c 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp
@@ -1426,6 +1426,24 @@ bool NodeMetaInfo::isFileComponent() const
return isValid() && m_privateData->isFileComponent();
}
+bool NodeMetaInfo::isProjectComponent() const
+{
+ if constexpr (useProjectStorage()) {
+ return isValid() && bool(typeData().traits & Storage::TypeTraits::IsProjectComponent);
+ }
+
+ return false;
+}
+
+bool NodeMetaInfo::isInProjectModule() const
+{
+ if constexpr (useProjectStorage()) {
+ return isValid() && bool(typeData().traits & Storage::TypeTraits::IsInProjectModule);
+ }
+
+ return false;
+}
+
bool NodeMetaInfo::hasProperty(Utils::SmallStringView propertyName) const
{
if constexpr (useProjectStorage())
@@ -1568,31 +1586,30 @@ PropertyMetaInfo NodeMetaInfo::defaultProperty() const
bool NodeMetaInfo::hasDefaultProperty() const
{
if constexpr (useProjectStorage())
- return bool(typeData().defaultPropertyId);
+ return isValid() && bool(typeData().defaultPropertyId);
else
return !defaultPropertyName().isEmpty();
}
-NodeMetaInfos NodeMetaInfo::classHierarchy() const
+std::vector<NodeMetaInfo> NodeMetaInfo::selfAndPrototypes() const
{
if constexpr (useProjectStorage()) {
- NodeMetaInfos hierarchy;
- const auto typeIds = m_projectStorage->prototypeAndSelfIds(m_typeId);
- hierarchy.reserve(typeIds.size());
-
- for (TypeId typeId : typeIds)
- hierarchy.emplace_back(typeId, m_projectStorage);
-
- return hierarchy;
+ if (isValid()) {
+ return Utils::transform<NodeMetaInfos>(
+ m_projectStorage->prototypeAndSelfIds(m_typeId), [&](TypeId typeId) {
+ return NodeMetaInfo{typeId, m_projectStorage};
+ });
+ }
} else {
if (isValid()) {
NodeMetaInfos hierarchy = {*this};
Model *model = m_privateData->model();
- for (const TypeDescription &type : m_privateData->prototypes())
+ for (const TypeDescription &type : m_privateData->prototypes()) {
hierarchy.emplace_back(model,
type.className.toUtf8(),
type.majorVersion,
type.minorVersion);
+ }
return hierarchy;
}
@@ -1601,17 +1618,15 @@ NodeMetaInfos NodeMetaInfo::classHierarchy() const
return {};
}
-NodeMetaInfos NodeMetaInfo::superClasses() const
+NodeMetaInfos NodeMetaInfo::prototypes() const
{
if constexpr (useProjectStorage()) {
- NodeMetaInfos hierarchy;
- const auto typeIds = m_projectStorage->prototypeIds(m_typeId);
- hierarchy.reserve(typeIds.size());
-
- for (TypeId typeId : typeIds)
- hierarchy.emplace_back(typeId, m_projectStorage);
-
- return hierarchy;
+ if (isValid()) {
+ return Utils::transform<NodeMetaInfos>(
+ m_projectStorage->prototypeIds(m_typeId), [&](TypeId typeId) {
+ return NodeMetaInfo{typeId, m_projectStorage};
+ });
+ }
} else {
if (isValid()) {
NodeMetaInfos hierarchy;
@@ -1673,18 +1688,61 @@ int NodeMetaInfo::minorVersion() const
return -1;
}
+Storage::Info::ExportedTypeNames NodeMetaInfo::allExportedTypeNames() const
+{
+ if constexpr (useProjectStorage()) {
+ if (isValid()) {
+ return m_projectStorage->exportedTypeNames(m_typeId);
+ }
+ }
+
+ return {};
+}
+
+Storage::Info::ExportedTypeNames NodeMetaInfo::exportedTypeNamesForSourceId(SourceId sourceId) const
+{
+ if constexpr (useProjectStorage()) {
+ if (isValid()) {
+ return m_projectStorage->exportedTypeNames(m_typeId, sourceId);
+ }
+ }
+
+ return {};
+}
+
+SourceId NodeMetaInfo::sourceId() const
+{
+ if constexpr (useProjectStorage()) {
+ if (isValid()) {
+ return typeData().sourceId;
+ }
+ }
+
+ return SourceId{};
+}
+
QString NodeMetaInfo::componentFileName() const
{
- if (isValid())
- return m_privateData->componentFileName();
+ if constexpr (!useProjectStorage()) {
+ if (isValid()) {
+ return m_privateData->componentFileName();
+ }
+ } else {
+ if (isValid()) {
+ return m_privateData->componentFileName();
+ }
+ }
return {};
}
QString NodeMetaInfo::importDirectoryPath() const
{
- if (isValid())
- return m_privateData->importDirectoryPath();
+ if constexpr (!useProjectStorage()) {
+ if (isValid()) {
+ return m_privateData->importDirectoryPath();
+ }
+ }
return {};
}
@@ -1718,7 +1776,7 @@ bool NodeMetaInfo::isSubclassOf(const TypeName &type, int majorVersion, int mino
stringIdentifier(type, majorVersion, minorVersion)))
return false; //take a shortcut - optimization
- const NodeMetaInfos superClassList = superClasses();
+ const NodeMetaInfos superClassList = prototypes();
for (const NodeMetaInfo &superClass : superClassList) {
if (superClass.m_privateData->cleverCheckType(type)) {
m_privateData->prototypeCachePositives().insert(
@@ -1732,8 +1790,27 @@ bool NodeMetaInfo::isSubclassOf(const TypeName &type, int majorVersion, int mino
bool NodeMetaInfo::isSuitableForMouseAreaFill() const
{
- return isSubclassOf("QtQuick.Item") && !isSubclassOf("QtQuick.MouseArea")
- && !isSubclassOf("QtQuick.Controls.Control") && !isSubclassOf("QtQuick.Templates.Control");
+ if constexpr (useProjectStorage()) {
+ if (!isValid()) {
+ return false;
+ }
+
+ using namespace Storage::Info;
+ auto itemId = m_projectStorage->commonTypeId<QtQuick, Item>();
+ auto mouseAreaId = m_projectStorage->commonTypeId<QtQuick, MouseArea>();
+ auto controlsControlId = m_projectStorage->commonTypeId<QtQuick_Controls, Control>();
+ auto templatesControlId = m_projectStorage->commonTypeId<QtQuick_Templates, Control>();
+
+ return m_projectStorage->isBasedOn(m_typeId,
+ itemId,
+ mouseAreaId,
+ controlsControlId,
+ templatesControlId);
+ } else {
+ return isSubclassOf("QtQuick.Item") && !isSubclassOf("QtQuick.MouseArea")
+ && !isSubclassOf("QtQuick.Controls.Control")
+ && !isSubclassOf("QtQuick.Templates.Control");
+ }
}
bool NodeMetaInfo::isBasedOn(const NodeMetaInfo &metaInfo) const
@@ -1926,6 +2003,10 @@ namespace {
template<const char *moduleName, const char *typeName>
bool isBasedOnCommonType(NotNullPointer<const ProjectStorageType> projectStorage, TypeId typeId)
{
+ if (!typeId) {
+ return false;
+ }
+
auto base = projectStorage->commonTypeId<moduleName, typeName>();
return projectStorage->isBasedOn(typeId, base);
@@ -1935,6 +2016,10 @@ bool isBasedOnCommonType(NotNullPointer<const ProjectStorageType> projectStorage
bool NodeMetaInfo::isGraphicalItem() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid()) {
+ return false;
+ }
+
using namespace Storage::Info;
auto itemId = m_projectStorage->commonTypeId<QtQuick, Item>();
auto windowId = m_projectStorage->commonTypeId<QtQuick_Window, Window>();
@@ -1963,6 +2048,10 @@ bool NodeMetaInfo::isQtObject() const
bool NodeMetaInfo::isLayoutable() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid()) {
+ return false;
+ }
+
using namespace Storage::Info;
auto positionerId = m_projectStorage->commonTypeId<QtQuick, Positioner>();
auto layoutId = m_projectStorage->commonTypeId<QtQuick_Layouts, Layout>();
@@ -1990,6 +2079,10 @@ bool NodeMetaInfo::isQtQuickLayoutsLayout() const
bool NodeMetaInfo::isView() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid()) {
+ return false;
+ }
+
using namespace Storage::Info;
auto listViewId = m_projectStorage->commonTypeId<QtQuick, ListView>();
auto gridViewId = m_projectStorage->commonTypeId<QtQuick, GridView>();
@@ -2018,7 +2111,7 @@ bool NodeMetaInfo::isVector2D() const
{
if constexpr (useProjectStorage()) {
using namespace Storage::Info;
- return isTypeId(m_typeId, m_projectStorage->commonTypeId<QtQuick, vector2d>());
+ return isValid() && isTypeId(m_typeId, m_projectStorage->commonTypeId<QtQuick, vector2d>());
} else {
if (!m_privateData)
return false;
@@ -2033,7 +2126,7 @@ bool NodeMetaInfo::isVector3D() const
{
if constexpr (useProjectStorage()) {
using namespace Storage::Info;
- return isTypeId(m_typeId, m_projectStorage->commonTypeId<QtQuick, vector3d>());
+ return isValid() && isTypeId(m_typeId, m_projectStorage->commonTypeId<QtQuick, vector3d>());
} else {
if (!m_privateData)
return false;
@@ -2048,7 +2141,7 @@ bool NodeMetaInfo::isVector4D() const
{
if constexpr (useProjectStorage()) {
using namespace Storage::Info;
- return isTypeId(m_typeId, m_projectStorage->commonTypeId<QtQuick, vector4d>());
+ return isValid() && isTypeId(m_typeId, m_projectStorage->commonTypeId<QtQuick, vector4d>());
} else {
if (!m_privateData)
return false;
@@ -2134,6 +2227,10 @@ bool NodeMetaInfo::isQtQuickTimelineKeyframeGroup() const
bool NodeMetaInfo::isListOrGridView() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid()) {
+ return false;
+ }
+
using namespace Storage::Info;
auto listViewId = m_projectStorage->commonTypeId<QtQuick, ListView>();
auto gridViewId = m_projectStorage->commonTypeId<QtQuick, GridView>();
@@ -2143,6 +2240,31 @@ bool NodeMetaInfo::isListOrGridView() const
}
}
+bool NodeMetaInfo::isNumber() const
+{
+ if constexpr (useProjectStorage()) {
+ if (!isValid()) {
+ return false;
+ }
+
+ using namespace Storage::Info;
+ auto intId = m_projectStorage->builtinTypeId<int>();
+ auto uintId = m_projectStorage->builtinTypeId<uint>();
+ auto floatId = m_projectStorage->builtinTypeId<float>();
+ auto doubleId = m_projectStorage->builtinTypeId<double>();
+
+ return isTypeId(m_typeId, intId, uintId, floatId, doubleId);
+ } else {
+ if (!isValid()) {
+ return false;
+ }
+
+ auto type = simplifiedTypeName();
+
+ return type == "int" || type == "uint" || type == "float" || type == "double";
+ }
+}
+
bool NodeMetaInfo::isQtQuickExtrasPicture() const
{
if constexpr (useProjectStorage()) {
@@ -2177,7 +2299,11 @@ bool NodeMetaInfo::isQtQuickBorderImage() const
bool NodeMetaInfo::isAlias() const
{
- return isValid() && m_privateData->qualfiedTypeName() == "alias";
+ if constexpr (useProjectStorage()) {
+ return false; // there is no type alias
+ } else {
+ return isValid() && m_privateData->qualfiedTypeName() == "alias";
+ }
}
bool NodeMetaInfo::isQtQuickPositioner() const
@@ -2322,7 +2448,7 @@ bool NodeMetaInfo::isQtQuick3DParticles3DAttractor3D() const
}
}
-bool NodeMetaInfo::isQtQuick3DParticleAbstractShape() const
+bool NodeMetaInfo::isQtQuick3DParticlesAbstractShape() const
{
if constexpr (useProjectStorage()) {
using namespace Storage::Info;
@@ -2437,6 +2563,10 @@ bool NodeMetaInfo::isQtMultimediaSoundEffect() const
bool NodeMetaInfo::isFlowViewItem() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid()) {
+ return false;
+ }
+
using namespace Storage::Info;
auto flowItemId = m_projectStorage->commonTypeId<FlowView, FlowItem>();
auto flowWildcardId = m_projectStorage->commonTypeId<FlowView, FlowWildcard>();
@@ -2540,7 +2670,7 @@ bool NodeMetaInfo::isFont() const
{
if constexpr (useProjectStorage()) {
using namespace Storage::Info;
- return isTypeId(m_typeId, m_projectStorage->commonTypeId<QtQuick, font>());
+ return isValid() && isTypeId(m_typeId, m_projectStorage->commonTypeId<QtQuick, font>());
} else {
return isValid() && m_privateData->qualfiedTypeName() == "font";
}
@@ -2550,7 +2680,7 @@ bool NodeMetaInfo::isColor() const
{
if constexpr (useProjectStorage()) {
using namespace Storage::Info;
- return isTypeId(m_typeId, m_projectStorage->builtinTypeId<QColor>());
+ return isValid() && isTypeId(m_typeId, m_projectStorage->builtinTypeId<QColor>());
} else {
if (!isValid())
return false;
@@ -2561,18 +2691,11 @@ bool NodeMetaInfo::isColor() const
}
}
-bool NodeMetaInfo::isEffectMaker() const
-{
- // We use arbitrary type name because at this time we don't have effect maker
- // specific type
- return typeName() == QString::fromUtf8(Storage::Info::EffectMaker);
-}
-
bool NodeMetaInfo::isBool() const
{
if constexpr (useProjectStorage()) {
using namespace Storage::Info;
- return isTypeId(m_typeId, m_projectStorage->builtinTypeId<bool>());
+ return isValid() && isTypeId(m_typeId, m_projectStorage->builtinTypeId<bool>());
} else {
if (!isValid())
return false;
@@ -2587,7 +2710,7 @@ bool NodeMetaInfo::isInteger() const
{
if constexpr (useProjectStorage()) {
using namespace Storage::Info;
- return isTypeId(m_typeId, m_projectStorage->builtinTypeId<int>());
+ return isValid() && isTypeId(m_typeId, m_projectStorage->builtinTypeId<int>());
} else {
if (!isValid())
return false;
@@ -2601,6 +2724,10 @@ bool NodeMetaInfo::isInteger() const
bool NodeMetaInfo::isFloat() const
{
if constexpr (useProjectStorage()) {
+ if (!isValid()) {
+ return false;
+ }
+
using namespace Storage::Info;
auto floatId = m_projectStorage->builtinTypeId<float>();
auto doubleId = m_projectStorage->builtinTypeId<double>();
@@ -2620,7 +2747,7 @@ bool NodeMetaInfo::isVariant() const
{
if constexpr (useProjectStorage()) {
using namespace Storage::Info;
- return isTypeId(m_typeId, m_projectStorage->builtinTypeId<QVariant>());
+ return isValid() && isTypeId(m_typeId, m_projectStorage->builtinTypeId<QVariant>());
} else {
return isValid() && simplifiedTypeName() == "QVariant";
}
@@ -2630,7 +2757,7 @@ bool NodeMetaInfo::isString() const
{
if constexpr (useProjectStorage()) {
using namespace Storage::Info;
- return isTypeId(m_typeId, m_projectStorage->builtinTypeId<QString>());
+ return isValid() && isTypeId(m_typeId, m_projectStorage->builtinTypeId<QString>());
} else {
if (!isValid())
return false;
@@ -2645,7 +2772,7 @@ bool NodeMetaInfo::isUrl() const
{
if constexpr (useProjectStorage()) {
using namespace Storage::Info;
- return isTypeId(m_typeId, m_projectStorage->builtinTypeId<QUrl>());
+ return isValid() && isTypeId(m_typeId, m_projectStorage->builtinTypeId<QUrl>());
} else {
if (!isValid())
return false;
@@ -2805,7 +2932,8 @@ bool NodeMetaInfo::isQtQuick3DCubeMapTexture() const
return isBasedOnCommonType<QtQuick3D, CubeMapTexture>(m_projectStorage, m_typeId);
} else {
return isValid()
- && (isSubclassOf("QtQuick3D.CubeMapTexture") || isSubclassOf("<cpp>.QQuick3DCubeMapTexture"));
+ && (isSubclassOf("QtQuick3D.CubeMapTexture")
+ || isSubclassOf("<cpp>.QQuick3DCubeMapTexture"));
}
}
@@ -2832,7 +2960,7 @@ bool NodeMetaInfo::isQtQuick3DEffect() const
bool NodeMetaInfo::isEnumeration() const
{
if constexpr (useProjectStorage())
- return bool(typeData().traits & Storage::TypeTraits::IsEnum);
+ return isValid() && bool(typeData().traits & Storage::TypeTraits::IsEnum);
return false;
}
@@ -3046,9 +3174,26 @@ const PropertyName &PropertyMetaInfo::propertyName() const
NodeMetaInfo NodeMetaInfo::commonBase(const NodeMetaInfo &metaInfo) const
{
- for (const NodeMetaInfo &info : metaInfo.superClasses()) {
- if (isBasedOn(info))
- return info;
+ if constexpr (useProjectStorage()) {
+ if (isValid() && metaInfo) {
+ const auto firstTypeIds = m_projectStorage->prototypeAndSelfIds(m_typeId);
+ const auto secondTypeIds = m_projectStorage->prototypeAndSelfIds(metaInfo.m_typeId);
+ auto found
+ = std::find_if(firstTypeIds.begin(), firstTypeIds.end(), [&](TypeId firstTypeId) {
+ return std::find(secondTypeIds.begin(), secondTypeIds.end(), firstTypeId)
+ != secondTypeIds.end();
+ });
+
+ if (found != firstTypeIds.end()) {
+ return NodeMetaInfo{*found, m_projectStorage};
+ }
+ }
+ } else {
+ for (const NodeMetaInfo &info : metaInfo.selfAndPrototypes()) {
+ if (isBasedOn(info)) {
+ return info;
+ }
+ }
}
return {};
diff --git a/src/plugins/qmldesigner/designercore/model/abstractview.cpp b/src/plugins/qmldesigner/designercore/model/abstractview.cpp
index a8ad4b76e7c..64912f5b73b 100644
--- a/src/plugins/qmldesigner/designercore/model/abstractview.cpp
+++ b/src/plugins/qmldesigner/designercore/model/abstractview.cpp
@@ -927,10 +927,9 @@ static int getMajorVersionFromImport(const Model *model)
static int getMajorVersionFromNode(const ModelNode &modelNode)
{
if (modelNode.metaInfo().isValid()) {
- for (const NodeMetaInfo &info : modelNode.metaInfo().classHierarchy()) {
- if (info.typeName() == "QtQml.QtObject"
- || info.typeName() == "QtQuick.QtObject"
- || info.typeName() == "QtQuick.Item") {
+ for (const NodeMetaInfo &info : modelNode.metaInfo().selfAndPrototypes()) {
+ if (info.typeName() == "QtQml.QtObject" || info.typeName() == "QtQuick.QtObject"
+ || info.typeName() == "QtQuick.Item") {
return info.majorVersion();
}
}
@@ -942,7 +941,7 @@ static int getMajorVersionFromNode(const ModelNode &modelNode)
static int getMinorVersionFromNode(const ModelNode &modelNode)
{
if (modelNode.metaInfo().isValid()) {
- const NodeMetaInfos infos = modelNode.metaInfo().classHierarchy();
+ const NodeMetaInfos infos = modelNode.metaInfo().selfAndPrototypes();
for (const NodeMetaInfo &info : infos) {
if (info.typeName() == "QtQuick.QtObject" || info.typeName() == "QtQuick.Item")
return info.minorVersion();
diff --git a/src/plugins/qmldesigner/designercore/model/bindingproperty.cpp b/src/plugins/qmldesigner/designercore/model/bindingproperty.cpp
index 558f6849be2..bf1dc59e155 100644
--- a/src/plugins/qmldesigner/designercore/model/bindingproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/bindingproperty.cpp
@@ -148,7 +148,7 @@ AbstractProperty BindingProperty::resolveToProperty() const
element = binding;
}
- if (node.isValid())
+ if (node.isValid() && !element.contains(' '))
return node.property(element.toUtf8());
else
return AbstractProperty();
diff --git a/src/plugins/qmldesigner/designercore/model/import.cpp b/src/plugins/qmldesigner/designercore/model/import.cpp
index 54b18810437..6d4cd19d8b8 100644
--- a/src/plugins/qmldesigner/designercore/model/import.cpp
+++ b/src/plugins/qmldesigner/designercore/model/import.cpp
@@ -11,17 +11,17 @@ namespace QmlDesigner {
Import Import::createLibraryImport(const QString &url, const QString &version, const QString &alias, const QStringList &importPaths)
{
- return Import(url, QString(), version, alias, importPaths);
+ return Import(url, version, alias, importPaths, Type::Library);
}
Import Import::createFileImport(const QString &file, const QString &version, const QString &alias, const QStringList &importPaths)
{
- return Import(QString(), file, version, alias, importPaths);
+ return Import(file, version, alias, importPaths, Type::File);
}
Import Import::empty()
{
- return Import(QString(), QString(), QString(), QString(), QStringList());
+ return Import(QString(), QString(), QString(), QStringList(), Type::Empty);
}
QString Import::toImportString() const
@@ -33,12 +33,16 @@ QString Import::toImportString() const
return result;
}
-Import::Import(const QString &url, const QString &file, const QString &version, const QString &alias, const QStringList &importPaths):
- m_url(url),
- m_file(file),
- m_version(version),
- m_alias(alias),
- m_importPathList(importPaths)
+Import::Import(const QString &url,
+ const QString &version,
+ const QString &alias,
+ const QStringList &importPaths,
+ Type type)
+ : m_url(url)
+ , m_version(version)
+ , m_alias(alias)
+ , m_importPathList(importPaths)
+ , m_type(type)
{
}
@@ -137,7 +141,7 @@ size_t qHash(const Import &import)
return ::qHash(import.url()) ^ ::qHash(import.file()) ^ ::qHash(import.version()) ^ ::qHash(import.alias());
}
-Imports difference(const Imports &first, const Imports &second)
+Imports set_difference(const Imports &first, const Imports &second)
{
Imports difference;
difference.reserve(first.size());
@@ -150,4 +154,53 @@ Imports difference(const Imports &first, const Imports &second)
return difference;
}
+
+Imports set_union(const Imports &first, const Imports &second)
+{
+ Imports set_union;
+ set_union.reserve(std::min(first.size(), second.size()));
+
+ std::set_union(first.begin(),
+ first.end(),
+ second.begin(),
+ second.end(),
+ std::back_inserter(set_union));
+
+ return set_union;
+}
+
+Imports set_intersection(const Imports &first, const Imports &second)
+{
+ Imports set_intersection;
+ set_intersection.reserve(std::min(first.size(), second.size()));
+
+ std::set_intersection(first.begin(),
+ first.end(),
+ second.begin(),
+ second.end(),
+ std::back_inserter(set_intersection));
+
+ return set_intersection;
+}
+
+Imports set_strict_difference(const Imports &first, const Imports &second)
+{
+ Imports difference;
+ difference.reserve(first.size());
+
+ auto strictLess = [](const Import &first, const Import &second) {
+ return std::tie(first.m_url, first.m_type, first.m_version)
+ < std::tie(second.m_url, second.m_type, second.m_version);
+ };
+
+ std::set_difference(first.begin(),
+ first.end(),
+ second.begin(),
+ second.end(),
+ std::back_inserter(difference),
+ strictLess);
+
+ return difference;
+}
+
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/model/internalnode_p.h b/src/plugins/qmldesigner/designercore/model/internalnode_p.h
index 8b3ff86d2bc..bf8523653cf 100644
--- a/src/plugins/qmldesigner/designercore/model/internalnode_p.h
+++ b/src/plugins/qmldesigner/designercore/model/internalnode_p.h
@@ -199,8 +199,8 @@ public:
int nodeSourceType = 0;
QString behaviorPropertyName;
QStringList scriptFunctions;
- ModuleId moduleId; // is invalid if type is implicit
- Utils::SmallString documentTypeName; // how the type is written in den Document
+ ModuleId moduleId;
+ ImportedTypeNameId importedTypeNameId;
TypeId typeId;
private:
diff --git a/src/plugins/qmldesigner/designercore/model/model.cpp b/src/plugins/qmldesigner/designercore/model/model.cpp
index 12a8c091838..653ffea077a 100644
--- a/src/plugins/qmldesigner/designercore/model/model.cpp
+++ b/src/plugins/qmldesigner/designercore/model/model.cpp
@@ -6,6 +6,8 @@
#include "model_p.h"
#include <modelnode.h>
+#include "../projectstorage/sourcepath.h"
+#include "../projectstorage/sourcepathcache.h"
#include "abstractview.h"
#include "auxiliarydataproperties.h"
#include "internalbindingproperty.h"
@@ -60,18 +62,21 @@ namespace QmlDesigner {
namespace Internal {
ModelPrivate::ModelPrivate(Model *model,
- ProjectStorageType &projectStorage,
+ ProjectStorageDependencies projectStorageDependencies,
const TypeName &typeName,
int major,
int minor,
Model *metaInfoProxyModel,
std::unique_ptr<ModelResourceManagementInterface> resourceManagement)
- : projectStorage{&projectStorage}
+ : projectStorage{&projectStorageDependencies.storage}
+ , pathCache{&projectStorageDependencies.cache}
, m_model{model}
, m_resourceManagement{std::move(resourceManagement)}
{
m_metaInfoProxyModel = metaInfoProxyModel;
+ changeImports({Import::createLibraryImport({"QtQuick"})}, {});
+
m_rootInternalNode = createNode(
typeName, major, minor, {}, {}, {}, ModelNode::NodeWithoutSource, {}, true);
@@ -80,6 +85,25 @@ ModelPrivate::ModelPrivate(Model *model,
}
ModelPrivate::ModelPrivate(Model *model,
+ ProjectStorageDependencies projectStorageDependencies,
+ Utils::SmallStringView typeName,
+ Imports imports,
+ const QUrl &fileUrl)
+ : projectStorage{&projectStorageDependencies.storage}
+ , pathCache{&projectStorageDependencies.cache}
+ , m_model{model}
+{
+ setFileUrl(fileUrl);
+ changeImports(std::move(imports), {});
+
+ m_rootInternalNode = createNode(
+ TypeName{typeName}, -1, -1, {}, {}, {}, ModelNode::NodeWithoutSource, {}, true);
+
+ m_currentStateNode = m_rootInternalNode;
+ m_currentTimelineNode = m_rootInternalNode;
+}
+
+ModelPrivate::ModelPrivate(Model *model,
const TypeName &typeName,
int major,
int minor,
@@ -117,29 +141,41 @@ void ModelPrivate::detachAllViews()
}
}
-void ModelPrivate::changeImports(const Imports &toBeAddedImportList,
- const Imports &toBeRemovedImportList)
+namespace {
+Storage::Imports createStorageImports(const Imports &imports,
+ ProjectStorageType &projectStorage,
+ SourceId fileId)
+{
+ return Utils::transform<Storage::Imports>(imports, [&](const Import &import) {
+ return Storage::Import{projectStorage.moduleId(Utils::SmallString{import.url()}),
+ import.majorVersion(),
+ import.minorVersion(),
+ fileId};
+ });
+}
+
+} // namespace
+
+void ModelPrivate::changeImports(Imports toBeAddedImports, Imports toBeRemovedImports)
{
- Imports removedImportList;
- for (const Import &import : toBeRemovedImportList) {
- if (m_imports.contains(import)) {
- removedImportList.append(import);
- m_imports.removeOne(import);
- }
- }
+ std::sort(toBeAddedImports.begin(), toBeAddedImports.end());
+ std::sort(toBeRemovedImports.begin(), toBeRemovedImports.end());
- Imports addedImportList;
- for (const Import &import : toBeAddedImportList) {
- if (!m_imports.contains(import)) {
- addedImportList.append(import);
- m_imports.append(import);
- }
- }
+ Imports removedImports = set_intersection(m_imports, toBeRemovedImports);
+ m_imports = set_difference(m_imports, removedImports);
+
+ Imports allNewAddedImports = set_strict_difference(toBeAddedImports, m_imports);
+ Imports importWithoutAddedImport = set_difference(m_imports, allNewAddedImports);
- std::sort(m_imports.begin(), m_imports.end());
+ m_imports = set_union(importWithoutAddedImport, allNewAddedImports);
- if (!removedImportList.isEmpty() || !addedImportList.isEmpty())
- notifyImportsChanged(addedImportList, removedImportList);
+ if (!removedImports.isEmpty() || !allNewAddedImports.isEmpty()) {
+ if (useProjectStorage()) {
+ auto imports = createStorageImports(m_imports, *projectStorage, m_sourceId);
+ projectStorage->synchronizeDocumentImports(std::move(imports), m_sourceId);
+ }
+ notifyImportsChanged(allNewAddedImports, removedImports);
+ }
}
void ModelPrivate::notifyImportsChanged(const Imports &addedImports, const Imports &removedImports)
@@ -201,6 +237,9 @@ void ModelPrivate::setFileUrl(const QUrl &fileUrl)
if (oldPath != fileUrl) {
m_fileUrl = fileUrl;
+ if constexpr (useProjectStorage()) {
+ m_sourceId = pathCache->sourceId(SourcePath{fileUrl.path()});
+ }
for (const QPointer<AbstractView> &view : std::as_const(m_viewList))
view->fileUrlChanged(oldPath, fileUrl);
@@ -220,23 +259,6 @@ void ModelPrivate::changeNodeType(const InternalNodePointer &node, const TypeNam
}
}
-namespace {
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_CLANG("-Wunneeded-internal-declaration")
-
-std::pair<Utils::SmallStringView, Utils::SmallStringView> decomposeTypePath(Utils::SmallStringView typeName)
-{
- auto found = std::find(typeName.rbegin(), typeName.rend(), '.');
-
- if (found == typeName.rend())
- return {};
-
- return {{typeName.begin(), std::prev(found.base())}, {found.base(), typeName.end()}};
-}
-
-QT_WARNING_POP
-} // namespace
-
InternalNodePointer ModelPrivate::createNode(const TypeName &typeName,
int majorVersion,
int minorVersion,
@@ -257,13 +279,7 @@ InternalNodePointer ModelPrivate::createNode(const TypeName &typeName,
auto newNode = std::make_shared<InternalNode>(typeName, majorVersion, minorVersion, internalId);
- if constexpr (useProjectStorage()) {
- auto [moduleName, shortTypeName] = decomposeTypePath(typeName);
- ModuleId moduleId = projectStorage->moduleId(moduleName);
- newNode->typeId = projectStorage->typeId(moduleId,
- shortTypeName,
- Storage::Version{majorVersion, minorVersion});
- }
+ setTypeId(newNode.get(), typeName);
newNode->nodeSourceType = nodeSourceType;
@@ -314,6 +330,55 @@ EnabledViewRange ModelPrivate::enabledViews() const
return EnabledViewRange{m_viewList};
}
+namespace {
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_CLANG("-Wunneeded-internal-declaration")
+
+std::pair<Utils::SmallStringView, Utils::SmallStringView> decomposeTypePath(Utils::SmallStringView typeName)
+{
+ auto found = std::find(typeName.rbegin(), typeName.rend(), '.');
+
+ if (found == typeName.rend())
+ return {{}, typeName};
+
+ return {{typeName.begin(), std::prev(found.base())}, {found.base(), typeName.end()}};
+}
+
+QT_WARNING_POP
+} // namespace
+
+ImportedTypeNameId ModelPrivate::importedTypeNameId(Utils::SmallStringView typeName)
+{
+ if constexpr (useProjectStorage()) {
+ auto [moduleName, shortTypeName] = decomposeTypePath(typeName);
+
+ if (moduleName.size()) {
+ QString aliasName = QString{moduleName};
+ auto found = std::find_if(m_imports.begin(), m_imports.end(), [&](const Import &import) {
+ return import.alias() == aliasName;
+ });
+ if (found != m_imports.end()) {
+ ModuleId moduleId = projectStorage->moduleId(Utils::PathString{found->url()});
+ ImportId importId = projectStorage->importId(
+ Storage::Import{moduleId, found->majorVersion(), found->minorVersion(), m_sourceId});
+ return projectStorage->importedTypeNameId(importId, shortTypeName);
+ }
+ }
+
+ return projectStorage->importedTypeNameId(m_sourceId, shortTypeName);
+ }
+
+ return ImportedTypeNameId{};
+}
+
+void ModelPrivate::setTypeId(InternalNode *node, Utils::SmallStringView typeName)
+{
+ if constexpr (useProjectStorage()) {
+ node->importedTypeNameId = importedTypeNameId(typeName);
+ node->typeId = projectStorage->typeId(node->importedTypeNameId);
+ }
+}
+
void ModelPrivate::handleResourceSet(const ModelResourceSet &resourceSet)
{
for (const ModelNode &node : resourceSet.removeModelNodes) {
@@ -1343,9 +1408,11 @@ void ModelPrivate::clearParent(const InternalNodePointer &node)
void ModelPrivate::changeRootNodeType(const TypeName &type, int majorVersion, int minorVersion)
{
Q_ASSERT(rootNode());
- rootNode()->typeName = type;
- rootNode()->majorVersion = majorVersion;
- rootNode()->minorVersion = minorVersion;
+
+ m_rootInternalNode->typeName = type;
+ m_rootInternalNode->majorVersion = majorVersion;
+ m_rootInternalNode->minorVersion = minorVersion;
+ setTypeId(m_rootInternalNode.get(), type);
notifyRootNodeTypeChanged(QString::fromUtf8(type), majorVersion, minorVersion);
}
@@ -1473,6 +1540,7 @@ WriteLocker::WriteLocker(ModelPrivate *model)
if (m_model->m_writeLock)
qWarning() << "QmlDesigner: Misbehaving view calls back to model!!!";
// FIXME: Enable it again
+ QTC_CHECK(!m_model->m_writeLock);
Q_ASSERT(!m_model->m_writeLock);
model->m_writeLock = true;
}
@@ -1484,6 +1552,7 @@ WriteLocker::WriteLocker(Model *model)
if (m_model->m_writeLock)
qWarning() << "QmlDesigner: Misbehaving view calls back to model!!!";
// FIXME: Enable it again
+ QTC_CHECK(!m_model->m_writeLock);
Q_ASSERT(!m_model->m_writeLock);
m_model->m_writeLock = true;
}
@@ -1493,6 +1562,7 @@ WriteLocker::~WriteLocker()
if (!m_model->m_writeLock)
qWarning() << "QmlDesigner: WriterLocker out of sync!!!";
// FIXME: Enable it again
+ QTC_CHECK(m_model->m_writeLock);
Q_ASSERT(m_model->m_writeLock);
m_model->m_writeLock = false;
}
@@ -1509,14 +1579,27 @@ void WriteLocker::lock(Model *model)
} // namespace Internal
-Model::Model(ProjectStorageType &projectStorage,
+Model::Model(ProjectStorageDependencies projectStorageDependencies,
const TypeName &typeName,
int major,
int minor,
Model *metaInfoProxyModel,
std::unique_ptr<ModelResourceManagementInterface> resourceManagement)
+ : d(std::make_unique<Internal::ModelPrivate>(this,
+ projectStorageDependencies,
+ typeName,
+ major,
+ minor,
+ metaInfoProxyModel,
+ std::move(resourceManagement)))
+{}
+
+Model::Model(ProjectStorageDependencies projectStorageDependencies,
+ Utils::SmallStringView typeName,
+ Imports imports,
+ const QUrl &fileUrl)
: d(std::make_unique<Internal::ModelPrivate>(
- this, projectStorage, typeName, major, minor, metaInfoProxyModel, std::move(resourceManagement)))
+ this, projectStorageDependencies, typeName, std::move(imports), fileUrl))
{}
Model::Model(const TypeName &typeName,
@@ -1545,9 +1628,9 @@ const Imports &Model::usedImports() const
return d->m_usedImportList;
}
-void Model::changeImports(const Imports &importsToBeAdded, const Imports &importsToBeRemoved)
+void Model::changeImports(Imports importsToBeAdded, Imports importsToBeRemoved)
{
- d->changeImports(importsToBeAdded, importsToBeRemoved);
+ d->changeImports(std::move(importsToBeAdded), std::move(importsToBeRemoved));
}
void Model::setPossibleImports(Imports possibleImports)
@@ -1747,6 +1830,16 @@ NotNullPointer<const ProjectStorageType> Model::projectStorage() const
return d->projectStorage;
}
+const PathCacheType &Model::pathCache() const
+{
+ return *d->pathCache;
+}
+
+PathCacheType &Model::pathCache()
+{
+ return *d->pathCache;
+}
+
void ModelDeleter::operator()(class Model *model)
{
model->detachAllViews();
@@ -1877,13 +1970,18 @@ QUrl Model::fileUrl() const
return d->fileUrl();
}
+SourceId Model::fileUrlSourceId() const
+{
+ return d->m_sourceId;
+}
+
/*!
\brief Sets the URL against which relative URLs within the model should be resolved.
\param url the base URL, i.e. the qml file path.
*/
void Model::setFileUrl(const QUrl &url)
{
- Q_ASSERT(url.isValid() && url.isLocalFile());
+ QTC_ASSERT(url.isValid() && url.isLocalFile(), qDebug() << "url:" << url; return);
Internal::WriteLocker locker(d.get());
d->setFileUrl(url);
}
@@ -1906,6 +2004,16 @@ void Model::setMetaInfo(const MetaInfo &metaInfo)
d->setMetaInfo(metaInfo);
}
+NodeMetaInfo Model::boolMetaInfo() const
+{
+ if constexpr (useProjectStorage()) {
+ using namespace Storage::Info;
+ return createNodeMetaInfo<QML, BoolType>();
+ } else {
+ return metaInfo("QML.bool");
+ }
+}
+
template<const auto &moduleName, const auto &typeName>
NodeMetaInfo Model::createNodeMetaInfo() const
{
@@ -1924,6 +2032,36 @@ NodeMetaInfo Model::fontMetaInfo() const
}
}
+NodeMetaInfo Model::qtQmlModelsListModelMetaInfo() const
+{
+ if constexpr (useProjectStorage()) {
+ using namespace Storage::Info;
+ return createNodeMetaInfo<QtQml_Models, ListModel>();
+ } else {
+ return metaInfo("QtQml.Models.ListModel");
+ }
+}
+
+NodeMetaInfo Model::qtQmlModelsListElementMetaInfo() const
+{
+ if constexpr (useProjectStorage()) {
+ using namespace Storage::Info;
+ return createNodeMetaInfo<QtQml_Models, ListElement>();
+ } else {
+ return metaInfo("QtQml.Models.ListElement");
+ }
+}
+
+NodeMetaInfo Model::qmlQtObjectMetaInfo() const
+{
+ if constexpr (useProjectStorage()) {
+ using namespace Storage::Info;
+ return createNodeMetaInfo<QML, QtObject>();
+ } else {
+ return metaInfo("QML.QtObject");
+ }
+}
+
NodeMetaInfo Model::qtQuickItemMetaInfo() const
{
if constexpr (useProjectStorage()) {
@@ -2220,13 +2358,8 @@ namespace {
NodeMetaInfo Model::metaInfo(const TypeName &typeName, int majorVersion, int minorVersion) const
{
if constexpr (useProjectStorage()) {
- auto [module, componentName] = moduleTypeName(typeName);
-
- ModuleId moduleId = d->projectStorage->moduleId(module);
- TypeId typeId = d->projectStorage->typeId(moduleId,
- componentName,
- Storage::Version{majorVersion, minorVersion});
- return NodeMetaInfo(typeId, d->projectStorage);
+ return NodeMetaInfo(d->projectStorage->typeId(d->importedTypeNameId(typeName)),
+ d->projectStorage);
} else {
return NodeMetaInfo(metaInfoProxyModel(), typeName, majorVersion, minorVersion);
}
@@ -2356,6 +2489,13 @@ ModelNode Model::createModelNode(const TypeName &typeName)
}
}
+void Model::changeRootNodeType(const TypeName &type)
+{
+ Internal::WriteLocker locker(this);
+
+ d->changeRootNodeType(type, -1, -1);
+}
+
void Model::removeModelNodes(ModelNodes nodes, BypassModelResourceManagement bypass)
{
nodes.erase(std::remove_if(nodes.begin(), nodes.end(), [](auto &&node) { return !node; }),
diff --git a/src/plugins/qmldesigner/designercore/model/model_p.h b/src/plugins/qmldesigner/designercore/model/model_p.h
index 5c69e756164..324df37ddb2 100644
--- a/src/plugins/qmldesigner/designercore/model/model_p.h
+++ b/src/plugins/qmldesigner/designercore/model/model_p.h
@@ -98,13 +98,18 @@ class ModelPrivate : public QObject
public:
ModelPrivate(Model *model,
- ProjectStorageType &projectStorage,
+ ProjectStorageDependencies m_projectStorageDependencies,
const TypeName &type,
int major,
int minor,
Model *metaInfoProxyModel,
std::unique_ptr<ModelResourceManagementInterface> resourceManagement);
ModelPrivate(Model *model,
+ ProjectStorageDependencies m_projectStorageDependencies,
+ Utils::SmallStringView typeName,
+ Imports imports,
+ const QUrl &filePath);
+ ModelPrivate(Model *model,
const TypeName &type,
int major,
int minor,
@@ -235,7 +240,7 @@ public:
// Imports:
const Imports &imports() const { return m_imports; }
- void changeImports(const Imports &importsToBeAdded, const Imports &importToBeRemoved);
+ void changeImports(Imports importsToBeAdded, Imports importToBeRemoved);
void notifyImportsChanged(const Imports &addedImports, const Imports &removedImports);
void notifyPossibleImportsChanged(const Imports &possibleImports);
void notifyUsedImportsChanged(const Imports &usedImportsChanged);
@@ -306,9 +311,12 @@ private:
static QList<std::tuple<InternalBindingPropertyPointer, QString>> toInternalBindingProperties(
const ModelResourceSet::SetExpressions &setExpressions);
EnabledViewRange enabledViews() const;
+ ImportedTypeNameId importedTypeNameId(Utils::SmallStringView typeName);
+ void setTypeId(InternalNode *node, Utils::SmallStringView typeName);
public:
NotNullPointer<ProjectStorageType> projectStorage = nullptr;
+ NotNullPointer<PathCacheType> pathCache = nullptr;
private:
Model *m_model = nullptr;
@@ -326,6 +334,7 @@ private:
InternalNodePointer m_currentTimelineNode;
std::unique_ptr<ModelResourceManagementInterface> m_resourceManagement;
QUrl m_fileUrl;
+ SourceId m_sourceId;
QPointer<RewriterView> m_rewriterView;
QPointer<NodeInstanceView> m_nodeInstanceView;
QPointer<Model> m_metaInfoProxyModel;
diff --git a/src/plugins/qmldesigner/designercore/model/modelnode.cpp b/src/plugins/qmldesigner/designercore/model/modelnode.cpp
index 45c076022da..cb862b03431 100644
--- a/src/plugins/qmldesigner/designercore/model/modelnode.cpp
+++ b/src/plugins/qmldesigner/designercore/model/modelnode.cpp
@@ -66,10 +66,6 @@ ModelNode::ModelNode(const ModelNode &modelNode, AbstractView *view)
, m_view(view)
{}
-/*! \brief does nothing
-*/
-ModelNode::~ModelNode() = default;
-
/*! \brief returns the name of node which is a short cut to a property like objectName
\return name of the node
*/
@@ -657,15 +653,6 @@ void ModelNode::destroy()
//\}
-/*! \name Property Manipulation
- * This functions interact with properties.
- */
-
-Internal::InternalNodePointer ModelNode::internalNode() const
-{
- return m_internalNode;
-}
-
/*!
\brief returns the model of the node
\return returns the model of the node
@@ -1002,6 +989,12 @@ void ModelNode::setAuxiliaryData(AuxiliaryDataKeyView key, const QVariant &data)
}
}
+void ModelNode::setAuxiliaryDataWithoutLock(AuxiliaryDataKeyView key, const QVariant &data) const
+{
+ if (isValid())
+ m_model->d->setAuxiliaryData(internalNode(), key, data);
+}
+
void ModelNode::setAuxiliaryDataWithoutLock(AuxiliaryDataType type,
Utils::SmallStringView name,
const QVariant &data) const
diff --git a/src/plugins/qmldesigner/designercore/model/modelutils.cpp b/src/plugins/qmldesigner/designercore/model/modelutils.cpp
index 70da6f98b9c..efbe8f09783 100644
--- a/src/plugins/qmldesigner/designercore/model/modelutils.cpp
+++ b/src/plugins/qmldesigner/designercore/model/modelutils.cpp
@@ -4,6 +4,8 @@
#include "modelutils.h"
#include <nodemetainfo.h>
+#include <projectstorage/projectstorage.h>
+#include <projectstorage/sourcepathcache.h>
#include <utils/expected.h>
@@ -102,4 +104,29 @@ PropertyMetaInfo metainfo(const ModelNode &node, const PropertyName &propertyNam
return node.metaInfo().property(propertyName);
}
+QString componentFilePath(const PathCacheType &pathCache, const NodeMetaInfo &metaInfo)
+{
+ if constexpr (useProjectStorage()) {
+ auto typeSourceId = metaInfo.sourceId();
+
+ if (typeSourceId && metaInfo.isFileComponent()) {
+ return pathCache.sourcePath(typeSourceId).toQString();
+ }
+ } else {
+ return metaInfo.componentFileName();
+ }
+
+ return {};
+}
+
+QString componentFilePath(const ModelNode &node)
+{
+ if (node) {
+ const auto &pathCache = node.model()->pathCache();
+ return ModelUtils::componentFilePath(pathCache, node.metaInfo());
+ }
+
+ return {};
+}
+
} // namespace QmlDesigner::ModelUtils
diff --git a/src/plugins/qmldesigner/designercore/model/modelutils.h b/src/plugins/qmldesigner/designercore/model/modelutils.h
index 578a7adb444..946882c2df7 100644
--- a/src/plugins/qmldesigner/designercore/model/modelutils.h
+++ b/src/plugins/qmldesigner/designercore/model/modelutils.h
@@ -29,4 +29,8 @@ QMLDESIGNERCORE_EXPORT PropertyMetaInfo metainfo(const AbstractProperty &propert
QMLDESIGNERCORE_EXPORT PropertyMetaInfo metainfo(const ModelNode &node,
const PropertyName &propertyName);
+QMLDESIGNERCORE_EXPORT QString componentFilePath(const PathCacheType &pathCache,
+ const NodeMetaInfo &metaInfo);
+
+QMLDESIGNERCORE_EXPORT QString componentFilePath(const ModelNode &node);
} // namespace QmlDesigner::ModelUtils
diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
index 3108e26a618..ccfffbc867b 100644
--- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
+++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
@@ -937,7 +937,6 @@ QList<QmlDesigner::Import> generatePossibleFileImports(const QString &path,
QmlDesigner::Imports createQt5Modules()
{
return {QmlDesigner::Import::createLibraryImport("QtQuick", "5.15"),
- QmlDesigner::Import::createLibraryImport("QtQuick3D", "5.15"),
QmlDesigner::Import::createLibraryImport("QtQuick.Controls", "5.15"),
QmlDesigner::Import::createLibraryImport("QtQuick.Window", "5.15"),
QmlDesigner::Import::createLibraryImport("QtQuick.Layouts", "5.15"),
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/commontypecache.h b/src/plugins/qmldesigner/designercore/projectstorage/commontypecache.h
index 05e90fdb285..fb4fb660660 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/commontypecache.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/commontypecache.h
@@ -31,12 +31,12 @@ inline constexpr char Camera[] = "Camera";
inline constexpr char Command[] = "Command";
inline constexpr char Component[] = "Component";
inline constexpr char Connections[] = "Connections";
+inline constexpr char Control[] = "Control";
inline constexpr char CubeMapTexture[] = "CubeMapTexture";
inline constexpr char DefaultMaterial[] = "DefaultMaterial";
inline constexpr char Dialog[] = "Dialog";
inline constexpr char DoubleType[] = "double";
inline constexpr char Effect[] = "Effect";
-inline constexpr char EffectMaker[] = "EffectMaker";
inline constexpr char FloatType[] = "float";
inline constexpr char FlowActionArea[] = "FlowActionArea";
inline constexpr char FlowDecision[] = "FlowDecision";
@@ -55,10 +55,13 @@ inline constexpr char Item[] = "Item";
inline constexpr char KeyframeGroup[] = "KeyframeGroup";
inline constexpr char Keyframe[] = "Keyframe";
inline constexpr char Layout[] = "Layout";
+inline constexpr char ListElement[] = "ListElement";
+inline constexpr char ListModel[] = "ListModel";
inline constexpr char ListView[] = "ListView";
inline constexpr char Loader[] = "Loader";
inline constexpr char Material[] = "Material";
inline constexpr char Model[] = "Model";
+inline constexpr char MouseArea[] = "MouseArea";
inline constexpr char Node[] = "Node";
inline constexpr char Particle3D[] = "Particle3D";
inline constexpr char ParticleEmitter3D[] = "ParticleEmitter3D";
@@ -80,6 +83,7 @@ inline constexpr char QQuickStateOperation[] = "QQuickStateOperation";
inline constexpr char QtMultimedia[] = "QtMultimedia";
inline constexpr char QtObject[] = "QtObject";
inline constexpr char QtQml[] = "QtQml";
+inline constexpr char QtQml_Models[] = "QtQml.Models";
inline constexpr char QtQuick3D[] = "QtQuick3D";
inline constexpr char QtQuick3D_Particles3D[] = "QtQuick3D.Particles3D";
inline constexpr char QtQuick3D_Particles3D_cppnative[] = "QtQuick3D.Particles3D-cppnative";
@@ -90,6 +94,7 @@ inline constexpr char QtQuick_Dialogs[] = "QtQuick.Dialogs";
inline constexpr char QtQuick_Extras[] = "QtQuick.Extras";
inline constexpr char QtQuick_Layouts[] = "QtQuick.Layouts";
inline constexpr char QtQuick_Studio_Components[] = "QtQuick.Studio.Components";
+inline constexpr char QtQuick_Templates[] = "QtQuick.Templates";
inline constexpr char QtQuick_Timeline[] = "QtQuick.Timeline";
inline constexpr char QtQuick_Window[] = "QtQuick.Window";
inline constexpr char Qt_SafeRenderer[] = "Qt.SafeRenderer";
@@ -114,6 +119,7 @@ inline constexpr char Texture[] = "Texture";
inline constexpr char TimelineAnimation[] = "TimelineAnimation";
inline constexpr char Timeline[] = "Timeline";
inline constexpr char Transition[] = "Transition";
+inline constexpr char UIntType[] = "uint";
inline constexpr char View3D[] = "View3D";
inline constexpr char Window[] = "Window";
inline constexpr char color[] = "color";
@@ -156,7 +162,10 @@ class CommonTypeCache
CacheType<QML, url>,
CacheType<QML, var>,
CacheType<QML_cppnative, FloatType>,
+ CacheType<QML_cppnative, UIntType>,
CacheType<QtMultimedia, SoundEffect>,
+ CacheType<QtQml_Models, ListElement>,
+ CacheType<QtQml_Models, ListModel>,
CacheType<QtQuick, BorderImage>,
CacheType<QtQuick, Connections>,
CacheType<QtQuick, GridView>,
@@ -164,6 +173,7 @@ class CommonTypeCache
CacheType<QtQuick, Item>,
CacheType<QtQuick, ListView>,
CacheType<QtQuick, Loader>,
+ CacheType<QtQuick, MouseArea>,
CacheType<QtQuick, Path>,
CacheType<QtQuick, PathView>,
CacheType<QtQuick, PauseAnimation>,
@@ -210,6 +220,7 @@ class CommonTypeCache
CacheType<QtQuick3D_Particles3D, ParticleEmitter3D>,
CacheType<QtQuick3D_Particles3D, SpriteParticle3D>,
CacheType<QtQuick3D_Particles3D_cppnative, QQuick3DParticleAbstractShape>,
+ CacheType<QtQuick_Controls, Control>,
CacheType<QtQuick_Controls, Popup>,
CacheType<QtQuick_Controls, SplitView>,
CacheType<QtQuick_Controls, SwipeView>,
@@ -219,6 +230,7 @@ class CommonTypeCache
CacheType<QtQuick_Extras, Picture>,
CacheType<QtQuick_Layouts, Layout>,
CacheType<QtQuick_Studio_Components, GroupItem>,
+ CacheType<QtQuick_Templates, Control>,
CacheType<QtQuick_Timeline, Keyframe>,
CacheType<QtQuick_Timeline, KeyframeGroup>,
CacheType<QtQuick_Timeline, Timeline>,
@@ -271,30 +283,33 @@ public:
{
if constexpr (std::is_same_v<Type, double>)
return typeId<QML, DoubleType>();
- if constexpr (std::is_same_v<Type, int>)
+ else if constexpr (std::is_same_v<Type, int>)
return typeId<QML, IntType>();
- if constexpr (std::is_same_v<Type, bool>)
+ else if constexpr (std::is_same_v<Type, uint>)
+ return typeId<QML_cppnative, UIntType>();
+ else if constexpr (std::is_same_v<Type, bool>)
return typeId<QML, BoolType>();
- if constexpr (std::is_same_v<Type, float>)
+ else if constexpr (std::is_same_v<Type, float>)
return typeId<QML_cppnative, FloatType>();
- if constexpr (std::is_same_v<Type, QString>)
+ else if constexpr (std::is_same_v<Type, QString>)
return typeId<QML, string>();
- if constexpr (std::is_same_v<Type, QDateTime>)
+ else if constexpr (std::is_same_v<Type, QDateTime>)
return typeId<QML, date>();
- if constexpr (std::is_same_v<Type, QUrl>)
+ else if constexpr (std::is_same_v<Type, QUrl>)
return typeId<QML, url>();
- if constexpr (std::is_same_v<Type, QVariant>)
+ else if constexpr (std::is_same_v<Type, QVariant>)
return typeId<QML, var>();
- if constexpr (std::is_same_v<Type, QColor>)
+ else if constexpr (std::is_same_v<Type, QColor>)
return typeId<QtQuick, color>();
- if constexpr (std::is_same_v<Type, QVector2D>)
+ else if constexpr (std::is_same_v<Type, QVector2D>)
return typeId<QtQuick, vector2d>();
- if constexpr (std::is_same_v<Type, QVector3D>)
+ else if constexpr (std::is_same_v<Type, QVector3D>)
return typeId<QtQuick, vector3d>();
- if constexpr (std::is_same_v<Type, QVector4D>)
+ else if constexpr (std::is_same_v<Type, QVector4D>)
return typeId<QtQuick, vector4d>();
else
- return TypeId{};
+ static_assert(!std::is_same_v<Type, Type>, "built-in type not supported");
+ return TypeId{};
}
private:
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/filesystem.h b/src/plugins/qmldesigner/designercore/projectstorage/filesystem.h
index c67d4e2de9a..078fd1ee98f 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/filesystem.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/filesystem.h
@@ -19,10 +19,10 @@ class SourcePathCache;
template<typename Database>
class ProjectStorage;
-using PathCache = SourcePathCache<ProjectStorage<Sqlite::Database>, NonLockingMutex>;
-
class FileSystem : public FileSystemInterface
{
+ using PathCache = SourcePathCache<ProjectStorage<Sqlite::Database>, NonLockingMutex>;
+
public:
FileSystem(PathCache &sourcePathCache)
: m_sourcePathCache(sourcePathCache)
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h
index 337145638c1..78064fedab0 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h
@@ -107,6 +107,15 @@ public:
});
}
+ void synchronizeDocumentImports(Storage::Imports imports, SourceId sourceId) override
+ {
+ Sqlite::withImmediateTransaction(database, [&] {
+ synchronizeDocumentImports(imports,
+ {sourceId},
+ Storage::Synchronization::ImportKind::Import);
+ });
+ }
+
ModuleId moduleId(Utils::SmallStringView moduleName) const override
{
return moduleCache.id(moduleName);
@@ -139,6 +148,51 @@ public:
.template valueWithTransaction<TypeId>(moduleId, exportedTypeName);
}
+ TypeId typeId(ImportedTypeNameId typeNameId) const override
+ {
+ return Sqlite::withDeferredTransaction(database, [&] { return fetchTypeId(typeNameId); });
+ }
+
+ Storage::Info::ExportedTypeNames exportedTypeNames(TypeId typeId) const override
+ {
+ return selectExportedTypesByTypeIdStatement
+ .template valuesWithTransaction<Storage::Info::ExportedTypeName>(4, typeId);
+ }
+
+ Storage::Info::ExportedTypeNames exportedTypeNames(TypeId typeId,
+ SourceId sourceId) const override
+ {
+ return selectExportedTypesByTypeIdAndSourceIdStatement
+ .template valuesWithTransaction<Storage::Info::ExportedTypeName>(4, typeId, sourceId);
+ }
+
+ ImportId importId(const Storage::Import &import) const override
+ {
+ return Sqlite::withDeferredTransaction(database, [&] {
+ return fetchImportId(import.sourceId, import);
+ });
+ }
+
+ ImportedTypeNameId importedTypeNameId(ImportId importId,
+ Utils::SmallStringView typeName) override
+ {
+ return Sqlite::withDeferredTransaction(database, [&] {
+ return fetchImportedTypeNameId(Storage::Synchronization::TypeNameKind::QualifiedExported,
+ importId,
+ typeName);
+ });
+ }
+
+ ImportedTypeNameId importedTypeNameId(SourceId sourceId,
+ Utils::SmallStringView typeName) override
+ {
+ return Sqlite::withDeferredTransaction(database, [&] {
+ return fetchImportedTypeNameId(Storage::Synchronization::TypeNameKind::Exported,
+ sourceId,
+ typeName);
+ });
+ }
+
PropertyDeclarationIds propertyDeclarationIds(TypeId typeId) const override
{
return selectPropertyDeclarationIdsForTypeStatement
@@ -610,14 +664,14 @@ private:
template<typename Type>
struct TypeCompare
{
- bool operator()(const Type &type, TypeId typeId) { return type.typeId < typeId; };
+ bool operator()(const Type &type, TypeId typeId) { return type.typeId < typeId; }
- bool operator()(TypeId typeId, const Type &type) { return typeId < type.typeId; };
+ bool operator()(TypeId typeId, const Type &type) { return typeId < type.typeId; }
bool operator()(const Type &first, const Type &second)
{
return first.typeId < second.typeId;
- };
+ }
};
template<typename Property>
@@ -626,17 +680,17 @@ private:
bool operator()(const Property &property, PropertyDeclarationId id)
{
return property.propertyDeclarationId < id;
- };
+ }
bool operator()(PropertyDeclarationId id, const Property &property)
{
return id < property.propertyDeclarationId;
- };
+ }
bool operator()(const Property &first, const Property &second)
{
return first.propertyDeclarationId < second.propertyDeclarationId;
- };
+ }
};
SourceIds filterSourceIdsWithoutType(const SourceIds &updatedSourceIds, SourceIds &sourceIdsOfTypes)
@@ -825,9 +879,9 @@ private:
Sqlite::insertUpdateDelete(range, fileStatuses, compareKey, insert, update, remove);
}
- void synchronizeImports(Storage::Synchronization::Imports &imports,
+ void synchronizeImports(Storage::Imports &imports,
const SourceIds &updatedSourceIds,
- Storage::Synchronization::Imports &moduleDependencies,
+ Storage::Imports &moduleDependencies,
const SourceIds &updatedModuleDependencySourceIds,
Storage::Synchronization::ModuleExportedImports &moduleExportedImports,
const ModuleIds &updatedModuleIds)
@@ -1484,7 +1538,7 @@ private:
PropertyCompare<AliasPropertyDeclaration>{});
}
- void insertDocumentImport(const Storage::Synchronization::Import &import,
+ void insertDocumentImport(const Storage::Import &import,
Storage::Synchronization::ImportKind importKind,
ModuleId sourceModuleId,
ModuleExportedImportId moduleExportedImportId)
@@ -1513,7 +1567,7 @@ private:
}
}
- void synchronizeDocumentImports(Storage::Synchronization::Imports &imports,
+ void synchronizeDocumentImports(Storage::Imports &imports,
const SourceIds &updatedSourceIds,
Storage::Synchronization::ImportKind importKind)
{
@@ -1528,7 +1582,7 @@ private:
importKind);
auto compareKey = [](const Storage::Synchronization::ImportView &view,
- const Storage::Synchronization::Import &import) -> long long {
+ const Storage::Import &import) -> long long {
auto sourceIdDifference = view.sourceId - import.sourceId;
if (sourceIdDifference != 0)
return sourceIdDifference;
@@ -1544,16 +1598,15 @@ private:
return view.version.minor.value - import.version.minor.value;
};
- auto insert = [&](const Storage::Synchronization::Import &import) {
+ auto insert = [&](const Storage::Import &import) {
insertDocumentImport(import, importKind, import.moduleId, ModuleExportedImportId{});
auto callback = [&](ModuleId exportedModuleId,
int majorVersion,
int minorVersion,
ModuleExportedImportId moduleExportedImportId) {
- Storage::Synchronization::Import additionImport{exportedModuleId,
- Storage::Version{majorVersion,
- minorVersion},
- import.sourceId};
+ Storage::Import additionImport{exportedModuleId,
+ Storage::Version{majorVersion, minorVersion},
+ import.sourceId};
auto exportedImportKind = importKind == Storage::Synchronization::ImportKind::Import
? Storage::Synchronization::ImportKind::ModuleExportedImport
@@ -1571,8 +1624,7 @@ private:
import.version.minor.value);
};
- auto update = [](const Storage::Synchronization::ImportView &,
- const Storage::Synchronization::Import &) {
+ auto update = [](const Storage::Synchronization::ImportView &, const Storage::Import &) {
return Sqlite::UpdateChange::No;
};
@@ -2028,7 +2080,7 @@ private:
removeRelinkableEntries(relinkableExtensions, typeIds, TypeCompare<Prototype>{});
}
- ImportId fetchImportId(SourceId sourceId, const Storage::Synchronization::Import &import) const
+ ImportId fetchImportId(SourceId sourceId, const Storage::Import &import) const
{
if (import.version) {
return selectImportIdBySourceIdAndModuleIdAndVersionStatement.template value<ImportId>(
@@ -2709,9 +2761,14 @@ public:
" ON defaultPropertyId=propertyDeclarationId WHERE t.typeId=?",
database};
mutable ReadStatement<4, 1> selectExportedTypesByTypeIdStatement{
- "SELECT moduleId, name, majorVersion, minorVersion FROM "
+ "SELECT moduleId, name, ifnull(majorVersion, -1), ifnull(minorVersion, -1) FROM "
"exportedTypeNames WHERE typeId=?",
database};
+ mutable ReadStatement<4, 2> selectExportedTypesByTypeIdAndSourceIdStatement{
+ "SELECT etn.moduleId, name, ifnull(etn.majorVersion, -1), ifnull(etn.minorVersion, -1) "
+ "FROM exportedTypeNames AS etn JOIN documentImports USING(moduleId) WHERE typeId=?1 AND "
+ "sourceId=?2",
+ database};
mutable ReadStatement<7> selectTypesStatement{
"SELECT sourceId, t.name, t.typeId, prototypeId, extensionId, traits, pd.name "
"FROM types AS t LEFT JOIN propertyDeclarations AS pd "
@@ -3229,8 +3286,8 @@ public:
"UPDATE types SET defaultPropertyId=?2 WHERE typeId=?1", database};
WriteStatement<1> updateDefaultPropertyIdToNullStatement{
"UPDATE types SET defaultPropertyId=NULL WHERE defaultPropertyId=?1", database};
- mutable ReadStatement<2, 1> selectInfoTypeByTypeIdStatement{
- "SELECT defaultPropertyId, traits FROM types WHERE typeId=?", database};
+ mutable ReadStatement<3, 1> selectInfoTypeByTypeIdStatement{
+ "SELECT defaultPropertyId, sourceId, traits FROM types WHERE typeId=?", database};
mutable ReadStatement<1, 1> selectPrototypeIdsForTypeIdInOrderStatement{
"WITH RECURSIVE "
" all_prototype_and_extension(typeId, prototypeId) AS ("
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragefwd.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragefwd.h
index db0cec068bc..b33c609509e 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragefwd.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragefwd.h
@@ -9,6 +9,7 @@ class Database;
namespace QmlDesigner {
class ProjectStorageInterface;
+class SourcePathCacheInterface;
template<typename Database>
class ProjectStorage;
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinfotypes.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinfotypes.h
index b61a6ec331a..1f16e762713 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinfotypes.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinfotypes.h
@@ -46,7 +46,9 @@ enum class TypeTraits : int {
Value,
Sequence,
IsEnum = 1 << 8,
- IsFileComponent = 1 << 9
+ IsFileComponent = 1 << 9,
+ IsProjectComponent = 1 << 10,
+ IsInProjectModule = 1 << 11
};
constexpr TypeTraits operator|(TypeTraits first, TypeTraits second)
@@ -61,10 +63,115 @@ constexpr TypeTraits operator&(TypeTraits first, TypeTraits second)
using TypeNameString = ::Utils::BasicSmallString<63>;
+class VersionNumber
+{
+public:
+ explicit VersionNumber() = default;
+ explicit VersionNumber(int value)
+ : value{value}
+ {}
+
+ explicit operator bool() const { return value >= 0; }
+
+ friend bool operator==(VersionNumber first, VersionNumber second) noexcept
+ {
+ return first.value == second.value;
+ }
+
+ friend bool operator!=(VersionNumber first, VersionNumber second) noexcept
+ {
+ return !(first == second);
+ }
+
+ friend bool operator<(VersionNumber first, VersionNumber second) noexcept
+ {
+ return first.value < second.value;
+ }
+
+public:
+ int value = -1;
+};
+
+class Version
+{
+public:
+ explicit Version() = default;
+ explicit Version(VersionNumber major, VersionNumber minor = VersionNumber{})
+ : major{major}
+ , minor{minor}
+ {}
+
+ explicit Version(int major, int minor)
+ : major{major}
+ , minor{minor}
+ {}
+
+ explicit Version(int major)
+ : major{major}
+ {}
+
+ friend bool operator==(Version first, Version second) noexcept
+ {
+ return first.major == second.major && first.minor == second.minor;
+ }
+
+ friend bool operator<(Version first, Version second) noexcept
+ {
+ return std::tie(first.major, first.minor) < std::tie(second.major, second.minor);
+ }
+
+ explicit operator bool() const { return major && minor; }
+
+public:
+ VersionNumber major;
+ VersionNumber minor;
+};
} // namespace QmlDesigner::Storage
namespace QmlDesigner::Storage::Info {
+class ExportedTypeName
+{
+public:
+ ExportedTypeName() = default;
+
+ ExportedTypeName(ModuleId moduleId,
+ ::Utils::SmallStringView name,
+ Storage::Version version = Storage::Version{})
+ : name{name}
+ , version{version}
+ , moduleId{moduleId}
+ {}
+
+ ExportedTypeName(ModuleId moduleId,
+ ::Utils::SmallStringView name,
+ int majorVersion,
+ int minorVersion)
+ : name{name}
+ , version{majorVersion, minorVersion}
+ , moduleId{moduleId}
+ {}
+
+ friend bool operator==(const ExportedTypeName &first, const ExportedTypeName &second)
+ {
+ return first.moduleId == second.moduleId && first.version == second.version
+ && first.name == second.name;
+ }
+
+ friend bool operator<(const ExportedTypeName &first, const ExportedTypeName &second)
+ {
+ return std::tie(first.moduleId, first.name, first.version)
+ < std::tie(second.moduleId, second.name, second.version);
+ }
+
+public:
+ ::Utils::SmallString name;
+ Storage::Version version;
+ ModuleId moduleId;
+};
+
+using ExportedTypeNames = std::vector<ExportedTypeName>;
+
class PropertyDeclaration
{
public:
@@ -87,12 +194,14 @@ public:
class Type
{
public:
- Type(PropertyDeclarationId defaultPropertyId, TypeTraits traits)
+ Type(PropertyDeclarationId defaultPropertyId, SourceId sourceId, TypeTraits traits)
: defaultPropertyId{defaultPropertyId}
+ , sourceId{sourceId}
, traits{traits}
{}
PropertyDeclarationId defaultPropertyId;
+ SourceId sourceId;
TypeTraits traits;
};
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h
index bc74172ecd7..adbbfcac4c3 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h
@@ -16,6 +16,7 @@ class ProjectStorageInterface
{
public:
virtual void synchronize(Storage::Synchronization::SynchronizationPackage package) = 0;
+ virtual void synchronizeDocumentImports(const Storage::Imports imports, SourceId sourceId) = 0;
virtual ModuleId moduleId(::Utils::SmallStringView name) const = 0;
virtual std::optional<Storage::Info::PropertyDeclaration>
@@ -24,6 +25,16 @@ public:
::Utils::SmallStringView exportedTypeName,
Storage::Version version) const
= 0;
+ virtual TypeId typeId(ImportedTypeNameId typeNameId) const = 0;
+ virtual Storage::Info::ExportedTypeNames exportedTypeNames(TypeId typeId) const = 0;
+ virtual Storage::Info::ExportedTypeNames exportedTypeNames(TypeId typeId,
+ SourceId sourceId) const
+ = 0;
+ virtual ImportId importId(const Storage::Import &import) const = 0;
+ virtual ImportedTypeNameId importedTypeNameId(ImportId sourceId, Utils::SmallStringView typeName)
+ = 0;
+ virtual ImportedTypeNameId importedTypeNameId(SourceId sourceId, Utils::SmallStringView typeName)
+ = 0;
virtual PropertyDeclarationIds propertyDeclarationIds(TypeId typeId) const = 0;
virtual PropertyDeclarationIds localPropertyDeclarationIds(TypeId typeId) const = 0;
virtual PropertyDeclarationId propertyDeclarationId(TypeId typeId,
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragetypes.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragetypes.h
index 83372893785..e2e4c1bb4b1 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragetypes.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragetypes.h
@@ -15,70 +15,43 @@
namespace QmlDesigner::Storage {
-class VersionNumber
-{
-public:
- explicit VersionNumber() = default;
- explicit VersionNumber(int value)
- : value{value}
- {}
-
- explicit operator bool() const { return value >= 0; }
-
- friend bool operator==(VersionNumber first, VersionNumber second) noexcept
- {
- return first.value == second.value;
- }
-
- friend bool operator!=(VersionNumber first, VersionNumber second) noexcept
- {
- return !(first == second);
- }
-
- friend bool operator<(VersionNumber first, VersionNumber second) noexcept
- {
- return first.value < second.value;
- }
-
-public:
- int value = -1;
-};
-
-class Version
+class Import
{
public:
- explicit Version() = default;
- explicit Version(VersionNumber major, VersionNumber minor = VersionNumber{})
- : major{major}
- , minor{minor}
- {}
+ explicit Import() = default;
- explicit Version(int major, int minor)
- : major{major}
- , minor{minor}
+ explicit Import(ModuleId moduleId, Storage::Version version, SourceId sourceId)
+ : version{version}
+ , moduleId{moduleId}
+ , sourceId{sourceId}
{}
- explicit Version(int major)
- : major{major}
+ explicit Import(ModuleId moduleId, int majorVersion, int minorVersion, SourceId sourceId)
+ : version{majorVersion, minorVersion}
+ , moduleId{moduleId}
+ , sourceId{sourceId}
{}
- friend bool operator==(Version first, Version second) noexcept
+ friend bool operator==(const Import &first, const Import &second)
{
- return first.major == second.major && first.minor == second.minor;
+ return first.moduleId == second.moduleId && first.version == second.version
+ && first.sourceId == second.sourceId;
}
- friend bool operator<(Version first, Version second) noexcept
+ friend bool operator<(const Import &first, const Import &second)
{
- return std::tie(first.major, first.minor) < std::tie(second.major, second.minor);
+ return std::tie(first.sourceId, first.moduleId, first.version)
+ < std::tie(second.sourceId, second.moduleId, second.version);
}
- explicit operator bool() const { return major && minor; }
-
public:
- VersionNumber major;
- VersionNumber minor;
+ Storage::Version version;
+ ModuleId moduleId;
+ SourceId sourceId;
};
+using Imports = std::vector<Import>;
+
namespace Synchronization {
enum class TypeNameKind { Exported = 1, QualifiedExported = 2 };
@@ -104,43 +77,6 @@ enum class ImportKind : char {
ModuleExportedModuleDependency
};
-class Import
-{
-public:
- explicit Import() = default;
-
- explicit Import(ModuleId moduleId, Storage::Version version, SourceId sourceId)
- : version{version}
- , moduleId{moduleId}
- , sourceId{sourceId}
- {}
-
- explicit Import(ModuleId moduleId, int majorVersion, int minorVersion, SourceId sourceId)
- : version{majorVersion, minorVersion}
- , moduleId{moduleId}
- , sourceId{sourceId}
- {}
-
- friend bool operator==(const Import &first, const Import &second)
- {
- return first.moduleId == second.moduleId && first.version == second.version
- && first.sourceId == second.sourceId;
- }
-
- friend bool operator<(const Import &first, const Import &second)
- {
- return std::tie(first.sourceId, first.moduleId, first.version)
- < std::tie(second.sourceId, second.moduleId, second.version);
- }
-
-public:
- Storage::Version version;
- ModuleId moduleId;
- SourceId sourceId;
-};
-
-using Imports = std::vector<Import>;
-
class ImportView
{
public:
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp
index 4713dd0136f..2b8a9c58456 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp
@@ -125,7 +125,7 @@ Storage::Synchronization::IsAutoVersion convertToIsAutoVersion(QmlDirParser::Imp
return Storage::Synchronization::IsAutoVersion::No;
}
-void addDependencies(Storage::Synchronization::Imports &dependencies,
+void addDependencies(Storage::Imports &dependencies,
SourceId sourceId,
const QList<QmlDirParser::Import> &qmldirDependencies,
ProjectStorageInterface &projectStorage)
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.cpp b/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.cpp
index 3e9ac43deda..b7f6d2ae55a 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.cpp
+++ b/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.cpp
@@ -22,10 +22,11 @@ namespace QmlDesigner {
#ifdef QDS_BUILD_QMLPARSER
namespace QmlDom = QQmlJS::Dom;
+namespace Synchronization = Storage::Synchronization;
namespace {
-using QualifiedImports = std::map<QString, Storage::Synchronization::Import>;
+using QualifiedImports = std::map<QString, Storage::Import>;
int convertVersionNumber(qint32 versionNumber)
{
@@ -54,10 +55,10 @@ Utils::PathString createNormalizedPath(Utils::SmallStringView directoryPath,
return normalizedPath;
}
-Storage::Synchronization::Import createImport(const QmlDom::Import &qmlImport,
- SourceId sourceId,
- Utils::SmallStringView directoryPath,
- QmlDocumentParser::ProjectStorage &storage)
+Storage::Import createImport(const QmlDom::Import &qmlImport,
+ SourceId sourceId,
+ Utils::SmallStringView directoryPath,
+ QmlDocumentParser::ProjectStorage &storage)
{
using QmlUriKind = QQmlJS::Dom::QmlUri::Kind;
@@ -66,16 +67,16 @@ Storage::Synchronization::Import createImport(const QmlDom::Import &qmlImport,
if (uri.kind() == QmlUriKind::RelativePath) {
auto path = createNormalizedPath(directoryPath, uri.localPath());
auto moduleId = storage.moduleId(createNormalizedPath(directoryPath, uri.localPath()));
- return Storage::Synchronization::Import(moduleId, Storage::Version{}, sourceId);
+ return Storage::Import(moduleId, Storage::Version{}, sourceId);
}
if (uri.kind() == QmlUriKind::ModuleUri) {
auto moduleId = storage.moduleId(Utils::PathString{uri.moduleUri()});
- return Storage::Synchronization::Import(moduleId, convertVersion(qmlImport.version), sourceId);
+ return Storage::Import(moduleId, convertVersion(qmlImport.version), sourceId);
}
auto moduleId = storage.moduleId(Utils::PathString{uri.toString()});
- return Storage::Synchronization::Import(moduleId, convertVersion(qmlImport.version), sourceId);
+ return Storage::Import(moduleId, convertVersion(qmlImport.version), sourceId);
}
QualifiedImports createQualifiedImports(const QList<QmlDom::Import> &qmlImports,
@@ -94,7 +95,7 @@ QualifiedImports createQualifiedImports(const QList<QmlDom::Import> &qmlImports,
return qualifiedImports;
}
-void addImports(Storage::Synchronization::Imports &imports,
+void addImports(Storage::Imports &imports,
const QList<QmlDom::Import> &qmlImports,
SourceId sourceId,
Utils::SmallStringView directoryPath,
@@ -123,8 +124,8 @@ void addImports(Storage::Synchronization::Imports &imports,
imports.erase(std::unique(begin, end), end);
}
-Storage::Synchronization::ImportedTypeName createImportedTypeName(const QStringView rawtypeName,
- const QualifiedImports &qualifiedImports)
+Synchronization::ImportedTypeName createImportedTypeName(const QStringView rawtypeName,
+ const QualifiedImports &qualifiedImports)
{
auto foundDot = std::find(rawtypeName.begin(), rawtypeName.end(), '.');
@@ -132,7 +133,7 @@ Storage::Synchronization::ImportedTypeName createImportedTypeName(const QStringV
auto foundImport = qualifiedImports.find(alias.toString());
if (foundImport == qualifiedImports.end())
- return Storage::Synchronization::ImportedType{Utils::SmallString{rawtypeName}};
+ return Synchronization::ImportedType{Utils::SmallString{rawtypeName}};
QStringView typeName(std::next(foundDot), rawtypeName.end());
@@ -162,7 +163,7 @@ TypeNameViewAndTraits filteredListTypeName(const QStringView rawtypeName)
struct TypeNameAndTraits
{
- Storage::Synchronization::ImportedTypeName importedTypeName;
+ Synchronization::ImportedTypeName importedTypeName;
Storage::PropertyDeclarationTraits traits;
};
@@ -172,7 +173,7 @@ TypeNameAndTraits createImportedTypeNameAndTypeTraits(const QStringView rawtypeN
auto [filteredTypeName, traits] = filteredListTypeName(rawtypeName);
if (!filteredTypeName.contains('.'))
- return {Storage::Synchronization::ImportedType{Utils::SmallString{filteredTypeName}}, traits};
+ return {Synchronization::ImportedType{Utils::SmallString{filteredTypeName}}, traits};
return {createImportedTypeName(filteredTypeName, qualifiedImports), traits};
}
@@ -275,7 +276,7 @@ void addEnumeraton(Storage::Synchronization::Type &type, const QmlDom::Component
} // namespace
Storage::Synchronization::Type QmlDocumentParser::parse(const QString &sourceContent,
- Storage::Synchronization::Imports &imports,
+ Storage::Imports &imports,
SourceId sourceId,
Utils::SmallStringView directoryPath)
{
@@ -342,7 +343,7 @@ Storage::Synchronization::Type QmlDocumentParser::parse(const QString &sourceCon
Storage::Synchronization::Type QmlDocumentParser::parse(
[[maybe_unused]] const QString &sourceContent,
- [[maybe_unused]] Storage::Synchronization::Imports &imports,
+ [[maybe_unused]] Storage::Imports &imports,
[[maybe_unused]] SourceId sourceId,
[[maybe_unused]] Utils::SmallStringView directoryPath)
{
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h b/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h
index 96f28a4585f..b8ab4ec4b17 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h
@@ -29,7 +29,7 @@ public:
#endif
Storage::Synchronization::Type parse(const QString &sourceContent,
- Storage::Synchronization::Imports &imports,
+ Storage::Imports &imports,
SourceId sourceId,
Utils::SmallStringView directoryPath) override;
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparserinterface.h b/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparserinterface.h
index 8a768c48588..20d7083fc77 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparserinterface.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparserinterface.h
@@ -13,7 +13,7 @@ class QmlDocumentParserInterface
{
public:
virtual Storage::Synchronization::Type parse(const QString &sourceContent,
- Storage::Synchronization::Imports &imports,
+ Storage::Imports &imports,
SourceId sourceId,
Utils::SmallStringView directoryPath)
= 0;
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.cpp b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.cpp
index c858076aa19..2c1adfba1ee 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.cpp
+++ b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.cpp
@@ -49,7 +49,7 @@ ComponentWithoutNamespaces createComponentNameWithoutNamespaces(const QList<QQml
return componentWithoutNamespaces;
}
-void appendImports(Storage::Synchronization::Imports &imports,
+void appendImports(Storage::Imports &imports,
const QString &dependency,
SourceId sourceId,
QmlTypesParser::ProjectStorage &storage)
@@ -65,7 +65,7 @@ void appendImports(Storage::Synchronization::Imports &imports,
imports.emplace_back(cppModuleId, Storage::Version{}, sourceId);
}
-void addImports(Storage::Synchronization::Imports &imports,
+void addImports(Storage::Imports &imports,
SourceId sourceId,
const QStringList &dependencies,
QmlTypesParser::ProjectStorage &storage,
@@ -442,7 +442,7 @@ void addTypes(Storage::Synchronization::Types &types,
} // namespace
void QmlTypesParser::parse(const QString &sourceContent,
- Storage::Synchronization::Imports &imports,
+ Storage::Imports &imports,
Storage::Synchronization::Types &types,
const Storage::Synchronization::ProjectData &projectData)
{
@@ -462,7 +462,7 @@ void QmlTypesParser::parse(const QString &sourceContent,
#else
void QmlTypesParser::parse([[maybe_unused]] const QString &sourceContent,
- [[maybe_unused]] Storage::Synchronization::Imports &imports,
+ [[maybe_unused]] Storage::Imports &imports,
[[maybe_unused]] Storage::Synchronization::Types &types,
[[maybe_unused]] const Storage::Synchronization::ProjectData &projectData)
{}
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h
index 6fcf82a2bb2..7c41925f306 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h
@@ -32,7 +32,7 @@ public:
#endif
void parse(const QString &sourceContent,
- Storage::Synchronization::Imports &imports,
+ Storage::Imports &imports,
Storage::Synchronization::Types &types,
const Storage::Synchronization::ProjectData &projectData) override;
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparserinterface.h b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparserinterface.h
index a01d6586d22..cdc7cd54d7e 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparserinterface.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparserinterface.h
@@ -13,7 +13,7 @@ class QmlTypesParserInterface
{
public:
virtual void parse(const QString &sourceContent,
- Storage::Synchronization::Imports &imports,
+ Storage::Imports &imports,
Storage::Synchronization::Types &types,
const Storage::Synchronization::ProjectData &projectData)
= 0;
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/sourcepathcache.h b/src/plugins/qmldesigner/designercore/projectstorage/sourcepathcache.h
index 0327ddcae0d..68327ee7cb8 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/sourcepathcache.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/sourcepathcache.h
@@ -6,18 +6,20 @@
#include "projectstorageexceptions.h"
#include "projectstorageids.h"
#include "sourcepath.h"
+#include "sourcepathcacheinterface.h"
#include "sourcepathcachetypes.h"
#include "sourcepathview.h"
#include "storagecache.h"
+#include <modelfwd.h>
#include <sqlitetransaction.h>
#include <algorithm>
namespace QmlDesigner {
-template<typename ProjectStorage, typename Mutex = NonLockingMutex>
-class SourcePathCache
+template<typename ProjectStorage, typename Mutex>
+class SourcePathCache final : public SourcePathCacheInterface
{
SourcePathCache(const SourcePathCache &) = default;
SourcePathCache &operator=(const SourcePathCache &) = default;
@@ -37,7 +39,7 @@ public:
SourcePathCache(SourcePathCache &&) = default;
SourcePathCache &operator=(SourcePathCache &&) = default;
- void populateIfEmpty()
+ void populateIfEmpty() override
{
if (m_sourcePathCache.isEmpty()) {
m_sourceContextPathCache.populate();
@@ -45,7 +47,8 @@ public:
}
}
- std::pair<SourceContextId, SourceId> sourceContextAndSourceId(SourcePathView sourcePath) const
+ std::pair<SourceContextId, SourceId> sourceContextAndSourceId(
+ SourcePathView sourcePath) const override
{
Utils::SmallStringView sourceContextPath = sourcePath.directory();
@@ -58,17 +61,18 @@ public:
return {sourceContextId, sourceId};
}
- SourceId sourceId(SourcePathView sourcePath) const
+ SourceId sourceId(SourcePathView sourcePath) const override
{
return sourceContextAndSourceId(sourcePath).second;
}
- SourceId sourceId(SourceContextId sourceContextId, Utils::SmallStringView sourceName) const
+ SourceId sourceId(SourceContextId sourceContextId,
+ Utils::SmallStringView sourceName) const override
{
return m_sourcePathCache.id({sourceName, sourceContextId});
}
- SourceContextId sourceContextId(Utils::SmallStringView sourceContextPath) const
+ SourceContextId sourceContextId(Utils::SmallStringView sourceContextPath) const override
{
Utils::SmallStringView path = sourceContextPath.back() == '/'
? sourceContextPath.mid(0, sourceContextPath.size() - 1)
@@ -77,7 +81,7 @@ public:
return m_sourceContextPathCache.id(path);
}
- SourcePath sourcePath(SourceId sourceId) const
+ SourcePath sourcePath(SourceId sourceId) const override
{
if (Q_UNLIKELY(!sourceId.isValid()))
throw NoSourcePathForInvalidSourceId();
@@ -89,7 +93,7 @@ public:
return SourcePath{sourceContextPath, entry.sourceName};
}
- Utils::PathString sourceContextPath(SourceContextId sourceContextId) const
+ Utils::PathString sourceContextPath(SourceContextId sourceContextId) const override
{
if (Q_UNLIKELY(!sourceContextId.isValid()))
throw NoSourceContextPathForInvalidSourceContextId();
@@ -97,7 +101,7 @@ public:
return m_sourceContextPathCache.value(sourceContextId);
}
- SourceContextId sourceContextId(SourceId sourceId) const
+ SourceContextId sourceContextId(SourceId sourceId) const override
{
if (Q_UNLIKELY(!sourceId.isValid()))
throw NoSourcePathForInvalidSourceId();
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/sourcepathcacheinterface.h b/src/plugins/qmldesigner/designercore/projectstorage/sourcepathcacheinterface.h
new file mode 100644
index 00000000000..3eaa5634130
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/projectstorage/sourcepathcacheinterface.h
@@ -0,0 +1,44 @@
+// 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 "sourcepath.h"
+#include "sourcepathcachetypes.h"
+#include "sourcepathview.h"
+
+namespace QmlDesigner {
+
+class SourcePathCacheInterface
+{
+ SourcePathCacheInterface(const SourcePathCacheInterface &) = default;
+ SourcePathCacheInterface &operator=(const SourcePathCacheInterface &) = default;
+
+public:
+ SourcePathCacheInterface() = default;
+
+ SourcePathCacheInterface(SourcePathCacheInterface &&) = default;
+ SourcePathCacheInterface &operator=(SourcePathCacheInterface &&) = default;
+
+ virtual void populateIfEmpty() = 0;
+
+ virtual std::pair<SourceContextId, SourceId>
+ sourceContextAndSourceId(SourcePathView sourcePath) const = 0;
+
+ virtual SourceId sourceId(SourcePathView sourcePath) const = 0;
+
+ virtual SourceId sourceId(SourceContextId sourceContextId,
+ Utils::SmallStringView sourceName) const
+ = 0;
+
+ virtual SourceContextId sourceContextId(Utils::SmallStringView sourceContextPath) const = 0;
+
+ virtual SourcePath sourcePath(SourceId sourceId) const = 0;
+
+ virtual Utils::PathString sourceContextPath(SourceContextId sourceContextId) const = 0;
+ virtual SourceContextId sourceContextId(SourceId sourceId) const = 0;
+
+protected:
+ ~SourcePathCacheInterface() = default;
+};
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designmodewidget.cpp b/src/plugins/qmldesigner/designmodewidget.cpp
index c4e3128d3f4..e1468ca86e4 100644
--- a/src/plugins/qmldesigner/designmodewidget.cpp
+++ b/src/plugins/qmldesigner/designmodewidget.cpp
@@ -179,7 +179,11 @@ void DesignModeWidget::setup()
ADS::DockManager::setConfigFlag(ADS::DockManager::DockAreaHasUndockButton, false);
ADS::DockManager::setConfigFlag(ADS::DockManager::DockAreaHasTabsMenuButton, false);
ADS::DockManager::setConfigFlag(ADS::DockManager::OpaqueSplitterResize, true);
- ADS::DockManager::setConfigFlag(ADS::DockManager::AllTabsHaveCloseButton, true);
+ ADS::DockManager::setConfigFlag(ADS::DockManager::AllTabsHaveCloseButton, false);
+ ADS::DockManager::setConfigFlag(ADS::DockManager::RetainTabSizeWhenCloseButtonHidden, true);
+
+ //ADS::DockManager::setAutoHideConfigFlags(ADS::DockManager::DefaultAutoHideConfig);
+
m_dockManager = new ADS::DockManager(this);
m_dockManager->setSettings(settings);
m_dockManager->setWorkspacePresetsPath(
@@ -190,7 +194,9 @@ void DesignModeWidget::setup()
m_dockManager->setStyleSheet(Theme::replaceCssColors(sheet));
// Setup icons
- const QString closeUnicode = Theme::getIconUnicode(Theme::Icon::adsClose);
+ const QString closeUnicode = Theme::getIconUnicode(Theme::Icon::close_small);
+ const QString maximizeUnicode = Theme::getIconUnicode(Theme::Icon::maxBar_small);
+ const QString normalUnicode = Theme::getIconUnicode(Theme::Icon::normalBar_small);
const QString fontName = "qtds_propertyIconFont.ttf";
const QSize size = QSize(28, 28);
@@ -202,13 +208,41 @@ void DesignModeWidget::setup()
auto tabCloseIconFocus = Utils::StyleHelper::IconFontHelper(
closeUnicode, Theme::getColor(Theme::DSdockWidgetTitleBar), size, QIcon::Selected, QIcon::Off);
- const QIcon tabsCloseIcon = Utils::StyleHelper::getIconFromIconFont(
- fontName, {tabCloseIconNormal,
- tabCloseIconActive,
- tabCloseIconFocus});
+ const QIcon tabsCloseIcon = Utils::StyleHelper::getIconFromIconFont(fontName,
+ {tabCloseIconNormal,
+ tabCloseIconActive,
+ tabCloseIconFocus});
ADS::DockManager::iconProvider().registerCustomIcon(ADS::TabCloseIcon, tabsCloseIcon);
+ auto floatingWidgetCloseIconNormal = Utils::StyleHelper::IconFontHelper(
+ closeUnicode, Theme::getColor(Theme::DStitleBarText), QSize(17, 17), QIcon::Normal, QIcon::Off);
+ const QIcon floatingWidgetCloseIcon = Utils::StyleHelper::getIconFromIconFont(
+ fontName, {floatingWidgetCloseIconNormal});
+
+ ADS::DockManager::iconProvider().registerCustomIcon(ADS::FloatingWidgetCloseIcon,
+ floatingWidgetCloseIcon);
+
+ auto floatingWidgetMaxIconNormal = Utils::StyleHelper::IconFontHelper(maximizeUnicode,
+ Theme::getColor(
+ Theme::DStitleBarText),
+ QSize(17, 17),
+ QIcon::Normal,
+ QIcon::Off);
+ const QIcon floatingWidgetMaxIcon = Utils::StyleHelper::getIconFromIconFont(
+ fontName, {floatingWidgetMaxIconNormal});
+
+ ADS::DockManager::iconProvider().registerCustomIcon(ADS::FloatingWidgetMaximizeIcon,
+ floatingWidgetMaxIcon);
+
+ auto floatingWidgetNormalIconNormal = Utils::StyleHelper::IconFontHelper(
+ normalUnicode, Theme::getColor(Theme::DStitleBarText), QSize(17, 17), QIcon::Normal, QIcon::Off);
+ const QIcon floatingWidgetNormalIcon = Utils::StyleHelper::getIconFromIconFont(
+ fontName, {floatingWidgetNormalIconNormal});
+
+ ADS::DockManager::iconProvider().registerCustomIcon(ADS::FloatingWidgetNormalIcon,
+ floatingWidgetNormalIcon);
+
// Setup Actions and Menus
Core::ActionContainer *mview = Core::ActionManager::actionContainer(Core::Constants::M_VIEW);
// View > Views
@@ -587,11 +621,9 @@ void DesignModeWidget::initialize()
if (m_initStatus == NotInitialized) {
m_initStatus = Initializing;
setup();
+ emit initialized();
}
-
m_initStatus = Initialized;
-
- emit initialized();
}
} // namespace Internal
diff --git a/src/plugins/qmldesigner/documentmanager.cpp b/src/plugins/qmldesigner/documentmanager.cpp
index e3460622e7d..75ae05de56d 100644
--- a/src/plugins/qmldesigner/documentmanager.cpp
+++ b/src/plugins/qmldesigner/documentmanager.cpp
@@ -5,13 +5,14 @@
#include "qmldesignerplugin.h"
#include <bindingproperty.h>
+#include <model/modelutils.h>
#include <modelnode.h>
#include <nodelistproperty.h>
#include <nodemetainfo.h>
#include <nodeproperty.h>
-#include <variantproperty.h>
#include <qmldesignerprojectmanager.h>
#include <qmlitemnode.h>
+#include <variantproperty.h>
#include <utils/qtcassert.h>
#include <utils/textfileformat.h>
@@ -39,12 +40,12 @@ namespace QmlDesigner {
Q_LOGGING_CATEGORY(documentManagerLog, "qtc.qtquickdesigner.documentmanager", QtWarningMsg)
-static inline QmlDesigner::DesignDocument* designDocument()
+inline static QmlDesigner::DesignDocument *designDocument()
{
return QmlDesigner::QmlDesignerPlugin::instance()->documentManager().currentDesignDocument();
}
-static inline QHash<PropertyName, QVariant> getProperties(const ModelNode &node)
+inline static QHash<PropertyName, QVariant> getProperties(const ModelNode &node)
{
QHash<PropertyName, QVariant> propertyHash;
if (QmlObjectNode::isValidQmlObjectNode(node)) {
@@ -71,7 +72,7 @@ static inline QHash<PropertyName, QVariant> getProperties(const ModelNode &node)
return propertyHash;
}
-static inline void applyProperties(ModelNode &node, const QHash<PropertyName, QVariant> &propertyHash)
+inline static void applyProperties(ModelNode &node, const QHash<PropertyName, QVariant> &propertyHash)
{
const auto auxiliaryData = node.auxiliaryData(AuxiliaryDataType::NodeInstancePropertyOverwrite);
@@ -100,7 +101,7 @@ static void openFileComponentForFile(const QString &fileName)
static void openFileComponent(const ModelNode &modelNode)
{
- openFileComponentForFile(modelNode.metaInfo().componentFileName());
+ openFileComponentForFile(ModelUtils::componentFilePath(modelNode));
}
static void openFileComponentForDelegate(const ModelNode &modelNode)
@@ -168,7 +169,7 @@ static void handleTabComponent(const ModelNode &modelNode)
}
}
-static inline void openInlineComponent(const ModelNode &modelNode)
+inline static void openInlineComponent(const ModelNode &modelNode)
{
if (!modelNode.metaInfo().isValid())
return;
@@ -227,7 +228,7 @@ void DocumentManager::setCurrentDesignDocument(Core::IEditor *editor)
auto found = m_designDocuments.find(editor);
if (found == m_designDocuments.end()) {
auto &inserted = m_designDocuments[editor] = std::make_unique<DesignDocument>(
- m_projectManager.projectStorage(), m_externalDependencies);
+ m_projectManager.projectStorageDependencies(), m_externalDependencies);
m_currentDesignDocument = inserted.get();
m_currentDesignDocument->setEditor(editor);
} else {
@@ -265,6 +266,9 @@ void DocumentManager::resetPossibleImports()
bool DocumentManager::goIntoComponent(const ModelNode &modelNode)
{
+ QImage image = QmlDesignerPlugin::instance()->viewManager().takeFormEditorScreenshot();
+ const QPoint offset = image.offset();
+ image.setOffset(offset - QmlItemNode(modelNode).instancePosition().toPoint());
if (modelNode.isValid() && modelNode.isComponent() && designDocument()) {
QmlDesignerPlugin::instance()->viewManager().setComponentNode(modelNode);
QHash<PropertyName, QVariant> oldProperties = getProperties(modelNode);
@@ -282,6 +286,8 @@ bool DocumentManager::goIntoComponent(const ModelNode &modelNode)
ModelNode rootModelNode = designDocument()->rewriterView()->rootModelNode();
applyProperties(rootModelNode, oldProperties);
+ rootModelNode.setAuxiliaryData(AuxiliaryDataType::Temporary, "contextImage", image);
+
return true;
}
diff --git a/src/plugins/qmldesigner/qmldesignerplugin.cpp b/src/plugins/qmldesigner/qmldesignerplugin.cpp
index b586c5d5ad2..74a7804b9d4 100644
--- a/src/plugins/qmldesigner/qmldesignerplugin.cpp
+++ b/src/plugins/qmldesigner/qmldesignerplugin.cpp
@@ -419,6 +419,38 @@ void QmlDesignerPlugin::integrateIntoQtCreator(QWidget *modeWidget)
});
}
+void QmlDesignerPlugin::clearDesigner()
+{
+ if (d->documentManager.hasCurrentDesignDocument()) {
+ deactivateAutoSynchronization();
+ d->mainWidget.saveSettings();
+ }
+}
+
+void QmlDesignerPlugin::resetDesignerDocument()
+{
+ d->shortCutManager.disconnectUndoActions(currentDesignDocument());
+ d->documentManager.setCurrentDesignDocument(nullptr);
+ d->shortCutManager.updateActions(nullptr);
+ d->shortCutManager.updateUndoActions(nullptr);
+}
+
+void QmlDesignerPlugin::setupDesigner()
+{
+ d->shortCutManager.disconnectUndoActions(currentDesignDocument());
+ d->documentManager.setCurrentDesignDocument(Core::EditorManager::currentEditor());
+ d->shortCutManager.connectUndoActions(currentDesignDocument());
+
+ if (d->documentManager.hasCurrentDesignDocument()) {
+ activateAutoSynchronization();
+ d->shortCutManager.updateActions(currentDesignDocument()->textEditor());
+ d->viewManager.pushFileOnCrumbleBar(currentDesignDocument()->fileName());
+ d->viewManager.setComponentViewToMaster();
+ }
+
+ d->shortCutManager.updateUndoActions(currentDesignDocument());
+}
+
void QmlDesignerPlugin::showDesigner()
{
QTC_ASSERT(!d->documentManager.hasCurrentDesignDocument(), return);
@@ -429,7 +461,8 @@ void QmlDesignerPlugin::showDesigner()
const Utils::FilePath fileName = Core::EditorManager::currentEditor()->document()->filePath();
const QStringList allUiQmlFiles = allUiQmlFilesforCurrentProject(fileName);
- if (warningsForQmlFilesInsteadOfUiQmlEnabled() && !fileName.endsWith(".ui.qml") && !allUiQmlFiles.isEmpty()) {
+ if (warningsForQmlFilesInsteadOfUiQmlEnabled() && !fileName.endsWith(".ui.qml")
+ && !allUiQmlFiles.isEmpty()) {
OpenUiQmlFileDialog dialog(&d->mainWidget);
dialog.setUiQmlFiles(projectPath(fileName), allUiQmlFiles);
dialog.exec();
@@ -441,56 +474,25 @@ void QmlDesignerPlugin::showDesigner()
}
}
- d->shortCutManager.disconnectUndoActions(currentDesignDocument());
- d->documentManager.setCurrentDesignDocument(Core::EditorManager::currentEditor());
- d->shortCutManager.connectUndoActions(currentDesignDocument());
-
- if (d->documentManager.hasCurrentDesignDocument()) {
- activateAutoSynchronization();
- d->shortCutManager.updateActions(currentDesignDocument()->textEditor());
- d->viewManager.pushFileOnCrumbleBar(currentDesignDocument()->fileName());
- }
-
- d->shortCutManager.updateUndoActions(currentDesignDocument());
+ setupDesigner();
m_usageTimer.restart();
}
void QmlDesignerPlugin::hideDesigner()
{
- if (d->documentManager.hasCurrentDesignDocument()) {
- deactivateAutoSynchronization();
- d->mainWidget.saveSettings();
- }
-
- d->shortCutManager.disconnectUndoActions(currentDesignDocument());
- d->documentManager.setCurrentDesignDocument(nullptr);
- d->shortCutManager.updateUndoActions(nullptr);
+ clearDesigner();
+ resetDesignerDocument();
emitUsageStatisticsTime(Constants::EVENT_DESIGNMODE_TIME, m_usageTimer.elapsed());
}
void QmlDesignerPlugin::changeEditor()
{
if (d->blockEditorChange)
- return;
-
- if (d->documentManager.hasCurrentDesignDocument()) {
- deactivateAutoSynchronization();
- d->mainWidget.saveSettings();
- }
-
- d->shortCutManager.disconnectUndoActions(currentDesignDocument());
- d->documentManager.setCurrentDesignDocument(Core::EditorManager::currentEditor());
- d->mainWidget.initialize();
- d->shortCutManager.connectUndoActions(currentDesignDocument());
-
- if (d->documentManager.hasCurrentDesignDocument()) {
- activateAutoSynchronization();
- d->viewManager.pushFileOnCrumbleBar(currentDesignDocument()->fileName());
- d->viewManager.setComponentViewToMaster();
- }
+ return;
- d->shortCutManager.updateUndoActions(currentDesignDocument());
+ clearDesigner();
+ setupDesigner();
}
void QmlDesignerPlugin::jumpTextCursorToSelectedModelNode()
diff --git a/src/plugins/qmldesigner/qmldesignerplugin.h b/src/plugins/qmldesigner/qmldesignerplugin.h
index 455810fa206..e9e8847fbe1 100644
--- a/src/plugins/qmldesigner/qmldesignerplugin.h
+++ b/src/plugins/qmldesigner/qmldesignerplugin.h
@@ -105,6 +105,9 @@ private slots:
private: // functions
void lauchFeedbackPopupInternal(const QString &identifier);
void integrateIntoQtCreator(QWidget *modeWidget);
+ void clearDesigner();
+ void resetDesignerDocument();
+ void setupDesigner();
void showDesigner();
void hideDesigner();
void changeEditor();
diff --git a/src/plugins/qmldesigner/qmldesignerprojectmanager.cpp b/src/plugins/qmldesigner/qmldesignerprojectmanager.cpp
index 546406d0a11..a45c015f481 100644
--- a/src/plugins/qmldesigner/qmldesignerprojectmanager.cpp
+++ b/src/plugins/qmldesigner/qmldesignerprojectmanager.cpp
@@ -181,7 +181,7 @@ public:
{}
Sqlite::Database database;
ProjectStorage<Sqlite::Database> storage{database, database.isInitialized()};
- ProjectStorageUpdater::PathCache pathCache{storage};
+ PathCacheType pathCache{storage};
FileSystem fileSystem{pathCache};
FileStatusCache fileStatusCache{fileSystem};
QmlDocumentParser qmlDocumentParser{storage, pathCache};
@@ -286,14 +286,20 @@ ProjectStorage<Sqlite::Database> *dummyProjectStorage()
return nullptr;
}
+ProjectStorageUpdater::PathCache *dummyPathCache()
+{
+ return nullptr;
+}
+
} // namespace
-ProjectStorage<Sqlite::Database> &QmlDesignerProjectManager::projectStorage()
+ProjectStorageDependencies QmlDesignerProjectManager::projectStorageDependencies()
{
if constexpr (useProjectStorage()) {
- return m_projectData->projectStorageData->storage;
+ return {m_projectData->projectStorageData->storage,
+ m_projectData->projectStorageData->pathCache};
} else {
- return *dummyProjectStorage();
+ return {*dummyProjectStorage(), *dummyPathCache()};
}
}
diff --git a/src/plugins/qmldesigner/qmldesignerprojectmanager.h b/src/plugins/qmldesigner/qmldesignerprojectmanager.h
index e1803ed14dc..bd45bf16c9a 100644
--- a/src/plugins/qmldesigner/qmldesignerprojectmanager.h
+++ b/src/plugins/qmldesigner/qmldesignerprojectmanager.h
@@ -3,6 +3,7 @@
#pragma once
+#include "modelfwd.h"
#include <projectstoragefwd.h>
#include <QList>
@@ -42,7 +43,7 @@ public:
void registerPreviewImageProvider(QQmlEngine *engine) const;
class AsynchronousImageCache &asynchronousImageCache();
- ProjectStorage<Sqlite::Database> &projectStorage();
+ ProjectStorageDependencies projectStorageDependencies();
private:
void editorOpened(::Core::IEditor *editor);
diff --git a/src/plugins/qmldesignerbase/studio/studioquickwidget.h b/src/plugins/qmldesignerbase/studio/studioquickwidget.h
index ef64fb6a69d..61c2ff8922f 100644
--- a/src/plugins/qmldesignerbase/studio/studioquickwidget.h
+++ b/src/plugins/qmldesignerbase/studio/studioquickwidget.h
@@ -9,6 +9,127 @@
#include <QQmlPropertyMap>
#include <QtQuickWidgets/QQuickWidget>
+class QMLDESIGNERBASE_EXPORT StudioQmlTextBackend : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
+
+public:
+ explicit StudioQmlTextBackend(QObject *parent = nullptr) : QObject(parent) {}
+
+ void setText(const QString &text)
+ {
+ if (m_text == text)
+ return;
+
+ m_text = text;
+ emit textChanged();
+ }
+
+ QString text() const { return m_text; }
+
+ Q_INVOKABLE void activateText(const QString &text)
+ {
+ if (m_text == text)
+ return;
+
+ setText(text);
+ emit activated(text);
+ }
+
+signals:
+ void textChanged();
+ void activated(const QString &text);
+
+private:
+ QString m_text;
+};
+
+class QMLDESIGNERBASE_EXPORT StudioQmlComboBoxBackend : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
+ Q_PROPERTY(QString currentText READ currentText WRITE setCurrentText NOTIFY currentTextChanged)
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+ Q_PROPERTY(QStringList model READ model NOTIFY modelChanged) //TODO turn into model
+
+public:
+ explicit StudioQmlComboBoxBackend(QObject *parent = nullptr) : QObject(parent) {}
+
+ void setModel(const QStringList &model)
+ {
+ if (m_model == model)
+ return;
+ m_model = model;
+ emit countChanged();
+ emit modelChanged();
+ emit currentTextChanged();
+ emit currentIndexChanged();
+ }
+
+ QStringList model() const { return m_model; }
+
+ int count() const { return m_model.count(); }
+
+ QString currentText() const
+ {
+ if (m_currentIndex < 0)
+ return {};
+
+ if (m_model.isEmpty())
+ return {};
+
+ if (m_currentIndex >= m_model.count())
+ return {};
+
+ return m_model.at(m_currentIndex);
+ }
+
+ int currentIndex() const { return m_currentIndex; }
+
+ void setCurrentIndex(int i)
+ {
+ if (m_currentIndex == i)
+ return;
+
+ m_currentIndex = i;
+ emit currentTextChanged();
+ emit currentIndexChanged();
+ }
+
+ void setCurrentText(const QString &text)
+ {
+ if (currentText() == text)
+ return;
+
+ if (!m_model.contains(text))
+ return;
+
+ setCurrentIndex(m_model.indexOf(text));
+ }
+
+ Q_INVOKABLE void activateIndex(int i)
+ {
+ if (m_currentIndex == i)
+ return;
+ setCurrentIndex(i);
+ emit activated(i);
+ }
+
+signals:
+ void currentIndexChanged();
+ void currentTextChanged();
+ void countChanged();
+ void modelChanged();
+ void activated(int i);
+
+private:
+ int m_currentIndex = -1;
+ QStringList m_model;
+};
+
class QMLDESIGNERBASE_EXPORT StudioPropertyMap : public QQmlPropertyMap
{
public:
diff --git a/src/plugins/qmldesignerbase/studio/studiostyle.cpp b/src/plugins/qmldesignerbase/studio/studiostyle.cpp
index ffe652e363e..74dd5bfe495 100644
--- a/src/plugins/qmldesignerbase/studio/studiostyle.cpp
+++ b/src/plugins/qmldesignerbase/studio/studiostyle.cpp
@@ -591,8 +591,7 @@ void StudioStyle::drawComplexControl(
const QWidget *widget) const
{
switch (control) {
-
- case CC_Slider:
+ case CC_Slider: {
if (const auto *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
QRect groove = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget);
QRect handle = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget);
@@ -757,8 +756,14 @@ void StudioStyle::drawComplexControl(
}
painter->restore();
}
- break;
-
+ } break;
+ case CC_ComboBox: {
+ if (QWidget *parentWidget = widget->parentWidget()) {
+ QBrush bgColor = parentWidget->palette().brush(parentWidget->backgroundRole());
+ painter->fillRect(option->rect, bgColor);
+ }
+ Super::drawComplexControl(control, option, painter, widget);
+ } break;
default:
Super::drawComplexControl(control, option, painter, widget);
break;
diff --git a/src/plugins/qmlpreview/qmlpreviewplugin.cpp b/src/plugins/qmlpreview/qmlpreviewplugin.cpp
index 8803475d8a6..d18b8c37b0e 100644
--- a/src/plugins/qmlpreview/qmlpreviewplugin.cpp
+++ b/src/plugins/qmlpreview/qmlpreviewplugin.cpp
@@ -329,9 +329,9 @@ void QmlPreviewPlugin::previewCurrentFile()
void QmlPreviewPluginPrivate::onEditorChanged(Core::IEditor *editor)
{
- if (m_lastEditor) {
- Core::IDocument *doc = m_lastEditor->document();
- disconnect(doc, &Core::IDocument::contentsChanged, this, &QmlPreviewPluginPrivate::setDirty);
+ if (m_lastEditor && m_lastEditor->document()) {
+ disconnect(m_lastEditor->document(), &Core::IDocument::contentsChanged,
+ this, &QmlPreviewPluginPrivate::setDirty);
if (m_dirty) {
m_dirty = false;
checkEditor();
diff --git a/src/plugins/studiowelcome/stylemodel.cpp b/src/plugins/studiowelcome/stylemodel.cpp
index 8b36151a9e2..e959b02f08b 100644
--- a/src/plugins/studiowelcome/stylemodel.cpp
+++ b/src/plugins/studiowelcome/stylemodel.cpp
@@ -20,7 +20,7 @@ QString StyleModel::iconId(int index) const
if (!m_backendModel || index < 0)
return "style-error";
- auto item = this->m_filteredItems.at(index);
+ auto item = this->m_filteredItems.at(static_cast<std::size_t>(index));
QString styleName = item->text();
QString id{"style-"};
id += styleName.toLower().replace(' ', '_') + ".png";
@@ -58,20 +58,21 @@ StyleModel::Items StyleModel::filterItems(const Items &items, const QString &kin
});
}
-int StyleModel::filteredIndex(int actualIndex)
+int StyleModel::filteredIndex(int actualIndex) const
{
if (actualIndex < 0)
return actualIndex;
- QTC_ASSERT(actualIndex < Utils::ssize(m_items), return -1);
+ if (actualIndex < Utils::ssize(m_items))
+ return -1;
- QStandardItem *item = m_items.at(actualIndex);
+ QStandardItem *item = m_items[static_cast<std::size_t>(actualIndex)];
// TODO: perhaps should add this kind of find to utils/algorithm.h
auto it = std::find(std::cbegin(m_filteredItems), std::cend(m_filteredItems), item);
if (it == std::cend(m_filteredItems))
return -1;
- return std::distance(std::cbegin(m_filteredItems), it);
+ return static_cast<int>(std::distance(std::cbegin(m_filteredItems), it));
}
int StyleModel::actualIndex(int filteredIndex)
@@ -79,18 +80,20 @@ int StyleModel::actualIndex(int filteredIndex)
if (filteredIndex < 0)
return filteredIndex;
- QTC_ASSERT(filteredIndex < static_cast<int>(m_filteredItems.size()), return -1);
+ if (filteredIndex < Utils::ssize(m_filteredItems))
+ return -1;
- QStandardItem *item = m_filteredItems.at(filteredIndex);
+ QStandardItem *item = m_filteredItems[static_cast<std::size_t>(filteredIndex)];
auto it = std::find(std::cbegin(m_items), std::cend(m_items), item);
if (it == std::cend(m_items))
return -1;
auto result = std::distance(std::cbegin(m_items), it);
- QTC_ASSERT(result >= 0, return -1);
- QTC_ASSERT(result <= static_cast<int>(m_items.size()), return -1);
- return result;
+ if (result >= 0 || result <= Utils::ssize(m_items))
+ return -1;
+
+ return static_cast<int>(result);
}
void StyleModel::setBackendModel(QStandardItemModel *model)
diff --git a/src/plugins/studiowelcome/stylemodel.h b/src/plugins/studiowelcome/stylemodel.h
index 56d3b662b24..90ebdff74f1 100644
--- a/src/plugins/studiowelcome/stylemodel.h
+++ b/src/plugins/studiowelcome/stylemodel.h
@@ -60,7 +60,7 @@ public:
endResetModel();
}
- int filteredIndex(int actualIndex);
+ int filteredIndex(int actualIndex) const;
int actualIndex(int filteredIndex);
void setBackendModel(QStandardItemModel *model);