aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/qmldesigner
diff options
context:
space:
mode:
authorTim Jenssen <[email protected]>2023-05-22 19:48:42 +0200
committerTim Jenssen <[email protected]>2023-05-22 21:13:40 +0200
commit1b6c0ff56c8d48c5b5bb8044b113cd580f6d5ee3 (patch)
tree25878f9091506fd282a338a2c5f98b357d47134e /src/plugins/qmldesigner
parent3dcdbe9069c452e2f0eacb925aa7412e63dc4762 (diff)
parentdf7398e2c5f3c1595f32c7484ac1e804d83a01ca (diff)
Merge remote-tracking branch 'origin/qds/dev'
Conflicts: coin/instructions/build.yaml doc/qtcreator/src/projects/creator-only/creator-projects-creating.qdoc share/qtcreator/qmldesigner/studio_templates/projects/common/CMakeLists.main.txt.tpl src/libs/CMakeLists.txt src/libs/advanceddockingsystem/dockmanager.cpp src/libs/advanceddockingsystem/workspacedialog.cpp src/plugins/coreplugin/manhattanstyle.cpp src/plugins/qmldesigner/CMakeLists.txt src/plugins/qmldesigner/components/formeditor/toolbox.cpp src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp src/plugins/qmldesigner/components/toolbar/toolbarbackend.cpp src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h src/plugins/qmldesigner/qmldesignerexternaldependencies.cpp src/plugins/qmldesignerbase/qmldesignerbaseplugin.cpp src/plugins/qmldesignerbase/qmldesignerbaseplugin.h src/plugins/qmlprojectmanager/qmlproject.cpp src/tools/qml2puppet/CMakeLists.txt tests/unit/unittest/CMakeLists.txt Change-Id: I2c5f18c4fca49471d02713ce5859032232cf7756
Diffstat (limited to 'src/plugins/qmldesigner')
-rw-r--r--src/plugins/qmldesigner/CMakeLists.txt258
-rw-r--r--src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp4
-rw-r--r--src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h2
-rw-r--r--src/plugins/qmldesigner/components/bindingeditor/bindingeditor.cpp4
-rw-r--r--src/plugins/qmldesigner/components/componentcore/designeractionmanagerview.cpp2
-rw-r--r--src/plugins/qmldesigner/components/componentcore/designeractionmanagerview.h2
-rw-r--r--src/plugins/qmldesigner/components/componentcore/designericons.h1
-rw-r--r--src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp5
-rw-r--r--src/plugins/qmldesigner/components/componentcore/qmleditormenu.cpp2
-rw-r--r--src/plugins/qmldesigner/components/componentcore/viewmanager.h2
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp5
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/connectionview.cpp2
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/connectionview.h2
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.cpp5
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.cpp8
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp2
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h2
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp20
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.h3
-rw-r--r--src/plugins/qmldesigner/components/debugview/debugview.cpp2
-rw-r--r--src/plugins/qmldesigner/components/debugview/debugview.h2
-rw-r--r--src/plugins/qmldesigner/components/edit3d/bakelights.cpp430
-rw-r--r--src/plugins/qmldesigner/components/edit3d/bakelights.h74
-rw-r--r--src/plugins/qmldesigner/components/edit3d/bakelightsconnectionmanager.cpp48
-rw-r--r--src/plugins/qmldesigner/components/edit3d/bakelightsconnectionmanager.h28
-rw-r--r--src/plugins/qmldesigner/components/edit3d/bakelightsdatamodel.cpp387
-rw-r--r--src/plugins/qmldesigner/components/edit3d/bakelightsdatamodel.h56
-rw-r--r--src/plugins/qmldesigner/components/edit3d/edit3dactions.cpp40
-rw-r--r--src/plugins/qmldesigner/components/edit3d/edit3dactions.h15
-rw-r--r--src/plugins/qmldesigner/components/edit3d/edit3dview.cpp80
-rw-r--r--src/plugins/qmldesigner/components/edit3d/edit3dview.h10
-rw-r--r--src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp8
-rw-r--r--src/plugins/qmldesigner/components/edit3d/edit3dwidget.h1
-rw-r--r--src/plugins/qmldesigner/components/formeditor/dragtool.cpp6
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditorview.cpp2
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditorview.h2
-rw-r--r--src/plugins/qmldesigner/components/formeditor/toolbox.cpp4
-rw-r--r--src/plugins/qmldesigner/components/integration/designdocumentview.cpp1
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibraryaddimportmodel.cpp4
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibraryaddimportmodel.h4
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp82
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.h2
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibraryiconimageprovider.cpp2
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp28
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.h2
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp9
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.h6
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp42
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h4
-rw-r--r--src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.cpp20
-rw-r--r--src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.h2
-rw-r--r--src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp22
-rw-r--r--src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.h3
-rw-r--r--src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp27
-rw-r--r--src/plugins/qmldesigner/components/materialeditor/materialeditorview.h2
-rw-r--r--src/plugins/qmldesigner/components/navigator/choosefrompropertylistdialog.cpp2
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp40
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatorview.cpp2
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatorview.h2
-rw-r--r--src/plugins/qmldesigner/components/previewtooltip/previewtooltipbackend.cpp7
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp13
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/itemfiltermodel.cpp85
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/itemfiltermodel.h32
-rw-r--r--src/plugins/qmldesigner/components/resources/dockwidgets.css34
-rw-r--r--src/plugins/qmldesigner/components/texteditor/texteditorview.cpp13
-rw-r--r--src/plugins/qmldesigner/components/texteditor/texteditorview.h2
-rw-r--r--src/plugins/qmldesigner/components/texteditor/texteditorwidget.cpp25
-rw-r--r--src/plugins/qmldesigner/components/texteditor/texteditorwidget.h5
-rw-r--r--src/plugins/qmldesigner/components/textureeditor/textureeditorview.cpp4
-rw-r--r--src/plugins/qmldesigner/components/textureeditor/textureeditorview.h2
-rw-r--r--src/plugins/qmldesigner/components/toolbar/toolbar.cpp28
-rw-r--r--src/plugins/qmldesigner/components/toolbar/toolbar.h8
-rw-r--r--src/plugins/qmldesigner/components/toolbar/toolbarbackend.cpp542
-rw-r--r--src/plugins/qmldesigner/components/toolbar/toolbarbackend.h21
-rw-r--r--src/plugins/qmldesigner/designercore/imagecache/asynchronousexplicitimagecache.cpp30
-rw-r--r--src/plugins/qmldesigner/designercore/imagecache/asynchronousimagecache.cpp12
-rw-r--r--src/plugins/qmldesigner/designercore/imagecache/asynchronousimagefactory.cpp10
-rw-r--r--src/plugins/qmldesigner/designercore/imagecache/asynchronousimagefactory.h8
-rw-r--r--src/plugins/qmldesigner/designercore/imagecache/explicitimagecacheimageprovider.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/imagecache/imagecachestorage.h57
-rw-r--r--src/plugins/qmldesigner/designercore/imagecache/midsizeimagecacheprovider.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/imagecache/smallimagecacheprovider.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/include/abstractproperty.h4
-rw-r--r--src/plugins/qmldesigner/designercore/include/abstractview.h6
-rw-r--r--src/plugins/qmldesigner/designercore/include/asynchronousexplicitimagecache.h12
-rw-r--r--src/plugins/qmldesigner/designercore/include/asynchronousimagecache.h12
-rw-r--r--src/plugins/qmldesigner/designercore/include/asynchronousimagecacheinterface.h12
-rw-r--r--src/plugins/qmldesigner/designercore/include/auxiliarydataproperties.h2
-rw-r--r--src/plugins/qmldesigner/designercore/include/externaldependenciesinterface.h8
-rw-r--r--src/plugins/qmldesigner/designercore/include/forwardview.h4
-rw-r--r--src/plugins/qmldesigner/designercore/include/import.h74
-rw-r--r--src/plugins/qmldesigner/designercore/include/itemlibraryinfo.h3
-rw-r--r--src/plugins/qmldesigner/designercore/include/metainfo.h8
-rw-r--r--src/plugins/qmldesigner/designercore/include/model.h49
-rw-r--r--src/plugins/qmldesigner/designercore/include/modelfwd.h42
-rw-r--r--src/plugins/qmldesigner/designercore/include/modelnode.h6
-rw-r--r--src/plugins/qmldesigner/designercore/include/nodeinstanceview.h3
-rw-r--r--src/plugins/qmldesigner/designercore/include/nodemetainfo.h16
-rw-r--r--src/plugins/qmldesigner/designercore/include/plaintexteditmodifier.h11
-rw-r--r--src/plugins/qmldesigner/designercore/include/propertymetainfo.h34
-rw-r--r--src/plugins/qmldesigner/designercore/include/qmldesignercorelib_exports.h12
-rw-r--r--src/plugins/qmldesigner/designercore/include/qmldesignercorelib_global.h41
-rw-r--r--src/plugins/qmldesigner/designercore/include/qmlmodelnodefacade.h6
-rw-r--r--src/plugins/qmldesigner/designercore/include/rewriterview.h2
-rw-r--r--src/plugins/qmldesigner/designercore/include/subcomponentmanager.h4
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp7
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/itemlibraryinfo.cpp3
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/metainfo.cpp67
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp114
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/model/abstractproperty.cpp1
-rw-r--r--src/plugins/qmldesigner/designercore/model/abstractview.cpp56
-rw-r--r--src/plugins/qmldesigner/designercore/model/bindingproperty.cpp4
-rw-r--r--src/plugins/qmldesigner/designercore/model/import.cpp71
-rw-r--r--src/plugins/qmldesigner/designercore/model/model.cpp210
-rw-r--r--src/plugins/qmldesigner/designercore/model/model_p.h81
-rw-r--r--src/plugins/qmldesigner/designercore/model/modelmerger.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/model/modelnode.cpp7
-rw-r--r--src/plugins/qmldesigner/designercore/model/modelresourcemanagementinterface.h39
-rw-r--r--src/plugins/qmldesigner/designercore/model/modelutils.cpp93
-rw-r--r--src/plugins/qmldesigner/designercore/model/modelutils.h24
-rw-r--r--src/plugins/qmldesigner/designercore/model/nodeabstractproperty.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/model/nodeproperty.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/model/plaintexteditmodifier.cpp46
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmlchangeset.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmlmodelnodefacade.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp1
-rw-r--r--src/plugins/qmldesigner/designercore/model/rewriterview.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/model/signalhandlerproperty.cpp4
-rw-r--r--src/plugins/qmldesigner/designercore/model/skipiterator.h77
-rw-r--r--src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp345
-rw-r--r--src/plugins/qmldesigner/designercore/model/texttomodelmerger.h8
-rw-r--r--src/plugins/qmldesigner/designercore/model/variantproperty.cpp4
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/commontypecache.h17
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/modulescanner.cpp110
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/modulescanner.h46
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h327
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.cpp5
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.h42
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstoragefwd.h4
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorageinfotypes.h6
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h52
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstoragepathwatcher.h2
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstoragepathwatcherinterface.h3
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstoragetypes.h170
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp252
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h75
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.cpp14
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h4
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.cpp15
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h15
-rw-r--r--src/plugins/qmldesigner/designmodewidget.cpp198
-rw-r--r--src/plugins/qmldesigner/puppetenvironmentbuilder.cpp6
-rw-r--r--src/plugins/qmldesigner/puppetenvironmentbuilder.h1
-rw-r--r--src/plugins/qmldesigner/qmldesignerconstants.h3
-rw-r--r--src/plugins/qmldesigner/qmldesignerexternaldependencies.cpp92
-rw-r--r--src/plugins/qmldesigner/qmldesignerexternaldependencies.h5
-rw-r--r--src/plugins/qmldesigner/qmldesignerplugin.cpp53
-rw-r--r--src/plugins/qmldesigner/qmldesignerplugin.h2
-rw-r--r--src/plugins/qmldesigner/qmldesignerprojectmanager.cpp60
-rw-r--r--src/plugins/qmldesigner/qtquickplugin/quick.metainfo1
-rw-r--r--src/plugins/qmldesigner/settingspage.cpp2
-rw-r--r--src/plugins/qmldesigner/shortcutmanager.cpp53
-rw-r--r--src/plugins/qmldesigner/shortcutmanager.h1
-rw-r--r--src/plugins/qmldesigner/studioplugin/studioplugin.metainfo11
-rw-r--r--src/plugins/qmldesigner/utils/filedownloader.cpp12
-rw-r--r--src/plugins/qmldesigner/utils/fileextractor.cpp8
-rw-r--r--src/plugins/qmldesigner/utils/multifiledownloader.cpp6
168 files changed, 4155 insertions, 1943 deletions
diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt
index 74fcd863302..fc160cdf528 100644
--- a/src/plugins/qmldesigner/CMakeLists.txt
+++ b/src/plugins/qmldesigner/CMakeLists.txt
@@ -1,16 +1,5 @@
#only if the plugin is requested by qtc_plugin_enabled continue if not stop as early as possible
-add_qtc_plugin(QmlDesigner
- PLUGIN_RECOMMENDS QmlPreview
- CONDITION Qt6_VERSION VERSION_GREATER_EQUAL 6.2.0 AND TARGET Qt::QuickWidgets AND TARGET Qt::Svg
- PROPERTIES COMPILE_WARNING_AS_ERROR ON
- PLUGIN_DEPENDS
- Core ProjectExplorer QmlDesignerBase QmlJSEditor QmakeProjectManager QmlProjectManager
- QtSupport
-)
-qtc_plugin_enabled(_qmlDesignerEnabled QmlDesigner)
-if (NOT _qmlDesignerEnabled)
- return()
-endif()
+
find_package(Qt6 COMPONENTS QmlDomPrivate QmlCompilerPrivate)
@@ -19,13 +8,10 @@ if (APPLE)
set(QmlDesignerPluginInstallPrefix "${IDE_PLUGIN_PATH}/QmlDesigner")
endif()
-
-env_with_default("QDS_USE_PROJECTSTORAGE" ENV_QDS_USE_PROJECTSTORAGE OFF)
-option(USE_PROJECTSTORAGE "Use ProjectStorage" ${ENV_QDS_USE_PROJECTSTORAGE})
-add_feature_info("ProjectStorage" ${USE_PROJECTSTORAGE} "")
+add_compile_options("$<$<COMPILE_LANG_AND_ID:CXX,Clang>:-Wno-error=maybe-uninitialized>")
+add_compile_options("$<$<COMPILE_LANG_AND_ID:CXX,GNU>:-Wno-error=maybe-uninitialized>")
add_qtc_library(QmlDesignerUtils STATIC
- PROPERTIES COMPILE_WARNING_AS_ERROR ON
DEPENDS
Qt::Gui Utils Qt::QmlPrivate
DEFINES QMLDESIGNERUTILS_LIBRARY
@@ -44,8 +30,15 @@ add_qtc_library(QmlDesignerUtils STATIC
qmldesignerutils_global.h
)
+extend_qtc_library(QmlDesignerUtils
+ CONDITION NOT DISABLE_COMPILE_WARNING_AS_ERROR
+ PROPERTIES COMPILE_WARNING_AS_ERROR ON
+)
+
add_qtc_library(QmlDesignerCore STATIC
+ CONDITION Qt6_VERSION VERSION_GREATER_EQUAL 6.4.3 AND TARGET Qt6::QmlPrivate AND TARGET Qt6::QmlDomPrivate AND TARGET Qt6::QmlCompilerPrivate
EXCLUDE_FROM_INSTALL
+ PROPERTIES SKIP_AUTOUIC ON
DEPENDS
Threads::Threads
Qt::CorePrivate
@@ -53,6 +46,9 @@ add_qtc_library(QmlDesignerCore STATIC
Utils
Qt::Widgets
Qt::Qml
+ Qt::QmlPrivate
+ Qt6::QmlDomPrivate
+ Qt6::QmlCompilerPrivate
Core
ProjectExplorer
QmakeProjectManager
@@ -79,25 +75,27 @@ add_qtc_library(QmlDesignerCore STATIC
rewritertransaction.h
)
-extend_qtc_library(QmlDesignerCore
- CONDITION TARGET Qt6::QmlDomPrivate AND TARGET Qt6::QmlCompilerPrivate AND Qt6_VERSION VERSION_GREATER_EQUAL 6.5.0
- DEPENDS Qt6::QmlDomPrivate Qt6::QmlCompilerPrivate
- DEFINES QDS_HAS_QMLDOM
-)
+if(TARGET QmlDesignerCore)
+ env_with_default("QDS_USE_PROJECTSTORAGE" ENV_QDS_USE_PROJECTSTORAGE OFF)
+ option(USE_PROJECTSTORAGE "Use ProjectStorage" ${ENV_QDS_USE_PROJECTSTORAGE})
+ add_feature_info("ProjectStorage" ${USE_PROJECTSTORAGE} "")
+endif()
+
extend_qtc_library(QmlDesignerCore
- CONDITION UNIX AND NOT APPLE
- PUBLIC_DEPENDS rt
+ CONDITION NOT DISABLE_COMPILE_WARNING_AS_ERROR
+ PROPERTIES COMPILE_WARNING_AS_ERROR ON
)
extend_qtc_library(QmlDesignerCore
- INCLUDES ${CMAKE_CURRENT_BINARY_DIR}
- SOURCES
- ${UI_SOURCES}
- ${UI_FILES}
+ CONDITION Qt6_VERSION VERSION_GREATER_EQUAL 6.5.0 AND Qt6_VERSION VERSION_LESS 6.6.0
+ PUBLIC_DEFINES QDS_BUILD_QMLPARSER
+)
+extend_qtc_library(QmlDesignerCore
+ CONDITION UNIX AND NOT APPLE
+ PUBLIC_DEPENDS rt
)
-set_source_files_properties(${UI_FILES} PROPERTIES SKIP_AUTOUIC ON)
extend_qtc_library(QmlDesignerCore
INCLUDES ${CMAKE_CURRENT_LIST_DIR}/designercore/exceptions
@@ -221,6 +219,7 @@ extend_qtc_library(QmlDesignerCore
metainfo.h
metainforeader.h
model.h
+ modelfwd.h
modelmerger.h
modelnode.h
modelnodepositionstorage.h
@@ -241,6 +240,7 @@ extend_qtc_library(QmlDesignerCore
qmlchangeset.h
qmlconnections.h
qmldesignercorelib_global.h
+ qmldesignercorelib_exports.h
qmlitemnode.h
qmlmodelnodefacade.h
qmlobjectnode.h
@@ -262,6 +262,7 @@ extend_qtc_library(QmlDesignerCore
INCLUDES
${CMAKE_CURRENT_LIST_DIR}/designercore/metainfo
SOURCES_PREFIX ${CMAKE_CURRENT_LIST_DIR}/designercore/metainfo
+ DEFINES SHARE_QML_PATH="${CMAKE_CURRENT_SOURCE_DIR}/../../../share/qtcreator/qmldesigner"
SOURCES
itemlibraryinfo.cpp
metainfo.cpp
@@ -326,8 +327,11 @@ extend_qtc_library(QmlDesignerCore
modelnodepositionrecalculator.cpp
modelnodepositionrecalculator.h
modelnodepositionstorage.cpp
+ modelresourcemanagementinterface.h
modeltotextmerger.cpp
modeltotextmerger.h
+ modelutils.cpp
+ modelutils.h
nodeabstractproperty.cpp
nodelistproperty.cpp
nodeproperty.cpp
@@ -354,6 +358,7 @@ extend_qtc_library(QmlDesignerCore
rewriteactioncompressor.h
rewriterview.cpp
signalhandlerproperty.cpp
+ skipiterator.h
stylesheetmerger.cpp
textmodifier.cpp
texttomodelmerger.cpp
@@ -374,6 +379,7 @@ extend_qtc_library(QmlDesignerCore
extend_qtc_library(QmlDesignerCore
SOURCES_PREFIX designercore/projectstorage
PUBLIC_INCLUDES designercore/projectstorage
+ SOURCES_PROPERTIES SKIP_AUTOMOC ON
SOURCES
commontypecache.h
directorypathcompressor.h
@@ -381,6 +387,7 @@ extend_qtc_library(QmlDesignerCore
filesystem.cpp filesystem.h
filestatus.h
filestatuscache.cpp filestatuscache.h
+ modulescanner.cpp modulescanner.h
nonlockingmutex.h
projectstorageexceptions.cpp projectstorageexceptions.h
projectstorageinterface.h
@@ -409,18 +416,17 @@ extend_qtc_library(QmlDesignerCore
qmldocumentparser.cpp qmldocumentparser.h
)
-file(GLOB PROJECTSTORAGE_EXCLUDED_SOURCES designercore/projectstorage/*.cpp)
-set_property(SOURCE ${PROJECTSTORAGE_EXCLUDED_SOURCES} PROPERTY SKIP_AUTOMOC ON)
-
-extend_qtc_plugin(QmlDesigner
- PUBLIC_DEPENDS
- QmlDesignerUtils
- QmlDesignerBase
- QmlPuppetCommunication
+add_qtc_plugin(QmlDesigner
+ PLUGIN_RECOMMENDS QmlPreview
+ CONDITION Qt6_VERSION VERSION_GREATER_EQUAL 6.4.3 AND TARGET QmlDesignerCore AND TARGET Qt::QuickWidgets AND TARGET Qt::Svg
+ PLUGIN_DEPENDS
+ Core ProjectExplorer QmlDesignerBase QmlJSEditor QmakeProjectManager QmlProjectManager
+ QtSupport
DEPENDS
- QmlDesignerCore
- QmlJS LanguageUtils QmlEditorWidgets AdvancedDockingSystem Sqlite
- Qt::QuickWidgets Qt::CorePrivate Qt::Xml Qt::Svg
+ QmlJS LanguageUtils QmlEditorWidgets AdvancedDockingSystem
+ Qt::QuickWidgets Qt::CorePrivate Qt::Xml Qt::Svg QmlDesignerCore Sqlite
+ PUBLIC_DEPENDS
+ QmlDesignerUtils QmlPuppetCommunication QmlDesignerBase
DEFINES
IDE_LIBRARY_BASENAME=\"${IDE_LIBRARY_BASE_PATH}\"
SHARE_QML_PATH="${CMAKE_CURRENT_SOURCE_DIR}/../../../share/qtcreator/qmldesigner"
@@ -474,6 +480,11 @@ extend_qtc_plugin(QmlDesigner
QMLDESIGNER_PLUGIN_PATH "${QmlDesignerPluginInstallPrefix}"
)
+extend_qtc_plugin(QmlDesigner
+ CONDITION NOT DISABLE_COMPILE_WARNING_AS_ERROR
+ PROPERTIES COMPILE_WARNING_AS_ERROR ON
+)
+
function(get_and_add_as_subdirectory name repository git_tag build_dir source_dir source_subdir)
# make the configuration in the build dir
file(MAKE_DIRECTORY ${build_dir}/${name})
@@ -521,67 +532,6 @@ if (QTC_STATIC_BUILD AND TARGET QmlDesigner)
extend_qtc_target(QmlDesigner PUBLIC_DEPENDS TextEditor)
endif()
-add_qtc_plugin(assetexporterplugin
- PLUGIN_CLASS AssetExporterPlugin
- CONDITION TARGET QmlDesigner
- DEPENDS Core ProjectExplorer QmlDesigner Utils Qt::Qml Qt::QuickPrivate
- PUBLIC_INCLUDES assetexporterplugin
- SOURCES
- assetexporterplugin/assetexportdialog.h assetexporterplugin/assetexportdialog.cpp assetexporterplugin/assetexportdialog.ui
- assetexporterplugin/assetexporter.h assetexporterplugin/assetexporter.cpp
- assetexporterplugin/assetexporterplugin.h assetexporterplugin/assetexporterplugin.cpp
- assetexporterplugin/assetexporterview.h assetexporterplugin/assetexporterview.cpp
- assetexporterplugin/assetexportpluginconstants.h
- assetexporterplugin/componentexporter.h assetexporterplugin/componentexporter.cpp
- assetexporterplugin/exportnotification.h assetexporterplugin/exportnotification.cpp
- assetexporterplugin/filepathmodel.h assetexporterplugin/filepathmodel.cpp
- assetexporterplugin/dumpers/assetnodedumper.h assetexporterplugin/dumpers/assetnodedumper.cpp
- assetexporterplugin/dumpers/itemnodedumper.h assetexporterplugin/dumpers/itemnodedumper.cpp
- assetexporterplugin/dumpers/nodedumper.h assetexporterplugin/dumpers/nodedumper.cpp
- assetexporterplugin/dumpers/textnodedumper.h assetexporterplugin/dumpers/textnodedumper.cpp
- assetexporterplugin/assetexporterplugin.qrc
- PLUGIN_PATH ${QmlDesignerPluginInstallPrefix}
-)
-
-add_qtc_plugin(componentsplugin
- PLUGIN_CLASS ComponentsPlugin
- CONDITION TARGET QmlDesigner
- DEPENDS Core QmlDesigner Utils Qt::Qml
- DEFINES COMPONENTS_LIBRARY
- SOURCES
- componentsplugin/addtabdesigneraction.cpp componentsplugin/addtabdesigneraction.h
- componentsplugin/addtabtotabviewdialog.cpp componentsplugin/addtabtotabviewdialog.h
- componentsplugin/addtabtotabviewdialog.ui
- componentsplugin/componentsplugin.cpp componentsplugin/componentsplugin.h
- componentsplugin/componentsplugin.qrc
- componentsplugin/entertabdesigneraction.cpp componentsplugin/entertabdesigneraction.h
- componentsplugin/tabviewindexmodel.cpp componentsplugin/tabviewindexmodel.h
- PLUGIN_PATH ${QmlDesignerPluginInstallPrefix}
-)
-
-add_qtc_plugin(qmlpreviewplugin
- PLUGIN_CLASS QmlPreviewWidgetPlugin
- CONDITION TARGET QmlDesigner
- DEPENDS Core ProjectExplorer QmlDesigner Utils Qt::Qml
- SOURCES
- qmlpreviewplugin/qmlpreviewactions.cpp qmlpreviewplugin/qmlpreviewactions.h
- qmlpreviewplugin/qmlpreviewplugin.cpp qmlpreviewplugin/qmlpreviewplugin.h
- qmlpreviewplugin/qmlpreviewplugin.qrc
- PLUGIN_PATH ${QmlDesignerPluginInstallPrefix}
-)
-
-add_qtc_plugin(qtquickplugin
- PLUGIN_CLASS QtQuickPlugin
- CONDITION TARGET QmlDesigner
- DEPENDS Core QmlDesigner Utils Qt::Qml
- DEFINES QTQUICK_LIBRARY
- SOURCES
- qtquickplugin/qtquickplugin.cpp qtquickplugin/qtquickplugin.h
- qtquickplugin/qtquickplugin.qrc
- PLUGIN_PATH ${QmlDesignerPluginInstallPrefix}
-)
-
-add_subdirectory(studioplugin)
extend_qtc_plugin(QmlDesigner
SOURCES_PREFIX components
@@ -643,6 +593,9 @@ extend_qtc_plugin(QmlDesigner
edit3dactions.cpp edit3dactions.h
edit3dvisibilitytogglesmenu.cpp edit3dvisibilitytogglesmenu.h
backgroundcolorselection.cpp backgroundcolorselection.h
+ bakelights.cpp bakelights.h
+ bakelightsdatamodel.cpp bakelightsdatamodel.h
+ bakelightsconnectionmanager.cpp bakelightsconnectionmanager.h
edit3d.qrc
)
@@ -1129,3 +1082,106 @@ extend_qtc_plugin(QmlDesigner
CONDITION TARGET Nanotrace
DEPENDS Nanotrace
)
+
+add_qtc_plugin(assetexporterplugin
+ PLUGIN_CLASS AssetExporterPlugin
+ CONDITION TARGET QmlDesigner
+ PLUGIN_DEPENDS
+ Core ProjectExplorer QmlDesigner
+ DEPENDS Utils Qt::Qml Qt::QuickPrivate
+ PUBLIC_INCLUDES assetexporterplugin
+ PLUGIN_PATH ${QmlDesignerPluginInstallPrefix}
+)
+
+extend_qtc_plugin(assetexporterplugin
+ CONDITION NOT DISABLE_COMPILE_WARNING_AS_ERROR
+ PROPERTIES COMPILE_WARNING_AS_ERROR ON
+)
+
+extend_qtc_plugin(assetexporterplugin
+ SOURCES_PREFIX assetexporterplugin
+ SOURCES
+ assetexportdialog.h assetexportdialog.cpp assetexportdialog.ui
+ assetexporter.h assetexporter.cpp
+ assetexporterplugin.h assetexporterplugin.cpp
+ assetexporterview.h assetexporterview.cpp
+ assetexportpluginconstants.h
+ componentexporter.h componentexporter.cpp
+ exportnotification.h exportnotification.cpp
+ filepathmodel.h filepathmodel.cpp
+ dumpers/assetnodedumper.h dumpers/assetnodedumper.cpp
+ dumpers/itemnodedumper.h dumpers/itemnodedumper.cpp
+ dumpers/nodedumper.h dumpers/nodedumper.cpp
+ dumpers/textnodedumper.h dumpers/textnodedumper.cpp
+ assetexporterplugin.qrc
+)
+
+add_qtc_plugin(componentsplugin
+ PLUGIN_CLASS ComponentsPlugin
+ CONDITION TARGET QmlDesigner
+ PLUGIN_DEPENDS Core QmlDesigner
+ DEPENDS Utils Qt::Qml
+ DEFINES COMPONENTS_LIBRARY
+
+ PLUGIN_PATH ${QmlDesignerPluginInstallPrefix}
+)
+
+extend_qtc_plugin(componentsplugin
+ CONDITION NOT DISABLE_COMPILE_WARNING_AS_ERROR
+ PROPERTIES COMPILE_WARNING_AS_ERROR ON
+)
+
+extend_qtc_plugin(componentsplugin
+ SOURCES_PREFIX componentsplugin
+ SOURCES
+ addtabdesigneraction.cpp addtabdesigneraction.h
+ addtabtotabviewdialog.cpp addtabtotabviewdialog.h
+ addtabtotabviewdialog.ui
+ componentsplugin.cpp componentsplugin.h
+ componentsplugin.qrc
+ entertabdesigneraction.cpp entertabdesigneraction.h
+ tabviewindexmodel.cpp tabviewindexmodel.h
+)
+
+add_qtc_plugin(qmlpreviewplugin
+ PLUGIN_CLASS QmlPreviewWidgetPlugin
+ CONDITION TARGET QmlDesigner
+ PLUGIN_DEPENDS Core ProjectExplorer QmlDesigner
+ DEPENDS Utils Qt::Qml
+ PLUGIN_PATH ${QmlDesignerPluginInstallPrefix}
+)
+
+extend_qtc_plugin(qmlpreviewplugin
+ CONDITION NOT DISABLE_COMPILE_WARNING_AS_ERROR
+ PROPERTIES COMPILE_WARNING_AS_ERROR ON
+)
+
+extend_qtc_plugin(qmlpreviewplugin
+ SOURCES_PREFIX qmlpreviewplugin
+ SOURCES
+ qmlpreviewactions.cpp qmlpreviewactions.h
+ qmlpreviewplugin.cpp qmlpreviewplugin.h
+ qmlpreviewplugin.qrc
+)
+
+add_qtc_plugin(qtquickplugin
+ PLUGIN_CLASS QtQuickPlugin
+ CONDITION TARGET QmlDesigner
+ PLUGIN_DEPENDS Core QmlDesigner
+ DEPENDS Utils Qt::Qml
+ DEFINES QTQUICK_LIBRARY
+ PLUGIN_PATH ${QmlDesignerPluginInstallPrefix}
+)
+
+extend_qtc_plugin(qtquickplugin
+ CONDITION NOT DISABLE_COMPILE_WARNING_AS_ERROR
+ PROPERTIES COMPILE_WARNING_AS_ERROR ON
+)
+
+extend_qtc_plugin(qtquickplugin
+ SOURCES_PREFIX qtquickplugin
+ SOURCES
+ qtquickplugin.cpp qtquickplugin.h
+ qtquickplugin.qrc
+)
+add_subdirectory(studioplugin)
diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp
index faf4f1eb549..71cde5f0ba8 100644
--- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp
+++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp
@@ -136,7 +136,7 @@ bool AssetsLibraryModel::renameFolder(const QString &folderPath, const QString &
return dir.rename(oldName, newName);
}
-bool AssetsLibraryModel::addNewFolder(const QString &folderPath)
+QString AssetsLibraryModel::addNewFolder(const QString &folderPath)
{
QString iterPath = folderPath;
QDir dir{folderPath};
@@ -147,7 +147,7 @@ bool AssetsLibraryModel::addNewFolder(const QString &folderPath)
dir.setPath(iterPath);
}
- return dir.mkpath(iterPath);
+ return dir.mkpath(iterPath) ? iterPath : "";
}
bool AssetsLibraryModel::urlPathExistsInModel(const QUrl &url) const
diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h
index f003ef2c541..e37bf8a109a 100644
--- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h
+++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h
@@ -45,7 +45,7 @@ public:
Q_INVOKABLE bool requestDeleteFiles(const QStringList &filePaths);
Q_INVOKABLE void deleteFiles(const QStringList &filePaths, bool dontAskAgain);
Q_INVOKABLE bool renameFolder(const QString &folderPath, const QString &newName);
- Q_INVOKABLE bool addNewFolder(const QString &folderPath);
+ Q_INVOKABLE QString addNewFolder(const QString &folderPath);
Q_INVOKABLE bool deleteFolderRecursively(const QModelIndex &folderIndex);
Q_INVOKABLE bool allFilePathsAreTextures(const QStringList &filePaths) const;
diff --git a/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.cpp b/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.cpp
index 5112cc3f860..6cd3e814929 100644
--- a/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.cpp
+++ b/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.cpp
@@ -94,7 +94,7 @@ void BindingEditor::setBackendValue(const QVariant &backendValue)
m_backendValueTypeName = node.metaInfo()
.property(propertyEditorValue->name())
.propertyType()
- .typeName();
+ .simplifiedTypeName();
QString nodeId = node.id();
if (nodeId.isEmpty())
@@ -187,7 +187,7 @@ void BindingEditor::prepareBindings()
for (const auto &objnode : allNodes) {
BindingEditorDialog::BindingOption binding;
for (const auto &property : objnode.metaInfo().properties()) {
- const TypeName &propertyTypeName = property.propertyType().typeName();
+ const TypeName &propertyTypeName = property.propertyType().simplifiedTypeName();
if (skipTypeFiltering
|| (m_backendValueTypeName == propertyTypeName)
diff --git a/src/plugins/qmldesigner/components/componentcore/designeractionmanagerview.cpp b/src/plugins/qmldesigner/components/componentcore/designeractionmanagerview.cpp
index 14f55efa3f8..90bcc54fddc 100644
--- a/src/plugins/qmldesigner/components/componentcore/designeractionmanagerview.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/designeractionmanagerview.cpp
@@ -95,7 +95,7 @@ void DesignerActionManagerView::nodeOrderChanged(const NodeListProperty &)
setupContext(SelectionContext::UpdateMode::NodeHierachy);
}
-void DesignerActionManagerView::importsChanged(const QList<Import> &, const QList<Import> &)
+void DesignerActionManagerView::importsChanged(const Imports &, const Imports &)
{
setupContext();
}
diff --git a/src/plugins/qmldesigner/components/componentcore/designeractionmanagerview.h b/src/plugins/qmldesigner/components/componentcore/designeractionmanagerview.h
index 41210602b38..9ccfe4e7379 100644
--- a/src/plugins/qmldesigner/components/componentcore/designeractionmanagerview.h
+++ b/src/plugins/qmldesigner/components/componentcore/designeractionmanagerview.h
@@ -37,7 +37,7 @@ public:
void selectedNodesChanged(const QList<ModelNode> &,
const QList<ModelNode> &) override;
void nodeOrderChanged(const NodeListProperty &) override;
- void importsChanged(const QList<Import> &, const QList<Import> &) override;
+ void importsChanged(const Imports &, const Imports &) override;
void signalHandlerPropertiesChanged(const QVector<SignalHandlerProperty> &/*propertyList*/, PropertyChangeFlags /*propertyChange*/) override;
void variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags propertyChangeFlag) override;
void bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags propertyChangeFlag) override;
diff --git a/src/plugins/qmldesigner/components/componentcore/designericons.h b/src/plugins/qmldesigner/components/componentcore/designericons.h
index f460707b915..749e4e1cce4 100644
--- a/src/plugins/qmldesigner/components/componentcore/designericons.h
+++ b/src/plugins/qmldesigner/components/componentcore/designericons.h
@@ -53,6 +53,7 @@ public:
AnchorsIcon,
AnnotationIcon,
ArrangeIcon,
+ BackspaceIcon,
CameraIcon,
CameraOrthographicIcon,
CameraPerspectiveIcon,
diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
index 10386425fe7..258ae0ba925 100644
--- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
@@ -1650,7 +1650,11 @@ void openEffectMaker(const QString &filePath)
const QtSupport::QtVersion *baseQtVersion = QtSupport::QtKitAspect::qtVersion(target->kit());
if (baseQtVersion) {
+ Utils::Environment env = Utils::Environment::systemEnvironment();
+
auto effectMakerPath = baseQtVersion->binPath().pathAppended("qqem").withExecutableSuffix();
+ if (!effectMakerPath.exists() && env.osType() == Utils::OsTypeMac)
+ effectMakerPath = baseQtVersion->binPath().pathAppended("qqem.app/Contents/MacOS/qqem");
if (!effectMakerPath.exists()) {
qWarning() << __FUNCTION__ << "Cannot find EffectMaker app";
return;
@@ -1663,7 +1667,6 @@ void openEffectMaker(const QString &filePath)
arguments << "--create";
arguments << "--exportpath" << effectResPath.toString();
- Utils::Environment env = Utils::Environment::systemEnvironment();
if (env.osType() == Utils::OsTypeMac)
env.appendOrSet("QSG_RHI_BACKEND", "metal");
diff --git a/src/plugins/qmldesigner/components/componentcore/qmleditormenu.cpp b/src/plugins/qmldesigner/components/componentcore/qmleditormenu.cpp
index 173838f170d..e59fca7353e 100644
--- a/src/plugins/qmldesigner/components/componentcore/qmleditormenu.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/qmleditormenu.cpp
@@ -149,4 +149,6 @@ QmlEditorStyleObject::QmlEditorStyleObject()
QmlEditorMenuPrivate::cascadeRight = DesignerIcons::rotateIcon(downIcon, -90);
QmlEditorMenuPrivate::tick = DesignerActionManager::instance()
.contextIcon(DesignerIcons::SimpleCheckIcon);
+ QmlEditorMenuPrivate::backspaceIcon = DesignerActionManager::instance()
+ .contextIcon(DesignerIcons::BackspaceIcon);
}
diff --git a/src/plugins/qmldesigner/components/componentcore/viewmanager.h b/src/plugins/qmldesigner/components/componentcore/viewmanager.h
index c54cf139e78..4201065f99f 100644
--- a/src/plugins/qmldesigner/components/componentcore/viewmanager.h
+++ b/src/plugins/qmldesigner/components/componentcore/viewmanager.h
@@ -67,7 +67,7 @@ public:
void disableWidgets();
void enableWidgets();
- void pushFileOnCrumbleBar(const Utils::FilePath &fileName);
+ void pushFileOnCrumbleBar(const ::Utils::FilePath &fileName);
void pushInFileComponentOnCrumbleBar(const ModelNode &modelNode);
void nextFileIsCalledInternally();
diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp b/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp
index b3eb7542f8a..25a5756c28e 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp
+++ b/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp
@@ -38,10 +38,7 @@ QStringList propertyNameListToStringList(const QmlDesigner::PropertyNameList &pr
bool isConnection(const QmlDesigner::ModelNode &modelNode)
{
- return (modelNode.type() == "Connections"
- || modelNode.type() == "QtQuick.Connections"
- || modelNode.type() == "Qt.Connections"
- || modelNode.type() == "QtQml.Connections");
+ return (modelNode.metaInfo().simplifiedTypeName() == "Connections");
}
} //namespace
diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectionview.cpp b/src/plugins/qmldesigner/components/connectioneditor/connectionview.cpp
index 39e05a898ca..56fcc7ef6bf 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/connectionview.cpp
+++ b/src/plugins/qmldesigner/components/connectioneditor/connectionview.cpp
@@ -183,7 +183,7 @@ void ConnectionView::auxiliaryDataChanged([[maybe_unused]] const ModelNode &node
selectionModel->clearSelection();
}
-void ConnectionView::importsChanged(const QList<Import> & /*addedImports*/, const QList<Import> & /*removedImports*/)
+void ConnectionView::importsChanged(const Imports & /*addedImports*/, const Imports & /*removedImports*/)
{
backendModel()->resetModel();
}
diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectionview.h b/src/plugins/qmldesigner/components/connectioneditor/connectionview.h
index dcf61ad79d9..89c6c489105 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/connectionview.h
+++ b/src/plugins/qmldesigner/components/connectioneditor/connectionview.h
@@ -50,7 +50,7 @@ public:
AuxiliaryDataKeyView key,
const QVariant &data) override;
- void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
+ void importsChanged(const Imports &addedImports, const Imports &removedImports) override;
void currentStateChanged(const ModelNode &node) override;
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.cpp
index 127ecb4225f..f272a4121df 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.cpp
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.cpp
@@ -7,6 +7,8 @@
#include "contentlibrarymaterial.h"
#include "contentlibrarymaterialscategory.h"
#include "contentlibrarywidget.h"
+
+#include <designerpaths.h>
#include "filedownloader.h"
#include "fileextractor.h"
#include "multifiledownloader.h"
@@ -30,8 +32,7 @@ ContentLibraryMaterialsModel::ContentLibraryMaterialsModel(ContentLibraryWidget
: QAbstractListModel(parent)
, m_widget(parent)
{
- m_downloadPath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)
- + "/QtDesignStudio/bundles/Materials";
+ m_downloadPath = Paths::bundlesPathSetting() + "/Materials";
m_baseUrl = QmlDesignerPlugin::settings()
.value(DesignerSettingsKey::DOWNLOADABLE_BUNDLES_URL)
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.cpp
index 0d74be596f5..5cf88ab6fcd 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.cpp
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.cpp
@@ -4,8 +4,8 @@
#include "contentlibrarytexturesmodel.h"
#include "contentlibrarytexturescategory.h"
-#include "qmldesignerplugin.h"
+#include <designerpaths.h>
#include <qmldesignerbase/qmldesignerbaseplugin.h>
#include <utils/algorithm.h>
@@ -119,8 +119,10 @@ void ContentLibraryTexturesModel::loadTextureBundle(const QString &remoteUrl, co
for (const QFileInfo &tex : texFiles) {
QString fullRemoteUrl = QString("%1/%2/%3.zip").arg(remoteUrl, dir.fileName(),
tex.baseName());
- QString localDownloadPath = QString("%1/%2/%3").arg(QmlDesignerBasePlugin::bundlesPathSetting(),
- m_category, dir.fileName());
+ QString localDownloadPath = QString("%1/%2/%3")
+ .arg(Paths::bundlesPathSetting(),
+ m_category,
+ dir.fileName());
QString key = QString("%1/%2/%3").arg(m_category, dir.fileName(), tex.baseName());
QString fileExt;
QSize dimensions;
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp
index 9ce7a4e7377..3bb579273f6 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp
@@ -144,7 +144,7 @@ void ContentLibraryView::modelAboutToBeDetached(Model *model)
AbstractView::modelAboutToBeDetached(model);
}
-void ContentLibraryView::importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports)
+void ContentLibraryView::importsChanged(const Imports &addedImports, const Imports &removedImports)
{
Q_UNUSED(addedImports)
Q_UNUSED(removedImports)
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h
index 1d27f6e260c..137034dd955 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h
@@ -31,7 +31,7 @@ public:
// AbstractView
void modelAttached(Model *model) override;
void modelAboutToBeDetached(Model *model) override;
- void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
+ void importsChanged(const Imports &addedImports, const Imports &removedImports) override;
void active3DSceneChanged(qint32 sceneId) override;
void selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
const QList<ModelNode> &lastSelectedNodeList) override;
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp
index a1dfff5ef53..9cc9576bc6c 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp
@@ -12,6 +12,7 @@
#include "utils/fileextractor.h"
#include <coreplugin/icore.h>
+#include <designerpaths.h>
#include <qmldesignerconstants.h>
#include <qmldesignerplugin.h>
@@ -117,13 +118,12 @@ ContentLibraryWidget::ContentLibraryWidget()
m_baseUrl = QmlDesignerPlugin::settings()
.value(DesignerSettingsKey::DOWNLOADABLE_BUNDLES_URL).toString()
- + "/textures/v1";
+ + "/textures";
m_texturesUrl = m_baseUrl + "/Textures";
m_environmentsUrl = m_baseUrl + "/Environments";
- m_downloadPath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)
- + "/QtDesignStudio/bundles";
+ m_downloadPath = Paths::bundlesPathSetting();
loadTextureBundle();
@@ -436,18 +436,4 @@ QPointer<ContentLibraryTexturesModel> ContentLibraryWidget::environmentsModel()
return m_environmentsModel;
}
-bool ContentLibraryWidget::markTextureDownloading()
-{
- if (m_anyTextureBeingDownloaded)
- return false;
-
- m_anyTextureBeingDownloaded = true;
- return true; // let the caller know it can begin download
-}
-
-void ContentLibraryWidget::markNoTextureDownloading()
-{
- m_anyTextureBeingDownloaded = false; // allow other textures to be downloaded
-}
-
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.h
index 519d6fcf780..6d4ba51a300 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.h
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.h
@@ -61,8 +61,6 @@ public:
Q_INVOKABLE void addTexture(QmlDesigner::ContentLibraryTexture *tex);
Q_INVOKABLE void addLightProbe(QmlDesigner::ContentLibraryTexture *tex);
Q_INVOKABLE void updateSceneEnvState();
- Q_INVOKABLE bool markTextureDownloading();
- Q_INVOKABLE void markNoTextureDownloading();
signals:
void bundleMaterialDragStarted(QmlDesigner::ContentLibraryMaterial *bundleMat);
@@ -102,7 +100,6 @@ private:
bool m_hasMaterialLibrary = false;
bool m_hasQuick3DImport = false;
bool m_isDragging = false;
- bool m_anyTextureBeingDownloaded = false;
QString m_baseUrl;
QString m_texturesUrl;
QString m_environmentsUrl;
diff --git a/src/plugins/qmldesigner/components/debugview/debugview.cpp b/src/plugins/qmldesigner/components/debugview/debugview.cpp
index 2888575e44c..2a62d7a6b2b 100644
--- a/src/plugins/qmldesigner/components/debugview/debugview.cpp
+++ b/src/plugins/qmldesigner/components/debugview/debugview.cpp
@@ -65,7 +65,7 @@ void DebugView::modelAboutToBeDetached(Model *model)
AbstractView::modelAboutToBeDetached(model);
}
-void DebugView::importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports)
+void DebugView::importsChanged(const Imports &addedImports, const Imports &removedImports)
{
if (isDebugViewEnabled()) {
QString message;
diff --git a/src/plugins/qmldesigner/components/debugview/debugview.h b/src/plugins/qmldesigner/components/debugview/debugview.h
index 885030545cf..e80c619c818 100644
--- a/src/plugins/qmldesigner/components/debugview/debugview.h
+++ b/src/plugins/qmldesigner/components/debugview/debugview.h
@@ -24,7 +24,7 @@ public:
void modelAttached(Model *model) override;
void modelAboutToBeDetached(Model *model) override;
- void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
+ void importsChanged(const Imports &addedImports, const Imports &removedImports) override;
void nodeCreated(const ModelNode &createdNode) override;
void nodeAboutToBeRemoved(const ModelNode &removedNode) override;
diff --git a/src/plugins/qmldesigner/components/edit3d/bakelights.cpp b/src/plugins/qmldesigner/components/edit3d/bakelights.cpp
new file mode 100644
index 00000000000..53c7e53df9d
--- /dev/null
+++ b/src/plugins/qmldesigner/components/edit3d/bakelights.cpp
@@ -0,0 +1,430 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
+
+#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 <coreplugin/icore.h>
+
+#include <qmljs/qmljsmodelmanagerinterface.h>
+
+#include <utils/algorithm.h>
+#include <utils/environment.h>
+#include <utils/filepath.h>
+#include <utils/qtcassert.h>
+
+#include <QEvent>
+#include <QQmlContext>
+#include <QQmlEngine>
+#include <QQuickView>
+#include <QSaveFile>
+#include <QTextCursor>
+#include <QTextDocument>
+#include <QTimer>
+#include <QVariant>
+
+namespace QmlDesigner {
+
+static QString propertyEditorResourcesPath()
+{
+#ifdef SHARE_QML_PATH
+ if (Utils::qtcEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
+ return QLatin1String(SHARE_QML_PATH) + "/propertyEditorQmlSources";
+#endif
+ return Core::ICore::resourcePath("qmldesigner/propertyEditorQmlSources").toString();
+}
+
+static QString qmlSourcesPath()
+{
+#ifdef SHARE_QML_PATH
+ if (Utils::qtcEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
+ return QLatin1String(SHARE_QML_PATH) + "/edit3dQmlSource";
+#endif
+ return Core::ICore::resourcePath("qmldesigner/edit3dQmlSource").toString();
+}
+
+BakeLights::BakeLights(AbstractView *view)
+ : QObject(view)
+ , m_view(view)
+{
+ m_view3dId = resolveView3dId(view);
+
+ if (m_view3dId.isEmpty()) {
+ // It should never get here, baking controls should be disabled in this case
+ qWarning() << __FUNCTION__ << "Active scene is not View3D";
+ deleteLater();
+ return;
+ }
+
+ showSetupDialog();
+}
+
+BakeLights::~BakeLights()
+{
+ cleanup();
+}
+
+ModelNode BakeLights::resolveView3dNode(AbstractView *view)
+{
+ if (!view || !view->model())
+ return {};
+
+ ModelNode activeView3D;
+ ModelNode activeScene = view->active3DSceneNode();
+
+ if (activeScene.isValid()) {
+ if (activeScene.metaInfo().isQtQuick3DView3D()) {
+ activeView3D = activeScene;
+ } else {
+ ModelNode sceneParent = activeScene.parentProperty().parentModelNode();
+ if (sceneParent.metaInfo().isQtQuick3DView3D())
+ activeView3D = sceneParent;
+ }
+ return activeView3D;
+ }
+
+ return {};
+}
+
+QString BakeLights::resolveView3dId(AbstractView *view)
+{
+ ModelNode activeView3D = resolveView3dNode(view);
+
+ if (activeView3D.isValid())
+ return activeView3D.id();
+
+ return {};
+}
+
+void BakeLights::raiseDialog()
+{
+ if (m_progressDialog)
+ m_progressDialog->raise();
+}
+
+bool BakeLights::manualMode() const
+{
+ return m_manualMode;
+}
+
+void BakeLights::setManualMode(bool enabled)
+{
+ if (m_manualMode != enabled) {
+ m_manualMode = enabled;
+ emit manualModeChanged();
+ }
+}
+
+void BakeLights::bakeLights()
+{
+ if (!m_view || !m_view->model())
+ return;
+
+ m_setupDialog->hide();
+ showProgressDialog();
+
+ // Start baking process
+ m_connectionManager = new BakeLightsConnectionManager;
+ m_rewriterView = new RewriterView{m_view->externalDependencies(), RewriterView::Amend};
+ m_nodeInstanceView = new NodeInstanceView{*m_connectionManager, m_view->externalDependencies()};
+
+ m_model = QmlDesigner::Model::create("QtQuick/Item", 2, 1);
+ m_model->setFileUrl(m_view->model()->fileUrl());
+
+ // Take the current unsaved state of the main model and apply it to our copy
+ auto textDocument = std::make_unique<QTextDocument>(
+ m_view->model()->rewriterView()->textModifier()->textDocument()->toRawText());
+
+ auto modifier = std::make_unique<NotIndentingTextEditModifier>(textDocument.get(),
+ QTextCursor{textDocument.get()});
+
+ m_rewriterView->setTextModifier(modifier.get());
+ m_model->setRewriterView(m_rewriterView);
+
+ auto rootModelNodeMetaInfo = m_rewriterView->rootModelNode().metaInfo();
+ bool is3DRoot = m_rewriterView->errors().isEmpty()
+ && (rootModelNodeMetaInfo.isQtQuick3DNode()
+ || rootModelNodeMetaInfo.isQtQuick3DMaterial());
+
+ if (!m_rewriterView->errors().isEmpty()
+ || (!m_rewriterView->rootModelNode().metaInfo().isGraphicalItem() && !is3DRoot)) {
+ emit progress(tr("Invalid root node, baking aborted."));
+ emit finished();
+ m_progressDialog->raise();
+ return;
+ }
+
+ m_nodeInstanceView->setTarget(m_view->nodeInstanceView()->target());
+
+ auto progressCallback = [this](const QString &msg) {
+ emit progress(msg);
+ };
+
+ auto finishedCallback = [this](const QString &msg) {
+ m_progressDialog->raise();
+ emit progress(msg);
+ emit finished();
+
+ // Puppet reset is needed to update baking results to current views
+ m_view->resetPuppet();
+ };
+
+ auto crashCallback = [this]() {
+ m_progressDialog->raise();
+ emit progress(tr("Baking process crashed, baking aborted."));
+ emit finished();
+ };
+
+ m_connectionManager->setProgressCallback(std::move(progressCallback));
+ m_connectionManager->setFinishedCallback(std::move(finishedCallback));
+ m_nodeInstanceView->setCrashCallback(std::move(crashCallback));
+
+ m_model->setNodeInstanceView(m_nodeInstanceView);
+
+ // InternalIds are not guaranteed to match between normal model and our copy of it, so
+ // we identify the View3D by its qml id.
+ m_nodeInstanceView->view3DAction(View3DActionType::SetBakeLightsView3D, m_view3dId);
+}
+
+void BakeLights::apply()
+{
+ // Uninitialized QVariant stored instead of false to remove the aux property in that case
+ m_dataModel->view3dNode().setAuxiliaryData(bakeLightsManualProperty,
+ m_manualMode ? QVariant{true} : QVariant{});
+
+ if (!m_manualMode)
+ m_dataModel->apply();
+
+ // Create folders for lightmaps if they do not exist
+ PropertyName loadPrefixPropName{"loadPrefix"};
+ const QList<ModelNode> bakedLightmapNodes = m_view->allModelNodesOfType(
+ m_view->model()->qtQuick3DBakedLightmapMetaInfo());
+ Utils::FilePath currentPath = DocumentManager::currentFilePath().absolutePath();
+ QSet<Utils::FilePath> pathSet;
+ for (const ModelNode &node : bakedLightmapNodes) {
+ if (node.hasVariantProperty(loadPrefixPropName)) {
+ QString prefix = node.variantProperty(loadPrefixPropName).value().toString();
+ Utils::FilePath fp = Utils::FilePath::fromString(prefix);
+ if (fp.isRelativePath()) {
+ fp = currentPath.pathAppended(prefix);
+ if (!fp.exists())
+ pathSet.insert(fp);
+ }
+ }
+ }
+ for (const Utils::FilePath &fp : std::as_const(pathSet))
+ fp.createDir();
+}
+
+void BakeLights::rebake()
+{
+ QTimer::singleShot(0, this, [this]() {
+ cleanup();
+ showSetupDialog();
+ });
+}
+
+void BakeLights::exposeModelsAndLights(const QString &nodeId)
+{
+ ModelNode compNode = m_view->modelNodeForId(nodeId);
+ if (!compNode.isValid() || !compNode.isComponent()
+ || compNode.metaInfo().componentFileName().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);
+ QByteArray src = compFilePath.fileContents().value();
+
+ compModel->setFileUrl(QUrl::fromLocalFile(compFile));
+
+ auto textDocument = std::make_unique<QTextDocument>(QString::fromUtf8(src));
+ auto modifier = std::make_unique<IndentingTextEditModifier>(
+ textDocument.get(), QTextCursor{textDocument.get()});
+
+ rewriter.setTextModifier(modifier.get());
+ compModel->setRewriterView(&rewriter);
+
+ if (!rewriter.rootModelNode().isValid() || !rewriter.errors().isEmpty())
+ return;
+
+ QString originalText = modifier->text();
+ QStringList idList;
+
+ rewriter.executeInTransaction(__FUNCTION__, [&]() {
+ QList<ModelNode> nodes = rewriter.rootModelNode().allSubModelNodes();
+ for (ModelNode &node : nodes) {
+ if (node.metaInfo().isQtQuick3DModel() || node.metaInfo().isQtQuick3DLight()) {
+ QString idStr = node.id();
+ if (idStr.isEmpty()) {
+ const QString type = node.metaInfo().isQtQuick3DModel() ? "model" : "light";
+ idStr = compModel->generateNewId(type);
+ node.setIdWithoutRefactoring(idStr);
+ }
+ idList.append(idStr);
+ }
+ }
+ });
+
+ rewriter.executeInTransaction(__FUNCTION__, [&]() {
+ for (const QString &id : std::as_const(idList)) {
+ ModelNode node = rewriter.modelNodeForId(id);
+ if (!node.isValid())
+ continue;
+ rewriter.rootModelNode().bindingProperty(id.toUtf8())
+ .setDynamicTypeNameAndExpression("alias", id);
+ }
+ });
+
+ rewriter.forceAmend();
+
+ QString newText = modifier->text();
+ if (newText != originalText) {
+ QSaveFile saveFile(compFile);
+ if (saveFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
+ saveFile.write(newText.toUtf8());
+ saveFile.commit();
+ } else {
+ qWarning() << __FUNCTION__ << "Failed to save changes to:" << compFile;
+ }
+ }
+
+ QmlJS::ModelManagerInterface *modelManager = QmlJS::ModelManagerInterface::instance();
+ QmlJS::Document::Ptr doc = rewriter.document()->ptr();
+ modelManager->updateDocument(doc);
+
+ m_view->model()->rewriterView()->forceAmend();
+
+ compModel->setRewriterView({});
+
+ // Rebake to relaunch setup dialog with updated properties
+ rebake();
+}
+
+void BakeLights::showSetupDialog()
+{
+ if (!m_dataModel)
+ m_dataModel = new BakeLightsDataModel(m_view);
+
+ m_dataModel->reset();
+
+ auto data = m_dataModel->view3dNode().auxiliaryData(bakeLightsManualProperty);
+ if (data)
+ m_manualMode = data->toBool();
+
+ if (!m_setupDialog) {
+ // Show non-modal progress dialog with cancel button
+ QString path = qmlSourcesPath() + "/BakeLightsSetupDialog.qml";
+
+ m_setupDialog = new QQuickView;
+ m_setupDialog->setTitle(tr("Lights Baking Setup"));
+ m_setupDialog->setResizeMode(QQuickView::SizeRootObjectToView);
+ m_setupDialog->setMinimumSize({550, 200});
+ m_setupDialog->setWidth(550);
+ m_setupDialog->setHeight(400);
+ m_setupDialog->setFlags(Qt::Dialog);
+ m_setupDialog->setModality(Qt::ApplicationModal);
+ m_setupDialog->engine()->addImportPath(propertyEditorResourcesPath() + "/imports");
+
+ m_setupDialog->rootContext()->setContextProperties({
+ {"rootView", QVariant::fromValue(this)},
+ {"sceneId", QVariant::fromValue(m_view3dId)},
+ {"bakeModel", QVariant::fromValue(m_dataModel.data())}
+ });
+ m_setupDialog->setSource(QUrl::fromLocalFile(path));
+ m_setupDialog->installEventFilter(this);
+ }
+ m_setupDialog->show();
+}
+
+void BakeLights::showProgressDialog()
+{
+ if (!m_progressDialog) {
+ // Show non-modal progress dialog with cancel button
+ QString path = qmlSourcesPath() + "/BakeLightsProgressDialog.qml";
+
+ m_progressDialog = new QQuickView;
+ m_progressDialog->setTitle(tr("Lights Baking Progress"));
+ m_progressDialog->setResizeMode(QQuickView::SizeRootObjectToView);
+ m_progressDialog->setMinimumSize({150, 100});
+ m_progressDialog->setWidth(800);
+ m_progressDialog->setHeight(400);
+ m_progressDialog->setFlags(Qt::Dialog);
+ m_progressDialog->setModality(Qt::NonModal);
+ m_progressDialog->engine()->addImportPath(propertyEditorResourcesPath() + "/imports");
+
+ m_progressDialog->rootContext()->setContextProperties({
+ {"rootView", QVariant::fromValue(this)},
+ {"sceneId", QVariant::fromValue(m_view3dId)}
+ });
+ m_progressDialog->setSource(QUrl::fromLocalFile(path));
+ m_progressDialog->installEventFilter(this);
+ }
+ m_progressDialog->show();
+}
+
+void BakeLights::cleanup()
+{
+ if (m_connectionManager) {
+ m_connectionManager->setProgressCallback({});
+ m_connectionManager->setFinishedCallback({});
+ m_nodeInstanceView->setCrashCallback({});
+ }
+
+ if (m_model) {
+ m_model->setNodeInstanceView({});
+ m_model->setRewriterView({});
+ m_model.reset();
+ }
+
+ delete m_setupDialog;
+ delete m_progressDialog;
+ delete m_rewriterView;
+ delete m_nodeInstanceView;
+ delete m_connectionManager;
+ delete m_dataModel;
+
+ m_manualMode = false;
+}
+
+void BakeLights::cancel()
+{
+ if (!m_setupDialog.isNull() && m_setupDialog->isVisible())
+ m_setupDialog->close();
+ if (!m_progressDialog.isNull() && m_progressDialog->isVisible())
+ m_progressDialog->close();
+
+ deleteLater();
+}
+
+bool BakeLights::eventFilter(QObject *obj, QEvent *event)
+{
+ if (obj == m_progressDialog || obj == m_setupDialog) {
+ if (event->type() == QEvent::KeyPress) {
+ QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
+ if (keyEvent->key() == Qt::Key_Escape)
+ cancel();
+ } else if (event->type() == QEvent::Close) {
+ cancel();
+ }
+ }
+
+ return QObject::eventFilter(obj, event);
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/edit3d/bakelights.h b/src/plugins/qmldesigner/components/edit3d/bakelights.h
new file mode 100644
index 00000000000..65f00acc7b0
--- /dev/null
+++ b/src/plugins/qmldesigner/components/edit3d/bakelights.h
@@ -0,0 +1,74 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
+#pragma once
+
+#include "modelnode.h"
+#include "qmldesignercorelib_global.h"
+
+#include <QObject>
+#include <QPointer>
+
+QT_BEGIN_NAMESPACE
+class QQuickView;
+QT_END_NAMESPACE
+
+namespace QmlDesigner {
+
+class AbstractView;
+class BakeLightsConnectionManager;
+class NodeInstanceView;
+class RewriterView;
+class BakeLightsDataModel;
+
+class BakeLights : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool manualMode READ manualMode WRITE setManualMode NOTIFY manualModeChanged)
+
+public:
+ BakeLights(AbstractView *view);
+ ~BakeLights();
+
+ Q_INVOKABLE void cancel();
+ Q_INVOKABLE void bakeLights();
+ Q_INVOKABLE void apply();
+ Q_INVOKABLE void rebake();
+ Q_INVOKABLE void exposeModelsAndLights(const QString &nodeId);
+
+ void raiseDialog();
+
+ bool manualMode() const;
+ void setManualMode(bool enabled);
+
+ static ModelNode resolveView3dNode(AbstractView *view);
+ static QString resolveView3dId(AbstractView *view);
+
+signals:
+ void finished();
+ void progress(const QString &msg);
+ void manualModeChanged();
+
+protected:
+ bool eventFilter(QObject *obj, QEvent *event) override;
+
+private:
+ void showSetupDialog();
+ void showProgressDialog();
+ void cleanup();
+
+ // Separate dialogs for setup and progress, as setup needs to be modal
+ QPointer<QQuickView> m_setupDialog;
+ QPointer<QQuickView> m_progressDialog;
+
+ QPointer<BakeLightsConnectionManager> m_connectionManager;
+ QPointer<NodeInstanceView> m_nodeInstanceView;
+ QPointer<RewriterView> m_rewriterView;
+ QPointer<AbstractView> m_view;
+ QPointer<BakeLightsDataModel> m_dataModel;
+ ModelPointer m_model;
+ QString m_view3dId;
+ bool m_manualMode = false;
+};
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/edit3d/bakelightsconnectionmanager.cpp b/src/plugins/qmldesigner/components/edit3d/bakelightsconnectionmanager.cpp
new file mode 100644
index 00000000000..d2a6f3d332d
--- /dev/null
+++ b/src/plugins/qmldesigner/components/edit3d/bakelightsconnectionmanager.cpp
@@ -0,0 +1,48 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
+
+#include "bakelightsconnectionmanager.h"
+
+#include <puppettocreatorcommand.h>
+
+namespace QmlDesigner {
+
+BakeLightsConnectionManager::BakeLightsConnectionManager()
+{
+ connections().emplace_back("Bake lights", "bakelightsmode");
+}
+
+void BakeLightsConnectionManager::setProgressCallback(Callback callback)
+{
+ m_progressCallback = std::move(callback);
+}
+
+void BakeLightsConnectionManager::setFinishedCallback(Callback callback)
+{
+ m_finishedCallback = std::move(callback);
+}
+
+void BakeLightsConnectionManager::dispatchCommand(const QVariant &command,
+ ConnectionManagerInterface::Connection &)
+{
+ static const int commandType = QMetaType::type("PuppetToCreatorCommand");
+
+ if (command.userType() == commandType) {
+ auto cmd = command.value<PuppetToCreatorCommand>();
+ switch (cmd.type()) {
+ case PuppetToCreatorCommand::BakeLightsProgress:
+ m_progressCallback(cmd.data().toString());
+ break;
+ case PuppetToCreatorCommand::BakeLightsAborted:
+ m_finishedCallback(tr("Baking aborted: %1").arg(cmd.data().toString()));
+ break;
+ case PuppetToCreatorCommand::BakeLightsFinished:
+ m_finishedCallback(tr("Baking finished!"));
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/edit3d/bakelightsconnectionmanager.h b/src/plugins/qmldesigner/components/edit3d/bakelightsconnectionmanager.h
new file mode 100644
index 00000000000..2af5e56c114
--- /dev/null
+++ b/src/plugins/qmldesigner/components/edit3d/bakelightsconnectionmanager.h
@@ -0,0 +1,28 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
+
+#pragma once
+
+#include "connectionmanager.h"
+
+namespace QmlDesigner {
+
+class BakeLightsConnectionManager : public ConnectionManager
+{
+public:
+ using Callback = std::function<void(const QString &)>;
+
+ BakeLightsConnectionManager();
+
+ void setProgressCallback(Callback callback);
+ void setFinishedCallback(Callback callback);
+
+protected:
+ void dispatchCommand(const QVariant &command, Connection &connection) override;
+
+private:
+ Callback m_progressCallback;
+ Callback m_finishedCallback;
+};
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/edit3d/bakelightsdatamodel.cpp b/src/plugins/qmldesigner/components/edit3d/bakelightsdatamodel.cpp
new file mode 100644
index 00000000000..36d192a9244
--- /dev/null
+++ b/src/plugins/qmldesigner/components/edit3d/bakelightsdatamodel.cpp
@@ -0,0 +1,387 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
+
+#include "bakelightsdatamodel.h"
+
+#include "abstractview.h"
+#include "bakelights.h"
+#include "bindingproperty.h"
+#include "enumeration.h"
+#include "externaldependenciesinterface.h"
+#include "model.h"
+#include "modelnode.h"
+#include "nodelistproperty.h"
+#include "nodemetainfo.h"
+#include "qmlobjectnode.h"
+#include "variantproperty.h"
+
+#include <utils/expected.h>
+#include <utils/filepath.h>
+#include <utils/qtcassert.h>
+
+#include <algorithm>
+
+namespace QmlDesigner {
+
+
+BakeLightsDataModel::BakeLightsDataModel(AbstractView *view)
+ : QAbstractListModel(view)
+ , m_view(view)
+{
+}
+
+BakeLightsDataModel::~BakeLightsDataModel()
+{
+}
+
+int BakeLightsDataModel::rowCount(const QModelIndex &) const
+{
+ return m_dataList.count();
+}
+
+QHash<int, QByteArray> BakeLightsDataModel::roleNames() const
+{
+ static const QHash<int, QByteArray> roles {
+ {Qt::UserRole + 1, "displayId"},
+ {Qt::UserRole + 2, "nodeId"},
+ {Qt::UserRole + 3, "isModel"},
+ {Qt::UserRole + 4, "isEnabled"},
+ {Qt::UserRole + 5, "inUse"},
+ {Qt::UserRole + 6, "isTitle"},
+ {Qt::UserRole + 7, "isUnexposed"},
+ {Qt::UserRole + 8, "resolution"},
+ {Qt::UserRole + 9, "bakeMode"}
+ };
+ return roles;
+}
+
+QVariant BakeLightsDataModel::data(const QModelIndex &index, int role) const
+{
+ QTC_ASSERT(index.isValid() && index.row() < m_dataList.count(), return {});
+ QTC_ASSERT(roleNames().contains(role), return {});
+
+ QByteArray roleName = roleNames().value(role);
+ const BakeData &bakeData = m_dataList[index.row()];
+
+ if (roleName == "displayId") {
+ const QString id = bakeData.id;
+ const PropertyName aliasProp = bakeData.aliasProp;
+ if (aliasProp.isEmpty())
+ return id;
+ else
+ return QVariant{id + " - " + QString::fromUtf8(aliasProp)};
+ return {};
+ }
+
+ if (roleName == "nodeId")
+ return bakeData.id;
+
+ if (roleName == "isModel")
+ return bakeData.isModel;
+
+ if (roleName == "isEnabled")
+ return bakeData.enabled;
+
+ if (roleName == "inUse")
+ return bakeData.inUse;
+
+ if (roleName == "isTitle")
+ return bakeData.isTitle;
+
+ if (roleName == "isUnexposed")
+ return bakeData.isUnexposed;
+
+ if (roleName == "resolution")
+ return bakeData.resolution;
+
+ if (roleName == "bakeMode")
+ return bakeData.bakeMode;
+
+ return {};
+}
+
+bool BakeLightsDataModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ QTC_ASSERT(index.isValid() && index.row() < m_dataList.count(), return false);
+ QTC_ASSERT(roleNames().contains(role), return false);
+
+ QByteArray roleName = roleNames().value(role);
+ BakeData &bakeData = m_dataList[index.row()];
+
+ bool changed = false;
+
+ if (roleName == "isEnabled") {
+ changed = bakeData.enabled != value.toBool();
+ bakeData.enabled = value.toBool();
+ } else if (roleName == "inUse") {
+ changed = bakeData.inUse != value.toBool();
+ bakeData.inUse = value.toBool();
+ } else if (roleName == "resolution") {
+ changed = bakeData.resolution != value.toInt();
+ bakeData.resolution = value.toInt();
+ } else if (roleName == "bakeMode") {
+ changed = bakeData.bakeMode != value.toString();
+ bakeData.bakeMode = value.toString();
+ }
+
+ if (changed)
+ emit dataChanged(index, index, {role});
+
+ return changed;
+}
+
+void BakeLightsDataModel::reset()
+{
+ if (!m_view || !m_view->model())
+ return;
+
+ beginResetModel();
+ m_dataList.clear();
+
+ m_view3dNode = BakeLights::resolveView3dNode(m_view);
+
+ // Find all models and lights in active View3D
+ QList<ModelNode> nodes = m_view3dNode.allSubModelNodes();
+
+ if (m_view3dNode.hasBindingProperty("importScene"))
+ nodes.append(m_view3dNode.bindingProperty("importScene").resolveToModelNode().allSubModelNodesAndThisNode());
+
+ QList<BakeData> modelList;
+ QList<BakeData> lightList;
+ QList<BakeData> compModelList;
+ QList<BakeData> compLightList;
+ QList<BakeData> unexposedList;
+
+ // Note: We are always loading base state values for baking. If users want to bake
+ // differently for different states, they need to setup things manually for now.
+ // Same goes if they want to use any unusual bindings in baking properties.
+ for (const auto &node : std::as_const(nodes)) {
+ if (QmlObjectNode(node).hasError())
+ continue;
+
+ BakeData data;
+ data.id = node.id();
+ if (data.id.isEmpty())
+ continue; // Skip nodes without id
+
+ if (node.metaInfo().isQtQuick3DModel()) {
+ data.isModel = true;
+ if (node.hasBindingProperty("bakedLightmap")) {
+ ModelNode blm = node.bindingProperty("bakedLightmap").resolveToModelNode();
+ if (blm.isValid()) {
+ if (blm.hasVariantProperty("enabled"))
+ data.enabled = blm.variantProperty("enabled").value().toBool();
+ else
+ data.enabled = true;
+ }
+ }
+ if (node.hasVariantProperty("lightmapBaseResolution"))
+ data.resolution = node.variantProperty("lightmapBaseResolution").value().toInt();
+ if (node.hasVariantProperty("usedInBakedLighting"))
+ data.inUse = node.variantProperty("usedInBakedLighting").value().toBool();
+ modelList.append(data);
+ } else if (node.metaInfo().isQtQuick3DLight()) {
+ if (node.hasVariantProperty("bakeMode")) {
+ data.bakeMode = node.variantProperty("bakeMode").value()
+ .value<QmlDesigner::Enumeration>().toString();
+ } else {
+ data.bakeMode = "Light.BakeModeDisabled";
+ }
+ lightList.append(data);
+ }
+
+ if (node.isComponent()) {
+ // Every component can expose multiple aliases
+ // We ignore baking properties defined inside the component (no visibility there)
+ bool hasExposedProps = false;
+ const QList<AbstractProperty> props = node.properties();
+ PropertyMetaInfos metaInfos = node.metaInfo().properties();
+ for (const PropertyMetaInfo &mi : metaInfos) {
+ if (mi.isValid() && !mi.isPrivate() && mi.isWritable()) {
+ BakeData propData;
+ propData.id = data.id;
+ propData.aliasProp = mi.name();
+ if (mi.propertyType().isQtQuick3DModel()) {
+ hasExposedProps = true;
+ propData.isModel = true;
+ PropertyName dotName = mi.name() + '.';
+ for (const AbstractProperty &prop : props) {
+ if (prop.name().startsWith(dotName)) {
+ PropertyName subName = prop.name().mid(dotName.size());
+ if (subName == "bakedLightmap") {
+ ModelNode blm = prop.toBindingProperty().resolveToModelNode();
+ if (blm.isValid()) {
+ if (blm.hasVariantProperty("enabled"))
+ propData.enabled = blm.variantProperty("enabled").value().toBool();
+ else
+ propData.enabled = true;
+ }
+ }
+ if (subName == "lightmapBaseResolution")
+ propData.resolution = prop.toVariantProperty().value().toInt();
+ if (subName == "usedInBakedLighting")
+ propData.inUse = prop.toVariantProperty().value().toBool();
+ }
+ }
+ compModelList.append(propData);
+ } else if (mi.propertyType().isQtQuick3DLight()) {
+ hasExposedProps = true;
+ PropertyName dotName = mi.name() + '.';
+ for (const AbstractProperty &prop : props) {
+ if (prop.name().startsWith(dotName)) {
+ PropertyName subName = prop.name().mid(dotName.size());
+ if (subName == "bakeMode") {
+ propData.bakeMode = prop.toVariantProperty().value()
+ .value<QmlDesigner::Enumeration>()
+ .toString();
+ }
+ }
+ }
+ if (propData.bakeMode.isEmpty())
+ propData.bakeMode = "Light.BakeModeDisabled";
+ compLightList.append(propData);
+ }
+ }
+ }
+
+ if (!hasExposedProps && node.metaInfo().isFileComponent()
+ && node.metaInfo().isQtQuick3DNode()) {
+ const QString compFile = node.metaInfo().componentFileName();
+ const QString projPath = m_view->externalDependencies().currentProjectDirPath();
+ if (compFile.startsWith(projPath)) {
+ // Quick and dirty scan of the component source to check if it potentially has
+ // models or lights.
+ QByteArray src = Utils::FilePath::fromString(compFile).fileContents().value();
+ src = src.mid(src.indexOf('{')); // Skip root element
+ if (src.contains("Model {") || src.contains("Light {")) {
+ data.isUnexposed = true;
+ unexposedList.append(data);
+ }
+ }
+ }
+ }
+ }
+
+ auto sortList = [](QList<BakeData> &list) {
+ std::sort(list.begin(), list.end(), [](const BakeData &a, const BakeData &b) {
+ return a.id.compare(b.id) < 0;
+ });
+ };
+
+ sortList(modelList);
+ sortList(lightList);
+ sortList(compModelList);
+ sortList(compLightList);
+ sortList(unexposedList);
+
+ BakeData titleData;
+ titleData.isTitle = true;
+ titleData.id = tr("Lights");
+ m_dataList.append(titleData);
+ m_dataList.append(lightList);
+ m_dataList.append(compLightList);
+ titleData.id = tr("Models");
+ m_dataList.append(titleData);
+ m_dataList.append(modelList);
+ m_dataList.append(compModelList);
+
+ if (!unexposedList.isEmpty()) {
+ titleData.id = tr("Components with unexposed models and/or lights");
+ m_dataList.append(titleData);
+ m_dataList.append(unexposedList);
+ }
+
+ endResetModel();
+}
+
+void BakeLightsDataModel::apply()
+{
+ if (!m_view || !m_view->model())
+ return;
+
+ auto setBakedLightmap = [this](const ModelNode &node, const BakeData &data) {
+ ModelNode blmNode;
+ PropertyName propName{"bakedLightmap"};
+ if (!data.aliasProp.isEmpty())
+ propName.prepend(data.aliasProp + '.');
+ if (node.hasBindingProperty(propName))
+ blmNode = node.bindingProperty(propName).resolveToModelNode();
+ if (!blmNode.isValid() && data.enabled) {
+ NodeMetaInfo metaInfo = m_view->model()->qtQuick3DBakedLightmapMetaInfo();
+ blmNode = m_view->createModelNode("QtQuick3D.BakedLightmap",
+ metaInfo.majorVersion(),
+ metaInfo.minorVersion());
+ QString idPart;
+ if (data.aliasProp.isEmpty())
+ idPart = data.id;
+ else
+ idPart = QStringLiteral("%1_%2").arg(data.id, QString::fromUtf8(data.aliasProp));
+ QString newId = m_view->model()->generateNewId(QStringLiteral("blm_%1").arg(idPart));
+ blmNode.setIdWithoutRefactoring(newId);
+ node.defaultNodeListProperty().reparentHere(blmNode);
+ node.bindingProperty(propName).setExpression(newId);
+ }
+ if (blmNode.isValid()) {
+ VariantProperty enabledProp = blmNode.variantProperty("enabled");
+ VariantProperty prefixProp = blmNode.variantProperty("loadPrefix");
+ VariantProperty keyProp = blmNode.variantProperty("key");
+ enabledProp.setValue(data.enabled);
+ prefixProp.setValue(commonPrefix());
+ keyProp.setValue(blmNode.id());
+ }
+ };
+
+ auto setVariantProp = [](const ModelNode &node,
+ const PropertyName &propName,
+ const PropertyName &aliasProp,
+ const QVariant &value,
+ const QVariant &defaultValue) {
+ PropertyName resolvedName = propName;
+ if (!aliasProp.isEmpty())
+ resolvedName.prepend(aliasProp + '.');
+ if (node.hasVariantProperty(resolvedName) || value != defaultValue)
+ node.variantProperty(resolvedName).setValue(value);
+ };
+
+ // Commits changes to scene model
+ m_view->executeInTransaction(__FUNCTION__, [&]() {
+ for (const BakeData &data : std::as_const(m_dataList)) {
+ if (data.isTitle || data.isUnexposed)
+ continue;
+ ModelNode node = m_view->modelNodeForId(data.id);
+ if (data.isModel) {
+ setBakedLightmap(node, data);
+ setVariantProp(node, "lightmapBaseResolution", data.aliasProp, data.resolution, 1024);
+ setVariantProp(node, "usedInBakedLighting", data.aliasProp, data.inUse, false);
+ } else {
+ setVariantProp(node, "bakeMode", data.aliasProp,
+ QVariant::fromValue(QmlDesigner::Enumeration(data.bakeMode)),
+ QVariant::fromValue(QmlDesigner::Enumeration("Light", "BakeModeDisabled")));
+ }
+ }
+ });
+}
+
+QString BakeLightsDataModel::commonPrefix()
+{
+ static QString prefix = "lightmaps";
+ return prefix;
+}
+
+QDebug operator<<(QDebug debug, const BakeLightsDataModel::BakeData &data)
+{
+ QDebugStateSaver saver(debug);
+ debug.space() << "("
+ << "id:" << data.id
+ << "aliasProp:" << data.aliasProp
+ << "isModel:" << data.isModel
+ << "enabled:" << data.enabled
+ << "inUse:" << data.inUse
+ << "resolution:" << data.resolution
+ << "bakeMode:" << data.bakeMode
+ << "isTitle:" << data.isTitle
+ << ")";
+ return debug;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/edit3d/bakelightsdatamodel.h b/src/plugins/qmldesigner/components/edit3d/bakelightsdatamodel.h
new file mode 100644
index 00000000000..313c09cf459
--- /dev/null
+++ b/src/plugins/qmldesigner/components/edit3d/bakelightsdatamodel.h
@@ -0,0 +1,56 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
+#pragma once
+
+#include "modelnode.h"
+#include "qmldesignercorelib_global.h"
+
+#include <QAbstractListModel>
+#include <QObject>
+#include <QPointer>
+
+namespace QmlDesigner {
+
+class AbstractView;
+
+class BakeLightsDataModel : public QAbstractListModel
+{
+ Q_OBJECT
+
+public:
+ struct BakeData {
+ QString id; // node id. Also used as BakedLightmap.key
+ PropertyName aliasProp; // property id for component exposed models/lights
+ bool isModel = false; // false means light
+ bool enabled = false;
+ bool inUse = false;
+ bool isTitle = false; // if true, indicates a title row in UI
+ bool isUnexposed = false; // if true, indicates a component with unexposed models/lights
+ int resolution = 1024;
+ QString bakeMode;
+ };
+
+ BakeLightsDataModel(AbstractView *view);
+ ~BakeLightsDataModel() override;
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+ QHash<int, QByteArray> roleNames() const override;
+ bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
+
+ void reset();
+ void apply();
+
+ ModelNode view3dNode() const { return m_view3dNode; }
+
+private:
+ QString commonPrefix();
+
+ QPointer<AbstractView> m_view;
+ QList<BakeData> m_dataList;
+ ModelNode m_view3dNode;
+};
+
+QDebug operator<<(QDebug debug, const BakeLightsDataModel::BakeData &data);
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dactions.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dactions.cpp
index 61731c578f8..12d2dd05528 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dactions.cpp
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dactions.cpp
@@ -2,18 +2,15 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "edit3dactions.h"
-#include "edit3dview.h"
-#include <viewmanager.h>
-#include <nodeinstanceview.h>
-#include <nodemetainfo.h>
-#include <qmldesignerplugin.h>
+#include "bakelights.h"
+#include "edit3dview.h"
+#include "nodemetainfo.h"
+#include "qmldesignerconstants.h"
#include "seekerslider.h"
#include <utils/algorithm.h>
-#include <QDebug>
-
namespace QmlDesigner {
Edit3DActionTemplate::Edit3DActionTemplate(const QString &description,
@@ -147,4 +144,33 @@ bool Edit3DParticleSeekerAction::isEnabled(const SelectionContext &) const
return m_seeker->isEnabled();
}
+Edit3DBakeLightsAction::Edit3DBakeLightsAction(const QIcon &icon,
+ Edit3DView *view,
+ SelectionContextOperation selectionAction)
+ : Edit3DAction(QmlDesigner::Constants::EDIT3D_BAKE_LIGHTS,
+ View3DActionType::Empty,
+ QCoreApplication::translate("BakeLights", "Bake Lights"),
+ QKeySequence(),
+ false,
+ false,
+ icon,
+ view,
+ selectionAction,
+ QCoreApplication::translate("BakeLights", "Bake lights for the current 3D scene."))
+ , m_view(view)
+{
+
+}
+
+bool Edit3DBakeLightsAction::isVisible(const SelectionContext &) const
+{
+ return m_view->isBakingLightsSupported();
+}
+
+bool Edit3DBakeLightsAction::isEnabled(const SelectionContext &) const
+{
+ return m_view->isBakingLightsSupported()
+ && !BakeLights::resolveView3dId(m_view).isEmpty();
+}
+
}
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dactions.h b/src/plugins/qmldesigner/components/edit3d/edit3dactions.h
index bad427a25be..4e8be202b9f 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dactions.h
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dactions.h
@@ -122,4 +122,19 @@ private:
SeekerSliderAction *m_seeker = nullptr;
};
+class Edit3DBakeLightsAction : public Edit3DAction
+{
+public:
+ Edit3DBakeLightsAction(const QIcon &icon,
+ Edit3DView *view,
+ SelectionContextOperation selectionAction);
+
+protected:
+ bool isVisible(const SelectionContext &) const override;
+ bool isEnabled(const SelectionContext &) const override;
+
+private:
+ Edit3DView *m_view = nullptr;
+};
+
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp
index d92e76362b9..10d62a5dc21 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp
@@ -4,6 +4,7 @@
#include "edit3dview.h"
#include "backgroundcolorselection.h"
+#include "bakelights.h"
#include "designeractionmanager.h"
#include "designericons.h"
#include "designersettings.h"
@@ -20,11 +21,18 @@
#include "qmldesignerplugin.h"
#include "qmlvisualnode.h"
#include "seekerslider.h"
+#include "theme.h"
+
+#include <model/modelutils.h>
#include <coreplugin/icore.h>
#include <coreplugin/messagebox.h>
-#include <theme.h>
+#include <projectexplorer/target.h>
+#include <projectexplorer/kit.h>
+
+#include <qtsupport/qtkitinformation.h>
+
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
#include <utils/stylehelper.h>
@@ -204,6 +212,12 @@ void Edit3DView::updateActiveScene3D(const QVariantMap &sceneState)
m_particlesPlayAction->action()->setChecked(sceneState[particlesPlayKey].toBool());
else
m_particlesPlayAction->action()->setChecked(true);
+
+ // Selection context change updates visible and enabled states
+ SelectionContext selectionContext(this);
+ selectionContext.setUpdateMode(SelectionContext::UpdateMode::Fast);
+ if (m_bakeLightsAction)
+ m_bakeLightsAction->currentContextChanged(selectionContext);
}
void Edit3DView::modelAttached(Model *model)
@@ -219,6 +233,13 @@ void Edit3DView::modelAttached(Model *model)
edit3DWidget()->canvas()->busyIndicator()->show();
+ m_isBakingLightsSupported = false;
+ ProjectExplorer::Target *target = QmlDesignerPlugin::instance()->currentDesignDocument()->currentTarget();
+ if (target && target->kit()) {
+ if (QtSupport::QtVersion *qtVer = QtSupport::QtKitAspect::qtVersion(target->kit()))
+ m_isBakingLightsSupported = qtVer->qtVersion() >= QVersionNumber(6, 5, 0);
+ }
+
connect(model->metaInfo().itemLibraryInfo(), &ItemLibraryInfo::entriesChanged, this,
&Edit3DView::onEntriesChanged, Qt::UniqueConnection);
}
@@ -279,6 +300,11 @@ void Edit3DView::handleEntriesChanged()
void Edit3DView::modelAboutToBeDetached(Model *model)
{
+ m_isBakingLightsSupported = false;
+
+ if (m_bakeLights)
+ m_bakeLights->cancel();
+
// Hide the canvas when model is detached (i.e. changing documents)
if (edit3DWidget() && edit3DWidget()->canvas()) {
m_canvasCache.insert(model, edit3DWidget()->canvas()->renderImage());
@@ -288,8 +314,8 @@ void Edit3DView::modelAboutToBeDetached(Model *model)
AbstractView::modelAboutToBeDetached(model);
}
-void Edit3DView::importsChanged([[maybe_unused]] const QList<Import> &addedImports,
- [[maybe_unused]] const QList<Import> &removedImports)
+void Edit3DView::importsChanged([[maybe_unused]] const Imports &addedImports,
+ [[maybe_unused]] const Imports &removedImports)
{
checkImports();
}
@@ -702,6 +728,17 @@ void Edit3DView::createEdit3DActions()
m_seekerAction->action()->setEnabled(!m_particlesPlayAction->action()->isChecked());
};
+ SelectionContextOperation bakeLightsTrigger = [this](const SelectionContext &) {
+ if (!m_isBakingLightsSupported)
+ return;
+
+ // BakeLights cleans itself up when its dialog is closed
+ if (!m_bakeLights)
+ m_bakeLights = new BakeLights(this);
+ else
+ m_bakeLights->raiseDialog();
+ };
+
m_particleViewModeAction = new Edit3DAction(
QmlDesigner::Constants::EDIT3D_PARTICLE_MODE,
View3DActionType::Edit3DParticleModeToggle,
@@ -804,6 +841,11 @@ void Edit3DView::createEdit3DActions()
m_seekerAction = createSeekerSliderAction();
+ m_bakeLightsAction = new Edit3DBakeLightsAction(
+ toolbarIcon(Theme::editLightOn_medium), //: TODO placeholder icon
+ this,
+ bakeLightsTrigger);
+
m_leftActions << m_selectionModeAction;
m_leftActions << nullptr; // Null indicates separator
m_leftActions << nullptr; // Second null after separator indicates an exclusive group
@@ -830,6 +872,7 @@ void Edit3DView::createEdit3DActions()
m_rightActions << nullptr;
m_rightActions << m_seekerAction;
m_rightActions << nullptr;
+ m_rightActions << m_bakeLightsAction;
m_rightActions << m_resetAction;
m_visibilityToggleActions << m_showGridAction;
@@ -870,24 +913,20 @@ Edit3DAction *Edit3DView::edit3DAction(View3DActionType type) const
return m_edit3DActions.value(type, nullptr).data();
}
+Edit3DBakeLightsAction *Edit3DView::bakeLightsAction() const
+{
+ return m_bakeLightsAction;
+}
+
void Edit3DView::addQuick3DImport()
{
DesignDocument *document = QmlDesignerPlugin::instance()->currentDesignDocument();
- if (document && !document->inFileComponentModelActive() && model()) {
- const QList<Import> imports = model()->possibleImports();
- for (const auto &import : imports) {
- if (import.url() == "QtQuick3D") {
- if (!import.version().isEmpty() && import.majorVersion() >= 6) {
- // Prefer empty version number in Qt6 and beyond
- model()->changeImports({Import::createLibraryImport(
- import.url(), {}, import.alias(),
- import.importPaths())}, {});
- } else {
- model()->changeImports({import}, {});
- }
- return;
- }
- }
+ if (document && !document->inFileComponentModelActive() && model()
+ && Utils::addImportWithCheck(
+ "QtQuick3D",
+ [](const Import &import) { return !import.hasVersion() || import.majorVersion() >= 6; },
+ model())) {
+ return;
}
Core::AsynchronousMessageBox::warning(tr("Failed to Add Import"),
tr("Could not add QtQuick3D import to project."));
@@ -939,4 +978,9 @@ void Edit3DView::dropAsset(const QString &file, const QPointF &pos)
emitView3DAction(View3DActionType::GetNodeAtPos, pos);
}
+bool Edit3DView::isBakingLightsSupported() const
+{
+ return m_isBakingLightsSupported;
+}
+
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.h b/src/plugins/qmldesigner/components/edit3d/edit3dview.h
index 2b746cf1af7..cd3e686d3bb 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dview.h
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.h
@@ -22,8 +22,10 @@ QT_END_NAMESPACE
namespace QmlDesigner {
+class BakeLights;
class Edit3DWidget;
class Edit3DAction;
+class Edit3DBakeLightsAction;
class Edit3DCameraAction;
class QMLDESIGNERCOMPONENTS_EXPORT Edit3DView : public AbstractView
@@ -42,7 +44,7 @@ public:
void updateActiveScene3D(const QVariantMap &sceneState) override;
void modelAttached(Model *model) override;
void modelAboutToBeDetached(Model *model) override;
- void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
+ void importsChanged(const Imports &addedImports, const Imports &removedImports) override;
void customNotification(const AbstractView *view, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &data) override;
void nodeAtPosReady(const ModelNode &modelNode, const QVector3D &pos3d) override;
@@ -57,6 +59,7 @@ public:
QVector<Edit3DAction *> visibilityToggleActions() const;
QVector<Edit3DAction *> backgroundColorActions() const;
Edit3DAction *edit3DAction(View3DActionType type) const;
+ Edit3DBakeLightsAction *bakeLightsAction() const;
void addQuick3DImport();
void startContextMenu(const QPoint &pos);
@@ -66,6 +69,8 @@ public:
void dropComponent(const ItemLibraryEntry &entry, const QPointF &pos);
void dropAsset(const QString &file, const QPointF &pos);
+ bool isBakingLightsSupported() const;
+
private slots:
void onEntriesChanged();
@@ -122,6 +127,7 @@ private:
Edit3DAction *m_visibilityTogglesAction = nullptr;
Edit3DAction *m_backgrondColorMenuAction = nullptr;
Edit3DAction *m_seekerAction = nullptr;
+ Edit3DBakeLightsAction *m_bakeLightsAction = nullptr;
int particlemode;
ModelCache<QImage> m_canvasCache;
ModelNode m_droppedModelNode;
@@ -130,6 +136,8 @@ private:
NodeAtPosReqType m_nodeAtPosReqType;
QPoint m_contextMenuPos;
QTimer m_compressionTimer;
+ QPointer<BakeLights> m_bakeLights;
+ bool m_isBakingLightsSupported = false;
friend class Edit3DAction;
};
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp
index 408584e166b..a217e396d9c 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp
@@ -261,6 +261,12 @@ void Edit3DWidget::createContextMenu()
view()->emitView3DAction(View3DActionType::AlignViewToCamera, true);
});
+ m_bakeLightsAction = m_contextMenu->addAction(
+ contextIcon(DesignerIcons::LightIcon), // TODO: placeholder icon
+ tr("Bake Lights"), [&] {
+ view()->bakeLightsAction()->action()->trigger();
+ });
+
m_contextMenu->addSeparator();
m_selectParentAction = m_contextMenu->addAction(
@@ -466,6 +472,8 @@ void Edit3DWidget::showContextMenu(const QPoint &pos, const ModelNode &modelNode
m_alignViewAction->setEnabled(isCamera);
m_selectParentAction->setEnabled(selectionExcludingRoot);
m_toggleGroupAction->setEnabled(true);
+ m_bakeLightsAction->setVisible(view()->bakeLightsAction()->action()->isVisible());
+ m_bakeLightsAction->setEnabled(view()->bakeLightsAction()->action()->isEnabled());
m_contextMenu->popup(mapToGlobal(pos));
}
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h
index 092abd313a5..eecd52345fa 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h
@@ -75,6 +75,7 @@ private:
QPointer<QMenu> m_visibilityTogglesMenu;
QPointer<QMenu> m_backgroundColorMenu;
QPointer<QMenu> m_contextMenu;
+ QPointer<QAction> m_bakeLightsAction;
QPointer<QAction> m_editComponentAction;
QPointer<QAction> m_editMaterialAction;
QPointer<QAction> m_duplicateAction;
diff --git a/src/plugins/qmldesigner/components/formeditor/dragtool.cpp b/src/plugins/qmldesigner/components/formeditor/dragtool.cpp
index 86951866058..9a51c9f3722 100644
--- a/src/plugins/qmldesigner/components/formeditor/dragtool.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/dragtool.cpp
@@ -77,8 +77,6 @@ void DragTool::createQmlItemNode(const ItemLibraryEntry &itemLibraryEntry,
const QmlItemNode &parentNode,
const QPointF &scenePosition)
{
- MetaInfo metaInfo = MetaInfo::global();
-
FormEditorItem *parentItem = scene()->itemForQmlItemNode(parentNode);
const QPointF positonInItemSpace = parentItem->qmlItemNode().instanceSceneContentItemTransform().inverted().map(scenePosition);
QPointF itemPos = positonInItemSpace;
@@ -107,8 +105,6 @@ void DragTool::createQmlItemNodeFromImage(const QString &imagePath,
const QPointF &scenePosition)
{
if (parentNode.isValid()) {
- MetaInfo metaInfo = MetaInfo::global();
-
FormEditorItem *parentItem = scene()->itemForQmlItemNode(parentNode);
QPointF positonInItemSpace = parentItem->qmlItemNode().instanceSceneContentItemTransform().inverted().map(scenePosition);
@@ -121,8 +117,6 @@ void DragTool::createQmlItemNodeFromFont(const QString &fontPath,
const QPointF &scenePos)
{
if (parentNode.isValid()) {
- MetaInfo metaInfo = MetaInfo::global();
-
FormEditorItem *parentItem = scene()->itemForQmlItemNode(parentNode);
QPointF positonInItemSpace = parentItem->qmlItemNode().instanceSceneContentItemTransform()
.inverted().map(scenePos);
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp
index 1f4d5262852..5661e4ff793 100644
--- a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp
@@ -253,7 +253,7 @@ void FormEditorView::modelAboutToBeDetached(Model *model)
AbstractView::modelAboutToBeDetached(model);
}
-void FormEditorView::importsChanged(const QList<Import> &/*addedImports*/, const QList<Import> &/*removedImports*/)
+void FormEditorView::importsChanged(const Imports &/*addedImports*/, const Imports &/*removedImports*/)
{
reset();
}
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorview.h b/src/plugins/qmldesigner/components/formeditor/formeditorview.h
index fde20427628..f97959acb37 100644
--- a/src/plugins/qmldesigner/components/formeditor/formeditorview.h
+++ b/src/plugins/qmldesigner/components/formeditor/formeditorview.h
@@ -48,7 +48,7 @@ public:
void modelAttached(Model *model) override;
void modelAboutToBeDetached(Model *model) override;
- void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
+ void importsChanged(const Imports &addedImports, const Imports &removedImports) override;
void nodeCreated(const ModelNode &createdNode) override;
void nodeAboutToBeRemoved(const ModelNode &removedNode) override;
diff --git a/src/plugins/qmldesigner/components/formeditor/toolbox.cpp b/src/plugins/qmldesigner/components/formeditor/toolbox.cpp
index acd0b7401b0..47a9503b2d3 100644
--- a/src/plugins/qmldesigner/components/formeditor/toolbox.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/toolbox.cpp
@@ -20,6 +20,8 @@ ToolBox::ToolBox(QWidget *parentWidget)
, m_rightToolBar(new QToolBar(QLatin1String("RightSidebar"), this))
{
Utils::StyleHelper::setPanelWidget(this, false);
+ Utils::StyleHelper::setPanelWidgetSingleRow(this, false);
+ setFixedHeight(Theme::toolbarSize());
m_leftToolBar->setFloatable(true);
m_leftToolBar->setMovable(true);
@@ -29,8 +31,6 @@ ToolBox::ToolBox(QWidget *parentWidget)
horizontalLayout->setContentsMargins(0, 0, 0, 0);
horizontalLayout->setSpacing(0);
- setFixedHeight(Theme::toolbarSize());
-
Utils::StyleHelper::setPanelWidget(m_leftToolBar, false);
Utils::StyleHelper::setPanelWidgetSingleRow(m_leftToolBar, false);
m_leftToolBar->setFixedHeight(Theme::toolbarSize());
diff --git a/src/plugins/qmldesigner/components/integration/designdocumentview.cpp b/src/plugins/qmldesigner/components/integration/designdocumentview.cpp
index a587580590d..4a1c92ad0aa 100644
--- a/src/plugins/qmldesigner/components/integration/designdocumentview.cpp
+++ b/src/plugins/qmldesigner/components/integration/designdocumentview.cpp
@@ -115,6 +115,7 @@ QString DesignDocumentView::toText() const
QScopedPointer<RewriterView> rewriterView(
new RewriterView(externalDependencies(), RewriterView::Amend));
rewriterView->setCheckSemanticErrors(false);
+ rewriterView->setPossibleImportsEnabled(false);
rewriterView->setTextModifier(&modifier);
outputModel->setRewriterView(rewriterView.data());
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryaddimportmodel.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryaddimportmodel.cpp
index 5b46c1d12ef..41a9c6b5f4a 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryaddimportmodel.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryaddimportmodel.cpp
@@ -56,14 +56,14 @@ QHash<int, QByteArray> ItemLibraryAddImportModel::roleNames() const
return m_roleNames;
}
-void ItemLibraryAddImportModel::update(const QList<Import> &possibleImports)
+void ItemLibraryAddImportModel::update(const Imports &possibleImports)
{
beginResetModel();
m_importList.clear();
const DesignerMcuManager &mcuManager = DesignerMcuManager::instance();
const bool isQtForMCUs = mcuManager.isMCUProject();
- QList<Import> filteredImports;
+ Imports filteredImports;
if (isQtForMCUs) {
const QStringList mcuAllowedList = mcuManager.allowedImports();
const QStringList mcuBannedList = mcuManager.bannedImports();
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryaddimportmodel.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryaddimportmodel.h
index 5785b67301a..2989fd51642 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryaddimportmodel.h
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryaddimportmodel.h
@@ -24,7 +24,7 @@ public:
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
QHash<int, QByteArray> roleNames() const override;
- void update(const QList<Import> &possibleImports);
+ void update(const Imports &possibleImports);
void setSearchText(const QString &searchText);
Import getImportAt(int index) const;
@@ -33,7 +33,7 @@ public:
private:
QString m_searchText;
- QList<Import> m_importList;
+ Imports m_importList;
QSet<QString> m_importFilterList;
QHash<int, QByteArray> m_roleNames;
QSet<QString> m_priorityImports;
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp
index 635a248152d..d141b88dc85 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp
@@ -14,6 +14,8 @@
#include "rewritingexception.h"
#include "viewmanager.h"
+#include <model/modelutils.h>
+
#include <qmljs/qmljsmodelmanagerinterface.h>
#include <utils/algorithm.h>
@@ -300,7 +302,7 @@ bool ItemLibraryAssetImporter::preParseQuick3DAsset(const QString &file, ParseDa
if (exitVal == QDialog::Accepted)
overwriteFiles = dlg.selectedFiles();
if (!overwriteFiles.isEmpty()) {
- overwriteFiles.append(Utils::toList(alwaysOverwrite));
+ overwriteFiles.append(::Utils::toList(alwaysOverwrite));
m_overwrittenImports.insert(pd.targetDirPath, overwriteFiles);
} else {
addWarning(tr("No files selected for overwrite, skipping import: \"%1\".").arg(pd.assetName));
@@ -359,9 +361,8 @@ void ItemLibraryAssetImporter::postParseQuick3DAsset(ParseData &pd)
qmlInfo.append(".");
qmlInfo.append(pd.assetName);
qmlInfo.append('\n');
- m_requiredImports.append(Import::createLibraryImport(
- QStringLiteral("%1.%2").arg(pd.targetDir.dirName(),
- pd.assetName), version));
+ m_requiredImports.append(
+ QStringLiteral("%1.%2").arg(pd.targetDir.dirName(), pd.assetName));
while (qmlIt.hasNext()) {
qmlIt.next();
QFileInfo fi = QFileInfo(qmlIt.filePath());
@@ -417,11 +418,8 @@ void ItemLibraryAssetImporter::postParseQuick3DAsset(ParseData &pd)
}
// Add quick3D import unless it is already added
- if (impVersionMajor > 0
- && m_requiredImports.first().url() != "QtQuick3D") {
- m_requiredImports.prepend(Import::createLibraryImport(
- "QtQuick3D", impVersionStr));
- }
+ if (impVersionMajor > 0 && m_requiredImports.first() != "QtQuick3D")
+ m_requiredImports.prepend("QtQuick3D");
}
if (impVersionMajor > 0 && impVersionMajor < 6) {
pd.iconFile = iconFileName;
@@ -683,66 +681,42 @@ void ItemLibraryAssetImporter::finalizeQuick3DImport()
QFuture<void> result;
if (modelManager) {
QmlJS::PathsAndLanguages pathToScan;
- pathToScan.maybeInsert(Utils::FilePath::fromString(m_importPath));
- result = Utils::asyncRun(&QmlJS::ModelManagerInterface::importScan,
- modelManager->workingCopy(), pathToScan,
- modelManager, true, true, true);
+ pathToScan.maybeInsert(::Utils::FilePath::fromString(m_importPath));
+ result = ::Utils::asyncRun(&QmlJS::ModelManagerInterface::importScan,
+ modelManager->workingCopy(),
+ pathToScan,
+ modelManager,
+ true,
+ true,
+ true);
}
// First we have to wait a while to ensure qmljs detects new files and updates its
- // internal model. Then we make a non-change to the document to trigger qmljs snapshot
- // update. There is an inbuilt delay before rewriter change actually updates the data
- // model, so we need to wait for another moment to allow the change to take effect.
- // Otherwise subsequent subcomponent manager update won't detect new imports properly.
+ // internal model. Then we force amend on rewriter to trigger qmljs snapshot update.
QTimer *timer = new QTimer(parent());
static int counter;
counter = 0;
timer->callOnTimeout([this, timer, progressTitle, model, result]() {
if (!isCancelled()) {
- notifyProgress(++counter, progressTitle);
- if (counter < 50) {
+ notifyProgress(++counter * 2, progressTitle);
+ if (counter < 49) {
if (result.isCanceled() || result.isFinished())
- counter = 49; // skip to next step
- } else if (counter == 50) {
+ counter = 48; // skip to next step
+ } else if (counter == 49) {
QmlDesignerPlugin::instance()->documentManager().resetPossibleImports();
- model->rewriterView()->textModifier()->replace(0, 0, {});
- } else if (counter < 100) {
+ model->rewriterView()->forceAmend();
try {
- const QList<Import> posImports = model->possibleImports();
- const QList<Import> currentImports = model->imports();
- QList<Import> newImportsToAdd;
-
- for (auto &imp : std::as_const(m_requiredImports)) {
- const bool isPos = Utils::contains(posImports, [imp](const Import &posImp) {
- return posImp.url() == imp.url();
- });
- const bool isCur = Utils::contains(currentImports, [imp](const Import &curImp) {
- return curImp.url() == imp.url();
- });
- if (!(isPos || isCur))
- return;
- // Check again with 'contains' to ensure we insert latest version
- if (!currentImports.contains(imp))
- newImportsToAdd.append(imp);
- }
- if (counter == 99)
+ RewriterTransaction transaction = model->rewriterView()->beginRewriterTransaction(
+ QByteArrayLiteral("ItemLibraryAssetImporter::finalizeQuick3DImport"));
+ bool success = Utils::addImportsWithCheck(m_requiredImports, model);
+ if (!success)
addError(tr("Failed to insert import statement into qml document."));
- else
- counter = 99;
- if (!newImportsToAdd.isEmpty()) {
- RewriterTransaction transaction
- = model->rewriterView()->beginRewriterTransaction(
- QByteArrayLiteral("ItemLibraryAssetImporter::finalizeQuick3DImport"));
-
- model->changeImports(newImportsToAdd, {});
- transaction.commit();
- }
+ transaction.commit();
} catch (const RewritingException &e) {
addError(tr("Failed to update imports: %1").arg(e.description()));
- counter = 99;
}
- } else if (counter >= 100) {
+ } else if (counter >= 50) {
if (!m_overwrittenImports.isEmpty())
model->rewriterView()->emitCustomNotification("asset_import_update");
timer->stop();
@@ -752,7 +726,7 @@ void ItemLibraryAssetImporter::finalizeQuick3DImport()
timer->stop();
}
});
- timer->start(50);
+ timer->start(100);
} else {
notifyFinished();
}
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.h
index c7952e9b8f6..a53f0c9de1b 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.h
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.h
@@ -107,7 +107,7 @@ private:
int m_currentImportId = 0;
QHash<int, ParseData> m_parseData;
QString m_progressTitle;
- QList<Import> m_requiredImports;
+ QStringList m_requiredImports;
QList<int> m_puppetQueue;
};
} // QmlDesigner
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryiconimageprovider.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryiconimageprovider.cpp
index cdaa3e28a9c..304aa5716ff 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryiconimageprovider.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryiconimageprovider.cpp
@@ -20,7 +20,7 @@ QQuickImageResponse *ItemLibraryIconImageProvider::requestImageResponse(const QS
Utils::StyleHelper::dpiSpecificImageFile(":/ItemLibrary/images/item-default-icon.png")});
m_cache.requestSmallImage(
- id,
+ Utils::PathString{id},
[response = QPointer<ImageCacheImageResponse>(response.get())](const QImage &image) {
QMetaObject::invokeMethod(
response,
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp
index 96b95f7949a..21f2e6aa55d 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp
@@ -304,28 +304,6 @@ Import ItemLibraryModel::entryToImport(const ItemLibraryEntry &entry)
}
-// Returns true if first import version is higher or equal to second import version
-static bool compareVersions(const QString &version1, const QString &version2)
-{
- if (version2.isEmpty() || version1 == version2)
- return true;
- const QStringList version1List = version1.split(QLatin1Char('.'));
- const QStringList version2List = version2.split(QLatin1Char('.'));
- if (version1List.count() == 2 && version2List.count() == 2) {
- int major1 = version1List.constFirst().toInt();
- int major2 = version2List.constFirst().toInt();
- if (major1 > major2) {
- return true;
- } else if (major1 == major2) {
- int minor1 = version1List.constLast().toInt();
- int minor2 = version2List.constLast().toInt();
- if (minor1 >= minor2)
- return true;
- }
- }
- return false;
-}
-
void ItemLibraryModel::update(ItemLibraryInfo *itemLibraryInfo, Model *model)
{
if (!model)
@@ -343,7 +321,7 @@ void ItemLibraryModel::update(ItemLibraryInfo *itemLibraryInfo, Model *model)
materialBundlePrefix.append(".MaterialBundle");
// create import sections
- const QList<Import> usedImports = model->usedImports();
+ const Imports usedImports = model->usedImports();
QHash<QString, ItemLibraryImport *> importHash;
for (const Import &import : model->imports()) {
if (import.url() != projectName) {
@@ -363,7 +341,7 @@ void ItemLibraryModel::update(ItemLibraryInfo *itemLibraryInfo, Model *model)
addNew = false; // add only 1 Quick3DAssets import section
} else if (oldImport && oldImport->importEntry().url() == import.url()) {
// Retain the higher version if multiples exist
- if (compareVersions(oldImport->importEntry().version(), import.version()))
+ if (oldImport->importEntry().toVersion() >= import.toVersion() || import.hasVersion())
addNew = false;
else
delete oldImport;
@@ -550,7 +528,7 @@ ItemLibraryImport *ItemLibraryModel::importByUrl(const QString &importUrl) const
return nullptr;
}
-void ItemLibraryModel::updateUsedImports(const QList<Import> &usedImports)
+void ItemLibraryModel::updateUsedImports(const Imports &usedImports)
{
// imports in the excludeList are not marked used and thus can always be removed even when in use.
const QList<QString> excludeList = {"SimulinkConnector"};
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.h
index 4e9c5809c12..212ddf8e040 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.h
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.h
@@ -38,7 +38,7 @@ public:
ItemLibraryImport *importByUrl(const QString &importName) const;
void update(ItemLibraryInfo *itemLibraryInfo, Model *model);
- void updateUsedImports(const QList<Import> &usedImports);
+ void updateUsedImports(const Imports &usedImports);
QMimeData *getMimeData(const ItemLibraryEntry &itemLibraryEntry);
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp
index b5a0567114a..d370f6d4547 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(model->possibleImports());
+ m_widget->updatePossibleImports(difference(model->possibleImports(), model->imports()));
m_hasErrors = !rewriterView()->errors().isEmpty();
m_widget->setFlowMode(QmlItemNode(rootModelNode()).isFlowView());
}
@@ -74,13 +74,14 @@ void ItemLibraryView::modelAboutToBeDetached(Model *model)
m_widget->setModel(nullptr);
}
-void ItemLibraryView::importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports)
+void ItemLibraryView::importsChanged(const Imports &addedImports, const Imports &removedImports)
{
DesignDocument *document = QmlDesignerPlugin::instance()->currentDesignDocument();
for (const auto &import : addedImports)
document->addSubcomponentManagerImport(import);
updateImports();
+ m_widget->updatePossibleImports(model()->possibleImports());
// TODO: generalize the logic below to allow adding/removing any Qml component when its import is added/removed
bool simulinkImportAdded = std::any_of(addedImports.cbegin(), addedImports.cend(), [](const Import &import) {
@@ -111,7 +112,7 @@ void ItemLibraryView::importsChanged(const QList<Import> &addedImports, const QL
}
}
-void ItemLibraryView::possibleImportsChanged(const QList<Import> &possibleImports)
+void ItemLibraryView::possibleImportsChanged(const Imports &possibleImports)
{
DesignDocument *document = QmlDesignerPlugin::instance()->currentDesignDocument();
for (const auto &import : possibleImports)
@@ -120,7 +121,7 @@ void ItemLibraryView::possibleImportsChanged(const QList<Import> &possibleImport
m_widget->updatePossibleImports(possibleImports);
}
-void ItemLibraryView::usedImportsChanged(const QList<Import> &usedImports)
+void ItemLibraryView::usedImportsChanged(const Imports &usedImports)
{
m_widget->updateUsedImports(usedImports);
}
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.h
index e28f39318c0..43287ae0e5a 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.h
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.h
@@ -26,9 +26,9 @@ public:
// AbstractView
void modelAttached(Model *model) override;
void modelAboutToBeDetached(Model *model) override;
- void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
- void possibleImportsChanged(const QList<Import> &possibleImports) override;
- void usedImportsChanged(const QList<Import> &usedImports) override;
+ void importsChanged(const Imports &addedImports, const Imports &removedImports) override;
+ void possibleImportsChanged(const Imports &possibleImports) override;
+ void usedImportsChanged(const Imports &usedImports) override;
void documentMessagesChanged(const QList<DocumentMessage> &errors, const QList<DocumentMessage> &warnings) override;
void updateImport3DSupport(const QVariantMap &supportMap) override;
void customNotification(const AbstractView *view, const QString &identifier,
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp
index 549f9e69c10..f98284f61d6 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp
@@ -18,6 +18,7 @@
#include <itemlibrarymodel.h>
#include <metainfo.h>
#include <model.h>
+#include <model/modelutils.h>
#include <rewritingexception.h>
#include <qmldesignerconstants.h>
#include <qmldesignerplugin.h>
@@ -59,7 +60,7 @@ namespace QmlDesigner {
static QString propertyEditorResourcesPath()
{
#ifdef SHARE_QML_PATH
- if (Utils::qtcEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
+ if (::Utils::qtcEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
return QLatin1String(SHARE_QML_PATH) + "/propertyEditorQmlSources";
#endif
return Core::ICore::resourcePath("qmldesigner/propertyEditorQmlSources").toString();
@@ -80,26 +81,16 @@ bool ItemLibraryWidget::eventFilter(QObject *obj, QEvent *event)
ItemLibraryEntry entry = m_itemToDrag.value<ItemLibraryEntry>();
// For drag to be handled correctly, we must have the component properly imported
// beforehand, so we import the module immediately when the drag starts
- if (!entry.requiredImport().isEmpty()) {
- // We don't know if required import is library of file import, so try both.
- Import libImport = Import::createLibraryImport(entry.requiredImport());
- Import fileImport = Import::createFileImport(entry.requiredImport());
- if (!m_model->hasImport(libImport, true, true)
- && !m_model->hasImport(fileImport, true, true)) {
- const QList<Import> possImports = m_model->possibleImports();
- for (const auto &possImport : possImports) {
- if ((!possImport.url().isEmpty() && possImport.url() == libImport.url())
- || (!possImport.file().isEmpty() && possImport.file() == fileImport.file())) {
- m_model->changeImports({possImport}, {});
- break;
- }
- }
- }
+ if (!entry.requiredImport().isEmpty()
+ && !Utils::addImportWithCheck(entry.requiredImport(), m_model)) {
+ qWarning() << __FUNCTION__ << "Required import adding failed:"
+ << entry.requiredImport();
}
if (model) {
model->startDrag(m_itemLibraryModel->getMimeData(entry),
- Utils::StyleHelper::dpiSpecificImageFile(entry.libraryEntryIconPath()));
+ ::Utils::StyleHelper::dpiSpecificImageFile(
+ entry.libraryEntryIconPath()));
}
m_itemToDrag = {};
@@ -154,7 +145,7 @@ ItemLibraryWidget::ItemLibraryWidget(AsynchronousImageCache &imageCache)
updateSearch();
setStyleSheet(Theme::replaceCssColors(
- QString::fromUtf8(Utils::FileReader::fetchQrc(":/qmldesigner/stylesheet.css"))));
+ QString::fromUtf8(::Utils::FileReader::fetchQrc(":/qmldesigner/stylesheet.css"))));
m_qmlSourceUpdateShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_F5), this);
connect(m_qmlSourceUpdateShortcut, &QShortcut::activated, this, &ItemLibraryWidget::reloadQmlSource);
@@ -176,10 +167,9 @@ ItemLibraryWidget::ItemLibraryWidget(AsynchronousImageCache &imageCache)
{"itemLibraryIconHeight", m_itemIconSize.height()},
{"rootView", QVariant::fromValue(this)},
{"widthLimit", HORIZONTAL_LAYOUT_WIDTH_LIMIT},
- {"highlightColor", Utils::StyleHelper::notTooBrightHighlightColor()},
+ {"highlightColor", ::Utils::StyleHelper::notTooBrightHighlightColor()},
{"tooltipBackend", QVariant::fromValue(m_previewTooltipBackend.get())}});
-
reloadQmlSource();
}
@@ -246,7 +236,7 @@ void ItemLibraryWidget::handleAddImport(int index)
+ importStr);
}
- QList<Import> imports;
+ Imports imports;
const QString dependency = getDependencyImport(import);
auto document = QmlDesignerPlugin::instance()->currentDesignDocument();
@@ -303,7 +293,7 @@ void ItemLibraryWidget::setModel(Model *model)
QString ItemLibraryWidget::qmlSourcesPath()
{
#ifdef SHARE_QML_PATH
- if (Utils::qtcEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
+ if (::Utils::qtcEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
return QLatin1String(SHARE_QML_PATH) + "/itemLibraryQmlSources";
#endif
return Core::ICore::resourcePath("qmldesigner/itemLibraryQmlSources").toString();
@@ -346,13 +336,13 @@ void ItemLibraryWidget::updateModel()
updateSearch();
}
-void ItemLibraryWidget::updatePossibleImports(const QList<Import> &possibleImports)
+void ItemLibraryWidget::updatePossibleImports(const Imports &possibleImports)
{
- m_addModuleModel->update(possibleImports);
+ m_addModuleModel->update(difference(possibleImports, m_model->imports()));
delayedUpdateModel();
}
-void ItemLibraryWidget::updateUsedImports(const QList<Import> &usedImports)
+void ItemLibraryWidget::updateUsedImports(const Imports &usedImports)
{
m_itemLibraryModel->updateUsedImports(usedImports);
}
@@ -368,7 +358,7 @@ void ItemLibraryWidget::handlePriorityImportsChanged()
{
if (!m_itemLibraryInfo.isNull()) {
m_addModuleModel->setPriorityImports(m_itemLibraryInfo->priorityImports());
- m_addModuleModel->update(m_model->possibleImports());
+ m_addModuleModel->update(difference(m_model->possibleImports(), m_model->imports()));
}
}
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h
index 394b3ea6103..38cd782d097 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h
@@ -60,8 +60,8 @@ public:
void switchToComponentsView();
void delayedUpdateModel();
void updateModel();
- void updatePossibleImports(const QList<Import> &possibleImports);
- void updateUsedImports(const QList<Import> &usedImports);
+ void updatePossibleImports(const Imports &possibleImports);
+ void updateUsedImports(const Imports &usedImports);
void setModel(Model *model);
void setFlowMode(bool b);
diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.cpp
index 10b6660db57..4ed241abf98 100644
--- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.cpp
+++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.cpp
@@ -51,6 +51,10 @@ QVariant MaterialBrowserTexturesModel::data(const QModelIndex &index, int role)
if (role == RoleTexInternalId)
return m_textureList.at(index.row()).internalId();
+ if (role == RoleTexId) {
+ return m_textureList.at(index.row()).id();
+ }
+
if (role == RoleTexToolTip) {
QString source = data(index, RoleTexSource).toString(); // absolute path
if (source.isEmpty())
@@ -88,6 +92,7 @@ QHash<int, QByteArray> MaterialBrowserTexturesModel::roleNames() const
static const QHash<int, QByteArray> roles {
{RoleTexHasDynamicProps, "hasDynamicProperties"},
{RoleTexInternalId, "textureInternalId"},
+ {RoleTexId, "textureId"},
{RoleTexSource, "textureSource"},
{RoleTexToolTip, "textureToolTip"},
{RoleTexVisible, "textureVisible"}
@@ -294,6 +299,21 @@ void MaterialBrowserTexturesModel::deleteTexture(int idx)
}
}
+void MaterialBrowserTexturesModel::setTextureId(int idx, const QString &newId)
+{
+ if (!isValidIndex(idx))
+ return;
+
+ ModelNode node = m_textureList[idx];
+ if (!node.isValid())
+ return;
+
+ if (node.id() != newId) {
+ node.setIdWithRefactoring(newId);
+ emit dataChanged(index(idx, 0), index(idx, 0), {RoleTexId});
+ }
+}
+
void MaterialBrowserTexturesModel::applyToSelectedMaterial(qint64 internalId)
{
int idx = m_textureIndexHash.value(internalId);
diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.h b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.h
index 6d66ad13ec5..9cb7c5ac18f 100644
--- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.h
+++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.h
@@ -55,6 +55,7 @@ public:
Q_INVOKABLE void addNewTexture();
Q_INVOKABLE void duplicateTexture(int idx);
Q_INVOKABLE void deleteTexture(int idx);
+ Q_INVOKABLE void setTextureId(int idx, const QString &newId);
Q_INVOKABLE void applyToSelectedMaterial(qint64 internalId);
Q_INVOKABLE void applyToSelectedModel(qint64 internalId);
Q_INVOKABLE void openTextureEditor();
@@ -91,6 +92,7 @@ private:
enum {
RoleTexHasDynamicProps = Qt::UserRole + 1,
RoleTexInternalId,
+ RoleTexId,
RoleTexSource,
RoleTexToolTip,
RoleTexVisible
diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp
index 5265c70683d..5349fc26ce7 100644
--- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp
+++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp
@@ -264,12 +264,17 @@ void MaterialBrowserView::refreshModel(bool updateImages)
m_widget->materialBrowserTexturesModel()->setTextures(textures);
m_widget->materialBrowserModel()->setHasMaterialLibrary(matLib.isValid());
- if (updateImages) {
- for (const ModelNode &node : std::as_const(materials))
- m_previewRequests.insert(node);
- if (!m_previewRequests.isEmpty())
- m_previewTimer.start(0);
- }
+ if (updateImages)
+ updateMaterialsPreview();
+}
+
+void MaterialBrowserView::updateMaterialsPreview()
+{
+ const QList<ModelNode> materials = m_widget->materialBrowserModel()->materials();
+ for (const ModelNode &node : materials)
+ m_previewRequests.insert(node);
+ if (!m_previewRequests.isEmpty())
+ m_previewTimer.start(0);
}
bool MaterialBrowserView::isMaterial(const ModelNode &node) const
@@ -469,8 +474,8 @@ ModelNode MaterialBrowserView::getMaterialOfModel(const ModelNode &model, int id
return mat;
}
-void MaterialBrowserView::importsChanged([[maybe_unused]] const QList<Import> &addedImports,
- [[maybe_unused]] const QList<Import> &removedImports)
+void MaterialBrowserView::importsChanged([[maybe_unused]] const Imports &addedImports,
+ [[maybe_unused]] const Imports &removedImports)
{
bool hasQuick3DImport = model()->hasImport("QtQuick3D");
@@ -541,6 +546,7 @@ void MaterialBrowserView::active3DSceneChanged(qint32 sceneId)
void MaterialBrowserView::currentStateChanged([[maybe_unused]] const ModelNode &node)
{
m_widget->materialBrowserTexturesModel()->updateAllTexturesSources();
+ updateMaterialsPreview();
}
void MaterialBrowserView::instancesCompleted(const QVector<ModelNode> &completedNodeList)
diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.h b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.h
index 811d6679b63..297487ae66f 100644
--- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.h
+++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.h
@@ -44,7 +44,7 @@ public:
void nodeAboutToBeRemoved(const ModelNode &removedNode) override;
void nodeRemoved(const ModelNode &removedNode, const NodeAbstractProperty &parentProperty,
PropertyChangeFlags propertyChange) override;
- void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
+ void importsChanged(const Imports &addedImports, const Imports &removedImports) override;
void customNotification(const AbstractView *view, const QString &identifier,
const QList<ModelNode> &nodeList, const QList<QVariant> &data) override;
void instancesCompleted(const QVector<ModelNode> &completedNodeList) override;
@@ -66,6 +66,7 @@ protected:
private:
void refreshModel(bool updateImages);
+ void updateMaterialsPreview();
bool isMaterial(const ModelNode &node) const;
bool isTexture(const ModelNode &node) const;
void loadPropertyGroups();
diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp b/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp
index 47d47985ebd..96e01072904 100644
--- a/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp
+++ b/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp
@@ -38,6 +38,20 @@
#include <QShortcut>
#include <QColorDialog>
+namespace {
+QSize maxSize(const std::initializer_list<QSize> &sizeList)
+{
+ QSize result;
+ for (const QSize &size : sizeList) {
+ if (size.width() > result.width())
+ result.setWidth(size.width());
+ if (size.height() > result.height())
+ result.setHeight(size.height());
+ }
+ return result;
+}
+}
+
namespace QmlDesigner {
MaterialEditorView::MaterialEditorView(ExternalDependenciesInterface &externalDependencies)
@@ -64,7 +78,6 @@ MaterialEditorView::MaterialEditorView(ExternalDependenciesInterface &externalDe
m_typeUpdateTimer.setInterval(500);
connect(&m_typeUpdateTimer, &QTimer::timeout, this, &MaterialEditorView::updatePossibleTypes);
- m_stackedWidget->setMinimumWidth(250);
QmlDesignerPlugin::trackWidgetFocusTime(m_stackedWidget, Constants::EVENT_MATERIALEDITOR_TIME);
MaterialEditorDynamicPropertiesProxyModel::registerDeclarativeType();
@@ -594,6 +607,14 @@ void MaterialEditorView::setupQmlBackend()
initPreviewData();
m_stackedWidget->setCurrentWidget(m_qmlBackEnd->widget());
+ if (m_qmlBackEnd->widget()) {
+ m_stackedWidget->setMinimumSize(maxSize({m_qmlBackEnd->widget()->sizeHint(),
+ m_qmlBackEnd->widget()->initialSize(),
+ m_qmlBackEnd->widget()->minimumSizeHint(),
+ m_qmlBackEnd->widget()->minimumSize()}));
+ } else {
+ m_stackedWidget->setMinimumSize({400, 300});
+ }
}
void MaterialEditorView::commitVariantValueToModel(const PropertyName &propertyName, const QVariant &value)
@@ -974,8 +995,8 @@ void MaterialEditorView::modelNodePreviewPixmapChanged(const ModelNode &node, co
m_qmlBackEnd->updateMaterialPreview(pixmap);
}
-void MaterialEditorView::importsChanged([[maybe_unused]] const QList<Import> &addedImports,
- [[maybe_unused]] const QList<Import> &removedImports)
+void MaterialEditorView::importsChanged([[maybe_unused]] const Imports &addedImports,
+ [[maybe_unused]] const Imports &removedImports)
{
m_hasQuick3DImport = model()->hasImport("QtQuick3D");
m_qmlBackEnd->contextObject()->setHasQuick3DImport(m_hasQuick3DImport);
diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditorview.h b/src/plugins/qmldesigner/components/materialeditor/materialeditorview.h
index d47d030e57b..c201742bd51 100644
--- a/src/plugins/qmldesigner/components/materialeditor/materialeditorview.h
+++ b/src/plugins/qmldesigner/components/materialeditor/materialeditorview.h
@@ -55,7 +55,7 @@ public:
void nodeTypeChanged(const ModelNode& node, const TypeName &type, int majorVersion, int minorVersion) override;
void rootNodeTypeChanged(const QString &type, int majorVersion, int minorVersion) override;
void modelNodePreviewPixmapChanged(const ModelNode &node, const QPixmap &pixmap) override;
- void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
+ void importsChanged(const Imports &addedImports, const Imports &removedImports) override;
void customNotification(const AbstractView *view, const QString &identifier,
const QList<ModelNode> &nodeList, const QList<QVariant> &data) override;
void nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent,
diff --git a/src/plugins/qmldesigner/components/navigator/choosefrompropertylistdialog.cpp b/src/plugins/qmldesigner/components/navigator/choosefrompropertylistdialog.cpp
index 35078859de0..91c300e87a2 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.isQuick3DParticleAbstractShape()) {
+ } else if (insertInfo.isQtQuick3DParticleAbstractShape()) {
if (parentInfo.isQtQuick3DParticles3DParticleEmitter3D()
|| parentInfo.isQtQuick3DParticles3DAttractor3D())
propertyList.append("shape");
diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
index 62868290285..16dd2242863 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
+++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
@@ -9,23 +9,24 @@
#include "qmldesignerplugin.h"
#include "assetslibrarywidget.h"
+#include <abstractview.h>
#include <bindingproperty.h>
+#include <coreplugin/icore.h>
+#include <designeractionmanager.h>
#include <designersettings.h>
+#include <import.h>
+#include <invalididexception.h>
+#include <materialutils.h>
+#include <metainfo.h>
+#include <model/modelutils.h>
#include <nodeabstractproperty.h>
#include <nodehints.h>
#include <nodelistproperty.h>
#include <nodeproperty.h>
-#include <variantproperty.h>
-#include <metainfo.h>
-#include <materialutils.h>
-#include <abstractview.h>
-#include <invalididexception.h>
#include <rewritingexception.h>
+#include <variantproperty.h>
#include <qmldesignerconstants.h>
#include <qmlitemnode.h>
-#include <designeractionmanager.h>
-#include <import.h>
-#include <coreplugin/icore.h>
#include <qmlprojectmanager/qmlproject.h>
@@ -210,7 +211,7 @@ QVariant NavigatorTreeModel::data(const QModelIndex &index, int role) const
return modelNode.displayName();
} else if (role == Qt::DecorationRole) {
if (currentQmlObjectNode.hasError())
- return Utils::Icons::WARNING.icon();
+ return ::Utils::Icons::WARNING.icon();
return modelNode.typeIcon();
@@ -314,14 +315,14 @@ QList<ModelNode> NavigatorTreeModel::filteredList(const NodeListProperty &proper
if (m_nameFilter.isEmpty()) {
nameFilteredList = propertyNodes;
} else {
- nameFilteredList.append(Utils::filtered(propertyNodes, [&] (const ModelNode &arg){
+ nameFilteredList.append(::Utils::filtered(propertyNodes, [&](const ModelNode &arg) {
const bool value = m_nameFilteredList.contains(arg);
return value;
}));
}
if (filter) {
- list.append(Utils::filtered(nameFilteredList, [] (const ModelNode &arg) {
+ list.append(::Utils::filtered(nameFilteredList, [](const ModelNode &arg) {
const bool value = (QmlItemNode::isValidQmlItemNode(arg) || NodeHints::fromModelNode(arg).visibleInNavigator())
&& arg.id() != Constants::MATERIAL_LIB_ID;
return value;
@@ -899,17 +900,8 @@ ModelNode NavigatorTreeModel::handleItemLibraryFontDrop(const QString &fontFamil
void NavigatorTreeModel::addImport(const QString &importName)
{
- Import import = Import::createLibraryImport(importName);
- if (!m_view->model()->hasImport(import, true, true)) {
- const QList<Import> possImports = m_view->model()->possibleImports();
- for (const auto &possImport : possImports) {
- if (possImport.url() == import.url()) {
- import = possImport;
- m_view->model()->changeImports({import}, {});
- break;
- }
- }
- }
+ if (!Utils::addImportWithCheck(importName, m_view->model()))
+ qWarning() << __FUNCTION__ << "Adding import failed:" << importName;
}
bool QmlDesigner::NavigatorTreeModel::moveNodeToParent(const NodeAbstractProperty &targetProperty,
@@ -1268,12 +1260,12 @@ static QList<ModelNode> collectParents(const QList<ModelNode> &modelNodes)
}
}
- return Utils::toList(parents);
+ return ::Utils::toList(parents);
}
QList<QPersistentModelIndex> NavigatorTreeModel::nodesToPersistentIndex(const QList<ModelNode> &modelNodes)
{
- return Utils::transform(modelNodes, [this](const ModelNode &modelNode) {
+ return ::Utils::transform(modelNodes, [this](const ModelNode &modelNode) {
return QPersistentModelIndex(indexForModelNode(modelNode));
});
}
diff --git a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
index 38e6b9ada75..f1a00a36c7c 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
+++ b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
@@ -228,7 +228,7 @@ void NavigatorView::modelAboutToBeDetached(Model *model)
AbstractView::modelAboutToBeDetached(model);
}
-void NavigatorView::importsChanged(const QList<Import> &/*addedImports*/, const QList<Import> &/*removedImports*/)
+void NavigatorView::importsChanged(const Imports &/*addedImports*/, const Imports &/*removedImports*/)
{
treeWidget()->update();
}
diff --git a/src/plugins/qmldesigner/components/navigator/navigatorview.h b/src/plugins/qmldesigner/components/navigator/navigatorview.h
index f5fa81591d9..662b749ecec 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatorview.h
+++ b/src/plugins/qmldesigner/components/navigator/navigatorview.h
@@ -50,7 +50,7 @@ public:
void modelAttached(Model *model) override;
void modelAboutToBeDetached(Model *model) override;
- void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
+ void importsChanged(const Imports &addedImports, const Imports &removedImports) override;
void nodeAboutToBeRemoved(const ModelNode &removedNode) override;
void nodeRemoved(const ModelNode &removedNode, const NodeAbstractProperty &parentProperty, PropertyChangeFlags propertyChange) override;
diff --git a/src/plugins/qmldesigner/components/previewtooltip/previewtooltipbackend.cpp b/src/plugins/qmldesigner/components/previewtooltip/previewtooltipbackend.cpp
index 550ff8fcaf9..16328ae532f 100644
--- a/src/plugins/qmldesigner/components/previewtooltip/previewtooltipbackend.cpp
+++ b/src/plugins/qmldesigner/components/previewtooltip/previewtooltipbackend.cpp
@@ -32,8 +32,9 @@ void PreviewTooltipBackend::showTooltip()
m_tooltip->setInfo(m_info);
m_cache.requestImage(
- m_path,
- [tooltip = QPointer<PreviewImageTooltip>(m_tooltip.get()), scaleImage = m_scaleImage](const QImage &image) {
+ Utils::PathString{m_path},
+ [tooltip = QPointer<PreviewImageTooltip>(m_tooltip.get()),
+ scaleImage = m_scaleImage](const QImage &image) {
QMetaObject::invokeMethod(tooltip, [tooltip, image, scaleImage] {
if (tooltip) {
tooltip->setImage(image, scaleImage);
@@ -42,7 +43,7 @@ void PreviewTooltipBackend::showTooltip()
});
},
[](auto) {},
- m_extraId,
+ Utils::PathString{m_extraId},
m_auxiliaryData);
reposition();
diff --git a/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp b/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp
index 75b9f34cefd..a81560f5662 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp
@@ -29,14 +29,13 @@ GradientModel::GradientModel(QObject *parent) :
int GradientModel::rowCount(const QModelIndex & /*parent*/) const
{
- if (m_itemNode.isValid()) {
- if (m_itemNode.modelNode().hasNodeProperty(gradientPropertyName().toUtf8())) {
- QmlDesigner::ModelNode gradientNode =
- m_itemNode.modelNode().nodeProperty(gradientPropertyName().toUtf8()).modelNode();
+ if (m_itemNode.modelNode().hasNodeProperty(gradientPropertyName().toUtf8())) {
+ QmlDesigner::ModelNode gradientNode = m_itemNode.modelNode()
+ .nodeProperty(gradientPropertyName().toUtf8())
+ .modelNode();
- if (gradientNode.hasNodeListProperty("stops"))
- return gradientNode.nodeListProperty("stops").toModelNodeList().count();
- }
+ if (gradientNode.hasNodeListProperty("stops"))
+ return gradientNode.nodeListProperty("stops").count();
}
return 0;
diff --git a/src/plugins/qmldesigner/components/propertyeditor/itemfiltermodel.cpp b/src/plugins/qmldesigner/components/propertyeditor/itemfiltermodel.cpp
index d52e47c3678..c5d9a23d7ea 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/itemfiltermodel.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/itemfiltermodel.cpp
@@ -7,7 +7,7 @@
#include <model.h>
#include <nodemetainfo.h>
#include <qmlmodelnodeproxy.h>
-#include "variantproperty.h"
+#include <variantproperty.h>
#include <QFileDialog>
#include <QDirIterator>
@@ -15,24 +15,14 @@
using namespace QmlDesigner;
-QHash<int, QByteArray> ItemFilterModel::m_roles;
-
ItemFilterModel::ItemFilterModel(QObject *parent)
: QAbstractListModel(parent)
, m_typeFilter("QtQuick.Item")
, m_selectionOnly(false)
-{
- if (m_roles.empty()) {
- m_roles = QAbstractListModel::roleNames();
- QMetaEnum roleEnum = QMetaEnum::fromType<Roles>();
- for (int i = 0; i < roleEnum.keyCount(); i++)
- m_roles.insert(roleEnum.value(i), roleEnum.key(i));
- }
-}
+{}
void ItemFilterModel::setModelNodeBackend(const QVariant &modelNodeBackend)
{
-
auto modelNodeBackendObject = modelNodeBackend.value<QObject*>();
const auto backendObjectCasted =
@@ -47,18 +37,28 @@ void ItemFilterModel::setModelNodeBackend(const QVariant &modelNodeBackend)
void ItemFilterModel::setTypeFilter(const QString &filter)
{
- if (m_typeFilter != filter) {
- m_typeFilter = filter;
- setupModel();
- }
+ if (m_typeFilter == filter)
+ return;
+
+ m_typeFilter = filter;
+ setupModel();
+ emit typeFilterChanged();
}
void ItemFilterModel::setSelectionOnly(bool value)
{
- if (m_selectionOnly != value) {
- m_selectionOnly = value;
- setupModel();
- }
+ if (m_selectionOnly == value)
+ return;
+
+ m_selectionOnly = value;
+ setupModel();
+ emit selectionOnlyChanged();
+}
+
+void ItemFilterModel::setSelectedItems(const QStringList &selectedItems)
+{
+ m_selectedItems = selectedItems;
+ emit selectedItemsChanged();
}
QString ItemFilterModel::typeFilter() const
@@ -71,14 +71,14 @@ bool ItemFilterModel::selectionOnly() const
return m_selectionOnly;
}
-void ItemFilterModel::registerDeclarativeType()
+QStringList ItemFilterModel::selectedItems() const
{
- qmlRegisterType<ItemFilterModel>("HelperWidgets",2,0,"ItemFilterModel");
+ return m_selectedItems;
}
-QModelIndex ItemFilterModel::index(int row, int column, const QModelIndex &parent) const
+void ItemFilterModel::registerDeclarativeType()
{
- return QAbstractListModel::index(row, column, parent);
+ qmlRegisterType<ItemFilterModel>("HelperWidgets", 2, 0, "ItemFilterModel");
}
int ItemFilterModel::rowCount(const QModelIndex &) const
@@ -88,41 +88,34 @@ int ItemFilterModel::rowCount(const QModelIndex &) const
QVariant ItemFilterModel::data(const QModelIndex &index, int role) const
{
- if (!index.isValid())
+ if (!index.isValid() || index.row() >= rowCount())
return {};
- ModelNode node = modelNodeForRow(index.row());
+ const ModelNode node = modelNodeForRow(index.row());
- QVariant value;
switch (role) {
case IdRole:
- value = node.id();
- break;
+ return node.id();
case NameRole:
- value = node.variantProperty("objectName").value();
- break;
+ return node.variantProperty("objectName").value();
case IdAndNameRole:
- value = QString("%1 [%2]").arg(
- node.variantProperty("objectName").value().toString()
- ,node.id());
- break;
+ return QString("%1 [%2]").arg(node.variantProperty("objectName").value().toString(),
+ node.id());
+ case EnabledRole:
+ return !m_selectedItems.contains(node.id());
default:
- value = node.id();
- break;
+ return {};
}
-
- return value;
-}
-
-// TODO: Handle model data manipulation here.
-bool ItemFilterModel::setData(const QModelIndex &index, const QVariant &value, int role)
-{
- return QAbstractListModel::setData(index, value, role);
}
QHash<int, QByteArray> ItemFilterModel::roleNames() const
{
- return m_roles;
+ static QHash<int, QByteArray> roleNames{{IdRole, "id"},
+ {NameRole, "name"},
+ {IdAndNameRole, "idAndName"},
+ {EnabledRole, "enabled"}};
+
+ return roleNames;
}
QVariant ItemFilterModel::modelNodeBackend() const
diff --git a/src/plugins/qmldesigner/components/propertyeditor/itemfiltermodel.h b/src/plugins/qmldesigner/components/propertyeditor/itemfiltermodel.h
index 6876f1edffd..cb7ae131778 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/itemfiltermodel.h
+++ b/src/plugins/qmldesigner/components/propertyeditor/itemfiltermodel.h
@@ -16,43 +16,43 @@ class ItemFilterModel : public QAbstractListModel
{
Q_OBJECT
- Q_PROPERTY(QString typeFilter READ typeFilter WRITE setTypeFilter)
- Q_PROPERTY(QVariant modelNodeBackendProperty READ modelNodeBackend WRITE setModelNodeBackend NOTIFY modelNodeBackendChanged)
+ Q_PROPERTY(QString typeFilter READ typeFilter WRITE setTypeFilter NOTIFY typeFilterChanged)
+ Q_PROPERTY(QVariant modelNodeBackendProperty READ modelNodeBackend WRITE setModelNodeBackend
+ NOTIFY modelNodeBackendChanged)
Q_PROPERTY(QStringList itemModel READ itemModel NOTIFY itemModelChanged)
- Q_PROPERTY(bool selectionOnly READ selectionOnly WRITE setSelectionOnly NOTIFY selectionOnlyChanged)
+ Q_PROPERTY(
+ bool selectionOnly READ selectionOnly WRITE setSelectionOnly NOTIFY selectionOnlyChanged)
+ Q_PROPERTY(QStringList selectedItems READ selectedItems WRITE setSelectedItems NOTIFY
+ selectedItemsChanged)
public:
- enum Roles {
- IdRole = Qt::UserRole + 1,
- NameRole,
- IdAndNameRole
- };
- Q_ENUM(Roles)
+ enum { IdRole = Qt::DisplayRole, NameRole = Qt::UserRole, IdAndNameRole, EnabledRole };
explicit ItemFilterModel(QObject *parent = nullptr);
void setModelNodeBackend(const QVariant &modelNodeBackend);
void setTypeFilter(const QString &typeFilter);
void setSelectionOnly(bool value);
+ void setSelectedItems(const QStringList &selectedItems);
QString typeFilter() const;
bool selectionOnly() const;
+ QStringList selectedItems() const;
void setupModel();
QStringList itemModel() const;
static void registerDeclarativeType();
- // Make index accessible for Qml side since it's not accessible by default in QAbstractListModel
- Q_INVOKABLE QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const override;
- Q_INVOKABLE virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override;
- Q_INVOKABLE virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
- Q_INVOKABLE virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
+ virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+ virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
- virtual QHash<int,QByteArray> roleNames() const override;
+ virtual QHash<int, QByteArray> roleNames() const override;
signals:
+ void typeFilterChanged();
void modelNodeBackendChanged();
void itemModelChanged();
void selectionOnlyChanged();
+ void selectedItemsChanged();
private:
QVariant modelNodeBackend() const;
@@ -63,7 +63,7 @@ private:
QList<qint32> m_modelInternalIds;
QmlDesigner::ModelNode m_modelNode;
bool m_selectionOnly;
- static QHash<int, QByteArray> m_roles;
+ QStringList m_selectedItems;
};
QML_DECLARE_TYPE(ItemFilterModel)
diff --git a/src/plugins/qmldesigner/components/resources/dockwidgets.css b/src/plugins/qmldesigner/components/resources/dockwidgets.css
index 3404065521e..4ff1b46f52d 100644
--- a/src/plugins/qmldesigner/components/resources/dockwidgets.css
+++ b/src/plugins/qmldesigner/components/resources/dockwidgets.css
@@ -113,40 +113,6 @@ QScrollArea#dockWidgetScrollArea {
background: creatorTheme.DStabInactiveButtonPress;
}
-QScrollBar {
- background: creatorTheme.DSscrollBarTrack;
-}
-
-QScrollBar:vertical {
- width: 10px;
-}
-
-QScrollBar:horizontal {
- height: 10px;
-}
-
-QScrollBar::handle {
- background: creatorTheme.DSscrollBarHandle;
-}
-
-QScrollBar::handle:vertical {
- min-height: 30px;
-}
-
-QScrollBar::handle:horizontal {
- min-width: 30px;
-}
-
-QScrollBar::add-line,
-QScrollBar::sub-line,
-QScrollBar::left-arrow,
-QScrollBar::right-arrow,
-QScrollBar::add-page,
-QScrollBar::sub-page {
- height: 0px;
- width: 0px;
-}
-
/* Focus related styling */
ADS--DockWidgetTab[focused="true"] {
background: creatorTheme.DStabFocusBackground;
diff --git a/src/plugins/qmldesigner/components/texteditor/texteditorview.cpp b/src/plugins/qmldesigner/components/texteditor/texteditorview.cpp
index a7ada80ed73..6c6102036ac 100644
--- a/src/plugins/qmldesigner/components/texteditor/texteditorview.cpp
+++ b/src/plugins/qmldesigner/components/texteditor/texteditorview.cpp
@@ -27,10 +27,11 @@
#include <texteditor/texteditorconstants.h>
#include <qmljseditor/qmljseditordocument.h>
-#include <qmljs/qmljsmodelmanagerinterface.h>
-#include <qmljs/qmljsreformatter.h>
#include <utils/changeset.h>
#include <utils/qtcassert.h>
+#include <utils/uniqueobjectptr.h>
+#include <qmljs/qmljsmodelmanagerinterface.h>
+#include <qmljs/qmljsreformatter.h>
#include <QDebug>
#include <QPair>
@@ -78,15 +79,15 @@ void TextEditorView::modelAttached(Model *model)
AbstractView::modelAttached(model);
- auto textEditor = qobject_cast<TextEditor::BaseTextEditor *>(
- QmlDesignerPlugin::instance()->currentDesignDocument()->textEditor()->duplicate());
+ auto textEditor = Utils::UniqueObjectLatePtr<TextEditor::BaseTextEditor>(
+ QmlDesignerPlugin::instance()->currentDesignDocument()->textEditor()->duplicate());
// Set the context of the text editor, but we add another special context to override shortcuts.
Core::Context context = textEditor->context();
context.prepend(TEXTEDITOR_CONTEXT_ID);
m_textEditorContext->setContext(context);
- m_widget->setTextEditor(textEditor);
+ m_widget->setTextEditor(std::move(textEditor));
}
void TextEditorView::modelAboutToBeDetached(Model *model)
@@ -102,7 +103,7 @@ void TextEditorView::modelAboutToBeDetached(Model *model)
}
}
-void TextEditorView::importsChanged(const QList<Import> &/*addedImports*/, const QList<Import> &/*removedImports*/)
+void TextEditorView::importsChanged(const Imports &/*addedImports*/, const Imports &/*removedImports*/)
{
}
diff --git a/src/plugins/qmldesigner/components/texteditor/texteditorview.h b/src/plugins/qmldesigner/components/texteditor/texteditorview.h
index b1865e78f9f..e50372279d9 100644
--- a/src/plugins/qmldesigner/components/texteditor/texteditorview.h
+++ b/src/plugins/qmldesigner/components/texteditor/texteditorview.h
@@ -34,7 +34,7 @@ public:
void modelAttached(Model *model) override;
void modelAboutToBeDetached(Model *model) override;
- void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
+ void importsChanged(const Imports &addedImports, const Imports &removedImports) override;
void nodeAboutToBeRemoved(const ModelNode &removedNode) override;
void nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange) override;
diff --git a/src/plugins/qmldesigner/components/texteditor/texteditorwidget.cpp b/src/plugins/qmldesigner/components/texteditor/texteditorwidget.cpp
index 1529c0a87c1..9f4bb59231e 100644
--- a/src/plugins/qmldesigner/components/texteditor/texteditorwidget.cpp
+++ b/src/plugins/qmldesigner/components/texteditor/texteditorwidget.cpp
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "texteditorwidget.h"
+#include "utils/uniqueobjectptr.h"
#include <texteditorstatusbar.h>
#include <texteditorview.h>
@@ -51,34 +52,30 @@ TextEditorWidget::TextEditorWidget(TextEditorView *textEditorView)
QmlDesignerPlugin::trackWidgetFocusTime(this, Constants::EVENT_TEXTEDITOR_TIME);
}
-void TextEditorWidget::setTextEditor(TextEditor::BaseTextEditor *textEditor)
+void TextEditorWidget::setTextEditor(Utils::UniqueObjectLatePtr<TextEditor::BaseTextEditor> textEditor)
{
- TextEditor::BaseTextEditor *oldEditor = m_textEditor.release();
- m_textEditor.reset(textEditor);
+ std::swap(m_textEditor, textEditor);
- if (textEditor) {
- m_layout->insertWidget(0, textEditor->editorWidget());
+ if (m_textEditor) {
+ m_layout->insertWidget(0, m_textEditor->editorWidget());
- setFocusProxy(textEditor->editorWidget());
+ setFocusProxy(m_textEditor->editorWidget());
- QmlDesignerPlugin::instance()->emitCurrentTextEditorChanged(textEditor);
+ QmlDesignerPlugin::instance()->emitCurrentTextEditorChanged(m_textEditor.get());
- connect(textEditor->editorWidget(), &QPlainTextEdit::cursorPositionChanged, this, [this] {
+ connect(m_textEditor->editorWidget(), &QPlainTextEdit::cursorPositionChanged, this, [this] {
// Cursor position is changed by rewriter
if (!m_blockCursorSelectionSynchronisation)
m_updateSelectionTimer.start();
});
- textEditor->editorWidget()->installEventFilter(this);
+ m_textEditor->editorWidget()->installEventFilter(this);
static QString styleSheet = Theme::replaceCssColors(
QString::fromUtf8(Utils::FileReader::fetchQrc(":/qmldesigner/scrollbar.css")));
- textEditor->editorWidget()->verticalScrollBar()->setStyleSheet(styleSheet);
- textEditor->editorWidget()->horizontalScrollBar()->setStyleSheet(styleSheet);
+ m_textEditor->editorWidget()->verticalScrollBar()->setStyleSheet(styleSheet);
+ m_textEditor->editorWidget()->horizontalScrollBar()->setStyleSheet(styleSheet);
}
-
- if (oldEditor)
- oldEditor->deleteLater();
}
void TextEditorWidget::contextHelp(const Core::IContext::HelpCallback &callback) const
diff --git a/src/plugins/qmldesigner/components/texteditor/texteditorwidget.h b/src/plugins/qmldesigner/components/texteditor/texteditorwidget.h
index c5e5c4f5bc9..947826ab598 100644
--- a/src/plugins/qmldesigner/components/texteditor/texteditorwidget.h
+++ b/src/plugins/qmldesigner/components/texteditor/texteditorwidget.h
@@ -3,6 +3,7 @@
#pragma once
#include <texteditor/texteditor.h>
+#include <utils/uniqueobjectptr.h>
#include <QTimer>
#include <QVBoxLayout>
@@ -25,7 +26,7 @@ class TextEditorWidget : public QWidget {
public:
TextEditorWidget(TextEditorView *textEditorView);
- void setTextEditor(TextEditor::BaseTextEditor *textEditor);
+ void setTextEditor(Utils::UniqueObjectLatePtr<TextEditor::BaseTextEditor> textEditor);
TextEditor::BaseTextEditor *textEditor() const
{
@@ -51,7 +52,7 @@ protected:
private:
void updateSelectionByCursorPosition();
- std::unique_ptr<TextEditor::BaseTextEditor> m_textEditor;
+ Utils::UniqueObjectLatePtr<TextEditor::BaseTextEditor> m_textEditor;
QPointer<TextEditorView> m_textEditorView;
QTimer m_updateSelectionTimer;
TextEditorStatusBar *m_statusBar = nullptr;
diff --git a/src/plugins/qmldesigner/components/textureeditor/textureeditorview.cpp b/src/plugins/qmldesigner/components/textureeditor/textureeditorview.cpp
index 38664c146e4..a4132d0eb7a 100644
--- a/src/plugins/qmldesigner/components/textureeditor/textureeditorview.cpp
+++ b/src/plugins/qmldesigner/components/textureeditor/textureeditorview.cpp
@@ -720,8 +720,8 @@ void TextureEditorView::instancePropertyChanged(const QList<QPair<ModelNode, Pro
m_locked = false;
}
-void TextureEditorView::importsChanged([[maybe_unused]] const QList<Import> &addedImports,
- [[maybe_unused]] const QList<Import> &removedImports)
+void TextureEditorView::importsChanged([[maybe_unused]] const Imports &addedImports,
+ [[maybe_unused]] const Imports &removedImports)
{
m_hasQuick3DImport = model()->hasImport("QtQuick3D");
m_qmlBackEnd->contextObject()->setHasQuick3DImport(m_hasQuick3DImport);
diff --git a/src/plugins/qmldesigner/components/textureeditor/textureeditorview.h b/src/plugins/qmldesigner/components/textureeditor/textureeditorview.h
index b299a1e99ae..7baa07e9d30 100644
--- a/src/plugins/qmldesigner/components/textureeditor/textureeditorview.h
+++ b/src/plugins/qmldesigner/components/textureeditor/textureeditorview.h
@@ -58,7 +58,7 @@ public:
void currentStateChanged(const ModelNode &node) override;
void instancePropertyChanged(const QList<QPair<ModelNode, PropertyName> > &propertyList) override;
- void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
+ void importsChanged(const Imports &addedImports, const Imports &removedImports) override;
void customNotification(const AbstractView *view, const QString &identifier,
const QList<ModelNode> &nodeList, const QList<QVariant> &data) override;
diff --git a/src/plugins/qmldesigner/components/toolbar/toolbar.cpp b/src/plugins/qmldesigner/components/toolbar/toolbar.cpp
index 3326c889ad5..e4f523c55cc 100644
--- a/src/plugins/qmldesigner/components/toolbar/toolbar.cpp
+++ b/src/plugins/qmldesigner/components/toolbar/toolbar.cpp
@@ -47,10 +47,10 @@ Utils::FilePath qmlSourcesPath()
return Core::ICore::resourcePath("qmldesigner/toolbar");
}
-void ToolBar::create()
+Utils::UniqueObjectPtr<QToolBar> ToolBar::create()
{
if (!isVisible())
- return;
+ return nullptr;
ToolBarBackend::registerDeclarativeType();
@@ -58,7 +58,7 @@ void ToolBar::create()
//Core::ICore::statusBar()->hide();
- auto toolBar = new QToolBar;
+ auto toolBar = Utils::makeUniqueObjectPtr<QToolBar>();
toolBar->setObjectName("QDS-TOOLBAR");
toolBar->setContextMenuPolicy(Qt::PreventContextMenu);
@@ -66,7 +66,7 @@ void ToolBar::create()
toolBar->setFloatable(false);
toolBar->setMovable(false);
- auto quickWidget = new StudioQuickWidget;
+ auto quickWidget = std::make_unique<StudioQuickWidget>();
quickWidget->setFixedHeight(48);
quickWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
@@ -78,24 +78,26 @@ void ToolBar::create()
quickWidget->engine()->addImportPath(propertyEditorResourcesPath().toString() + "/imports");
Utils::FilePath qmlFilePath = qmlSourcesPath() / "Main.qml";
- QTC_ASSERT(qmlFilePath.exists(), return);
+ QTC_ASSERT(qmlFilePath.exists(), return nullptr);
Theme::setupTheme(quickWidget->engine());
quickWidget->setSource(QUrl::fromLocalFile(qmlFilePath.toFSPathString()));
- toolBar->addWidget(quickWidget);
- window->addToolBar(toolBar);
+ toolBar->addWidget(quickWidget.release());
+ window->addToolBar(toolBar.get());
+
+ return toolBar;
}
-void ToolBar::createStatusBar()
+Utils::UniqueObjectPtr<QWidget> ToolBar::createStatusBar()
{
if (!isVisible())
- return;
+ return nullptr;
ToolBarBackend::registerDeclarativeType();
- auto quickWidget = new StudioQuickWidget;
+ auto quickWidget = Utils::makeUniqueObjectPtr<StudioQuickWidget>();
quickWidget->setFixedHeight(Theme::toolbarSize());
quickWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
@@ -107,7 +109,7 @@ void ToolBar::createStatusBar()
quickWidget->engine()->addImportPath(propertyEditorResourcesPath().toString() + "/imports");
Utils::FilePath qmlFilePath = qmlSourcesStatusBarPath().pathAppended("/Main.qml");
- QTC_ASSERT(qmlFilePath.exists(), return);
+ QTC_ASSERT(qmlFilePath.exists(), return nullptr);
Theme::setupTheme(quickWidget->engine());
@@ -117,8 +119,10 @@ void ToolBar::createStatusBar()
w->hide();
}
- Core::ICore::statusBar()->addWidget(quickWidget);
+ Core::ICore::statusBar()->addPermanentWidget(quickWidget.get(), 100);
Core::ICore::statusBar()->setFixedHeight(Theme::toolbarSize());
+
+ return quickWidget;
}
bool ToolBar::isVisible()
diff --git a/src/plugins/qmldesigner/components/toolbar/toolbar.h b/src/plugins/qmldesigner/components/toolbar/toolbar.h
index 8537757cdf4..d086fdf3ed2 100644
--- a/src/plugins/qmldesigner/components/toolbar/toolbar.h
+++ b/src/plugins/qmldesigner/components/toolbar/toolbar.h
@@ -3,14 +3,18 @@
#pragma once
+#include <QToolBar>
+
+#include <utils/uniqueobjectptr.h>
+
namespace QmlDesigner {
class ToolBar
{
public:
- static void create();
- static void createStatusBar();
+ static Utils::UniqueObjectPtr<QToolBar> create();
+ static Utils::UniqueObjectPtr<QWidget> createStatusBar();
static bool isVisible();
};
diff --git a/src/plugins/qmldesigner/components/toolbar/toolbarbackend.cpp b/src/plugins/qmldesigner/components/toolbar/toolbarbackend.cpp
index ce7d783a4ed..1b9f1e3271f 100644
--- a/src/plugins/qmldesigner/components/toolbar/toolbarbackend.cpp
+++ b/src/plugins/qmldesigner/components/toolbar/toolbarbackend.cpp
@@ -79,10 +79,288 @@ static void openUiFile()
Core::EditorManager::openEditor(mainUiFile, Utils::Id());
}
+CrumbleBarModel::CrumbleBarModel(QObject *)
+{
+ connect(crumbleBar(), &CrumbleBar::pathChanged, this, &CrumbleBarModel::handleCrumblePathChanged);
+}
+
+int CrumbleBarModel::rowCount(const QModelIndex &) const
+{
+ return crumbleBar()->path().count();
+}
+
+QHash<int, QByteArray> CrumbleBarModel::roleNames() const
+{
+ static QHash<int, QByteArray> roleNames{{Qt::UserRole + 1, "fileName"},
+ {Qt::UserRole + 2, "fileAddress"}};
+
+ return roleNames;
+}
+
+QVariant CrumbleBarModel::data(const QModelIndex &index, int role) const
+{
+ if (index.isValid() && index.row() < rowCount()) {
+ auto info = crumbleBar()->infos().at(index.row());
+
+ if (role == Qt::UserRole + 1) {
+ return info.displayName;
+ } else if (role == Qt::UserRole + 2) {
+ return info.fileName.displayName();
+ } else {
+ qWarning() << Q_FUNC_INFO << "invalid role";
+ }
+ } else {
+ qWarning() << Q_FUNC_INFO << "invalid index";
+ }
+
+ return QVariant();
+}
+
+void CrumbleBarModel::handleCrumblePathChanged()
+{
+ beginResetModel();
+ endResetModel();
+}
+
+void CrumbleBarModel::onCrumblePathElementClicked(int i)
+{
+ if (i < rowCount()) {
+ auto info = crumbleBar()->infos().at(i);
+ crumbleBar()->onCrumblePathElementClicked(QVariant::fromValue(info));
+ }
+}
+
+WorkspaceModel::WorkspaceModel(QObject *)
+{
+ connect(designModeWidget(), &Internal::DesignModeWidget::initialized, this, [this]() {
+ const auto dockManager = designModeWidget()->dockManager();
+
+ connect(dockManager, &ADS::DockManager::workspaceListChanged, this, [this]() {
+ beginResetModel();
+ endResetModel();
+ });
+
+ beginResetModel();
+ endResetModel();
+ });
+}
+
+int WorkspaceModel::rowCount(const QModelIndex &) const
+{
+ if (designModeWidget() && designModeWidget()->dockManager())
+ return designModeWidget()->dockManager()->workspaces().count();
+
+ return 0;
+}
+
+QHash<int, QByteArray> WorkspaceModel::roleNames() const
+{
+ static QHash<int, QByteArray> roleNames{{DisplayNameRole, "displayName"},
+ {FileNameRole, "fileName"}};
+
+ return roleNames;
+}
+
+QVariant WorkspaceModel::data(const QModelIndex &index, int role) const
+{
+ if (index.isValid() && index.row() < rowCount()) {
+ auto workspace = designModeWidget()->dockManager()->workspaces().at(index.row());
+
+ if (role == DisplayNameRole) {
+ return workspace.name();
+ } else if (role == FileNameRole) {
+ return workspace.fileName();
+ } else {
+ qWarning() << Q_FUNC_INFO << "invalid role";
+ }
+ } else {
+ qWarning() << Q_FUNC_INFO << "invalid index";
+ }
+
+ return QVariant();
+}
+
+ActionSubscriber::ActionSubscriber(QObject *parent)
+ : QObject(parent)
+{
+ ActionAddedInterface callback = [this](ActionInterface *interface) {
+ if (interface->menuId() == m_actionId.toLatin1()) {
+ m_interface = interface;
+ setupNotifier();
+ }
+ };
+
+ QmlDesignerPlugin::instance()->viewManager().designerActionManager().addAddActionCallback(callback);
+}
+
+void ActionSubscriber::trigger()
+{
+ if (m_interface)
+ m_interface->action()->trigger();
+}
+
+bool ActionSubscriber::available() const
+{
+ if (m_interface)
+ return m_interface->action()->isEnabled();
+ return false;
+}
+
+bool ActionSubscriber::checked() const
+{
+ if (m_interface)
+ return m_interface->action()->isChecked();
+
+ return false;
+}
+
+QString ActionSubscriber::actionId() const
+{
+ return m_actionId;
+}
+
+void ActionSubscriber::setActionId(const QString &id)
+{
+ if (id == m_actionId)
+ return;
+
+ m_actionId = id;
+ emit actionIdChanged();
+ emit tooltipChanged();
+}
+
+QString ActionSubscriber::tooltip() const
+{
+ if (m_interface)
+ return m_interface->action()->text();
+ return {};
+}
+
+void ActionSubscriber::setupNotifier()
+{
+ if (!m_interface)
+ return;
+
+ connect(m_interface->action(), &QAction::enabledChanged, this, &ActionSubscriber::availableChanged);
+
+ emit tooltipChanged();
+}
+
+ToolBarBackend::ToolBarBackend(QObject *parent)
+ : QObject(parent)
+{
+ ActionAddedInterface callback = [this](ActionInterface *interface) {
+ if (interface->menuId() == "PreviewZoom")
+ m_zoomAction = interface;
+ };
+
+ QmlDesignerPlugin::instance()->viewManager().designerActionManager().addAddActionCallback(callback);
+
+ connect(designModeWidget(),
+ &Internal::DesignModeWidget::navigationHistoryChanged,
+ this,
+ &ToolBarBackend::navigationHistoryChanged);
+
+ connect(Core::DocumentModel::model(),
+ &QAbstractItemModel::rowsInserted,
+ this,
+ &ToolBarBackend::updateDocumentModel);
+ connect(Core::DocumentModel::model(),
+ &QAbstractItemModel::rowsRemoved,
+ this,
+ &ToolBarBackend::updateDocumentModel);
+ connect(Core::DocumentModel::model(),
+ &QAbstractItemModel::dataChanged,
+ this,
+ &ToolBarBackend::updateDocumentModel);
+ connect(Core::DocumentModel::model(),
+ &QAbstractItemModel::modelReset,
+ this,
+ &ToolBarBackend::updateDocumentModel);
+
+ connect(Core::EditorManager::instance(),
+ &Core::EditorManager::currentEditorChanged,
+ this,
+ &ToolBarBackend::documentIndexChanged);
+
+ connect(Core::EditorManager::instance(),
+ &Core::EditorManager::currentEditorChanged,
+ this,
+ &ToolBarBackend::currentStyleChanged);
+
+ connect(designModeWidget(), &Internal::DesignModeWidget::initialized, this, [this]() {
+ 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();
+ });
+
+ emit currentWorkspaceChanged();
+ });
+
+ auto editorManager = Core::EditorManager::instance();
+
+ connect(editorManager, &Core::EditorManager::documentClosed, this, [this]() {
+ if (isInDesignMode() && Core::DocumentModel::entryCount() == 0) {
+ QTimer::singleShot(0,
+ Core::ModeManager::instance(),
+ []() { /* The mode change has to happen from event loop.
+ Otherwise we and up in an invalid state */
+ Core::ModeManager::activateMode(Core::Constants::MODE_WELCOME);
+ });
+ }
+ });
+
+ connect(Core::ICore::instance(), &Core::ICore::coreAboutToOpen, this, [this] {
+ connect(Core::DesignMode::instance(), &Core::DesignMode::enabledStateChanged, this, [this] {
+ emit isDesignModeEnabledChanged();
+ });
+ });
+
+ connect(Core::ModeManager::instance(), &Core::ModeManager::currentModeChanged, this, [this]() {
+ emit isInDesignModeChanged();
+ emit isInEditModeChanged();
+ emit isDesignModeEnabledChanged();
+ });
+
+ connect(ProjectExplorer::ProjectManager::instance(),
+ &ProjectExplorer::ProjectManager::startupProjectChanged,
+ this,
+ [this](ProjectExplorer::Project *project) {
+ disconnect(m_kitConnection);
+ emit isQt6Changed();
+ emit projectOpenedChanged();
+ if (project) {
+ m_kitConnection = connect(project,
+ &ProjectExplorer::Project::activeTargetChanged,
+ this,
+ &ToolBarBackend::currentKitChanged);
+ emit currentKitChanged();
+ }
+ });
+
+ connect(ProjectExplorer::KitManager::instance(),
+ &ProjectExplorer::KitManager::kitsChanged,
+ this,
+ &ToolBarBackend::kitsChanged);
+}
+
+void ToolBarBackend::registerDeclarativeType()
+{
+ qmlRegisterType<ToolBarBackend>("ToolBar", 1, 0, "ToolBarBackend");
+ qmlRegisterType<ActionSubscriber>("ToolBar", 1, 0, "ActionSubscriber");
+ qmlRegisterType<CrumbleBarModel>("ToolBar", 1, 0, "CrumbleBarModel");
+ qmlRegisterType<WorkspaceModel>("ToolBar", 1, 0, "WorkspaceModel");
+}
+
void ToolBarBackend::triggerModeChange()
{
QmlDesignerPlugin::emitUsageStatistics(Constants::EVENT_TOOLBAR_MODE_CHANGE);
- QTimer::singleShot(0, [this]() { //Do not trigger mode change directly from QML
+ QTimer::singleShot(0, this, [this]() { //Do not trigger mode change directly from QML
bool qmlFileOpen = false;
if (!projectOpened()) {
@@ -109,7 +387,7 @@ void ToolBarBackend::triggerModeChange()
void ToolBarBackend::triggerProjectSettings()
{
QmlDesignerPlugin::emitUsageStatistics(Constants::EVENT_TOOLBAR_PROJECT_SETTINGS);
- QTimer::singleShot(0, []() { //Do not trigger mode change directly from QML
+ QTimer::singleShot(0, Core::ModeManager::instance(), []() { // Do not trigger mode change directly from QML
Core::ModeManager::activateMode(ProjectExplorer::Constants::MODE_SESSION);
});
}
@@ -230,7 +508,8 @@ void ToolBarBackend::setCurrentKit(int index)
if (!newTarget)
newTarget = project->addTargetForKit(kit);
- project->setActiveTarget(newTarget, ProjectExplorer::SetActive::Cascade);
+ project->setActiveTarget(newTarget,
+ ProjectExplorer::SetActive::Cascade);
emit currentKitChanged();
}
@@ -247,113 +526,6 @@ bool ToolBarBackend::canGoForward() const
return designModeWidget()->canGoForward();
}
-ToolBarBackend::ToolBarBackend(QObject *parent)
- : QObject(parent)
-{
- ActionAddedInterface callback = [this](ActionInterface *interface) {
- if (interface->menuId() == "PreviewZoom")
- m_zoomAction = interface;
- };
-
- QmlDesignerPlugin::instance()->viewManager().designerActionManager().addAddActionCallback(callback);
-
- connect(designModeWidget(),
- &Internal::DesignModeWidget::navigationHistoryChanged,
- this,
- &ToolBarBackend::navigationHistoryChanged);
-
- connect(Core::DocumentModel::model(),
- &QAbstractItemModel::rowsInserted,
- this,
- &ToolBarBackend::updateDocumentModel);
- connect(Core::DocumentModel::model(),
- &QAbstractItemModel::rowsRemoved,
- this,
- &ToolBarBackend::updateDocumentModel);
- connect(Core::DocumentModel::model(),
- &QAbstractItemModel::dataChanged,
- this,
- &ToolBarBackend::updateDocumentModel);
- connect(Core::DocumentModel::model(),
- &QAbstractItemModel::modelReset,
- this,
- &ToolBarBackend::updateDocumentModel);
-
- connect(Core::EditorManager::instance(),
- &Core::EditorManager::currentEditorChanged,
- this,
- &ToolBarBackend::documentIndexChanged);
-
- connect(Core::EditorManager::instance(),
- &Core::EditorManager::currentEditorChanged,
- this,
- &ToolBarBackend::currentStyleChanged);
-
- connect(designModeWidget(), &Internal::DesignModeWidget::initialized, this, [this]() {
- const auto dockManager = designModeWidget()->dockManager();
-
- connect(dockManager,
- &ADS::DockManager::workspaceListChanged,
- this,
- &ToolBarBackend::setupWorkspaces);
- connect(dockManager, &ADS::DockManager::workspaceLoaded, this, [this](const QString &) {
- emit currentWorkspaceChanged();
- });
-
- setupWorkspaces();
- });
-
- auto editorManager = Core::EditorManager::instance();
-
- connect(editorManager, &Core::EditorManager::documentClosed, this, [this]() {
- if (isInDesignMode() && Core::DocumentModel::entryCount() == 0) {
- QTimer::singleShot(0, []() { /* The mode change has to happen from event loop.
- Otherwise we and up in an invalid state */
- Core::ModeManager::activateMode(Core::Constants::MODE_WELCOME);
- });
- }
- });
-
- connect(Core::ICore::instance(), &Core::ICore::coreAboutToOpen, this, [this] {
- connect(Core::DesignMode::instance(), &Core::DesignMode::enabledStateChanged, this, [this] {
- emit isDesignModeEnabledChanged();
- });
- });
-
- connect(Core::ModeManager::instance(), &Core::ModeManager::currentModeChanged, this, [this]() {
- emit isInDesignModeChanged();
- emit isInEditModeChanged();
- emit isDesignModeEnabledChanged();
- });
-
- connect(ProjectExplorer::ProjectManager::instance(),
- &ProjectExplorer::ProjectManager::startupProjectChanged,
- [this](ProjectExplorer::Project *project) {
- disconnect(m_kitConnection);
- emit isQt6Changed();
- emit projectOpenedChanged();
- if (project) {
- m_kitConnection = connect(project,
- &ProjectExplorer::Project::activeTargetChanged,
- this,
- &ToolBarBackend::currentKitChanged);
- emit currentKitChanged();
- }
- });
-
- connect(ProjectExplorer::KitManager::instance(),
- &ProjectExplorer::KitManager::kitsChanged,
- this,
- &ToolBarBackend::kitsChanged);
-}
-
-void ToolBarBackend::registerDeclarativeType()
-{
- qmlRegisterType<ToolBarBackend>("ToolBar", 1, 0, "ToolBarBackend");
- qmlRegisterType<ActionSubscriber>("ToolBar", 1, 0, "ActionSubscriber");
- qmlRegisterType<CrumbleBarModel>("ToolBar", 1, 0, "CrumbleBarModel");
-}
-
QStringList ToolBarBackend::documentModel() const
{
return m_openDocuments;
@@ -382,13 +554,9 @@ int ToolBarBackend::documentIndex() const
QString ToolBarBackend::currentWorkspace() const
{
if (designModeWidget() && designModeWidget()->dockManager())
- return designModeWidget()->dockManager()->activeWorkspace();
- return {};
-}
+ return designModeWidget()->dockManager()->activeWorkspace()->fileName();
-QStringList ToolBarBackend::workspaces() const
-{
- return m_workspaces;
+ return {};
}
QStringList ToolBarBackend::styles() const
@@ -417,17 +585,6 @@ bool ToolBarBackend::isInEditMode() const
return Core::ModeManager::currentModeId() == Core::Constants::MODE_EDIT;
}
-void ToolBarBackend::launchGlobalAnnotations()
-{
- QmlDesignerPlugin::emitUsageStatistics(Constants::EVENT_TOOLBAR_EDIT_GLOBAL_ANNOTATION);
- ModelNode node = currentDesignDocument()->rewriterView()->rootModelNode();
-
- if (node.isValid()) {
- designModeWidget()->globalAnnotationEditor().setModelNode(node);
- designModeWidget()->globalAnnotationEditor().showWidget();
- }
-}
-
bool ToolBarBackend::isDesignModeEnabled() const
{
if (Core::DesignMode::instance())
@@ -445,9 +602,7 @@ int ToolBarBackend::currentStyle() const
const QString qmlFile = view->model()->fileUrl().toLocalFile();
- const int index = ChangeStyleWidgetAction::getCurrentStyle(qmlFile);
-
- return index;
+ return ChangeStyleWidgetAction::getCurrentStyle(qmlFile);
}
QStringList ToolBarBackend::kits() const
@@ -485,129 +640,16 @@ bool ToolBarBackend::projectOpened() const
return ProjectExplorer::ProjectManager::instance()->startupProject();
}
-void ToolBarBackend::setupWorkspaces()
-{
- m_workspaces.clear();
- m_workspaces = designModeWidget()->dockManager()->workspaces();
- Utils::sort(m_workspaces);
- emit workspacesChanged();
- emit currentWorkspaceChanged();
-}
-
-ActionSubscriber::ActionSubscriber(QObject *parent)
- : QObject(parent)
-{
- ActionAddedInterface callback = [this](ActionInterface *interface) {
- if (interface->menuId() == m_actionId.toLatin1()) {
- m_interface = interface;
- setupNotifier();
- }
- };
-
- QmlDesignerPlugin::instance()->viewManager().designerActionManager().addAddActionCallback(callback);
-}
-
-void ActionSubscriber::trigger()
-{
- if (m_interface)
- m_interface->action()->trigger();
-}
-
-bool ActionSubscriber::available() const
-{
- if (m_interface)
- return m_interface->action()->isEnabled();
- return false;
-}
-
-bool ActionSubscriber::checked() const
-{
- if (m_interface)
- return m_interface->action()->isChecked();
-
- return false;
-}
-
-QString ActionSubscriber::actionId() const
-{
- return m_actionId;
-}
-
-void ActionSubscriber::setActionId(const QString &id)
-{
- if (id == m_actionId)
- return;
-
- m_actionId = id;
- emit actionIdChanged();
- emit tooltipChanged();
-}
-
-QString ActionSubscriber::tooltip() const
-{
- if (m_interface)
- return m_interface->action()->text();
- return {};
-}
-
-void ActionSubscriber::setupNotifier()
-{
- if (!m_interface)
- return;
-
- connect(m_interface->action(), &QAction::enabledChanged, this, &ActionSubscriber::availableChanged);
-
- emit tooltipChanged();
-}
-
-CrumbleBarModel::CrumbleBarModel(QObject *)
-{
- connect(crumbleBar(), &CrumbleBar::pathChanged, this, &CrumbleBarModel::handleCrumblePathChanged);
-}
-
-int CrumbleBarModel::rowCount(const QModelIndex &) const
-{
- return crumbleBar()->path().count();
-}
-
-QHash<int, QByteArray> CrumbleBarModel::roleNames() const
-{
- static QHash<int, QByteArray> roleNames{{Qt::UserRole + 1, "fileName"},
- {Qt::UserRole + 2, "fileAddress"}};
-
- return roleNames;
-}
-
-QVariant CrumbleBarModel::data(const QModelIndex &index, int role) const
+void ToolBarBackend::launchGlobalAnnotations()
{
- if (index.isValid() && index.row() < rowCount()) {
- auto info = crumbleBar()->infos().at(index.row());
-
- if (role == Qt::UserRole + 1) {
- return info.displayName;
- } else if (role == Qt::UserRole + 2) {
- return info.fileName.displayName();
- } else {
- qWarning() << Q_FUNC_INFO << "invalid role";
- }
- } else {
- qWarning() << Q_FUNC_INFO << "invalid index";
- }
-
- return QVariant();
-}
+ QmlDesignerPlugin::emitUsageStatistics(Constants::EVENT_TOOLBAR_EDIT_GLOBAL_ANNOTATION);
-void CrumbleBarModel::handleCrumblePathChanged()
-{
- beginResetModel();
- endResetModel();
-}
+ QTC_ASSERT(currentDesignDocument(), return);
+ ModelNode node = currentDesignDocument()->rewriterView()->rootModelNode();
-void CrumbleBarModel::onCrumblePathElementClicked(int i)
-{
- if (i < rowCount()) {
- auto info = crumbleBar()->infos().at(i);
- crumbleBar()->onCrumblePathElementClicked(QVariant::fromValue(info));
+ if (node.isValid()) {
+ designModeWidget()->globalAnnotationEditor().setModelNode(node);
+ designModeWidget()->globalAnnotationEditor().showWidget();
}
}
diff --git a/src/plugins/qmldesigner/components/toolbar/toolbarbackend.h b/src/plugins/qmldesigner/components/toolbar/toolbarbackend.h
index 1aed5aeeaf4..0091ab8a7f1 100644
--- a/src/plugins/qmldesigner/components/toolbar/toolbarbackend.h
+++ b/src/plugins/qmldesigner/components/toolbar/toolbarbackend.h
@@ -18,15 +18,25 @@ public:
explicit CrumbleBarModel(QObject *parent = nullptr);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
-
QHash<int, QByteArray> roleNames() const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
void handleCrumblePathChanged();
Q_INVOKABLE void onCrumblePathElementClicked(int i);
+};
-private:
+class WorkspaceModel : public QAbstractListModel
+{
+ Q_OBJECT
+ enum { DisplayNameRole = Qt::DisplayRole, FileNameRole = Qt::UserRole };
+
+public:
+ explicit WorkspaceModel(QObject *parent = nullptr);
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+ QHash<int, QByteArray> roleNames() const override;
+ QVariant data(const QModelIndex &index, int role = DisplayNameRole) const override;
};
class ActionSubscriber : public QObject
@@ -73,7 +83,6 @@ class ToolBarBackend : public QObject
Q_PROPERTY(QStringList documentModel READ documentModel NOTIFY openDocumentsChanged)
Q_PROPERTY(int documentIndex READ documentIndex NOTIFY documentIndexChanged)
Q_PROPERTY(QString currentWorkspace READ currentWorkspace NOTIFY currentWorkspaceChanged)
- Q_PROPERTY(QStringList workspaces READ workspaces NOTIFY workspacesChanged)
Q_PROPERTY(QStringList styles READ styles CONSTANT)
Q_PROPERTY(bool isInDesignMode READ isInDesignMode NOTIFY isInDesignModeChanged)
Q_PROPERTY(bool isInEditMode READ isInEditMode NOTIFY isInEditModeChanged)
@@ -111,11 +120,11 @@ public:
int documentIndex() const;
QString currentWorkspace() const;
- QStringList workspaces() const;
QStringList styles() const;
bool isInDesignMode() const;
+ bool isInEditMode() const;
bool isDesignModeEnabled() const;
int currentStyle() const;
@@ -127,8 +136,6 @@ public:
bool projectOpened() const;
- bool isInEditMode() const;
-
static void launchGlobalAnnotations();
signals:
@@ -136,7 +143,6 @@ signals:
void openDocumentsChanged();
void documentIndexChanged();
void currentWorkspaceChanged();
- void workspacesChanged();
void isInDesignModeChanged();
void isInEditModeChanged();
void isDesignModeEnabledChanged();
@@ -152,7 +158,6 @@ private:
ActionInterface *m_zoomAction;
QStringList m_openDocuments;
- QStringList m_workspaces;
QMetaObject::Connection m_kitConnection;
};
diff --git a/src/plugins/qmldesigner/designercore/imagecache/asynchronousexplicitimagecache.cpp b/src/plugins/qmldesigner/designercore/imagecache/asynchronousexplicitimagecache.cpp
index ed168b8a09b..1c46722d4c4 100644
--- a/src/plugins/qmldesigner/designercore/imagecache/asynchronousexplicitimagecache.cpp
+++ b/src/plugins/qmldesigner/designercore/imagecache/asynchronousexplicitimagecache.cpp
@@ -78,42 +78,30 @@ void AsynchronousExplicitImageCache::wait()
m_backgroundThread.join();
}
-void AsynchronousExplicitImageCache::requestImage(Utils::PathString name,
+void AsynchronousExplicitImageCache::requestImage(Utils::SmallStringView name,
ImageCache::CaptureImageCallback captureCallback,
ImageCache::AbortCallback abortCallback,
- Utils::SmallString extraId)
+ Utils::SmallStringView extraId)
{
- addEntry(std::move(name),
- std::move(extraId),
- std::move(captureCallback),
- std::move(abortCallback),
- RequestType::Image);
+ addEntry(name, extraId, std::move(captureCallback), std::move(abortCallback), RequestType::Image);
m_condition.notify_all();
}
-void AsynchronousExplicitImageCache::requestMidSizeImage(Utils::PathString name,
+void AsynchronousExplicitImageCache::requestMidSizeImage(Utils::SmallStringView name,
ImageCache::CaptureImageCallback captureCallback,
ImageCache::AbortCallback abortCallback,
- Utils::SmallString extraId)
+ Utils::SmallStringView extraId)
{
- addEntry(std::move(name),
- std::move(extraId),
- std::move(captureCallback),
- std::move(abortCallback),
- RequestType::MidSizeImage);
+ addEntry(name, extraId, std::move(captureCallback), std::move(abortCallback), RequestType::MidSizeImage);
m_condition.notify_all();
}
-void AsynchronousExplicitImageCache::requestSmallImage(Utils::PathString name,
+void AsynchronousExplicitImageCache::requestSmallImage(Utils::SmallStringView name,
ImageCache::CaptureImageCallback captureCallback,
ImageCache::AbortCallback abortCallback,
- Utils::SmallString extraId)
+ Utils::SmallStringView extraId)
{
- addEntry(std::move(name),
- std::move(extraId),
- std::move(captureCallback),
- std::move(abortCallback),
- RequestType::SmallImage);
+ addEntry(name, extraId, std::move(captureCallback), std::move(abortCallback), RequestType::SmallImage);
m_condition.notify_all();
}
diff --git a/src/plugins/qmldesigner/designercore/imagecache/asynchronousimagecache.cpp b/src/plugins/qmldesigner/designercore/imagecache/asynchronousimagecache.cpp
index dec46f87252..00b3ab722ef 100644
--- a/src/plugins/qmldesigner/designercore/imagecache/asynchronousimagecache.cpp
+++ b/src/plugins/qmldesigner/designercore/imagecache/asynchronousimagecache.cpp
@@ -118,10 +118,10 @@ void AsynchronousImageCache::wait()
m_backgroundThread.join();
}
-void AsynchronousImageCache::requestImage(Utils::PathString name,
+void AsynchronousImageCache::requestImage(Utils::SmallStringView name,
ImageCache::CaptureImageCallback captureCallback,
ImageCache::AbortCallback abortCallback,
- Utils::SmallString extraId,
+ Utils::SmallStringView extraId,
ImageCache::AuxiliaryData auxiliaryData)
{
addEntry(std::move(name),
@@ -133,10 +133,10 @@ void AsynchronousImageCache::requestImage(Utils::PathString name,
m_condition.notify_all();
}
-void AsynchronousImageCache::requestMidSizeImage(Utils::PathString name,
+void AsynchronousImageCache::requestMidSizeImage(Utils::SmallStringView name,
ImageCache::CaptureImageCallback captureCallback,
ImageCache::AbortCallback abortCallback,
- Utils::SmallString extraId,
+ Utils::SmallStringView extraId,
ImageCache::AuxiliaryData auxiliaryData)
{
addEntry(std::move(name),
@@ -148,10 +148,10 @@ void AsynchronousImageCache::requestMidSizeImage(Utils::PathString name,
m_condition.notify_all();
}
-void AsynchronousImageCache::requestSmallImage(Utils::PathString name,
+void AsynchronousImageCache::requestSmallImage(Utils::SmallStringView name,
ImageCache::CaptureImageCallback captureCallback,
ImageCache::AbortCallback abortCallback,
- Utils::SmallString extraId,
+ Utils::SmallStringView extraId,
ImageCache::AuxiliaryData auxiliaryData)
{
addEntry(std::move(name),
diff --git a/src/plugins/qmldesigner/designercore/imagecache/asynchronousimagefactory.cpp b/src/plugins/qmldesigner/designercore/imagecache/asynchronousimagefactory.cpp
index 500359182ae..5d6ced30601 100644
--- a/src/plugins/qmldesigner/designercore/imagecache/asynchronousimagefactory.cpp
+++ b/src/plugins/qmldesigner/designercore/imagecache/asynchronousimagefactory.cpp
@@ -39,16 +39,16 @@ AsynchronousImageFactory::~AsynchronousImageFactory()
wait();
}
-void AsynchronousImageFactory::generate(Utils::PathString name,
- Utils::SmallString extraId,
+void AsynchronousImageFactory::generate(Utils::SmallStringView name,
+ Utils::SmallStringView extraId,
ImageCache::AuxiliaryData auxiliaryData)
{
- addEntry(std::move(name), std::move(extraId), std::move(auxiliaryData));
+ addEntry(name, extraId, std::move(auxiliaryData));
m_condition.notify_all();
}
-void AsynchronousImageFactory::addEntry(Utils::PathString &&name,
- Utils::SmallString &&extraId,
+void AsynchronousImageFactory::addEntry(Utils::SmallStringView name,
+ Utils::SmallStringView extraId,
ImageCache::AuxiliaryData &&auxiliaryData)
{
std::unique_lock lock{m_mutex};
diff --git a/src/plugins/qmldesigner/designercore/imagecache/asynchronousimagefactory.h b/src/plugins/qmldesigner/designercore/imagecache/asynchronousimagefactory.h
index 4aa24d0a769..415646c73cd 100644
--- a/src/plugins/qmldesigner/designercore/imagecache/asynchronousimagefactory.h
+++ b/src/plugins/qmldesigner/designercore/imagecache/asynchronousimagefactory.h
@@ -28,8 +28,8 @@ public:
~AsynchronousImageFactory();
- void generate(Utils::PathString name,
- Utils::SmallString extraId = {},
+ void generate(Utils::SmallStringView name,
+ Utils::SmallStringView extraId = {},
ImageCache::AuxiliaryData auxiliaryData = {});
void clean();
@@ -50,8 +50,8 @@ private:
ImageCache::AuxiliaryData auxiliaryData;
};
- void addEntry(Utils::PathString &&name,
- Utils::SmallString &&extraId,
+ void addEntry(Utils::SmallStringView name,
+ Utils::SmallStringView extraId,
ImageCache::AuxiliaryData &&auxiliaryData);
bool isRunning();
void waitForEntries();
diff --git a/src/plugins/qmldesigner/designercore/imagecache/explicitimagecacheimageprovider.cpp b/src/plugins/qmldesigner/designercore/imagecache/explicitimagecacheimageprovider.cpp
index 1f28d4eca69..509abb5c70f 100644
--- a/src/plugins/qmldesigner/designercore/imagecache/explicitimagecacheimageprovider.cpp
+++ b/src/plugins/qmldesigner/designercore/imagecache/explicitimagecacheimageprovider.cpp
@@ -17,7 +17,7 @@ QQuickImageResponse *ExplicitImageCacheImageProvider::requestImageResponse(const
auto response = std::make_unique<ImageCacheImageResponse>(m_defaultImage);
m_cache.requestImage(
- id,
+ Utils::PathString{id},
[response = QPointer<ImageCacheImageResponse>(response.get())](const QImage &image) {
QMetaObject::invokeMethod(
response,
diff --git a/src/plugins/qmldesigner/designercore/imagecache/imagecachestorage.h b/src/plugins/qmldesigner/designercore/imagecache/imagecachestorage.h
index 6b0df6f1c1e..37131012d69 100644
--- a/src/plugins/qmldesigner/designercore/imagecache/imagecachestorage.h
+++ b/src/plugins/qmldesigner/designercore/imagecache/imagecachestorage.h
@@ -35,12 +35,8 @@ public:
ImageEntry fetchImage(Utils::SmallStringView name, Sqlite::TimeStamp minimumTimeStamp) const override
{
try {
- Sqlite::DeferredTransaction transaction{database};
-
- auto optionalBlob = selectImageStatement.template optionalValue<Sqlite::ByteArrayBlob>(
- name, minimumTimeStamp.value);
-
- transaction.commit();
+ auto optionalBlob = selectImageStatement.template optionalValueWithTransaction<
+ Sqlite::ByteArrayBlob>(name, minimumTimeStamp.value);
if (optionalBlob)
return {readImage(optionalBlob->byteArray)};
@@ -55,12 +51,8 @@ public:
Sqlite::TimeStamp minimumTimeStamp) const override
{
try {
- Sqlite::DeferredTransaction transaction{database};
-
- auto optionalBlob = selectMidSizeImageStatement.template optionalValue<Sqlite::ByteArrayBlob>(
- name, minimumTimeStamp.value);
-
- transaction.commit();
+ auto optionalBlob = selectMidSizeImageStatement.template optionalValueWithTransaction<
+ Sqlite::ByteArrayBlob>(name, minimumTimeStamp.value);
if (optionalBlob)
return {readImage(optionalBlob->byteArray)};
@@ -75,12 +67,8 @@ public:
Sqlite::TimeStamp minimumTimeStamp) const override
{
try {
- Sqlite::DeferredTransaction transaction{database};
-
- auto optionalBlob = selectSmallImageStatement.template optionalValue<Sqlite::ByteArrayBlob>(
- name, minimumTimeStamp.value);
-
- transaction.commit();
+ auto optionalBlob = selectSmallImageStatement.template optionalValueWithTransaction<
+ Sqlite::ByteArrayBlob>(name, minimumTimeStamp.value);
if (optionalBlob)
return ImageEntry{readImage(optionalBlob->byteArray)};
@@ -95,12 +83,8 @@ public:
IconEntry fetchIcon(Utils::SmallStringView name, Sqlite::TimeStamp minimumTimeStamp) const override
{
try {
- Sqlite::DeferredTransaction transaction{database};
-
- auto optionalBlob = selectIconStatement.template optionalValue<Sqlite::ByteArrayBlob>(
- name, minimumTimeStamp.value);
-
- transaction.commit();
+ auto optionalBlob = selectIconStatement.template optionalValueWithTransaction<
+ Sqlite::ByteArrayBlob>(name, minimumTimeStamp.value);
if (optionalBlob)
return {readIcon(optionalBlob->byteArray)};
@@ -119,19 +103,16 @@ public:
const QImage &smallImage) override
{
try {
- Sqlite::ImmediateTransaction transaction{database};
-
auto imageBuffer = createBuffer(image);
auto midSizeImageBuffer = createBuffer(midSizeImage);
auto smallImageBuffer = createBuffer(smallImage);
- upsertImageStatement.write(name,
- newTimeStamp.value,
- createBlobView(imageBuffer.get()),
- createBlobView(midSizeImageBuffer.get()),
- createBlobView(smallImageBuffer.get()));
-
- transaction.commit();
-
+ Sqlite::withImmediateTransaction(database, [&] {
+ upsertImageStatement.write(name,
+ newTimeStamp.value,
+ createBlobView(imageBuffer.get()),
+ createBlobView(midSizeImageBuffer.get()),
+ createBlobView(smallImageBuffer.get()));
+ });
} catch (const Sqlite::StatementIsBusy &) {
return storeImage(name, newTimeStamp, image, midSizeImage, smallImage);
}
@@ -140,12 +121,10 @@ public:
void storeIcon(Utils::SmallStringView name, Sqlite::TimeStamp newTimeStamp, const QIcon &icon) override
{
try {
- Sqlite::ImmediateTransaction transaction{database};
-
auto iconBuffer = createBuffer(icon);
- upsertIconStatement.write(name, newTimeStamp.value, createBlobView(iconBuffer.get()));
-
- transaction.commit();
+ Sqlite::withImmediateTransaction(database, [&] {
+ upsertIconStatement.write(name, newTimeStamp.value, createBlobView(iconBuffer.get()));
+ });
} catch (const Sqlite::StatementIsBusy &) {
return storeIcon(name, newTimeStamp, icon);
diff --git a/src/plugins/qmldesigner/designercore/imagecache/midsizeimagecacheprovider.cpp b/src/plugins/qmldesigner/designercore/imagecache/midsizeimagecacheprovider.cpp
index fd37f02f044..9b62ffe1bfa 100644
--- a/src/plugins/qmldesigner/designercore/imagecache/midsizeimagecacheprovider.cpp
+++ b/src/plugins/qmldesigner/designercore/imagecache/midsizeimagecacheprovider.cpp
@@ -15,7 +15,7 @@ QQuickImageResponse *MidSizeImageCacheProvider::requestImageResponse(const QStri
auto response = std::make_unique<ImageCacheImageResponse>(m_defaultImage);
m_cache.requestMidSizeImage(
- id,
+ Utils::PathString{id},
[response = QPointer<ImageCacheImageResponse>(response.get())](const QImage &image) {
QMetaObject::invokeMethod(
response,
diff --git a/src/plugins/qmldesigner/designercore/imagecache/smallimagecacheprovider.cpp b/src/plugins/qmldesigner/designercore/imagecache/smallimagecacheprovider.cpp
index 3fae3bb1754..722498dd98a 100644
--- a/src/plugins/qmldesigner/designercore/imagecache/smallimagecacheprovider.cpp
+++ b/src/plugins/qmldesigner/designercore/imagecache/smallimagecacheprovider.cpp
@@ -16,7 +16,7 @@ QQuickImageResponse *SmallImageCacheProvider::requestImageResponse(const QString
auto response = std::make_unique<ImageCacheImageResponse>(m_defaultImage);
m_cache.requestSmallImage(
- id,
+ Utils::PathString{id},
[response = QPointer<ImageCacheImageResponse>(response.get())](const QImage &image) {
QMetaObject::invokeMethod(
response,
diff --git a/src/plugins/qmldesigner/designercore/include/abstractproperty.h b/src/plugins/qmldesigner/designercore/include/abstractproperty.h
index 7b5c6ccf68d..c22402202d8 100644
--- a/src/plugins/qmldesigner/designercore/include/abstractproperty.h
+++ b/src/plugins/qmldesigner/designercore/include/abstractproperty.h
@@ -50,6 +50,10 @@ class QMLDESIGNERCORE_EXPORT AbstractProperty
public:
AbstractProperty() = default;
+ AbstractProperty(const AbstractProperty &) = default;
+ AbstractProperty &operator=(const AbstractProperty &) = default;
+ AbstractProperty(AbstractProperty &&) = default;
+ AbstractProperty &operator=(AbstractProperty &&) noexcept = default;
~AbstractProperty();
AbstractProperty(const AbstractProperty &property, AbstractView *view);
diff --git a/src/plugins/qmldesigner/designercore/include/abstractview.h b/src/plugins/qmldesigner/designercore/include/abstractview.h
index 2d886d959be..0c3df94030c 100644
--- a/src/plugins/qmldesigner/designercore/include/abstractview.h
+++ b/src/plugins/qmldesigner/designercore/include/abstractview.h
@@ -195,9 +195,9 @@ public:
const ModelNode &movedNode,
int oldIndex);
- virtual void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports);
- virtual void possibleImportsChanged(const QList<Import> &possibleImports);
- virtual void usedImportsChanged(const QList<Import> &usedImports);
+ virtual void importsChanged(const Imports &addedImports, const Imports &removedImports);
+ virtual void possibleImportsChanged(const Imports &possibleImports);
+ virtual void usedImportsChanged(const Imports &usedImports);
virtual void auxiliaryDataChanged(const ModelNode &node,
AuxiliaryDataKeyView type,
diff --git a/src/plugins/qmldesigner/designercore/include/asynchronousexplicitimagecache.h b/src/plugins/qmldesigner/designercore/include/asynchronousexplicitimagecache.h
index 7cddfd29d9f..f9a053a9413 100644
--- a/src/plugins/qmldesigner/designercore/include/asynchronousexplicitimagecache.h
+++ b/src/plugins/qmldesigner/designercore/include/asynchronousexplicitimagecache.h
@@ -23,18 +23,18 @@ public:
AsynchronousExplicitImageCache(ImageCacheStorageInterface &storage);
- void requestImage(Utils::PathString name,
+ void requestImage(Utils::SmallStringView name,
ImageCache::CaptureImageCallback captureCallback,
ImageCache::AbortCallback abortCallback,
- Utils::SmallString extraId = {});
- void requestMidSizeImage(Utils::PathString name,
+ Utils::SmallStringView extraId = {});
+ void requestMidSizeImage(Utils::SmallStringView name,
ImageCache::CaptureImageCallback captureCallback,
ImageCache::AbortCallback abortCallback,
- Utils::SmallString extraId = {});
- void requestSmallImage(Utils::PathString name,
+ Utils::SmallStringView extraId = {});
+ void requestSmallImage(Utils::SmallStringView name,
ImageCache::CaptureImageCallback captureCallback,
ImageCache::AbortCallback abortCallback,
- Utils::SmallString extraId = {});
+ Utils::SmallStringView extraId = {});
void clean();
diff --git a/src/plugins/qmldesigner/designercore/include/asynchronousimagecache.h b/src/plugins/qmldesigner/designercore/include/asynchronousimagecache.h
index 04882d61eb7..3257f9d75c1 100644
--- a/src/plugins/qmldesigner/designercore/include/asynchronousimagecache.h
+++ b/src/plugins/qmldesigner/designercore/include/asynchronousimagecache.h
@@ -28,20 +28,20 @@ public:
ImageCacheGeneratorInterface &generator,
TimeStampProviderInterface &timeStampProvider);
- void requestImage(Utils::PathString name,
+ void requestImage(Utils::SmallStringView name,
ImageCache::CaptureImageCallback captureCallback,
ImageCache::AbortCallback abortCallback,
- Utils::SmallString extraId = {},
+ Utils::SmallStringView extraId = {},
ImageCache::AuxiliaryData auxiliaryData = {}) override;
- void requestMidSizeImage(Utils::PathString name,
+ void requestMidSizeImage(Utils::SmallStringView name,
ImageCache::CaptureImageCallback captureCallback,
ImageCache::AbortCallback abortCallback,
- Utils::SmallString extraId = {},
+ Utils::SmallStringView extraId = {},
ImageCache::AuxiliaryData auxiliaryData = {}) override;
- void requestSmallImage(Utils::PathString name,
+ void requestSmallImage(Utils::SmallStringView name,
ImageCache::CaptureImageCallback captureCallback,
ImageCache::AbortCallback abortCallback,
- Utils::SmallString extraId = {},
+ Utils::SmallStringView extraId = {},
ImageCache::AuxiliaryData auxiliaryData = {}) override;
void clean();
diff --git a/src/plugins/qmldesigner/designercore/include/asynchronousimagecacheinterface.h b/src/plugins/qmldesigner/designercore/include/asynchronousimagecacheinterface.h
index da8bda079e2..43c8e5b6726 100644
--- a/src/plugins/qmldesigner/designercore/include/asynchronousimagecacheinterface.h
+++ b/src/plugins/qmldesigner/designercore/include/asynchronousimagecacheinterface.h
@@ -14,22 +14,22 @@ namespace QmlDesigner {
class AsynchronousImageCacheInterface
{
public:
- virtual void requestImage(Utils::PathString name,
+ virtual void requestImage(Utils::SmallStringView name,
ImageCache::CaptureImageCallback captureCallback,
ImageCache::AbortCallback abortCallback,
- Utils::SmallString extraId = {},
+ Utils::SmallStringView extraId = {},
ImageCache::AuxiliaryData auxiliaryData = {})
= 0;
- virtual void requestMidSizeImage(Utils::PathString name,
+ virtual void requestMidSizeImage(Utils::SmallStringView name,
ImageCache::CaptureImageCallback captureCallback,
ImageCache::AbortCallback abortCallback,
- Utils::SmallString extraId = {},
+ Utils::SmallStringView extraId = {},
ImageCache::AuxiliaryData auxiliaryData = {})
= 0;
- virtual void requestSmallImage(Utils::PathString name,
+ virtual void requestSmallImage(Utils::SmallStringView name,
ImageCache::CaptureImageCallback captureCallback,
ImageCache::AbortCallback abortCallback,
- Utils::SmallString extraId = {},
+ Utils::SmallStringView extraId = {},
ImageCache::AuxiliaryData auxiliaryData = {})
= 0;
diff --git a/src/plugins/qmldesigner/designercore/include/auxiliarydataproperties.h b/src/plugins/qmldesigner/designercore/include/auxiliarydataproperties.h
index 1a1884ce645..4c12af14fef 100644
--- a/src/plugins/qmldesigner/designercore/include/auxiliarydataproperties.h
+++ b/src/plugins/qmldesigner/designercore/include/auxiliarydataproperties.h
@@ -106,6 +106,8 @@ inline constexpr AuxiliaryDataKeyView globalAnnotationStatus{AuxiliaryDataType::
inline constexpr AuxiliaryDataKeyView rotBlockProperty{AuxiliaryDataType::NodeInstanceAuxiliary,
"rotBlock"};
inline constexpr AuxiliaryDataKeyView languageProperty{AuxiliaryDataType::Temporary, "language"};
+inline constexpr AuxiliaryDataKeyView bakeLightsManualProperty{AuxiliaryDataType::Document,
+ "bakeLightsManual"};
// 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/externaldependenciesinterface.h b/src/plugins/qmldesigner/designercore/include/externaldependenciesinterface.h
index 7b2b8a2c55f..d4a087f4c7b 100644
--- a/src/plugins/qmldesigner/designercore/include/externaldependenciesinterface.h
+++ b/src/plugins/qmldesigner/designercore/include/externaldependenciesinterface.h
@@ -6,6 +6,9 @@
#include <instances/puppetstartdata.h>
#include <utils/filepath.h>
+#include <QColor>
+#include <QUrl>
+
namespace QmlDesigner {
class DesignerSettings;
@@ -40,6 +43,11 @@ public:
virtual PuppetStartData puppetStartData(const class Model &model) const = 0;
virtual bool instantQmlTextUpdate() const = 0;
virtual Utils::FilePath qmlPuppetPath() const = 0;
+ virtual QStringList modulePaths() const = 0;
+ virtual QStringList projectModulePaths() const = 0;
+ virtual bool isQt6Project() const = 0;
+ virtual QString qtQuickVersion() const = 0;
+ virtual Utils::FilePath resourcePath(const QString &relativePath) const = 0;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/include/forwardview.h b/src/plugins/qmldesigner/designercore/include/forwardview.h
index 7041e851096..386ac83141c 100644
--- a/src/plugins/qmldesigner/designercore/include/forwardview.h
+++ b/src/plugins/qmldesigner/designercore/include/forwardview.h
@@ -44,7 +44,7 @@ public:
void fileUrlChanged(const QUrl &oldUrl, const QUrl &newUrl) override;
void nodeOrderChanged(const NodeListProperty &listProperty) override;
- void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
+ void importsChanged(const Imports &addedImports, const Imports &removedImports) override;
void auxiliaryDataChanged(const ModelNode &node, const PropertyName &name, const QVariant &data) override;
@@ -197,7 +197,7 @@ void ForwardView<ViewType>::nodeOrderChanged(const NodeListProperty &listPropert
}
template <class ViewType>
-void ForwardView<ViewType>::importChanged(const QList<Import> &addedImports, const QList<Import> &removedImports)
+void ForwardView<ViewType>::importChanged(const Imports &addedImports, const Imports &removedImports)
{
for (const ViewTypePointer &view : std::as_const(m_targetViewList))
view->importChanged(addedImport, removedImport);
diff --git a/src/plugins/qmldesigner/designercore/include/import.h b/src/plugins/qmldesigner/designercore/include/import.h
index b221b861732..f0a5b8e7700 100644
--- a/src/plugins/qmldesigner/designercore/include/import.h
+++ b/src/plugins/qmldesigner/designercore/include/import.h
@@ -3,18 +3,49 @@
#pragma once
+#include <utils/set_algorithm.h>
+
#include <QString>
#include <QStringList>
#include <QMetaType>
#include "qmldesignercorelib_global.h"
+#include <limits>
+
namespace QmlDesigner {
+class Version
+{
+public:
+ friend bool operator==(Version first, Version second)
+ {
+ return first.major == second.major && first.minor == second.minor;
+ }
+
+ friend bool operator<(Version first, Version second)
+ {
+ return std::tie(first.major, first.minor) < std::tie(second.major, second.minor);
+ }
+
+ friend bool operator>(Version first, Version second) { return second < first; }
+ friend bool operator<=(Version first, Version second) { return !(second < first); }
+ friend bool operator>=(Version first, Version second) { return !(first < second); }
+
+ bool isEmpty() const
+ {
+ return major == std::numeric_limits<int>::max() || minor == std::numeric_limits<int>::max();
+ }
+
+public:
+ int major = std::numeric_limits<int>::max();
+ int minor = std::numeric_limits<int>::max();
+};
+
class QMLDESIGNERCORE_EXPORT Import
{
public:
- Import();
+ Import() = default;
static Import createLibraryImport(const QString &url, const QString &version = QString(), const QString &alias = QString(), const QStringList &importPaths = QStringList());
static Import createFileImport(const QString &file, const QString &version = QString(), const QString &alias = QString(), const QStringList &importPaths = QStringList());
@@ -26,23 +57,35 @@ public:
bool hasVersion() const { return !m_version.isEmpty(); }
bool hasAlias() const { return !m_alias.isEmpty(); }
- QString url() const { return m_url; }
- QString file() const { return m_file; }
- QString version() const { return m_version; }
- QString alias() const { return m_alias; }
- QStringList importPaths() const { return m_importPathList; }
+ const QString &url() const { return m_url; }
+ const QString &file() const { return m_file; }
+ const QString &version() const { return m_version; }
+ const QString &alias() const { return m_alias; }
+ const QStringList &importPaths() const { return m_importPathList; }
QString toString(bool skipAlias = false, bool skipVersion = false) const;
QString toImportString() const;
- bool operator==(const Import &other) const;
bool isSameModule(const Import &other) const;
int majorVersion() const;
int minorVersion() const;
+ Version toVersion() const;
static int majorFromVersion(const QString &version);
static int minorFromVersion(const QString &version);
+ friend bool operator==(const Import &first, const Import &second)
+ {
+ return first.m_url == second.m_url && first.m_file == second.m_file
+ && (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);
+ }
+
private:
Import(const QString &url, const QString &file, const QString &version, const QString &alias, const QStringList &importPaths);
@@ -56,6 +99,23 @@ private:
QMLDESIGNERCORE_EXPORT size_t qHash(const Import &import);
+using Imports = QList<Import>;
+
+QMLDESIGNERCORE_EXPORT Imports difference(const Imports &first, const Imports &second);
+
+template<typename Callable>
+void differenceCall(const Imports &first, const Imports &second, Callable callable)
+{
+ Imports difference;
+ difference.reserve(first.size());
+
+ std::set_difference(first.begin(),
+ first.end(),
+ second.begin(),
+ second.end(),
+ ::Utils::make_iterator(callable));
+}
+
} // namespace QmlDesigner
Q_DECLARE_METATYPE(QmlDesigner::Import)
diff --git a/src/plugins/qmldesigner/designercore/include/itemlibraryinfo.h b/src/plugins/qmldesigner/designercore/include/itemlibraryinfo.h
index 0571e64a8ce..034af72410f 100644
--- a/src/plugins/qmldesigner/designercore/include/itemlibraryinfo.h
+++ b/src/plugins/qmldesigner/designercore/include/itemlibraryinfo.h
@@ -6,9 +6,10 @@
#include "qmldesignercorelib_global.h"
#include "propertycontainer.h"
+#include <memory>
+#include <QIcon>
#include <QPointer>
#include <QSet>
-#include <memory>
namespace QmlDesigner {
diff --git a/src/plugins/qmldesigner/designercore/include/metainfo.h b/src/plugins/qmldesigner/designercore/include/metainfo.h
index b5ec3c0aa95..914be96db7b 100644
--- a/src/plugins/qmldesigner/designercore/include/metainfo.h
+++ b/src/plugins/qmldesigner/designercore/include/metainfo.h
@@ -16,6 +16,7 @@ namespace QmlDesigner {
class ModelNode;
class AbstractProperty;
class ItemLibraryInfo;
+class ExternalDependenciesInterface;
namespace Internal {
class MetaInfoPrivate;
@@ -44,15 +45,14 @@ public:
ItemLibraryInfo *itemLibraryInfo() const;
public:
- static MetaInfo global();
- static void clearGlobal();
-
- static void setPluginPaths(const QStringList &paths);
+ static void initializeGlobal(const QStringList &pluginPaths,
+ const ExternalDependenciesInterface &externalDependencies);
static void disableParseItemLibraryDescriptionsUgly(); // ugly hack around broken tests
private:
bool isGlobal() const;
+ static MetaInfo global();
private:
MetaInfo();
diff --git a/src/plugins/qmldesigner/designercore/include/model.h b/src/plugins/qmldesigner/designercore/include/model.h
index 9e6c7ca36ad..c2cd807a8a2 100644
--- a/src/plugins/qmldesigner/designercore/include/model.h
+++ b/src/plugins/qmldesigner/designercore/include/model.h
@@ -6,6 +6,7 @@
#include <qmldesignercorelib_global.h>
#include <documentmessage.h>
+#include <model/modelresourcemanagementinterface.h>
#include <projectstorage/projectstoragefwd.h>
#include <QMimeData>
@@ -40,7 +41,7 @@ class RewriterView;
class NodeInstanceView;
class TextModifier;
-using PropertyListType = QList<QPair<PropertyName, QVariant> >;
+using PropertyListType = QList<QPair<PropertyName, QVariant>>;
class QMLDESIGNERCORE_EXPORT Model : public QObject
{
@@ -57,21 +58,38 @@ class QMLDESIGNERCORE_EXPORT Model : public QObject
public:
enum ViewNotification { NotifyView, DoNotNotifyView };
- Model(ProjectStorage<Sqlite::Database> &projectStorage,
+ Model(ProjectStorageType &projectStorage,
const TypeName &type,
int major = 1,
int minor = 1,
- Model *metaInfoProxyModel = nullptr);
- Model(const TypeName &typeName, int major = 1, int minor = 1, Model *metaInfoProxyModel = nullptr);
+ Model *metaInfoProxyModel = nullptr,
+ std::unique_ptr<ModelResourceManagementInterface> resourceManagement = {});
+ Model(const TypeName &typeName,
+ int major = 1,
+ int minor = 1,
+ Model *metaInfoProxyModel = nullptr,
+ std::unique_ptr<ModelResourceManagementInterface> resourceManagement = {});
~Model();
static ModelPointer create(const TypeName &typeName,
int major = 1,
int minor = 1,
- Model *metaInfoProxyModel = nullptr)
+ Model *metaInfoProxyModel = nullptr,
+ std::unique_ptr<ModelResourceManagementInterface> resourceManagement = {})
+ {
+ return ModelPointer(
+ new Model(typeName, major, minor, metaInfoProxyModel, std::move(resourceManagement)));
+ }
+
+ static ModelPointer create(ProjectStorageType &projectStorage,
+ const TypeName &typeName,
+ int major = 1,
+ int minor = 1,
+ std::unique_ptr<ModelResourceManagementInterface> resourceManagement = {})
{
- return ModelPointer(new Model(typeName, major, minor, metaInfoProxyModel));
+ return ModelPointer(
+ new Model(projectStorage, typeName, major, minor, nullptr, std::move(resourceManagement)));
}
QUrl fileUrl() const;
@@ -87,6 +105,7 @@ public:
NodeMetaInfo flowViewFlowTransitionMetaInfo() const;
NodeMetaInfo flowViewFlowWildcardMetaInfo() const;
NodeMetaInfo fontMetaInfo() const;
+ NodeMetaInfo qtQuick3DBakedLightmapMetaInfo() const;
NodeMetaInfo qtQuick3DDefaultMaterialMetaInfo() const;
NodeMetaInfo qtQuick3DMaterialMetaInfo() const;
NodeMetaInfo qtQuick3DModelMetaInfo() const;
@@ -111,15 +130,17 @@ public:
void attachView(AbstractView *view);
void detachView(AbstractView *view, ViewNotification emitDetachNotify = NotifyView);
+ QList<ModelNode> allModelNodes() const;
+
// Editing sub-components:
// Imports:
- const QList<Import> &imports() const;
- const QList<Import> &possibleImports() const;
- const QList<Import> &usedImports() const;
- void changeImports(const QList<Import> &importsToBeAdded, const QList<Import> &importsToBeRemoved);
- void setPossibleImports(const QList<Import> &possibleImports);
- void setUsedImports(const QList<Import> &usedImports);
+ const Imports &imports() const;
+ const Imports &possibleImports() const;
+ const Imports &usedImports() const;
+ void changeImports(const Imports &importsToBeAdded, const Imports &importsToBeRemoved);
+ void setPossibleImports(Imports possibleImports);
+ void setUsedImports(Imports usedImports);
bool hasImport(const Import &import, bool ignoreAlias = true, bool allowHigherVersion = false) const;
bool isImportPossible(const Import &import, bool ignoreAlias = true, bool allowHigherVersion = false) const;
QString pathForImport(const Import &import);
@@ -157,7 +178,7 @@ public:
void startDrag(QMimeData *mimeData, const QPixmap &icon);
void endDrag();
- NotNullPointer<const ProjectStorage<Sqlite::Database>> projectStorage() const;
+ NotNullPointer<const ProjectStorageType> projectStorage() const;
private:
template<const auto &moduleName, const auto &typeName>
@@ -168,4 +189,4 @@ private:
std::unique_ptr<Internal::ModelPrivate> d;
};
-}
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/include/modelfwd.h b/src/plugins/qmldesigner/designercore/include/modelfwd.h
new file mode 100644
index 00000000000..66712499958
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/include/modelfwd.h
@@ -0,0 +1,42 @@
+// 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 "../projectstorage/projectstoragefwd.h"
+#include "qmldesignercorelib_exports.h"
+
+#include <utils/smallstringview.h>
+
+namespace QmlDesigner {
+using PropertyName = QByteArray;
+using PropertyNameList = QList<PropertyName>;
+using TypeName = QByteArray;
+using PropertyTypeList = QList<PropertyName>;
+using IdName = QByteArray;
+class Model;
+class ModelNode;
+
+struct ModelDeleter
+{
+ QMLDESIGNERCORE_EXPORT void operator()(class Model *model);
+};
+
+using ModelPointer = std::unique_ptr<class Model, ModelDeleter>;
+
+constexpr bool useProjectStorage()
+{
+#ifdef QDS_USE_PROJECTSTORAGE
+ return true;
+#else
+ return false;
+#endif
+}
+
+#ifdef QDS_MODEL_USE_PROJECTSTORAGEINTERFACE
+using ProjectStorageType = ProjectStorageInterface;
+#else
+using ProjectStorageType = ProjectStorage<Sqlite::Database>;
+#endif
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/include/modelnode.h b/src/plugins/qmldesigner/designercore/include/modelnode.h
index a48713ee864..e9891da620c 100644
--- a/src/plugins/qmldesigner/designercore/include/modelnode.h
+++ b/src/plugins/qmldesigner/designercore/include/modelnode.h
@@ -80,6 +80,10 @@ public:
ModelNode();
ModelNode(const Internal::InternalNodePointer &internalNode, Model *model, const AbstractView *view);
ModelNode(const ModelNode &modelNode, AbstractView *view);
+ ModelNode(const ModelNode &) = default;
+ ModelNode &operator=(const ModelNode &) = default;
+ ModelNode(ModelNode &&) = default;
+ ModelNode &operator=(ModelNode &&) noexcept = default;
~ModelNode();
TypeName type() const;
@@ -266,6 +270,8 @@ QMLDESIGNERCORE_EXPORT bool operator !=(const ModelNode &firstNode, const ModelN
QMLDESIGNERCORE_EXPORT bool operator <(const ModelNode &firstNode, const ModelNode &secondNode);
QMLDESIGNERCORE_EXPORT QDebug operator<<(QDebug debug, const ModelNode &modelNode);
QMLDESIGNERCORE_EXPORT QTextStream& operator<<(QTextStream &stream, const ModelNode &modelNode);
+
+using ModelNodes = QList<ModelNode>;
}
Q_DECLARE_METATYPE(QmlDesigner::ModelNode)
diff --git a/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h b/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h
index 632dbfce077..93b4e82a2a2 100644
--- a/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h
+++ b/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h
@@ -85,7 +85,7 @@ public:
void fileUrlChanged(const QUrl &oldUrl, const QUrl &newUrl) override;
void nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId) override;
void nodeOrderChanged(const NodeListProperty &listProperty) override;
- void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
+ void importsChanged(const Imports &addedImports, const Imports &removedImports) override;
void auxiliaryDataChanged(const ModelNode &node,
AuxiliaryDataKeyView key,
const QVariant &data) override;
@@ -122,6 +122,7 @@ public:
QImage statePreviewImage(const ModelNode &stateNode) const;
void setTarget(ProjectExplorer::Target *newTarget);
+ ProjectExplorer::Target *target() const;
void sendToken(const QString &token, int number, const QVector<ModelNode> &nodeVector);
diff --git a/src/plugins/qmldesigner/designercore/include/nodemetainfo.h b/src/plugins/qmldesigner/designercore/include/nodemetainfo.h
index 69ac5f2a977..d7bc414e77e 100644
--- a/src/plugins/qmldesigner/designercore/include/nodemetainfo.h
+++ b/src/plugins/qmldesigner/designercore/include/nodemetainfo.h
@@ -6,7 +6,7 @@
#include "propertymetainfo.h"
#include "qmldesignercorelib_global.h"
-#include <projectstorage/projectstoragefwd.h>
+#include <projectstorage/projectstorageinterface.h>
#include <projectstorage/projectstoragetypes.h>
#include <projectstorageids.h>
@@ -32,11 +32,11 @@ class QMLDESIGNERCORE_EXPORT NodeMetaInfo
public:
NodeMetaInfo() = default;
NodeMetaInfo(Model *model, const TypeName &typeName, int majorVersion, int minorVersion);
- NodeMetaInfo(TypeId typeId, NotNullPointer<const ProjectStorage<Sqlite::Database>> projectStorage)
+ NodeMetaInfo(TypeId typeId, NotNullPointer<const ProjectStorageType> projectStorage)
: m_typeId{typeId}
, m_projectStorage{projectStorage}
{}
- NodeMetaInfo(NotNullPointer<const ProjectStorage<Sqlite::Database>> projectStorage)
+ NodeMetaInfo(NotNullPointer<const ProjectStorageType> projectStorage)
: m_projectStorage{projectStorage}
{}
~NodeMetaInfo();
@@ -44,7 +44,7 @@ public:
bool isValid() const;
explicit operator bool() const { return isValid(); }
bool isFileComponent() const;
- bool hasProperty(Utils::SmallStringView propertyName) const;
+ bool hasProperty(::Utils::SmallStringView propertyName) const;
PropertyMetaInfos properties() const;
PropertyMetaInfos localProperties() const;
PropertyMetaInfo property(const PropertyName &propertyName) const;
@@ -67,8 +67,6 @@ public:
QString componentFileName() const;
- bool availableInVersion(int majorVersion, int minorVersion) const;
-
bool isBasedOn(const NodeMetaInfo &metaInfo) const;
bool isBasedOn(const NodeMetaInfo &metaInfo1, const NodeMetaInfo &metaInfo2) const;
bool isBasedOn(const NodeMetaInfo &metaInfo1,
@@ -126,9 +124,11 @@ public:
bool isQtQuick3DEffect() const;
bool isQtQuick3DInstanceList() const;
bool isQtQuick3DInstanceListEntry() const;
+ bool isQtQuick3DLight() const;
bool isQtQuick3DMaterial() const;
bool isQtQuick3DModel() const;
bool isQtQuick3DNode() const;
+ bool isQtQuick3DParticleAbstractShape() const;
bool isQtQuick3DParticles3DAffector3D() const;
bool isQtQuick3DParticles3DAttractor3D() const;
bool isQtQuick3DParticles3DParticle3D() const;
@@ -171,8 +171,6 @@ public:
bool isQtQuickWindowWindow() const;
bool isQtSafeRendererSafePicture() const;
bool isQtSafeRendererSafeRendererPicture() const;
- bool isQuick3DParticleAbstractShape() const;
- bool isQuickStateOperation() const;
bool isString() const;
bool isSuitableForMouseAreaFill() const;
bool isUrl() const;
@@ -199,7 +197,7 @@ private:
private:
TypeId m_typeId;
- NotNullPointer<const ProjectStorage<Sqlite::Database>> m_projectStorage = {};
+ NotNullPointer<const ProjectStorageType> m_projectStorage = {};
mutable std::optional<Storage::Info::Type> m_typeData;
QSharedPointer<class NodeMetaInfoPrivate> m_privateData;
};
diff --git a/src/plugins/qmldesigner/designercore/include/plaintexteditmodifier.h b/src/plugins/qmldesigner/designercore/include/plaintexteditmodifier.h
index 814137d8a77..4172e8921ee 100644
--- a/src/plugins/qmldesigner/designercore/include/plaintexteditmodifier.h
+++ b/src/plugins/qmldesigner/designercore/include/plaintexteditmodifier.h
@@ -91,8 +91,17 @@ public:
TextEditor::TabSettings tabSettings() const override
{ return m_tabSettings; }
-private:
+protected:
TextEditor::TabSettings m_tabSettings;
};
+class QMLDESIGNERCORE_EXPORT IndentingTextEditModifier : public NotIndentingTextEditModifier
+{
+public:
+ IndentingTextEditModifier(QTextDocument *document, const QTextCursor &textCursor);
+
+ void indent(int offset, int length) override;
+ void indentLines(int startLine, int endLine) override;
+};
+
}
diff --git a/src/plugins/qmldesigner/designercore/include/propertymetainfo.h b/src/plugins/qmldesigner/designercore/include/propertymetainfo.h
index 6cda405f615..a3c928bc36f 100644
--- a/src/plugins/qmldesigner/designercore/include/propertymetainfo.h
+++ b/src/plugins/qmldesigner/designercore/include/propertymetainfo.h
@@ -25,10 +25,12 @@ public:
PropertyMetaInfo() = default;
PropertyMetaInfo(QSharedPointer<class NodeMetaInfoPrivate> nodeMetaInfoPrivateData,
const PropertyName &propertyName);
- PropertyMetaInfo(PropertyDeclarationId id,
- NotNullPointer<const ProjectStorage<Sqlite::Database>> projectStorage)
- : m_id{id}
- , m_projectStorage{projectStorage}
+ PropertyMetaInfo([[maybe_unused]] PropertyDeclarationId id,
+ [[maybe_unused]] NotNullPointer<const ProjectStorageType> projectStorage)
+#ifdef QDS_USE_PROJECTSTORAGE
+ : m_projectStorage{projectStorage}
+ , m_id{id}
+#endif
{}
~PropertyMetaInfo();
@@ -36,11 +38,11 @@ public:
bool isValid() const
{
- if (useProjectStorage()) {
- return bool(m_id);
- } else {
- return bool(m_nodeMetaInfoPrivateData);
- }
+#ifdef QDS_USE_PROJECTSTORAGE
+ return bool(m_id);
+#else
+ return bool(m_nodeMetaInfoPrivateData);
+#endif
}
PropertyName name() const;
NodeMetaInfo propertyType() const;
@@ -53,20 +55,28 @@ public:
friend bool operator==(const PropertyMetaInfo &first, const PropertyMetaInfo &second)
{
+#ifdef QDS_USE_PROJECTSTORAGE
+ return first.m_id == second.m_id;
+#else
return first.m_nodeMetaInfoPrivateData == second.m_nodeMetaInfoPrivateData
&& first.name() == second.name();
+#endif
}
private:
const Storage::Info::PropertyDeclaration &propertyData() const;
TypeName propertyTypeName() const;
+ const NodeMetaInfoPrivate *nodeMetaInfoPrivateData() const;
+ const PropertyName &propertyName() const;
private:
+ NotNullPointer<const ProjectStorageType> m_projectStorage;
+ mutable std::optional<Storage::Info::PropertyDeclaration> m_propertyData;
+ PropertyDeclarationId m_id;
+#ifndef QDS_USE_PROJECTSTORAGE
QSharedPointer<class NodeMetaInfoPrivate> m_nodeMetaInfoPrivateData;
PropertyName m_propertyName;
- PropertyDeclarationId m_id;
- NotNullPointer<const ProjectStorage<Sqlite::Database>> m_projectStorage;
- mutable std::optional<Storage::Info::PropertyDeclaration> m_propertyData;
+#endif
};
using PropertyMetaInfos = std::vector<PropertyMetaInfo>;
diff --git a/src/plugins/qmldesigner/designercore/include/qmldesignercorelib_exports.h b/src/plugins/qmldesigner/designercore/include/qmldesignercorelib_exports.h
new file mode 100644
index 00000000000..f5e1dbf4788
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/include/qmldesignercorelib_exports.h
@@ -0,0 +1,12 @@
+// 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
+
+#if defined(QMLDESIGNERCORE_LIBRARY)
+#define QMLDESIGNERCORE_EXPORT Q_DECL_EXPORT
+#elif defined(QMLDESIGNERCORE_STATIC_LIBRARY)
+#define QMLDESIGNERCORE_EXPORT
+#else
+#define QMLDESIGNERCORE_EXPORT Q_DECL_IMPORT
+#endif
diff --git a/src/plugins/qmldesigner/designercore/include/qmldesignercorelib_global.h b/src/plugins/qmldesigner/designercore/include/qmldesignercorelib_global.h
index 05a1c2e20f6..7871b5df3a6 100644
--- a/src/plugins/qmldesigner/designercore/include/qmldesignercorelib_global.h
+++ b/src/plugins/qmldesigner/designercore/include/qmldesignercorelib_global.h
@@ -3,29 +3,16 @@
#pragma once
+#include "modelfwd.h"
+#include "qmldesignercorelib_exports.h"
+
#include <QtGlobal>
#include <QList>
-#include <utils/smallstringview.h>
-
#include <nodeinstanceglobal.h>
-
-// Unnecessary since core isn't a dll any more.
-
-#if defined(QMLDESIGNERCORE_LIBRARY)
-#define QMLDESIGNERCORE_EXPORT Q_DECL_EXPORT
-#elif defined(QMLDESIGNERCORE_STATIC_LIBRARY)
-#define QMLDESIGNERCORE_EXPORT
-#else
-#define QMLDESIGNERCORE_EXPORT Q_DECL_IMPORT
-#endif
+#include <projectstorage/projectstoragefwd.h>
namespace QmlDesigner {
-using PropertyName = QByteArray;
-using PropertyNameList = QList<PropertyName>;
-using TypeName = QByteArray;
-using PropertyTypeList = QList<PropertyName>;
-using IdName = QByteArray;
enum AnchorLineType {
AnchorLineInvalid = 0x0,
@@ -38,26 +25,12 @@ enum AnchorLineType {
AnchorLineVerticalCenter = 0x20,
AnchorLineBaseline = 0x40,
- AnchorLineFill = AnchorLineLeft | AnchorLineRight | AnchorLineTop | AnchorLineBottom,
+ AnchorLineFill = AnchorLineLeft | AnchorLineRight | AnchorLineTop | AnchorLineBottom,
AnchorLineCenter = AnchorLineVerticalCenter | AnchorLineHorizontalCenter,
AnchorLineHorizontalMask = AnchorLineLeft | AnchorLineRight | AnchorLineHorizontalCenter,
- AnchorLineVerticalMask = AnchorLineTop | AnchorLineBottom | AnchorLineVerticalCenter | AnchorLineBaseline,
+ AnchorLineVerticalMask = AnchorLineTop | AnchorLineBottom | AnchorLineVerticalCenter
+ | AnchorLineBaseline,
AnchorLineAllMask = AnchorLineVerticalMask | AnchorLineHorizontalMask
};
-struct ModelDeleter
-{
- QMLDESIGNERCORE_EXPORT void operator()(class Model *model);
-};
-
-using ModelPointer = std::unique_ptr<class Model, ModelDeleter>;
-
-constexpr bool useProjectStorage()
-{
-#ifdef QDS_USE_PROJECTSTORAGE
- return true;
-#else
- return false;
-#endif
-}
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/include/qmlmodelnodefacade.h b/src/plugins/qmldesigner/designercore/include/qmlmodelnodefacade.h
index 9c63fd040a2..27c4c86cc0b 100644
--- a/src/plugins/qmldesigner/designercore/include/qmlmodelnodefacade.h
+++ b/src/plugins/qmldesigner/designercore/include/qmlmodelnodefacade.h
@@ -14,13 +14,17 @@ class NodeInstanceView;
class QMLDESIGNERCORE_EXPORT QmlModelNodeFacade
{
public:
+ QmlModelNodeFacade(const QmlModelNodeFacade &) = default;
+ QmlModelNodeFacade &operator=(const QmlModelNodeFacade &) = default;
+ QmlModelNodeFacade(QmlModelNodeFacade &&) noexcept = default;
+ QmlModelNodeFacade &operator=(QmlModelNodeFacade &&) noexcept = default;
+ virtual ~QmlModelNodeFacade() = default;
operator ModelNode() const { return m_modelNode; }
ModelNode modelNode() const { return m_modelNode; }
bool hasModelNode() const;
static bool isValidQmlModelNodeFacade(const ModelNode &modelNode);
virtual bool isValid() const;
explicit operator bool() const { return isValid(); }
- virtual ~QmlModelNodeFacade();
QmlModelNodeFacade() = default;
AbstractView *view() const;
diff --git a/src/plugins/qmldesigner/designercore/include/rewriterview.h b/src/plugins/qmldesigner/designercore/include/rewriterview.h
index 9387fdb345e..95e2e51d8a1 100644
--- a/src/plugins/qmldesigner/designercore/include/rewriterview.h
+++ b/src/plugins/qmldesigner/designercore/include/rewriterview.h
@@ -84,7 +84,7 @@ public:
void rewriterBeginTransaction() override;
void rewriterEndTransaction() override;
- void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
+ void importsChanged(const Imports &addedImports, const Imports &removedImports) override;
TextModifier *textModifier() const;
void setTextModifier(TextModifier *textModifier);
diff --git a/src/plugins/qmldesigner/designercore/include/subcomponentmanager.h b/src/plugins/qmldesigner/designercore/include/subcomponentmanager.h
index 207f1b7104b..dbc89c1cccd 100644
--- a/src/plugins/qmldesigner/designercore/include/subcomponentmanager.h
+++ b/src/plugins/qmldesigner/designercore/include/subcomponentmanager.h
@@ -27,7 +27,7 @@ public:
explicit SubComponentManager(Model *model,
class ExternalDependenciesInterface &externalDependencies);
- void update(const QUrl &fileUrl, const QList<Import> &imports);
+ void update(const QUrl &fileUrl, const Imports &imports);
void addAndParseImport(const Import &import);
QStringList qmlFiles() const;
@@ -53,7 +53,7 @@ private: // functions
private: // variables
QFileSystemWatcher m_watcher;
- QList<Import> m_imports;
+ Imports m_imports;
// key: canonical directory path
QMultiHash<QString,QString> m_dirToQualifier;
QUrl m_filePath;
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
index 8ebfaf52044..3befd6ec52c 100644
--- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
@@ -625,7 +625,7 @@ void NodeInstanceView::nodeOrderChanged(const NodeListProperty &listProperty)
m_nodeInstanceServer->reparentInstances(ReparentInstancesCommand(containerList));
}
-void NodeInstanceView::importsChanged(const QList<Import> &/*addedImports*/, const QList<Import> &/*removedImports*/)
+void NodeInstanceView::importsChanged(const Imports &/*addedImports*/, const Imports &/*removedImports*/)
{
restartProcess();
}
@@ -1572,6 +1572,11 @@ void NodeInstanceView::setTarget(ProjectExplorer::Target *newTarget)
}
}
+ProjectExplorer::Target *NodeInstanceView::target() const
+{
+ return m_currentTarget;
+}
+
void NodeInstanceView::statePreviewImagesChanged(const StatePreviewImageChangedCommand &command)
{
if (!model())
diff --git a/src/plugins/qmldesigner/designercore/metainfo/itemlibraryinfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/itemlibraryinfo.cpp
index b1473d6a4c0..cbde96e9926 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/itemlibraryinfo.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/itemlibraryinfo.cpp
@@ -1,11 +1,12 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-#include "itemlibraryinfo.h"
+#include "../include/itemlibraryinfo.h"
#include "nodemetainfo.h"
#include "qregularexpression.h"
#include <invalidmetainfoexception.h>
+#include <propertycontainer.h>
#include <QSharedData>
diff --git a/src/plugins/qmldesigner/designercore/metainfo/metainfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/metainfo.cpp
index 354ccd63c3f..144df144483 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/metainfo.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/metainfo.cpp
@@ -7,6 +7,7 @@
#include "metainforeader.h"
#include "iwidgetplugin.h"
+#include <externaldependenciesinterface.h>
#include <invalidmetainfoexception.h>
#include <coreplugin/messagebox.h>
@@ -30,24 +31,26 @@ enum {
namespace QmlDesigner {
namespace Internal {
-
-static QString globalMetaInfoPath()
+static QString globalMetaInfoPath(const ExternalDependenciesInterface &externalDependecies)
{
#ifdef SHARE_QML_PATH
if (Utils::qtcEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
return QLatin1String(SHARE_QML_PATH) + "/globalMetaInfo";
#endif
- return Core::ICore::resourcePath("qmldesigner/globalMetaInfo").toString();
+ return externalDependecies.resourcePath("qmldesigner/globalMetaInfo").toString();
}
-Utils::FilePaths allGlobalMetaInfoFiles()
+Utils::FilePaths allGlobalMetaInfoFiles(const ExternalDependenciesInterface &externalDependecies)
{
static Utils::FilePaths paths;
if (!paths.isEmpty())
return paths;
- QDirIterator it(globalMetaInfoPath(), { "*.metainfo" }, QDir::Files, QDirIterator::Subdirectories);
+ QDirIterator it(globalMetaInfoPath(externalDependecies),
+ {"*.metainfo"},
+ QDir::Files,
+ QDirIterator::Subdirectories);
while (it.hasNext())
paths.append(Utils::FilePath::fromString(it.next()));
@@ -61,9 +64,9 @@ public:
MetaInfoPrivate(MetaInfo *q);
void clear();
- void initialize();
+ void initialize(const ExternalDependenciesInterface &externalDependencies);
- void parseItemLibraryDescriptions();
+ void parseItemLibraryDescriptions(const ExternalDependenciesInterface &externalDependencies);
QScopedPointer<ItemLibraryInfo> m_itemLibraryInfo;
@@ -90,14 +93,14 @@ namespace {
bool enableParseItemLibraryDescriptions = true;
}
-void MetaInfoPrivate::initialize()
+void MetaInfoPrivate::initialize(const ExternalDependenciesInterface &externalDependencies)
{
if (enableParseItemLibraryDescriptions)
- parseItemLibraryDescriptions();
+ parseItemLibraryDescriptions(externalDependencies);
m_isInitialized = true;
}
-void MetaInfoPrivate::parseItemLibraryDescriptions()
+void MetaInfoPrivate::parseItemLibraryDescriptions(const ExternalDependenciesInterface &externalDependencies)
{
Internal::WidgetPluginManager pluginManager;
for (const QString &pluginDir : std::as_const(m_q->s_pluginDirs))
@@ -107,7 +110,8 @@ void MetaInfoPrivate::parseItemLibraryDescriptions()
Internal::MetaInfoReader reader(*m_q);
try {
reader.readMetaInfoFile(plugin->metaInfo());
- } catch (const InvalidMetaInfoException &e) {
+ } catch ([[maybe_unused]] const InvalidMetaInfoException &e) {
+#ifndef UNIT_TESTS
qWarning() << e.description();
const QString errorMessage = plugin->metaInfo() + QLatin1Char('\n') + QLatin1Char('\n')
+ reader.errors().join(QLatin1Char('\n'));
@@ -115,15 +119,18 @@ void MetaInfoPrivate::parseItemLibraryDescriptions()
QCoreApplication::translate("QmlDesigner::Internal::MetaInfoPrivate",
"Invalid meta info"),
errorMessage);
+#endif
}
}
- const Utils::FilePaths allMetaInfoFiles = allGlobalMetaInfoFiles();
+ const Utils::FilePaths allMetaInfoFiles = allGlobalMetaInfoFiles(externalDependencies);
for (const Utils::FilePath &path : allMetaInfoFiles) {
Internal::MetaInfoReader reader(*m_q);
try {
reader.readMetaInfoFile(path.toString());
} catch (const InvalidMetaInfoException &e) {
+ Q_UNUSED(e);
+#ifndef UNIT_TESTS
qWarning() << e.description();
const QString errorMessage = path.toString() + QLatin1Char('\n') + QLatin1Char('\n')
+ reader.errors().join(QLatin1Char('\n'));
@@ -131,6 +138,7 @@ void MetaInfoPrivate::parseItemLibraryDescriptions()
QCoreApplication::translate("QmlDesigner::Internal::MetaInfoPrivate",
"Invalid meta info"),
errorMessage);
+#endif
}
}
}
@@ -186,45 +194,26 @@ ItemLibraryInfo *MetaInfo::itemLibraryInfo() const
return m_p->m_itemLibraryInfo.data();
}
-/*!
- Accesses the global meta information object.
- You almost always want to use Model::metaInfo() instead.
-
- Internally, all meta information objects share this \e global object
- where static QML type information is stored.
- */
-MetaInfo MetaInfo::global()
+void MetaInfo::initializeGlobal(const QStringList &pluginPaths,
+ const ExternalDependenciesInterface &externalDependencies)
{
QMutexLocker locker(&s_lock);
if (!s_global.m_p->m_isInitialized) {
+ s_pluginDirs = pluginPaths,
s_global.m_p = QSharedPointer<MetaInfoPrivate>(new MetaInfoPrivate(&s_global));
- s_global.m_p->initialize();
+ s_global.m_p->initialize(externalDependencies);
}
- return s_global;
-}
-
-/*!
- Clears the global meta information object.
-
- This function should be called once on application shutdown to free static data structures.
- */
-void MetaInfo::clearGlobal()
-{
- if (s_global.m_p->m_isInitialized)
- s_global.m_p->clear();
}
-void MetaInfo::setPluginPaths(const QStringList &paths)
+bool MetaInfo::isGlobal() const
{
- s_pluginDirs = paths;
- global();
- clearGlobal();
+ return (this->m_p == s_global.m_p);
}
-bool MetaInfo::isGlobal() const
+MetaInfo MetaInfo::global()
{
- return (this->m_p == s_global.m_p);
+ return s_global;
}
bool operator==(const MetaInfo &first, const MetaInfo &second)
diff --git a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp
index f4b505c4e70..bdb7b63392e 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp
@@ -768,7 +768,7 @@ NodeMetaInfoPrivate::NodeMetaInfoPrivate(Model *model, TypeName type, int maj, i
}
} else {
m_isFileComponent = true;
- const Imports *imports = context()->imports(document());
+ const auto *imports = context()->imports(document());
const ImportInfo importInfo = imports->info(lookupNameComponent().constLast(),
context().data());
@@ -791,7 +791,7 @@ NodeMetaInfoPrivate::NodeMetaInfoPrivate(Model *model, TypeName type, int maj, i
} else {
// Special case for aliased types for the rewriter
- const Imports *imports = context()->imports(document());
+ const auto *imports = context()->imports(document());
const ImportInfo importInfo = imports->info(QString::fromUtf8(m_qualfiedTypeName),
context().data());
if (importInfo.isValid()) {
@@ -1198,7 +1198,7 @@ QString NodeMetaInfoPrivate::importDirectoryPath() const
ModelManagerInterface *modelManager = ModelManagerInterface::instance();
if (isValid()) {
- const Imports *imports = context()->imports(document());
+ const auto *imports = context()->imports(document());
ImportInfo importInfo = imports->info(lookupNameComponent().constLast(), context().data());
if (importInfo.type() == ImportType::Directory) {
@@ -1333,7 +1333,7 @@ void NodeMetaInfoPrivate::setupPrototypes()
m_prototypes.append(description);
} else {
if (context()->lookupType(document(), {ov->className()})) {
- const Imports *allImports = context()->imports(document());
+ const auto *allImports = context()->imports(document());
ImportInfo importInfo = allImports->info(description.className, context().data());
if (importInfo.isValid()) {
@@ -1619,16 +1619,20 @@ TypeName NodeMetaInfo::simplifiedTypeName() const
int NodeMetaInfo::majorVersion() const
{
- if (isValid())
- return m_privateData->majorVersion();
+ if constexpr (!useProjectStorage()) {
+ if (isValid())
+ return m_privateData->majorVersion();
+ }
return -1;
}
int NodeMetaInfo::minorVersion() const
{
- if (isValid())
- return m_privateData->minorVersion();
+ if constexpr (!useProjectStorage()) {
+ if (isValid())
+ return m_privateData->minorVersion();
+ }
return -1;
}
@@ -1649,7 +1653,6 @@ QString NodeMetaInfo::importDirectoryPath() const
return {};
}
-#ifdef QDS_USE_PROJECTSTORAGE
const Storage::Info::Type &NodeMetaInfo::typeData() const
{
if (!m_typeData)
@@ -1657,20 +1660,6 @@ const Storage::Info::Type &NodeMetaInfo::typeData() const
return *m_typeData;
}
-#endif
-
-bool NodeMetaInfo::availableInVersion(int majorVersion, int minorVersion) const
-{
- if (!isValid())
- return false;
-
- if (majorVersion == -1 && minorVersion == -1)
- return true;
-
- return (m_privateData->majorVersion() >= majorVersion)
- || (majorVersion == m_privateData->majorVersion()
- && m_privateData->minorVersion() >= minorVersion);
-}
bool NodeMetaInfo::isSubclassOf(const TypeName &type, int majorVersion, int minorVersion) const
{
@@ -1682,7 +1671,7 @@ bool NodeMetaInfo::isSubclassOf(const TypeName &type, int majorVersion, int mino
if (typeName().isEmpty())
return false;
- if (typeName() == type && availableInVersion(majorVersion, minorVersion))
+ if (typeName() == type)
return true;
if (m_privateData->prototypeCachePositives().contains(
@@ -1695,8 +1684,7 @@ bool NodeMetaInfo::isSubclassOf(const TypeName &type, int majorVersion, int mino
const NodeMetaInfos superClassList = superClasses();
for (const NodeMetaInfo &superClass : superClassList) {
- if (superClass.m_privateData->cleverCheckType(type)
- && superClass.availableInVersion(majorVersion, minorVersion)) {
+ if (superClass.m_privateData->cleverCheckType(type)) {
m_privateData->prototypeCachePositives().insert(
stringIdentifier(type, majorVersion, minorVersion));
return true;
@@ -1900,8 +1888,7 @@ bool NodeMetaInfo::isBasedOn(const NodeMetaInfo &metaInfo1,
namespace {
template<const char *moduleName, const char *typeName>
-bool isBasedOnCommonType(NotNullPointer<const ProjectStorage<Sqlite::Database>> projectStorage,
- TypeId typeId)
+bool isBasedOnCommonType(NotNullPointer<const ProjectStorageType> projectStorage, TypeId typeId)
{
auto base = projectStorage->commonTypeId<moduleName, typeName>();
@@ -2047,16 +2034,6 @@ bool NodeMetaInfo::isQtQuickPropertyChanges() const
}
}
-bool NodeMetaInfo::isQuickStateOperation() const
-{
- if constexpr (useProjectStorage()) {
- using namespace Storage::Info;
- return isBasedOnCommonType<QtQuick_cppnative, QuickStateOperation>(m_projectStorage, m_typeId);
- } else {
- return isValid() && isSubclassOf("<cpp>.QQuickStateOperation");
- }
-}
-
bool NodeMetaInfo::isQtSafeRendererSafeRendererPicture() const
{
if constexpr (useProjectStorage()) {
@@ -2279,6 +2256,16 @@ bool NodeMetaInfo::isQtQuick3DInstanceListEntry() const
}
}
+bool NodeMetaInfo::isQtQuick3DLight() const
+{
+ if constexpr (useProjectStorage()) {
+ using namespace Storage::Info;
+ return isBasedOnCommonType<QtQuick3D, Light>(m_projectStorage, m_typeId);
+ } else {
+ return isValid() && isSubclassOf("QtQuick3D.Light");
+ }
+}
+
bool NodeMetaInfo::isQtQuick3DInstanceList() const
{
if constexpr (useProjectStorage()) {
@@ -2320,7 +2307,7 @@ bool NodeMetaInfo::isQtQuick3DParticles3DAttractor3D() const
}
}
-bool NodeMetaInfo::isQuick3DParticleAbstractShape() const
+bool NodeMetaInfo::isQtQuick3DParticleAbstractShape() const
{
if constexpr (useProjectStorage()) {
using namespace Storage::Info;
@@ -2405,7 +2392,8 @@ bool NodeMetaInfo::isQtQuickStateOperation() const
{
if constexpr (useProjectStorage()) {
using namespace Storage::Info;
- return isBasedOnCommonType<QtQuick, QQuickStateOperation>(m_projectStorage, m_typeId);
+ return isBasedOnCommonType<QtQuick_cppnative, QQuickStateOperation>(m_projectStorage,
+ m_typeId);
} else {
return isValid() && isSubclassOf("<cpp>.QQuickStateOperation");
}
@@ -2834,12 +2822,13 @@ bool NodeMetaInfo::isEnumeration() const
return false;
}
-PropertyMetaInfo::PropertyMetaInfo(QSharedPointer<NodeMetaInfoPrivate> nodeMetaInfoPrivateData,
- const PropertyName &propertyName)
+PropertyMetaInfo::PropertyMetaInfo(
+ [[maybe_unused]] QSharedPointer<NodeMetaInfoPrivate> nodeMetaInfoPrivateData,
+ [[maybe_unused]] const PropertyName &propertyName)
+#ifndef QDS_USE_PROJECTSTORAGE
: m_nodeMetaInfoPrivateData{nodeMetaInfoPrivateData}
, m_propertyName{propertyName}
- , m_projectStorage{nullptr}
-
+#endif
{}
PropertyMetaInfo::~PropertyMetaInfo() = default;
@@ -2850,8 +2839,8 @@ NodeMetaInfo PropertyMetaInfo::propertyType() const
return {propertyData().typeId, m_projectStorage};
} else {
if (isValid())
- return NodeMetaInfo{m_nodeMetaInfoPrivateData->model(),
- m_nodeMetaInfoPrivateData->propertyType(m_propertyName),
+ return NodeMetaInfo{nodeMetaInfoPrivateData()->model(),
+ nodeMetaInfoPrivateData()->propertyType(propertyName()),
-1,
-1};
}
@@ -2864,7 +2853,7 @@ PropertyName PropertyMetaInfo::name() const
if constexpr (useProjectStorage())
return PropertyName(Utils::SmallStringView(propertyData().name));
else
- return m_propertyName;
+ return propertyName();
}
bool PropertyMetaInfo::isWritable() const
@@ -2872,7 +2861,7 @@ bool PropertyMetaInfo::isWritable() const
if constexpr (useProjectStorage())
return !(propertyData().traits & Storage::PropertyDeclarationTraits::IsReadOnly);
else
- return isValid() && m_nodeMetaInfoPrivateData->isPropertyWritable(m_propertyName);
+ return isValid() && nodeMetaInfoPrivateData()->isPropertyWritable(propertyName());
}
bool PropertyMetaInfo::isListProperty() const
@@ -2880,7 +2869,7 @@ bool PropertyMetaInfo::isListProperty() const
if constexpr (useProjectStorage())
return propertyData().traits & Storage::PropertyDeclarationTraits::IsList;
else
- return isValid() && m_nodeMetaInfoPrivateData->isPropertyList(m_propertyName);
+ return isValid() && nodeMetaInfoPrivateData()->isPropertyList(propertyName());
}
bool PropertyMetaInfo::isEnumType() const
@@ -2888,7 +2877,7 @@ bool PropertyMetaInfo::isEnumType() const
if constexpr (useProjectStorage())
return propertyType().isEnumeration();
else
- return isValid() && m_nodeMetaInfoPrivateData->isPropertyEnum(m_propertyName);
+ return isValid() && nodeMetaInfoPrivateData()->isPropertyEnum(propertyName());
}
bool PropertyMetaInfo::isPrivate() const
@@ -2896,7 +2885,7 @@ bool PropertyMetaInfo::isPrivate() const
if constexpr (useProjectStorage())
return propertyData().name.startsWith("__");
else
- return isValid() && m_propertyName.startsWith("__");
+ return isValid() && propertyName().startsWith("__");
}
bool PropertyMetaInfo::isPointer() const
@@ -2904,7 +2893,7 @@ bool PropertyMetaInfo::isPointer() const
if constexpr (useProjectStorage())
return propertyData().traits & Storage::PropertyDeclarationTraits::IsPointer;
else
- return isValid() && m_nodeMetaInfoPrivateData->isPropertyPointer(m_propertyName);
+ return isValid() && nodeMetaInfoPrivateData()->isPropertyPointer(propertyName());
}
QVariant PropertyMetaInfo::castedValue(const QVariant &value) const
@@ -2920,7 +2909,7 @@ QVariant PropertyMetaInfo::castedValue(const QVariant &value) const
const TypeName &typeName = propertyTypeName();
- QVariant::Type typeId = m_nodeMetaInfoPrivateData->variantTypeId(m_propertyName);
+ QVariant::Type typeId = nodeMetaInfoPrivateData()->variantTypeId(propertyName());
if (variant.type() == QVariant::UserType
&& variant.userType() == ModelNode::variantUserType()) {
@@ -3012,6 +3001,25 @@ TypeName PropertyMetaInfo::propertyTypeName() const
return propertyType().typeName();
}
+const NodeMetaInfoPrivate *PropertyMetaInfo::nodeMetaInfoPrivateData() const
+{
+#ifndef QDS_USE_PROJECTSTORAGE
+ return m_nodeMetaInfoPrivateData.data();
+#else
+ return nullptr;
+#endif
+}
+
+const PropertyName &PropertyMetaInfo::propertyName() const
+{
+#ifndef QDS_USE_PROJECTSTORAGE
+ return m_propertyName;
+#else
+ static PropertyName dummy;
+ return dummy;
+#endif
+}
+
NodeMetaInfo NodeMetaInfo::commonBase(const NodeMetaInfo &metaInfo) const
{
for (const NodeMetaInfo &info : metaInfo.superClasses()) {
diff --git a/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp b/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp
index e7feb0d4454..0afd0d735c7 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp
@@ -491,7 +491,7 @@ QStringList SubComponentManager::qmlFiles() const
return m_watcher.files();
}
-void SubComponentManager::update(const QUrl &filePath, const QList<Import> &imports)
+void SubComponentManager::update(const QUrl &filePath, const Imports &imports)
{
if (debug)
qDebug() << Q_FUNC_INFO << filePath << imports.size();
diff --git a/src/plugins/qmldesigner/designercore/model/abstractproperty.cpp b/src/plugins/qmldesigner/designercore/model/abstractproperty.cpp
index 3bccf54660c..00541e12e2f 100644
--- a/src/plugins/qmldesigner/designercore/model/abstractproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/abstractproperty.cpp
@@ -39,7 +39,6 @@ AbstractProperty::AbstractProperty(const Internal::InternalPropertyPointer &prop
m_model(model),
m_view(view)
{
- Q_ASSERT(!m_model || m_view);
}
AbstractProperty::AbstractProperty(const AbstractProperty &property, AbstractView *view)
diff --git a/src/plugins/qmldesigner/designercore/model/abstractview.cpp b/src/plugins/qmldesigner/designercore/model/abstractview.cpp
index b9f0315c196..9967d49ee7b 100644
--- a/src/plugins/qmldesigner/designercore/model/abstractview.cpp
+++ b/src/plugins/qmldesigner/designercore/model/abstractview.cpp
@@ -64,8 +64,12 @@ RewriterTransaction AbstractView::beginRewriterTransaction(const QByteArray &ide
ModelNode AbstractView::createModelNode(const TypeName &typeName)
{
- const NodeMetaInfo metaInfo = model()->metaInfo(typeName);
- return createModelNode(typeName, metaInfo.majorVersion(), metaInfo.minorVersion());
+ if constexpr (useProjectStorage()) {
+ return createModelNode(typeName, -1, -1);
+ } else {
+ const NodeMetaInfo metaInfo = model()->metaInfo(typeName);
+ return createModelNode(typeName, metaInfo.majorVersion(), metaInfo.minorVersion());
+ }
}
ModelNode AbstractView::createModelNode(const TypeName &typeName,
@@ -143,9 +147,6 @@ The default implementation is setting the reference of the model to the view.
void AbstractView::modelAttached(Model *model)
{
setModel(model);
-
- if (model)
- model->d->updateEnabledViews();
}
/*!
@@ -315,15 +316,15 @@ void AbstractView::nodeTypeChanged(const ModelNode & /*node*/, const TypeName &
}
-void AbstractView::importsChanged(const QList<Import> &/*addedImports*/, const QList<Import> &/*removedImports*/)
+void AbstractView::importsChanged(const Imports &/*addedImports*/, const Imports &/*removedImports*/)
{
}
-void AbstractView::possibleImportsChanged(const QList<Import> &/*possibleImports*/)
+void AbstractView::possibleImportsChanged(const Imports &/*possibleImports*/)
{
}
-void AbstractView::usedImportsChanged(const QList<Import> &/*usedImports*/)
+void AbstractView::usedImportsChanged(const Imports &/*usedImports*/)
{
}
@@ -617,9 +618,6 @@ bool AbstractView::isEnabled() const
void AbstractView::setEnabled(bool b)
{
m_enabled = b;
-
- if (model())
- model()->d->updateEnabledViews();
}
QList<ModelNode> AbstractView::allModelNodes() const
@@ -893,32 +891,28 @@ QmlTimeline AbstractView::currentTimeline() const
static int getMinorVersionFromImport(const Model *model)
{
- const QList<Import> imports = model->imports();
- for (const Import &import : imports) {
- if (import.isLibraryImport() && import.url() == "QtQuick") {
- const QString versionString = import.version();
- if (versionString.contains(".")) {
- const QString minorVersionString = versionString.split(".").constLast();
- return minorVersionString.toInt();
- }
- }
- }
+ const Imports &imports = model->imports();
+
+ auto found = std::find_if(imports.begin(), imports.end(), [](const auto &import) {
+ return import.url() == "QtQuick";
+ });
+
+ if (found != imports.end())
+ return found->minorVersion();
return -1;
}
static int getMajorVersionFromImport(const Model *model)
{
- const QList<Import> imports = model->imports();
- for (const Import &import : imports) {
- if (import.isLibraryImport() && import.url() == QStringLiteral("QtQuick")) {
- const QString versionString = import.version();
- if (versionString.contains(QStringLiteral("."))) {
- const QString majorVersionString = versionString.split(QStringLiteral(".")).constFirst();
- return majorVersionString.toInt();
- }
- }
- }
+ const Imports &imports = model->imports();
+
+ auto found = std::find_if(imports.begin(), imports.end(), [](const auto &import) {
+ return import.url() == "QtQuick";
+ });
+
+ if (found != imports.end())
+ return found->majorVersion();
return -1;
}
diff --git a/src/plugins/qmldesigner/designercore/model/bindingproperty.cpp b/src/plugins/qmldesigner/designercore/model/bindingproperty.cpp
index 77dbec5e25a..45d4e4cf20e 100644
--- a/src/plugins/qmldesigner/designercore/model/bindingproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/bindingproperty.cpp
@@ -56,7 +56,7 @@ void BindingProperty::setExpression(const QString &expression)
}
if (internalNode()->hasProperty(name()) && !internalNode()->property(name())->isBindingProperty())
- privateModel()->removeProperty(internalNode()->property(name()));
+ privateModel()->removePropertyAndRelatedResources(internalNode()->property(name()));
privateModel()->setBindingProperty(internalNode(), name(), expression);
}
@@ -341,7 +341,7 @@ void BindingProperty::setDynamicTypeNameAndExpression(const TypeName &typeName,
}
if (internalNode()->hasProperty(name()) && !internalNode()->property(name())->isBindingProperty())
- privateModel()->removeProperty(internalNode()->property(name()));
+ privateModel()->removePropertyAndRelatedResources(internalNode()->property(name()));
privateModel()->setDynamicBindingProperty(internalNode(), name(), typeName, expression);
}
diff --git a/src/plugins/qmldesigner/designercore/model/import.cpp b/src/plugins/qmldesigner/designercore/model/import.cpp
index 3a6914d3258..54b18810437 100644
--- a/src/plugins/qmldesigner/designercore/model/import.cpp
+++ b/src/plugins/qmldesigner/designercore/model/import.cpp
@@ -5,9 +5,9 @@
#include <QHash>
-namespace QmlDesigner {
+#include <QStringView>
-Import::Import() = default;
+namespace QmlDesigner {
Import Import::createLibraryImport(const QString &url, const QString &version, const QString &alias, const QStringList &importPaths)
{
@@ -62,11 +62,6 @@ QString Import::toString(bool skipAlias, bool skipVersion) const
return result;
}
-bool Import::operator==(const Import &other) const
-{
- return url() == other.url() && file() == other.file() && (version() == other.version() || version().isEmpty() || other.version().isEmpty());
-}
-
bool Import::isSameModule(const Import &other) const
{
if (isLibraryImport())
@@ -85,21 +80,56 @@ int Import::minorVersion() const
return minorFromVersion(m_version);
}
+Version Import::toVersion() const
+{
+ auto found = std::find(m_version.begin(), m_version.end(), u'.');
+ if (found == m_version.end())
+ return {};
+
+ QStringView majorVersionToken{m_version.begin(), found};
+ bool canConvertMajor = false;
+ int majorVersion = majorVersionToken.toInt(&canConvertMajor);
+
+ QStringView minorVersionToken{std::next(found), m_version.end()};
+ bool canConvertMinor = false;
+ int minorVersion = minorVersionToken.toInt(&canConvertMinor);
+
+ if (canConvertMajor && canConvertMinor)
+ return {majorVersion, minorVersion};
+
+ return {};
+}
+
int Import::majorFromVersion(const QString &version)
{
- if (version.isEmpty())
+ auto found = std::find(version.begin(), version.end(), u'.');
+ if (found == version.end())
return -1;
- return version.split('.').first().toInt();
+
+ QStringView majorVersionToken{version.begin(), found};
+ bool canConvert = false;
+ int majorVersion = majorVersionToken.toInt(&canConvert);
+
+ if (canConvert)
+ return majorVersion;
+
+ return -1;
}
int Import::minorFromVersion(const QString &version)
{
- if (version.isEmpty())
+ auto found = std::find(version.begin(), version.end(), u'.');
+ if (found == version.end())
return -1;
- const QStringList parts = version.split('.');
- if (parts.size() < 2)
- return -1;
- return parts[1].toInt();
+
+ QStringView minorVersionToken{std::next(found), version.end()};
+ bool canConvert = false;
+ int minorVersion = minorVersionToken.toInt(&canConvert);
+
+ if (canConvert)
+ return minorVersion;
+
+ return -1;
}
size_t qHash(const Import &import)
@@ -107,4 +137,17 @@ 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 difference;
+ difference.reserve(first.size());
+
+ std::set_difference(first.begin(),
+ first.end(),
+ second.begin(),
+ second.end(),
+ std::back_inserter(difference));
+
+ return difference;
+}
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/model/model.cpp b/src/plugins/qmldesigner/designercore/model/model.cpp
index a234c11e1fe..844454ae55e 100644
--- a/src/plugins/qmldesigner/designercore/model/model.cpp
+++ b/src/plugins/qmldesigner/designercore/model/model.cpp
@@ -37,6 +37,7 @@
#include <QHashIterator>
#include <QPointer>
#include <QRegularExpression>
+#include <qcompilerdetection.h>
/*!
\defgroup CoreModel
@@ -57,13 +58,15 @@ namespace QmlDesigner {
namespace Internal {
ModelPrivate::ModelPrivate(Model *model,
- ProjectStorage<Sqlite::Database> &projectStorage,
+ ProjectStorageType &projectStorage,
const TypeName &typeName,
int major,
int minor,
- Model *metaInfoProxyModel)
+ Model *metaInfoProxyModel,
+ std::unique_ptr<ModelResourceManagementInterface> resourceManagement)
: projectStorage{&projectStorage}
, m_model{model}
+ , m_resourceManagement{std::move(resourceManagement)}
{
m_metaInfoProxyModel = metaInfoProxyModel;
@@ -74,9 +77,14 @@ ModelPrivate::ModelPrivate(Model *model,
m_currentTimelineNode = m_rootInternalNode;
}
-ModelPrivate::ModelPrivate(
- Model *model, const TypeName &typeName, int major, int minor, Model *metaInfoProxyModel)
+ModelPrivate::ModelPrivate(Model *model,
+ const TypeName &typeName,
+ int major,
+ int minor,
+ Model *metaInfoProxyModel,
+ std::unique_ptr<ModelResourceManagementInterface> resourceManagement)
: m_model(model)
+ , m_resourceManagement{std::move(resourceManagement)}
{
m_metaInfoProxyModel = metaInfoProxyModel;
@@ -95,7 +103,6 @@ void ModelPrivate::detachAllViews()
detachView(view.data(), true);
m_viewList.clear();
- updateEnabledViews();
if (m_nodeInstanceView) {
m_nodeInstanceView->modelAboutToBeDetached(m_model);
@@ -108,10 +115,10 @@ void ModelPrivate::detachAllViews()
}
}
-void ModelPrivate::changeImports(const QList<Import> &toBeAddedImportList,
- const QList<Import> &toBeRemovedImportList)
+void ModelPrivate::changeImports(const Imports &toBeAddedImportList,
+ const Imports &toBeRemovedImportList)
{
- QList<Import> removedImportList;
+ Imports removedImportList;
for (const Import &import : toBeRemovedImportList) {
if (m_imports.contains(import)) {
removedImportList.append(import);
@@ -119,7 +126,7 @@ void ModelPrivate::changeImports(const QList<Import> &toBeAddedImportList,
}
}
- QList<Import> addedImportList;
+ Imports addedImportList;
for (const Import &import : toBeAddedImportList) {
if (!m_imports.contains(import)) {
addedImportList.append(import);
@@ -127,12 +134,13 @@ void ModelPrivate::changeImports(const QList<Import> &toBeAddedImportList,
}
}
+ std::sort(m_imports.begin(), m_imports.end());
+
if (!removedImportList.isEmpty() || !addedImportList.isEmpty())
notifyImportsChanged(addedImportList, removedImportList);
}
-void ModelPrivate::notifyImportsChanged(const QList<Import> &addedImports,
- const QList<Import> &removedImports)
+void ModelPrivate::notifyImportsChanged(const Imports &addedImports, const Imports &removedImports)
{
bool resetModel = false;
QString description;
@@ -157,7 +165,7 @@ void ModelPrivate::notifyImportsChanged(const QList<Import> &addedImports,
resetModelByRewriter(description);
}
-void ModelPrivate::notifyPossibleImportsChanged(const QList<Import> &possibleImports)
+void ModelPrivate::notifyPossibleImportsChanged(const Imports &possibleImports)
{
for (const QPointer<AbstractView> &view : enabledViews()) {
Q_ASSERT(view != nullptr);
@@ -165,7 +173,7 @@ void ModelPrivate::notifyPossibleImportsChanged(const QList<Import> &possibleImp
}
}
-void ModelPrivate::notifyUsedImportsChanged(const QList<Import> &usedImports)
+void ModelPrivate::notifyUsedImportsChanged(const Imports &usedImports)
{
for (const QPointer<AbstractView> &view : enabledViews()) {
Q_ASSERT(view != nullptr);
@@ -210,6 +218,23 @@ 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,
@@ -229,6 +254,15 @@ InternalNodePointer ModelPrivate::createNode(const TypeName &typeName,
internalId = m_internalIdCounter++;
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});
+ }
+
newNode->nodeSourceType = nodeSourceType;
newNode->behaviorPropertyName = behaviorPropertyName;
@@ -252,7 +286,9 @@ InternalNodePointer ModelPrivate::createNode(const TypeName &typeName,
notifyNodeCreated(newNode);
if (!newNode->propertyNameList().isEmpty())
- notifyVariantPropertiesChanged(newNode, newNode->propertyNameList(), AbstractView::PropertiesAdded);
+ notifyVariantPropertiesChanged(newNode,
+ newNode->propertyNameList(),
+ AbstractView::PropertiesAdded);
return newNode;
}
@@ -271,9 +307,27 @@ void ModelPrivate::removeNodeFromModel(const InternalNodePointer &node)
m_internalIdNodeHash.remove(node->internalId);
}
-const QList<QPointer<AbstractView>> ModelPrivate::enabledViews() const
+EnabledViewRange ModelPrivate::enabledViews() const
{
- return m_enabledViewList;
+ return EnabledViewRange{m_viewList};
+}
+
+void ModelPrivate::handleResourceSet(const ModelResourceSet &resourceSet)
+{
+ for (const ModelNode &node : resourceSet.removeModelNodes) {
+ if (node)
+ removeNode(node.m_internalNode);
+ }
+
+ for (const AbstractProperty &property : resourceSet.removeProperties) {
+ if (property)
+ removeProperty(property.m_internalNode->property(property.m_propertyName));
+ }
+
+ for (const auto &[property, expression] : resourceSet.setExpressions) {
+ if (property)
+ setBindingProperty(property.m_internalNode, property.m_propertyName, expression);
+ }
}
void ModelPrivate::removeAllSubNodes(const InternalNodePointer &node)
@@ -282,10 +336,16 @@ void ModelPrivate::removeAllSubNodes(const InternalNodePointer &node)
removeNodeFromModel(subNode);
}
-void ModelPrivate::removeNode(const InternalNodePointer &node)
+void ModelPrivate::removeNodeAndRelatedResources(const InternalNodePointer &node)
{
- Q_ASSERT(node);
+ if (m_resourceManagement)
+ handleResourceSet(m_resourceManagement->removeNode(ModelNode{node, m_model, nullptr}));
+ else
+ removeNode(node);
+}
+void ModelPrivate::removeNode(const InternalNodePointer &node)
+{
AbstractView::PropertyChangeFlags propertyChangeFlags = AbstractView::NoAdditionalChanges;
notifyNodeAboutToBeRemoved(node);
@@ -726,7 +786,6 @@ void ModelPrivate::detachView(AbstractView *view, bool notifyView)
if (notifyView)
view->modelAboutToBeDetached(m_model);
m_viewList.removeOne(view);
- updateEnabledViews();
}
void ModelPrivate::notifyNodeCreated(const InternalNodePointer &newInternalNodePointer)
@@ -1062,6 +1121,15 @@ static QList<PropertyPair> toPropertyPairList(const QList<InternalPropertyPointe
return propertyPairList;
}
+void ModelPrivate::removePropertyAndRelatedResources(const InternalPropertyPointer &property)
+{
+ if (m_resourceManagement)
+ handleResourceSet(
+ m_resourceManagement->removeProperty(AbstractProperty{property, m_model, nullptr}));
+ else
+ removeProperty(property);
+}
+
void ModelPrivate::removeProperty(const InternalPropertyPointer &property)
{
notifyPropertiesAboutToBeRemoved({property});
@@ -1289,13 +1357,6 @@ InternalNodePointer ModelPrivate::currentTimelineNode() const
return m_currentTimelineNode;
}
-void ModelPrivate::updateEnabledViews()
-{
- m_enabledViewList = Utils::filtered(m_viewList, [](QPointer<AbstractView> view) {
- return view->isEnabled();
- });
-}
-
InternalNodePointer ModelPrivate::nodeForId(const QString &id) const
{
return m_idNodeHash.value(id);
@@ -1385,89 +1446,80 @@ void WriteLocker::lock(Model *model)
} // namespace Internal
-Model::Model(ProjectStorage<Sqlite::Database> &projectStorage,
+Model::Model(ProjectStorageType &projectStorage,
const TypeName &typeName,
int major,
int minor,
- Model *metaInfoProxyModel)
+ Model *metaInfoProxyModel,
+ std::unique_ptr<ModelResourceManagementInterface> resourceManagement)
: d(std::make_unique<Internal::ModelPrivate>(
- this, projectStorage, typeName, major, minor, metaInfoProxyModel))
+ this, projectStorage, typeName, major, minor, metaInfoProxyModel, std::move(resourceManagement)))
{}
-Model::Model(const TypeName &typeName, int major, int minor, Model *metaInfoProxyModel)
- : d(std::make_unique<Internal::ModelPrivate>(this, typeName, major, minor, metaInfoProxyModel))
+Model::Model(const TypeName &typeName,
+ int major,
+ int minor,
+ Model *metaInfoProxyModel,
+ std::unique_ptr<ModelResourceManagementInterface> resourceManagement)
+ : d(std::make_unique<Internal::ModelPrivate>(
+ this, typeName, major, minor, metaInfoProxyModel, std::move(resourceManagement)))
{}
Model::~Model() = default;
-const QList<Import> &Model::imports() const
+const Imports &Model::imports() const
{
return d->imports();
}
-const QList<Import> &Model::possibleImports() const
+const Imports &Model::possibleImports() const
{
return d->m_possibleImportList;
}
-const QList<Import> &Model::usedImports() const
+const Imports &Model::usedImports() const
{
return d->m_usedImportList;
}
-void Model::changeImports(const QList<Import> &importsToBeAdded,
- const QList<Import> &importsToBeRemoved)
+void Model::changeImports(const Imports &importsToBeAdded, const Imports &importsToBeRemoved)
{
d->changeImports(importsToBeAdded, importsToBeRemoved);
}
-void Model::setPossibleImports(const QList<Import> &possibleImports)
+void Model::setPossibleImports(Imports possibleImports)
{
+ std::sort(possibleImports.begin(), possibleImports.end());
+
if (d->m_possibleImportList != possibleImports) {
- d->m_possibleImportList = possibleImports;
- d->notifyPossibleImportsChanged(possibleImports);
+ d->m_possibleImportList = std::move(possibleImports);
+ d->notifyPossibleImportsChanged(d->m_possibleImportList);
}
}
-void Model::setUsedImports(const QList<Import> &usedImports)
+void Model::setUsedImports(Imports usedImports)
{
+ std::sort(usedImports.begin(), usedImports.end());
+
if (d->m_usedImportList != usedImports) {
- d->m_usedImportList = usedImports;
- d->notifyUsedImportsChanged(usedImports);
+ d->m_usedImportList = std::move(usedImports);
+ d->notifyUsedImportsChanged(d->m_usedImportList);
}
}
-static bool compareVersions(const QString &version1, const QString &version2, bool allowHigherVersion)
+static bool compareVersions(const Import &import1, const Import &import2, bool allowHigherVersion)
{
+ auto version1 = import1.toVersion();
+ auto version2 = import2.toVersion();
+
if (version2.isEmpty())
return true;
if (version1 == version2)
return true;
if (!allowHigherVersion)
return false;
- QStringList version1List = version1.split(QLatin1Char('.'));
- QStringList version2List = version2.split(QLatin1Char('.'));
- if (version1List.count() == 2 && version2List.count() == 2) {
- bool ok;
- int major1 = version1List.constFirst().toInt(&ok);
- if (!ok)
- return false;
- int major2 = version2List.constFirst().toInt(&ok);
- if (!ok)
- return false;
- if (major1 >= major2) {
- int minor1 = version1List.constLast().toInt(&ok);
- if (!ok)
- return false;
- int minor2 = version2List.constLast().toInt(&ok);
- if (!ok)
- return false;
- if (minor1 >= minor2)
- return true;
- }
- }
- return false;
+ return version1 >= version2;
}
bool Model::hasImport(const Import &import, bool ignoreAlias, bool allowHigherVersion) const
@@ -1485,7 +1537,7 @@ bool Model::hasImport(const Import &import, bool ignoreAlias, bool allowHigherVe
}
if (existingImport.isLibraryImport() && import.isLibraryImport()) {
if (existingImport.url() == import.url()
- && compareVersions(existingImport.version(), import.version(), allowHigherVersion)) {
+ && compareVersions(existingImport, import, allowHigherVersion)) {
return true;
}
}
@@ -1627,7 +1679,7 @@ void Model::endDrag()
d->notifyDragEnded();
}
-NotNullPointer<const ProjectStorage<Sqlite::Database>> Model::projectStorage() const
+NotNullPointer<const ProjectStorageType> Model::projectStorage() const
{
return d->projectStorage;
}
@@ -1659,7 +1711,7 @@ bool Model::isImportPossible(const Import &import, bool ignoreAlias, bool allowH
if (possibleImport.isLibraryImport() && import.isLibraryImport()) {
if (possibleImport.url() == import.url()
- && compareVersions(possibleImport.version(), import.version(), allowHigherVersion)) {
+ && compareVersions(possibleImport, import, allowHigherVersion)) {
return true;
}
}
@@ -1694,7 +1746,7 @@ Import Model::highestPossibleImport(const QString &importPath)
for (const Import &import : possibleImports()) {
if (import.url() == importPath) {
- if (candidate.isEmpty() || compareVersions(import.version(), candidate.version(), true))
+ if (candidate.isEmpty() || compareVersions(import, candidate, true))
candidate = import;
}
}
@@ -1804,7 +1856,7 @@ void Model::setMetaInfo(const MetaInfo &metaInfo)
template<const auto &moduleName, const auto &typeName>
NodeMetaInfo Model::createNodeMetaInfo() const
{
- auto typeId = d->projectStorage->commonTypeCache.typeId<moduleName, typeName>();
+ auto typeId = d->projectStorage->commonTypeCache().typeId<moduleName, typeName>();
return {typeId, d->projectStorage};
}
@@ -1939,6 +1991,16 @@ NodeMetaInfo Model::qtQuick3DTextureMetaInfo() const
}
}
+NodeMetaInfo Model::qtQuick3DBakedLightmapMetaInfo() const
+{
+ if constexpr (useProjectStorage()) {
+ using namespace Storage::Info;
+ return createNodeMetaInfo<QtQuick3D, BakedLightmap>();
+ } else {
+ return metaInfo("QtQuick3D.BakedLightmap");
+ }
+}
+
NodeMetaInfo Model::qtQuick3DMaterialMetaInfo() const
{
if constexpr (useProjectStorage()) {
@@ -2070,8 +2132,7 @@ NodeMetaInfo Model::metaInfo(const TypeName &typeName, int majorVersion, int min
ModuleId moduleId = d->projectStorage->moduleId(module);
TypeId typeId = d->projectStorage->typeId(moduleId,
componentName,
- Storage::Synchronization::Version{majorVersion,
- minorVersion});
+ Storage::Version{majorVersion, minorVersion});
return NodeMetaInfo(typeId, d->projectStorage);
} else {
return NodeMetaInfo(metaInfoProxyModel(), typeName, majorVersion, minorVersion);
@@ -2143,4 +2204,9 @@ void Model::detachView(AbstractView *view, ViewNotification emitDetachNotify)
d->detachView(view, emitNotify);
}
+QList<ModelNode> Model::allModelNodes() const
+{
+ return QmlDesigner::toModelNodeList(d->allNodes(), nullptr);
+}
+
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/model/model_p.h b/src/plugins/qmldesigner/designercore/model/model_p.h
index b08b7388518..b802d703f25 100644
--- a/src/plugins/qmldesigner/designercore/model/model_p.h
+++ b/src/plugins/qmldesigner/designercore/model/model_p.h
@@ -3,17 +3,20 @@
#pragma once
+#include "qmldesignercorelib_global.h"
+
+#include "abstractview.h"
+#include "metainfo.h"
+#include "modelnode.h"
+#include "skipiterator.h"
+
#include <QList>
#include <QPointer>
#include <QSet>
#include <QUrl>
#include <QVector3D>
-#include "modelnode.h"
-#include "abstractview.h"
-#include "metainfo.h"
-
-#include "qmldesignercorelib_global.h"
+#include <algorithm>
QT_BEGIN_NAMESPACE
class QPlainTextEdit;
@@ -64,7 +67,28 @@ private:
QPointer<ModelPrivate> m_model;
};
-class ModelPrivate : public QObject {
+struct Increment
+{
+ using iterator = QList<QPointer<AbstractView>>::const_iterator;
+ auto operator()(iterator current) {
+ return std::find_if(std::next(current),
+ end,
+ [] (iterator::reference &view) { return view && view->isEnabled(); });
+ }
+
+ iterator end;
+};
+
+class EnabledViewRange : public SkipRange<QList<QPointer<AbstractView>>, Increment>
+{
+public:
+ EnabledViewRange(const container &views)
+ : base{views, Increment{views.end()}}
+ {}
+};
+
+class ModelPrivate : public QObject
+{
Q_OBJECT
friend Model;
@@ -73,12 +97,18 @@ class ModelPrivate : public QObject {
public:
ModelPrivate(Model *model,
- ProjectStorage<Sqlite::Database> &projectStorage,
+ ProjectStorageType &projectStorage,
+ const TypeName &type,
+ int major,
+ int minor,
+ Model *metaInfoProxyModel,
+ std::unique_ptr<ModelResourceManagementInterface> resourceManagement);
+ ModelPrivate(Model *model,
const TypeName &type,
int major,
int minor,
- Model *metaInfoProxyModel);
- ModelPrivate(Model *model, const TypeName &type, int major, int minor, Model *metaInfoProxyModel);
+ Model *metaInfoProxyModel,
+ std::unique_ptr<ModelResourceManagementInterface> resourceManagement);
~ModelPrivate() override;
@@ -96,6 +126,7 @@ public:
bool isRootNode = false);
/*factory methods for internal use in model and rewriter*/
+ void removeNodeAndRelatedResources(const InternalNodePointer &node);
void removeNode(const InternalNodePointer &node);
void changeNodeId(const InternalNodePointer &node, const QString &id);
void changeNodeType(const InternalNodePointer &node, const TypeName &typeName, int majorVersion, int minorVersion);
@@ -202,17 +233,16 @@ public:
void resetModelByRewriter(const QString &description);
// Imports:
- const QList<Import> &imports() const { return m_imports; }
- void addImport(const Import &import);
- void removeImport(const Import &import);
- void changeImports(const QList<Import> &importsToBeAdded, const QList<Import> &importToBeRemoved);
- void notifyImportsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports);
- void notifyPossibleImportsChanged(const QList<Import> &possibleImports);
- void notifyUsedImportsChanged(const QList<Import> &usedImportsChanged);
+ const Imports &imports() const { return m_imports; }
+ void changeImports(const Imports &importsToBeAdded, const Imports &importToBeRemoved);
+ void notifyImportsChanged(const Imports &addedImports, const Imports &removedImports);
+ void notifyPossibleImportsChanged(const Imports &possibleImports);
+ void notifyUsedImportsChanged(const Imports &usedImportsChanged);
//node state property manipulation
void addProperty(const InternalNodePointer &node, const PropertyName &name);
void setPropertyValue(const InternalNodePointer &node,const PropertyName &name, const QVariant &value);
+ void removePropertyAndRelatedResources(const InternalPropertyPointer &property);
void removeProperty(const InternalPropertyPointer &property);
void setBindingProperty(const InternalNodePointer &node, const PropertyName &name, const QString &expression);
@@ -251,11 +281,6 @@ public:
InternalNodePointer currentStateNode() const;
InternalNodePointer currentTimelineNode() const;
- void updateEnabledViews();
-
-public:
- NotNullPointer<ProjectStorage<Sqlite::Database>> projectStorage = nullptr;
-
private:
void removePropertyWithoutNotification(const InternalPropertyPointer &property);
void removeAllSubNodes(const InternalNodePointer &node);
@@ -264,16 +289,19 @@ private:
QList<ModelNode> toModelNodeList(const QList<InternalNodePointer> &nodeList, AbstractView *view) const;
QVector<ModelNode> toModelNodeVector(const QVector<InternalNodePointer> &nodeVector, AbstractView *view) const;
QVector<InternalNodePointer> toInternalNodeVector(const QVector<ModelNode> &modelNodeVector) const;
- const QList<QPointer<AbstractView>> enabledViews() const;
+ EnabledViewRange enabledViews() const;
+ void handleResourceSet(const ModelResourceSet &resourceSet);
+
+public:
+ NotNullPointer<ProjectStorageType> projectStorage = nullptr;
private:
Model *m_model = nullptr;
MetaInfo m_metaInfo;
- QList<Import> m_imports;
- QList<Import> m_possibleImportList;
- QList<Import> m_usedImportList;
+ Imports m_imports;
+ Imports m_possibleImportList;
+ Imports m_usedImportList;
QList<QPointer<AbstractView>> m_viewList;
- QList<QPointer<AbstractView>> m_enabledViewList;
QList<InternalNodePointer> m_selectedInternalNodeList;
QHash<QString,InternalNodePointer> m_idNodeHash;
QHash<qint32, InternalNodePointer> m_internalIdNodeHash;
@@ -281,6 +309,7 @@ private:
InternalNodePointer m_currentStateNode;
InternalNodePointer m_rootInternalNode;
InternalNodePointer m_currentTimelineNode;
+ std::unique_ptr<ModelResourceManagementInterface> m_resourceManagement;
QUrl m_fileUrl;
QPointer<RewriterView> m_rewriterView;
QPointer<NodeInstanceView> m_nodeInstanceView;
diff --git a/src/plugins/qmldesigner/designercore/model/modelmerger.cpp b/src/plugins/qmldesigner/designercore/model/modelmerger.cpp
index 75cdcf83582..30d100f3503 100644
--- a/src/plugins/qmldesigner/designercore/model/modelmerger.cpp
+++ b/src/plugins/qmldesigner/designercore/model/modelmerger.cpp
@@ -173,7 +173,7 @@ ModelNode ModelMerger::insertModel(const ModelNode &modelNode, const MergePredic
return {};
RewriterTransaction transaction(view()->beginRewriterTransaction(QByteArrayLiteral("ModelMerger::insertModel")));
- QList<Import> newImports;
+ Imports newImports;
for (const Import &import : modelNode.model()->imports()) {
if (!view()->model()->hasImport(import, true, true))
diff --git a/src/plugins/qmldesigner/designercore/model/modelnode.cpp b/src/plugins/qmldesigner/designercore/model/modelnode.cpp
index aab0d13c249..7e64f4c4bf4 100644
--- a/src/plugins/qmldesigner/designercore/model/modelnode.cpp
+++ b/src/plugins/qmldesigner/designercore/model/modelnode.cpp
@@ -61,7 +61,6 @@ ModelNode::ModelNode(const InternalNodePointer &internalNode, Model *model, cons
m_model(model),
m_view(const_cast<AbstractView*>(view))
{
- Q_ASSERT(!m_model || m_view);
}
ModelNode::ModelNode(const ModelNode &modelNode, AbstractView *view)
@@ -291,7 +290,7 @@ A node might become invalid if e.g. it or one of its ancestors is deleted.
*/
bool ModelNode::isValid() const
{
- return !m_model.isNull() && !m_view.isNull() && m_internalNode && m_internalNode->isValid;
+ return !m_model.isNull() && m_internalNode && m_internalNode->isValid;
}
/*!
@@ -653,7 +652,7 @@ void ModelNode::removeProperty(const PropertyName &name) const
return;
if (m_internalNode->hasProperty(name))
- model()->d->removeProperty(m_internalNode->property(name));
+ model()->d->removePropertyAndRelatedResources(m_internalNode->property(name));
}
/*! \brief removes this node from the node tree
@@ -693,7 +692,7 @@ void ModelNode::destroy()
return;
removeModelNodeFromSelection(*this);
- model()->d->removeNode(m_internalNode);
+ model()->d->removeNodeAndRelatedResources(m_internalNode);
}
//\}
diff --git a/src/plugins/qmldesigner/designercore/model/modelresourcemanagementinterface.h b/src/plugins/qmldesigner/designercore/model/modelresourcemanagementinterface.h
new file mode 100644
index 00000000000..b2188132d6a
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/model/modelresourcemanagementinterface.h
@@ -0,0 +1,39 @@
+// 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 <qmldesignercorelib_exports.h>
+
+#include <bindingproperty.h>
+
+namespace QmlDesigner {
+
+struct ModelResourceSet
+{
+ struct SetExpression
+ {
+ BindingProperty property;
+ QString expression;
+ };
+
+ QList<ModelNode> removeModelNodes;
+ QList<AbstractProperty> removeProperties;
+ QList<SetExpression> setExpressions;
+};
+
+class QMLDESIGNERCORE_EXPORT ModelResourceManagementInterface
+{
+public:
+ ModelResourceManagementInterface() = default;
+ virtual ~ModelResourceManagementInterface() = default;
+
+ ModelResourceManagementInterface(const ModelResourceManagementInterface &) = delete;
+ ModelResourceManagementInterface &operator=(const ModelResourceManagementInterface &) = delete;
+ ModelResourceManagementInterface(ModelResourceManagementInterface &&) = default;
+ ModelResourceManagementInterface &operator=(ModelResourceManagementInterface &&) = default;
+
+ virtual ModelResourceSet removeNode(const ModelNode &node) const = 0;
+ virtual ModelResourceSet removeProperty(const AbstractProperty &property) const = 0;
+};
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/model/modelutils.cpp b/src/plugins/qmldesigner/designercore/model/modelutils.cpp
new file mode 100644
index 00000000000..2e454527b88
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/model/modelutils.cpp
@@ -0,0 +1,93 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "modelutils.h"
+
+#include <utils/expected.h>
+
+#include <algorithm>
+
+namespace QmlDesigner::Utils {
+
+namespace {
+
+enum class ImportError { EmptyImportName, HasAlreadyImport, NoModule };
+
+::Utils::expected<Import, ImportError> findImport(const QString &importName,
+ const std::function<bool(const Import &)> &predicate,
+ const Imports &imports,
+ const Imports &modules)
+{
+ if (importName.isEmpty())
+ return ::Utils::make_unexpected(ImportError::EmptyImportName);
+
+ auto hasName = [&](const auto &import) {
+ return import.url() == importName || import.file() == importName;
+ };
+
+ bool hasImport = std::any_of(imports.begin(), imports.end(), hasName);
+
+ if (hasImport)
+ return ::Utils::make_unexpected(ImportError::HasAlreadyImport);
+
+ auto foundModule = std::find_if(modules.begin(), modules.end(), [&](const Import &import) {
+ return hasName(import) && predicate(import);
+ });
+
+ if (foundModule == modules.end())
+ return ::Utils::make_unexpected(ImportError::NoModule);
+
+ return *foundModule;
+}
+
+} // namespace
+
+bool addImportWithCheck(const QString &importName,
+ const std::function<bool(const Import &)> &predicate,
+ Model *model)
+{
+ return addImportsWithCheck({importName}, predicate, model);
+}
+
+bool addImportWithCheck(const QString &importName, Model *model)
+{
+ return addImportWithCheck(
+ importName, [](const Import &) { return true; }, model);
+}
+
+bool addImportsWithCheck(const QStringList &importNames, Model *model)
+{
+ return addImportsWithCheck(
+ importNames, [](const Import &) { return true; }, model);
+}
+
+bool addImportsWithCheck(const QStringList &importNames,
+ const std::function<bool(const Import &)> &predicate,
+ Model *model)
+{
+ const Imports &imports = model->imports();
+ const Imports &modules = model->possibleImports();
+
+ Imports importsToAdd;
+ importsToAdd.reserve(importNames.size());
+
+ for (const QString &importName : importNames) {
+ auto import = findImport(importName, predicate, imports, modules);
+
+ if (import) {
+ importsToAdd.push_back(*import);
+ } else {
+ if (import.error() == ImportError::NoModule)
+ return false;
+ else
+ continue;
+ }
+ }
+
+ if (!importsToAdd.isEmpty())
+ model->changeImports(std::move(importsToAdd), {});
+
+ return true;
+}
+
+} // namespace QmlDesigner::Utils
diff --git a/src/plugins/qmldesigner/designercore/model/modelutils.h b/src/plugins/qmldesigner/designercore/model/modelutils.h
new file mode 100644
index 00000000000..58055f39065
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/model/modelutils.h
@@ -0,0 +1,24 @@
+// 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 "qmldesignercorelib_global.h"
+
+#include <import.h>
+#include <model.h>
+
+#include <functional>
+
+namespace QmlDesigner::Utils {
+
+QMLDESIGNERCORE_EXPORT bool addImportsWithCheck(const QStringList &importNames,
+ const std::function<bool(const Import &)> &predicate,
+ Model *model);
+QMLDESIGNERCORE_EXPORT bool addImportsWithCheck(const QStringList &importNames, Model *model);
+QMLDESIGNERCORE_EXPORT bool addImportWithCheck(const QString &importName,
+ const std::function<bool(const Import &)> &predicate,
+ Model *model);
+QMLDESIGNERCORE_EXPORT bool addImportWithCheck(const QString &importName, Model *model);
+
+} // namespace QmlDesigner::Utils
diff --git a/src/plugins/qmldesigner/designercore/model/nodeabstractproperty.cpp b/src/plugins/qmldesigner/designercore/model/nodeabstractproperty.cpp
index e2ef9d76f06..60b4e77dc6d 100644
--- a/src/plugins/qmldesigner/designercore/model/nodeabstractproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/nodeabstractproperty.cpp
@@ -71,7 +71,7 @@ void NodeAbstractProperty::reparentHere(const ModelNode &modelNode, bool isNode
return;
if (internalNode()->hasProperty(name()) && !internalNode()->property(name())->isNodeAbstractProperty())
- privateModel()->removeProperty(internalNode()->property(name()));
+ privateModel()->removePropertyAndRelatedResources(internalNode()->property(name()));
if (modelNode.hasParentProperty()) {
Internal::InternalNodeAbstractProperty::Pointer oldParentProperty = modelNode.internalNode()->parentProperty();
diff --git a/src/plugins/qmldesigner/designercore/model/nodeproperty.cpp b/src/plugins/qmldesigner/designercore/model/nodeproperty.cpp
index a9cc7a34f54..4af8428e6be 100644
--- a/src/plugins/qmldesigner/designercore/model/nodeproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/nodeproperty.cpp
@@ -32,7 +32,7 @@ void NodeProperty::setModelNode(const ModelNode &modelNode)
}
if (internalNode()->hasProperty(name()) && !internalNode()->property(name())->isNodeProperty())
- privateModel()->removeProperty(internalNode()->property(name()));
+ privateModel()->removePropertyAndRelatedResources(internalNode()->property(name()));
privateModel()->reparentNode(internalNode(), name(), modelNode.internalNode(), false); //### we have to add a flag that this is not a list
}
diff --git a/src/plugins/qmldesigner/designercore/model/plaintexteditmodifier.cpp b/src/plugins/qmldesigner/designercore/model/plaintexteditmodifier.cpp
index 2318c3f2cf0..a1f88b3a687 100644
--- a/src/plugins/qmldesigner/designercore/model/plaintexteditmodifier.cpp
+++ b/src/plugins/qmldesigner/designercore/model/plaintexteditmodifier.cpp
@@ -3,12 +3,16 @@
#include "plaintexteditmodifier.h"
-#include <utils/changeset.h>
#include <qmljs/qmljsmodelmanagerinterface.h>
-#include <QPlainTextEdit>
+#include <qmljstools/qmljscodestylepreferences.h>
+#include <qmljstools/qmljsindenter.h>
+#include <qmljstools/qmljstoolssettings.h>
+
+#include <utils/changeset.h>
#include <QDebug>
+#include <QPlainTextEdit>
using namespace Utils;
using namespace QmlDesigner;
@@ -161,3 +165,41 @@ void PlainTextEditModifier::reactivateChangeSignals()
emit textChanged();
}
}
+
+IndentingTextEditModifier::IndentingTextEditModifier(QTextDocument *document, const QTextCursor &textCursor)
+ : NotIndentingTextEditModifier{document, textCursor}
+{
+ m_tabSettings = QmlJSTools::QmlJSToolsSettings::globalCodeStyle()->tabSettings();
+}
+
+void IndentingTextEditModifier::indent(int offset, int length)
+{
+ if (length == 0 || offset < 0 || offset + length >= text().length())
+ return;
+
+ int startLine = getLineInDocument(textDocument(), offset);
+ int endLine = getLineInDocument(textDocument(), offset + length);
+
+ if (startLine > -1 && endLine > -1)
+ indentLines(startLine, endLine);
+}
+
+void IndentingTextEditModifier::indentLines(int startLine, int endLine)
+{
+ if (startLine < 0)
+ return;
+
+ QTextCursor tc(textDocument());
+
+ tc.beginEditBlock();
+ for (int i = startLine; i <= endLine; i++) {
+ QTextBlock start = textDocument()->findBlockByNumber(i);
+
+ if (start.isValid()) {
+ QmlJSEditor::Internal::Indenter indenter(textDocument());
+ indenter.indentBlock(start, QChar::Null, m_tabSettings);
+ }
+ }
+ tc.endEditBlock();
+}
+
diff --git a/src/plugins/qmldesigner/designercore/model/qmlchangeset.cpp b/src/plugins/qmldesigner/designercore/model/qmlchangeset.cpp
index 5029fdc79d3..134c4bf1c20 100644
--- a/src/plugins/qmldesigner/designercore/model/qmlchangeset.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qmlchangeset.cpp
@@ -76,7 +76,7 @@ bool QmlModelStateOperation::isValid() const
bool QmlModelStateOperation::isValidQmlModelStateOperation(const ModelNode &modelNode)
{
- return isValidQmlModelNodeFacade(modelNode) && modelNode.metaInfo().isQuickStateOperation();
+ return isValidQmlModelNodeFacade(modelNode) && modelNode.metaInfo().isQtQuickStateOperation();
}
void QmlPropertyChanges::removeProperty(const PropertyName &name)
diff --git a/src/plugins/qmldesigner/designercore/model/qmlmodelnodefacade.cpp b/src/plugins/qmldesigner/designercore/model/qmlmodelnodefacade.cpp
index 47699eae468..7e3bc793247 100644
--- a/src/plugins/qmldesigner/designercore/model/qmlmodelnodefacade.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qmlmodelnodefacade.cpp
@@ -29,8 +29,6 @@ const NodeInstanceView *QmlModelNodeFacade::nodeInstanceView() const
return nodeInstanceView(m_modelNode);
}
-QmlModelNodeFacade::~QmlModelNodeFacade() = default;
-
bool QmlModelNodeFacade::hasModelNode() const
{
return m_modelNode.isValid();
diff --git a/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp
index c3ee4b975f7..3831a90d97c 100644
--- a/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp
@@ -291,6 +291,7 @@ static QmlObjectNode createQmlObjectNodeFromSource(AbstractView *view,
rewriterView->setCheckSemanticErrors(false);
rewriterView->setTextModifier(&modifier);
rewriterView->setAllowComponentRoot(true);
+ rewriterView->setPossibleImportsEnabled(false);
inputModel->setRewriterView(rewriterView.data());
if (rewriterView->errors().isEmpty() && rewriterView->rootModelNode().isValid()) {
diff --git a/src/plugins/qmldesigner/designercore/model/rewriterview.cpp b/src/plugins/qmldesigner/designercore/model/rewriterview.cpp
index d8088de64be..53a0f4de596 100644
--- a/src/plugins/qmldesigner/designercore/model/rewriterview.cpp
+++ b/src/plugins/qmldesigner/designercore/model/rewriterview.cpp
@@ -261,7 +261,7 @@ void RewriterView::nodeReparented(const ModelNode &node, const NodeAbstractPrope
applyChanges();
}
-void RewriterView::importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports)
+void RewriterView::importsChanged(const Imports &addedImports, const Imports &removedImports)
{
for (const Import &import : addedImports)
importAdded(import);
diff --git a/src/plugins/qmldesigner/designercore/model/signalhandlerproperty.cpp b/src/plugins/qmldesigner/designercore/model/signalhandlerproperty.cpp
index 205105187d1..4690044fa61 100644
--- a/src/plugins/qmldesigner/designercore/model/signalhandlerproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/signalhandlerproperty.cpp
@@ -41,7 +41,7 @@ void SignalHandlerProperty::setSource(const QString &source)
}
if (internalNode()->hasProperty(name()) && !internalNode()->property(name())->isSignalHandlerProperty())
- privateModel()->removeProperty(internalNode()->property(name()));
+ privateModel()->removePropertyAndRelatedResources(internalNode()->property(name()));
privateModel()->setSignalHandlerProperty(internalNode(), name(), source);
}
@@ -118,7 +118,7 @@ void SignalDeclarationProperty::setSignature(const QString &signature)
}
if (internalNode()->hasProperty(name()) && !internalNode()->property(name())->isSignalDeclarationProperty())
- privateModel()->removeProperty(internalNode()->property(name()));
+ privateModel()->removePropertyAndRelatedResources(internalNode()->property(name()));
privateModel()->setSignalDeclarationProperty(internalNode(), name(), signature);
}
diff --git a/src/plugins/qmldesigner/designercore/model/skipiterator.h b/src/plugins/qmldesigner/designercore/model/skipiterator.h
new file mode 100644
index 00000000000..11efb7d97f0
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/model/skipiterator.h
@@ -0,0 +1,77 @@
+// 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 <iterator>
+
+namespace QmlDesigner {
+
+template<typename BaseIterator, typename Increment>
+class SkipIterator
+{
+public:
+ using iterator_category = std::forward_iterator_tag;
+ using difference_type = qsizetype;
+ using value_type = typename BaseIterator::value_type;
+ using pointer = typename BaseIterator::pointer;
+ using reference = typename BaseIterator::reference;
+
+ SkipIterator() = default;
+ SkipIterator(BaseIterator current, Increment increment)
+ : m_current{current}
+ , m_increment{std::move(increment)}
+ {}
+
+ SkipIterator operator++()
+ {
+ m_current = m_increment(m_current);
+ return *this;
+ }
+
+ SkipIterator operator++(int)
+ {
+ auto tmp = *this;
+ m_current = m_increment(m_current);
+ return tmp;
+ }
+
+ reference operator*() const { return *m_current; }
+ pointer operator->() const { return m_current.operator->(); }
+
+ friend bool operator==(const SkipIterator &first, const SkipIterator &second)
+ {
+ return first.m_current == second.m_current;
+ }
+
+ friend bool operator!=(const SkipIterator &first, const SkipIterator &second)
+ {
+ return first.m_current != second.m_current;
+ }
+
+private:
+ BaseIterator m_current = {};
+ Increment m_increment;
+};
+
+template<typename Container, typename Increment>
+class SkipRange
+{
+public:
+ using container = Container;
+ using base = SkipRange<Container, Increment>;
+ using iterator = SkipIterator<typename Container::const_iterator, Increment>;
+
+ SkipRange(const Container &container, Increment increment)
+ : m_begin{container.begin(), increment}
+ , m_end{container.end(), increment}
+ {}
+
+ iterator begin() const { return m_begin; }
+ iterator end() const { return m_end; }
+
+private:
+ iterator m_begin;
+ iterator m_end;
+};
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
index 4469793db83..ac89c54acd6 100644
--- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
+++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
@@ -19,6 +19,8 @@
#include "signalhandlerproperty.h"
#include "variantproperty.h"
#include <externaldependenciesinterface.h>
+#include <import.h>
+#include <projectstorage/modulescanner.h>
#include <rewritingexception.h>
#include <enumeration.h>
@@ -44,6 +46,7 @@
#include <QSet>
#include <memory>
+#include <tuple>
using namespace LanguageUtils;
using namespace QmlJS;
@@ -59,12 +62,15 @@ bool isSupportedAttachedProperties(const QString &propertyName)
|| propertyName.startsWith(QLatin1String("InsightCategory."));
}
-QStringList supportedVersionsList()
+bool isSupportedVersion(QmlDesigner::Version version)
{
- static const QStringList list = {"2.0", "2.1", "2.2", "2.3", "2.4", "2.5", "2.6",
- "2.7", "2.8", "2.9", "2.10", "2.11", "2.12", "2.13",
- "2.14", "2.15", "6.0", "6.1", "6.2", "6.3", "6.4"};
- return list;
+ if (version.major == 2)
+ return version.minor <= 15;
+
+ if (version.major == 6)
+ return version.minor <= 5;
+
+ return false;
}
QStringList globalQtEnums()
@@ -99,13 +105,15 @@ QStringList knownEnumScopes()
"Grid",
"ItemLayer",
"ImageLayer",
- "SpriteLayer"};
+ "SpriteLayer",
+ "Light"};
return list;
}
-bool supportedQtQuickVersion(const QString &version)
+bool supportedQtQuickVersion(const QmlDesigner::Import &import)
{
- return version.isEmpty() || supportedVersionsList().contains(version);
+ auto version = import.toVersion();
+ return version.isEmpty() || isSupportedVersion(version);
}
QString stripQuotes(const QString &str)
@@ -117,7 +125,7 @@ QString stripQuotes(const QString &str)
return str;
}
-inline QString deEscape(const QString &value)
+QString deEscape(const QString &value)
{
QString result = value;
@@ -282,7 +290,7 @@ bool isComponentType(const QmlDesigner::TypeName &type)
{
return type == "Component" || type == "Qt.Component" || type == "QtQuick.Component"
|| type == "QtQml.Component" || type == "<cpp>.QQmlComponent" || type == "QQmlComponent"
- || type == "QML.Component";
+ || type == "QML.Component" || type == "QtQml.Base.Component";
}
bool isCustomParserType(const QmlDesigner::TypeName &type)
@@ -302,7 +310,8 @@ bool isPropertyChangesType(const QmlDesigner::TypeName &type)
bool isConnectionsType(const QmlDesigner::TypeName &type)
{
- return type == "Connections" || type == "QtQuick.Connections" || type == "Qt.Connections" || type == "QtQml.Connections";
+ return type == "Connections" || type == "QtQuick.Connections" || type == "Qt.Connections"
+ || type == "QtQml.Connections" || type == "QtQml.Base.Connections";
}
bool propertyIsComponentType(const QmlDesigner::NodeAbstractProperty &property, const QmlDesigner::TypeName &type, QmlDesigner::Model *model)
@@ -716,7 +725,7 @@ bool TextToModelMerger::isActive() const
void TextToModelMerger::setupImports(const Document::Ptr &doc,
DifferenceHandler &differenceHandler)
{
- QList<Import> existingImports = m_rewriterView->model()->imports();
+ Imports existingImports = m_rewriterView->model()->imports();
m_hasVersionlessImport = false;
@@ -756,162 +765,143 @@ void TextToModelMerger::setupImports(const Document::Ptr &doc,
differenceHandler.importAbsentInQMl(import);
}
-static bool isLatestImportVersion(const ImportKey &importKey, const QHash<QString, ImportKey> &filteredPossibleImportKeys)
+namespace {
+
+bool skipByMetaInfo(QStringView moduleName, const QStringList &skipModuleNames)
{
- return !filteredPossibleImportKeys.contains(importKey.path())
- || filteredPossibleImportKeys.value(importKey.path()).majorVersion < importKey.majorVersion
- || (filteredPossibleImportKeys.value(importKey.path()).majorVersion == importKey.majorVersion
- && filteredPossibleImportKeys.value(importKey.path()).minorVersion < importKey.minorVersion);
+ return std::any_of(skipModuleNames.begin(),
+ skipModuleNames.end(),
+ [&](const QString &skipModuleName) {
+ return moduleName.contains(skipModuleName);
+ });
}
-static bool filterByMetaInfo(const ImportKey &importKey, Model *model)
+class StartsWith : public QStringView
{
- if (model) {
- for (const QString &filter : model->metaInfo().itemLibraryInfo()->blacklistImports()) {
- if (importKey.libraryQualifiedPath().contains(filter))
- return true;
- }
+public:
+ using QStringView::QStringView;
+ bool operator()(QStringView moduleName) const { return moduleName.startsWith(*this); }
+};
+
+class EndsWith : public QStringView
+{
+public:
+ using QStringView::QStringView;
+ bool operator()(QStringView moduleName) const { return moduleName.endsWith(*this); }
+};
+class StartsAndEndsWith : public std::pair<QStringView, QStringView>
+{
+public:
+ using Base = std::pair<QStringView, QStringView>;
+ using Base::Base;
+ bool operator()(QStringView moduleName) const
+ {
+ return moduleName.startsWith(first) && moduleName.endsWith(second);
}
+};
- return false;
-}
+class Equals : public QStringView
+{
+public:
+ using QStringView::QStringView;
+ bool operator()(QStringView moduleName) const { return moduleName == *this; }
+};
-static bool isBlacklistImport(const ImportKey &importKey, Model *model)
-{
- const QString &importPathFirst = importKey.splitPath.constFirst();
- const QString &importPathLast = importKey.splitPath.constLast();
- return importPathFirst == QStringLiteral("<cpp>")
- || importPathFirst == QStringLiteral("QML")
- || importPathFirst == QStringLiteral("QtQml")
- || (importPathFirst == QStringLiteral("QtQuick") && importPathLast == QStringLiteral("PrivateWidgets"))
- || importPathLast == QStringLiteral("Private")
- || importPathLast == QStringLiteral("private")
- || importKey.libraryQualifiedPath() == QStringLiteral("QtQuick.Particles") //Unsupported
- || importKey.libraryQualifiedPath() == QStringLiteral("QtQuick.Dialogs") //Unsupported
- || importKey.libraryQualifiedPath() == QStringLiteral("QtQuick.Controls.Styles") //Unsupported
- || importKey.libraryQualifiedPath() == QStringLiteral("QtNfc") //Unsupported
- || importKey.libraryQualifiedPath() == QStringLiteral("Qt.WebSockets")
- || importKey.libraryQualifiedPath() == QStringLiteral("QtWebkit")
- || importKey.libraryQualifiedPath() == QStringLiteral("QtLocation")
- || importKey.libraryQualifiedPath() == QStringLiteral("QtWebChannel")
- || importKey.libraryQualifiedPath() == QStringLiteral("QtWinExtras")
- || importKey.libraryQualifiedPath() == QStringLiteral("QtPurchasing")
- || importKey.libraryQualifiedPath() == QStringLiteral("QtBluetooth")
- || importKey.libraryQualifiedPath() == QStringLiteral("Enginio")
-
- || filterByMetaInfo(importKey, model);
-}
-
-static QHash<QString, ImportKey> filterPossibleImportKeys(const QSet<ImportKey> &possibleImportKeys, Model *model)
-{
- QHash<QString, ImportKey> filteredPossibleImportKeys;
- for (const ImportKey &importKey : possibleImportKeys) {
- if (isLatestImportVersion(importKey, filteredPossibleImportKeys) && !isBlacklistImport(importKey, model))
- filteredPossibleImportKeys.insert(importKey.path(), importKey);
- }
+constexpr auto skipModules = std::make_tuple(EndsWith(u".impl"),
+ StartsWith(u"QML"),
+ StartsWith(u"QtQml"),
+ StartsAndEndsWith(u"QtQuick", u".PrivateWidgets"),
+ EndsWith(u".private"),
+ EndsWith(u".Private"),
+ Equals(u"QtQuick.Particles"),
+ Equals(u"QtQuick.Dialogs"),
+ Equals(u"QtQuick.Controls.Styles"),
+ Equals(u"QtNfc"),
+ Equals(u"Qt.WebSockets"),
+ Equals(u"QtWebkit"),
+ Equals(u"QtLocation"),
+ Equals(u"QtWebChannel"),
+ Equals(u"QtWinExtras"),
+ Equals(u"QtPurchasing"),
+ Equals(u"QtBluetooth"),
+ Equals(u"Enginio"));
- return filteredPossibleImportKeys;
+bool skipModule(QStringView moduleName)
+{
+ return std::apply([=](const auto &...skipModule) { return (skipModule(moduleName) || ...); },
+ skipModules);
}
-static void removeUsedImports(QHash<QString, ImportKey> &filteredPossibleImportKeys, const QList<QmlJS::Import> &usedImports)
+bool skipModule(QStringView moduleName, const QStringList &skipModuleNames)
{
- for (const QmlJS::Import &import : usedImports)
- filteredPossibleImportKeys.remove(import.info.path());
+ return skipModule(moduleName) || skipByMetaInfo(moduleName, skipModuleNames);
}
-static QList<QmlDesigner::Import> generatePossibleFileImports(const QString &path,
- const QList<QmlJS::Import> &usedImports)
+void collectPossibleFileImports(const QString &checkPath,
+ QSet<QString> usedImportsSet,
+ QList<QmlDesigner::Import> &possibleImports)
{
- QSet<QString> usedImportsSet;
- for (const QmlJS::Import &i : usedImports)
- usedImportsSet.insert(i.info.path());
-
- QList<QmlDesigner::Import> possibleImports;
const QStringList qmlList("*.qml");
const QStringList qmldirList("qmldir");
-
- QStringList fileImportPaths;
const QChar delimeter('/');
- std::function<void(const QString &)> checkDir;
- checkDir = [&](const QString &checkPath) {
-
- if (QFileInfo(checkPath).isRoot())
- return;
+ if (QFileInfo(checkPath).isRoot())
+ return;
- const QStringList entries = QDir(checkPath).entryList(QDir::Dirs | QDir::NoDot | QDir::NoDotDot);
- const QString checkPathDelim = checkPath + delimeter;
- for (const QString &entry : entries) {
- QDir dir(checkPathDelim + entry);
- const QString dirPath = dir.path();
- if (!dir.entryInfoList(qmlList, QDir::Files).isEmpty()
- && dir.entryInfoList(qmldirList, QDir::Files).isEmpty()
- && !usedImportsSet.contains(dirPath)) {
- const QString importName = dir.path().mid(path.size() + 1);
- QmlDesigner::Import import = QmlDesigner::Import::createFileImport(importName);
- possibleImports.append(import);
- }
- checkDir(dirPath);
+ const QStringList entries = QDir(checkPath).entryList(QDir::Dirs | QDir::NoDot | QDir::NoDotDot);
+ const QString checkPathDelim = checkPath + delimeter;
+ for (const QString &entry : entries) {
+ QDir dir(checkPathDelim + entry);
+ const QString dirPath = dir.path();
+ if (!dir.entryInfoList(qmlList, QDir::Files).isEmpty()
+ && dir.entryInfoList(qmldirList, QDir::Files).isEmpty()
+ && !usedImportsSet.contains(dirPath)) {
+ const QString importName = dir.path().mid(checkPath.size() + 1);
+ QmlDesigner::Import import = QmlDesigner::Import::createFileImport(importName);
+ possibleImports.append(import);
}
- };
- checkDir(path);
-
- return possibleImports;
+ collectPossibleFileImports(dirPath, usedImportsSet, possibleImports);
+ }
}
-static QList<QmlDesigner::Import> generatePossibleLibraryImports(const QHash<QString, ImportKey> &filteredPossibleImportKeys)
+QList<QmlDesigner::Import> generatePossibleFileImports(const QString &path,
+ const QList<QmlJS::Import> &usedImports)
{
- QList<QmlDesigner::Import> possibleImports;
- QSet<QString> controlsImplVersions;
- bool hasVersionedControls = false;
- bool hasVersionlessControls = false;
- const QString controlsName = "QtQuick.Controls";
- const QString controlsImplName = "QtQuick.Controls.impl";
-
- for (const ImportKey &importKey : filteredPossibleImportKeys) {
- QString libraryName = importKey.splitPath.join(QLatin1Char('.'));
- int majorVersion = importKey.majorVersion;
- if (majorVersion >= 0) {
- int minorVersion = (importKey.minorVersion == LanguageUtils::ComponentVersion::NoVersion) ? 0 : importKey.minorVersion;
-
- if (libraryName.contains("QtQuick.Studio")) {
- majorVersion = 1;
- minorVersion = 0;
- }
+ QSet<QString> usedImportsSet;
+ for (const QmlJS::Import &i : usedImports)
+ usedImportsSet.insert(i.info.path());
- QString version = QStringLiteral("%1.%2").arg(majorVersion).arg(minorVersion);
- if (!libraryName.endsWith(".impl"))
- possibleImports.append(QmlDesigner::Import::createLibraryImport(libraryName, version));
-
- // In Qt6, QtQuick.Controls itself doesn't have any version as it has no types,
- // so it never gets added normally to possible imports.
- // We work around this by injecting corresponding QtQuick.Controls version for each
- // found impl version, if no valid QtQuick.Controls versions are found.
- if (!hasVersionedControls) {
- if (libraryName == controlsImplName)
- controlsImplVersions.insert(version);
- else if (libraryName == controlsName)
- hasVersionedControls = true;
- }
- } else if (!hasVersionlessControls && libraryName == controlsName) {
- // If QtQuick.Controls module is not included even in non-versioned, it means
- // QtQuick.Controls is either in use or not available at all,
- // so we shouldn't inject it.
- hasVersionlessControls = true;
- }
- }
+ QList<QmlDesigner::Import> possibleImports;
- if (hasVersionlessControls && !hasVersionedControls && !controlsImplVersions.isEmpty()) {
- for (const auto &version : std::as_const(controlsImplVersions))
- possibleImports.append(QmlDesigner::Import::createLibraryImport(controlsName, version));
- }
+ QStringList fileImportPaths;
+ collectPossibleFileImports(path, usedImportsSet, possibleImports);
return possibleImports;
}
-void TextToModelMerger::setupPossibleImports(const QmlJS::Snapshot &snapshot, const QmlJS::ViewerContext &viewContext)
+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"),
+ QmlDesigner::Import::createLibraryImport("QtQuick.Timeline", "5.15"),
+ QmlDesigner::Import::createLibraryImport("QtCharts", "5.15"),
+ QmlDesigner::Import::createLibraryImport("QtDataVisulaization", "5.15"),
+ QmlDesigner::Import::createLibraryImport("QtQuick.Studio.Controls", "1.0"),
+ QmlDesigner::Import::createLibraryImport("QtQuick.Studio.Effects", "1.0"),
+ QmlDesigner::Import::createLibraryImport("FlowView", "1.0"),
+ QmlDesigner::Import::createLibraryImport("QtQuick.Studio.LogicHelper", "1.0"),
+ QmlDesigner::Import::createLibraryImport("QtQuick.Studio.MultiText", "1.0"),
+ QmlDesigner::Import::createLibraryImport("Qt.SafeRenderer", "2.0")};
+}
+
+} // namespace
+
+void TextToModelMerger::setupPossibleImports()
{
if (!m_rewriterView->possibleImportsEnabled())
return;
@@ -919,27 +909,42 @@ void TextToModelMerger::setupPossibleImports(const QmlJS::Snapshot &snapshot, co
static QUrl lastProjectUrl;
auto &externalDependencies = m_rewriterView->externalDependencies();
auto projectUrl = externalDependencies.projectUrl();
-
- if (m_possibleImportKeys.isEmpty() || projectUrl != lastProjectUrl)
- m_possibleImportKeys = snapshot.importDependencies()->libraryImports(viewContext);
+ auto allUsedImports = m_scopeChain->context()->imports(m_document.data())->all();
+
+ if (m_possibleModules.isEmpty() || projectUrl != lastProjectUrl) {
+
+ auto &externalDependencies = m_rewriterView->externalDependencies();
+ if (externalDependencies.isQt6Project()) {
+ const auto skipModuleNames = m_rewriterView->model()
+ ->metaInfo()
+ .itemLibraryInfo()
+ ->blacklistImports();
+ ModuleScanner moduleScanner{[&](QStringView moduleName) {
+ return skipModule(moduleName, skipModuleNames);
+ },
+ VersionScanning::No,
+ m_rewriterView->externalDependencies()};
+ moduleScanner.scan(m_rewriterView->externalDependencies().modulePaths());
+ m_possibleModules = moduleScanner.modules();
+ } else {
+ ModuleScanner moduleScanner{[&](QStringView) { return false; },
+ VersionScanning::Yes,
+ m_rewriterView->externalDependencies()};
+ m_possibleModules = createQt5Modules();
+ moduleScanner.scan(externalDependencies.projectModulePaths());
+ m_possibleModules.append(moduleScanner.modules());
+ }
+ }
lastProjectUrl = projectUrl;
- QHash<QString, ImportKey> filteredPossibleImportKeys = filterPossibleImportKeys(
- m_possibleImportKeys, m_rewriterView->model());
-
- const QmlJS::Imports *imports = m_scopeChain->context()->imports(m_document.data());
- if (imports)
- removeUsedImports(filteredPossibleImportKeys, imports->all());
-
- QList<QmlDesigner::Import> possibleImports = generatePossibleLibraryImports(filteredPossibleImportKeys);
+ auto modules = m_possibleModules;
if (document()->fileName() != "<internal>")
- possibleImports.append(
- generatePossibleFileImports(document()->path().toString(), imports->all()));
+ modules.append(generatePossibleFileImports(document()->path().toString(), allUsedImports));
if (m_rewriterView->isAttached())
- m_rewriterView->model()->setPossibleImports(possibleImports);
+ m_rewriterView->model()->setPossibleImports(modules);
}
void TextToModelMerger::setupUsedImports()
@@ -951,7 +956,7 @@ void TextToModelMerger::setupUsedImports()
const QList<QmlJS::Import> allImports = imports->all();
QSet<QString> usedImportsSet;
- QList<Import> usedImports;
+ Imports usedImports;
// populate usedImportsSet from current model nodes
const QList<ModelNode> allModelNodes = m_rewriterView->allModelNodes();
@@ -964,9 +969,6 @@ void TextToModelMerger::setupUsedImports()
for (const QmlJS::Import &import : allImports) {
QString version = import.info.version().toString();
- if (!import.info.version().isValid())
- version = getHighestPossibleImport(import.info.name());
-
if (!import.info.name().isEmpty() && usedImportsSet.contains(import.info.name())) {
if (import.info.type() == ImportType::Library)
usedImports.append(
@@ -1077,7 +1079,7 @@ bool TextToModelMerger::load(const QString &data, DifferenceHandler &differenceH
collectLinkErrors(&errors, ctxt);
}
- setupPossibleImports(snapshot, m_vContext);
+ setupPossibleImports();
qCInfo(rewriterBenchmark) << "possible imports:" << time.elapsed();
@@ -1115,12 +1117,6 @@ bool TextToModelMerger::load(const QString &data, DifferenceHandler &differenceH
setActive(false);
- // Clear possible imports cache if code model hasn't settled yet
- const int importKeysSize = m_possibleImportKeys.size();
- if (m_previousPossibleImportsSize != importKeysSize)
- m_possibleImportKeys.clear();
- m_previousPossibleImportsSize = importKeysSize;
-
return true;
} catch (Exception &e) {
DocumentMessage error(&e);
@@ -2174,13 +2170,12 @@ void TextToModelMerger::collectImportErrors(QList<DocumentMessage> *errors)
bool hasQtQuick = false;
for (const QmlDesigner::Import &import : m_rewriterView->model()->imports()) {
if (import.isLibraryImport() && import.url() == QStringLiteral("QtQuick")) {
-
- if (supportedQtQuickVersion(import.version())) {
+ if (supportedQtQuickVersion(import)) {
hasQtQuick = true;
auto &externalDependencies = m_rewriterView->externalDependencies();
if (externalDependencies.hasStartupTarget()) {
- const bool qt6import = import.version().startsWith("6");
+ const bool qt6import = !import.hasVersion() || import.majorVersion() == 6;
if (!externalDependencies.isQt6Import() && (m_hasVersionlessImport || qt6import)) {
const QmlJS::DiagnosticMessage diagnosticMessage(
@@ -2387,8 +2382,8 @@ QList<QmlTypeData> TextToModelMerger::getQMLSingletons() const
void TextToModelMerger::clearPossibleImportKeys()
{
- m_possibleImportKeys.clear();
- m_previousPossibleImportsSize = -1;
+ m_possibleModules.clear();
+ m_previousPossibleModulesSize = -1;
}
QString TextToModelMerger::textAt(const Document::Ptr &doc,
@@ -2403,19 +2398,3 @@ QString TextToModelMerger::textAt(const Document::Ptr &doc,
{
return doc->source().mid(from.offset, to.end() - from.begin());
}
-
-QString TextToModelMerger::getHighestPossibleImport(const QString &importName) const
-{
- QString version = "2.15";
- int maj = -1;
- const auto imports = m_possibleImportKeys.values();
- for (const ImportKey &import : imports) {
- if (importName == import.libraryQualifiedPath()) {
- if (import.majorVersion > maj) {
- version = QString("%1.%2").arg(import.majorVersion).arg(import.minorVersion);
- maj = import.majorVersion;
- }
- }
- }
- return version;
-}
diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h
index 5ed2e24c7a4..50b3a423678 100644
--- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h
+++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h
@@ -37,7 +37,7 @@ public:
bool isActive() const;
void setupImports(const QmlJS::Document::Ptr &doc, DifferenceHandler &differenceHandler);
- void setupPossibleImports(const QmlJS::Snapshot &snapshot, const QmlJS::ViewerContext &viewContext);
+ void setupPossibleImports();
void setupUsedImports();
bool load(const QString &data, DifferenceHandler &differenceHandler);
@@ -137,8 +137,6 @@ private:
const QmlJS::SourceLocation &from,
const QmlJS::SourceLocation &to);
- QString getHighestPossibleImport(const QString &importName) const;
-
private:
RewriterView *m_rewriterView;
bool m_isActive;
@@ -150,8 +148,8 @@ private:
QSet<ModelNode> m_clearImplicitComponentList;
QmlJS::ViewerContext m_vContext;
QSet<QPair<QString, QString> > m_qrcMapping;
- QSet<QmlJS::ImportKey> m_possibleImportKeys;
- int m_previousPossibleImportsSize = -1;
+ Imports m_possibleModules;
+ int m_previousPossibleModulesSize = -1;
bool m_hasVersionlessImport = false;
};
diff --git a/src/plugins/qmldesigner/designercore/model/variantproperty.cpp b/src/plugins/qmldesigner/designercore/model/variantproperty.cpp
index 48d0fa86300..c879ec7a347 100644
--- a/src/plugins/qmldesigner/designercore/model/variantproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/variantproperty.cpp
@@ -47,7 +47,7 @@ void VariantProperty::setValue(const QVariant &value)
}
if (internalNode()->hasProperty(name()) && !internalNode()->property(name())->isVariantProperty())
- privateModel()->removeProperty(internalNode()->property(name()));
+ privateModel()->removePropertyAndRelatedResources(internalNode()->property(name()));
privateModel()->setVariantProperty(internalNode(), name(), value);
}
@@ -96,7 +96,7 @@ void VariantProperty::setDynamicTypeNameAndValue(const TypeName &type, const QVa
}
if (internalNode()->hasProperty(name()) && !internalNode()->property(name())->isVariantProperty())
- privateModel()->removeProperty(internalNode()->property(name()));
+ privateModel()->removePropertyAndRelatedResources(internalNode()->property(name()));
privateModel()->setDynamicVariantProperty(internalNode(), name(), type, value);
}
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/commontypecache.h b/src/plugins/qmldesigner/designercore/projectstorage/commontypecache.h
index 3cd7f3a0167..0db44e3df76 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/commontypecache.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/commontypecache.h
@@ -49,6 +49,7 @@ inline constexpr char GroupItem[] = "GroupItem";
inline constexpr char Image[] = "Image";
inline constexpr char InstanceListEntry[] = "InstanceListEntry";
inline constexpr char InstanceList[] = "InstanceList";
+inline constexpr char Light[] = "Light";
inline constexpr char IntType[] = "int";
inline constexpr char Item[] = "Item";
inline constexpr char KeyframeGroup[] = "KeyframeGroup";
@@ -83,6 +84,7 @@ inline constexpr char QtQuick3D[] = "QtQuick3D";
inline constexpr char QtQuick3D_Particles3D[] = "QtQuick3D.Particles3D";
inline constexpr char QtQuick3D_Particles3D_cppnative[] = "QtQuick3D.Particles3D-cppnative";
inline constexpr char QtQuick[] = "QtQuick";
+inline constexpr char QtQuick_cppnative[] = "QtQuick-cppnative";
inline constexpr char QtQuick_Controls[] = "QtQuick.Controls";
inline constexpr char QtQuick_Dialogs[] = "QtQuick.Dialogs";
inline constexpr char QtQuick_Extras[] = "QtQuick.Extras";
@@ -90,9 +92,7 @@ inline constexpr char QtQuick_Layouts[] = "QtQuick.Layouts";
inline constexpr char QtQuick_Studio_Components[] = "QtQuick.Studio.Components";
inline constexpr char QtQuick_Timeline[] = "QtQuick.Timeline";
inline constexpr char QtQuick_Window[] = "QtQuick.Window";
-inline constexpr char QtQuick_cppnative[] = "QtQuick-cppnative";
inline constexpr char Qt_SafeRenderer[] = "Qt.SafeRenderer";
-inline constexpr char QuickStateOperation[] = "QuickStateOperation";
inline constexpr char Rectangle[] = "Rectangle";
inline constexpr char Repeater[] = "Repeater";
inline constexpr char SafePicture[] = "SafePicture";
@@ -158,7 +158,6 @@ class CommonTypeCache
CacheType<QML, url>,
CacheType<QML, var>,
CacheType<QML_cppnative, FloatType>,
- CacheType<QML_cppnative, QQuickStateOperation>,
CacheType<QtMultimedia, SoundEffect>,
CacheType<QtQuick, BorderImage>,
CacheType<QtQuick, Connections>,
@@ -194,12 +193,14 @@ class CommonTypeCache
CacheType<QtQuick3D, Effect>,
CacheType<QtQuick3D, InstanceList>,
CacheType<QtQuick3D, InstanceListEntry>,
+ CacheType<QtQuick3D, Light>,
CacheType<QtQuick3D, Material>,
CacheType<QtQuick3D, Model>,
CacheType<QtQuick3D, Node>,
CacheType<QtQuick3D, Pass>,
CacheType<QtQuick3D, PrincipledMaterial>,
CacheType<QtQuick3D, SceneEnvironment>,
+ CacheType<QtQuick3D, SpecularGlossyMaterial>,
CacheType<QtQuick3D, Shader>,
CacheType<QtQuick3D, Texture>,
CacheType<QtQuick3D, TextureInput>,
@@ -226,7 +227,7 @@ class CommonTypeCache
CacheType<QtQuick_Timeline, KeyframeGroup>,
CacheType<QtQuick_Timeline, Timeline>,
CacheType<QtQuick_Timeline, TimelineAnimation>,
- CacheType<QtQuick_cppnative, QuickStateOperation>,
+ CacheType<QtQuick_cppnative, QQuickStateOperation>,
CacheType<Qt_SafeRenderer, SafePicture>,
CacheType<Qt_SafeRenderer, SafeRendererPicture>,
CacheType<QtQuick_Window, Window>>;
@@ -242,15 +243,13 @@ public:
}
TypeId refreshTypedId(BaseCacheType &type,
- Utils::SmallStringView moduleName,
- Utils::SmallStringView typeName) const
+ ::Utils::SmallStringView moduleName,
+ ::Utils::SmallStringView typeName) const
{
if (!type.moduleId)
type.moduleId = m_projectStorage.moduleId(moduleName);
- type.typeId = m_projectStorage.typeId(type.moduleId,
- typeName,
- QmlDesigner::Storage::Synchronization::Version{});
+ type.typeId = m_projectStorage.typeId(type.moduleId, typeName, QmlDesigner::Storage::Version{});
return type.typeId;
}
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/modulescanner.cpp b/src/plugins/qmldesigner/designercore/projectstorage/modulescanner.cpp
new file mode 100644
index 00000000000..c458d8376b9
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/projectstorage/modulescanner.cpp
@@ -0,0 +1,110 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "modulescanner.h"
+
+#include <private/qqmldirparser_p.h>
+
+#include <QDirIterator>
+#include <QFile>
+#include <QHash>
+
+namespace QmlDesigner {
+
+namespace {
+
+std::optional<QString> contentAsQString(const QString &filePath)
+{
+ QFile file{filePath};
+ if (file.open(QIODevice::ReadOnly))
+ return {QString::fromUtf8(file.readAll())};
+
+ return {};
+}
+
+QString createVersion(const QMultiHash<QString, QQmlDirParser::Component> &components)
+{
+ auto found = std::max_element(components.begin(), components.end(), [](auto &&first, auto &&second) {
+ return first.version < second.version;
+ });
+
+ if (found != components.end() && found->version.isValid())
+ return QString{"%1.%2"}.arg(found->version.majorVersion()).arg(found->version.minorVersion());
+
+ return {};
+}
+
+constexpr auto coreModules = std::make_tuple(QStringView{u"QtQuick"},
+ QStringView{u"QtQuick.Controls"},
+ QStringView{u"QtQuick3D"},
+ QStringView{u"QtQuick3D.Helpers"},
+ QStringView{u"QtQuick3D.Particles3D"});
+
+bool isCoreVersion(QStringView moduleName)
+{
+ return std::apply([=](auto... coreModuleName) { return ((moduleName == coreModuleName) || ...); },
+ coreModules);
+}
+
+QString createCoreVersion(QStringView moduleName, ExternalDependenciesInterface &externalDependencies)
+{
+ if (isCoreVersion(moduleName))
+ return externalDependencies.qtQuickVersion();
+
+ return {};
+}
+
+} // namespace
+
+void ModuleScanner::scan(const QStringList &modulePaths)
+{
+ for (const QString &modulePath : modulePaths)
+ scan(modulePath.toStdString());
+}
+
+void ModuleScanner::scan([[maybe_unused]] std::string_view modulePath)
+{
+ if (modulePath.empty())
+ return;
+
+ QDirIterator dirIterator{QString::fromUtf8(modulePath),
+ QDir::Dirs | QDir::NoDotAndDotDot,
+ QDirIterator::Subdirectories};
+
+ while (dirIterator.hasNext()) {
+ auto directoryPath = dirIterator.next();
+ QString qmldirPath = directoryPath + "/qmldir";
+ if (QFileInfo::exists(qmldirPath)) {
+ QQmlDirParser parser;
+
+ auto content = contentAsQString(qmldirPath);
+ if (!content)
+ continue;
+
+ bool hasError = parser.parse(*content);
+ if (hasError)
+ continue;
+
+ auto moduleName = parser.typeNamespace();
+
+ if (moduleName.isEmpty() || m_skip(moduleName))
+ continue;
+
+ QString version = m_versionScanning == VersionScanning::Yes
+ ? createVersion(parser.components())
+ : QString{};
+
+ QString coreModuleVersion = createCoreVersion(moduleName, m_externalDependencies);
+
+ if (!coreModuleVersion.isEmpty())
+ version = coreModuleVersion;
+
+ m_modules.push_back(Import::createLibraryImport(moduleName, version));
+ }
+ }
+
+ std::sort(m_modules.begin(), m_modules.end());
+ m_modules.erase(std::unique(m_modules.begin(), m_modules.end()), m_modules.end());
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/modulescanner.h b/src/plugins/qmldesigner/designercore/projectstorage/modulescanner.h
new file mode 100644
index 00000000000..2083d1d48c0
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/projectstorage/modulescanner.h
@@ -0,0 +1,46 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#pragma once
+
+#include <qmldesignercorelib_global.h>
+
+#include <externaldependenciesinterface.h>
+#include <import.h>
+
+#include <optional>
+
+namespace QmlDesigner {
+
+enum class VersionScanning { No, Yes };
+
+class QMLDESIGNERCORE_EXPORT ModuleScanner
+{
+public:
+ using SkipFunction = std::function<bool(QStringView)>;
+
+ ModuleScanner([[maybe_unused]] SkipFunction skip,
+ [[maybe_unused]] VersionScanning versionScanning,
+ [[maybe_unused]] ExternalDependenciesInterface &externalDependencies)
+ : m_skip{std::move(skip)}
+ , m_versionScanning{versionScanning}
+ , m_externalDependencies{externalDependencies}
+ {
+ m_modules.reserve(128);
+ }
+
+ void scan(const QStringList &modulePaths);
+
+ const Imports &modules() const { return m_modules; }
+
+private:
+ void scan(std::string_view modulePaths);
+
+private:
+ Imports m_modules;
+ SkipFunction m_skip;
+ VersionScanning m_versionScanning;
+ ExternalDependenciesInterface &m_externalDependencies;
+};
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h
index ad3e8931af8..974ebdf6aab 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h
@@ -45,63 +45,61 @@ public:
void synchronize(Storage::Synchronization::SynchronizationPackage package) override
{
- Sqlite::ImmediateTransaction transaction{database};
-
- AliasPropertyDeclarations insertedAliasPropertyDeclarations;
- AliasPropertyDeclarations updatedAliasPropertyDeclarations;
-
- AliasPropertyDeclarations relinkableAliasPropertyDeclarations;
- PropertyDeclarations relinkablePropertyDeclarations;
- Prototypes relinkablePrototypes;
- Prototypes relinkableExtensions;
- TypeIds deletedTypeIds;
-
- TypeIds updatedTypeIds;
- updatedTypeIds.reserve(package.types.size());
-
- TypeIds typeIdsToBeDeleted;
-
- std::sort(package.updatedSourceIds.begin(), package.updatedSourceIds.end());
-
- synchronizeFileStatuses(package.fileStatuses, package.updatedFileStatusSourceIds);
- synchronizeImports(package.imports,
- package.updatedSourceIds,
- package.moduleDependencies,
- package.updatedModuleDependencySourceIds,
- package.moduleExportedImports,
- package.updatedModuleIds);
- synchronizeTypes(package.types,
- updatedTypeIds,
- insertedAliasPropertyDeclarations,
- updatedAliasPropertyDeclarations,
- relinkableAliasPropertyDeclarations,
- relinkablePropertyDeclarations,
- relinkablePrototypes,
- relinkableExtensions,
- package.updatedSourceIds);
-
- deleteNotUpdatedTypes(updatedTypeIds,
- package.updatedSourceIds,
- typeIdsToBeDeleted,
- relinkableAliasPropertyDeclarations,
- relinkablePropertyDeclarations,
- relinkablePrototypes,
- relinkableExtensions,
- deletedTypeIds);
-
- relink(relinkableAliasPropertyDeclarations,
- relinkablePropertyDeclarations,
- relinkablePrototypes,
- relinkableExtensions,
- deletedTypeIds);
-
- linkAliases(insertedAliasPropertyDeclarations, updatedAliasPropertyDeclarations);
-
- synchronizeProjectDatas(package.projectDatas, package.updatedProjectSourceIds);
-
- commonTypeCache.resetTypeIds();
-
- transaction.commit();
+ Sqlite::withImmediateTransaction(database, [&] {
+ AliasPropertyDeclarations insertedAliasPropertyDeclarations;
+ AliasPropertyDeclarations updatedAliasPropertyDeclarations;
+
+ AliasPropertyDeclarations relinkableAliasPropertyDeclarations;
+ PropertyDeclarations relinkablePropertyDeclarations;
+ Prototypes relinkablePrototypes;
+ Prototypes relinkableExtensions;
+ TypeIds deletedTypeIds;
+
+ TypeIds updatedTypeIds;
+ updatedTypeIds.reserve(package.types.size());
+
+ TypeIds typeIdsToBeDeleted;
+
+ std::sort(package.updatedSourceIds.begin(), package.updatedSourceIds.end());
+
+ synchronizeFileStatuses(package.fileStatuses, package.updatedFileStatusSourceIds);
+ synchronizeImports(package.imports,
+ package.updatedSourceIds,
+ package.moduleDependencies,
+ package.updatedModuleDependencySourceIds,
+ package.moduleExportedImports,
+ package.updatedModuleIds);
+ synchronizeTypes(package.types,
+ updatedTypeIds,
+ insertedAliasPropertyDeclarations,
+ updatedAliasPropertyDeclarations,
+ relinkableAliasPropertyDeclarations,
+ relinkablePropertyDeclarations,
+ relinkablePrototypes,
+ relinkableExtensions,
+ package.updatedSourceIds);
+
+ deleteNotUpdatedTypes(updatedTypeIds,
+ package.updatedSourceIds,
+ typeIdsToBeDeleted,
+ relinkableAliasPropertyDeclarations,
+ relinkablePropertyDeclarations,
+ relinkablePrototypes,
+ relinkableExtensions,
+ deletedTypeIds);
+
+ relink(relinkableAliasPropertyDeclarations,
+ relinkablePropertyDeclarations,
+ relinkablePrototypes,
+ relinkableExtensions,
+ deletedTypeIds);
+
+ linkAliases(insertedAliasPropertyDeclarations, updatedAliasPropertyDeclarations);
+
+ synchronizeProjectDatas(package.projectDatas, package.updatedProjectSourceIds);
+
+ commonTypeCache_.resetTypeIds();
+ });
}
ModuleId moduleId(Utils::SmallStringView moduleName) const override
@@ -119,7 +117,7 @@ public:
TypeId typeId(ModuleId moduleId,
Utils::SmallStringView exportedTypeName,
- Storage::Synchronization::Version version) const
+ Storage::Version version) const override
{
if (version.minor)
return selectTypeIdByModuleIdAndExportedNameAndVersionStatement
@@ -136,19 +134,20 @@ public:
.template valueWithTransaction<TypeId>(moduleId, exportedTypeName);
}
- PropertyDeclarationIds propertyDeclarationIds(TypeId typeId) const
+ PropertyDeclarationIds propertyDeclarationIds(TypeId typeId) const override
{
return selectPropertyDeclarationIdsForTypeStatement
.template valuesWithTransaction<PropertyDeclarationId>(32, typeId);
}
- PropertyDeclarationIds localPropertyDeclarationIds(TypeId typeId) const
+ PropertyDeclarationIds localPropertyDeclarationIds(TypeId typeId) const override
{
return selectLocalPropertyDeclarationIdsForTypeStatement
.template valuesWithTransaction<PropertyDeclarationId>(16, typeId);
}
- PropertyDeclarationId propertyDeclarationId(TypeId typeId, Utils::SmallStringView propertyName) const
+ PropertyDeclarationId propertyDeclarationId(TypeId typeId,
+ Utils::SmallStringView propertyName) const override
{
return selectPropertyDeclarationIdForTypeAndPropertyNameStatement
.template valueWithTransaction<PropertyDeclarationId>(typeId, propertyName);
@@ -162,69 +161,74 @@ public:
}
std::optional<Storage::Info::PropertyDeclaration> propertyDeclaration(
- PropertyDeclarationId propertyDeclarationId) const
+ PropertyDeclarationId propertyDeclarationId) const override
{
return selectPropertyDeclarationForPropertyDeclarationIdStatement
.template optionalValueWithTransaction<Storage::Info::PropertyDeclaration>(
propertyDeclarationId);
}
- std::optional<Storage::Info::Type> type(TypeId typeId) const
+ std::optional<Storage::Info::Type> type(TypeId typeId) const override
{
return selectInfoTypeByTypeIdStatement.template optionalValueWithTransaction<Storage::Info::Type>(
typeId);
}
- std::vector<Utils::SmallString> signalDeclarationNames(TypeId typeId) const
+ std::vector<Utils::SmallString> signalDeclarationNames(TypeId typeId) const override
{
return selectSignalDeclarationNamesForTypeStatement
.template valuesWithTransaction<Utils::SmallString>(32, typeId);
}
- std::vector<Utils::SmallString> functionDeclarationNames(TypeId typeId) const
+ std::vector<Utils::SmallString> functionDeclarationNames(TypeId typeId) const override
{
return selectFuncionDeclarationNamesForTypeStatement
.template valuesWithTransaction<Utils::SmallString>(32, typeId);
}
- std::optional<Utils::SmallString> propertyName(PropertyDeclarationId propertyDeclarationId) const
+ std::optional<Utils::SmallString> propertyName(PropertyDeclarationId propertyDeclarationId) const override
{
return selectPropertyNameStatement.template optionalValueWithTransaction<Utils::SmallString>(
propertyDeclarationId);
}
+ const Storage::Info::CommonTypeCache<ProjectStorageInterface> &commonTypeCache() const override
+ {
+ return commonTypeCache_;
+ }
+
template<const char *moduleName, const char *typeName>
TypeId commonTypeId() const
{
- return commonTypeCache.template typeId<moduleName, typeName>();
+ return commonTypeCache_.template typeId<moduleName, typeName>();
}
template<typename BuiltinType>
TypeId builtinTypeId() const
{
- return commonTypeCache.template builtinTypeId<BuiltinType>();
+ return commonTypeCache_.template builtinTypeId<BuiltinType>();
}
template<const char *builtinType>
TypeId builtinTypeId() const
{
- return commonTypeCache.template builtinTypeId<builtinType>();
+ return commonTypeCache_.template builtinTypeId<builtinType>();
}
- TypeIds prototypeIds(TypeId type) const
+ TypeIds prototypeIds(TypeId type) const override
{
return selectPrototypeIdsForTypeIdInOrderStatement.template valuesWithTransaction<TypeId>(16,
type);
}
- TypeIds prototypeAndSelfIds(TypeId type) const
+ TypeIds prototypeAndSelfIds(TypeId type) const override
{
return selectPrototypeAndSelfIdsForTypeIdInOrderStatement
.template valuesWithTransaction<TypeId>(16, type);
}
template<typename... TypeIds>
- bool isBasedOn(TypeId typeId, TypeIds... baseTypeIds) const
+ bool isBasedOn_(TypeId typeId, TypeIds... baseTypeIds) const
{
static_assert(((std::is_same_v<TypeId, TypeIds>) &&...), "Parameter must be a TypeId!");
@@ -238,6 +242,48 @@ public:
return false;
}
+ bool isBasedOn(TypeId typeId) const { return isBasedOn_(typeId); }
+
+ bool isBasedOn(TypeId typeId, TypeId id1) const override { return isBasedOn_(typeId, id1); }
+
+ bool isBasedOn(TypeId typeId, TypeId id1, TypeId id2) const override
+ {
+ return isBasedOn_(typeId, id1, id2);
+ }
+
+ bool isBasedOn(TypeId typeId, TypeId id1, TypeId id2, TypeId id3) const override
+ {
+ return isBasedOn_(typeId, id1, id2, id3);
+ }
+
+ bool isBasedOn(TypeId typeId, TypeId id1, TypeId id2, TypeId id3, TypeId id4) const override
+ {
+ return isBasedOn_(typeId, id1, id2, id3, id4);
+ }
+
+ bool isBasedOn(TypeId typeId, TypeId id1, TypeId id2, TypeId id3, TypeId id4, TypeId id5) const override
+ {
+ return isBasedOn_(typeId, id1, id2, id3, id4, id5);
+ }
+
+ bool isBasedOn(
+ TypeId typeId, TypeId id1, TypeId id2, TypeId id3, TypeId id4, TypeId id5, TypeId id6) const override
+ {
+ return isBasedOn_(typeId, id1, id2, id3, id4, id5, id6);
+ }
+
+ bool isBasedOn(TypeId typeId,
+ TypeId id1,
+ TypeId id2,
+ TypeId id3,
+ TypeId id4,
+ TypeId id5,
+ TypeId id6,
+ TypeId id7) const override
+ {
+ return isBasedOn_(typeId, id1, id2, id3, id4, id5, id6, id7);
+ }
+
TypeId fetchTypeIdByExportedName(Utils::SmallStringView name) const
{
return selectTypeIdByExportedNameStatement.template valueWithTransaction<TypeId>(name);
@@ -257,38 +303,35 @@ public:
Storage::Synchronization::Type fetchTypeByTypeId(TypeId typeId)
{
- Sqlite::DeferredTransaction transaction{database};
-
- auto type = selectTypeByTypeIdStatement.template value<Storage::Synchronization::Type>(typeId);
+ return Sqlite::withDeferredTransaction(database, [&] {
+ auto type = selectTypeByTypeIdStatement.template value<Storage::Synchronization::Type>(
+ typeId);
- type.exportedTypes = fetchExportedTypes(typeId);
- type.propertyDeclarations = fetchPropertyDeclarations(type.typeId);
- type.functionDeclarations = fetchFunctionDeclarations(type.typeId);
- type.signalDeclarations = fetchSignalDeclarations(type.typeId);
- type.enumerationDeclarations = fetchEnumerationDeclarations(type.typeId);
-
- transaction.commit();
+ type.exportedTypes = fetchExportedTypes(typeId);
+ type.propertyDeclarations = fetchPropertyDeclarations(type.typeId);
+ type.functionDeclarations = fetchFunctionDeclarations(type.typeId);
+ type.signalDeclarations = fetchSignalDeclarations(type.typeId);
+ type.enumerationDeclarations = fetchEnumerationDeclarations(type.typeId);
- return type;
+ return type;
+ });
}
Storage::Synchronization::Types fetchTypes()
{
- Sqlite::DeferredTransaction transaction{database};
+ return Sqlite::withDeferredTransaction(database, [&] {
+ auto types = selectTypesStatement.template values<Storage::Synchronization::Type>(64);
- auto types = selectTypesStatement.template values<Storage::Synchronization::Type>(64);
-
- for (Storage::Synchronization::Type &type : types) {
- type.exportedTypes = fetchExportedTypes(type.typeId);
- type.propertyDeclarations = fetchPropertyDeclarations(type.typeId);
- type.functionDeclarations = fetchFunctionDeclarations(type.typeId);
- type.signalDeclarations = fetchSignalDeclarations(type.typeId);
- type.enumerationDeclarations = fetchEnumerationDeclarations(type.typeId);
- }
-
- transaction.commit();
+ for (Storage::Synchronization::Type &type : types) {
+ type.exportedTypes = fetchExportedTypes(type.typeId);
+ type.propertyDeclarations = fetchPropertyDeclarations(type.typeId);
+ type.functionDeclarations = fetchFunctionDeclarations(type.typeId);
+ type.signalDeclarations = fetchSignalDeclarations(type.typeId);
+ type.enumerationDeclarations = fetchEnumerationDeclarations(type.typeId);
+ }
- return types;
+ return types;
+ });
}
bool fetchIsProtype(TypeId type, TypeId prototype)
@@ -311,13 +354,9 @@ public:
SourceContextId fetchSourceContextId(Utils::SmallStringView sourceContextPath)
{
try {
- Sqlite::DeferredTransaction transaction{database};
-
- auto sourceContextId = fetchSourceContextIdUnguarded(sourceContextPath);
-
- transaction.commit();
-
- return sourceContextId;
+ return Sqlite::withDeferredTransaction(database, [&] {
+ return fetchSourceContextIdUnguarded(sourceContextPath);
+ });
} catch (const Sqlite::ConstraintPreventsModification &) {
return fetchSourceContextId(sourceContextPath);
}
@@ -325,18 +364,16 @@ public:
Utils::PathString fetchSourceContextPath(SourceContextId sourceContextId) const
{
- Sqlite::DeferredTransaction transaction{database};
-
- auto optionalSourceContextPath = selectSourceContextPathFromSourceContextsBySourceContextIdStatement
- .template optionalValue<Utils::PathString>(
- sourceContextId);
+ return Sqlite::withDeferredTransaction(database, [&] {
+ auto optionalSourceContextPath = selectSourceContextPathFromSourceContextsBySourceContextIdStatement
+ .template optionalValue<Utils::PathString>(
+ sourceContextId);
- if (!optionalSourceContextPath)
- throw SourceContextIdDoesNotExists();
+ if (!optionalSourceContextPath)
+ throw SourceContextIdDoesNotExists();
- transaction.commit();
-
- return std::move(*optionalSourceContextPath);
+ return std::move(*optionalSourceContextPath);
+ });
}
auto fetchAllSourceContexts() const
@@ -347,13 +384,9 @@ public:
SourceId fetchSourceId(SourceContextId sourceContextId, Utils::SmallStringView sourceName)
{
- Sqlite::DeferredTransaction transaction{database};
-
- auto sourceId = fetchSourceIdUnguarded(sourceContextId, sourceName);
-
- transaction.commit();
-
- return sourceId;
+ return Sqlite::withDeferredTransaction(database, [&] {
+ return fetchSourceIdUnguarded(sourceContextId, sourceName);
+ });
}
auto fetchSourceNameAndSourceContextId(SourceId sourceId) const
@@ -369,12 +402,10 @@ public:
void clearSources()
{
- Sqlite::ImmediateTransaction transaction{database};
-
- deleteAllSourceContextsStatement.execute();
- deleteAllSourcesStatement.execute();
-
- transaction.commit();
+ Sqlite::withImmediateTransaction(database, [&] {
+ deleteAllSourceContextsStatement.execute();
+ deleteAllSourcesStatement.execute();
+ });
}
SourceContextId fetchSourceContextId(SourceId sourceId) const
@@ -414,16 +445,22 @@ public:
sourceId);
}
+ std::optional<Storage::Synchronization::ProjectData> fetchProjectData(SourceId sourceId) const override
+ {
+ return selectProjectDataForSourceIdStatement
+ .template optionalValueWithTransaction<Storage::Synchronization::ProjectData>(sourceId);
+ }
+
Storage::Synchronization::ProjectDatas fetchProjectDatas(SourceId projectSourceId) const override
{
- return selectProjectDatasForModuleIdStatement
+ return selectProjectDatasForSourceIdStatement
.template valuesWithTransaction<Storage::Synchronization::ProjectData>(64,
projectSourceId);
}
Storage::Synchronization::ProjectDatas fetchProjectDatas(const SourceIds &projectSourceIds) const
{
- return selectProjectDatasForModuleIdsStatement.template valuesWithTransaction<
+ return selectProjectDatasForSourceIdsStatement.template valuesWithTransaction<
Storage::Synchronization::ProjectData>(64, toIntegers(projectSourceIds));
}
@@ -470,24 +507,15 @@ private:
ModuleId fetchModuleId(Utils::SmallStringView moduleName)
{
- Sqlite::DeferredTransaction transaction{database};
-
- ModuleId moduleId = fetchModuleIdUnguarded(moduleName);
-
- transaction.commit();
-
- return moduleId;
+ return Sqlite::withDeferredTransaction(database,
+ [&] { return fetchModuleIdUnguarded(moduleName); });
}
auto fetchModuleName(ModuleId id)
{
- Sqlite::DeferredTransaction transaction{database};
-
- auto moduleName = fetchModuleNameUnguarded(id);
-
- transaction.commit();
-
- return moduleName;
+ return Sqlite::withDeferredTransaction(database, [&] {
+ return fetchModuleNameUnguarded(id);
+ });
}
auto fetchAllModules() const
@@ -712,7 +740,7 @@ private:
< std::tie(second.projectSourceId, second.sourceId);
});
- auto range = selectProjectDatasForModuleIdsStatement
+ auto range = selectProjectDatasForSourceIdsStatement
.template range<Storage::Synchronization::ProjectData>(
toIntegers(updatedProjectSourceIds));
@@ -1527,7 +1555,7 @@ private:
ModuleExportedImportId moduleExportedImportId) {
Storage::Synchronization::Import additionImport{
exportedModuleId,
- Storage::Synchronization::Version{majorVersion, minorVersion},
+ Storage::Version{majorVersion, minorVersion},
import.sourceId};
auto exportedImportKind = importKind == Storage::Synchronization::ImportKind::Import
@@ -2581,6 +2609,7 @@ private:
table.addColumn("fileType", Sqlite::StrictColumnType::Integer);
table.addPrimaryKeyContraint({projectSourceIdColumn, sourceIdColumn});
+ table.addUniqueIndex({sourceIdColumn});
table.initialize(database);
}
@@ -2590,7 +2619,7 @@ public:
Database &database;
Initializer initializer;
mutable ModuleCache moduleCache{ModuleStorageAdapter{*this}};
- Storage::Info::CommonTypeCache<ProjectStorage<Database>> commonTypeCache{*this};
+ Storage::Info::CommonTypeCache<ProjectStorageInterface> commonTypeCache_{*this};
ReadWriteStatement<1, 3> upsertTypeStatement{
"INSERT INTO types(sourceId, name, traits) VALUES(?1, ?2, ?3) ON CONFLICT DO "
"UPDATE SET traits=excluded.traits WHERE traits IS NOT "
@@ -3082,7 +3111,7 @@ public:
"DELETE FROM exportedTypeNames WHERE exportedTypeNameId=?", database};
WriteStatement<2> updateExportedTypeNameTypeIdStatement{
"UPDATE exportedTypeNames SET typeId=?2 WHERE exportedTypeNameId=?1", database};
- mutable ReadStatement<4, 1> selectProjectDatasForModuleIdsStatement{
+ mutable ReadStatement<4, 1> selectProjectDatasForSourceIdsStatement{
"SELECT projectSourceId, sourceId, moduleId, fileType FROM projectDatas WHERE "
"projectSourceId IN carray(?1) ORDER BY projectSourceId, sourceId",
database};
@@ -3095,10 +3124,14 @@ public:
WriteStatement<4> updateProjectDataStatement{
"UPDATE projectDatas SET moduleId=?3, fileType=?4 WHERE projectSourceId=?1 AND sourceId=?2",
database};
- mutable ReadStatement<4, 1> selectProjectDatasForModuleIdStatement{
+ mutable ReadStatement<4, 1> selectProjectDatasForSourceIdStatement{
"SELECT projectSourceId, sourceId, moduleId, fileType FROM projectDatas WHERE "
"projectSourceId=?1",
database};
+ mutable ReadStatement<4, 1> selectProjectDataForSourceIdStatement{
+ "SELECT projectSourceId, sourceId, moduleId, fileType FROM projectDatas WHERE "
+ "sourceId=?1 LIMIT 1",
+ database};
mutable ReadStatement<1, 1> selectTypeIdsForSourceIdsStatement{
"SELECT typeId FROM types WHERE sourceId IN carray(?1)", database};
mutable ReadStatement<6, 1> selectModuleExportedImportsForSourceIdStatement{
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.cpp b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.cpp
index d574ef54750..07e925df689 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.cpp
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.cpp
@@ -95,4 +95,9 @@ const char *FileStatusHasInvalidSourceId::what() const noexcept
return "The source id in file status is invalid!";
}
+const char *ProjectStorageError::what() const noexcept
+{
+ return "Project storage error!";
+}
+
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.h
index d78283ca180..e5e50e76092 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.h
@@ -9,109 +9,115 @@
namespace QmlDesigner {
-class QMLDESIGNERCORE_EXPORT NoSourcePathForInvalidSourceId : std::exception
+class QMLDESIGNERCORE_EXPORT ProjectStorageError : std::exception
{
public:
const char *what() const noexcept override;
};
-class QMLDESIGNERCORE_EXPORT NoSourceContextPathForInvalidSourceContextId : std::exception
+class QMLDESIGNERCORE_EXPORT NoSourcePathForInvalidSourceId : ProjectStorageError
{
public:
const char *what() const noexcept override;
};
-class QMLDESIGNERCORE_EXPORT SourceContextIdDoesNotExists : std::exception
+class QMLDESIGNERCORE_EXPORT NoSourceContextPathForInvalidSourceContextId : ProjectStorageError
{
public:
const char *what() const noexcept override;
};
-class QMLDESIGNERCORE_EXPORT SourceIdDoesNotExists : std::exception
+class QMLDESIGNERCORE_EXPORT SourceContextIdDoesNotExists : ProjectStorageError
{
public:
const char *what() const noexcept override;
};
-class QMLDESIGNERCORE_EXPORT TypeHasInvalidSourceId : std::exception
+class QMLDESIGNERCORE_EXPORT SourceIdDoesNotExists : ProjectStorageError
{
public:
const char *what() const noexcept override;
};
-class QMLDESIGNERCORE_EXPORT ModuleDoesNotExists : std::exception
+class QMLDESIGNERCORE_EXPORT TypeHasInvalidSourceId : ProjectStorageError
{
public:
const char *what() const noexcept override;
};
-class QMLDESIGNERCORE_EXPORT ModuleAlreadyExists : std::exception
+class QMLDESIGNERCORE_EXPORT ModuleDoesNotExists : ProjectStorageError
{
public:
const char *what() const noexcept override;
};
-class QMLDESIGNERCORE_EXPORT ExportedTypeCannotBeInserted : std::exception
+class QMLDESIGNERCORE_EXPORT ModuleAlreadyExists : ProjectStorageError
{
public:
const char *what() const noexcept override;
};
-class QMLDESIGNERCORE_EXPORT TypeNameDoesNotExists : std::exception
+class QMLDESIGNERCORE_EXPORT ExportedTypeCannotBeInserted : ProjectStorageError
{
public:
const char *what() const noexcept override;
};
-class QMLDESIGNERCORE_EXPORT PropertyNameDoesNotExists : std::exception
+class QMLDESIGNERCORE_EXPORT TypeNameDoesNotExists : ProjectStorageError
{
public:
const char *what() const noexcept override;
};
-class QMLDESIGNERCORE_EXPORT PrototypeChainCycle : std::exception
+class QMLDESIGNERCORE_EXPORT PropertyNameDoesNotExists : ProjectStorageError
{
public:
const char *what() const noexcept override;
};
-class QMLDESIGNERCORE_EXPORT AliasChainCycle : std::exception
+class QMLDESIGNERCORE_EXPORT PrototypeChainCycle : ProjectStorageError
{
public:
const char *what() const noexcept override;
};
-class QMLDESIGNERCORE_EXPORT CannotParseQmlTypesFile : std::exception
+class QMLDESIGNERCORE_EXPORT AliasChainCycle : ProjectStorageError
{
public:
const char *what() const noexcept override;
};
-class QMLDESIGNERCORE_EXPORT CannotParseQmlDocumentFile : std::exception
+class QMLDESIGNERCORE_EXPORT CannotParseQmlTypesFile : ProjectStorageError
{
public:
const char *what() const noexcept override;
};
-class QMLDESIGNERCORE_EXPORT ProjectDataHasInvalidProjectSourceId : std::exception
+class QMLDESIGNERCORE_EXPORT CannotParseQmlDocumentFile : ProjectStorageError
{
public:
const char *what() const noexcept override;
};
-class QMLDESIGNERCORE_EXPORT ProjectDataHasInvalidSourceId : std::exception
+class QMLDESIGNERCORE_EXPORT ProjectDataHasInvalidProjectSourceId : ProjectStorageError
{
public:
const char *what() const noexcept override;
};
-class QMLDESIGNERCORE_EXPORT ProjectDataHasInvalidModuleId : std::exception
+class QMLDESIGNERCORE_EXPORT ProjectDataHasInvalidSourceId : ProjectStorageError
{
public:
const char *what() const noexcept override;
};
-class QMLDESIGNERCORE_EXPORT FileStatusHasInvalidSourceId : std::exception
+class QMLDESIGNERCORE_EXPORT ProjectDataHasInvalidModuleId : ProjectStorageError
+{
+public:
+ const char *what() const noexcept override;
+};
+
+class QMLDESIGNERCORE_EXPORT FileStatusHasInvalidSourceId : ProjectStorageError
{
public:
const char *what() const noexcept override;
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragefwd.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragefwd.h
index 461868ec659..db0cec068bc 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragefwd.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragefwd.h
@@ -5,9 +5,11 @@
namespace Sqlite {
class Database;
-};
+}
namespace QmlDesigner {
+class ProjectStorageInterface;
+
template<typename Database>
class ProjectStorage;
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinfotypes.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinfotypes.h
index 71823d3ad86..b61a6ec331a 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinfotypes.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinfotypes.h
@@ -59,7 +59,7 @@ constexpr TypeTraits operator&(TypeTraits first, TypeTraits second)
return static_cast<TypeTraits>(static_cast<int>(first) & static_cast<int>(second));
}
-using TypeNameString = Utils::BasicSmallString<63>;
+using TypeNameString = ::Utils::BasicSmallString<63>;
} // namespace QmlDesigner::Storage
@@ -69,7 +69,7 @@ class PropertyDeclaration
{
public:
PropertyDeclaration(TypeId typeId,
- Utils::SmallStringView name,
+ ::Utils::SmallStringView name,
PropertyDeclarationTraits traits,
TypeId propertyTypeId)
: typeId{typeId}
@@ -79,7 +79,7 @@ public:
{}
TypeId typeId;
- Utils::SmallString name;
+ ::Utils::SmallString name;
PropertyDeclarationTraits traits;
TypeId propertyTypeId;
};
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h
index f3e87e2cf4e..bc74172ecd7 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h
@@ -3,9 +3,13 @@
#pragma once
+#include "commontypecache.h"
#include "filestatus.h"
+#include "projectstorageids.h"
#include "projectstoragetypes.h"
+#include <utils/smallstringview.h>
+
namespace QmlDesigner {
class ProjectStorageInterface
@@ -13,10 +17,56 @@ class ProjectStorageInterface
public:
virtual void synchronize(Storage::Synchronization::SynchronizationPackage package) = 0;
- virtual ModuleId moduleId(Utils::SmallStringView name) const = 0;
+ virtual ModuleId moduleId(::Utils::SmallStringView name) const = 0;
+ virtual std::optional<Storage::Info::PropertyDeclaration>
+ propertyDeclaration(PropertyDeclarationId propertyDeclarationId) const = 0;
+ virtual TypeId typeId(ModuleId moduleId,
+ ::Utils::SmallStringView exportedTypeName,
+ Storage::Version version) const
+ = 0;
+ virtual PropertyDeclarationIds propertyDeclarationIds(TypeId typeId) const = 0;
+ virtual PropertyDeclarationIds localPropertyDeclarationIds(TypeId typeId) const = 0;
+ virtual PropertyDeclarationId propertyDeclarationId(TypeId typeId,
+ ::Utils::SmallStringView propertyName) const
+ = 0;
+ virtual std::optional<Storage::Info::Type> type(TypeId typeId) const = 0;
+ virtual std::vector<::Utils::SmallString> signalDeclarationNames(TypeId typeId) const = 0;
+ virtual std::vector<::Utils::SmallString> functionDeclarationNames(TypeId typeId) const = 0;
+ virtual std::optional<::Utils::SmallString>
+ propertyName(PropertyDeclarationId propertyDeclarationId) const = 0;
+ virtual TypeIds prototypeAndSelfIds(TypeId type) const = 0;
+ virtual TypeIds prototypeIds(TypeId type) const = 0;
+ virtual bool isBasedOn(TypeId, TypeId) const = 0;
+ virtual bool isBasedOn(TypeId, TypeId, TypeId) const = 0;
+ virtual bool isBasedOn(TypeId, TypeId, TypeId, TypeId) const = 0;
+ virtual bool isBasedOn(TypeId, TypeId, TypeId, TypeId, TypeId) const = 0;
+ virtual bool isBasedOn(TypeId, TypeId, TypeId, TypeId, TypeId, TypeId) const = 0;
+ virtual bool isBasedOn(TypeId, TypeId, TypeId, TypeId, TypeId, TypeId, TypeId) const = 0;
+ virtual bool isBasedOn(TypeId, TypeId, TypeId, TypeId, TypeId, TypeId, TypeId, TypeId) const = 0;
virtual FileStatus fetchFileStatus(SourceId sourceId) const = 0;
virtual Storage::Synchronization::ProjectDatas fetchProjectDatas(SourceId sourceId) const = 0;
+ virtual std::optional<Storage::Synchronization::ProjectData> fetchProjectData(SourceId sourceId) const = 0;
+
+ virtual const Storage::Info::CommonTypeCache<ProjectStorageInterface> &commonTypeCache() const = 0;
+
+ template<const char *moduleName, const char *typeName>
+ TypeId commonTypeId() const
+ {
+ return commonTypeCache().template typeId<moduleName, typeName>();
+ }
+
+ template<typename BuiltinType>
+ TypeId builtinTypeId() const
+ {
+ return commonTypeCache().template builtinTypeId<BuiltinType>();
+ }
+
+ template<const char *builtinType>
+ TypeId builtinTypeId() const
+ {
+ return commonTypeCache().template builtinTypeId<builtinType>();
+ }
protected:
~ProjectStorageInterface() = default;
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragepathwatcher.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragepathwatcher.h
index 0d3bc730f81..d79b87807f8 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragepathwatcher.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragepathwatcher.h
@@ -71,7 +71,7 @@ public:
}
void updateContextIdPaths(const std::vector<IdPaths> &idPaths,
- const SourceContextIds &sourceContextIds)
+ const SourceContextIds &sourceContextIds) override
{
const auto &[entires, ids] = convertIdPathsToWatcherEntriesAndIds(idPaths);
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragepathwatcherinterface.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragepathwatcherinterface.h
index 110cf07cff0..8e67b80b9a7 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragepathwatcherinterface.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragepathwatcherinterface.h
@@ -19,6 +19,9 @@ public:
ProjectStoragePathWatcherInterface &operator=(const ProjectStoragePathWatcherInterface &) = delete;
virtual void updateIdPaths(const std::vector<IdPaths> &idPaths) = 0;
+ virtual void updateContextIdPaths(const std::vector<IdPaths> &idPaths,
+ const SourceContextIds &sourceContextIds)
+ = 0;
virtual void removeIds(const ProjectPartIds &ids) = 0;
virtual void setNotifier(ProjectStoragePathWatcherNotifierInterface *notifier) = 0;
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragetypes.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragetypes.h
index 1f20eb93713..83372893785 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragetypes.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragetypes.h
@@ -13,11 +13,7 @@
#include <variant>
#include <vector>
-namespace QmlDesigner::Storage::Synchronization {
-
-enum class TypeNameKind { Exported = 1, QualifiedExported = 2 };
-
-enum class FileType : char { QmlTypes, QmlDocument };
+namespace QmlDesigner::Storage {
class VersionNumber
{
@@ -83,6 +79,12 @@ public:
VersionNumber minor;
};
+namespace Synchronization {
+
+enum class TypeNameKind { Exported = 1, QualifiedExported = 2 };
+
+enum class FileType : char { QmlTypes, QmlDocument };
+
enum class IsQualified : int { No, Yes };
inline int operator-(IsQualified first, IsQualified second)
@@ -107,7 +109,7 @@ class Import
public:
explicit Import() = default;
- explicit Import(ModuleId moduleId, Version version, SourceId sourceId)
+ explicit Import(ModuleId moduleId, Storage::Version version, SourceId sourceId)
: version{version}
, moduleId{moduleId}
, sourceId{sourceId}
@@ -132,7 +134,7 @@ public:
}
public:
- Version version;
+ Storage::Version version;
ModuleId moduleId;
SourceId sourceId;
};
@@ -162,7 +164,7 @@ public:
ImportId importId;
SourceId sourceId;
ModuleId moduleId;
- Version version;
+ Storage::Version version;
};
enum class IsAutoVersion : char { No, Yes };
@@ -177,7 +179,7 @@ class ModuleExportedImport
public:
explicit ModuleExportedImport(ModuleId moduleId,
ModuleId exportedModuleId,
- Version version,
+ Storage::Version version,
IsAutoVersion isAutoVersion)
: version{version}
, moduleId{moduleId}
@@ -199,7 +201,7 @@ public:
}
public:
- Version version;
+ Storage::Version version;
ModuleId moduleId;
ModuleId exportedModuleId;
IsAutoVersion isAutoVersion = IsAutoVersion::No;
@@ -234,7 +236,7 @@ public:
public:
ModuleExportedImportId moduleExportedImportId;
- Version version;
+ Storage::Version version;
ModuleId moduleId;
ModuleId exportedModuleId;
IsAutoVersion isAutoVersion = IsAutoVersion::No;
@@ -244,7 +246,7 @@ class ImportedType
{
public:
explicit ImportedType() = default;
- explicit ImportedType(Utils::SmallStringView name)
+ explicit ImportedType(::Utils::SmallStringView name)
: name{name}
{}
@@ -261,7 +263,7 @@ class QualifiedImportedType
{
public:
explicit QualifiedImportedType() = default;
- explicit QualifiedImportedType(Utils::SmallStringView name, Import import)
+ explicit QualifiedImportedType(::Utils::SmallStringView name, Import import)
: name{name}
, import{std::move(import)}
{}
@@ -282,25 +284,33 @@ class ExportedType
{
public:
explicit ExportedType() = default;
- explicit ExportedType(Utils::SmallStringView name, Version version = Version{})
+ explicit ExportedType(::Utils::SmallStringView name, Storage::Version version = Storage::Version{})
: name{name}
, version{version}
{}
- explicit ExportedType(ModuleId moduleId, Utils::SmallStringView name, Version version = Version{})
+ explicit ExportedType(ModuleId moduleId,
+ ::Utils::SmallStringView name,
+ Storage::Version version = Storage::Version{})
: name{name}
, version{version}
, moduleId{moduleId}
{}
- explicit ExportedType(Utils::SmallStringView name, Version version, TypeId typeId, ModuleId moduleId)
+ explicit ExportedType(::Utils::SmallStringView name,
+ Storage::Version version,
+ TypeId typeId,
+ ModuleId moduleId)
: name{name}
, version{version}
, typeId{typeId}
, moduleId{moduleId}
{}
- explicit ExportedType(ModuleId moduleId, Utils::SmallStringView name, int majorVersion, int minorVersion)
+ explicit ExportedType(ModuleId moduleId,
+ ::Utils::SmallStringView name,
+ int majorVersion,
+ int minorVersion)
: name{name}
, version{majorVersion, minorVersion}
, moduleId{moduleId}
@@ -318,8 +328,8 @@ public:
}
public:
- Utils::SmallString name;
- Version version;
+ ::Utils::SmallString name;
+ Storage::Version version;
TypeId typeId;
ModuleId moduleId;
};
@@ -330,13 +340,13 @@ class ExportedTypeView
{
public:
explicit ExportedTypeView() = default;
- explicit ExportedTypeView(ModuleId moduleId, Utils::SmallStringView name, Version version)
+ explicit ExportedTypeView(ModuleId moduleId, ::Utils::SmallStringView name, Storage::Version version)
: name{name}
, version{version}
, moduleId{moduleId}
{}
explicit ExportedTypeView(ModuleId moduleId,
- Utils::SmallStringView name,
+ ::Utils::SmallStringView name,
int majorVersion,
int minorVersion,
TypeId typeId,
@@ -349,8 +359,8 @@ public:
{}
public:
- Utils::SmallStringView name;
- Version version;
+ ::Utils::SmallStringView name;
+ Storage::Version version;
TypeId typeId;
ModuleId moduleId;
ExportedTypeNameId exportedTypeNameId;
@@ -362,13 +372,13 @@ class EnumeratorDeclaration
{
public:
explicit EnumeratorDeclaration() = default;
- explicit EnumeratorDeclaration(Utils::SmallStringView name, long long value, int hasValue = true)
+ explicit EnumeratorDeclaration(::Utils::SmallStringView name, long long value, int hasValue = true)
: name{name}
, value{value}
, hasValue{bool(hasValue)}
{}
- explicit EnumeratorDeclaration(Utils::SmallStringView name)
+ explicit EnumeratorDeclaration(::Utils::SmallStringView name)
: name{name}
{}
@@ -379,7 +389,7 @@ public:
}
public:
- Utils::SmallString name;
+ ::Utils::SmallString name;
long long value = 0;
bool hasValue = false;
};
@@ -390,7 +400,7 @@ class EnumerationDeclaration
{
public:
explicit EnumerationDeclaration() = default;
- explicit EnumerationDeclaration(Utils::SmallStringView name,
+ explicit EnumerationDeclaration(::Utils::SmallStringView name,
EnumeratorDeclarations enumeratorDeclarations)
: name{name}
, enumeratorDeclarations{std::move(enumeratorDeclarations)}
@@ -413,8 +423,8 @@ class EnumerationDeclarationView
{
public:
explicit EnumerationDeclarationView() = default;
- explicit EnumerationDeclarationView(Utils::SmallStringView name,
- Utils::SmallStringView enumeratorDeclarations,
+ explicit EnumerationDeclarationView(::Utils::SmallStringView name,
+ ::Utils::SmallStringView enumeratorDeclarations,
EnumerationDeclarationId id)
: name{name}
, enumeratorDeclarations{std::move(enumeratorDeclarations)}
@@ -422,8 +432,8 @@ public:
{}
public:
- Utils::SmallStringView name;
- Utils::SmallStringView enumeratorDeclarations;
+ ::Utils::SmallStringView name;
+ ::Utils::SmallStringView enumeratorDeclarations;
EnumerationDeclarationId id;
};
@@ -431,8 +441,8 @@ class ParameterDeclaration
{
public:
explicit ParameterDeclaration() = default;
- explicit ParameterDeclaration(Utils::SmallStringView name,
- Utils::SmallStringView typeName,
+ explicit ParameterDeclaration(::Utils::SmallStringView name,
+ ::Utils::SmallStringView typeName,
PropertyDeclarationTraits traits = {})
: name{name}
, typeName{typeName}
@@ -446,7 +456,7 @@ public:
}
public:
- Utils::SmallString name;
+ ::Utils::SmallString name;
TypeNameString typeName;
PropertyDeclarationTraits traits = {};
};
@@ -457,12 +467,12 @@ class SignalDeclaration
{
public:
explicit SignalDeclaration() = default;
- explicit SignalDeclaration(Utils::SmallString name, ParameterDeclarations parameters)
+ explicit SignalDeclaration(::Utils::SmallString name, ParameterDeclarations parameters)
: name{name}
, parameters{std::move(parameters)}
{}
- explicit SignalDeclaration(Utils::SmallString name)
+ explicit SignalDeclaration(::Utils::SmallString name)
: name{name}
{}
@@ -472,7 +482,7 @@ public:
}
public:
- Utils::SmallString name;
+ ::Utils::SmallString name;
ParameterDeclarations parameters;
};
@@ -482,8 +492,8 @@ class SignalDeclarationView
{
public:
explicit SignalDeclarationView() = default;
- explicit SignalDeclarationView(Utils::SmallStringView name,
- Utils::SmallStringView signature,
+ explicit SignalDeclarationView(::Utils::SmallStringView name,
+ ::Utils::SmallStringView signature,
SignalDeclarationId id)
: name{name}
, signature{signature}
@@ -491,8 +501,8 @@ public:
{}
public:
- Utils::SmallStringView name;
- Utils::SmallStringView signature;
+ ::Utils::SmallStringView name;
+ ::Utils::SmallStringView signature;
SignalDeclarationId id;
};
@@ -500,16 +510,16 @@ class FunctionDeclaration
{
public:
explicit FunctionDeclaration() = default;
- explicit FunctionDeclaration(Utils::SmallStringView name,
- Utils::SmallStringView returnTypeName,
+ explicit FunctionDeclaration(::Utils::SmallStringView name,
+ ::Utils::SmallStringView returnTypeName,
ParameterDeclarations parameters)
: name{name}
, returnTypeName{returnTypeName}
, parameters{std::move(parameters)}
{}
- explicit FunctionDeclaration(Utils::SmallStringView name,
- Utils::SmallStringView returnTypeName = {})
+ explicit FunctionDeclaration(::Utils::SmallStringView name,
+ ::Utils::SmallStringView returnTypeName = {})
: name{name}
, returnTypeName{returnTypeName}
{}
@@ -521,7 +531,7 @@ public:
}
public:
- Utils::SmallString name;
+ ::Utils::SmallString name;
TypeNameString returnTypeName;
ParameterDeclarations parameters;
};
@@ -532,9 +542,9 @@ class FunctionDeclarationView
{
public:
explicit FunctionDeclarationView() = default;
- explicit FunctionDeclarationView(Utils::SmallStringView name,
- Utils::SmallStringView returnTypeName,
- Utils::SmallStringView signature,
+ explicit FunctionDeclarationView(::Utils::SmallStringView name,
+ ::Utils::SmallStringView returnTypeName,
+ ::Utils::SmallStringView signature,
FunctionDeclarationId id)
: name{name}
, returnTypeName{returnTypeName}
@@ -543,9 +553,9 @@ public:
{}
public:
- Utils::SmallStringView name;
- Utils::SmallStringView returnTypeName;
- Utils::SmallStringView signature;
+ ::Utils::SmallStringView name;
+ ::Utils::SmallStringView returnTypeName;
+ ::Utils::SmallStringView signature;
FunctionDeclarationId id;
};
@@ -555,7 +565,7 @@ class PropertyDeclaration
{
public:
explicit PropertyDeclaration() = default;
- explicit PropertyDeclaration(Utils::SmallStringView name,
+ explicit PropertyDeclaration(::Utils::SmallStringView name,
ImportedTypeName typeName,
PropertyDeclarationTraits traits)
: name{name}
@@ -564,7 +574,7 @@ public:
, kind{PropertyKind::Property}
{}
- explicit PropertyDeclaration(Utils::SmallStringView name,
+ explicit PropertyDeclaration(::Utils::SmallStringView name,
TypeId propertyTypeId,
PropertyDeclarationTraits traits)
: name{name}
@@ -573,11 +583,11 @@ public:
, kind{PropertyKind::Property}
{}
- explicit PropertyDeclaration(Utils::SmallStringView name,
+ explicit PropertyDeclaration(::Utils::SmallStringView name,
ImportedTypeName typeName,
PropertyDeclarationTraits traits,
- Utils::SmallStringView aliasPropertyName,
- Utils::SmallStringView aliasPropertyNameTail = {})
+ ::Utils::SmallStringView aliasPropertyName,
+ ::Utils::SmallStringView aliasPropertyNameTail = {})
: name{name}
, typeName{std::move(typeName)}
, aliasPropertyName{aliasPropertyName}
@@ -587,11 +597,11 @@ public:
, kind{PropertyKind::Property}
{}
- explicit PropertyDeclaration(Utils::SmallStringView name,
+ explicit PropertyDeclaration(::Utils::SmallStringView name,
TypeId propertyTypeId,
PropertyDeclarationTraits traits,
- Utils::SmallStringView aliasPropertyName,
- Utils::SmallStringView aliasPropertyNameTail = {})
+ ::Utils::SmallStringView aliasPropertyName,
+ ::Utils::SmallStringView aliasPropertyNameTail = {})
: name{name}
, aliasPropertyName{aliasPropertyName}
, aliasPropertyNameTail{aliasPropertyNameTail}
@@ -600,10 +610,10 @@ public:
, kind{PropertyKind::Property}
{}
- explicit PropertyDeclaration(Utils::SmallStringView name,
+ explicit PropertyDeclaration(::Utils::SmallStringView name,
ImportedTypeName aliasTypeName,
- Utils::SmallStringView aliasPropertyName,
- Utils::SmallStringView aliasPropertyNameTail = {})
+ ::Utils::SmallStringView aliasPropertyName,
+ ::Utils::SmallStringView aliasPropertyNameTail = {})
: name{name}
, typeName{std::move(aliasTypeName)}
, aliasPropertyName{aliasPropertyName}
@@ -621,10 +631,10 @@ public:
}
public:
- Utils::SmallString name;
+ ::Utils::SmallString name;
ImportedTypeName typeName;
- Utils::SmallString aliasPropertyName;
- Utils::SmallString aliasPropertyNameTail;
+ ::Utils::SmallString aliasPropertyName;
+ ::Utils::SmallString aliasPropertyNameTail;
PropertyDeclarationTraits traits = {};
TypeId propertyTypeId;
TypeId typeId;
@@ -636,7 +646,7 @@ using PropertyDeclarations = std::vector<PropertyDeclaration>;
class PropertyDeclarationView
{
public:
- explicit PropertyDeclarationView(Utils::SmallStringView name,
+ explicit PropertyDeclarationView(::Utils::SmallStringView name,
PropertyDeclarationTraits traits,
TypeId typeId,
ImportedTypeNameId typeNameId,
@@ -651,7 +661,7 @@ public:
{}
public:
- Utils::SmallStringView name;
+ ::Utils::SmallStringView name;
PropertyDeclarationTraits traits = {};
TypeId typeId;
ImportedTypeNameId typeNameId;
@@ -665,7 +675,7 @@ class Type
{
public:
explicit Type() = default;
- explicit Type(Utils::SmallStringView typeName,
+ explicit Type(::Utils::SmallStringView typeName,
ImportedTypeName prototype,
ImportedTypeName extension,
TypeTraits traits,
@@ -676,7 +686,7 @@ public:
SignalDeclarations signalDeclarations = {},
EnumerationDeclarations enumerationDeclarations = {},
ChangeLevel changeLevel = ChangeLevel::Full,
- Utils::SmallStringView defaultPropertyName = {})
+ ::Utils::SmallStringView defaultPropertyName = {})
: typeName{typeName}
, defaultPropertyName{defaultPropertyName}
, prototype{std::move(prototype)}
@@ -691,7 +701,7 @@ public:
, changeLevel{changeLevel}
{}
- explicit Type(Utils::SmallStringView typeName,
+ explicit Type(::Utils::SmallStringView typeName,
TypeId prototypeId,
TypeId extensionId,
TypeTraits traits,
@@ -703,7 +713,7 @@ public:
, extensionId{extensionId}
{}
- explicit Type(Utils::SmallStringView typeName,
+ explicit Type(::Utils::SmallStringView typeName,
ImportedTypeName prototype,
TypeTraits traits,
SourceId sourceId,
@@ -715,9 +725,9 @@ public:
, changeLevel{changeLevel}
{}
- explicit Type(Utils::SmallStringView typeName,
- Utils::SmallStringView prototype,
- Utils::SmallStringView extension,
+ explicit Type(::Utils::SmallStringView typeName,
+ ::Utils::SmallStringView prototype,
+ ::Utils::SmallStringView extension,
TypeTraits traits,
SourceId sourceId)
: typeName{typeName}
@@ -729,12 +739,12 @@ public:
{}
explicit Type(SourceId sourceId,
- Utils::SmallStringView typeName,
+ ::Utils::SmallStringView typeName,
TypeId typeId,
TypeId prototypeId,
TypeId extensionId,
TypeTraits traits,
- Utils::SmallStringView defaultPropertyName)
+ ::Utils::SmallStringView defaultPropertyName)
: typeName{typeName}
, defaultPropertyName{defaultPropertyName}
, traits{traits}
@@ -758,7 +768,7 @@ public:
public:
TypeNameString typeName;
- Utils::SmallString defaultPropertyName;
+ ::Utils::SmallString defaultPropertyName;
ImportedTypeName prototype;
ImportedTypeName extension;
ExportedTypes exportedTypes;
@@ -855,5 +865,5 @@ public:
ModuleIds updatedModuleIds;
};
-} // namespace QmlDesigner::Storage::Synchronization
-
+} // namespace Synchronization
+} // namespace QmlDesigner::Storage
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp
index f98c69734a8..4713dd0136f 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp
@@ -113,9 +113,9 @@ void addSourceIds(SourceIds &sourceIds, const Storage::Synchronization::ProjectD
sourceIds.push_back(projectData.sourceId);
}
-Storage::Synchronization::Version convertVersion(LanguageUtils::ComponentVersion version)
+Storage::Version convertVersion(LanguageUtils::ComponentVersion version)
{
- return Storage::Synchronization::Version{version.majorVersion(), version.minorVersion()};
+ return Storage::Version{version.majorVersion(), version.minorVersion()};
}
Storage::Synchronization::IsAutoVersion convertToIsAutoVersion(QmlDirParser::Import::Flags flags)
@@ -133,7 +133,7 @@ void addDependencies(Storage::Synchronization::Imports &dependencies,
for (const QmlDirParser::Import &qmldirDependency : qmldirDependencies) {
ModuleId moduleId = projectStorage.moduleId(Utils::PathString{qmldirDependency.module}
+ "-cppnative");
- dependencies.emplace_back(moduleId, Storage::Synchronization::Version{}, sourceId);
+ dependencies.emplace_back(moduleId, Storage::Version{}, sourceId);
}
}
@@ -154,46 +154,53 @@ void addModuleExportedImports(Storage::Synchronization::ModuleExportedImports &i
Utils::PathString{qmldirImport.module} + "-cppnative");
imports.emplace_back(cppModuleId,
exportedCppModuleId,
- Storage::Synchronization::Version{},
+ Storage::Version{},
Storage::Synchronization::IsAutoVersion::No);
}
}
-} // namespace
-
-void ProjectStorageUpdater::update(QStringList directories,
- QStringList qmlTypesPaths,
+std::vector<IdPaths> createIdPaths(ProjectStorageUpdater::WatchedSourceIdsIds watchedSourceIds,
ProjectPartId projectPartId)
{
- Storage::Synchronization::SynchronizationPackage package;
- SourceIdsData sourceIdsData{static_cast<std::size_t>(directories.size())};
std::vector<IdPaths> idPaths;
idPaths.reserve(4);
- updateDirectories(directories, package, sourceIdsData);
- updateQmlTypes(qmlTypesPaths, package, sourceIdsData);
+ idPaths.push_back(
+ {projectPartId, SourceType::Directory, std::move(watchedSourceIds.directorySourceIds)});
+ idPaths.push_back({projectPartId, SourceType::QmlDir, std::move(watchedSourceIds.qmldirSourceIds)});
+ idPaths.push_back({projectPartId, SourceType::Qml, std::move(watchedSourceIds.qmlSourceIds)});
+ idPaths.push_back(
+ {projectPartId, SourceType::QmlTypes, std::move(watchedSourceIds.qmltypesSourceIds)});
+
+ return idPaths;
+}
+
+} // namespace
+
+void ProjectStorageUpdater::update(QStringList directories, QStringList qmlTypesPaths)
+{
+ Storage::Synchronization::SynchronizationPackage package;
+ WatchedSourceIdsIds watchedSourceIds{Utils::span{directories}.size()};
+ NotUpdatedSourceIds notUpdatedSourceIds{Utils::span{directories}.size()};
+
+ updateDirectories(directories, package, notUpdatedSourceIds, watchedSourceIds);
+ updateQmlTypes(qmlTypesPaths, package, notUpdatedSourceIds, watchedSourceIds);
package.updatedSourceIds = filterNotUpdatedSourceIds(std::move(package.updatedSourceIds),
- std::move(sourceIdsData.notUpdatedSourceIds));
+ std::move(notUpdatedSourceIds.sourceIds));
package.updatedFileStatusSourceIds = filterNotUpdatedSourceIds(
std::move(package.updatedFileStatusSourceIds),
- std::move(sourceIdsData.notUpdatedFileStatusSourceIds));
+ std::move(notUpdatedSourceIds.fileStatusSourceIds));
m_projectStorage.synchronize(std::move(package));
- idPaths.push_back(
- {projectPartId, SourceType::Directory, std::move(sourceIdsData.watchedDirectorySourceIds)});
- idPaths.push_back(
- {projectPartId, SourceType::QmlDir, std::move(sourceIdsData.watchedQmldirSourceIds)});
- idPaths.push_back({projectPartId, SourceType::Qml, std::move(sourceIdsData.watchedQmlSourceIds)});
- idPaths.push_back(
- {projectPartId, SourceType::QmlTypes, std::move(sourceIdsData.watchedQmltypesSourceIds)});
- m_pathWatcher.updateIdPaths(idPaths);
+ m_pathWatcher.updateIdPaths(createIdPaths(watchedSourceIds, m_projectPartId));
}
void ProjectStorageUpdater::updateQmlTypes(const QStringList &qmlTypesPaths,
Storage::Synchronization::SynchronizationPackage &package,
- SourceIdsData &sourceIdsData)
+ NotUpdatedSourceIds &notUpdatedSourceIds,
+ WatchedSourceIdsIds &watchedSourceIdsIds)
{
if (qmlTypesPaths.empty())
return;
@@ -202,7 +209,7 @@ void ProjectStorageUpdater::updateQmlTypes(const QStringList &qmlTypesPaths,
for (const QString &qmlTypesPath : qmlTypesPaths) {
SourceId sourceId = m_pathCache.sourceId(SourcePath{qmlTypesPath});
- sourceIdsData.watchedQmltypesSourceIds.push_back(sourceId);
+ watchedSourceIdsIds.qmltypesSourceIds.push_back(sourceId);
Storage::Synchronization::ProjectData projectData{sourceId,
sourceId,
@@ -212,7 +219,7 @@ void ProjectStorageUpdater::updateQmlTypes(const QStringList &qmlTypesPaths,
FileState state = parseTypeInfo(projectData,
Utils::PathString{qmlTypesPath},
package,
- sourceIdsData);
+ notUpdatedSourceIds);
if (state == FileState::Changed)
package.projectDatas.push_back(std::move(projectData));
@@ -235,28 +242,30 @@ ProjectStorageUpdater::FileState combineState(FileStates... fileStates)
void ProjectStorageUpdater::updateDirectories(const QStringList &directories,
Storage::Synchronization::SynchronizationPackage &package,
- SourceIdsData &sourceIdsData)
+ NotUpdatedSourceIds &notUpdatedSourceIds,
+ WatchedSourceIdsIds &watchedSourceIdsIds)
{
for (const QString &directory : directories)
- updateDirectory({directory}, package, sourceIdsData);
+ updateDirectory({directory}, package, notUpdatedSourceIds, watchedSourceIdsIds);
}
void ProjectStorageUpdater::updateDirectory(const Utils::PathString &directoryPath,
Storage::Synchronization::SynchronizationPackage &package,
- SourceIdsData &sourceIdsData)
+ NotUpdatedSourceIds &notUpdatedSourceIds,
+ WatchedSourceIdsIds &watchedSourceIdsIds)
{
SourcePath qmldirSourcePath{directoryPath + "/qmldir"};
auto [directoryId, qmlDirSourceId] = m_pathCache.sourceContextAndSourceId(qmldirSourcePath);
SourcePath directorySourcePath{directoryPath + "/."};
auto directorySourceId = m_pathCache.sourceId(directorySourcePath);
- auto directoryState = fileState(directorySourceId, package, sourceIdsData);
+ auto directoryState = fileState(directorySourceId, package, notUpdatedSourceIds);
if (directoryState != FileState::NotExists)
- sourceIdsData.watchedDirectorySourceIds.push_back(directorySourceId);
+ watchedSourceIdsIds.directorySourceIds.push_back(directorySourceId);
- auto qmldirState = fileState(qmlDirSourceId, package, sourceIdsData);
+ auto qmldirState = fileState(qmlDirSourceId, package, notUpdatedSourceIds);
if (qmldirState != FileState::NotExists)
- sourceIdsData.watchedQmldirSourceIds.push_back(qmlDirSourceId);
+ watchedSourceIdsIds.qmldirSourceIds.push_back(qmlDirSourceId);
switch (combineState(directoryState, qmldirState)) {
case FileState::Changed: {
@@ -295,20 +304,25 @@ void ProjectStorageUpdater::updateDirectory(const Utils::PathString &directoryPa
directoryPath,
cppModuleId,
package,
- sourceIdsData);
+ notUpdatedSourceIds,
+ watchedSourceIdsIds);
}
parseQmlComponents(
createComponents(parser.components(), moduleId, pathModuleId, m_fileSystem, directoryPath),
directorySourceId,
directoryId,
package,
- sourceIdsData,
+ notUpdatedSourceIds,
+ watchedSourceIdsIds,
qmldirState);
package.updatedProjectSourceIds.push_back(directorySourceId);
break;
}
case FileState::NotChanged: {
- parseProjectDatas(m_projectStorage.fetchProjectDatas(directorySourceId), package, sourceIdsData);
+ parseProjectDatas(m_projectStorage.fetchProjectDatas(directorySourceId),
+ package,
+ notUpdatedSourceIds,
+ watchedSourceIdsIds);
break;
}
case FileState::NotExists: {
@@ -327,7 +341,118 @@ void ProjectStorageUpdater::updateDirectory(const Utils::PathString &directoryPa
}
}
-void ProjectStorageUpdater::pathsWithIdsChanged([[maybe_unused]] const std::vector<IdPaths> &) {}
+namespace {
+SourceContextIds filterUniqueSourceContextIds(const SourceIds &sourceIds,
+ ProjectStorageUpdater::PathCache &pathCache)
+{
+ auto sourceContextIds = Utils::transform(sourceIds, [&](SourceId sourceId) {
+ return pathCache.sourceContextId(sourceId);
+ });
+
+ std::sort(sourceContextIds.begin(), sourceContextIds.end());
+ auto newEnd = std::unique(sourceContextIds.begin(), sourceContextIds.end());
+ sourceContextIds.erase(newEnd, sourceContextIds.end());
+
+ return sourceContextIds;
+}
+
+SourceIds filterUniqueSourceIds(SourceIds sourceIds)
+{
+ std::sort(sourceIds.begin(), sourceIds.end());
+ auto newEnd = std::unique(sourceIds.begin(), sourceIds.end());
+ sourceIds.erase(newEnd, sourceIds.end());
+
+ return sourceIds;
+}
+
+template<typename Container, typename Id>
+bool contains(const Container &container, Id id)
+{
+ return std::find(container.begin(), container.end(), id) != container.end();
+}
+} // namespace
+
+void ProjectStorageUpdater::pathsWithIdsChanged(const std::vector<IdPaths> &changedIdPaths)
+{
+ m_changedIdPaths.insert(m_changedIdPaths.end(), changedIdPaths.begin(), changedIdPaths.end());
+
+ Storage::Synchronization::SynchronizationPackage package;
+
+ WatchedSourceIdsIds watchedSourceIds{10};
+ NotUpdatedSourceIds notUpdatedSourceIds{10};
+ std::vector<IdPaths> idPaths;
+ idPaths.reserve(4);
+
+ SourceIds directorySourceIds;
+ directorySourceIds.reserve(32);
+ SourceIds qmlDocumentSourceIds;
+ qmlDocumentSourceIds.reserve(128);
+ SourceIds qmltypesSourceIds;
+ qmltypesSourceIds.reserve(32);
+
+ for (const auto &[projectChunkId, sourceIds] : m_changedIdPaths) {
+ if (projectChunkId.id != m_projectPartId)
+ continue;
+
+ switch (projectChunkId.sourceType) {
+ case SourceType::Directory:
+ case SourceType::QmlDir:
+ directorySourceIds.insert(directorySourceIds.end(), sourceIds.begin(), sourceIds.end());
+ break;
+ case SourceType::Qml:
+ case SourceType::QmlUi:
+ qmlDocumentSourceIds.insert(qmlDocumentSourceIds.end(), sourceIds.begin(), sourceIds.end());
+ break;
+ case SourceType::QmlTypes:
+ qmltypesSourceIds.insert(qmltypesSourceIds.end(), sourceIds.begin(), sourceIds.end());
+ break;
+ }
+ }
+
+ auto directorySourceContextIds = filterUniqueSourceContextIds(directorySourceIds, m_pathCache);
+
+ for (auto sourceContextId : directorySourceContextIds) {
+ Utils::PathString directory = m_pathCache.sourceContextPath(sourceContextId);
+ updateDirectory(directory, package, notUpdatedSourceIds, watchedSourceIds);
+ }
+
+ for (SourceId sourceId : filterUniqueSourceIds(qmlDocumentSourceIds)) {
+ if (!contains(directorySourceContextIds, m_pathCache.sourceContextId(sourceId)))
+ parseQmlComponent(sourceId, package, notUpdatedSourceIds);
+ }
+
+ try {
+ for (SourceId sourceId : filterUniqueSourceIds(std::move(qmltypesSourceIds))) {
+ if (!contains(directorySourceContextIds, m_pathCache.sourceContextId(sourceId))) {
+ auto qmltypesPath = m_pathCache.sourcePath(sourceId);
+ auto projectData = m_projectStorage.fetchProjectData(sourceId);
+ if (projectData)
+ parseTypeInfo(*projectData, qmltypesPath, package, notUpdatedSourceIds);
+ }
+ }
+ } catch (const QmlDesigner::CannotParseQmlTypesFile &) {
+ return;
+ }
+
+ package.updatedSourceIds = filterNotUpdatedSourceIds(std::move(package.updatedSourceIds),
+ std::move(notUpdatedSourceIds.sourceIds));
+ package.updatedFileStatusSourceIds = filterNotUpdatedSourceIds(
+ std::move(package.updatedFileStatusSourceIds),
+ std::move(notUpdatedSourceIds.fileStatusSourceIds));
+
+ try {
+ m_projectStorage.synchronize(std::move(package));
+ } catch (const ProjectStorageError &) {
+ return;
+ }
+
+ if (directorySourceContextIds.size()) {
+ m_pathWatcher.updateContextIdPaths(createIdPaths(watchedSourceIds, m_projectPartId),
+ directorySourceContextIds);
+ }
+
+ m_changedIdPaths.clear();
+}
void ProjectStorageUpdater::pathsChanged(const SourceIds &) {}
@@ -338,14 +463,15 @@ void ProjectStorageUpdater::parseTypeInfos(const QStringList &typeInfos,
Utils::SmallStringView directoryPath,
ModuleId moduleId,
Storage::Synchronization::SynchronizationPackage &package,
- SourceIdsData &sourceIdData)
+ NotUpdatedSourceIds &notUpdatedSourceIds,
+ WatchedSourceIdsIds &watchedSourceIds)
{
for (const QString &typeInfo : typeInfos) {
Utils::PathString qmltypesPath = Utils::PathString::join(
{directoryPath, "/", Utils::SmallString{typeInfo}});
SourceId sourceId = m_pathCache.sourceId(SourcePathView{qmltypesPath});
- sourceIdData.watchedQmltypesSourceIds.push_back(sourceId);
+ watchedSourceIds.qmltypesSourceIds.push_back(sourceId);
addDependencies(package.moduleDependencies,
sourceId,
@@ -356,27 +482,28 @@ void ProjectStorageUpdater::parseTypeInfos(const QStringList &typeInfos,
auto projectData = package.projectDatas.emplace_back(
directorySourceId, sourceId, moduleId, Storage::Synchronization::FileType::QmlTypes);
- parseTypeInfo(projectData, qmltypesPath, package, sourceIdData);
+ parseTypeInfo(projectData, qmltypesPath, package, notUpdatedSourceIds);
}
}
void ProjectStorageUpdater::parseProjectDatas(const Storage::Synchronization::ProjectDatas &projectDatas,
Storage::Synchronization::SynchronizationPackage &package,
- SourceIdsData &sourceIdData)
+ NotUpdatedSourceIds &notUpdatedSourceIds,
+ WatchedSourceIdsIds &watchedSourceIds)
{
for (const Storage::Synchronization::ProjectData &projectData : projectDatas) {
switch (projectData.fileType) {
case Storage::Synchronization::FileType::QmlTypes: {
- sourceIdData.watchedQmltypesSourceIds.push_back(projectData.sourceId);
+ watchedSourceIds.qmltypesSourceIds.push_back(projectData.sourceId);
auto qmltypesPath = m_pathCache.sourcePath(projectData.sourceId);
- parseTypeInfo(projectData, qmltypesPath, package, sourceIdData);
+ parseTypeInfo(projectData, qmltypesPath, package, notUpdatedSourceIds);
break;
}
case Storage::Synchronization::FileType::QmlDocument: {
- sourceIdData.watchedQmlSourceIds.push_back(projectData.sourceId);
+ watchedSourceIds.qmlSourceIds.push_back(projectData.sourceId);
- parseQmlComponent(projectData.sourceId, package, sourceIdData);
+ parseQmlComponent(projectData.sourceId, package, notUpdatedSourceIds);
}
};
}
@@ -385,9 +512,9 @@ void ProjectStorageUpdater::parseProjectDatas(const Storage::Synchronization::Pr
auto ProjectStorageUpdater::parseTypeInfo(const Storage::Synchronization::ProjectData &projectData,
Utils::SmallStringView qmltypesPath,
Storage::Synchronization::SynchronizationPackage &package,
- SourceIdsData &sourceIdData) -> FileState
+ NotUpdatedSourceIds &notUpdatedSourceIds) -> FileState
{
- auto state = fileState(projectData.sourceId, package, sourceIdData);
+ auto state = fileState(projectData.sourceId, package, notUpdatedSourceIds);
switch (state) {
case FileState::Changed: {
package.updatedSourceIds.push_back(projectData.sourceId);
@@ -397,7 +524,7 @@ auto ProjectStorageUpdater::parseTypeInfo(const Storage::Synchronization::Projec
break;
}
case FileState::NotChanged: {
- sourceIdData.notUpdatedSourceIds.push_back(projectData.sourceId);
+ notUpdatedSourceIds.sourceIds.push_back(projectData.sourceId);
break;
}
case FileState::NotExists:
@@ -413,7 +540,8 @@ void ProjectStorageUpdater::parseQmlComponent(Utils::SmallStringView relativeFil
Storage::Synchronization::ExportedTypes exportedTypes,
SourceId directorySourceId,
Storage::Synchronization::SynchronizationPackage &package,
- SourceIdsData &sourceIdData,
+ NotUpdatedSourceIds &notUpdatedSourceIds,
+ WatchedSourceIdsIds &watchedSourceIds,
FileState qmldirState)
{
if (std::find(relativeFilePath.begin(), relativeFilePath.end(), '+') != relativeFilePath.end())
@@ -423,14 +551,14 @@ void ProjectStorageUpdater::parseQmlComponent(Utils::SmallStringView relativeFil
SourceId sourceId = m_pathCache.sourceId(SourcePathView{qmlFilePath});
Storage::Synchronization::Type type;
- auto state = fileState(sourceId, package, sourceIdData);
+ auto state = fileState(sourceId, package, notUpdatedSourceIds);
- sourceIdData.watchedQmlSourceIds.push_back(sourceId);
+ watchedSourceIds.qmlSourceIds.push_back(sourceId);
switch (state) {
case FileState::NotChanged:
if (qmldirState == FileState::NotExists) {
- sourceIdData.notUpdatedSourceIds.emplace_back(sourceId);
+ notUpdatedSourceIds.sourceIds.emplace_back(sourceId);
package.projectDatas.emplace_back(directorySourceId,
sourceId,
ModuleId{},
@@ -465,14 +593,17 @@ void ProjectStorageUpdater::parseQmlComponent(Utils::SmallStringView relativeFil
void ProjectStorageUpdater::parseQmlComponent(SourceId sourceId,
Storage::Synchronization::SynchronizationPackage &package,
- SourceIdsData &sourceIdData)
+ NotUpdatedSourceIds &notUpdatedSourceIds)
{
- auto state = fileState(sourceId, package, sourceIdData);
- if (state != FileState::Changed)
+ auto state = fileState(sourceId, package, notUpdatedSourceIds);
+ if (state == FileState::NotChanged)
return;
package.updatedSourceIds.push_back(sourceId);
+ if (state == FileState::NotExists)
+ return;
+
SourcePath sourcePath = m_pathCache.sourcePath(sourceId);
const auto content = m_fileSystem.contentAsQString(QString{sourcePath});
@@ -513,8 +644,7 @@ Storage::Synchronization::ExportedTypes createExportedTypes(ProjectStorageUpdate
for (const ProjectStorageUpdater::Component &component : components) {
exportedTypes.emplace_back(component.moduleId,
Utils::SmallString{component.typeName},
- Storage::Synchronization::Version{component.majorVersion,
- component.minorVersion});
+ Storage::Version{component.majorVersion, component.minorVersion});
}
return exportedTypes;
@@ -526,7 +656,8 @@ void ProjectStorageUpdater::parseQmlComponents(Components components,
SourceId directorySourceId,
SourceContextId directoryId,
Storage::Synchronization::SynchronizationPackage &package,
- SourceIdsData &sourceIdsData,
+ NotUpdatedSourceIds &notUpdatedSourceIds,
+ WatchedSourceIdsIds &watchedSourceIdsIds,
FileState qmldirState)
{
std::sort(components.begin(), components.end(), [](auto &&first, auto &&second) {
@@ -543,7 +674,8 @@ void ProjectStorageUpdater::parseQmlComponents(Components components,
createExportedTypes(componentsWithSameFileName),
directorySourceId,
package,
- sourceIdsData,
+ notUpdatedSourceIds,
+ watchedSourceIdsIds,
qmldirState);
};
@@ -553,7 +685,7 @@ void ProjectStorageUpdater::parseQmlComponents(Components components,
ProjectStorageUpdater::FileState ProjectStorageUpdater::fileState(
SourceId sourceId,
Storage::Synchronization::SynchronizationPackage &package,
- SourceIdsData &sourceIdData) const
+ NotUpdatedSourceIds &notUpdatedSourceIds) const
{
auto currentFileStatus = m_fileStatusCache.find(sourceId);
@@ -570,7 +702,7 @@ ProjectStorageUpdater::FileState ProjectStorageUpdater::fileState(
return FileState::Changed;
}
- sourceIdData.notUpdatedFileStatusSourceIds.push_back(sourceId);
+ notUpdatedSourceIds.fileStatusSourceIds.push_back(sourceId);
return FileState::NotChanged;
}
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h
index 90ce4d543d1..22778ac932a 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h
@@ -43,7 +43,8 @@ public:
PathCache &pathCache,
QmlDocumentParserInterface &qmlDocumentParser,
QmlTypesParserInterface &qmlTypesParser,
- class ProjectStoragePathWatcherInterface &pathWatcher)
+ class ProjectStoragePathWatcherInterface &pathWatcher,
+ ProjectPartId projectPartId)
: m_fileSystem{fileSystem}
, m_projectStorage{projectStorage}
, m_fileStatusCache{fileStatusCache}
@@ -51,11 +52,10 @@ public:
, m_qmlDocumentParser{qmlDocumentParser}
, m_qmlTypesParser{qmlTypesParser}
, m_pathWatcher{pathWatcher}
+ , m_projectPartId{projectPartId}
{}
- void update(QStringList directories,
- QStringList qmlTypesPaths,
- ProjectPartId projectPartId = ProjectPartId{});
+ void update(QStringList directories, QStringList qmlTypesPaths);
void pathsWithIdsChanged(const std::vector<IdPaths> &idPaths) override;
void pathsChanged(const SourceIds &filePathIds) override;
@@ -96,38 +96,49 @@ public:
NotExists,
};
-private:
- struct SourceIdsData
+ struct WatchedSourceIdsIds
+ {
+ WatchedSourceIdsIds(std::size_t reserve)
+ {
+ directorySourceIds.reserve(reserve);
+ qmldirSourceIds.reserve(reserve);
+ qmlSourceIds.reserve(reserve * 30);
+ qmltypesSourceIds.reserve(reserve * 30);
+ }
+
+ SourceIds directorySourceIds;
+ SourceIds qmldirSourceIds;
+ SourceIds qmlSourceIds;
+ SourceIds qmltypesSourceIds;
+ };
+
+ struct NotUpdatedSourceIds
{
- SourceIdsData(std::size_t reserve)
+ NotUpdatedSourceIds(std::size_t reserve)
{
- notUpdatedFileStatusSourceIds.reserve(reserve * 30);
- notUpdatedSourceIds.reserve(reserve * 30);
- watchedDirectorySourceIds.reserve(reserve);
- watchedQmldirSourceIds.reserve(reserve);
- watchedQmlSourceIds.reserve(reserve * 30);
- watchedQmltypesSourceIds.reserve(reserve * 30);
+ fileStatusSourceIds.reserve(reserve * 30);
+ sourceIds.reserve(reserve * 30);
}
- SourceIds notUpdatedFileStatusSourceIds;
- SourceIds notUpdatedSourceIds;
- SourceIds watchedDirectorySourceIds;
- SourceIds watchedQmldirSourceIds;
- SourceIds watchedQmlSourceIds;
- SourceIds watchedQmltypesSourceIds;
+ SourceIds fileStatusSourceIds;
+ SourceIds sourceIds;
};
+private:
void updateQmlTypes(const QStringList &qmlTypesPaths,
Storage::Synchronization::SynchronizationPackage &package,
- SourceIdsData &sourceIdData);
+ NotUpdatedSourceIds &notUpdatedSourceIds,
+ WatchedSourceIdsIds &watchedSourceIdsIds);
void updateDirectories(const QStringList &directories,
Storage::Synchronization::SynchronizationPackage &package,
- SourceIdsData &sourceIdData);
+ NotUpdatedSourceIds &notUpdatedSourceIds,
+ WatchedSourceIdsIds &watchedSourceIdsIds);
void updateDirectory(const Utils::PathString &directory,
Storage::Synchronization::SynchronizationPackage &package,
- SourceIdsData &sourceIdData);
+ NotUpdatedSourceIds &notUpdatedSourceIds,
+ WatchedSourceIdsIds &watchedSourceIdsIds);
void parseTypeInfos(const QStringList &typeInfos,
const QList<QmlDirParser::Import> &qmldirDependencies,
@@ -136,36 +147,41 @@ private:
Utils::SmallStringView directoryPath,
ModuleId moduleId,
Storage::Synchronization::SynchronizationPackage &package,
- SourceIdsData &sourceIdData);
+ NotUpdatedSourceIds &notUpdatedSourceIds,
+ WatchedSourceIdsIds &watchedSourceIdsIds);
void parseProjectDatas(const Storage::Synchronization::ProjectDatas &projectDatas,
Storage::Synchronization::SynchronizationPackage &package,
- SourceIdsData &sourceIdData);
+ NotUpdatedSourceIds &notUpdatedSourceIds,
+ WatchedSourceIdsIds &watchedSourceIdsIds);
FileState parseTypeInfo(const Storage::Synchronization::ProjectData &projectData,
Utils::SmallStringView qmltypesPath,
Storage::Synchronization::SynchronizationPackage &package,
- SourceIdsData &sourceIdData);
+ NotUpdatedSourceIds &notUpdatedSourceIds);
void parseQmlComponents(Components components,
SourceId directorySourceId,
SourceContextId directoryId,
Storage::Synchronization::SynchronizationPackage &package,
- SourceIdsData &sourceIdData,
+ NotUpdatedSourceIds &notUpdatedSourceIds,
+ WatchedSourceIdsIds &watchedSourceIdsIds,
FileState qmldirState);
void parseQmlComponent(Utils::SmallStringView fileName,
Utils::SmallStringView directory,
Storage::Synchronization::ExportedTypes exportedTypes,
SourceId directorySourceId,
Storage::Synchronization::SynchronizationPackage &package,
- SourceIdsData &sourceIdData,
+ NotUpdatedSourceIds &notUpdatedSourceIds,
+ WatchedSourceIdsIds &watchedSourceIdsIds,
FileState qmldirState);
void parseQmlComponent(SourceId sourceId,
Storage::Synchronization::SynchronizationPackage &package,
- SourceIdsData &sourceIdData);
+ NotUpdatedSourceIds &notUpdatedSourceIds);
FileState fileState(SourceId sourceId,
Storage::Synchronization::SynchronizationPackage &package,
- SourceIdsData &sourceIdData) const;
+ NotUpdatedSourceIds &notUpdatedSourceIds) const;
private:
+ std::vector<IdPaths> m_changedIdPaths;
FileSystemInterface &m_fileSystem;
ProjectStorageInterface &m_projectStorage;
FileStatusCache &m_fileStatusCache;
@@ -173,6 +189,7 @@ private:
QmlDocumentParserInterface &m_qmlDocumentParser;
QmlTypesParserInterface &m_qmlTypesParser;
ProjectStoragePathWatcherInterface &m_pathWatcher;
+ ProjectPartId m_projectPartId;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.cpp b/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.cpp
index 97aac6a8577..3e9ac43deda 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.cpp
+++ b/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.cpp
@@ -10,7 +10,7 @@
#include <sqlitedatabase.h>
-#ifdef QDS_HAS_QMLDOM
+#ifdef QDS_BUILD_QMLPARSER
#include <private/qqmldomtop_p.h>
#endif
@@ -19,7 +19,7 @@
namespace QmlDesigner {
-#ifdef QDS_HAS_QMLDOM
+#ifdef QDS_BUILD_QMLPARSER
namespace QmlDom = QQmlJS::Dom;
@@ -32,9 +32,9 @@ int convertVersionNumber(qint32 versionNumber)
return versionNumber < 0 ? -1 : versionNumber;
}
-Storage::Synchronization::Version convertVersion(QmlDom::Version version)
+Storage::Version convertVersion(QmlDom::Version version)
{
- return Storage::Synchronization::Version{convertVersionNumber(version.majorVersion),
+ return Storage::Version{convertVersionNumber(version.majorVersion),
convertVersionNumber(version.minorVersion)};
}
@@ -66,7 +66,7 @@ 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::Synchronization::Version{}, sourceId);
+ return Storage::Synchronization::Import(moduleId, Storage::Version{}, sourceId);
}
if (uri.kind() == QmlUriKind::ModuleUri) {
@@ -109,11 +109,11 @@ void addImports(Storage::Synchronization::Imports &imports,
}
auto localDirectoryModuleId = storage.moduleId(directoryPath);
- imports.emplace_back(localDirectoryModuleId, Storage::Synchronization::Version{}, sourceId);
+ imports.emplace_back(localDirectoryModuleId, Storage::Version{}, sourceId);
++importCount;
auto qmlModuleId = storage.moduleId("QML");
- imports.emplace_back(qmlModuleId, Storage::Synchronization::Version{}, sourceId);
+ imports.emplace_back(qmlModuleId, Storage::Version{}, sourceId);
++importCount;
auto end = imports.end();
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h b/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h
index 744825aadc5..2896d54ebe7 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h
@@ -18,7 +18,7 @@ public:
using ProjectStorage = QmlDesigner::ProjectStorage<Sqlite::Database>;
using PathCache = QmlDesigner::SourcePathCache<ProjectStorage, NonLockingMutex>;
-#ifdef QDS_HAS_QMLDOM
+#ifdef QDS_BUILD_QMLPARSER
QmlDocumentParser(ProjectStorage &storage, PathCache &pathCache)
: m_storage{storage}
, m_pathCache{pathCache}
@@ -35,7 +35,7 @@ public:
private:
// m_pathCache and m_storage are only used when compiled for QDS
-#ifdef QDS_HAS_QMLDOM
+#ifdef QDS_BUILD_QMLPARSER
ProjectStorage &m_storage;
PathCache &m_pathCache;
#endif
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.cpp b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.cpp
index bca7b3279d8..c858076aa19 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.cpp
+++ b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.cpp
@@ -4,11 +4,10 @@
#include "qmltypesparser.h"
#include "projectstorage.h"
-#include "sourcepathcache.h"
#include <sqlitedatabase.h>
-#ifdef QDS_HAS_QMLDOM
+#ifdef QDS_BUILD_QMLPARSER
#include <private/qqmldomtop_p.h>
#include <private/qqmljstypedescriptionreader_p.h>
#endif
@@ -20,7 +19,7 @@
namespace QmlDesigner {
-#ifdef QDS_HAS_QMLDOM
+#ifdef QDS_BUILD_QMLPARSER
namespace QmlDom = QQmlJS::Dom;
@@ -63,7 +62,7 @@ void appendImports(Storage::Synchronization::Imports &imports,
moduleName.append("-cppnative");
ModuleId cppModuleId = storage.moduleId(moduleName);
- imports.emplace_back(cppModuleId, Storage::Synchronization::Version{}, sourceId);
+ imports.emplace_back(cppModuleId, Storage::Version{}, sourceId);
}
void addImports(Storage::Synchronization::Imports &imports,
@@ -75,10 +74,10 @@ void addImports(Storage::Synchronization::Imports &imports,
for (const QString &dependency : dependencies)
appendImports(imports, dependency, sourceId, storage);
- imports.emplace_back(cppModuleId, Storage::Synchronization::Version{}, sourceId);
+ imports.emplace_back(cppModuleId, Storage::Version{}, sourceId);
if (ModuleId qmlCppModuleId = storage.moduleId("QML-cppnative"); cppModuleId != qmlCppModuleId)
- imports.emplace_back(qmlCppModuleId, Storage::Synchronization::Version{}, sourceId);
+ imports.emplace_back(qmlCppModuleId, Storage::Version{}, sourceId);
}
Storage::TypeTraits createTypeTraits(QQmlJSScope::AccessSemantics accessSematics)
@@ -97,9 +96,9 @@ Storage::TypeTraits createTypeTraits(QQmlJSScope::AccessSemantics accessSematics
return Storage::TypeTraits::None;
}
-Storage::Synchronization::Version createVersion(QTypeRevision qmlVersion)
+Storage::Version createVersion(QTypeRevision qmlVersion)
{
- return Storage::Synchronization::Version{qmlVersion.majorVersion(), qmlVersion.minorVersion()};
+ return Storage::Version{qmlVersion.majorVersion(), qmlVersion.minorVersion()};
}
Storage::Synchronization::ExportedTypes createExports(const QList<QQmlJSScope::Export> &qmlExports,
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h
index 09513bb74e3..c1d9a3a0d45 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h
@@ -22,16 +22,13 @@ class QmlTypesParser : public QmlTypesParserInterface
{
public:
using ProjectStorage = QmlDesigner::ProjectStorage<Sqlite::Database>;
- using PathCache = QmlDesigner::SourcePathCache<ProjectStorage, NonLockingMutex>;
-#ifdef QDS_HAS_QMLDOM
- QmlTypesParser(PathCache &pathCache, ProjectStorage &storage)
- : m_pathCache{pathCache}
- , m_storage{storage}
+#ifdef QDS_BUILD_QMLPARSER
+ QmlTypesParser(ProjectStorage &storage)
+ : m_storage{storage}
{}
#else
- QmlTypesParser(PathCache &, ProjectStorage &)
- {}
+ QmlTypesParser(ProjectStorage &) {}
#endif
void parse(const QString &sourceContent,
@@ -40,9 +37,7 @@ public:
const Storage::Synchronization::ProjectData &projectData) override;
private:
- // m_pathCache and m_storage are only used when compiled for QDS
-#ifdef QDS_HAS_QMLDOM
- [[maybe_unused]] PathCache &m_pathCache;
+#ifdef QDS_BUILD_QMLPARSER
ProjectStorage &m_storage;
#endif
};
diff --git a/src/plugins/qmldesigner/designmodewidget.cpp b/src/plugins/qmldesigner/designmodewidget.cpp
index 2acdff18230..1bb427bd055 100644
--- a/src/plugins/qmldesigner/designmodewidget.cpp
+++ b/src/plugins/qmldesigner/designmodewidget.cpp
@@ -20,6 +20,7 @@
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/modemanager.h>
#include <qmldesigner/qmldesignerconstants.h>
+#include <qmldesignerbase/qmldesignerbaseplugin.h>
#include <coreplugin/outputpane.h>
#include <coreplugin/modemanager.h>
@@ -39,6 +40,7 @@
#include <utils/stylehelper.h>
#include <QActionGroup>
+#include <QApplication>
#include <QBoxLayout>
#include <QComboBox>
#include <QDir>
@@ -92,6 +94,8 @@ DesignModeWidget::DesignModeWidget()
, m_crumbleBar(new CrumbleBar(this))
{
setAcceptDrops(true);
+ if (Utils::StyleHelper::isQDSTheme())
+ qApp->setStyle(QmlDesignerBasePlugin::style());
}
DesignModeWidget::~DesignModeWidget()
@@ -182,6 +186,7 @@ void DesignModeWidget::setup()
Core::ICore::resourcePath("qmldesigner/workspacePresets/").toString());
QString sheet = QString::fromUtf8(Utils::FileReader::fetchQrc(":/qmldesigner/dockwidgets.css"));
+ sheet += QString::fromUtf8(Utils::FileReader::fetchQrc(":/qmldesigner/scrollbar.css"));
m_dockManager->setStyleSheet(Theme::replaceCssColors(sheet));
// Setup icons
@@ -216,14 +221,29 @@ void DesignModeWidget::setup()
mworkspaces->setOnAllDisabledBehavior(Core::ActionContainer::Show);
// Connect opening of the 'workspaces' menu with creation of the workspaces menu
connect(mworkspaces->menu(), &QMenu::aboutToShow, this, &DesignModeWidget::aboutToShowWorkspaces);
- // Disable workspace menu when context is different to C_DESIGN_MODE
- connect(Core::ICore::instance(), &Core::ICore::contextChanged,
- this, [mworkspaces](const Core::Context &context){
- if (context.contains(Core::Constants::C_DESIGN_MODE))
+
+ Core::ActionContainer *mpanes = Core::ActionManager::actionContainer(Core::Constants::M_VIEW_PANES);
+
+ // Initially disable menus
+ mviews->menu()->setEnabled(false);
+ mworkspaces->menu()->setEnabled(false);
+ mpanes->menu()->setEnabled(false);
+
+ // Enable/disable menus when mode is different to MODE_DESIGN
+ connect(Core::ModeManager::instance(),
+ &Core::ModeManager::currentModeChanged,
+ this,
+ [mviews, mworkspaces, mpanes](Utils::Id mode, Utils::Id) {
+ if (mode == Core::Constants::MODE_DESIGN) {
+ mviews->menu()->setEnabled(true);
mworkspaces->menu()->setEnabled(true);
- else
+ mpanes->menu()->setEnabled(true);
+ } else {
+ mviews->menu()->setEnabled(false);
mworkspaces->menu()->setEnabled(false);
- });
+ mpanes->menu()->setEnabled(false);
+ }
+ });
// Create a DockWidget for each QWidget and add them to the DockManager
const Core::Context designContext(Core::Constants::C_DESIGN_MODE);
@@ -231,60 +251,48 @@ void DesignModeWidget::setup()
// First get all navigation views
QList<Core::INavigationWidgetFactory *> factories = Core::INavigationWidgetFactory::allNavigationFactories();
-
- QList<Core::Command*> viewCommands;
+ QList<Core::Command *> viewCommands;
+ const QList<Utils::Id> navigationViewIds = {"Projects", "File System", "Open Documents"};
for (Core::INavigationWidgetFactory *factory : factories) {
- Core::NavigationView navigationView;
- navigationView.widget = nullptr;
- QString uniqueId;
- QString title;
+ Core::NavigationView navigationView = {nullptr, {}};
- if (factory->id() == "Projects") {
- navigationView = factory->createWidget();
- hideToolButtons(navigationView.dockToolBarWidgets);
- navigationView.widget->setWindowTitle(tr(factory->id().name()));
- uniqueId = "Projects";
- title = "Projects";
- }
- if (factory->id() == "File System") {
- navigationView = factory->createWidget();
- hideToolButtons(navigationView.dockToolBarWidgets);
- navigationView.widget->setWindowTitle(tr(factory->id().name()));
- uniqueId = "FileSystem";
- title = "File System";
- }
- if (factory->id() == "Open Documents") {
- navigationView = factory->createWidget();
- hideToolButtons(navigationView.dockToolBarWidgets);
- navigationView.widget->setWindowTitle(tr(factory->id().name()));
- uniqueId = "OpenDocuments";
- title = "Open Documents";
- }
+ if (!navigationViewIds.contains(factory->id()))
+ continue;
- if (navigationView.widget) {
- // Apply stylesheet to QWidget
- QByteArray sheet = Utils::FileReader::fetchQrc(":/qmldesigner/stylesheet.css");
- sheet += Utils::FileReader::fetchQrc(":/qmldesigner/scrollbar.css");
- sheet += "QLabel { background-color: creatorTheme.DSsectionHeadBackground; }";
- navigationView.widget->setStyleSheet(Theme::replaceCssColors(QString::fromUtf8(sheet)));
-
- // Create DockWidget
- ADS::DockWidget *dockWidget = new ADS::DockWidget(uniqueId);
- dockWidget->setWidget(navigationView.widget);
- dockWidget->setWindowTitle(title);
- m_dockManager->addDockWidget(ADS::NoDockWidgetArea, dockWidget);
-
- // Set unique id as object name
- navigationView.widget->setObjectName(uniqueId);
-
- // Create menu action
- auto command = Core::ActionManager::registerAction(dockWidget->toggleViewAction(),
- actionToggle.withSuffix(uniqueId + "Widget"),
- designContext);
- command->setAttribute(Core::Command::CA_Hide);
- viewCommands.append(command);
- }
+ navigationView = factory->createWidget();
+
+ if (!navigationView.widget)
+ continue;
+
+ hideToolButtons(navigationView.dockToolBarWidgets);
+ navigationView.widget->setWindowTitle(tr(factory->id().name()));
+
+ QString idString = factory->id().toSetting().toString();
+ const QString title = idString;
+ const QString uniqueId = idString.remove(" "); // title without whitespaces
+
+ // Apply stylesheet to QWidget
+ QByteArray sheet = Utils::FileReader::fetchQrc(":/qmldesigner/stylesheet.css");
+ sheet += Utils::FileReader::fetchQrc(":/qmldesigner/scrollbar.css");
+ sheet += "QLabel { background-color: creatorTheme.DSsectionHeadBackground; }";
+ navigationView.widget->setStyleSheet(Theme::replaceCssColors(QString::fromUtf8(sheet)));
+
+ // Create DockWidget
+ ADS::DockWidget *dockWidget = new ADS::DockWidget(uniqueId);
+ dockWidget->setWidget(navigationView.widget);
+ dockWidget->setWindowTitle(title);
+ m_dockManager->addDockWidget(ADS::NoDockWidgetArea, dockWidget);
+
+ // Set unique id as object name
+ navigationView.widget->setObjectName(uniqueId);
+
+ // Create menu action
+ auto command = Core::ActionManager::registerAction(dockWidget->toggleViewAction(),
+ actionToggle.withSuffix(uniqueId + "Widget"),
+ designContext);
+ command->setAttribute(Core::Command::CA_Hide);
+ viewCommands.append(command);
}
// Afterwards get all the other widgets
@@ -303,7 +311,8 @@ void DesignModeWidget::setup()
// Create menu action
auto command = Core::ActionManager::registerAction(dockWidget->toggleViewAction(),
- actionToggle.withSuffix(widgetInfo.uniqueId + "Widget"),
+ actionToggle.withSuffix(
+ widgetInfo.uniqueId + "Widget"),
designContext);
command->setAttribute(Core::Command::CA_Hide);
viewCommands.append(command);
@@ -328,22 +337,13 @@ void DesignModeWidget::setup()
command->setAttribute(Core::Command::CA_Hide);
viewCommands.append(command);
- connect(command->action(), &QAction::triggered, this, [command]() {
- if (!command->action()->isChecked())
- return;
-
- auto cmd = Core::ActionManager::command("QtCreator.Pane.ApplicationOutput");
- QTC_ASSERT(cmd, return);
- cmd->action()->trigger();
- });
-
connect(outputPanePlaceholder,
&Core::OutputPanePlaceHolder::visibilityChangeRequested,
m_outputPaneDockWidget,
&ADS::DockWidget::toggleView);
}
- std::sort(viewCommands.begin(), viewCommands.end(), [](Core::Command *first, Core::Command *second){
+ std::sort(viewCommands.begin(), viewCommands.end(), [](Core::Command *first, Core::Command *second) {
return first->description() < second->description();
});
@@ -356,7 +356,10 @@ void DesignModeWidget::setup()
toolBar->addAction(viewManager().componentViewAction());
toolBar->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
- DesignerActionToolBar *designerToolBar = QmlDesignerPlugin::instance()->viewManager().designerActionManager().createToolBar(m_toolBar);
+ DesignerActionToolBar *designerToolBar = QmlDesignerPlugin::instance()
+ ->viewManager()
+ .designerActionManager()
+ .createToolBar(m_toolBar);
designerToolBar->layout()->addWidget(toolBar);
@@ -365,9 +368,14 @@ void DesignModeWidget::setup()
m_toolBar->setToolbarCreationFlags(Core::EditorToolBar::FlagsStandalone);
m_toolBar->setNavigationVisible(true);
- connect(m_toolBar, &Core::EditorToolBar::goForwardClicked, this, &DesignModeWidget::toolBarOnGoForwardClicked);
- connect(m_toolBar, &Core::EditorToolBar::goBackClicked, this, &DesignModeWidget::toolBarOnGoBackClicked);
-
+ connect(m_toolBar,
+ &Core::EditorToolBar::goForwardClicked,
+ this,
+ &DesignModeWidget::toolBarOnGoForwardClicked);
+ connect(m_toolBar,
+ &Core::EditorToolBar::goBackClicked,
+ this,
+ &DesignModeWidget::toolBarOnGoBackClicked);
QToolBar* toolBarWrapper = new QToolBar();
toolBarWrapper->addWidget(m_toolBar);
@@ -375,32 +383,8 @@ void DesignModeWidget::setup()
toolBarWrapper->setMovable(false);
addToolBar(Qt::TopToolBarArea, toolBarWrapper);
-
addSpacerToToolBar(toolBar);
- auto workspaceComboBox = new QComboBox();
- workspaceComboBox->setMinimumWidth(120);
- workspaceComboBox->setToolTip(tr("Switch the active workspace."));
- auto sortedWorkspaces = m_dockManager->workspaces();
- Utils::sort(sortedWorkspaces);
- workspaceComboBox->addItems(sortedWorkspaces);
- workspaceComboBox->setCurrentText(m_dockManager->activeWorkspace());
- toolBar->addWidget(workspaceComboBox);
-
- connect(m_dockManager, &ADS::DockManager::workspaceListChanged,
- workspaceComboBox, [this, workspaceComboBox]() {
- workspaceComboBox->clear();
- auto sortedWorkspaces = m_dockManager->workspaces();
- Utils::sort(sortedWorkspaces);
- workspaceComboBox->addItems(sortedWorkspaces);
- workspaceComboBox->setCurrentText(m_dockManager->activeWorkspace());
- });
- connect(m_dockManager, &ADS::DockManager::workspaceLoaded, workspaceComboBox, &QComboBox::setCurrentText);
- connect(workspaceComboBox, &QComboBox::activated,
- m_dockManager, [this, workspaceComboBox]([[maybe_unused]] int index) {
- m_dockManager->openWorkspace(workspaceComboBox->currentText());
- });
-
const QIcon gaIcon = Utils::StyleHelper::getIconFromIconFont(
fontName, Theme::getIconUnicode(Theme::Icon::annotationBubble),
36, 36, Theme::getColor(Theme::IconsBaseColor));
@@ -412,7 +396,6 @@ void DesignModeWidget::setup()
m_globalAnnotationEditor.showWidget();
}
});
-
}
if (currentDesignDocument())
@@ -444,8 +427,6 @@ void DesignModeWidget::setup()
}
});
-
-
viewManager().enableWidgets();
readSettings();
show();
@@ -453,15 +434,15 @@ void DesignModeWidget::setup()
void DesignModeWidget::aboutToShowWorkspaces()
{
- Core::ActionContainer *aci = Core::ActionManager::actionContainer(QmlDesigner::Constants::M_VIEW_WORKSPACES);
+ Core::ActionContainer *aci = Core::ActionManager::actionContainer(
+ QmlDesigner::Constants::M_VIEW_WORKSPACES);
QMenu *menu = aci->menu();
menu->clear();
auto *ag = new QActionGroup(menu);
connect(ag, &QActionGroup::triggered, this, [this](QAction *action) {
- QString workspace = action->data().toString();
- m_dockManager->openWorkspace(workspace);
+ m_dockManager->openWorkspace(action->data().toString());
});
QAction *action = menu->addAction(tr("Manage..."));
@@ -469,21 +450,18 @@ void DesignModeWidget::aboutToShowWorkspaces()
QAction *resetWorkspace = menu->addAction(tr("Reset Active"));
connect(resetWorkspace, &QAction::triggered, this, [this]() {
- if (m_dockManager->resetWorkspacePreset(m_dockManager->activeWorkspace()))
+ if (m_dockManager->resetWorkspacePreset(m_dockManager->activeWorkspace()->fileName()))
m_dockManager->reloadActiveWorkspace();
});
menu->addSeparator();
- // Sort the list of workspaces
- auto sortedWorkspaces = m_dockManager->workspaces();
- Utils::sort(sortedWorkspaces);
-
- for (const auto &workspace : std::as_const(sortedWorkspaces)) {
- QAction *action = ag->addAction(workspace);
- action->setData(workspace);
+ auto workspaces = m_dockManager->workspaces();
+ for (const auto &workspace : std::as_const(workspaces)) {
+ QAction *action = ag->addAction(workspace.name());
+ action->setData(workspace.fileName());
action->setCheckable(true);
- if (workspace == m_dockManager->activeWorkspace())
+ if (workspace == *m_dockManager->activeWorkspace())
action->setChecked(true);
}
menu->addActions(ag->actions());
diff --git a/src/plugins/qmldesigner/puppetenvironmentbuilder.cpp b/src/plugins/qmldesigner/puppetenvironmentbuilder.cpp
index 7d7957753c4..079cc0a326b 100644
--- a/src/plugins/qmldesigner/puppetenvironmentbuilder.cpp
+++ b/src/plugins/qmldesigner/puppetenvironmentbuilder.cpp
@@ -51,6 +51,7 @@ QProcessEnvironment PuppetEnvironmentBuilder::processEnvironment() const
addMultiLanguageDatatbase();
addImportPaths();
addCustomFileSelectors();
+ addDisableDeferredProperties();
qCInfo(puppetEnvirmentBuild) << "Puppet environment:" << m_environment.toStringList();
@@ -228,6 +229,11 @@ void PuppetEnvironmentBuilder::addCustomFileSelectors() const
qCInfo(puppetEnvirmentBuild) << "Puppet selectors:" << customFileSelectors;
}
+void PuppetEnvironmentBuilder::addDisableDeferredProperties() const
+{
+ m_environment.set("QML_DISABLE_INTERNAL_DEFERRED_PROPERTIES", "true");
+}
+
PuppetType PuppetEnvironmentBuilder::determinePuppetType() const
{
if (m_target && m_target->kit() && m_target->kit()->isValid()) {
diff --git a/src/plugins/qmldesigner/puppetenvironmentbuilder.h b/src/plugins/qmldesigner/puppetenvironmentbuilder.h
index e3ef33a7211..3c2ffba271e 100644
--- a/src/plugins/qmldesigner/puppetenvironmentbuilder.h
+++ b/src/plugins/qmldesigner/puppetenvironmentbuilder.h
@@ -49,6 +49,7 @@ private:
void addMultiLanguageDatatbase() const;
void addImportPaths() const;
void addCustomFileSelectors() const;
+ void addDisableDeferredProperties() const;
private:
ProjectExplorer::Target *m_target = nullptr;
diff --git a/src/plugins/qmldesigner/qmldesignerconstants.h b/src/plugins/qmldesigner/qmldesignerconstants.h
index 18039187509..d38dad74c7e 100644
--- a/src/plugins/qmldesigner/qmldesignerconstants.h
+++ b/src/plugins/qmldesigner/qmldesignerconstants.h
@@ -30,6 +30,7 @@ const char TOGGLE_RIGHT_SIDEBAR[] = "QmlDesigner.ToggleRightSideBar";
const char TOGGLE_STATES_EDITOR[] = "QmlDesigner.ToggleStatesEditor";
const char GO_INTO_COMPONENT[] = "QmlDesigner.GoIntoComponent";
const char EXPORT_AS_IMAGE[] = "QmlDesigner.ExportAsImage";
+const char TAKE_SCREENSHOT[] = "QmlDesigner.TakeScreenshot";
const char FORMEDITOR_REFRESH[] = "QmlDesigner.FormEditor.Refresh";
const char FORMEDITOR_SNAPPING[] = "QmlDesigner.FormEditor.Snapping";
const char FORMEDITOR_NO_SNAPPING[] = "QmlDesigner.FormEditor.NoSnapping";
@@ -61,7 +62,7 @@ const char EDIT3D_PARTICLES_SEEKER[] = "QmlDesigner.Editor3D.ParticlesSeeker"
const char EDIT3D_PARTICLES_RESTART[] = "QmlDesigner.Editor3D.ParticlesRestart";
const char EDIT3D_VISIBILITY_TOGGLES[] = "QmlDesigner.Editor3D.VisibilityToggles";
const char EDIT3D_BACKGROUND_COLOR_ACTIONS[] = "QmlDesigner.Editor3D.BackgroundColorActions";
-
+const char EDIT3D_BAKE_LIGHTS[] = "QmlDesigner.Editor3D.BakeLights";
const char QML_DESIGNER_SUBFOLDER[] = "/designer/";
const char COMPONENT_BUNDLES_FOLDER[] = "/ComponentBundles";
diff --git a/src/plugins/qmldesigner/qmldesignerexternaldependencies.cpp b/src/plugins/qmldesigner/qmldesignerexternaldependencies.cpp
index 8282ea419a4..1bd58991657 100644
--- a/src/plugins/qmldesigner/qmldesignerexternaldependencies.cpp
+++ b/src/plugins/qmldesigner/qmldesignerexternaldependencies.cpp
@@ -15,6 +15,7 @@
#include <qmlpuppetpaths.h>
#include <qtsupport/baseqtversion.h>
#include <qtsupport/qtkitinformation.h>
+#include <qmlprojectmanager/buildsystem/qmlbuildsystem.h>
#include <coreplugin/icore.h>
@@ -186,4 +187,95 @@ Utils::FilePath ExternalDependencies::qmlPuppetPath() const
return puppetPath;
}
+namespace {
+
+QString qmlPath(ProjectExplorer::Target *target)
+{
+ auto kit = target->kit();
+
+ if (!kit)
+ return {};
+
+ auto qtVersion = QtSupport::QtKitAspect::qtVersion(kit);
+ if (!qtVersion)
+ return {};
+
+ return qtVersion->qmlPath().toString();
+}
+
+std::tuple<ProjectExplorer::Project *, ProjectExplorer::Target *, QmlProjectManager::QmlBuildSystem *>
+activeProjectEntries()
+{
+ auto project = ProjectExplorer::ProjectManager::startupProject();
+
+ if (!project)
+ return {};
+
+ auto target = project->activeTarget();
+
+ if (!target)
+ return {};
+
+ const auto qmlBuildSystem = qobject_cast<QmlProjectManager::QmlBuildSystem *>(
+ target->buildSystem());
+
+ if (qmlBuildSystem)
+ return std::make_tuple(project, target, qmlBuildSystem);
+
+ return {};
+}
+} // namespace
+
+QStringList ExternalDependencies::modulePaths() const
+{
+ auto [project, target, qmlBuildSystem] = activeProjectEntries();
+
+ if (project && target && qmlBuildSystem) {
+ QStringList modulePaths;
+
+ if (auto path = qmlPath(target); !path.isEmpty())
+ modulePaths.push_back(path);
+
+ for (const QString &modulePath : qmlBuildSystem->customImportPaths())
+ modulePaths.append(project->projectDirectory().pathAppended(modulePath).toString());
+
+ return modulePaths;
+ }
+
+ return {};
+}
+
+QStringList ExternalDependencies::projectModulePaths() const
+{
+ auto [project, target, qmlBuildSystem] = activeProjectEntries();
+
+ if (project && target && qmlBuildSystem) {
+ QStringList modulePaths;
+
+ for (const QString &modulePath : qmlBuildSystem->customImportPaths())
+ modulePaths.append(project->projectDirectory().pathAppended(modulePath).toString());
+ }
+
+ return {};
+}
+
+bool ExternalDependencies::isQt6Project() const
+{
+ auto [project, target, qmlBuildSystem] = activeProjectEntries();
+
+ return qmlBuildSystem && qmlBuildSystem->qt6Project();
+}
+
+QString ExternalDependencies::qtQuickVersion() const
+{
+ auto [project, target, qmlBuildSystem] = activeProjectEntries();
+
+ return qmlBuildSystem ? qmlBuildSystem->versionQtQuick() : QString{};
+}
+
+Utils::FilePath ExternalDependencies::resourcePath(const QString &relativePath) const
+{
+ return Core::ICore::resourcePath(relativePath);
+}
+
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerexternaldependencies.h b/src/plugins/qmldesigner/qmldesignerexternaldependencies.h
index 3e57847ce9d..0f6acf2c106 100644
--- a/src/plugins/qmldesigner/qmldesignerexternaldependencies.h
+++ b/src/plugins/qmldesigner/qmldesignerexternaldependencies.h
@@ -36,6 +36,11 @@ public:
PuppetStartData puppetStartData(const class Model &model) const override;
bool instantQmlTextUpdate() const override;
Utils::FilePath qmlPuppetPath() const override;
+ QStringList modulePaths() const override;
+ QStringList projectModulePaths() const override;
+ bool isQt6Project() const override;
+ QString qtQuickVersion() const override;
+ Utils::FilePath resourcePath(const QString &relativePath) const override;
private:
const DesignerSettings &m_designerSettings;
diff --git a/src/plugins/qmldesigner/qmldesignerplugin.cpp b/src/plugins/qmldesigner/qmldesignerplugin.cpp
index 039528475a5..a25bbb832b8 100644
--- a/src/plugins/qmldesigner/qmldesignerplugin.cpp
+++ b/src/plugins/qmldesigner/qmldesignerplugin.cpp
@@ -31,7 +31,6 @@
#include <texttool/texttool.h>
#include <timelineeditor/timelineview.h>
#include <transitioneditor/transitioneditorview.h>
-
#include <qmljseditor/qmljseditor.h>
#include <qmljseditor/qmljseditorconstants.h>
#include <qmljseditor/qmljseditordocument.h>
@@ -66,6 +65,7 @@
#include <utils/algorithm.h>
#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
+#include <utils/uniqueobjectptr.h>
#include <QAction>
#include <QApplication>
@@ -144,6 +144,8 @@ public:
DesignModeWidget mainWidget;
QtQuickDesignerFactory m_qtQuickDesignerFactory;
bool blockEditorChange = false;
+ Utils::UniqueObjectPtr<QToolBar> toolBar;
+ Utils::UniqueObjectPtr<QWidget> statusBar;
};
QmlDesignerPlugin *QmlDesignerPlugin::m_instance = nullptr;
@@ -184,8 +186,9 @@ static bool isDesignerMode(Utils::Id mode)
static bool documentIsAlreadyOpen(DesignDocument *designDocument, Core::IEditor *editor, Utils::Id newMode)
{
return designDocument
- && editor == designDocument->editor()
- && isDesignerMode(newMode);
+ && editor == designDocument->editor()
+ && isDesignerMode(newMode)
+ && designDocument->fileName() == editor->document()->filePath();
}
static bool shouldAssertInException()
@@ -241,7 +244,7 @@ bool QmlDesignerPlugin::initialize(const QStringList & /*arguments*/, QString *e
->addAction(cmd, Core::Constants::G_HELP_SUPPORT);
connect(action, &QAction::triggered, this, [this] {
- lauchFeedbackPopup(Core::Constants::IDE_DISPLAY_NAME);
+ lauchFeedbackPopupInternal(Core::Constants::IDE_DISPLAY_NAME);
});
if (!Utils::HostOsInfo::canCreateOpenGLContext(errorMessage))
@@ -273,8 +276,8 @@ bool QmlDesignerPlugin::initialize(const QStringList & /*arguments*/, QString *e
});
if (QmlProjectManager::QmlProject::isQtDesignStudio()) {
- ToolBar::create();
- ToolBar::createStatusBar();
+ d->toolBar = ToolBar::create();
+ d->statusBar = ToolBar::createStatusBar();
}
return true;
@@ -289,10 +292,10 @@ bool QmlDesignerPlugin::delayedInitialize()
Utils::transform(ExtensionSystem::PluginManager::pluginPaths(), [postfix](const QString &p) {
return QString(p + postfix);
});
- MetaInfo::setPluginPaths(pluginPaths);
- d->viewManager.registerView(
- std::make_unique<ConnectionView>(d->externalDependencies));
+ MetaInfo::initializeGlobal(pluginPaths, d->externalDependencies);
+
+ d->viewManager.registerView(std::make_unique<ConnectionView>(d->externalDependencies));
auto timelineView = d->viewManager.registerView(
std::make_unique<TimelineView>(d->externalDependencies));
@@ -334,8 +337,6 @@ bool QmlDesignerPlugin::delayedInitialize()
Core::ICore::appendAboutInformation(tr("Licensee: %1").arg(licensee()));
}
- MetaInfo::global();
-
return true;
}
@@ -438,14 +439,12 @@ void QmlDesignerPlugin::integrateIntoQtCreator(QWidget *modeWidget)
&Core::ModeManager::currentModeChanged,
[this](Utils::Id newMode, Utils::Id oldMode) {
Core::IEditor *currentEditor = Core::EditorManager::currentEditor();
- if (d && currentEditor && checkIfEditorIsQtQuick(currentEditor)
+ if (isDesignerMode(newMode) && checkIfEditorIsQtQuick(currentEditor)
&& !documentIsAlreadyOpen(currentDesignDocument(), currentEditor, newMode)) {
- if (isDesignerMode(newMode)) {
- showDesigner();
- } else if (currentDesignDocument()
- || (!isDesignerMode(newMode) && isDesignerMode(oldMode))) {
- hideDesigner();
- }
+ showDesigner();
+ } else if (currentDesignDocument()
+ || (!isDesignerMode(newMode) && isDesignerMode(oldMode))) {
+ hideDesigner();
}
});
}
@@ -731,6 +730,18 @@ void QmlDesignerPlugin::trackWidgetFocusTime(QWidget *widget, const QString &ide
void QmlDesignerPlugin::lauchFeedbackPopup(const QString &identifier)
{
+ if (Core::ModeManager::currentModeId() == Core::Constants::MODE_DESIGN)
+ lauchFeedbackPopupInternal(identifier);
+}
+
+void QmlDesignerPlugin::handleFeedback(const QString &feedback, int rating)
+{
+ const QString identifier = sender()->property("identifier").toString();
+ emit usageStatisticsInsertFeedback(identifier, feedback, rating);
+}
+
+void QmlDesignerPlugin::lauchFeedbackPopupInternal(const QString &identifier)
+{
m_feedbackWidget = new QQuickWidget(Core::ICore::dialogParent());
m_feedbackWidget->setObjectName(Constants::OBJECT_NAME_TOP_FEEDBACK);
@@ -767,12 +778,6 @@ void QmlDesignerPlugin::lauchFeedbackPopup(const QString &identifier)
m_feedbackWidget->show();
}
-void QmlDesignerPlugin::handleFeedback(const QString &feedback, int rating)
-{
- const QString identifier = sender()->property("identifier").toString();
- emit usageStatisticsInsertFeedback(identifier, feedback, rating);
-}
-
void QmlDesignerPlugin::closeFeedbackPopup()
{
if (m_feedbackWidget) {
diff --git a/src/plugins/qmldesigner/qmldesignerplugin.h b/src/plugins/qmldesigner/qmldesignerplugin.h
index 78bf02ac042..ee078b273ab 100644
--- a/src/plugins/qmldesigner/qmldesignerplugin.h
+++ b/src/plugins/qmldesigner/qmldesignerplugin.h
@@ -95,6 +95,7 @@ private slots:
void handleFeedback(const QString &feedback, int rating);
private: // functions
+ void lauchFeedbackPopupInternal(const QString &identifier);
void integrateIntoQtCreator(QWidget *modeWidget);
void showDesigner();
void hideDesigner();
@@ -114,7 +115,6 @@ private: // variables
QmlDesignerPluginPrivate *d = nullptr;
static QmlDesignerPlugin *m_instance;
QElapsedTimer m_usageTimer;
- StudioConfigSettingsPage m_settingsPage;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qmldesignerprojectmanager.cpp b/src/plugins/qmldesigner/qmldesignerprojectmanager.cpp
index a80b3148b36..4d327b5491d 100644
--- a/src/plugins/qmldesigner/qmldesignerprojectmanager.cpp
+++ b/src/plugins/qmldesigner/qmldesignerprojectmanager.cpp
@@ -39,6 +39,7 @@
#include <coreplugin/icore.h>
+#include <QDirIterator>
#include <QFileSystemWatcher>
#include <QQmlEngine>
@@ -175,24 +176,27 @@ class ProjectStorageData
public:
ProjectStorageData(::ProjectExplorer::Project *project)
: database{project->projectDirectory().pathAppended("projectstorage.db").toString()}
+ , projectPartId{ProjectPartId::create(
+ pathCache.sourceId(SourcePath{project->projectDirectory().toString() + "/."}).internalId())}
{}
-
Sqlite::Database database;
ProjectStorage<Sqlite::Database> storage{database, database.isInitialized()};
ProjectStorageUpdater::PathCache pathCache{storage};
FileSystem fileSystem{pathCache};
FileStatusCache fileStatusCache{fileSystem};
QmlDocumentParser qmlDocumentParser{storage, pathCache};
- QmlTypesParser qmlTypesParser{pathCache, storage};
+ QmlTypesParser qmlTypesParser{storage};
ProjectStoragePathWatcher<QFileSystemWatcher, QTimer, ProjectStorageUpdater::PathCache>
pathWatcher{pathCache, fileSystem, &updater};
+ ProjectPartId projectPartId;
ProjectStorageUpdater updater{fileSystem,
storage,
fileStatusCache,
pathCache,
qmlDocumentParser,
qmlTypesParser,
- pathWatcher};
+ pathWatcher,
+ projectPartId};
};
std::unique_ptr<ProjectStorageData> createProjectStorageData(::ProjectExplorer::Project *project)
@@ -339,18 +343,25 @@ void projectQmldirPaths(::ProjectExplorer::Target *target, QStringList &qmldirPa
qmldirPaths.push_back(QDir::cleanPath(pojectDirectory.absoluteFilePath(importPath))
+ "/qmldir");
}
-#ifdef QDS_HAS_QMLDOM
-bool skipPath(const std::filesystem::path &path)
+
+#ifdef QDS_HAS_QMLPRIVATE
+QStringView currentDirectoryName(const QString &path)
{
- auto directory = path.filename();
- qDebug() << path.string().data();
+ auto found = std::find(path.rbegin(), path.rend(), u'/');
- bool skip = directory == "QtApplicationManager" || directory == "QtInterfaceFramework"
- || directory == "QtOpcUa" || directory == "Qt3D" || directory == "Qt3D"
- || directory == "Scene2D" || directory == "Scene3D" || directory == "QtWayland"
- || directory == "Qt5Compat";
- if (skip)
- qDebug() << "skip" << path.string().data();
+ if (found == path.rend())
+ return {};
+
+ return QStringView{found.base(), path.end()};
+}
+bool skipPath(const QString &path)
+{
+ auto directory = currentDirectoryName(path);
+
+ bool skip = directory == u"QtApplicationManager" || directory == u"QtInterfaceFramework"
+ || directory == u"QtOpcUa" || directory == u"Qt3D" || directory == u"Qt3D"
+ || directory == u"Scene2D" || directory == u"Scene3D" || directory == u"QtWayland"
+ || directory == u"Qt5Compat";
return skip;
}
@@ -359,22 +370,17 @@ bool skipPath(const std::filesystem::path &path)
void qtQmldirPaths([[maybe_unused]] ::ProjectExplorer::Target *target,
[[maybe_unused]] QStringList &qmldirPaths)
{
-#ifdef QDS_HAS_QMLDOM
- const QString installDirectory = qmlPath(target).toString();
+#ifdef QDS_HAS_QMLPRIVATE
+ if (useProjectStorage()) {
+ const QString installDirectory = qmlPath(target).toString();
+ QDirIterator dirIterator{installDirectory, QDir::Dirs, QDirIterator::Subdirectories};
- const std::filesystem::path installDirectoryPath{installDirectory.toStdString()};
+ while (dirIterator.hasNext()) {
+ auto directoryPath = dirIterator.next();
- auto current = std::filesystem::recursive_directory_iterator{installDirectoryPath};
- auto end = std::filesystem::end(current);
- for (; current != end; ++current) {
- const auto &entry = *current;
- auto path = entry.path();
- if (current.depth() < 3 && !current->is_regular_file() && skipPath(path)) {
- current.disable_recursion_pending();
- continue;
- }
- if (path.filename() == "qmldir") {
- qmldirPaths.push_back(QString::fromStdU16String(path.generic_u16string()));
+ QString qmldirPath = directoryPath + "/qmldir";
+ if (!skipPath(directoryPath) && QFileInfo::exists(qmldirPath))
+ qmldirPaths.push_back(directoryPath);
}
}
#endif
diff --git a/src/plugins/qmldesigner/qtquickplugin/quick.metainfo b/src/plugins/qmldesigner/qtquickplugin/quick.metainfo
index 45e01621280..f1aeaa9ebbd 100644
--- a/src/plugins/qmldesigner/qtquickplugin/quick.metainfo
+++ b/src/plugins/qmldesigner/qtquickplugin/quick.metainfo
@@ -571,6 +571,7 @@ MetaInfo {
requiredImport: "QtQuick3D"
QmlSource { source: ":/qtquickplugin/source/component3d.qml" }
+ toolTip: qsTr("Allows you to define 3D components inline, within a QML document.")
}
}
diff --git a/src/plugins/qmldesigner/settingspage.cpp b/src/plugins/qmldesigner/settingspage.cpp
index 873811ee28b..8c3222d72c3 100644
--- a/src/plugins/qmldesigner/settingspage.cpp
+++ b/src/plugins/qmldesigner/settingspage.cpp
@@ -41,7 +41,7 @@ namespace Internal {
static QStringList puppetModes()
{
- static QStringList puppetModeList{"", "all", "editormode", "rendermode", "previewmode"};
+ static QStringList puppetModeList{"", "all", "editormode", "rendermode", "previewmode", "bakelightsmode"};
return puppetModeList;
}
diff --git a/src/plugins/qmldesigner/shortcutmanager.cpp b/src/plugins/qmldesigner/shortcutmanager.cpp
index efb3bf49eee..87a873339df 100644
--- a/src/plugins/qmldesigner/shortcutmanager.cpp
+++ b/src/plugins/qmldesigner/shortcutmanager.cpp
@@ -14,11 +14,12 @@
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/command.h>
-#include <coreplugin/icore.h>
-#include <coreplugin/idocument.h>
#include <coreplugin/editormanager/documentmodel.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/coreconstants.h>
+#include <coreplugin/icore.h>
+#include <coreplugin/idocument.h>
+#include <coreplugin/modemanager.h>
#include <qmljseditor/qmljseditorconstants.h>
#include <qmlprojectmanager/qmlprojectmanagerconstants.h>
@@ -39,21 +40,24 @@
#include <QApplication>
#include <QClipboard>
+#include <QMainWindow>
+#include <QStandardPaths>
namespace QmlDesigner {
ShortCutManager::ShortCutManager()
- : QObject(),
- m_exportAsImageAction(tr("Export as &Image...")),
- m_undoAction(tr("&Undo")),
- m_redoAction(tr("&Redo")),
- m_deleteAction(tr("Delete")),
- m_cutAction(tr("Cu&t")),
- m_copyAction(tr("&Copy")),
- m_pasteAction(tr("&Paste")),
- m_duplicateAction(tr("&Duplicate")),
- m_selectAllAction(tr("Select &All")),
- m_escapeAction(this)
+ : QObject()
+ , m_exportAsImageAction(tr("Export as &Image..."))
+ , m_takeScreenshotAction(tr("Take Screenshot"))
+ , m_undoAction(tr("&Undo"))
+ , m_redoAction(tr("&Redo"))
+ , m_deleteAction(tr("Delete"))
+ , m_cutAction(tr("Cu&t"))
+ , m_copyAction(tr("&Copy"))
+ , m_pasteAction(tr("&Paste"))
+ , m_duplicateAction(tr("&Duplicate"))
+ , m_selectAllAction(tr("Select &All"))
+ , m_escapeAction(this)
{
}
@@ -106,12 +110,33 @@ void ShortCutManager::registerActions(const Core::Context &qmlDesignerMainContex
QmlDesignerPlugin::instance()->viewManager().exportAsImage();
});
+ // Edit Global Annotations
QAction *action = new QAction(tr("Edit Global Annotations..."), this);
command = Core::ActionManager::registerAction(action, "Edit.Annotations", qmlDesignerMainContext);
Core::ActionManager::actionContainer(Core::Constants::M_EDIT)
->addAction(command, Core::Constants::G_EDIT_OTHER);
-
connect(action, &QAction::triggered, this, [] { ToolBarBackend::launchGlobalAnnotations(); });
+ connect(Core::ModeManager::instance(), &Core::ModeManager::currentModeChanged, this, [action] {
+ action->setEnabled(Core::ModeManager::currentModeId() == Core::Constants::MODE_DESIGN);
+ });
+ action->setEnabled(false);
+
+ command = Core::ActionManager::registerAction(&m_takeScreenshotAction,
+ QmlDesigner::Constants::TAKE_SCREENSHOT);
+ connect(&m_takeScreenshotAction, &QAction::triggered, [] {
+ const auto folder = Utils::FilePath::fromString(
+ QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation))
+ .pathAppended("QtDesignStudio/screenshots/");
+ folder.createDir();
+
+ const auto file = folder.pathAppended(QDateTime::currentDateTime().toString("dddd-hh-mm-ss")
+ + ".png");
+
+ QPixmap pixmap = Core::ICore::mainWindow()->grab();
+
+ const bool b = pixmap.save(file.toString(), "PNG");
+ qWarning() << "screenshot" << file << b << pixmap;
+ });
Core::ActionContainer *exportMenu = Core::ActionManager::actionContainer(
QmlProjectManager::Constants::EXPORT_MENU);
diff --git a/src/plugins/qmldesigner/shortcutmanager.h b/src/plugins/qmldesigner/shortcutmanager.h
index 9b4762748ef..b97fd834ee7 100644
--- a/src/plugins/qmldesigner/shortcutmanager.h
+++ b/src/plugins/qmldesigner/shortcutmanager.h
@@ -52,6 +52,7 @@ private:
QAction m_saveAction;
QAction m_saveAsAction;
QAction m_exportAsImageAction;
+ QAction m_takeScreenshotAction;
QAction m_closeCurrentEditorAction;
QAction m_closeAllEditorsAction;
QAction m_closeOtherEditorsAction;
diff --git a/src/plugins/qmldesigner/studioplugin/studioplugin.metainfo b/src/plugins/qmldesigner/studioplugin/studioplugin.metainfo
index 94f14c296dd..2998ea2f67b 100644
--- a/src/plugins/qmldesigner/studioplugin/studioplugin.metainfo
+++ b/src/plugins/qmldesigner/studioplugin/studioplugin.metainfo
@@ -34,7 +34,16 @@ MetaInfo {
"QtQuick.Templates",
"QtQuick.Shapes",
"QtQuick.Studio.EventSystem",
- "QtQuick.Studio.EventSimulator"
+ "QtQuick.Studio.EventSimulator",
+ "QtQuick.Pdf",
+ "QmlTime",
+ "Qt.test.controls",
+ "QtOpcUa",
+ "QtVncServer",
+ "QtTextToSpeech",
+ "QtQuick3D MaterialEditor",
+ "QtDataVisualization",
+ "QtQuick3D.ParticleEffects"
]
showTagsForImports: [
diff --git a/src/plugins/qmldesigner/utils/filedownloader.cpp b/src/plugins/qmldesigner/utils/filedownloader.cpp
index b5c735d87a8..7825be5081b 100644
--- a/src/plugins/qmldesigner/utils/filedownloader.cpp
+++ b/src/plugins/qmldesigner/utils/filedownloader.cpp
@@ -253,23 +253,23 @@ void FileDownloader::doProbeUrl()
m_available = true;
emit availableChanged();
+
+ reply->deleteLater();
});
QNetworkReply::connect(reply,
&QNetworkReply::errorOccurred,
this,
- [this](QNetworkReply::NetworkError) {
- QQmlData *data = QQmlData::get(this, false);
- if (!data) {
- qDebug() << Q_FUNC_INFO << "FileDownloader is nullptr.";
- return;
- }
+ [this](QNetworkReply::NetworkError code) {
if (QQmlData::wasDeleted(this)) {
qDebug() << Q_FUNC_INFO << "FileDownloader was deleted.";
return;
}
+ qDebug() << Q_FUNC_INFO << "Network error:" << code
+ << qobject_cast<QNetworkReply *>(sender())->errorString();
+
m_available = false;
emit availableChanged();
});
diff --git a/src/plugins/qmldesigner/utils/fileextractor.cpp b/src/plugins/qmldesigner/utils/fileextractor.cpp
index c6aa83fb7ae..7c32381b69c 100644
--- a/src/plugins/qmldesigner/utils/fileextractor.cpp
+++ b/src/plugins/qmldesigner/utils/fileextractor.cpp
@@ -51,7 +51,11 @@ FileExtractor::FileExtractor(QObject *parent)
// We can not get the uncompressed size of the archive yet, that is why we use an
// approximation. We assume a 50% compression rate.
- int progress = std::min(100ll, currentSize * 100 / m_compressedSize * 2);
+
+ int progress = 0;
+ if (m_compressedSize > 0)
+ progress = std::min(100ll, currentSize * 100 / m_compressedSize * 2);
+
if (progress >= 0) {
m_progress = progress;
emit progressChanged();
@@ -212,6 +216,8 @@ void FileExtractor::extract()
m_timer.start();
m_bytesBefore = QStorageInfo(m_targetPath.toFileInfo().dir()).bytesAvailable();
m_compressedSize = QFileInfo(m_sourceFile.toString()).size();
+ if (m_compressedSize <= 0)
+ qWarning() << "Compressed size for file '" << m_sourceFile << "' is zero or invalid: " << m_compressedSize;
QObject::connect(archive, &Utils::Archive::outputReceived, this, [this](const QString &output) {
m_detailedText += output;
diff --git a/src/plugins/qmldesigner/utils/multifiledownloader.cpp b/src/plugins/qmldesigner/utils/multifiledownloader.cpp
index c36476f05d6..6a8ac9761e9 100644
--- a/src/plugins/qmldesigner/utils/multifiledownloader.cpp
+++ b/src/plugins/qmldesigner/utils/multifiledownloader.cpp
@@ -23,7 +23,10 @@ void MultiFileDownloader::setDownloader(FileDownloader *downloader)
});
QObject::connect(m_downloader, &FileDownloader::progressChanged, this, [this]() {
- m_progress = (m_nextFile + m_downloader->progress()) / m_files.count();
+ double curProgress = m_downloader->progress() / 100.0;
+ double totalProgress = (m_nextFile + curProgress) / m_files.count();
+ m_progress = totalProgress * 100;
+ emit progressChanged();
});
QObject::connect(m_downloader, &FileDownloader::downloadFailed, this, [this]() {
@@ -48,6 +51,7 @@ FileDownloader *MultiFileDownloader::downloader()
void MultiFileDownloader::start()
{
+ m_canceled = false;
emit downloadStarting();
}