aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTim Jenssen <tim.jenssen@qt.io>2023-07-04 20:35:24 +0200
committerTim Jenssen <tim.jenssen@qt.io>2023-07-04 20:36:03 +0200
commitd9910058a394330a404239ca38d95d909f15c68e (patch)
tree22437614d76a7dfe8aabcf7bdfe4c8c46f48fee9 /src
parentae7e72cca51e309b50056fa095f3e913906f367c (diff)
parent7fada70e8f77fdccf7efc931421cf456561e097a (diff)
Merge remote-tracking branch 'origin/qds/dev'
Diffstat (limited to 'src')
m---------src/libs/3rdparty/googletest0
-rw-r--r--src/libs/3rdparty/sqlite/config.h4
-rw-r--r--src/libs/CMakeLists.txt4
-rw-r--r--src/libs/googletest/CMakeLists.txt27
-rw-r--r--src/libs/qmljs/qmljsreformatter.cpp25
-rw-r--r--src/libs/sqlite/CMakeLists.txt30
-rw-r--r--src/libs/sqlite/sqlitebasestatement.cpp3
-rw-r--r--src/libs/sqlite/sqlitebasestatement.h20
-rw-r--r--src/libs/utils/set_algorithm.h59
-rw-r--r--src/libs/utils/smallstringview.h40
-rw-r--r--src/plugins/insight/insightmodel.cpp2
-rw-r--r--src/plugins/mcusupport/test/CMakeLists.txt21
-rw-r--r--src/plugins/projectexplorer/projectwindow.cpp2
-rw-r--r--src/plugins/python/pythonlanguageclient.cpp1
-rw-r--r--src/plugins/qmldesigner/.clang-format43
-rw-r--r--src/plugins/qmldesigner/CMakeLists.txt19
-rw-r--r--src/plugins/qmldesigner/assetexporterplugin/filepathmodel.cpp14
-rw-r--r--src/plugins/qmldesigner/components/annotationeditor/annotationtableview.cpp34
-rw-r--r--src/plugins/qmldesigner/components/annotationeditor/defaultannotations.cpp4
-rw-r--r--src/plugins/qmldesigner/components/bindingeditor/actioneditordialog.cpp4
-rw-r--r--src/plugins/qmldesigner/components/bindingeditor/bindingeditor.cpp60
-rw-r--r--src/plugins/qmldesigner/components/componentcore/crumblebar.cpp30
-rw-r--r--src/plugins/qmldesigner/components/componentcore/crumblebar.h1
-rw-r--r--src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp6
-rw-r--r--src/plugins/qmldesigner/components/componentcore/formatoperation.cpp2
-rw-r--r--src/plugins/qmldesigner/components/componentcore/layoutingridlayout.cpp10
-rw-r--r--src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp20
-rw-r--r--src/plugins/qmldesigner/components/componentcore/svgpasteaction.cpp6
-rw-r--r--src/plugins/qmldesigner/components/componentcore/theme.h3
-rw-r--r--src/plugins/qmldesigner/components/componentcore/viewmanager.cpp54
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/backendmodel.cpp2
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/bindingmodel.cpp6
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp2
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/connectionview.cpp2
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.cpp8
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.cpp10
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffect.cpp78
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffect.h62
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectscategory.cpp63
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectscategory.h47
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.cpp286
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.h90
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibraryiconprovider.cpp42
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibraryiconprovider.h17
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.cpp14
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.cpp32
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h24
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.cpp23
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.h7
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.cpp76
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.h10
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp83
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h9
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp375
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.h19
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/curveeditormodel.cpp2
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/curveeditorstyle.h4
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/curveeditorview.cpp2
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/curvesegment.cpp4
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.cpp27
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.h2
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/detail/treeview.cpp2
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/keyframe.cpp2
-rw-r--r--src/plugins/qmldesigner/components/edit3d/bakelights.cpp12
-rw-r--r--src/plugins/qmldesigner/components/edit3d/bakelightsconnectionmanager.cpp2
-rw-r--r--src/plugins/qmldesigner/components/edit3d/bakelightsdatamodel.cpp82
-rw-r--r--src/plugins/qmldesigner/components/edit3d/bakelightsdatamodel.h2
-rw-r--r--src/plugins/qmldesigner/components/edit3d/edit3dactions.cpp19
-rw-r--r--src/plugins/qmldesigner/components/edit3d/edit3dactions.h17
-rw-r--r--src/plugins/qmldesigner/components/edit3d/edit3dview.cpp63
-rw-r--r--src/plugins/qmldesigner/components/edit3d/edit3dview.h17
-rw-r--r--src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp40
-rw-r--r--src/plugins/qmldesigner/components/edit3d/edit3dwidget.h1
-rw-r--r--src/plugins/qmldesigner/components/formeditor/abstractformeditortool.cpp2
-rw-r--r--src/plugins/qmldesigner/components/formeditor/anchorindicator.cpp2
-rw-r--r--src/plugins/qmldesigner/components/formeditor/backgroundaction.cpp4
-rw-r--r--src/plugins/qmldesigner/components/formeditor/bindingindicator.cpp2
-rw-r--r--src/plugins/qmldesigner/components/formeditor/movetool.cpp6
-rw-r--r--src/plugins/qmldesigner/components/formeditor/seekerslider.cpp2
-rw-r--r--src/plugins/qmldesigner/components/formeditor/snapper.cpp4
-rw-r--r--src/plugins/qmldesigner/components/formeditor/toolbox.cpp2
-rw-r--r--src/plugins/qmldesigner/components/integration/designdocument.cpp20
-rw-r--r--src/plugins/qmldesigner/components/integration/designdocumentview.cpp3
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/assetimportupdatetreeitem.cpp2
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibraryaddimportmodel.cpp4
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp2
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp4
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrarycategoriesmodel.cpp4
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibraryitemsmodel.cpp2
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp12
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp4
-rw-r--r--src/plugins/qmldesigner/components/listmodeleditor/listmodeleditormodel.cpp4
-rw-r--r--src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.cpp19
-rw-r--r--src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.h6
-rw-r--r--src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.cpp19
-rw-r--r--src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.h6
-rw-r--r--src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp6
-rw-r--r--src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.cpp13
-rw-r--r--src/plugins/qmldesigner/components/materialeditor/materialeditorqmlbackend.cpp8
-rw-r--r--src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp7
-rw-r--r--src/plugins/qmldesigner/components/navigator/choosefrompropertylistdialog.cpp8
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp40
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatorview.cpp15
-rw-r--r--src/plugins/qmldesigner/components/pathtool/pathitem.cpp12
-rw-r--r--src/plugins/qmldesigner/components/pathtool/pathselectionmanipulator.cpp4
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/aligndistribute.cpp10
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/dynamicpropertiesproxymodel.cpp2
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp4
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/gradientpresetlistmodel.cpp4
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/itemfiltermodel.cpp68
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/itemfiltermodel.h16
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/listvalidator.cpp58
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/listvalidator.h33
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.cpp14
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp40
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp19
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp64
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.cpp2
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/quick2propertyeditorview.cpp10
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/propertychangesmodel.cpp (renamed from src/plugins/qmldesigner/components/stateseditornew/propertychangesmodel.cpp)28
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/propertychangesmodel.h (renamed from src/plugins/qmldesigner/components/stateseditornew/propertychangesmodel.h)28
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/propertymodel.cpp (renamed from src/plugins/qmldesigner/components/stateseditornew/propertymodel.cpp)28
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/propertymodel.h (renamed from src/plugins/qmldesigner/components/stateseditornew/propertymodel.h)28
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/stateseditorimageprovider.cpp16
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/stateseditorimageprovider.h6
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp277
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/stateseditormodel.h61
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp555
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/stateseditorview.h58
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.cpp59
-rw-r--r--src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.h13
-rw-r--r--src/plugins/qmldesigner/components/stateseditornew/stateseditorimageprovider.cpp82
-rw-r--r--src/plugins/qmldesigner/components/stateseditornew/stateseditorimageprovider.h54
-rw-r--r--src/plugins/qmldesigner/components/stateseditornew/stateseditormodel.cpp462
-rw-r--r--src/plugins/qmldesigner/components/stateseditornew/stateseditormodel.h127
-rw-r--r--src/plugins/qmldesigner/components/stateseditornew/stateseditorview.cpp964
-rw-r--r--src/plugins/qmldesigner/components/stateseditornew/stateseditorview.h157
-rw-r--r--src/plugins/qmldesigner/components/stateseditornew/stateseditorwidget.cpp200
-rw-r--r--src/plugins/qmldesigner/components/stateseditornew/stateseditorwidget.h80
-rw-r--r--src/plugins/qmldesigner/components/textureeditor/textureeditorcontextobject.cpp11
-rw-r--r--src/plugins/qmldesigner/components/textureeditor/textureeditorqmlbackend.cpp8
-rw-r--r--src/plugins/qmldesigner/components/textureeditor/textureeditorview.cpp9
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/canvas.cpp2
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/easingcurve.cpp26
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelineanimationform.cpp2
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinecontrols.cpp4
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinegraphicsscene.cpp2
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.cpp9
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinesectionitem.cpp4
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelineselectiontool.cpp2
-rw-r--r--src/plugins/qmldesigner/components/toolbar/toolbarbackend.cpp8
-rw-r--r--src/plugins/qmldesigner/components/transitioneditor/transitioneditorsectionitem.cpp2
-rw-r--r--src/plugins/qmldesigner/components/transitioneditor/transitioneditorview.cpp2
-rw-r--r--src/plugins/qmldesigner/components/transitioneditor/transitionform.cpp8
-rw-r--r--src/plugins/qmldesigner/designercore/imagecache/imagecacheconnectionmanager.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/imagecache/imagecachestorage.h13
-rw-r--r--src/plugins/qmldesigner/designercore/include/abstractproperty.h30
-rw-r--r--src/plugins/qmldesigner/designercore/include/abstractview.h7
-rw-r--r--src/plugins/qmldesigner/designercore/include/bindingproperty.h10
-rw-r--r--src/plugins/qmldesigner/designercore/include/model.h25
-rw-r--r--src/plugins/qmldesigner/designercore/include/modelfwd.h10
-rw-r--r--src/plugins/qmldesigner/designercore/include/modelnode.h27
-rw-r--r--src/plugins/qmldesigner/designercore/include/nodeabstractproperty.h2
-rw-r--r--src/plugins/qmldesigner/designercore/include/nodeinstanceview.h4
-rw-r--r--src/plugins/qmldesigner/designercore/include/nodelistproperty.h2
-rw-r--r--src/plugins/qmldesigner/designercore/include/nodemetainfo.h13
-rw-r--r--src/plugins/qmldesigner/designercore/include/propertymetainfo.h16
-rw-r--r--src/plugins/qmldesigner/designercore/include/propertynode.h2
-rw-r--r--src/plugins/qmldesigner/designercore/include/qml3dnode.h9
-rw-r--r--src/plugins/qmldesigner/designercore/include/qmlchangeset.h4
-rw-r--r--src/plugins/qmldesigner/designercore/include/qmlconnections.h3
-rw-r--r--src/plugins/qmldesigner/designercore/include/qmlitemnode.h12
-rw-r--r--src/plugins/qmldesigner/designercore/include/qmlmodelnodefacade.h45
-rw-r--r--src/plugins/qmldesigner/designercore/include/qmlobjectnode.h12
-rw-r--r--src/plugins/qmldesigner/designercore/include/qmlstate.h3
-rw-r--r--src/plugins/qmldesigner/designercore/include/qmltimeline.h2
-rw-r--r--src/plugins/qmldesigner/designercore/include/qmltimelinekeyframegroup.h2
-rw-r--r--src/plugins/qmldesigner/designercore/include/qmlvisualnode.h3
-rw-r--r--src/plugins/qmldesigner/designercore/include/stringutils.h42
-rw-r--r--src/plugins/qmldesigner/designercore/instances/baseconnectionmanager.cpp4
-rw-r--r--src/plugins/qmldesigner/designercore/instances/capturingconnectionmanager.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/instances/interactiveconnectionmanager.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp18
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp31
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp30
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/metainfo.cpp3
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/metainforeader.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/nodehints.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp157
-rw-r--r--src/plugins/qmldesigner/designercore/model/abstractproperty.cpp43
-rw-r--r--src/plugins/qmldesigner/designercore/model/abstractview.cpp17
-rw-r--r--src/plugins/qmldesigner/designercore/model/bindingproperty.cpp84
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalbindingproperty.cpp21
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalbindingproperty.h9
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalnode.cpp129
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalnode_p.h122
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalnodeabstractproperty.cpp11
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalnodeabstractproperty.h10
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalnodelistproperty.cpp22
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalnodelistproperty.h12
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalnodeproperty.cpp20
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalnodeproperty.h8
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalproperty.cpp103
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalproperty.h106
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalsignalhandlerproperty.cpp44
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalsignalhandlerproperty.h21
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalvariantproperty.cpp20
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalvariantproperty.h10
-rw-r--r--src/plugins/qmldesigner/designercore/model/model.cpp271
-rw-r--r--src/plugins/qmldesigner/designercore/model/model_p.h42
-rw-r--r--src/plugins/qmldesigner/designercore/model/modelnode.cpp191
-rw-r--r--src/plugins/qmldesigner/designercore/model/modelresourcemanagement.cpp796
-rw-r--r--src/plugins/qmldesigner/designercore/model/modelresourcemanagement.h20
-rw-r--r--src/plugins/qmldesigner/designercore/model/modelresourcemanagementfwd.h27
-rw-r--r--src/plugins/qmldesigner/designercore/model/modelresourcemanagementinterface.h20
-rw-r--r--src/plugins/qmldesigner/designercore/model/modelutils.cpp16
-rw-r--r--src/plugins/qmldesigner/designercore/model/modelutils.h12
-rw-r--r--src/plugins/qmldesigner/designercore/model/nodeabstractproperty.cpp20
-rw-r--r--src/plugins/qmldesigner/designercore/model/nodelistproperty.cpp27
-rw-r--r--src/plugins/qmldesigner/designercore/model/nodeproperty.cpp17
-rw-r--r--src/plugins/qmldesigner/designercore/model/propertycontainer.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/model/qml3dnode.cpp17
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmlchangeset.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp179
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmltextgenerator.cpp36
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmltextgenerator.h2
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp14
-rw-r--r--src/plugins/qmldesigner/designercore/model/rewriterview.cpp7
-rw-r--r--src/plugins/qmldesigner/designercore/model/signalhandlerproperty.cpp38
-rw-r--r--src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp123
-rw-r--r--src/plugins/qmldesigner/designercore/model/variantproperty.cpp45
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h46
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstoragesqlitefunctionregistry.cpp61
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstoragesqlitefunctionregistry.h16
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h2
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h2
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h2
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/sourcepathcache.h5
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/sourcepathcachetypes.h1
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/storagecache.h86
-rw-r--r--src/plugins/qmldesigner/documentwarningwidget.cpp4
-rw-r--r--src/plugins/qmldesigner/generateresource.cpp4
-rw-r--r--src/plugins/qmldesigner/qmldesignerconstants.h4
-rw-r--r--src/plugins/qmldesigner/qmldesignerplugin.cpp188
-rw-r--r--src/plugins/qmldesigner/qmldesignerplugin.h13
-rw-r--r--src/plugins/qmldesigner/qtquickplugin/images/mouse-area-icon.pngbin317 -> 358 bytes
-rw-r--r--src/plugins/qmldesigner/qtquickplugin/images/mouse-area-icon16.pngbin158 -> 263 bytes
-rw-r--r--src/plugins/qmldesigner/qtquickplugin/images/mouse-area-icon@2x.pngbin392 -> 755 bytes
-rw-r--r--src/plugins/qmldesigner/utils/filedownloader.cpp50
-rw-r--r--src/plugins/qmldesigner/utils/filedownloader.h7
-rw-r--r--src/plugins/qmldesigner/utils/fileextractor.cpp8
-rw-r--r--src/plugins/qmldesigner/utils/multifiledownloader.cpp2
-rw-r--r--src/plugins/qmldesignerbase/utils/designersettings.cpp2
-rw-r--r--src/plugins/qmldesignerbase/utils/designersettings.h2
-rw-r--r--src/plugins/qmlprojectmanager/buildsystem/projectitem/converters.cpp51
-rw-r--r--src/plugins/qmlprojectmanager/buildsystem/projectitem/qmlprojectitem.h7
-rw-r--r--src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.cpp89
-rw-r--r--src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.h2
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.cpp28
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/qmlprojectmaincpp.tpl2
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/qmlprojectmodulecmakelists.tpl1
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/qmlprojectmodules.tpl1
-rw-r--r--src/plugins/qmlprojectmanager/qmlproject.cpp48
-rw-r--r--src/plugins/studiowelcome/studiowelcomeplugin.cpp39
-rw-r--r--src/tools/qml2puppet/instances/nodeinstanceclientproxy.cpp46
-rw-r--r--src/tools/qml2puppet/instances/nodeinstanceclientproxy.h1
-rw-r--r--src/tools/qml2puppet/mockfiles/qt5/EditView3D.qml12
-rw-r--r--src/tools/qml2puppet/mockfiles/qt6/EditView3D.qml12
-rw-r--r--src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.cpp4
-rw-r--r--src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.cpp29
-rw-r--r--src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.h1
-rw-r--r--src/tools/qml2puppet/qml2puppet/instances/objectnodeinstance.cpp2
-rw-r--r--src/tools/qml2puppet/qml2puppet/instances/qt5bakelightsnodeinstanceserver.cpp7
-rw-r--r--src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp85
-rw-r--r--src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.h4
-rw-r--r--src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceserver.cpp83
-rw-r--r--src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceserver.h5
-rw-r--r--src/tools/qml2puppet/qmlprivategate/qmlprivategate.cpp9
279 files changed, 5970 insertions, 4601 deletions
diff --git a/src/libs/3rdparty/googletest b/src/libs/3rdparty/googletest
new file mode 160000
+Subproject b796f7d44681514f58a683a3a71ff17c94edb0c
diff --git a/src/libs/3rdparty/sqlite/config.h b/src/libs/3rdparty/sqlite/config.h
index 3672f4c5dd..f0e73be300 100644
--- a/src/libs/3rdparty/sqlite/config.h
+++ b/src/libs/3rdparty/sqlite/config.h
@@ -27,10 +27,6 @@
#include <string.h>
-#if defined(SQLITE_STATIC_LIBRARY) || defined(SQLITEC_STATIC_LIBRARY)
-#include "sqlite_static_config.h"
-#endif
-
#if __has_include(<unistd.h>)
#include <unistd.h>
#endif
diff --git a/src/libs/CMakeLists.txt b/src/libs/CMakeLists.txt
index de2d2b01ef..73a554bae8 100644
--- a/src/libs/CMakeLists.txt
+++ b/src/libs/CMakeLists.txt
@@ -22,6 +22,10 @@ if (WITH_QMLDESIGNER)
add_subdirectory(qmlpuppetcommunication)
endif()
+if (WITH_TESTS)
+ add_subdirectory(googletest)
+endif()
+
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/qlitehtml/src/CMakeLists.txt)
option(BUILD_LIBRARY_QLITEHTML "Build library qlitehtml." ${BUILD_LIBRARIES_BY_DEFAULT})
set(QLITEHTML_VERSION_COMPAT ${IDE_VERSION_COMPAT} CACHE STRING "")
diff --git a/src/libs/googletest/CMakeLists.txt b/src/libs/googletest/CMakeLists.txt
new file mode 100644
index 0000000000..50e82e1edf
--- /dev/null
+++ b/src/libs/googletest/CMakeLists.txt
@@ -0,0 +1,27 @@
+set(GOOGLETEST_DIR ${CMAKE_CURRENT_LIST_DIR}/../3rdparty/googletest)
+
+if(EXISTS "${GOOGLETEST_DIR}/googletest")
+ set(GOOGLETEST_SUBMODULE_IS_CHECKED_OUT YES)
+else()
+ set(GOOGLETEST_SUBMODULE_IS_CHECKED_OUT NO)
+endif()
+
+add_qtc_library(Googletest STATIC
+ CONDITION GOOGLETEST_SUBMODULE_IS_CHECKED_OUT
+ DEPENDS
+ Threads::Threads
+ PUBLIC_INCLUDES
+ "${GOOGLETEST_DIR}/googletest/include"
+ "${GOOGLETEST_DIR}/googlemock/include"
+ INCLUDES
+ "${GOOGLETEST_DIR}/googletest"
+ "${GOOGLETEST_DIR}/googlemock"
+ PROPERTIES
+ AUTOMOC OFF AUTOUIC OFF QT_COMPILE_OPTIONS_DISABLE_WARNINGS ON
+ POSITION_INDEPENDENT_CODE ON
+ URL "https://github.com/google/googletest"
+ DESCRIPTION "Google Testing and Mocking Framework"
+ SOURCES
+ "${GOOGLETEST_DIR}/googletest/src/gtest-all.cc"
+ "${GOOGLETEST_DIR}/googlemock/src/gmock-all.cc"
+)
diff --git a/src/libs/qmljs/qmljsreformatter.cpp b/src/libs/qmljs/qmljsreformatter.cpp
index 232c0361a1..d2891451e9 100644
--- a/src/libs/qmljs/qmljsreformatter.cpp
+++ b/src/libs/qmljs/qmljsreformatter.cpp
@@ -590,11 +590,32 @@ protected:
return true;
}
+ bool visit(UiAnnotation *ast) override
+ {
+ out("@");
+ accept(ast->qualifiedTypeNameId);
+ out(" ");
+ accept(ast->initializer);
+ return false;
+ }
+
+ bool visit(UiAnnotationList *ast) override
+ {
+ for (UiAnnotationList *it = ast; it; it = it->next) {
+ accept(it->annotation);
+ newLine();
+ }
+ return false;
+ }
+
bool visit(UiObjectDefinition *ast) override
{
+ accept(ast->annotations);
+
accept(ast->qualifiedTypeNameId);
out(" ");
accept(ast->initializer);
+
return false;
}
@@ -687,9 +708,12 @@ protected:
bool visit(UiScriptBinding *ast) override
{
+ accept(ast->annotations);
+
accept(ast->qualifiedId);
out(": ", ast->colonToken);
accept(ast->statement);
+
return false;
}
@@ -1290,6 +1314,7 @@ protected:
{
for (UiObjectMemberList *it = ast; it; it = it->next) {
accept(it->member);
+
if (it->next)
newLine();
}
diff --git a/src/libs/sqlite/CMakeLists.txt b/src/libs/sqlite/CMakeLists.txt
index 4c7cd774c6..aa33171bab 100644
--- a/src/libs/sqlite/CMakeLists.txt
+++ b/src/libs/sqlite/CMakeLists.txt
@@ -1,8 +1,7 @@
-add_qtc_library(SqliteC OBJECT
+add_qtc_library(SqliteInternal OBJECT
PROPERTIES AUTOMOC OFF AUTOUIC OFF QT_COMPILE_OPTIONS_DISABLE_WARNINGS ON
DEFINES SQLITE_CORE SQLITE_CUSTOM_INCLUDE=config.h $<$<CONFIG:Debug>:SQLITE_DEBUG>
- PROPERTIES COMPILE_OPTIONS $<IF:$<CXX_COMPILER_ID:MSVC>,/FIconfig.h,-includeconfig.h>
- PUBLIC_INCLUDES
+ INCLUDES
../3rdparty/sqlite
SOURCES
../3rdparty/sqlite
@@ -11,12 +10,26 @@ add_qtc_library(SqliteC OBJECT
../3rdparty/sqlite/sqlite3ext.h
../3rdparty/sqlite/carray.c
../3rdparty/sqlite/config.h
+ ../3rdparty/sqlite/sqlite_static_config.h
../3rdparty/sqlite/sqlite.h
)
+extend_qtc_library(SqliteInternal
+ CONDITION QTC_STATIC_BUILD
+ PROPERTIES COMPILE_OPTIONS $<IF:$<CXX_COMPILER_ID:MSVC>,/FIsqlite_static_config.h,-includesqlite_static_config.h>
+)
+
+if (APPLE)
+ extend_qtc_library(SqliteInternal DEFINES _BSD_SOURCE)
+elseif (UNIX)
+ extend_qtc_library(SqliteInternal DEFINES _POSIX_C_SOURCE=200809L _GNU_SOURCE _DEFAULT_SOURCE)
+endif()
+
add_qtc_library(Sqlite
PROPERTIES AUTOMOC OFF AUTOUIC OFF
- DEPENDS Qt::Core Threads::Threads ${CMAKE_DL_LIBS} SqliteC
+ DEPENDS Qt::Core Threads::Threads ${CMAKE_DL_LIBS} SqliteInternal
+ INCLUDES
+ ../3rdparty/sqlite
PUBLIC_INCLUDES
"${CMAKE_CURRENT_LIST_DIR}"
DEFINES SQLITE_CUSTOM_INCLUDE=config.h $<$<CONFIG:Debug>:SQLITE_REVERSE>
@@ -53,8 +66,7 @@ add_qtc_library(Sqlite
sqliteids.h
)
-if (APPLE)
- extend_qtc_library(SqliteC DEFINES _BSD_SOURCE)
-elseif (UNIX)
- extend_qtc_library(SqliteC DEFINES _POSIX_C_SOURCE=200809L _GNU_SOURCE _DEFAULT_SOURCE)
-endif()
+extend_qtc_library(Sqlite
+ CONDITION QTC_STATIC_BUILD
+ PROPERTIES COMPILE_OPTIONS $<IF:$<CXX_COMPILER_ID:MSVC>,/FIsqlite_static_config.h,-includesqlite_static_config.h>
+)
diff --git a/src/libs/sqlite/sqlitebasestatement.cpp b/src/libs/sqlite/sqlitebasestatement.cpp
index 91b417bea1..d9d677c395 100644
--- a/src/libs/sqlite/sqlitebasestatement.cpp
+++ b/src/libs/sqlite/sqlitebasestatement.cpp
@@ -274,6 +274,9 @@ void BaseStatement::bind(int index, ValueView value)
void BaseStatement::prepare(Utils::SmallStringView sqlStatement)
{
+ if (!m_database.isLocked())
+ throw DatabaseIsNotLocked{};
+
int resultCode;
do {
diff --git a/src/libs/sqlite/sqlitebasestatement.h b/src/libs/sqlite/sqlitebasestatement.h
index 1178b97f3a..54d08260b7 100644
--- a/src/libs/sqlite/sqlitebasestatement.h
+++ b/src/libs/sqlite/sqlitebasestatement.h
@@ -49,6 +49,7 @@ public:
BaseStatement(const BaseStatement &) = delete;
BaseStatement &operator=(const BaseStatement &) = delete;
+ BaseStatement(BaseStatement &&) = default;
bool next() const;
void step() const;
@@ -146,6 +147,7 @@ class StatementImplementation : public BaseStatement
public:
using BaseStatement::BaseStatement;
+ StatementImplementation(StatementImplementation &&) = default;
void execute()
{
@@ -496,16 +498,30 @@ private:
return createValue<ResultType>(std::make_integer_sequence<int, ResultCount>{});
}
+ template<typename Callable, typename... Arguments>
+ CallbackControl invokeCallable(Callable &&callable, Arguments &&...arguments)
+ {
+ if constexpr (std::is_void_v<std::invoke_result_t<Callable, Arguments...>>) {
+ std::invoke(std::forward<Callable>(callable), std::forward<Arguments>(arguments)...);
+ return CallbackControl::Continue;
+ } else {
+ return std::invoke(std::forward<Callable>(callable),
+ std::forward<Arguments>(arguments)...);
+ }
+ }
+
template<typename Callable, int... ColumnIndices>
CallbackControl callCallable(Callable &&callable, std::integer_sequence<int, ColumnIndices...>)
{
- return std::invoke(callable, ValueGetter(*this, ColumnIndices)...);
+ return invokeCallable(std::forward<Callable>(callable),
+ ValueGetter(*this, ColumnIndices)...);
}
template<typename Callable>
CallbackControl callCallable(Callable &&callable)
{
- return callCallable(callable, std::make_integer_sequence<int, ResultCount>{});
+ return callCallable(std::forward<Callable>(callable),
+ std::make_integer_sequence<int, ResultCount>{});
}
void setMaximumResultCount(std::size_t count)
diff --git a/src/libs/utils/set_algorithm.h b/src/libs/utils/set_algorithm.h
index a3e442f736..f6d3f73fed 100644
--- a/src/libs/utils/set_algorithm.h
+++ b/src/libs/utils/set_algorithm.h
@@ -60,8 +60,17 @@ bool set_intersection_compare(
++first1;
} else {
if (!comp(*first2, *first1)) {
- if (call(*first1++, *first2))
- return true;
+ if constexpr (std::is_void_v<std::invoke_result_t<Callable,
+ decltype(*first1),
+ decltype(*first2)>>) {
+ call(*first1, *first2);
+ ++first1;
+ } else {
+ auto success = call(*first1, *first2);
+ ++first1;
+ if (success)
+ return true;
+ }
}
++first2;
}
@@ -71,6 +80,52 @@ bool set_intersection_compare(
}
template<class InputIt1, class InputIt2, class Callable, class Compare>
+bool set_greedy_intersection_compare(
+ InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, Callable call, Compare comp)
+{
+ while (first1 != last1 && first2 != last2) {
+ if (comp(*first1, *first2)) {
+ ++first1;
+ } else {
+ if (!comp(*first2, *first1)) {
+ if constexpr (std::is_void_v<std::invoke_result_t<Callable,
+ decltype(*first1),
+ decltype(*first2)>>) {
+ call(*first1, *first2);
+ ++first1;
+ } else {
+ auto success = call(*first1, *first2);
+ ++first1;
+ if (success)
+ return true;
+ }
+ } else {
+ ++first2;
+ }
+ }
+ }
+
+ return false;
+}
+
+template<typename InputIt1, typename InputIt2, typename OutputIt>
+constexpr OutputIt set_greedy_intersection(
+ InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, OutputIt result)
+{
+ while (first1 != last1 && first2 != last2)
+ if (*first1 < *first2)
+ ++first1;
+ else if (*first2 < *first1)
+ ++first2;
+ else {
+ *result = *first1;
+ ++first1;
+ ++result;
+ }
+ return result;
+}
+
+template<class InputIt1, class InputIt2, class Callable, class Compare>
void set_greedy_difference(
InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, Callable call, Compare comp)
{
diff --git a/src/libs/utils/smallstringview.h b/src/libs/utils/smallstringview.h
index 82a8c50305..982192c7a4 100644
--- a/src/libs/utils/smallstringview.h
+++ b/src/libs/utils/smallstringview.h
@@ -12,6 +12,12 @@
#include <string>
#include <string_view>
+#if __cpp_lib_constexpr_string >= 201907L
+#define constexpr_string constexpr
+#else
+#define constexpr_string
+#endif
+
namespace Utils {
template <typename String>
@@ -63,7 +69,7 @@ public:
return SmallStringView(data() + position, length);
}
- constexpr20 operator std::string() const { return std::string(data(), size()); }
+ constexpr_string operator std::string() const { return std::string(data(), size()); }
explicit operator QString() const
{
@@ -131,38 +137,6 @@ constexpr int compare(SmallStringView first, SmallStringView second) noexcept
return first.compare(second);
}
-namespace Internal {
-constexpr int reverse_memcmp(const char *first, const char *second, size_t n)
-{
- const char *currentFirst = first + n - 1;
- const char *currentSecond = second + n - 1;
-
- while (n > 0) {
- // If the current characters differ, return an appropriately signed
- // value; otherwise, keep searching backwards
- int difference = *currentFirst - *currentSecond;
- if (difference != 0)
- return difference;
-
- --currentFirst;
- --currentSecond;
- --n;
- }
-
- return 0;
-}
-} // namespace Internal
-
-constexpr int reverseCompare(SmallStringView first, SmallStringView second) noexcept
-{
- int difference = Internal::reverse_memcmp(first.data(), second.data(), first.size());
-
- if (difference == 0)
- return int(first.size()) - int(second.size());
-
- return difference;
-}
-
} // namespace Utils
constexpr Utils::SmallStringView operator""_sv(const char *const string, size_t size)
diff --git a/src/plugins/insight/insightmodel.cpp b/src/plugins/insight/insightmodel.cpp
index b80249d212..2d2550aac5 100644
--- a/src/plugins/insight/insightmodel.cpp
+++ b/src/plugins/insight/insightmodel.cpp
@@ -227,7 +227,7 @@ InsightModel::InsightModel(InsightView *view, ExternalDependenciesInterface &ext
int InsightModel::rowCount(const QModelIndex &) const
{
- return m_qtdsConfig.empty() ? 0 : m_qtdsConfig.size();
+ return m_qtdsConfig.empty() ? 0 : static_cast<int>(m_qtdsConfig.size());
}
QVariant InsightModel::data(const QModelIndex &index, int role) const
diff --git a/src/plugins/mcusupport/test/CMakeLists.txt b/src/plugins/mcusupport/test/CMakeLists.txt
index 2df4faa891..7d2a94c286 100644
--- a/src/plugins/mcusupport/test/CMakeLists.txt
+++ b/src/plugins/mcusupport/test/CMakeLists.txt
@@ -1,13 +1,8 @@
-find_package(Googletest MODULE)
-
-if(TARGET Googletest)
- message("Googletest target is present")
- extend_qtc_plugin(McuSupport
- CONDITION WITH_TESTS
- DEPENDS Googletest
- SOURCES
- unittest.h unittest.cpp packagemock.h settingshandlermock.h
- )
-else()
- message("Googletest target is missing")
-endif()
+extend_qtc_plugin(McuSupport
+ CONDITION WITH_TESTS AND TARGET Googletest
+ DEPENDS Googletest
+ SOURCES
+ unittest.h unittest.cpp
+ packagemock.h
+ settingshandlermock.h
+)
diff --git a/src/plugins/projectexplorer/projectwindow.cpp b/src/plugins/projectexplorer/projectwindow.cpp
index 6d51ada410..a69ee4c855 100644
--- a/src/plugins/projectexplorer/projectwindow.cpp
+++ b/src/plugins/projectexplorer/projectwindow.cpp
@@ -585,7 +585,7 @@ public:
PanelsWidget::PanelVMargin, 0);
QStringList list = Core::ICore::settings()->value("HideOptionCategories").toStringList();
- if (!list.contains("Kit")) {
+ if (!list.contains("Kits")) {
innerLayout->addWidget(m_manageKits);
innerLayout->addSpacerItem(new QSpacerItem(10, 30, QSizePolicy::Maximum, QSizePolicy::Maximum));
}
diff --git a/src/plugins/python/pythonlanguageclient.cpp b/src/plugins/python/pythonlanguageclient.cpp
index 9f347d8e48..eecfb35c97 100644
--- a/src/plugins/python/pythonlanguageclient.cpp
+++ b/src/plugins/python/pythonlanguageclient.cpp
@@ -115,6 +115,7 @@ static PythonLanguageServerState checkPythonLanguageServer(const FilePath &pytho
const FilePath &modulePath = getPylsModulePath(pythonLShelpCommand);
Process pythonProcess;
+ pythonProcess.setTimeoutS(2);
pythonProcess.setCommand(pythonLShelpCommand);
pythonProcess.runBlocking();
if (pythonProcess.allOutput().contains("Python Language Server"))
diff --git a/src/plugins/qmldesigner/.clang-format b/src/plugins/qmldesigner/.clang-format
index e1dad0fa0c..968dfdec7d 100644
--- a/src/plugins/qmldesigner/.clang-format
+++ b/src/plugins/qmldesigner/.clang-format
@@ -6,10 +6,12 @@ AlignConsecutiveDeclarations: false
AlignEscapedNewlines: DontAlign
AlignOperands: true
AlignTrailingComments: true
+AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Inline
+AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
@@ -32,13 +34,16 @@ BraceWrapping:
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false
+BreakAfterAttributes: Never
BreakBeforeBinaryOperators: All
BreakBeforeBraces: Custom
+BreakBeforeConceptDeclarations: Always
BreakBeforeInheritanceComma: false
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeComma
BreakAfterJavaFieldAnnotations: false
+BreakInheritanceList: AfterComma
BreakStringLiterals: true
ColumnLimit: 100
CommentPragmas: '^ IWYU pragma:'
@@ -49,6 +54,8 @@ ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
+EmptyLineAfterAccessModifier: Never
+EmptyLineBeforeAccessModifier: LogicalBlock
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
@@ -56,17 +63,23 @@ ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
+#IncludeBlocks: Regroup
IncludeCategories:
- Regex: '^<Q.*'
Priority: 200
IncludeIsMainRegex: '(Test)?$'
+IndentCaseBlocks: false
IndentCaseLabels: false
+IndentPPDirectives: AfterHash
+IndentRequiresClause: true
IndentWidth: 4
IndentWrappedFunctionNames: false
+InsertBraces : false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
# Do not add QT_BEGIN_NAMESPACE/QT_END_NAMESPACE as this will indent lines in between.
+LambdaBodyIndentation: Signature
MacroBlockBegin: ""
MacroBlockEnd: ""
MaxEmptyLinesToKeep: 1
@@ -74,6 +87,8 @@ NamespaceIndentation: None
ObjCBlockIndentWidth: 4
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
+PPIndentWidth: 2
+PackConstructorInitializers: Never
PenaltyBreakAssignment: 500
PenaltyBreakBeforeFirstCallParameter: 150
PenaltyBreakComment: 500
@@ -82,20 +97,40 @@ PenaltyBreakString: 600
PenaltyExcessCharacter: 7
PenaltyReturnTypeOnItsOwnLine: 300
PointerAlignment: Right
+QualifierAlignment: Custom
+QualifierOrder: ['friend', 'inline', 'static', 'constexpr', 'const', 'type']
ReflowComments: false
-SortIncludes: true
-SortUsingDeclarations: true
+ReferenceAlignment: Right
+RequiresClausePosition: OwnLine
+SeparateDefinitionBlocks: Always
+ShortNamespaceLines: 1
+SortIncludes: CaseInsensitive
+SortUsingDeclarations: Lexicographic
SpaceAfterCStyleCast: true
+SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
+SpaceBeforeCpp11BracedList: false
+SpaceBeforeCtorInitializerColon: true
+SpaceBeforeInheritanceColon: true
+SpaceBeforeParens: ControlStatementsExceptControlMacros
+SpaceBeforeRangeBasedForLoopColon: true
+SpaceBeforeSquareBrackets: false
+SpaceInEmptyBlock: false
SpacesBeforeTrailingComments: 1
-SpacesInAngles: false
+SpacesInAngles: Never
+SpacesInConditionalStatement: false
SpacesInContainerLiterals: false
+SpacesInLineCommentPrefix:
+ Minimum: 1
+ Maximum: -1
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
-Standard: Cpp11
+Standard: Latest
+StatementAttributeLikeMacros: [emit]
+StatementMacros: [Q_UNUSED]
TabWidth: 4
UseTab: Never
diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt
index feba07e446..b6d9f10bfb 100644
--- a/src/plugins/qmldesigner/CMakeLists.txt
+++ b/src/plugins/qmldesigner/CMakeLists.txt
@@ -36,7 +36,7 @@ extend_qtc_library(QmlDesignerUtils
)
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
+ CONDITION Qt6_VERSION VERSION_GREATER_EQUAL 6.4.3 AND TARGET QmlDesignerBase AND TARGET Qt6::QmlPrivate AND TARGET Qt6::QmlDomPrivate AND TARGET Qt6::QmlCompilerPrivate
EXCLUDE_FROM_INSTALL
PROPERTIES SKIP_AUTOUIC ON
DEPENDS
@@ -251,6 +251,7 @@ extend_qtc_library(QmlDesignerCore
rewriterview.h
rewritingexception.h
signalhandlerproperty.h
+ stringutils.h
stylesheetmerger.h
subcomponentmanager.h
synchronousimagecache.h
@@ -328,6 +329,8 @@ extend_qtc_library(QmlDesignerCore
modelnodepositionrecalculator.h
modelnodepositionstorage.cpp
modelresourcemanagementinterface.h
+ modelresourcemanagementfwd.h
+ modelresourcemanagement.cpp modelresourcemanagement.h
modeltotextmerger.cpp
modeltotextmerger.h
modelutils.cpp
@@ -722,6 +725,7 @@ extend_qtc_plugin(QmlDesigner
designerpropertymap.cpp designerpropertymap.h
fileresourcesmodel.cpp fileresourcesmodel.h
itemfiltermodel.cpp itemfiltermodel.h
+ listvalidator.cpp listvalidator.h
gradientmodel.cpp gradientmodel.h
dynamicpropertiesproxymodel.cpp dynamicpropertiesproxymodel.h
gradientpresetcustomlistmodel.cpp gradientpresetcustomlistmodel.h
@@ -752,6 +756,10 @@ extend_qtc_plugin(QmlDesigner
contentlibrarymaterialsmodel.cpp contentlibrarymaterialsmodel.h
contentlibrarymaterialscategory.cpp contentlibrarymaterialscategory.h
contentlibrarymaterial.cpp contentlibrarymaterial.h
+ contentlibraryiconprovider.cpp contentlibraryiconprovider.h
+ contentlibraryeffect.cpp contentlibraryeffect.h
+ contentlibraryeffectscategory.cpp contentlibraryeffectscategory.h
+ contentlibraryeffectsmodel.cpp contentlibraryeffectsmodel.h
)
extend_qtc_plugin(QmlDesigner
@@ -794,15 +802,6 @@ extend_qtc_plugin(QmlDesigner
extend_qtc_plugin(QmlDesigner
SOURCES_PREFIX components/stateseditor
SOURCES
- stateseditorimageprovider.cpp stateseditorimageprovider.h
- stateseditormodel.cpp stateseditormodel.h
- stateseditorview.cpp stateseditorview.h
- stateseditorwidget.cpp stateseditorwidget.h
-)
-
-extend_qtc_plugin(QmlDesigner
- SOURCES_PREFIX components/stateseditornew
- SOURCES
propertychangesmodel.cpp propertychangesmodel.h
propertymodel.cpp propertymodel.h
stateseditorimageprovider.cpp stateseditorimageprovider.h
diff --git a/src/plugins/qmldesigner/assetexporterplugin/filepathmodel.cpp b/src/plugins/qmldesigner/assetexporterplugin/filepathmodel.cpp
index 5020b095a3..f5df42df39 100644
--- a/src/plugins/qmldesigner/assetexporterplugin/filepathmodel.cpp
+++ b/src/plugins/qmldesigner/assetexporterplugin/filepathmodel.cpp
@@ -67,7 +67,7 @@ Qt::ItemFlags FilePathModel::flags(const QModelIndex &index) const
int FilePathModel::rowCount(const QModelIndex &parent) const
{
if (!parent.isValid())
- return m_files.count();
+ return m_files.size();
return 0;
}
@@ -123,12 +123,14 @@ void FilePathModel::processProject()
beginResetModel();
m_preprocessWatcher.reset(new QFutureWatcher<Utils::FilePath>(this));
- connect(m_preprocessWatcher.get(), &QFutureWatcher<Utils::FilePath>::resultReadyAt, this,
+ connect(m_preprocessWatcher.get(),
+ &QFutureWatcher<Utils::FilePath>::resultReadyAt,
+ this,
[this](int resultIndex) {
- beginInsertRows(index(0, 0) , m_files.count(), m_files.count());
- m_files.append(m_preprocessWatcher->resultAt(resultIndex));
- endInsertRows();
- });
+ beginInsertRows(index(0, 0), m_files.size(), m_files.size());
+ m_files.append(m_preprocessWatcher->resultAt(resultIndex));
+ endInsertRows();
+ });
connect(m_preprocessWatcher.get(), &QFutureWatcher<Utils::FilePath>::finished,
this, &FilePathModel::endResetModel);
diff --git a/src/plugins/qmldesigner/components/annotationeditor/annotationtableview.cpp b/src/plugins/qmldesigner/components/annotationeditor/annotationtableview.cpp
index 7c8daa5eeb..f3cc629dd8 100644
--- a/src/plugins/qmldesigner/components/annotationeditor/annotationtableview.cpp
+++ b/src/plugins/qmldesigner/components/annotationeditor/annotationtableview.cpp
@@ -66,7 +66,7 @@ void CommentDelegate::updateEditorGeometry(QWidget *editor,
editor->setGeometry(option.rect);
}
-Comment CommentDelegate::comment(QModelIndex const &index)
+Comment CommentDelegate::comment(const QModelIndex &index)
{
auto *model = index.model();
return model->data(model->index(index.row(), ColumnId::Title), CommentRole).value<Comment>();
@@ -136,9 +136,9 @@ void CommentValueDelegate::paint(QPainter *painter,
const QModelIndex &index) const
{
auto data = index.model()->data(index, Qt::DisplayRole);
- if (data.userType() == qMetaTypeId<RichTextProxy>())
+ if (data.typeId() == qMetaTypeId<RichTextProxy>())
drawDisplay(painter, option, option.rect, data.value<RichTextProxy>().plainText());
- else if (data.userType() == QMetaType::QColor)
+ else if (data.typeId() == QMetaType::QColor)
painter->fillRect(option.rect, data.value<QColor>());
else
QItemDelegate::paint(painter, option, index);
@@ -147,7 +147,7 @@ void CommentValueDelegate::paint(QPainter *painter,
void CommentValueDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
auto data = index.model()->data(index, Qt::DisplayRole);
- if (data.userType() == qMetaTypeId<RichTextProxy>()) {
+ if (data.typeId() == qMetaTypeId<RichTextProxy>()) {
auto richText = data.value<RichTextProxy>();
auto *e = qobject_cast<RichTextCellEditor *>(editor);
e->setText(richText.plainText());
@@ -157,10 +157,10 @@ void CommentValueDelegate::setEditorData(QWidget *editor, const QModelIndex &ind
this,
&CommentValueDelegate::richTextEditorRequested,
Qt::UniqueConnection);
- } else if (data.userType() == QMetaType::QString) {
+ } else if (data.typeId() == QMetaType::QString) {
auto *e = qobject_cast<QLineEdit *>(editor);
e->setText(data.toString());
- } else if (data.userType() == QMetaType::QColor) {
+ } else if (data.typeId() == QMetaType::QColor) {
auto *e = qobject_cast<AnnotationTableColorButton *>(editor);
e->setColor(data.value<QColor>());
e->installEventFilter(e);
@@ -206,15 +206,13 @@ void CommentValueDelegate::setModelData(QWidget *editor,
const QModelIndex &index) const
{
auto data = model->data(index, Qt::EditRole);
- if (data.userType() == qMetaTypeId<RichTextProxy>())
+ if (data.typeId() == qMetaTypeId<RichTextProxy>())
return;
- else if (data.userType() == QMetaType::QColor)
- {
+ else if (data.typeId() == QMetaType::QColor) {
model->setData(index,
qobject_cast<AnnotationTableColorButton *>(editor)->color(),
Qt::DisplayRole);
- }
- else if (data.userType() == QMetaType::QString)
+ } else if (data.typeId() == QMetaType::QString)
model->setData(index, qobject_cast<QLineEdit *>(editor)->text(), Qt::DisplayRole);
else
QItemDelegate::setModelData(editor, model, index);
@@ -288,7 +286,7 @@ AnnotationTableView::AnnotationTableView(QWidget *parent)
// When comment title was edited, make value item editable
if (item->column() == ColumnId::Title && valueItem) {
valueItem->setEditable(!item->text().isEmpty());
- valueItem->setCheckable(valueItem->data(Qt::DisplayRole).userType() == QMetaType::Bool);
+ valueItem->setCheckable(valueItem->data(Qt::DisplayRole).typeId() == QMetaType::Bool);
}
m_modelUpdating = true;
@@ -344,7 +342,7 @@ Comment AnnotationTableView::fetchComment(int row) const
return comment;
}
-void AnnotationTableView::setupComments(QVector<Comment> const &comments)
+void AnnotationTableView::setupComments(const QVector<Comment> &comments)
{
m_model->clear();
m_modelUpdating = true;
@@ -379,7 +377,7 @@ void AnnotationTableView::setDefaultAnnotations(DefaultAnnotationsModel *default
m_valueDelegate.setDefaultAnnotations(defaults);
}
-void AnnotationTableView::changeRow(int index, Comment const &comment)
+void AnnotationTableView::changeRow(int index, const Comment &comment)
{
auto *titleItem = m_model->item(index, ColumnId::Title);
auto *authorItem = m_model->item(index, ColumnId::Author);
@@ -395,7 +393,7 @@ void AnnotationTableView::changeRow(int index, Comment const &comment)
: QMetaType::UnknownType);
textItem->setEditable(data.isValid());
- textItem->setCheckable(data.userType() == QMetaType::Bool);
+ textItem->setCheckable(data.typeId() == QMetaType::Bool);
textItem->setData(data, Qt::DisplayRole);
}
@@ -433,9 +431,9 @@ bool AnnotationTableView::rowIsEmpty(int row) const
return QString(itemText(0) + itemText(1) + itemText(2)).isEmpty();
}
-QString AnnotationTableView::dataToCommentText(QVariant const &data)
+QString AnnotationTableView::dataToCommentText(const QVariant &data)
{
- auto type = data.userType();
+ auto type = data.typeId();
if (type == qMetaTypeId<RichTextProxy>())
return data.value<RichTextProxy>().text;
@@ -451,7 +449,7 @@ QString AnnotationTableView::dataToCommentText(QVariant const &data)
return {};
}
-QVariant AnnotationTableView::commentToData(Comment const& comment, QMetaType::Type type)
+QVariant AnnotationTableView::commentToData(const Comment &comment, QMetaType::Type type)
{
switch (type) {
case QMetaType::Bool:
diff --git a/src/plugins/qmldesigner/components/annotationeditor/defaultannotations.cpp b/src/plugins/qmldesigner/components/annotationeditor/defaultannotations.cpp
index 7a9212d535..d3a302a782 100644
--- a/src/plugins/qmldesigner/components/annotationeditor/defaultannotations.cpp
+++ b/src/plugins/qmldesigner/components/annotationeditor/defaultannotations.cpp
@@ -58,7 +58,7 @@ bool DefaultAnnotationsModel::hasDefault(const Comment &comment) const
QMetaType::Type DefaultAnnotationsModel::defaultType(const Comment &comment) const
{
- return hasDefault(comment) ? QMetaType::Type(m_defaultMap[comment.title().toLower()].userType())
+ return hasDefault(comment) ? QMetaType::Type(m_defaultMap[comment.title().toLower()].typeId())
: QMetaType::UnknownType;
}
@@ -73,7 +73,7 @@ bool DefaultAnnotationsModel::isRichText(const Comment &comment) const
return type == QMetaType::UnknownType || type == qMetaTypeId<RichTextProxy>();
}
-void DefaultAnnotationsModel::loadFromFile(QString const &filename)
+void DefaultAnnotationsModel::loadFromFile(const QString &filename)
{
QFile file(filename);
if (file.open(QFile::ReadOnly)) {
diff --git a/src/plugins/qmldesigner/components/bindingeditor/actioneditordialog.cpp b/src/plugins/qmldesigner/components/bindingeditor/actioneditordialog.cpp
index ba797ee1a7..8fddcb1ade 100644
--- a/src/plugins/qmldesigner/components/bindingeditor/actioneditordialog.cpp
+++ b/src/plugins/qmldesigner/components/bindingeditor/actioneditordialog.cpp
@@ -88,7 +88,7 @@ void ActionEditorDialog::adjustProperties()
bool typeDone = false;
bool targetDone = false;
- for (int i = 0; i < expression.count(); ++i) {
+ for (int i = 0; i < expression.size(); ++i) {
switch (expression[i].first) {
case QmlJS::AST::Node::Kind::Kind_CallExpression:
@@ -592,7 +592,7 @@ void ActionEditorDialog::fillAndSetSourceProperty(const QString &value,
for (const auto &state : std::as_const(m_states))
m_assignmentSourceProperty->addItem(state, specificItem);
- specificsEnd = m_states.count();
+ specificsEnd = m_states.size();
}
if (specificsEnd != -1)
diff --git a/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.cpp b/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.cpp
index 6cd3e81492..8c8d091179 100644
--- a/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.cpp
+++ b/src/plugins/qmldesigner/components/bindingeditor/bindingeditor.cpp
@@ -174,27 +174,38 @@ void BindingEditor::prepareBindings()
QList<BindingEditorDialog::BindingOption> bindings;
- const QList<TypeName> variantTypes = {"alias", "unknown", "variant", "var"};
- const QList<TypeName> numericTypes = {"double", "real", "int"};
- const QList<TypeName> colorTypes = {"QColor", "color"};
- auto isVariant = [&variantTypes](const TypeName &compareType) { return variantTypes.contains(compareType); };
- auto isNumeric = [&numericTypes](const TypeName &compareType) { return numericTypes.contains(compareType); };
- auto isColor = [&colorTypes](const TypeName &compareType) { return colorTypes.contains(compareType); };
-
- const bool skipTypeFiltering = isVariant(m_backendValueTypeName);
- const bool targetTypeIsNumeric = isNumeric(m_backendValueTypeName);
+ const QVarLengthArray<TypeName> variantTypes = {"alias", "unknown", "variant", "var"};
+ const QVarLengthArray<TypeName> numericTypes = {"double", "real", "int"};
+ const QVarLengthArray<TypeName> colorTypes = {"QColor", "color"};
+ const QVarLengthArray<TypeName> stringTypes = {"QString", "string"};
+
+ auto isVariant = [&variantTypes](const TypeName &compareType) {
+ return variantTypes.contains(compareType);
+ };
+ auto isNumeric = [&numericTypes](const TypeName &compareType) {
+ return numericTypes.contains(compareType);
+ };
+ auto isColor = [&colorTypes](const TypeName &compareType) {
+ return colorTypes.contains(compareType);
+ };
+ auto isString = [&stringTypes](const TypeName &compareType) {
+ return stringTypes.contains(compareType);
+ };
+
+ auto compareTypes = [&](const TypeName &targetType, const TypeName &sourceType) {
+ return isVariant(targetType) || isVariant(sourceType) || (targetType == sourceType)
+ || (isNumeric(targetType) && isNumeric(sourceType))
+ || (isColor(targetType) && isColor(sourceType))
+ || (isString(targetType) && isString(sourceType));
+ };
for (const auto &objnode : allNodes) {
BindingEditorDialog::BindingOption binding;
for (const auto &property : objnode.metaInfo().properties()) {
const TypeName &propertyTypeName = property.propertyType().simplifiedTypeName();
- if (skipTypeFiltering
- || (m_backendValueTypeName == propertyTypeName)
- || isVariant(propertyTypeName)
- || (targetTypeIsNumeric && isNumeric(propertyTypeName))) {
+ if (compareTypes(m_backendValueTypeName, propertyTypeName))
binding.properties.append(QString::fromUtf8(property.name()));
- }
}
//dynamic properties:
@@ -202,12 +213,8 @@ void BindingEditor::prepareBindings()
if (bindingProperty.isValid()) {
if (bindingProperty.isDynamic()) {
const TypeName dynamicTypeName = bindingProperty.dynamicTypeName();
- if (skipTypeFiltering
- || (dynamicTypeName == m_backendValueTypeName)
- || isVariant(dynamicTypeName)
- || (targetTypeIsNumeric && isNumeric(dynamicTypeName))) {
+ if (compareTypes(m_backendValueTypeName, dynamicTypeName))
binding.properties.append(QString::fromUtf8(bindingProperty.name()));
- }
}
}
}
@@ -215,12 +222,8 @@ void BindingEditor::prepareBindings()
if (variantProperty.isValid()) {
if (variantProperty.isDynamic()) {
const TypeName dynamicTypeName = variantProperty.dynamicTypeName();
- if (skipTypeFiltering
- || (dynamicTypeName == m_backendValueTypeName)
- || isVariant(dynamicTypeName)
- || (targetTypeIsNumeric && isNumeric(dynamicTypeName))) {
+ if (compareTypes(m_backendValueTypeName, dynamicTypeName))
binding.properties.append(QString::fromUtf8(variantProperty.name()));
- }
}
}
}
@@ -241,15 +244,10 @@ void BindingEditor::prepareBindings()
BindingEditorDialog::BindingOption binding;
for (const auto &property : metaInfo.properties()) {
- TypeName propertyTypeName = property.propertyType().typeName();
+ const TypeName propertyTypeName = property.propertyType().typeName();
- if (skipTypeFiltering
- || (m_backendValueTypeName == propertyTypeName)
- || (isVariant(propertyTypeName))
- || (targetTypeIsNumeric && isNumeric(propertyTypeName))
- || (isColor(m_backendValueTypeName) && isColor(propertyTypeName))) {
+ if (compareTypes(m_backendValueTypeName, propertyTypeName))
binding.properties.append(QString::fromUtf8(property.name()));
- }
}
if (!binding.properties.isEmpty()) {
diff --git a/src/plugins/qmldesigner/components/componentcore/crumblebar.cpp b/src/plugins/qmldesigner/components/componentcore/crumblebar.cpp
index f4b6697c86..005e353be2 100644
--- a/src/plugins/qmldesigner/components/componentcore/crumblebar.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/crumblebar.cpp
@@ -73,10 +73,8 @@ void CrumbleBar::pushFile(const Utils::FilePath &fileName)
}
if (match != -1) {
- for (int i = crumblePath()->length() - 1 - match; i > 0; --i) {
- crumblePath()->popElement();
- m_pathes.removeLast();
- }
+ for (int i = crumblePath()->length() - 1 - match; i > 0; --i)
+ popElement();
}
}
@@ -163,6 +161,14 @@ bool CrumbleBar::showSaveDialog()
return !canceled;
}
+void CrumbleBar::popElement()
+{
+ crumblePath()->popElement();
+
+ if (!m_pathes.isEmpty())
+ m_pathes.removeLast();
+}
+
void CrumbleBar::onCrumblePathElementClicked(const QVariant &data)
{
CrumbleBarInfo clickedCrumbleBarInfo = data.value<CrumbleBarInfo>();
@@ -176,15 +182,12 @@ void CrumbleBar::onCrumblePathElementClicked(const QVariant &data)
if (!inlineComp && !showSaveDialog())
return;
- while (clickedCrumbleBarInfo != crumblePath()->dataForLastIndex().value<CrumbleBarInfo>()) {
- crumblePath()->popElement();
- m_pathes.removeLast();
- }
+ while (clickedCrumbleBarInfo != crumblePath()->dataForLastIndex().value<CrumbleBarInfo>()
+ && crumblePath()->length() > 0)
+ popElement();
- if (crumblePath()->dataForLastIndex().value<CrumbleBarInfo>().modelNode.isValid()) {
- crumblePath()->popElement();
- m_pathes.removeLast();
- }
+ if (crumblePath()->dataForLastIndex().value<CrumbleBarInfo>().modelNode.isValid())
+ popElement();
m_isInternalCalled = true;
if (inlineComp) {
@@ -192,8 +195,7 @@ void CrumbleBar::onCrumblePathElementClicked(const QVariant &data)
currentDesignDocument()->changeToDocumentModel();
QmlDesignerPlugin::instance()->viewManager().setComponentViewToMaster();
} else {
- crumblePath()->popElement();
- m_pathes.removeLast();
+ popElement();
nextFileIsCalledInternally();
Core::EditorManager::openEditor(clickedCrumbleBarInfo.fileName,
Utils::Id(),
diff --git a/src/plugins/qmldesigner/components/componentcore/crumblebar.h b/src/plugins/qmldesigner/components/componentcore/crumblebar.h
index b9da4488f6..48e71efba6 100644
--- a/src/plugins/qmldesigner/components/componentcore/crumblebar.h
+++ b/src/plugins/qmldesigner/components/componentcore/crumblebar.h
@@ -54,6 +54,7 @@ signals:
private:
void updateVisibility();
bool showSaveDialog();
+ void popElement();
private:
bool m_isInternalCalled = false;
diff --git a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp
index 7243225c88..1562d13b0e 100644
--- a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp
@@ -50,7 +50,7 @@
namespace QmlDesigner {
-static inline QString captionForModelNode(const ModelNode &modelNode)
+inline static QString captionForModelNode(const ModelNode &modelNode)
{
if (modelNode.id().isEmpty())
return modelNode.simplifiedTypeName();
@@ -58,7 +58,7 @@ static inline QString captionForModelNode(const ModelNode &modelNode)
return modelNode.id();
}
-static inline bool contains(const QmlItemNode &node, const QPointF &position)
+inline static bool contains(const QmlItemNode &node, const QPointF &position)
{
return node.isValid() && node.instanceSceneTransform().mapRect(node.instanceBoundingRect()).contains(position);
}
@@ -1208,7 +1208,7 @@ bool isStackedContainerAndIndexCanBeIncreased(const SelectionContext &context)
const int value = containerItemNode.instanceValue(propertyName).toInt();
- const int maxValue = currentSelectedNode.directSubModelNodes().count() - 1;
+ const int maxValue = currentSelectedNode.directSubModelNodes().size() - 1;
return value < maxValue;
}
diff --git a/src/plugins/qmldesigner/components/componentcore/formatoperation.cpp b/src/plugins/qmldesigner/components/componentcore/formatoperation.cpp
index 4676e0f46a..546ad0cc6b 100644
--- a/src/plugins/qmldesigner/components/componentcore/formatoperation.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/formatoperation.cpp
@@ -52,7 +52,7 @@ void readFormatConfiguration(){
QVariantMap rootMap = jsonObject.toVariantMap();
QJsonArray jsonArray = rootMap["propertylist"].toJsonArray();
- for (int i=0; i< jsonArray.count(); ++i){
+ for (int i = 0; i < jsonArray.size(); ++i) {
auto item = jsonArray.at(i).toObject();
QVariantMap itemMap = item.toVariantMap();
StylePropertyStruct current;
diff --git a/src/plugins/qmldesigner/components/componentcore/layoutingridlayout.cpp b/src/plugins/qmldesigner/components/componentcore/layoutingridlayout.cpp
index 09d3fdeffd..89a5868d89 100644
--- a/src/plugins/qmldesigner/components/componentcore/layoutingridlayout.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/layoutingridlayout.cpp
@@ -15,7 +15,7 @@
namespace QmlDesigner {
-static inline void reparentTo(const ModelNode &node, const QmlItemNode &parent)
+inline static void reparentTo(const ModelNode &node, const QmlItemNode &parent)
{
if (parent.isValid() && node.isValid()) {
@@ -78,7 +78,7 @@ static int lowerBound(int i)
return i;
}
-static inline QPointF getUpperLeftPosition(const QList<ModelNode> &modelNodeList)
+inline static QPointF getUpperLeftPosition(const QList<ModelNode> &modelNodeList)
{
QPointF postion(std::numeric_limits<qreal>::max(), std::numeric_limits<qreal>::max());
for (const ModelNode &modelNode : modelNodeList) {
@@ -193,7 +193,7 @@ void LayoutInGridLayout::doIt()
}
}
-bool static hasQtQuickLayoutImport(const SelectionContext &context)
+static bool hasQtQuickLayoutImport(const SelectionContext &context)
{
if (context.view() && context.view()->model()) {
Import import = Import::createLibraryImport(QStringLiteral("QtQuick.Layouts"), QStringLiteral("1.0"));
@@ -219,12 +219,12 @@ void LayoutInGridLayout::layout(const SelectionContext &context)
int LayoutInGridLayout::columnCount() const
{
- return m_xTopOffsets.count();
+ return m_xTopOffsets.size();
}
int LayoutInGridLayout::rowCount() const
{
- return m_yTopOffsets.count();
+ return m_yTopOffsets.size();
}
void LayoutInGridLayout::collectItemNodes()
diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
index 258ae0ba92..d791b04672 100644
--- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
@@ -88,7 +88,7 @@ Utils::SmallString auxPropertyString(Utils::SmallStringView name)
}
} // namespace
-static inline void reparentTo(const ModelNode &node, const QmlItemNode &parent)
+inline static void reparentTo(const ModelNode &node, const QmlItemNode &parent)
{
if (parent.isValid() && node.isValid()) {
@@ -103,7 +103,7 @@ static inline void reparentTo(const ModelNode &node, const QmlItemNode &parent)
}
}
-static inline QPointF getUpperLeftPosition(const QList<ModelNode> &modelNodeList)
+inline static QPointF getUpperLeftPosition(const QList<ModelNode> &modelNodeList)
{
QPointF postion(std::numeric_limits<qreal>::max(), std::numeric_limits<qreal>::max());
for (const ModelNode &modelNode : modelNodeList) {
@@ -364,7 +364,7 @@ void reverse(const SelectionContext &selectionState)
});
}
-static inline void backupPropertyAndRemove(const ModelNode &node, const PropertyName &propertyName)
+inline static void backupPropertyAndRemove(const ModelNode &node, const PropertyName &propertyName)
{
if (node.hasVariantProperty(propertyName)) {
node.setAuxiliaryData(AuxiliaryDataType::Document,
@@ -695,7 +695,8 @@ void addSignalHandlerOrGotoImplementation(const SelectionContext &selectionState
Core::ModeManager::activateMode(Core::Constants::MODE_EDIT);
- if (!usages.isEmpty() && (addAlwaysNewSlot || usages.count() < 2) && (!isModelNodeRoot || addAlwaysNewSlot)) {
+ if (!usages.isEmpty() && (addAlwaysNewSlot || usages.size() < 2)
+ && (!isModelNodeRoot || addAlwaysNewSlot)) {
Core::EditorManager::openEditorAt(
{usages.constFirst().path, usages.constFirst().line, usages.constFirst().col});
@@ -879,7 +880,7 @@ void addItemToStackedContainer(const SelectionContext &selectionContext)
if (potentialTabBar.isValid()) {// The stacked container is hooked up to a TabBar
NodeMetaInfo tabButtonMetaInfo = view->model()->metaInfo("QtQuick.Controls.TabButton", -1, -1);
if (tabButtonMetaInfo.isValid()) {
- const int buttonIndex = potentialTabBar.directSubModelNodes().count();
+ const int buttonIndex = potentialTabBar.directSubModelNodes().size();
ModelNode tabButtonNode =
view->createModelNode("QtQuick.Controls.TabButton",
tabButtonMetaInfo.majorVersion(),
@@ -949,7 +950,7 @@ void increaseIndexOfStackedContainer(const SelectionContext &selectionContext)
int value = containerItemNode.instanceValue(propertyName).toInt();
++value;
- const int maxValue = container.directSubModelNodes().count();
+ const int maxValue = container.directSubModelNodes().size();
QTC_ASSERT(value < maxValue, return);
@@ -1012,7 +1013,7 @@ void addTabBarToStackedContainer(const SelectionContext &selectionContext)
container.parentProperty().reparentHere(tabBarNode);
- const int maxValue = container.directSubModelNodes().count();
+ const int maxValue = container.directSubModelNodes().size();
QmlItemNode tabBarItem(tabBarNode);
@@ -1239,8 +1240,7 @@ void setFlowStartItem(const SelectionContext &selectionContext)
});
}
-
-bool static hasStudioComponentsImport(const SelectionContext &context)
+static bool hasStudioComponentsImport(const SelectionContext &context)
{
if (context.view() && context.view()->model()) {
Import import = Import::createLibraryImport("QtQuick.Studio.Components", "1.0");
@@ -1250,7 +1250,7 @@ bool static hasStudioComponentsImport(const SelectionContext &context)
return false;
}
-static inline void setAdjustedPos(const QmlDesigner::ModelNode &modelNode)
+inline static void setAdjustedPos(const QmlDesigner::ModelNode &modelNode)
{
if (modelNode.hasParentProperty()) {
ModelNode parentNode = modelNode.parentProperty().parentModelNode();
diff --git a/src/plugins/qmldesigner/components/componentcore/svgpasteaction.cpp b/src/plugins/qmldesigner/components/componentcore/svgpasteaction.cpp
index 99bf56078b..738b1affed 100644
--- a/src/plugins/qmldesigner/components/componentcore/svgpasteaction.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/svgpasteaction.cpp
@@ -27,7 +27,7 @@ namespace {
/* Copied from qquicksvgparser.cpp 3e783b26a8fb41e3f5a53b883735f5d10fbbd98a */
// '0' is 0x30 and '9' is 0x39
-static inline bool isDigit(ushort ch)
+inline static bool isDigit(ushort ch)
{
static quint16 magic = 0x3ff;
return ((ch >> 4) == 3) && (magic >> (ch & 15));
@@ -110,7 +110,7 @@ static qreal toDouble(const QChar *&str)
return val;
}
-static inline void parseNumbersArray(const QChar *&str, QVarLengthArray<qreal, 8> &points)
+inline static void parseNumbersArray(const QChar *&str, QVarLengthArray<qreal, 8> &points)
{
while (str->isSpace())
++str;
@@ -261,7 +261,7 @@ bool parsePathDataFast(const QString &dataStr, QPainterPath &path)
if (pathElem == QLatin1Char('z') || pathElem == QLatin1Char('Z'))
arg.append(0);//dummy
const qreal *num = arg.constData();
- int count = arg.count();
+ int count = arg.size();
while (count > 0) {
qreal offsetX = x; // correction offsets
qreal offsetY = y; // for relative commands
diff --git a/src/plugins/qmldesigner/components/componentcore/theme.h b/src/plugins/qmldesigner/components/componentcore/theme.h
index 8e5f10d361..a565ae03fc 100644
--- a/src/plugins/qmldesigner/components/componentcore/theme.h
+++ b/src/plugins/qmldesigner/components/componentcore/theme.h
@@ -141,6 +141,7 @@ public:
editLightOn_medium,
edit_medium,
edit_small,
+ effects,
events_small,
export_medium,
eyeDropper,
@@ -326,6 +327,8 @@ public:
unpin,
upDownIcon,
upDownSquare2,
+ updateAvailable_medium,
+ updateContent_medium,
visibilityOff,
visibilityOn,
visible_medium,
diff --git a/src/plugins/qmldesigner/components/componentcore/viewmanager.cpp b/src/plugins/qmldesigner/components/componentcore/viewmanager.cpp
index ee7ae3f678..29bee73620 100644
--- a/src/plugins/qmldesigner/components/componentcore/viewmanager.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/viewmanager.cpp
@@ -8,9 +8,8 @@
#include <assetslibraryview.h>
#include <capturingconnectionmanager.h>
#include <componentaction.h>
-#include <contentlibraryview.h>
-#include <componentaction.h>
#include <componentview.h>
+#include <contentlibraryview.h>
#include <crumblebar.h>
#include <debugview.h>
#include <designeractionmanagerview.h>
@@ -23,12 +22,11 @@
#include <navigatorview.h>
#include <nodeinstanceview.h>
#include <propertyeditorview.h>
+#include <qmldesignerplugin.h>
#include <rewriterview.h>
-#include <stateseditornew/stateseditorview.h>
#include <stateseditorview.h>
#include <texteditorview.h>
#include <textureeditorview.h>
-#include <qmldesignerplugin.h>
#include <utils/algorithm.h>
@@ -38,14 +36,6 @@
namespace QmlDesigner {
-static bool useOldStatesEditor()
-{
- return QmlDesignerPlugin::instance()
- ->settings()
- .value(DesignerSettingsKey::OLD_STATES_EDITOR)
- .toBool();
-}
-
static Q_LOGGING_CATEGORY(viewBenchmark, "qtc.viewmanager.attach", QtWarningMsg)
class ViewManagerData
@@ -58,7 +48,8 @@ public:
, nodeInstanceView(QCoreApplication::arguments().contains("-capture-puppet-stream")
? capturingConnectionManager
: connectionManager,
- externalDependencies)
+ externalDependencies,
+ true)
, contentLibraryView{externalDependencies}
, componentView{externalDependencies}
, edit3DView{externalDependencies}
@@ -72,7 +63,6 @@ public:
, materialBrowserView{imageCache, externalDependencies}
, textureEditorView{imageCache, externalDependencies}
, statesEditorView{externalDependencies}
- , newStatesEditorView{externalDependencies}
{}
InteractiveConnectionManager connectionManager;
@@ -94,7 +84,6 @@ public:
MaterialBrowserView materialBrowserView;
TextureEditorView textureEditorView;
StatesEditorView statesEditorView;
- Experimental::StatesEditorView newStatesEditorView;
std::vector<std::unique_ptr<AbstractView>> additionalViews;
bool disableStandardViews = false;
@@ -176,30 +165,16 @@ void ViewManager::detachRewriterView()
void ViewManager::switchStateEditorViewToBaseState()
{
- if (useOldStatesEditor()) {
- if (d->statesEditorView.isAttached()) {
- d->savedState = d->statesEditorView.currentState();
- d->statesEditorView.setCurrentState(d->statesEditorView.baseState());
- }
- } else {
- // TODO remove old statesview
- if (d->newStatesEditorView.isAttached()) {
- d->savedState = d->newStatesEditorView.currentState();
- d->newStatesEditorView.setCurrentState(d->newStatesEditorView.baseState());
- }
+ if (d->statesEditorView.isAttached()) {
+ d->savedState = d->statesEditorView.currentState();
+ d->statesEditorView.setCurrentState(d->statesEditorView.baseState());
}
}
void ViewManager::switchStateEditorViewToSavedState()
{
- if (useOldStatesEditor()) {
- if (d->savedState.isValid() && d->statesEditorView.isAttached())
- d->statesEditorView.setCurrentState(d->savedState);
- } else {
- // TODO remove old statesview
- if (d->savedState.isValid() && d->newStatesEditorView.isAttached())
- d->newStatesEditorView.setCurrentState(d->savedState);
- }
+ if (d->savedState.isValid() && d->statesEditorView.isAttached())
+ d->statesEditorView.setCurrentState(d->savedState);
}
QList<AbstractView *> ViewManager::views() const
@@ -223,14 +198,8 @@ QList<AbstractView *> ViewManager::standardViews() const
&d->materialBrowserView,
&d->textureEditorView,
&d->statesEditorView,
- &d->newStatesEditorView, // TODO
&d->designerActionManagerView};
- if (useOldStatesEditor())
- list.removeAll(&d->newStatesEditorView);
- else
- list.removeAll(&d->statesEditorView);
-
if (QmlDesignerPlugin::instance()
->settings()
.value(DesignerSettingsKey::ENABLE_DEBUGVIEW)
@@ -410,10 +379,7 @@ QList<WidgetInfo> ViewManager::widgetInfos() const
widgetInfoList.append(d->materialEditorView.widgetInfo());
widgetInfoList.append(d->materialBrowserView.widgetInfo());
widgetInfoList.append(d->textureEditorView.widgetInfo());
- if (useOldStatesEditor())
- widgetInfoList.append(d->statesEditorView.widgetInfo());
- else
- widgetInfoList.append(d->newStatesEditorView.widgetInfo());
+ widgetInfoList.append(d->statesEditorView.widgetInfo());
#ifdef CHECK_LICENSE
if (checkLicense() == FoundLicense::enterprise)
diff --git a/src/plugins/qmldesigner/components/connectioneditor/backendmodel.cpp b/src/plugins/qmldesigner/components/connectioneditor/backendmodel.cpp
index 6c970f2646..5778d8242f 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/backendmodel.cpp
+++ b/src/plugins/qmldesigner/components/connectioneditor/backendmodel.cpp
@@ -203,7 +203,7 @@ void BackendModel::addNewBackend()
if (dialog.applied()) {
QStringList importSplit = dialog.importString().split(" ");
- if (importSplit.count() != 2) {
+ if (importSplit.size() != 2) {
qWarning() << Q_FUNC_INFO << "invalid import" << importSplit;
QTC_ASSERT(false, return);
}
diff --git a/src/plugins/qmldesigner/components/connectioneditor/bindingmodel.cpp b/src/plugins/qmldesigner/components/connectioneditor/bindingmodel.cpp
index e0a8f03e99..191900d5e9 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/bindingmodel.cpp
+++ b/src/plugins/qmldesigner/components/connectioneditor/bindingmodel.cpp
@@ -217,7 +217,7 @@ static PropertyName unusedProperty(const ModelNode &modelNode)
void BindingModel::addBindingForCurrentNode()
{
- if (connectionView()->selectedModelNodes().count() == 1) {
+ if (connectionView()->selectedModelNodes().size() == 1) {
const ModelNode modelNode = connectionView()->selectedModelNodes().constFirst();
if (modelNode.isValid()) {
try {
@@ -380,9 +380,9 @@ bool BindingModel::getExpressionStrings(const BindingProperty &bindingProperty,
QString propertyName;
- for (int i=1; i < stringList.count(); i++) {
+ for (int i = 1; i < stringList.size(); i++) {
propertyName += stringList.at(i);
- if (i != stringList.count() - 1)
+ if (i != stringList.size() - 1)
propertyName += QLatin1String(".");
}
*sourceProperty = propertyName;
diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp b/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp
index 25a5756c28..4abb7b2137 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp
+++ b/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp
@@ -301,7 +301,7 @@ void ConnectionModel::addConnection()
nodeMetaInfo.minorVersion());
QString source = "console.log(\"clicked\")";
- if (connectionView()->selectedModelNodes().count() == 1) {
+ if (connectionView()->selectedModelNodes().size() == 1) {
ModelNode selectedNode = connectionView()->selectedModelNodes().constFirst();
if (QmlItemNode::isValidQmlItemNode(selectedNode))
selectedNode.nodeAbstractProperty("data").reparentHere(newNode);
diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectionview.cpp b/src/plugins/qmldesigner/components/connectioneditor/connectionview.cpp
index 56fcc7ef6b..d8f84f3e0f 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/connectionview.cpp
+++ b/src/plugins/qmldesigner/components/connectioneditor/connectionview.cpp
@@ -155,7 +155,7 @@ void ConnectionView::selectedNodesChanged(const QList<ModelNode> & selectedNodeL
if (connectionViewWidget()->currentTab() == ConnectionViewWidget::BindingTab
|| connectionViewWidget()->currentTab() == ConnectionViewWidget::DynamicPropertiesTab)
- emit connectionViewWidget()->setEnabledAddButton(selectedNodeList.count() == 1);
+ emit connectionViewWidget()->setEnabledAddButton(selectedNodeList.size() == 1);
}
void ConnectionView::auxiliaryDataChanged([[maybe_unused]] const ModelNode &node,
diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.cpp b/src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.cpp
index f1b0c3f4cb..edade6ae40 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.cpp
+++ b/src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.cpp
@@ -347,14 +347,14 @@ void ConnectionViewWidget::invalidateButtonStatus()
} else if (currentTab() == BindingTab) {
emit setEnabledRemoveButton(ui->bindingView->selectionModel()->hasSelection());
auto bindingModel = qobject_cast<BindingModel*>(ui->bindingView->model());
- emit setEnabledAddButton(bindingModel->connectionView()->model() &&
- bindingModel->connectionView()->selectedModelNodes().count() == 1);
+ emit setEnabledAddButton(bindingModel->connectionView()->model()
+ && bindingModel->connectionView()->selectedModelNodes().size() == 1);
} else if (currentTab() == DynamicPropertiesTab) {
emit setEnabledRemoveButton(ui->dynamicPropertiesView->selectionModel()->hasSelection());
auto dynamicPropertiesModel = qobject_cast<DynamicPropertiesModel*>(ui->dynamicPropertiesView->model());
- emit setEnabledAddButton(dynamicPropertiesModel->view()->model() &&
- dynamicPropertiesModel->selectedNodes().count() == 1);
+ emit setEnabledAddButton(dynamicPropertiesModel->view()->model()
+ && dynamicPropertiesModel->selectedNodes().size() == 1);
} else if (currentTab() == BackendTab) {
emit setEnabledAddButton(true);
emit setEnabledRemoveButton(ui->backendView->selectionModel()->hasSelection());
diff --git a/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.cpp b/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.cpp
index 89e08c5441..4faf5d23f1 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.cpp
+++ b/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.cpp
@@ -180,7 +180,7 @@ void DynamicPropertiesModel::resetModel()
// Value copying is optional
BindingProperty DynamicPropertiesModel::replaceVariantWithBinding(const PropertyName &name, bool copyValue)
{
- if (selectedNodes().count() == 1) {
+ if (selectedNodes().size() == 1) {
const ModelNode modelNode = selectedNodes().constFirst();
if (modelNode.isValid()) {
if (modelNode.hasVariantProperty(name)) {
@@ -214,7 +214,7 @@ BindingProperty DynamicPropertiesModel::replaceVariantWithBinding(const Property
// If it's a BindingProperty, then replaces it with empty VariantProperty
void DynamicPropertiesModel::resetProperty(const PropertyName &name)
{
- if (selectedNodes().count() == 1) {
+ if (selectedNodes().size() == 1) {
const ModelNode modelNode = selectedNodes().constFirst();
if (modelNode.isValid()) {
if (modelNode.hasProperty(name)) {
@@ -454,7 +454,7 @@ void DynamicPropertiesModel::addDynamicPropertyForCurrentNode()
{
QmlDesignerPlugin::emitUsageStatistics(Constants::EVENT_PROPERTY_ADDED);
- if (selectedNodes().count() == 1) {
+ if (selectedNodes().size() == 1) {
const ModelNode modelNode = selectedNodes().constFirst();
if (modelNode.isValid()) {
try {
@@ -839,9 +839,9 @@ bool DynamicPropertiesModel::getExpressionStrings(const BindingProperty &binding
QString propertyName;
- for (int i = 1; i < expressionParts.count(); ++i) {
+ for (int i = 1; i < expressionParts.size(); ++i) {
propertyName += expressionParts.at(i);
- if (i != expressionParts.count() - 1)
+ if (i != expressionParts.size() - 1)
propertyName += QLatin1String(".");
}
*sourceProperty = propertyName;
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffect.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffect.cpp
new file mode 100644
index 0000000000..f572fbe65f
--- /dev/null
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffect.cpp
@@ -0,0 +1,78 @@
+// 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 "contentlibraryeffect.h"
+
+#include <QFileInfo>
+
+namespace QmlDesigner {
+
+ContentLibraryEffect::ContentLibraryEffect(QObject *parent,
+ const QString &name,
+ const QString &qml,
+ const TypeName &type,
+ const QUrl &icon,
+ const QStringList &files)
+ : QObject(parent), m_name(name), m_qml(qml), m_type(type), m_icon(icon), m_files(files)
+{
+ m_allFiles = m_files;
+ m_allFiles.push_back(m_qml);
+}
+
+bool ContentLibraryEffect::filter(const QString &searchText)
+{
+ if (m_visible != m_name.contains(searchText, Qt::CaseInsensitive)) {
+ m_visible = !m_visible;
+ emit itemVisibleChanged();
+ }
+
+ return m_visible;
+}
+
+QUrl ContentLibraryEffect::icon() const
+{
+ return m_icon;
+}
+
+QString ContentLibraryEffect::qml() const
+{
+ return m_qml;
+}
+
+TypeName ContentLibraryEffect::type() const
+{
+ return m_type;
+}
+
+QStringList ContentLibraryEffect::files() const
+{
+ return m_files;
+}
+
+bool ContentLibraryEffect::visible() const
+{
+ return m_visible;
+}
+
+bool ContentLibraryEffect::setImported(bool imported)
+{
+ if (m_imported != imported) {
+ m_imported = imported;
+ emit itemImportedChanged();
+ return true;
+ }
+
+ return false;
+}
+
+bool ContentLibraryEffect::imported() const
+{
+ return m_imported;
+}
+
+QStringList ContentLibraryEffect::allFiles() const
+{
+ return m_allFiles;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffect.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffect.h
new file mode 100644
index 0000000000..fdb302b613
--- /dev/null
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffect.h
@@ -0,0 +1,62 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#pragma once
+
+#include "modelfwd.h"
+
+#include <QObject>
+#include <QUrl>
+
+namespace QmlDesigner {
+
+class ContentLibraryEffect : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString bundleItemName MEMBER m_name CONSTANT)
+ Q_PROPERTY(QUrl bundleItemIcon MEMBER m_icon CONSTANT)
+ Q_PROPERTY(QStringList bundleItemFiles READ allFiles CONSTANT)
+ Q_PROPERTY(bool bundleItemVisible MEMBER m_visible NOTIFY itemVisibleChanged)
+ Q_PROPERTY(bool bundleItemImported READ imported WRITE setImported NOTIFY itemImportedChanged)
+
+public:
+ ContentLibraryEffect(QObject *parent,
+ const QString &name,
+ const QString &qml,
+ const TypeName &type,
+ const QUrl &icon,
+ const QStringList &files);
+
+ bool filter(const QString &searchText);
+
+ QUrl icon() const;
+ QString qml() const;
+ TypeName type() const;
+ QStringList files() const;
+ bool visible() const;
+ QString qmlFilePath() const;
+
+ bool setImported(bool imported);
+ bool imported() const;
+ QString parentDirPath() const;
+ QStringList allFiles() const;
+
+signals:
+ void itemVisibleChanged();
+ void itemImportedChanged();
+
+private:
+ QString m_name;
+ QString m_qml;
+ TypeName m_type;
+ QUrl m_icon;
+ QStringList m_files;
+
+ bool m_visible = true;
+ bool m_imported = false;
+
+ QStringList m_allFiles;
+};
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectscategory.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectscategory.cpp
new file mode 100644
index 0000000000..38e6eed3da
--- /dev/null
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectscategory.cpp
@@ -0,0 +1,63 @@
+// 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 "contentlibraryeffectscategory.h"
+
+#include "contentlibraryeffect.h"
+
+namespace QmlDesigner {
+
+ContentLibraryEffectsCategory::ContentLibraryEffectsCategory(QObject *parent, const QString &name)
+ : QObject(parent), m_name(name) {}
+
+void ContentLibraryEffectsCategory::addBundleItem(ContentLibraryEffect *bundleItem)
+{
+ m_categoryItems.append(bundleItem);
+}
+
+bool ContentLibraryEffectsCategory::updateImportedState(const QStringList &importedItems)
+{
+ bool changed = false;
+
+ for (ContentLibraryEffect *item : std::as_const(m_categoryItems))
+ changed |= item->setImported(importedItems.contains(item->qml().chopped(4)));
+
+ return changed;
+}
+
+bool ContentLibraryEffectsCategory::filter(const QString &searchText)
+{
+ bool visible = false;
+ for (ContentLibraryEffect *item : std::as_const(m_categoryItems))
+ visible |= item->filter(searchText);
+
+ if (visible != m_visible) {
+ m_visible = visible;
+ emit categoryVisibleChanged();
+ return true;
+ }
+
+ return false;
+}
+
+QString ContentLibraryEffectsCategory::name() const
+{
+ return m_name;
+}
+
+bool ContentLibraryEffectsCategory::visible() const
+{
+ return m_visible;
+}
+
+bool ContentLibraryEffectsCategory::expanded() const
+{
+ return m_expanded;
+}
+
+QList<ContentLibraryEffect *> ContentLibraryEffectsCategory::categoryItems() const
+{
+ return m_categoryItems;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectscategory.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectscategory.h
new file mode 100644
index 0000000000..79737c1ec2
--- /dev/null
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectscategory.h
@@ -0,0 +1,47 @@
+// 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 <QObject>
+
+namespace QmlDesigner {
+
+class ContentLibraryEffect;
+
+class ContentLibraryEffectsCategory : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString bundleCategoryName MEMBER m_name CONSTANT)
+ Q_PROPERTY(bool bundleCategoryVisible MEMBER m_visible NOTIFY categoryVisibleChanged)
+ Q_PROPERTY(bool bundleCategoryExpanded MEMBER m_expanded NOTIFY categoryExpandChanged)
+ Q_PROPERTY(QList<ContentLibraryEffect *> bundleCategoryItems MEMBER m_categoryItems
+ NOTIFY categoryItemsChanged)
+
+public:
+ ContentLibraryEffectsCategory(QObject *parent, const QString &name);
+
+ void addBundleItem(ContentLibraryEffect *bundleItem);
+ bool updateImportedState(const QStringList &importedMats);
+ bool filter(const QString &searchText);
+
+ QString name() const;
+ bool visible() const;
+ bool expanded() const;
+ QList<ContentLibraryEffect *> categoryItems() const;
+
+signals:
+ void categoryVisibleChanged();
+ void categoryExpandChanged();
+ void categoryItemsChanged();
+
+private:
+ QString m_name;
+ bool m_visible = true;
+ bool m_expanded = true;
+
+ QList<ContentLibraryEffect *> m_categoryItems;
+};
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.cpp
new file mode 100644
index 0000000000..3bfd374bd8
--- /dev/null
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.cpp
@@ -0,0 +1,286 @@
+// 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 "contentlibraryeffectsmodel.h"
+
+#include "contentlibrarybundleimporter.h"
+#include "contentlibraryeffect.h"
+#include "contentlibraryeffectscategory.h"
+#include "contentlibrarywidget.h"
+#include "qmldesignerconstants.h"
+
+#include <utils/algorithm.h>
+#include <utils/qtcassert.h>
+
+#include <QCoreApplication>
+#include <QJsonArray>
+#include <QJsonDocument>
+#include <QUrl>
+
+namespace QmlDesigner {
+
+ContentLibraryEffectsModel::ContentLibraryEffectsModel(ContentLibraryWidget *parent)
+ : QAbstractListModel(parent)
+ , m_widget(parent)
+{
+}
+
+int ContentLibraryEffectsModel::rowCount(const QModelIndex &) const
+{
+ return m_bundleCategories.size();
+}
+
+QVariant ContentLibraryEffectsModel::data(const QModelIndex &index, int role) const
+{
+ QTC_ASSERT(index.isValid() && index.row() < m_bundleCategories.count(), return {});
+ QTC_ASSERT(roleNames().contains(role), return {});
+
+ return m_bundleCategories.at(index.row())->property(roleNames().value(role));
+}
+
+bool ContentLibraryEffectsModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ if (!index.isValid() || !roleNames().contains(role))
+ return false;
+
+ QByteArray roleName = roleNames().value(role);
+ ContentLibraryEffectsCategory *bundleCategory = m_bundleCategories.at(index.row());
+ QVariant currValue = bundleCategory->property(roleName);
+
+ if (currValue != value) {
+ bundleCategory->setProperty(roleName, value);
+
+ emit dataChanged(index, index, {role});
+ return true;
+ }
+
+ return false;
+}
+
+bool ContentLibraryEffectsModel::isValidIndex(int idx) const
+{
+ return idx > -1 && idx < rowCount();
+}
+
+void ContentLibraryEffectsModel::updateIsEmpty()
+{
+ bool anyCatVisible = Utils::anyOf(m_bundleCategories, [&](ContentLibraryEffectsCategory *cat) {
+ return cat->visible();
+ });
+
+ bool newEmpty = !anyCatVisible || m_bundleCategories.isEmpty() || !hasRequiredQuick3DImport();
+
+ if (newEmpty != m_isEmpty) {
+ m_isEmpty = newEmpty;
+ emit isEmptyChanged();
+ }
+}
+
+QHash<int, QByteArray> ContentLibraryEffectsModel::roleNames() const
+{
+ static const QHash<int, QByteArray> roles {
+ {Qt::UserRole + 1, "bundleCategoryName"},
+ {Qt::UserRole + 2, "bundleCategoryVisible"},
+ {Qt::UserRole + 3, "bundleCategoryExpanded"},
+ {Qt::UserRole + 4, "bundleCategoryItems"}
+ };
+ return roles;
+}
+
+void ContentLibraryEffectsModel::createImporter(const QString &bundlePath, const QString &bundleId,
+ const QStringList &sharedFiles)
+{
+ m_importer = new Internal::ContentLibraryBundleImporter(bundlePath, bundleId, sharedFiles);
+ connect(m_importer, &Internal::ContentLibraryBundleImporter::importFinished, this,
+ [&](const QmlDesigner::NodeMetaInfo &metaInfo) {
+ m_importerRunning = false;
+ emit importerRunningChanged();
+ if (metaInfo.isValid())
+ emit bundleItemImported(metaInfo);
+ });
+
+ connect(m_importer, &Internal::ContentLibraryBundleImporter::unimportFinished, this,
+ [&](const QmlDesigner::NodeMetaInfo &metaInfo) {
+ Q_UNUSED(metaInfo)
+ m_importerRunning = false;
+ emit importerRunningChanged();
+ emit bundleItemUnimported(metaInfo);
+ });
+
+ resetModel();
+ updateIsEmpty();
+}
+
+void ContentLibraryEffectsModel::loadBundle()
+{
+ if (m_bundleExists || m_probeBundleDir)
+ return;
+
+ QDir bundleDir = qEnvironmentVariable("EFFECT_BUNDLE_PATH");
+
+ // search for bundleDir from exec dir and up
+ if (bundleDir.dirName() == ".") {
+ m_probeBundleDir = true; // probe only once
+ bundleDir.setPath(QCoreApplication::applicationDirPath());
+ while (!bundleDir.cd("effect_bundle") && bundleDir.cdUp())
+ ; // do nothing
+
+ if (bundleDir.dirName() != "effect_bundle") // bundlePathDir not found
+ return;
+ }
+
+ QString bundlePath = bundleDir.filePath("effect_bundle.json");
+
+ if (m_bundleObj.isEmpty()) {
+ QFile propsFile(bundlePath);
+
+ if (!propsFile.open(QIODevice::ReadOnly)) {
+ qWarning("Couldn't open effect_bundle.json");
+ return;
+ }
+
+ QJsonDocument bundleJsonDoc = QJsonDocument::fromJson(propsFile.readAll());
+ if (bundleJsonDoc.isNull()) {
+ qWarning("Invalid effect_bundle.json file");
+ return;
+ } else {
+ m_bundleObj = bundleJsonDoc.object();
+ }
+ }
+
+ QString bundleId = m_bundleObj.value("id").toString();
+
+ const QJsonObject catsObj = m_bundleObj.value("categories").toObject();
+ const QStringList categories = catsObj.keys();
+ for (const QString &cat : categories) {
+ auto category = new ContentLibraryEffectsCategory(this, cat);
+
+ const QJsonObject itemsObj = catsObj.value(cat).toObject();
+ const QStringList items = itemsObj.keys();
+ for (const QString &item : items) {
+ const QJsonObject itemObj = itemsObj.value(item).toObject();
+
+ QStringList files;
+ const QJsonArray assetsArr = itemObj.value("files").toArray();
+ for (const auto /*QJson{Const,}ValueRef*/ &asset : assetsArr)
+ files.append(asset.toString());
+
+ QUrl icon = QUrl::fromLocalFile(bundleDir.filePath(itemObj.value("icon").toString()));
+ QString qml = itemObj.value("qml").toString();
+ TypeName type = QLatin1String("%1.%2.%3").arg(
+ QLatin1String(Constants::COMPONENT_BUNDLES_FOLDER).mid(1),
+ bundleId,
+ qml.chopped(4)).toLatin1(); // chopped(4): remove .qml
+
+ auto bundleItem = new ContentLibraryEffect(category, item, qml, type, icon, files);
+
+ category->addBundleItem(bundleItem);
+ }
+ m_bundleCategories.append(category);
+ }
+
+ QStringList sharedFiles;
+ const QJsonArray sharedFilesArr = m_bundleObj.value("sharedFiles").toArray();
+ for (const auto /*QJson{Const,}ValueRef*/ &file : sharedFilesArr)
+ sharedFiles.append(file.toString());
+
+ createImporter(bundleDir.path(), bundleId, sharedFiles);
+
+ m_bundleExists = true;
+ emit bundleExistsChanged();
+}
+
+bool ContentLibraryEffectsModel::hasRequiredQuick3DImport() const
+{
+ return m_widget->hasQuick3DImport() && m_quick3dMajorVersion == 6 && m_quick3dMinorVersion >= 4;
+}
+
+bool ContentLibraryEffectsModel::bundleExists() const
+{
+ return m_bundleExists;
+}
+
+Internal::ContentLibraryBundleImporter *ContentLibraryEffectsModel::bundleImporter() const
+{
+ return m_importer;
+}
+
+void ContentLibraryEffectsModel::setSearchText(const QString &searchText)
+{
+ QString lowerSearchText = searchText.toLower();
+
+ if (m_searchText == lowerSearchText)
+ return;
+
+ m_searchText = lowerSearchText;
+
+ for (int i = 0; i < m_bundleCategories.size(); ++i) {
+ ContentLibraryEffectsCategory *cat = m_bundleCategories.at(i);
+ bool catVisibilityChanged = cat->filter(m_searchText);
+ if (catVisibilityChanged)
+ emit dataChanged(index(i), index(i), {roleNames().keys("bundleCategoryVisible")});
+ }
+
+ updateIsEmpty();
+}
+
+void ContentLibraryEffectsModel::updateImportedState(const QStringList &importedItems)
+{
+ bool changed = false;
+ for (ContentLibraryEffectsCategory *cat : std::as_const(m_bundleCategories))
+ changed |= cat->updateImportedState(importedItems);
+
+ if (changed)
+ resetModel();
+}
+
+void ContentLibraryEffectsModel::setQuick3DImportVersion(int major, int minor)
+{
+ bool oldRequiredImport = hasRequiredQuick3DImport();
+
+ m_quick3dMajorVersion = major;
+ m_quick3dMinorVersion = minor;
+
+ bool newRequiredImport = hasRequiredQuick3DImport();
+
+ if (oldRequiredImport == newRequiredImport)
+ return;
+
+ emit hasRequiredQuick3DImportChanged();
+
+ updateIsEmpty();
+}
+
+void ContentLibraryEffectsModel::resetModel()
+{
+ beginResetModel();
+ endResetModel();
+}
+
+void ContentLibraryEffectsModel::addInstance(ContentLibraryEffect *bundleItem)
+{
+ QString err = m_importer->importComponent(bundleItem->qml(), bundleItem->files());
+
+ if (err.isEmpty()) {
+ m_importerRunning = true;
+ emit importerRunningChanged();
+ } else {
+ qWarning() << __FUNCTION__ << err;
+ }
+}
+
+void ContentLibraryEffectsModel::removeFromProject(ContentLibraryEffect *bundleItem)
+{
+ emit bundleItemAboutToUnimport(bundleItem->type());
+
+ QString err = m_importer->unimportComponent(bundleItem->qml());
+
+ if (err.isEmpty()) {
+ m_importerRunning = true;
+ emit importerRunningChanged();
+ } else {
+ qWarning() << __FUNCTION__ << err;
+ }
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.h
new file mode 100644
index 0000000000..104d34af2d
--- /dev/null
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.h
@@ -0,0 +1,90 @@
+// 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 "nodemetainfo.h"
+
+#include <QAbstractListModel>
+#include <QDir>
+#include <QJsonObject>
+
+namespace QmlDesigner {
+
+class ContentLibraryEffect;
+class ContentLibraryEffectsCategory;
+class ContentLibraryWidget;
+
+namespace Internal {
+class ContentLibraryBundleImporter;
+}
+
+class ContentLibraryEffectsModel : public QAbstractListModel
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool bundleExists READ bundleExists NOTIFY bundleExistsChanged)
+ Q_PROPERTY(bool isEmpty MEMBER m_isEmpty NOTIFY isEmptyChanged)
+ Q_PROPERTY(bool hasRequiredQuick3DImport READ hasRequiredQuick3DImport NOTIFY hasRequiredQuick3DImportChanged)
+ Q_PROPERTY(bool importerRunning MEMBER m_importerRunning NOTIFY importerRunningChanged)
+
+public:
+ ContentLibraryEffectsModel(ContentLibraryWidget *parent = nullptr);
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+ bool setData(const QModelIndex &index, const QVariant &value, int role) override;
+ QHash<int, QByteArray> roleNames() const override;
+
+ void loadBundle();
+ void setSearchText(const QString &searchText);
+ void updateImportedState(const QStringList &importedItems);
+
+ void setQuick3DImportVersion(int major, int minor);
+
+ bool hasRequiredQuick3DImport() const;
+
+ bool bundleExists() const;
+
+ void resetModel();
+ void updateIsEmpty();
+
+ Internal::ContentLibraryBundleImporter *bundleImporter() const;
+
+ Q_INVOKABLE void addInstance(QmlDesigner::ContentLibraryEffect *bundleItem);
+ Q_INVOKABLE void removeFromProject(QmlDesigner::ContentLibraryEffect *bundleItem);
+
+signals:
+ void isEmptyChanged();
+ void hasRequiredQuick3DImportChanged();
+ void bundleItemImported(const QmlDesigner::NodeMetaInfo &metaInfo);
+ void bundleItemAboutToUnimport(const QmlDesigner::TypeName &type);
+ void bundleItemUnimported(const QmlDesigner::NodeMetaInfo &metaInfo);
+ void importerRunningChanged();
+ void bundleExistsChanged();
+
+private:
+ bool isValidIndex(int idx) const;
+ void createImporter(const QString &bundlePath, const QString &bundleId,
+ const QStringList &sharedFiles);
+
+ ContentLibraryWidget *m_widget = nullptr;
+ QString m_searchText;
+ QList<ContentLibraryEffectsCategory *> m_bundleCategories;
+ QJsonObject m_bundleObj;
+ Internal::ContentLibraryBundleImporter *m_importer = nullptr;
+
+ bool m_isEmpty = true;
+ bool m_bundleExists = false;
+ bool m_probeBundleDir = false;
+ bool m_importerRunning = false;
+
+ int m_quick3dMajorVersion = -1;
+ int m_quick3dMinorVersion = -1;
+
+ QString m_importerBundlePath;
+ QString m_importerBundleId;
+ QStringList m_importerSharedFiles;
+};
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryiconprovider.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryiconprovider.cpp
new file mode 100644
index 0000000000..96102bf837
--- /dev/null
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryiconprovider.cpp
@@ -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
+
+#include "contentlibraryiconprovider.h"
+
+#include <coreplugin/icore.h>
+
+namespace QmlDesigner {
+
+namespace Internal {
+
+ContentLibraryIconProvider::ContentLibraryIconProvider()
+ : QQuickImageProvider(Pixmap)
+{
+
+}
+
+QPixmap ContentLibraryIconProvider::requestPixmap(const QString &id,
+ QSize *size,
+ [[maybe_unused]] const QSize &requestedSize)
+{
+ QString realPath = Core::ICore::resourcePath("qmldesigner/contentLibraryImages/" + id).toString();
+
+ QPixmap pixmap{realPath};
+
+ if (size) {
+ size->setWidth(pixmap.width());
+ size->setHeight(pixmap.height());
+ }
+
+ if (pixmap.isNull())
+ return pixmap;
+
+ if (requestedSize.isValid())
+ return pixmap.scaled(requestedSize);
+
+ return pixmap;
+}
+
+} // namespace Internal
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryiconprovider.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryiconprovider.h
new file mode 100644
index 0000000000..56633959d6
--- /dev/null
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryiconprovider.h
@@ -0,0 +1,17 @@
+// 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 <QQuickImageProvider>
+
+namespace QmlDesigner::Internal {
+
+class ContentLibraryIconProvider : public QQuickImageProvider
+{
+public:
+ ContentLibraryIconProvider();
+ QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize) override;
+};
+
+} // namespace QmlDesigner::Internal
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.cpp
index f272a4121d..e5ee371002 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.cpp
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.cpp
@@ -53,7 +53,7 @@ int ContentLibraryMaterialsModel::rowCount(const QModelIndex &) const
QVariant ContentLibraryMaterialsModel::data(const QModelIndex &index, int role) const
{
- QTC_ASSERT(index.isValid() && index.row() < m_bundleCategories.count(), return {});
+ QTC_ASSERT(index.isValid() && index.row() < m_bundleCategories.size(), return {});
QTC_ASSERT(roleNames().contains(role), return {});
return m_bundleCategories.at(index.row())->property(roleNames().value(role));
@@ -332,14 +332,14 @@ void ContentLibraryMaterialsModel::setSearchText(const QString &searchText)
m_searchText = lowerSearchText;
- bool catVisibilityChanged = false;
- for (ContentLibraryMaterialsCategory *cat : std::as_const(m_bundleCategories))
- catVisibilityChanged |= cat->filter(m_searchText);
+ for (int i = 0; i < m_bundleCategories.size(); ++i) {
+ ContentLibraryMaterialsCategory *cat = m_bundleCategories.at(i);
+ bool catVisibilityChanged = cat->filter(m_searchText);
+ if (catVisibilityChanged)
+ emit dataChanged(index(i), index(i), {roleNames().keys("bundleCategoryVisible")});
+ }
updateIsEmpty();
-
- if (catVisibilityChanged)
- resetModel();
}
void ContentLibraryMaterialsModel::updateImportedState(const QStringList &importedMats)
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.cpp
index fbc5199f98..7ab239aab4 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.cpp
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.cpp
@@ -13,17 +13,23 @@ namespace QmlDesigner {
ContentLibraryTexture::ContentLibraryTexture(QObject *parent, const QFileInfo &iconFileInfo,
const QString &downloadPath, const QUrl &icon,
- const QString &webUrl, const QString &fileExt,
- const QSize &dimensions, const qint64 sizeInBytes)
+ const QString &key, const QString &webTextureUrl,
+ const QString &webIconUrl, const QString &fileExt,
+ const QSize &dimensions, const qint64 sizeInBytes,
+ bool hasUpdate, bool isNew)
: QObject(parent)
, m_iconPath(iconFileInfo.filePath())
, m_downloadPath(downloadPath)
- , m_webUrl(webUrl)
+ , m_webTextureUrl(webTextureUrl)
+ , m_webIconUrl(webIconUrl)
, m_baseName{iconFileInfo.baseName()}
, m_fileExt(fileExt)
+ , m_textureKey(key)
, m_icon(icon)
, m_dimensions(dimensions)
, m_sizeInBytes(sizeInBytes)
+ , m_hasUpdate(hasUpdate)
+ , m_isNew(isNew)
{
doSetDownloaded();
}
@@ -58,7 +64,7 @@ QString ContentLibraryTexture::resolveFileExt()
if (textureFiles.isEmpty())
return {};
- if (textureFiles.count() > 1) {
+ if (textureFiles.size() > 1) {
qWarning() << "Found multiple textures with the same name in the same directories: "
<< Utils::transform(textureFiles, [](const QFileInfo &fi) {
return fi.fileName();
@@ -122,4 +128,22 @@ QString ContentLibraryTexture::parentDirPath() const
return m_downloadPath;
}
+QString ContentLibraryTexture::textureKey() const
+{
+ return m_textureKey;
+}
+
+void ContentLibraryTexture::setHasUpdate(bool value)
+{
+ if (m_hasUpdate != value) {
+ m_hasUpdate = value;
+ emit hasUpdateChanged();
+ }
+}
+
+bool ContentLibraryTexture::hasUpdate() const
+{
+ return m_hasUpdate;
+}
+
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h
index 074d4abb77..9f5b46630f 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h
@@ -19,12 +19,17 @@ class ContentLibraryTexture : public QObject
Q_PROPERTY(QString textureToolTip MEMBER m_toolTip NOTIFY textureToolTipChanged)
Q_PROPERTY(QUrl textureIcon MEMBER m_icon CONSTANT)
Q_PROPERTY(bool textureVisible MEMBER m_visible NOTIFY textureVisibleChanged)
- Q_PROPERTY(QString textureWebUrl MEMBER m_webUrl CONSTANT)
+ Q_PROPERTY(QString textureWebUrl MEMBER m_webTextureUrl CONSTANT)
+ Q_PROPERTY(QString textureWebIconUrl MEMBER m_webIconUrl CONSTANT)
+ Q_PROPERTY(bool textureHasUpdate WRITE setHasUpdate READ hasUpdate NOTIFY hasUpdateChanged)
+ Q_PROPERTY(bool textureIsNew MEMBER m_isNew CONSTANT)
+ Q_PROPERTY(QString textureKey MEMBER m_textureKey CONSTANT)
public:
- ContentLibraryTexture(QObject *parent, const QFileInfo &iconFileInfo,
- const QString &downloadPath, const QUrl &icon, const QString &webUrl,
- const QString &fileExt, const QSize &dimensions, const qint64 sizeInBytes);
+ ContentLibraryTexture(QObject *parent, const QFileInfo &iconFileInfo, const QString &downloadPath,
+ const QUrl &icon, const QString &key, const QString &webTextureUrl,
+ const QString &webIconUrl, const QString &fileExt, const QSize &dimensions,
+ const qint64 sizeInBytes, bool hasUpdate, bool isNew);
Q_INVOKABLE bool isDownloaded() const;
Q_INVOKABLE void setDownloaded();
@@ -35,10 +40,15 @@ public:
QString iconPath() const;
QString downloadedTexturePath() const;
QString parentDirPath() const;
+ QString textureKey() const;
+
+ void setHasUpdate(bool value);
+ bool hasUpdate() const;
signals:
void textureVisibleChanged();
void textureToolTipChanged();
+ void hasUpdateChanged();
private:
QString resolveFileExt();
@@ -47,16 +57,20 @@ private:
QString m_iconPath;
QString m_downloadPath;
- QString m_webUrl;
+ QString m_webTextureUrl;
+ QString m_webIconUrl;
QString m_toolTip;
QString m_baseName;
QString m_fileExt;
+ QString m_textureKey;
QUrl m_icon;
QSize m_dimensions;
qint64 m_sizeInBytes = -1;
bool m_isDownloaded = false;
bool m_visible = true;
+ bool m_hasUpdate = false;
+ bool m_isNew = false;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.cpp
index eecab42552..77519ad88f 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.cpp
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.cpp
@@ -5,6 +5,8 @@
#include "contentlibrarytexture.h"
+#include <utils/algorithm.h>
+
#include <QFileInfo>
namespace QmlDesigner {
@@ -13,13 +15,16 @@ ContentLibraryTexturesCategory::ContentLibraryTexturesCategory(QObject *parent,
: QObject(parent), m_name(name) {}
void ContentLibraryTexturesCategory::addTexture(const QFileInfo &tex, const QString &downloadPath,
- const QString &webUrl, const QString &fileExt,
- const QSize &dimensions, const qint64 sizeInBytes)
+ const QString &key, const QString &webTextureUrl,
+ const QString &webIconUrl, const QString &fileExt,
+ const QSize &dimensions, const qint64 sizeInBytes,
+ bool hasUpdate, bool isNew)
{
QUrl icon = QUrl::fromLocalFile(tex.absoluteFilePath());
- m_categoryTextures.append(new ContentLibraryTexture(this, tex, downloadPath, icon, webUrl,
- fileExt, dimensions, sizeInBytes));
+ m_categoryTextures.append(new ContentLibraryTexture(
+ this, tex, downloadPath, icon, key, webTextureUrl, webIconUrl,
+ fileExt, dimensions, sizeInBytes, hasUpdate, isNew));
}
bool ContentLibraryTexturesCategory::filter(const QString &searchText)
@@ -57,4 +62,14 @@ QList<ContentLibraryTexture *> ContentLibraryTexturesCategory::categoryTextures(
return m_categoryTextures;
}
+void ContentLibraryTexturesCategory::markTextureHasNoUpdate(const QString &textureKey)
+{
+ auto *texture = Utils::findOrDefault(m_categoryTextures, [&textureKey](ContentLibraryTexture *t) {
+ return t->textureKey() == textureKey;
+ });
+
+ if (texture)
+ texture->setHasUpdate(false);
+}
+
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.h
index 91ecaaac96..166528f05a 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.h
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.h
@@ -27,8 +27,9 @@ class ContentLibraryTexturesCategory : public QObject
public:
ContentLibraryTexturesCategory(QObject *parent, const QString &name);
- void addTexture(const QFileInfo &tex, const QString &subPath, const QString &webUrl,
- const QString &fileExt, const QSize &dimensions, const qint64 sizeInBytes);
+ void addTexture(const QFileInfo &tex, const QString &subPath, const QString &key,
+ const QString &webTextureUrl, const QString &webIconUrl, const QString &fileExt,
+ const QSize &dimensions, const qint64 sizeInBytes, bool hasUpdate, bool isNew);
bool filter(const QString &searchText);
QString name() const;
@@ -36,6 +37,8 @@ public:
bool expanded() const;
QList<ContentLibraryTexture *> categoryTextures() const;
+ void markTextureHasNoUpdate(const QString &textureKey);
+
signals:
void categoryVisibleChanged();
void categoryExpandChanged();
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.cpp
index 5cf88ab6fc..319ca2686f 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.cpp
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.cpp
@@ -36,7 +36,7 @@ int ContentLibraryTexturesModel::rowCount(const QModelIndex &) const
QVariant ContentLibraryTexturesModel::data(const QModelIndex &index, int role) const
{
- QTC_ASSERT(index.isValid() && index.row() < m_bundleCategories.count(), return {});
+ QTC_ASSERT(index.isValid() && index.row() < m_bundleCategories.size(), return {});
QTC_ASSERT(roleNames().contains(role), return {});
return m_bundleCategories.at(index.row())->property(roleNames().value(role));
@@ -98,7 +98,8 @@ QHash<int, QByteArray> ContentLibraryTexturesModel::roleNames() const
* @param bundlePath local path to the bundle folder and icons
* @param metaData bundle textures metadata
*/
-void ContentLibraryTexturesModel::loadTextureBundle(const QString &remoteUrl, const QString &bundleIconPath,
+void ContentLibraryTexturesModel::loadTextureBundle(const QString &remoteUrl, const QString &iconsUrl,
+ const QString &bundleIconPath,
const QVariantMap &metaData)
{
if (!m_bundleCategories.isEmpty())
@@ -117,8 +118,9 @@ void ContentLibraryTexturesModel::loadTextureBundle(const QString &remoteUrl, co
auto category = new ContentLibraryTexturesCategory(this, dir.fileName());
const QFileInfoList texFiles = QDir(dir.filePath()).entryInfoList(QDir::Files);
for (const QFileInfo &tex : texFiles) {
- QString fullRemoteUrl = QString("%1/%2/%3.zip").arg(remoteUrl, dir.fileName(),
- tex.baseName());
+ QString textureUrl = QString("%1/%2/%3.zip").arg(remoteUrl, dir.fileName(), tex.baseName());
+ QString iconUrl = QString("%1/%2/%3.png").arg(iconsUrl, dir.fileName(), tex.baseName());
+
QString localDownloadPath = QString("%1/%2/%3")
.arg(Paths::bundlesPathSetting(),
m_category,
@@ -127,15 +129,20 @@ void ContentLibraryTexturesModel::loadTextureBundle(const QString &remoteUrl, co
QString fileExt;
QSize dimensions;
qint64 sizeInBytes = -1;
+ bool hasUpdate = false;
+ bool isNew = false;
if (imageItems.contains(key)) {
QVariantMap dataMap = imageItems[key].toMap();
fileExt = '.' + dataMap.value("format").toString();
dimensions = QSize(dataMap.value("width").toInt(), dataMap.value("height").toInt());
sizeInBytes = dataMap.value("file_size").toLongLong();
+ hasUpdate = m_modifiedFiles.contains(key);
+ isNew = m_newFiles.contains(key);
}
- category->addTexture(tex, localDownloadPath, fullRemoteUrl, fileExt, dimensions, sizeInBytes);
+ category->addTexture(tex, localDownloadPath, key, textureUrl, iconUrl, fileExt,
+ dimensions, sizeInBytes, hasUpdate, isNew);
}
m_bundleCategories.append(category);
}
@@ -144,6 +151,52 @@ void ContentLibraryTexturesModel::loadTextureBundle(const QString &remoteUrl, co
updateIsEmpty();
}
+void ContentLibraryTexturesModel::setModifiedFileEntries(const QVariantMap &files)
+{
+ m_modifiedFiles.clear();
+
+ const QString prefix = m_category + "/";
+ const QStringList keys = files.keys();
+
+ for (const QString &key : keys) {
+ if (key.startsWith(prefix))
+ m_modifiedFiles[key] = files[key];
+ }
+}
+
+void ContentLibraryTexturesModel::setNewFileEntries(const QStringList &newFiles)
+{
+ const QString prefix = m_category + "/";
+
+ m_newFiles = Utils::filteredCast<QSet<QString>>(newFiles, [&prefix](const QString &key) {
+ return key.startsWith(prefix);
+ });
+}
+
+QString ContentLibraryTexturesModel::removeModifiedFileEntry(const QString &key)
+{
+ if (m_modifiedFiles.contains(key)) {
+ QVariantMap item = m_modifiedFiles[key].toMap();
+ m_modifiedFiles.remove(key);
+ return item["checksum"].toString();
+ } else {
+ return {};
+ }
+}
+
+void ContentLibraryTexturesModel::markTextureHasNoUpdates(const QString &subcategory,
+ const QString &textureKey)
+{
+ auto *categ = Utils::findOrDefault(m_bundleCategories,
+ [&subcategory](ContentLibraryTexturesCategory *c) {
+ return c->name() == subcategory;
+ });
+ if (!categ)
+ return;
+
+ categ->markTextureHasNoUpdate(textureKey);
+}
+
bool ContentLibraryTexturesModel::texBundleExists() const
{
return !m_bundleCategories.isEmpty();
@@ -172,15 +225,14 @@ void ContentLibraryTexturesModel::setSearchText(const QString &searchText)
m_searchText = lowerSearchText;
- bool catVisibilityChanged = false;
-
- for (ContentLibraryTexturesCategory *cat : std::as_const(m_bundleCategories))
- catVisibilityChanged |= cat->filter(m_searchText);
+ for (int i = 0; i < m_bundleCategories.size(); ++i) {
+ ContentLibraryTexturesCategory *cat = m_bundleCategories.at(i);
+ bool catVisibilityChanged = cat->filter(m_searchText);
+ if (catVisibilityChanged)
+ emit dataChanged(index(i), index(i), {roleNames().keys("bundleCategoryVisible")});
+ }
updateIsEmpty();
-
- if (catVisibilityChanged)
- resetModel();
}
void ContentLibraryTexturesModel::resetModel()
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.h
index 3f7e4d4868..92db4151a8 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.h
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.h
@@ -26,6 +26,10 @@ public:
QHash<int, QByteArray> roleNames() const override;
void setSearchText(const QString &searchText);
+ void setModifiedFileEntries(const QVariantMap &files);
+ void setNewFileEntries(const QStringList &newFiles);
+ QString removeModifiedFileEntry(const QString &key);
+ void markTextureHasNoUpdates(const QString &subcategory, const QString &textureKey);
bool texBundleExists() const;
@@ -33,8 +37,8 @@ public:
void setHasSceneEnv(bool b);
void resetModel();
- void loadTextureBundle(const QString &remoteUrl, const QString &bundlePath,
- const QVariantMap &metaData);
+ void loadTextureBundle(const QString &remoteUrl, const QString &iconsUrl,
+ const QString &bundlePath, const QVariantMap &metaData);
signals:
void isEmptyChanged();
@@ -48,6 +52,8 @@ private:
QString m_searchText;
QString m_category;
QList<ContentLibraryTexturesCategory *> m_bundleCategories;
+ QVariantMap m_modifiedFiles;
+ QSet<QString> m_newFiles;
bool m_isEmpty = true;
bool m_hasSceneEnv = false;
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp
index 3bb579273f..3f64f8d8b4 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp
@@ -4,6 +4,8 @@
#include "contentlibraryview.h"
#include "contentlibrarybundleimporter.h"
+#include "contentlibraryeffect.h"
+#include "contentlibraryeffectsmodel.h"
#include "contentlibrarymaterial.h"
#include "contentlibrarymaterialsmodel.h"
#include "contentlibrarytexture.h"
@@ -26,6 +28,8 @@
#include <qtsupport/qtkitinformation.h>
#endif
+#include <QVector3D>
+
namespace QmlDesigner {
ContentLibraryView::ContentLibraryView(ExternalDependenciesInterface &externalDependencies)
@@ -54,6 +58,10 @@ WidgetInfo ContentLibraryView::widgetInfo()
[&] (QmlDesigner::ContentLibraryTexture *tex) {
m_draggedBundleTexture = tex;
});
+ connect(m_widget, &ContentLibraryWidget::bundleEffectDragStarted, this,
+ [&] (QmlDesigner::ContentLibraryEffect *eff) {
+ m_draggedBundleEffect = eff;
+ });
connect(m_widget, &ContentLibraryWidget::addTextureRequested, this,
[&] (const QString &texPath, AddTextureMode mode) {
@@ -109,6 +117,46 @@ WidgetInfo ContentLibraryView::widgetInfo()
connect(materialsModel, &ContentLibraryMaterialsModel::bundleMaterialUnimported, this,
&ContentLibraryView::updateBundleMaterialsImportedState);
+
+ ContentLibraryEffectsModel *effectsModel = m_widget->effectsModel().data();
+
+ connect(effectsModel, &ContentLibraryEffectsModel::bundleItemImported, this,
+ [&] (const QmlDesigner::NodeMetaInfo &metaInfo) {
+ QTC_ASSERT(metaInfo.isValid(), return);
+
+ if (!m_bundleEffectTarget)
+ m_bundleEffectTarget = active3DSceneNode();
+
+ QTC_ASSERT(m_bundleEffectTarget, return);
+
+ executeInTransaction("ContentLibraryView::widgetInfo", [&] {
+ QVector3D pos = m_bundleEffectPos.value<QVector3D>();
+ ModelNode newEffNode = createModelNode(metaInfo.typeName(), metaInfo.majorVersion(),
+ metaInfo.minorVersion(),
+ {{"x", pos.x()}, {"y", pos.y()}, {"z", pos.z()}});
+ m_bundleEffectTarget.defaultNodeListProperty().reparentHere(newEffNode);
+ clearSelectedModelNodes();
+ selectModelNode(newEffNode);
+ });
+
+ updateBundleEffectsImportedState();
+ m_bundleEffectTarget = {};
+ m_bundleEffectPos = {};
+ });
+
+ connect(effectsModel, &ContentLibraryEffectsModel::bundleItemAboutToUnimport, this,
+ [&] (const QmlDesigner::TypeName &type) {
+ // delete instances of the bundle effect that is about to be unimported
+ executeInTransaction("ContentLibraryView::widgetInfo", [&] {
+ NodeMetaInfo metaInfo = model()->metaInfo(type);
+ QList<ModelNode> effects = allModelNodesOfType(metaInfo);
+ for (ModelNode &eff : effects)
+ eff.destroy();
+ });
+ });
+
+ connect(effectsModel, &ContentLibraryEffectsModel::bundleItemUnimported, this,
+ &ContentLibraryView::updateBundleEffectsImportedState);
}
return createWidgetInfo(m_widget.data(),
@@ -124,7 +172,7 @@ void ContentLibraryView::modelAttached(Model *model)
m_hasQuick3DImport = model->hasImport("QtQuick3D");
- updateBundleMaterialsQuick3DVersion();
+ updateBundlesQuick3DVersion();
updateBundleMaterialsImportedState();
const bool hasLibrary = materialLibraryNode().isValid();
@@ -134,6 +182,9 @@ void ContentLibraryView::modelAttached(Model *model)
m_sceneId = model->active3DSceneId();
m_widget->clearSearchFilter();
+
+ m_widget->effectsModel()->loadBundle();
+ updateBundleEffectsImportedState();
}
void ContentLibraryView::modelAboutToBeDetached(Model *model)
@@ -149,7 +200,7 @@ void ContentLibraryView::importsChanged(const Imports &addedImports, const Impor
Q_UNUSED(addedImports)
Q_UNUSED(removedImports)
- updateBundleMaterialsQuick3DVersion();
+ updateBundlesQuick3DVersion();
bool hasQuick3DImport = model()->hasImport("QtQuick3D");
@@ -211,6 +262,12 @@ void ContentLibraryView::customNotification(const AbstractView *view, const QStr
m_widget->addTexture(m_draggedBundleTexture);
m_draggedBundleTexture = nullptr;
+ } else if (identifier == "drop_bundle_effect") {
+ QTC_ASSERT(nodeList.size() == 1, return);
+
+ m_bundleEffectPos = data.size() == 1 ? data.first() : QVariant();
+ m_widget->effectsModel()->addInstance(m_draggedBundleEffect);
+ m_bundleEffectTarget = nodeList.first() ? nodeList.first() : active3DSceneNode();
}
}
@@ -349,7 +406,26 @@ void ContentLibraryView::updateBundleMaterialsImportedState()
m_widget->materialsModel()->updateImportedState(importedBundleMats);
}
-void ContentLibraryView::updateBundleMaterialsQuick3DVersion()
+void ContentLibraryView::updateBundleEffectsImportedState()
+{
+ using namespace Utils;
+
+ if (!m_widget->effectsModel()->bundleImporter())
+ return;
+
+ QStringList importedBundleEffs;
+
+ FilePath bundlePath = m_widget->effectsModel()->bundleImporter()->resolveBundleImportPath();
+
+ if (bundlePath.exists()) {
+ importedBundleEffs = transform(bundlePath.dirEntries({{"*.qml"}, QDir::Files}),
+ [](const FilePath &f) { return f.fileName().chopped(4); });
+ }
+
+ m_widget->effectsModel()->updateImportedState(importedBundleEffs);
+}
+
+void ContentLibraryView::updateBundlesQuick3DVersion()
{
bool hasImport = false;
int major = -1;
@@ -382,6 +458,7 @@ void ContentLibraryView::updateBundleMaterialsQuick3DVersion()
}
#endif
m_widget->materialsModel()->setQuick3DImportVersion(major, minor);
+ m_widget->effectsModel()->setQuick3DImportVersion(major, minor);
}
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h
index 137034dd95..741a77759e 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h
@@ -3,8 +3,8 @@
#pragma once
-#include "createtexture.h"
#include "abstractview.h"
+#include "createtexture.h"
#include "nodemetainfo.h"
#include <QObject>
@@ -12,6 +12,7 @@
namespace QmlDesigner {
+class ContentLibraryEffect;
class ContentLibraryMaterial;
class ContentLibraryTexture;
class ContentLibraryWidget;
@@ -44,16 +45,20 @@ public:
private:
void updateBundleMaterialsImportedState();
- void updateBundleMaterialsQuick3DVersion();
+ void updateBundleEffectsImportedState();
+ void updateBundlesQuick3DVersion();
void applyBundleMaterialToDropTarget(const ModelNode &bundleMat, const NodeMetaInfo &metaInfo = {});
ModelNode getBundleMaterialDefaultInstance(const TypeName &type);
ModelNode createMaterial(const NodeMetaInfo &metaInfo);
QPointer<ContentLibraryWidget> m_widget;
QList<ModelNode> m_bundleMaterialTargets;
+ ModelNode m_bundleEffectTarget; // target of the dropped bundle effect
+ QVariant m_bundleEffectPos; // pos of the dropped bundle effect
QList<ModelNode> m_selectedModels; // selected 3D model nodes
ContentLibraryMaterial *m_draggedBundleMaterial = nullptr;
ContentLibraryTexture *m_draggedBundleTexture = nullptr;
+ ContentLibraryEffect *m_draggedBundleEffect = nullptr;
bool m_bundleMaterialAddToSelected = false;
bool m_hasQuick3DImport = false;
qint32 m_sceneId = -1;
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp
index 4c15cce8d7..78bc1f07c3 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp
@@ -3,13 +3,17 @@
#include "contentlibrarywidget.h"
+#include "contentlibraryeffect.h"
+#include "contentlibraryeffectsmodel.h"
#include "contentlibrarymaterial.h"
#include "contentlibrarymaterialsmodel.h"
#include "contentlibrarytexture.h"
#include "contentlibrarytexturesmodel.h"
+#include "contentlibraryiconprovider.h"
#include "utils/filedownloader.h"
#include "utils/fileextractor.h"
+#include "utils/multifiledownloader.h"
#include <coreplugin/icore.h>
#include <designerpaths.h>
@@ -24,13 +28,16 @@
#include <utils/qtcassert.h>
#include <QDir>
+#include <QJsonArray>
#include <QJsonDocument>
+#include <QJsonObject>
#include <QMimeData>
#include <QMouseEvent>
#include <QQmlContext>
#include <QQmlEngine>
#include <QQuickItem>
#include <QQuickWidget>
+#include <QRegularExpression>
#include <QShortcut>
#include <QStandardPaths>
#include <QVBoxLayout>
@@ -59,7 +66,20 @@ bool ContentLibraryWidget::eventFilter(QObject *obj, QEvent *event)
Model *model = document->currentModel();
QTC_ASSERT(model, return false);
- if (m_materialToDrag) {
+ if (m_effectToDrag) {
+ QMouseEvent *me = static_cast<QMouseEvent *>(event);
+ if ((me->globalPos() - m_dragStartPoint).manhattanLength() > 20) {
+ QByteArray data;
+ QMimeData *mimeData = new QMimeData;
+ QDataStream stream(&data, QIODevice::WriteOnly);
+ stream << m_effectToDrag->type();
+ mimeData->setData(Constants::MIME_TYPE_BUNDLE_EFFECT, data);
+
+ emit bundleEffectDragStarted(m_effectToDrag);
+ model->startDrag(mimeData, m_effectToDrag->icon().toLocalFile());
+ m_effectToDrag = nullptr;
+ }
+ } else if (m_materialToDrag) {
QMouseEvent *me = static_cast<QMouseEvent *>(event);
if ((me->globalPosition().toPoint() - m_dragStartPoint).manhattanLength() > 20
&& m_materialToDrag->isDownloaded()) {
@@ -91,6 +111,7 @@ bool ContentLibraryWidget::eventFilter(QObject *obj, QEvent *event)
}
}
} else if (event->type() == QMouseEvent::MouseButtonRelease) {
+ m_effectToDrag = nullptr;
m_materialToDrag = nullptr;
m_textureToDrag = nullptr;
setIsDragging(false);
@@ -104,6 +125,7 @@ ContentLibraryWidget::ContentLibraryWidget()
, m_materialsModel(new ContentLibraryMaterialsModel(this))
, m_texturesModel(new ContentLibraryTexturesModel("Textures", this))
, m_environmentsModel(new ContentLibraryTexturesModel("Environments", this))
+ , m_effectsModel(new ContentLibraryEffectsModel(this))
{
qmlRegisterType<QmlDesigner::FileDownloader>("WebFetcher", 1, 0, "FileDownloader");
qmlRegisterType<QmlDesigner::FileExtractor>("WebFetcher", 1, 0, "FileExtractor");
@@ -113,6 +135,8 @@ ContentLibraryWidget::ContentLibraryWidget()
m_quickWidget->quickWidget()->setObjectName(Constants::OBJECT_NAME_CONTENT_LIBRARY);
m_quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
+ m_quickWidget->engine()->addImageProvider(QStringLiteral("contentlibrary"),
+ new Internal::ContentLibraryIconProvider);
m_quickWidget->engine()->addImportPath(propertyEditorResourcesPath() + "/imports");
m_quickWidget->setClearColor(Theme::getColor(Theme::Color::DSpanelBackground));
@@ -121,6 +145,8 @@ ContentLibraryWidget::ContentLibraryWidget()
+ "/textures";
m_texturesUrl = m_baseUrl + "/Textures";
+ m_textureIconsUrl = m_baseUrl + "/icons/Textures";
+ m_environmentIconsUrl = m_baseUrl + "/icons/Environments";
m_environmentsUrl = m_baseUrl + "/Environments";
m_downloadPath = Paths::bundlesPathSetting();
@@ -147,10 +173,11 @@ ContentLibraryWidget::ContentLibraryWidget()
auto map = m_quickWidget->registerPropertyMap("ContentLibraryBackend");
- map->setProperties({{"rootView", QVariant::fromValue(this)},
- {"materialsModel", QVariant::fromValue(m_materialsModel.data())},
- {"texturesModel", QVariant::fromValue(m_texturesModel.data())},
- {"environmentsModel", QVariant::fromValue(m_environmentsModel.data())}});
+ map->setProperties({{"rootView", QVariant::fromValue(this)},
+ {"materialsModel", QVariant::fromValue(m_materialsModel.data())},
+ {"texturesModel", QVariant::fromValue(m_texturesModel.data())},
+ {"environmentsModel", QVariant::fromValue(m_environmentsModel.data())},
+ {"effectsModel", QVariant::fromValue(m_effectsModel.data())}});
reloadQmlSource();
}
@@ -178,8 +205,231 @@ void ContentLibraryWidget::loadTextureBundle()
if (fetchTextureBundleMetadata(bundleDir) && fetchTextureBundleIcons(bundleDir)) {
QString bundleIconPath = m_downloadPath + "/TextureBundleIcons";
QVariantMap metaData = readBundleMetadata();
- m_texturesModel->loadTextureBundle(m_texturesUrl, bundleIconPath, metaData);
- m_environmentsModel->loadTextureBundle(m_environmentsUrl, bundleIconPath, metaData);
+ m_texturesModel->loadTextureBundle(m_texturesUrl, m_textureIconsUrl, bundleIconPath, metaData);
+ m_environmentsModel->loadTextureBundle(m_environmentsUrl, m_environmentIconsUrl,
+ bundleIconPath, metaData);
+ }
+}
+
+std::tuple<QVariantMap, QVariantMap, QVariantMap> ContentLibraryWidget::compareTextureMetaFiles(
+ const QString &existingMetaFilePath, const QString downloadedMetaFilePath)
+{
+ QVariantMap existingMeta;
+ QFile existingFile(existingMetaFilePath);
+ if (existingFile.open(QIODeviceBase::ReadOnly | QIODeviceBase::Text))
+ existingMeta = QJsonDocument::fromJson(existingFile.readAll()).toVariant().toMap();
+
+ QVariantMap downloadedMeta;
+ QFile downloadedFile(downloadedMetaFilePath);
+ if (downloadedFile.open(QIODeviceBase::ReadOnly | QIODeviceBase::Text))
+ downloadedMeta = QJsonDocument::fromJson(downloadedFile.readAll()).toVariant().toMap();
+
+ int existingVersion = existingMeta["version"].toInt();
+ int downloadedVersion = downloadedMeta["version"].toInt();
+
+ if (existingVersion != downloadedVersion) {
+ qWarning() << "We're not comparing local vs downloaded textures metadata because they are "
+ "of different versions";
+ return {};
+ }
+
+ QVariantMap existingItems = existingMeta["image_items"].toMap();
+ QVariantMap downloadedItems = downloadedMeta["image_items"].toMap();
+
+ QStringList existingKeys = existingItems.keys();
+ QStringList downloadedKeys = downloadedItems.keys();
+
+ QSet<QString> existing(existingKeys.cbegin(), existingKeys.cend());
+ QSet<QString> downloaded(downloadedKeys.cbegin(), downloadedKeys.cend());
+
+ const QSet<QString> newFiles = downloaded - existing;
+ const QSet<QString> commonFiles = downloaded & existing;
+
+ QVariantMap modifiedFileEntries;
+
+ for (const QString &file: commonFiles) {
+ QString existingCsum = existingItems[file].toMap()["checksum"].toString();
+ QString downloadedCsum = downloadedItems[file].toMap()["checksum"].toString();
+
+ if (existingCsum != downloadedCsum)
+ modifiedFileEntries[file] = downloadedItems[file];
+ }
+
+ QVariantMap newFileEntries;
+ for (const QString &path: newFiles)
+ newFileEntries[path] = downloadedItems[path];
+
+ return std::make_tuple(existingItems, newFileEntries, modifiedFileEntries);
+}
+
+void ContentLibraryWidget::fetchNewTextureIcons(const QVariantMap &existingFiles,
+ const QVariantMap &newFiles,
+ const QString &existingMetaFilePath,
+ const QDir &bundleDir)
+{
+ QStringList fileList = Utils::transform<QList>(newFiles.keys(), [](const QString &file) -> QString {
+ return file + ".png";
+ });
+
+ auto multidownloader = new MultiFileDownloader(this);
+ multidownloader->setBaseUrl(QString(m_baseUrl + "/icons"));
+ multidownloader->setFiles(fileList);
+ multidownloader->setTargetDirPath(m_downloadPath + "/TextureBundleIcons");
+
+ auto downloader = new FileDownloader(this);
+ downloader->setDownloadEnabled(true);
+ downloader->setProbeUrl(false);
+
+ downloader->setUrl(multidownloader->nextUrl());
+ downloader->setTargetFilePath(multidownloader->nextTargetPath());
+
+ QObject::connect(multidownloader, &MultiFileDownloader::nextUrlChanged, downloader, [=]() {
+ downloader->setUrl(multidownloader->nextUrl());
+ });
+
+ QObject::connect(multidownloader, &MultiFileDownloader::nextTargetPathChanged, downloader, [=]() {
+ downloader->setTargetFilePath(multidownloader->nextTargetPath());
+ });
+
+ multidownloader->setDownloader(downloader);
+
+ QVariantMap files = existingFiles;
+ files.insert(newFiles);
+
+ QObject::connect(multidownloader, &MultiFileDownloader::finishedChanged, this,
+ [multidownloader, files, existingMetaFilePath, this, bundleDir]() {
+ multidownloader->deleteLater();
+
+ QVariantMap newMap;
+ newMap["version"] = TextureBundleMetadataVersion;
+ newMap["image_items"] = files;
+
+ QJsonObject jobj = QJsonObject::fromVariantMap(newMap);
+ QJsonDocument doc(jobj);
+ QByteArray data = doc.toJson();
+
+ QFile existingFile(existingMetaFilePath);
+ if (existingFile.open(QIODeviceBase::WriteOnly | QIODeviceBase::Text)) {
+ existingFile.write(data);
+ existingFile.flush();
+ }
+
+ if (fetchTextureBundleIcons(bundleDir)) {
+ QString bundleIconPath = m_downloadPath + "/TextureBundleIcons";
+ QVariantMap metaData = readBundleMetadata();
+ m_texturesModel->loadTextureBundle(m_texturesUrl, m_textureIconsUrl, bundleIconPath,
+ metaData);
+ m_environmentsModel->loadTextureBundle(m_environmentsUrl, m_environmentIconsUrl,
+ bundleIconPath, metaData);
+ }
+
+ });
+
+ multidownloader->start();
+}
+
+QStringList ContentLibraryWidget::saveNewTextures(const QDir &bundleDir, const QStringList &newFiles)
+{
+ int newFileExpirationDays = QmlDesignerPlugin::settings()
+ .value(DesignerSettingsKey::CONTENT_LIBRARY_NEW_FLAG_EXPIRATION_DAYS)
+ .toInt();
+
+ int newFileExpirationSecs = newFileExpirationDays * 24 * 3600;
+
+ QString newFilesPath = bundleDir.filePath(".new_textures_on_server.json");
+
+ QFile jsonFile(newFilesPath);
+ if (jsonFile.exists()) {
+ jsonFile.open(QFile::ReadOnly | QFile::Text);
+
+ qint64 now = QDateTime::currentSecsSinceEpoch();
+ QByteArray existingData = jsonFile.readAll();
+ QJsonDocument doc = QJsonDocument::fromJson(existingData);
+ jsonFile.close();
+
+ QJsonObject mainObj = doc.object();
+ if (mainObj.value("version").toInt() > TextureBundleMetadataVersion) {
+ qDebug() << "Existing version of cached 'New Items' does not have a known version.";
+
+ // TODO: do simple save new file
+ return newFiles;
+ }
+
+ QJsonValue jsonValue = mainObj.value("image_items");
+ QJsonArray imageItems = jsonValue.toArray();
+
+ // remove those files that are older than N days (configurable via QSettings)
+ imageItems = Utils::filtered(imageItems, [newFileExpirationSecs, now](const QJsonValue &v) {
+ qint64 time = v["time"].toInt();
+ if (now - time >= newFileExpirationSecs)
+ return false;
+
+ return true;
+ });
+
+ QStringList pruned = Utils::transform<QStringList>(imageItems, [](const QJsonValue &value) -> QString {
+ return value.toObject()["file"].toString();
+ });
+
+ // filter out files from newFiles that already exist in the document
+
+ QStringList newFilesNow = Utils::filtered(newFiles, [&imageItems](const QString &file) {
+ bool contains = Utils::anyOf(imageItems, [file](const QJsonValue &v) {
+ if (!v.isObject())
+ return false;
+
+ QJsonObject o = v.toObject();
+ if (!o.contains("file"))
+ return false;
+
+ bool hasFile = (o["file"] == file);
+ return hasFile;
+
+ return false;
+ });
+ return !contains;
+ });
+
+ // add the filtered out files to the doc.
+ for (const QString &file: newFilesNow) {
+ QJsonObject obj({{"file", file}, {"time", now}});
+ imageItems.push_back(obj);
+ }
+
+ mainObj["image_items"] = imageItems;
+
+ // save the json file.
+ doc.setObject(mainObj);
+ QByteArray data = doc.toJson();
+
+ jsonFile.open(QFile::WriteOnly | QFile::Text);
+ jsonFile.write(data);
+ jsonFile.close();
+
+ return newFilesNow + pruned;
+ } else {
+ qint64 now = QDateTime::currentSecsSinceEpoch();
+
+ QJsonArray texturesFoundNow = Utils::transform<QJsonArray>(newFiles, [now](const QString &file) {
+ QJsonObject obj({{"file", file}, {"time", now}});
+ return QJsonValue(obj);
+ });
+
+ QVariantMap varMap;
+ varMap["version"] = TextureBundleMetadataVersion;
+ varMap["image_items"] = texturesFoundNow;
+
+ QJsonObject mainObj({{"version", TextureBundleMetadataVersion},
+ {"image_items", texturesFoundNow}});
+
+ QJsonDocument doc(mainObj);
+ QByteArray data = doc.toJson();
+
+ jsonFile.open(QFile::WriteOnly | QFile::Text);
+ jsonFile.write(data);
+ jsonFile.close();
+
+ return newFiles;
}
}
@@ -188,8 +438,7 @@ bool ContentLibraryWidget::fetchTextureBundleMetadata(const QDir &bundleDir)
QString filePath = bundleDir.filePath("texture_bundle.json");
QFileInfo fi(filePath);
- if (fi.exists() && fi.size() > 0)
- return true;
+ bool metaFileExists = fi.exists() && fi.size() > 0;
QString metaFileUrl = m_baseUrl + "/texture_bundle.zip";
FileDownloader *downloader = new FileDownloader(this);
@@ -197,11 +446,26 @@ bool ContentLibraryWidget::fetchTextureBundleMetadata(const QDir &bundleDir)
downloader->setProbeUrl(false);
downloader->setDownloadEnabled(true);
+ QObject::connect(downloader, &FileDownloader::downloadFailed, this, [=]() {
+ if (metaFileExists) {
+ if (fetchTextureBundleIcons(bundleDir)) {
+ QString bundleIconPath = m_downloadPath + "/TextureBundleIcons";
+ QVariantMap metaData = readBundleMetadata();
+ m_texturesModel->loadTextureBundle(m_texturesUrl, m_textureIconsUrl, bundleIconPath,
+ metaData);
+ m_environmentsModel->loadTextureBundle(m_environmentsUrl, m_environmentIconsUrl,
+ bundleIconPath, metaData);
+ }
+ }
+ });
+
QObject::connect(downloader, &FileDownloader::finishedChanged, this, [=]() {
FileExtractor *extractor = new FileExtractor(this);
extractor->setArchiveName(downloader->completeBaseName());
extractor->setSourceFile(downloader->outputFile());
- extractor->setTargetPath(bundleDir.absolutePath());
+ if (!metaFileExists)
+ extractor->setTargetPath(bundleDir.absolutePath());
+
extractor->setAlwaysCreateDir(false);
extractor->setClearTargetPathContents(false);
@@ -209,11 +473,35 @@ bool ContentLibraryWidget::fetchTextureBundleMetadata(const QDir &bundleDir)
downloader->deleteLater();
extractor->deleteLater();
+ if (metaFileExists) {
+ QVariantMap newFiles, existing;
+ QVariantMap modifiedFilesEntries;
+
+ std::tie(existing, newFiles, modifiedFilesEntries) =
+ compareTextureMetaFiles(filePath, extractor->targetPath() + "/texture_bundle.json");
+
+ const QStringList newFilesKeys = newFiles.keys();
+ const QStringList actualNewFiles = saveNewTextures(bundleDir, newFilesKeys);
+
+ m_texturesModel->setModifiedFileEntries(modifiedFilesEntries);
+ m_texturesModel->setNewFileEntries(actualNewFiles);
+
+ m_environmentsModel->setModifiedFileEntries(modifiedFilesEntries);
+ m_environmentsModel->setNewFileEntries(actualNewFiles);
+
+ if (newFiles.count() > 0) {
+ fetchNewTextureIcons(existing, newFiles, filePath, bundleDir);
+ return;
+ }
+ }
+
if (fetchTextureBundleIcons(bundleDir)) {
QString bundleIconPath = m_downloadPath + "/TextureBundleIcons";
QVariantMap metaData = readBundleMetadata();
- m_texturesModel->loadTextureBundle(m_texturesUrl, bundleIconPath, metaData);
- m_environmentsModel->loadTextureBundle(m_environmentsUrl, bundleIconPath, metaData);
+ m_texturesModel->loadTextureBundle(m_texturesUrl, m_textureIconsUrl, bundleIconPath,
+ metaData);
+ m_environmentsModel->loadTextureBundle(m_environmentsUrl, m_environmentIconsUrl,
+ bundleIconPath, metaData);
}
});
@@ -253,8 +541,10 @@ bool ContentLibraryWidget::fetchTextureBundleIcons(const QDir &bundleDir)
QString bundleIconPath = m_downloadPath + "/TextureBundleIcons";
QVariantMap metaData = readBundleMetadata();
- m_texturesModel->loadTextureBundle(m_texturesUrl, bundleIconPath, metaData);
- m_environmentsModel->loadTextureBundle(m_environmentsUrl, bundleIconPath, metaData);
+ m_texturesModel->loadTextureBundle(m_texturesUrl, m_textureIconsUrl, bundleIconPath,
+ metaData);
+ m_environmentsModel->loadTextureBundle(m_environmentsUrl, m_environmentIconsUrl,
+ bundleIconPath, metaData);
});
extractor->extract();
@@ -264,6 +554,48 @@ bool ContentLibraryWidget::fetchTextureBundleIcons(const QDir &bundleDir)
return false;
}
+void ContentLibraryWidget::markTextureUpdated(const QString &textureKey)
+{
+ static QRegularExpression re("([^/]+)/([^/]+)/.*");
+ QString category = re.match(textureKey).captured(1);
+ QString subcategory = re.match(textureKey).captured(2);
+
+ QString checksumOnServer;
+ if (category == "Textures")
+ checksumOnServer = m_texturesModel->removeModifiedFileEntry(textureKey);
+ else if (category == "Environments")
+ checksumOnServer = m_environmentsModel->removeModifiedFileEntry(textureKey);
+
+ QJsonObject metaDataObj;
+ QFile jsonFile(m_downloadPath + "/texture_bundle.json");
+ if (jsonFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ metaDataObj = QJsonDocument::fromJson(jsonFile.readAll()).object();
+ jsonFile.close();
+ }
+
+ QJsonObject imageItems = metaDataObj["image_items"].toObject();
+
+ QJsonObject oldImageItem = imageItems[textureKey].toObject();
+ oldImageItem["checksum"] = checksumOnServer;
+ imageItems[textureKey] = oldImageItem;
+
+ metaDataObj["image_items"] = imageItems;
+
+ QJsonDocument outDoc(metaDataObj);
+ QByteArray data = outDoc.toJson();
+
+ QFile outFile(m_downloadPath + "/texture_bundle.json");
+ if (outFile.open(QIODeviceBase::WriteOnly | QIODeviceBase::Text)) {
+ outFile.write(data);
+ outFile.flush();
+ }
+
+ if (category == "Textures")
+ m_texturesModel->markTextureHasNoUpdates(subcategory, textureKey);
+ else if (category == "Environments")
+ m_environmentsModel->markTextureHasNoUpdates(subcategory, textureKey);
+}
+
QList<QToolButton *> ContentLibraryWidget::createToolBarWidgets()
{
return {};
@@ -311,6 +643,7 @@ void ContentLibraryWidget::setHasQuick3DImport(bool b)
emit hasQuick3DImportChanged();
m_materialsModel->updateIsEmpty();
+ m_effectsModel->updateIsEmpty();
}
bool ContentLibraryWidget::hasMaterialLibrary() const
@@ -341,6 +674,7 @@ void ContentLibraryWidget::reloadQmlSource()
void ContentLibraryWidget::updateSearch()
{
m_materialsModel->setSearchText(m_filterText);
+ m_effectsModel->setSearchText(m_filterText);
m_texturesModel->setSearchText(m_filterText);
m_environmentsModel->setSearchText(m_filterText);
m_quickWidget->update();
@@ -376,6 +710,14 @@ QString ContentLibraryWidget::findTextureBundlePath()
return texBundleDir.path();
}
+void ContentLibraryWidget::startDragEffect(QmlDesigner::ContentLibraryEffect *eff,
+ const QPointF &mousePos)
+{
+ m_effectToDrag = eff;
+ m_dragStartPoint = mousePos.toPoint();
+ setIsDragging(true);
+}
+
void ContentLibraryWidget::startDragMaterial(QmlDesigner::ContentLibraryMaterial *mat,
const QPointF &mousePos)
{
@@ -436,4 +778,9 @@ QPointer<ContentLibraryTexturesModel> ContentLibraryWidget::environmentsModel()
return m_environmentsModel;
}
+QPointer<ContentLibraryEffectsModel> ContentLibraryWidget::effectsModel() const
+{
+ return m_effectsModel;
+}
+
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.h
index 6d4ba51a30..9f9fd167c3 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.h
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.h
@@ -18,10 +18,12 @@ class StudioQuickWidget;
namespace QmlDesigner {
-class ContentLibraryTexture;
+class ContentLibraryEffect;
+class ContentLibraryEffectsModel;
class ContentLibraryMaterial;
-class ContentLibraryTexturesModel;
class ContentLibraryMaterialsModel;
+class ContentLibraryTexture;
+class ContentLibraryTexturesModel;
class ContentLibraryWidget : public QFrame
{
@@ -54,15 +56,19 @@ public:
QPointer<ContentLibraryMaterialsModel> materialsModel() const;
QPointer<ContentLibraryTexturesModel> texturesModel() const;
QPointer<ContentLibraryTexturesModel> environmentsModel() const;
+ QPointer<ContentLibraryEffectsModel> effectsModel() const;
+ Q_INVOKABLE void startDragEffect(QmlDesigner::ContentLibraryEffect *eff, const QPointF &mousePos);
Q_INVOKABLE void startDragMaterial(QmlDesigner::ContentLibraryMaterial *mat, const QPointF &mousePos);
Q_INVOKABLE void startDragTexture(QmlDesigner::ContentLibraryTexture *tex, const QPointF &mousePos);
Q_INVOKABLE void addImage(QmlDesigner::ContentLibraryTexture *tex);
Q_INVOKABLE void addTexture(QmlDesigner::ContentLibraryTexture *tex);
Q_INVOKABLE void addLightProbe(QmlDesigner::ContentLibraryTexture *tex);
Q_INVOKABLE void updateSceneEnvState();
+ Q_INVOKABLE void markTextureUpdated(const QString &textureKey);
signals:
+ void bundleEffectDragStarted(QmlDesigner::ContentLibraryEffect *bundleEff);
void bundleMaterialDragStarted(QmlDesigner::ContentLibraryMaterial *bundleMat);
void bundleTextureDragStarted(QmlDesigner::ContentLibraryTexture *bundleTex);
void addTextureRequested(const QString texPath, QmlDesigner::AddTextureMode mode);
@@ -83,16 +89,23 @@ private:
QVariantMap readBundleMetadata();
bool fetchTextureBundleMetadata(const QDir &bundleDir);
bool fetchTextureBundleIcons(const QDir &bundleDir);
+ void fetchNewTextureIcons(const QVariantMap &existingFiles, const QVariantMap &newFiles,
+ const QString &existingMetaFilePath, const QDir &bundleDir);
+ std::tuple<QVariantMap, QVariantMap, QVariantMap> compareTextureMetaFiles(
+ const QString &existingMetaFile, const QString downloadedMetaFile);
+ QStringList saveNewTextures(const QDir &bundleDir, const QStringList &newFiles);
QScopedPointer<StudioQuickWidget> m_quickWidget;
QPointer<ContentLibraryMaterialsModel> m_materialsModel;
QPointer<ContentLibraryTexturesModel> m_texturesModel;
QPointer<ContentLibraryTexturesModel> m_environmentsModel;
+ QPointer<ContentLibraryEffectsModel> m_effectsModel;
QShortcut *m_qmlSourceUpdateShortcut = nullptr;
QString m_filterText;
+ ContentLibraryEffect *m_effectToDrag = nullptr;
ContentLibraryMaterial *m_materialToDrag = nullptr;
ContentLibraryTexture *m_textureToDrag = nullptr;
QPoint m_dragStartPoint;
@@ -102,6 +115,8 @@ private:
bool m_isDragging = false;
QString m_baseUrl;
QString m_texturesUrl;
+ QString m_textureIconsUrl;
+ QString m_environmentIconsUrl;
QString m_environmentsUrl;
QString m_downloadPath;
};
diff --git a/src/plugins/qmldesigner/components/curveeditor/curveeditormodel.cpp b/src/plugins/qmldesigner/components/curveeditor/curveeditormodel.cpp
index 802a75c2bf..84c8cb56bd 100644
--- a/src/plugins/qmldesigner/components/curveeditor/curveeditormodel.cpp
+++ b/src/plugins/qmldesigner/components/curveeditor/curveeditormodel.cpp
@@ -319,7 +319,7 @@ std::vector<Keyframe> resolveSmallCurves(const std::vector<Keyframe> &frames)
if (frame.hasData() && !out.empty()) {
QEasingCurve curve = frame.data().toEasingCurve();
// One-segment-curve: Since (0,0) is implicit => 3
- if (curve.toCubicSpline().count() == 3) {
+ if (curve.toCubicSpline().size() == 3) {
Keyframe &previous = out.back();
#if 0
// Do not resolve when two adjacent keyframes have the same value.
diff --git a/src/plugins/qmldesigner/components/curveeditor/curveeditorstyle.h b/src/plugins/qmldesigner/components/curveeditor/curveeditorstyle.h
index 163f998d7d..8193bdbf53 100644
--- a/src/plugins/qmldesigner/components/curveeditor/curveeditorstyle.h
+++ b/src/plugins/qmldesigner/components/curveeditor/curveeditorstyle.h
@@ -59,7 +59,7 @@ struct KeyframeItemStyleOption
double size = 10.0;
QColor color = QColor(200, 200, 0);
QColor selectionColor = QColor(200, 200, 200);
- QColor lockedColor = QColor(50, 50, 50);
+ QColor lockedColor = QColor(80, 80, 80);
QColor unifiedColor = QColor(250, 50, 250);
QColor splitColor = QColor(0, 250, 0);
};
@@ -71,7 +71,7 @@ struct CurveItemStyleOption
QColor errorColor = QColor(200, 0, 0);
QColor selectionColor = QColor(200, 200, 200);
QColor easingCurveColor = QColor(200, 0, 200);
- QColor lockedColor = QColor(50, 50, 50);
+ QColor lockedColor = QColor(120, 120, 120);
QColor hoverColor = QColor(200, 0, 200);
};
diff --git a/src/plugins/qmldesigner/components/curveeditor/curveeditorview.cpp b/src/plugins/qmldesigner/components/curveeditor/curveeditorview.cpp
index 2a401fc4fb..1d0b38b3f1 100644
--- a/src/plugins/qmldesigner/components/curveeditor/curveeditorview.cpp
+++ b/src/plugins/qmldesigner/components/curveeditor/curveeditorview.cpp
@@ -338,7 +338,7 @@ void CurveEditorView::commitKeyframes(TreeItem *item)
attachEasingCurve(group, pos.x(), segment.easingCurve());
} else if (frame.interpolation() == Keyframe::Interpolation::Easing) {
QVariant data = frame.data();
- if (data.type() == static_cast<int>(QMetaType::QEasingCurve))
+ if (data.typeId() == static_cast<int>(QMetaType::QEasingCurve))
attachEasingCurve(group, pos.x(), data.value<QEasingCurve>());
}
}
diff --git a/src/plugins/qmldesigner/components/curveeditor/curvesegment.cpp b/src/plugins/qmldesigner/components/curveeditor/curvesegment.cpp
index 2608e65144..76fa2a2ffc 100644
--- a/src/plugins/qmldesigner/components/curveeditor/curvesegment.cpp
+++ b/src/plugins/qmldesigner/components/curveeditor/curvesegment.cpp
@@ -244,7 +244,7 @@ void CurveSegment::extendWithEasingCurve(QPainterPath &path, const QEasingCurve
};
QVector<QPointF> points = curve.toCubicSpline();
- int numSegments = points.count() / 3;
+ int numSegments = points.size() / 3;
for (int i = 0; i < numSegments; i++) {
QPointF p1 = mapEasing(m_left.position(), m_right.position(), points.at(i * 3));
QPointF p2 = mapEasing(m_left.position(), m_right.position(), points.at(i * 3 + 1));
@@ -264,7 +264,7 @@ void CurveSegment::extend(QPainterPath &path) const
extendWithEasingCurve(path, easingCurve());
} else if (interpolation() == Keyframe::Interpolation::Easing) {
QVariant data = m_right.data();
- if (data.isValid() && data.type() == static_cast<int>(QMetaType::QEasingCurve)) {
+ if (data.isValid() && data.typeId() == static_cast<int>(QMetaType::QEasingCurve)) {
extendWithEasingCurve(path, data.value<QEasingCurve>());
}
}
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.cpp b/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.cpp
index 819a52d215..b754802072 100644
--- a/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.cpp
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.cpp
@@ -252,13 +252,21 @@ void GraphicsView::setPinned(TreeItem *item)
void GraphicsView::setZoomX(double zoom, const QPoint &pivot)
{
- applyZoom(zoom, m_zoomY, pivot);
+ if (pivot.isNull())
+ applyZoom(zoom, m_zoomY, viewportCenter());
+ else
+ applyZoom(zoom, m_zoomY, pivot);
+
viewport()->update();
}
void GraphicsView::setZoomY(double zoom, const QPoint &pivot)
{
- applyZoom(m_zoomX, zoom, pivot);
+ if (pivot.isNull())
+ applyZoom(zoom, m_zoomY, viewportCenter());
+ else
+ applyZoom(zoom, m_zoomY, pivot);
+
viewport()->update();
}
@@ -514,7 +522,14 @@ void GraphicsView::applyZoom(double x, double y, const QPoint &pivot)
m_transform = QTransform::fromScale(scaleX, scaleY);
m_scene->setComponentTransform(m_transform);
- QRectF sr = m_scene->rect().adjusted(
+ QRectF sr = m_scene->rect();
+ if (sr.isNull()) {
+ sr.setLeft(m_scene->animationRangeMin());
+ sr.setRight(m_scene->animationRangeMax());
+ sr = m_transform.mapRect(sr);
+ }
+
+ sr = sr.adjusted(
-m_style.valueAxisWidth - m_style.canvasMargin,
-m_style.timeAxisHeight - m_style.canvasMargin,
m_style.canvasMargin,
@@ -750,4 +765,10 @@ QRectF GraphicsView::rangeMaxHandle(const QRectF &rect)
return QRectF(QPointF(handle, bottom), size);
}
+QPoint GraphicsView::viewportCenter() const
+{
+ QPoint viewCenter = viewport()->rect().center();
+ return viewport()->mapToGlobal(viewCenter);
+}
+
} // End namespace QmlDesigner.
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.h b/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.h
index c292d0203d..120249b605 100644
--- a/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.h
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.h
@@ -136,6 +136,8 @@ private:
QRectF rangeMaxHandle(const QRectF &rect);
+ QPoint viewportCenter() const;
+
private:
bool m_dragging;
diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/treeview.cpp b/src/plugins/qmldesigner/components/curveeditor/detail/treeview.cpp
index c8b99d61c8..82d8e2dd99 100644
--- a/src/plugins/qmldesigner/components/curveeditor/detail/treeview.cpp
+++ b/src/plugins/qmldesigner/components/curveeditor/detail/treeview.cpp
@@ -37,6 +37,8 @@ TreeView::TreeView(CurveEditorModel *model, QWidget *parent)
setStyle(model->style());
+ header()->setMinimumSectionSize(20);
+
header()->setSectionResizeMode(0, QHeaderView::Stretch);
header()->setSectionResizeMode(1, QHeaderView::Fixed);
header()->setSectionResizeMode(2, QHeaderView::Fixed);
diff --git a/src/plugins/qmldesigner/components/curveeditor/keyframe.cpp b/src/plugins/qmldesigner/components/curveeditor/keyframe.cpp
index aa698c35da..8e71e593c3 100644
--- a/src/plugins/qmldesigner/components/curveeditor/keyframe.cpp
+++ b/src/plugins/qmldesigner/components/curveeditor/keyframe.cpp
@@ -149,7 +149,7 @@ void Keyframe::setRightHandle(const QPointF &pos)
void Keyframe::setData(const QVariant &data)
{
- if (data.type() == static_cast<int>(QMetaType::QEasingCurve))
+ if (data.typeId() == static_cast<int>(QMetaType::QEasingCurve))
m_interpolation = Interpolation::Easing;
m_data = data;
diff --git a/src/plugins/qmldesigner/components/edit3d/bakelights.cpp b/src/plugins/qmldesigner/components/edit3d/bakelights.cpp
index 53c7e53df9..c0ff5de2af 100644
--- a/src/plugins/qmldesigner/components/edit3d/bakelights.cpp
+++ b/src/plugins/qmldesigner/components/edit3d/bakelights.cpp
@@ -321,11 +321,13 @@ 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_dataModel->reset()) {
+ m_manualMode = true;
+ } else {
+ auto data = m_dataModel->view3dNode().auxiliaryData(bakeLightsManualProperty);
+ if (data)
+ m_manualMode = data->toBool();
+ }
if (!m_setupDialog) {
// Show non-modal progress dialog with cancel button
diff --git a/src/plugins/qmldesigner/components/edit3d/bakelightsconnectionmanager.cpp b/src/plugins/qmldesigner/components/edit3d/bakelightsconnectionmanager.cpp
index 9fb41b4686..e8faa42833 100644
--- a/src/plugins/qmldesigner/components/edit3d/bakelightsconnectionmanager.cpp
+++ b/src/plugins/qmldesigner/components/edit3d/bakelightsconnectionmanager.cpp
@@ -29,7 +29,7 @@ void BakeLightsConnectionManager::dispatchCommand(const QVariant &command,
{
static const int commandType = QMetaType::type("PuppetToCreatorCommand");
- if (command.userType() == commandType) {
+ if (command.typeId() == commandType) {
auto cmd = command.value<PuppetToCreatorCommand>();
switch (cmd.type()) {
case PuppetToCreatorCommand::BakeLightsProgress:
diff --git a/src/plugins/qmldesigner/components/edit3d/bakelightsdatamodel.cpp b/src/plugins/qmldesigner/components/edit3d/bakelightsdatamodel.cpp
index 36d192a924..e812bb6d00 100644
--- a/src/plugins/qmldesigner/components/edit3d/bakelightsdatamodel.cpp
+++ b/src/plugins/qmldesigner/components/edit3d/bakelightsdatamodel.cpp
@@ -36,7 +36,7 @@ BakeLightsDataModel::~BakeLightsDataModel()
int BakeLightsDataModel::rowCount(const QModelIndex &) const
{
- return m_dataList.count();
+ return m_dataList.size();
}
QHash<int, QByteArray> BakeLightsDataModel::roleNames() const
@@ -57,7 +57,7 @@ QHash<int, QByteArray> BakeLightsDataModel::roleNames() const
QVariant BakeLightsDataModel::data(const QModelIndex &index, int role) const
{
- QTC_ASSERT(index.isValid() && index.row() < m_dataList.count(), return {});
+ QTC_ASSERT(index.isValid() && index.row() < m_dataList.size(), return {});
QTC_ASSERT(roleNames().contains(role), return {});
QByteArray roleName = roleNames().value(role);
@@ -102,7 +102,7 @@ QVariant BakeLightsDataModel::data(const QModelIndex &index, int role) const
bool BakeLightsDataModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
- QTC_ASSERT(index.isValid() && index.row() < m_dataList.count(), return false);
+ QTC_ASSERT(index.isValid() && index.row() < m_dataList.size(), return false);
QTC_ASSERT(roleNames().contains(role), return false);
QByteArray roleName = roleNames().value(role);
@@ -130,10 +130,12 @@ bool BakeLightsDataModel::setData(const QModelIndex &index, const QVariant &valu
return changed;
}
-void BakeLightsDataModel::reset()
+// Return value of false indicates unexpected property assignments were detected, which means manual
+// mode for baking setup should be enforced.
+bool BakeLightsDataModel::reset()
{
if (!m_view || !m_view->model())
- return;
+ return true;
beginResetModel();
m_dataList.clear();
@@ -152,6 +154,8 @@ void BakeLightsDataModel::reset()
QList<BakeData> compLightList;
QList<BakeData> unexposedList;
+ bool forceManualMode = false;
+
// 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.
@@ -169,23 +173,42 @@ void BakeLightsDataModel::reset()
if (node.hasBindingProperty("bakedLightmap")) {
ModelNode blm = node.bindingProperty("bakedLightmap").resolveToModelNode();
if (blm.isValid()) {
- if (blm.hasVariantProperty("enabled"))
+ if (blm.hasVariantProperty("enabled")) {
data.enabled = blm.variantProperty("enabled").value().toBool();
- else
+ } else {
data.enabled = true;
+ if (blm.hasProperty("enabled"))
+ forceManualMode = true;
+ }
}
+ } else if (node.hasProperty("bakedLightmap")) {
+ forceManualMode = true;
}
if (node.hasVariantProperty("lightmapBaseResolution"))
data.resolution = node.variantProperty("lightmapBaseResolution").value().toInt();
+ else if (node.hasProperty("lightmapBaseResolution"))
+ forceManualMode = true;
+
if (node.hasVariantProperty("usedInBakedLighting"))
data.inUse = node.variantProperty("usedInBakedLighting").value().toBool();
+ else if (node.hasProperty("usedInBakedLighting"))
+ forceManualMode = true;
+
modelList.append(data);
} else if (node.metaInfo().isQtQuick3DLight()) {
if (node.hasVariantProperty("bakeMode")) {
- data.bakeMode = node.variantProperty("bakeMode").value()
- .value<QmlDesigner::Enumeration>().toString();
+ // Enum properties that have binding can still resolve as variant property,
+ // so check if the value is actually valid enum
+ QString bakeModeStr = node.variantProperty("bakeMode").value()
+ .value<QmlDesigner::Enumeration>().toString();
+ if (bakeModeStr.startsWith("Light.BakeMode"))
+ data.bakeMode = bakeModeStr;
+ else
+ forceManualMode = true;
} else {
data.bakeMode = "Light.BakeModeDisabled";
+ if (node.hasProperty("bakeMode"))
+ forceManualMode = true;
}
lightList.append(data);
}
@@ -211,16 +234,29 @@ void BakeLightsDataModel::reset()
if (subName == "bakedLightmap") {
ModelNode blm = prop.toBindingProperty().resolveToModelNode();
if (blm.isValid()) {
- if (blm.hasVariantProperty("enabled"))
+ if (blm.hasVariantProperty("enabled")) {
propData.enabled = blm.variantProperty("enabled").value().toBool();
- else
+ } else {
propData.enabled = true;
+ if (blm.hasProperty("enabled"))
+ forceManualMode = true;
+ }
+ } else {
+ forceManualMode = true;
}
}
- if (subName == "lightmapBaseResolution")
- propData.resolution = prop.toVariantProperty().value().toInt();
- if (subName == "usedInBakedLighting")
- propData.inUse = prop.toVariantProperty().value().toBool();
+ if (subName == "lightmapBaseResolution") {
+ if (prop.isVariantProperty())
+ propData.resolution = prop.toVariantProperty().value().toInt();
+ else
+ forceManualMode = true;
+ }
+ if (subName == "usedInBakedLighting") {
+ if (prop.isVariantProperty())
+ propData.inUse = prop.toVariantProperty().value().toBool();
+ else
+ forceManualMode = true;
+ }
}
}
compModelList.append(propData);
@@ -231,9 +267,17 @@ void BakeLightsDataModel::reset()
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 (prop.isVariantProperty()) {
+ QString bakeModeStr = prop.toVariantProperty().value()
+ .value<QmlDesigner::Enumeration>()
+ .toString();
+ if (bakeModeStr.startsWith("Light.BakeMode"))
+ propData.bakeMode = bakeModeStr;
+ else
+ forceManualMode = true;
+ } else {
+ forceManualMode = true;
+ }
}
}
}
@@ -292,6 +336,8 @@ void BakeLightsDataModel::reset()
}
endResetModel();
+
+ return !forceManualMode;
}
void BakeLightsDataModel::apply()
diff --git a/src/plugins/qmldesigner/components/edit3d/bakelightsdatamodel.h b/src/plugins/qmldesigner/components/edit3d/bakelightsdatamodel.h
index 313c09cf45..3ed7bfeed3 100644
--- a/src/plugins/qmldesigner/components/edit3d/bakelightsdatamodel.h
+++ b/src/plugins/qmldesigner/components/edit3d/bakelightsdatamodel.h
@@ -38,7 +38,7 @@ public:
QHash<int, QByteArray> roleNames() const override;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
- void reset();
+ bool reset();
void apply();
ModelNode view3dNode() const { return m_view3dNode; }
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dactions.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dactions.cpp
index 12d2dd0552..4ffdf0e801 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dactions.cpp
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dactions.cpp
@@ -98,25 +98,6 @@ bool Edit3DAction::isEnabled(const SelectionContext &selectionContext) const
return isVisible(selectionContext);
}
-Edit3DCameraAction::Edit3DCameraAction(const QByteArray &menuId,
- View3DActionType type,
- const QString &description,
- const QKeySequence &key,
- bool checkable,
- bool checked,
- const QIcon &icon,
- Edit3DView *view,
- SelectionContextOperation selectionAction)
- : Edit3DAction(menuId, type, description, key, checkable, checked, icon, view, selectionAction)
-{
-}
-
-bool Edit3DCameraAction::isEnabled(const SelectionContext &selectionContext) const
-{
- return Utils::anyOf(selectionContext.selectedModelNodes(),
- [](const ModelNode &node) { return node.metaInfo().isQtQuick3DCamera(); });
-}
-
Edit3DParticleSeekerAction::Edit3DParticleSeekerAction(const QByteArray &menuId,
View3DActionType type,
Edit3DView *view)
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dactions.h b/src/plugins/qmldesigner/components/edit3d/edit3dactions.h
index 4cf1ab837d..3a451ea40d 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dactions.h
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dactions.h
@@ -91,23 +91,6 @@ private:
View3DActionType m_actionType;
};
-class Edit3DCameraAction : public Edit3DAction
-{
-public:
- Edit3DCameraAction(const QByteArray &menuId,
- View3DActionType type,
- const QString &description,
- const QKeySequence &key,
- bool checkable,
- bool checked,
- const QIcon &icon,
- Edit3DView *view,
- SelectionContextOperation selectionAction = nullptr);
-
-protected:
- bool isEnabled(const SelectionContext &selectionContext) const override;
-};
-
class Edit3DParticleSeekerAction : public Edit3DAction
{
public:
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp
index 10d62a5dc2..a96ca59cae 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp
@@ -106,17 +106,6 @@ Edit3DWidget *Edit3DView::edit3DWidget() const
return m_edit3DWidget.data();
}
-void Edit3DView::selectedNodesChanged([[maybe_unused]] const QList<ModelNode> &selectedNodeList,
- [[maybe_unused]] const QList<ModelNode> &lastSelectedNodeList)
-{
- SelectionContext selectionContext(this);
- selectionContext.setUpdateMode(SelectionContext::UpdateMode::Fast);
- if (m_alignCamerasAction)
- m_alignCamerasAction->currentContextChanged(selectionContext);
- if (m_alignViewAction)
- m_alignViewAction->currentContextChanged(selectionContext);
-}
-
void Edit3DView::renderImage3DChanged(const QImage &img)
{
edit3DWidget()->canvas()->updateRenderImage(img);
@@ -149,6 +138,7 @@ void Edit3DView::updateActiveScene3D(const QVariantMap &sceneState)
qint32 newActiveScene = sceneState[sceneKey].value<qint32>();
edit3DWidget()->canvas()->updateActiveScene(newActiveScene);
model()->setActive3DSceneId(newActiveScene);
+ updateAlignActionStates();
}
if (sceneState.contains(selectKey))
@@ -298,6 +288,22 @@ void Edit3DView::handleEntriesChanged()
m_edit3DWidget->updateCreateSubMenu(entriesMap.values());
}
+void Edit3DView::updateAlignActionStates()
+{
+ bool enabled = false;
+
+ ModelNode activeScene = active3DSceneNode();
+ if (activeScene.isValid()) {
+ const QList<ModelNode> nodes = activeScene.allSubModelNodes();
+ enabled = ::Utils::anyOf(nodes, [](const ModelNode &node) {
+ return node.metaInfo().isQtQuick3DCamera();
+ });
+ }
+
+ m_alignCamerasAction->action()->setEnabled(enabled);
+ m_alignViewAction->action()->setEnabled(enabled);
+}
+
void Edit3DView::modelAboutToBeDetached(Model *model)
{
m_isBakingLightsSupported = false;
@@ -364,6 +370,8 @@ void Edit3DView::nodeAtPosReady(const ModelNode &modelNode, const QVector3D &pos
}
} else if (m_nodeAtPosReqType == NodeAtPosReqType::BundleMaterialDrop) {
emitCustomNotification("drop_bundle_material", {modelNode}); // To ContentLibraryView
+ } else if (m_nodeAtPosReqType == NodeAtPosReqType::BundleEffectDrop) {
+ emitCustomNotification("drop_bundle_effect", {modelNode}, {pos3d}); // To ContentLibraryView
} else if (m_nodeAtPosReqType == NodeAtPosReqType::TextureDrop) {
emitCustomNotification("apply_texture_to_model3D", {modelNode, m_droppedModelNode});
} else if (m_nodeAtPosReqType == NodeAtPosReqType::AssetDrop) {
@@ -377,6 +385,21 @@ void Edit3DView::nodeAtPosReady(const ModelNode &modelNode, const QVector3D &pos
m_nodeAtPosReqType = NodeAtPosReqType::None;
}
+void Edit3DView::nodeReparented(const ModelNode &,
+ const NodeAbstractProperty &,
+ const NodeAbstractProperty &,
+ PropertyChangeFlags)
+{
+ updateAlignActionStates();
+}
+
+void Edit3DView::nodeRemoved(const ModelNode &,
+ const NodeAbstractProperty &,
+ PropertyChangeFlags)
+{
+ updateAlignActionStates();
+}
+
void Edit3DView::sendInputEvent(QInputEvent *e) const
{
if (nodeInstanceView())
@@ -581,25 +604,27 @@ void Edit3DView::createEdit3DActions()
toolbarIcon(Theme::fitToView_medium),
this);
- m_alignCamerasAction = new Edit3DCameraAction(
+ m_alignCamerasAction = new Edit3DAction(
QmlDesigner::Constants::EDIT3D_ALIGN_CAMERAS,
View3DActionType::AlignCamerasToView,
- QCoreApplication::translate("AlignCamerasToViewAction", "Align Selected Cameras to View"),
+ QCoreApplication::translate("AlignCamerasToViewAction", "Align Cameras to View"),
QKeySequence(),
false,
false,
toolbarIcon(Theme::alignToCam_medium),
this);
+ m_alignCamerasAction->action()->setEnabled(false);
- m_alignViewAction = new Edit3DCameraAction(
+ m_alignViewAction = new Edit3DAction(
QmlDesigner::Constants::EDIT3D_ALIGN_VIEW,
View3DActionType::AlignViewToCamera,
- QCoreApplication::translate("AlignCamerasToViewAction", "Align View to Selected Camera"),
+ QCoreApplication::translate("AlignCamerasToViewAction", "Align View to Camera"),
QKeySequence(),
false,
false,
toolbarIcon(Theme::alignToView_medium),
this);
+ m_alignViewAction->action()->setEnabled(false);
m_cameraModeAction = new Edit3DAction(
QmlDesigner::Constants::EDIT3D_EDIT_CAMERA,
@@ -922,7 +947,7 @@ void Edit3DView::addQuick3DImport()
{
DesignDocument *document = QmlDesignerPlugin::instance()->currentDesignDocument();
if (document && !document->inFileComponentModelActive() && model()
- && Utils::addImportWithCheck(
+ && ModelUtils::addImportWithCheck(
"QtQuick3D",
[](const Import &import) { return !import.hasVersion() || import.majorVersion() >= 6; },
model())) {
@@ -953,6 +978,12 @@ void Edit3DView::dropBundleMaterial(const QPointF &pos)
emitView3DAction(View3DActionType::GetNodeAtPos, pos);
}
+void Edit3DView::dropBundleEffect(const QPointF &pos)
+{
+ m_nodeAtPosReqType = NodeAtPosReqType::BundleEffectDrop;
+ emitView3DAction(View3DActionType::GetNodeAtPos, pos);
+}
+
void Edit3DView::dropTexture(const ModelNode &textureNode, const QPointF &pos)
{
m_nodeAtPosReqType = NodeAtPosReqType::TextureDrop;
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.h b/src/plugins/qmldesigner/components/edit3d/edit3dview.h
index cd3e686d3b..6e6b82948e 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dview.h
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.h
@@ -26,7 +26,6 @@ class BakeLights;
class Edit3DWidget;
class Edit3DAction;
class Edit3DBakeLightsAction;
-class Edit3DCameraAction;
class QMLDESIGNERCOMPONENTS_EXPORT Edit3DView : public AbstractView
{
@@ -39,14 +38,19 @@ public:
Edit3DWidget *edit3DWidget() const;
- void selectedNodesChanged(const QList<ModelNode> &selectedNodeList, const QList<ModelNode> &lastSelectedNodeList) override;
void renderImage3DChanged(const QImage &img) override;
void updateActiveScene3D(const QVariantMap &sceneState) override;
void modelAttached(Model *model) override;
void modelAboutToBeDetached(Model *model) 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 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;
+ void nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent,
+ const NodeAbstractProperty &oldPropertyParent,
+ PropertyChangeFlags propertyChange) override;
+ void nodeRemoved(const ModelNode &removedNode, const NodeAbstractProperty &parentProperty,
+ PropertyChangeFlags propertyChange) override;
void sendInputEvent(QInputEvent *e) const;
void edit3DViewResized(const QSize &size) const;
@@ -65,6 +69,7 @@ public:
void startContextMenu(const QPoint &pos);
void dropMaterial(const ModelNode &matNode, const QPointF &pos);
void dropBundleMaterial(const QPointF &pos);
+ void dropBundleEffect(const QPointF &pos);
void dropTexture(const ModelNode &textureNode, const QPointF &pos);
void dropComponent(const ItemLibraryEntry &entry, const QPointF &pos);
void dropAsset(const QString &file, const QPointF &pos);
@@ -76,6 +81,7 @@ private slots:
private:
enum class NodeAtPosReqType {
+ BundleEffectDrop,
BundleMaterialDrop,
ComponentDrop,
MaterialDrop,
@@ -91,6 +97,7 @@ private:
void checkImports();
void handleEntriesChanged();
void showMaterialPropertiesView();
+ void updateAlignActionStates();
Edit3DAction *createSelectBackgroundColorAction(QAction *syncBackgroundColorAction);
Edit3DAction *createGridColorSelectionAction();
@@ -110,8 +117,8 @@ private:
Edit3DAction *m_rotateToolAction = nullptr;
Edit3DAction *m_scaleToolAction = nullptr;
Edit3DAction *m_fitAction = nullptr;
- Edit3DCameraAction *m_alignCamerasAction = nullptr;
- Edit3DCameraAction *m_alignViewAction = nullptr;
+ Edit3DAction *m_alignCamerasAction = nullptr;
+ Edit3DAction *m_alignViewAction = nullptr;
Edit3DAction *m_cameraModeAction = nullptr;
Edit3DAction *m_orientationModeAction = nullptr;
Edit3DAction *m_editLightAction = nullptr;
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp
index a217e396d9..163cfc951e 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp
@@ -21,6 +21,7 @@
#include <auxiliarydataproperties.h>
#include <designeractionmanager.h>
+#include <designermcumanager.h>
#include <import.h>
#include <nodeinstanceview.h>
#include <seekerslider.h>
@@ -167,6 +168,11 @@ Edit3DWidget::Edit3DWidget(Edit3DView *view)
createContextMenu();
+ m_mcuLabel = new QLabel(this);
+ m_mcuLabel->setText(tr("MCU project does not support Qt Quick 3D."));
+ m_mcuLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
+ fillLayout->addWidget(m_mcuLabel.data());
+
// Onboarding label contains instructions for new users how to get 3D content into the project
m_onboardingLabel = new QLabel(this);
QString labelText =
@@ -413,7 +419,24 @@ void Edit3DWidget::showCanvas(bool show)
m_canvas->updateRenderImage(emptyImage);
}
m_canvas->setVisible(show);
- m_onboardingLabel->setVisible(!show);
+
+ if (show) {
+ m_onboardingLabel->setVisible(false);
+ m_mcuLabel->setVisible(false);
+ } else {
+ bool quick3dAllowed = true;
+ const DesignerMcuManager &mcuManager = DesignerMcuManager::instance();
+ if (mcuManager.isMCUProject()) {
+ const QStringList mcuAllowedList = mcuManager.allowedImports();
+ if (!mcuAllowedList.contains("QtQuick3d"))
+ quick3dAllowed = false;
+ }
+
+ m_onboardingLabel->setVisible(quick3dAllowed);
+ m_mcuLabel->setVisible(!quick3dAllowed);
+ }
+
+
}
QMenu *Edit3DWidget::visibilityTogglesMenu() const
@@ -451,9 +474,8 @@ void Edit3DWidget::showContextMenu(const QPoint &pos, const ModelNode &modelNode
m_contextMenuTarget = modelNode;
m_contextMenuPos3d = pos3d;
- const bool isValid = modelNode.isValid();
const bool isModel = modelNode.metaInfo().isQtQuick3DModel();
- const bool isCamera = isValid && modelNode.metaInfo().isQtQuick3DCamera();
+ const bool allowAlign = view()->edit3DAction(View3DActionType::AlignCamerasToView)->action()->isEnabled();
const bool isSingleComponent = view()->hasSingleSelectedModelNode() && modelNode.isComponent();
const bool anyNodeSelected = view()->hasSelectedModelNodes();
const bool selectionExcludingRoot = anyNodeSelected && !view()->rootModelNode().isSelected();
@@ -468,8 +490,8 @@ void Edit3DWidget::showContextMenu(const QPoint &pos, const ModelNode &modelNode
m_pasteAction->setEnabled(isPasteAvailable());
m_deleteAction->setEnabled(selectionExcludingRoot);
m_fitSelectedAction->setEnabled(anyNodeSelected);
- m_alignCameraAction->setEnabled(isCamera);
- m_alignViewAction->setEnabled(isCamera);
+ m_alignCameraAction->setEnabled(allowAlign);
+ m_alignViewAction->setEnabled(allowAlign);
m_selectParentAction->setEnabled(selectionExcludingRoot);
m_toggleGroupAction->setEnabled(true);
m_bakeLightsAction->setVisible(view()->bakeLightsAction()->action()->isVisible());
@@ -517,6 +539,7 @@ void Edit3DWidget::dragEnterEvent(QDragEnterEvent *dragEnterEvent)
} else if (actionManager.externalDragHasSupportedAssets(dragEnterEvent->mimeData())
|| dragEnterEvent->mimeData()->hasFormat(Constants::MIME_TYPE_MATERIAL)
|| dragEnterEvent->mimeData()->hasFormat(Constants::MIME_TYPE_BUNDLE_MATERIAL)
+ || dragEnterEvent->mimeData()->hasFormat(Constants::MIME_TYPE_BUNDLE_EFFECT)
|| dragEnterEvent->mimeData()->hasFormat(Constants::MIME_TYPE_TEXTURE)) {
dragEnterEvent->acceptProposedAction();
} else if (dragEnterEvent->mimeData()->hasFormat(Constants::MIME_TYPE_ITEM_LIBRARY_INFO)) {
@@ -560,6 +583,13 @@ void Edit3DWidget::dropEvent(QDropEvent *dropEvent)
return;
}
+ // handle dropping bundle effects
+ if (dropEvent->mimeData()->hasFormat(Constants::MIME_TYPE_BUNDLE_EFFECT)) {
+ m_view->dropBundleEffect(pos);
+ m_view->model()->endDrag();
+ return;
+ }
+
// handle dropping from component view
if (dropEvent->mimeData()->hasFormat(Constants::MIME_TYPE_ITEM_LIBRARY_INFO)) {
if (!m_draggedEntry.name().isEmpty())
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h
index eecd52345f..f764f068bf 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h
@@ -70,6 +70,7 @@ private:
QPointer<Edit3DView> m_view;
QPointer<Edit3DCanvas> m_canvas;
QPointer<QLabel> m_onboardingLabel;
+ QPointer<QLabel> m_mcuLabel;
QPointer<ToolBox> m_toolBox;
Core::IContext *m_context = nullptr;
QPointer<QMenu> m_visibilityTogglesMenu;
diff --git a/src/plugins/qmldesigner/components/formeditor/abstractformeditortool.cpp b/src/plugins/qmldesigner/components/formeditor/abstractformeditortool.cpp
index c6cbb8252c..774b4c0d91 100644
--- a/src/plugins/qmldesigner/components/formeditor/abstractformeditortool.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/abstractformeditortool.cpp
@@ -260,7 +260,7 @@ void AbstractFormEditorTool::mouseReleaseEvent(const QList<QGraphicsItem*> & ite
QmlItemNode currentSelectedNode;
- if (view()->selectedModelNodes().count() == 1) {
+ if (view()->selectedModelNodes().size() == 1) {
currentSelectedNode = view()->selectedModelNodes().constFirst();
if (!containsItemNode(itemList, currentSelectedNode)) {
diff --git a/src/plugins/qmldesigner/components/formeditor/anchorindicator.cpp b/src/plugins/qmldesigner/components/formeditor/anchorindicator.cpp
index 7d75c71c22..8a8a3e524f 100644
--- a/src/plugins/qmldesigner/components/formeditor/anchorindicator.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/anchorindicator.cpp
@@ -64,7 +64,7 @@ void AnchorIndicator::setItems(const QList<FormEditorItem *> &itemList)
{
clear();
- if (itemList.count() == 1) {
+ if (itemList.size() == 1) {
m_formEditorItem = itemList.constFirst();
QmlItemNode sourceQmlItemNode = m_formEditorItem->qmlItemNode();
if (!sourceQmlItemNode.modelNode().isRootNode()) {
diff --git a/src/plugins/qmldesigner/components/formeditor/backgroundaction.cpp b/src/plugins/qmldesigner/components/formeditor/backgroundaction.cpp
index a9d72be8dd..37dfafad9a 100644
--- a/src/plugins/qmldesigner/components/formeditor/backgroundaction.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/backgroundaction.cpp
@@ -45,7 +45,7 @@ QWidget *BackgroundAction::createWidget(QWidget *parent)
auto comboBox = new QComboBox(parent);
comboBox->setFixedWidth(42);
- for (int i = 0; i < colors().count(); ++i) {
+ for (int i = 0; i < colors().size(); ++i) {
comboBox->addItem(tr(""));
comboBox->setItemIcon(i, iconForColor((colors().at(i))));
}
@@ -62,7 +62,7 @@ QWidget *BackgroundAction::createWidget(QWidget *parent)
void BackgroundAction::emitBackgroundChanged(int index)
{
- if (index < colors().count())
+ if (index < colors().size())
emit backgroundChanged(colors().at(index));
}
diff --git a/src/plugins/qmldesigner/components/formeditor/bindingindicator.cpp b/src/plugins/qmldesigner/components/formeditor/bindingindicator.cpp
index e5a990d1ef..5795841693 100644
--- a/src/plugins/qmldesigner/components/formeditor/bindingindicator.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/bindingindicator.cpp
@@ -91,7 +91,7 @@ void BindingIndicator::setItems(const QList<FormEditorItem *> &itemList)
{
clear();
- if (itemList.count() == 1) {
+ if (itemList.size() == 1) {
m_formEditorItem = itemList.constFirst();
const QmlItemNode qmlItemNode = m_formEditorItem->qmlItemNode();
diff --git a/src/plugins/qmldesigner/components/formeditor/movetool.cpp b/src/plugins/qmldesigner/components/formeditor/movetool.cpp
index 449cdd745c..76b8f9a5f6 100644
--- a/src/plugins/qmldesigner/components/formeditor/movetool.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/movetool.cpp
@@ -94,9 +94,9 @@ void MoveTool::mouseMoveEvent(const QList<QGraphicsItem*> &itemList,
const FormEditorItem *movingItem = m_movingItems.constFirst();
- if (m_movingItems.count() > 1
- || (movingItem->qmlItemNode().canBereparentedTo(containerItem->qmlItemNode())))
- m_moveManipulator.reparentTo(containerItem, MoveManipulator::EnforceReparent);
+ if (m_movingItems.size() > 1
+ || (movingItem->qmlItemNode().canBereparentedTo(containerItem->qmlItemNode())))
+ m_moveManipulator.reparentTo(containerItem, MoveManipulator::EnforceReparent);
}
}
diff --git a/src/plugins/qmldesigner/components/formeditor/seekerslider.cpp b/src/plugins/qmldesigner/components/formeditor/seekerslider.cpp
index 804f061657..a6bfd25873 100644
--- a/src/plugins/qmldesigner/components/formeditor/seekerslider.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/seekerslider.cpp
@@ -97,9 +97,11 @@ QWidget *SeekerSliderAction::createWidget(QWidget *parent)
QObject::connect(m_defaultSlider, &SeekerSlider::valueChanged, slider, &SeekerSlider::setValue);
QObject::connect(slider, &SeekerSlider::valueChanged, m_defaultSlider, &SeekerSlider::setValue);
QObject::connect(m_defaultSlider, &QSlider::rangeChanged, slider, &QSlider::setRange);
+ QObject::connect(this, &QWidgetAction::enabledChanged, slider, &QSlider::setEnabled);
slider->setValue(m_defaultSlider->value());
slider->setMaxValue(m_defaultSlider->maxValue());
+ slider->setEnabled(isEnabled());
return slider;
}
diff --git a/src/plugins/qmldesigner/components/formeditor/snapper.cpp b/src/plugins/qmldesigner/components/formeditor/snapper.cpp
index da50f92a81..828a713211 100644
--- a/src/plugins/qmldesigner/components/formeditor/snapper.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/snapper.cpp
@@ -426,7 +426,7 @@ double Snapper::snappingDistance() const
static QLineF mergedHorizontalLine(const QList<QLineF> &lineList)
{
- if (lineList.count() == 1)
+ if (lineList.size() == 1)
return lineList.constFirst();
double minimumX = std::numeric_limits<double>::max();
@@ -444,7 +444,7 @@ static QLineF mergedHorizontalLine(const QList<QLineF> &lineList)
static QLineF mergedVerticalLine(const QList<QLineF> &lineList)
{
- if (lineList.count() == 1)
+ if (lineList.size() == 1)
return lineList.constFirst();
double minimumY = std::numeric_limits<double>::max();
diff --git a/src/plugins/qmldesigner/components/formeditor/toolbox.cpp b/src/plugins/qmldesigner/components/formeditor/toolbox.cpp
index 47a9503b2d..53da8773eb 100644
--- a/src/plugins/qmldesigner/components/formeditor/toolbox.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/toolbox.cpp
@@ -34,11 +34,13 @@ ToolBox::ToolBox(QWidget *parentWidget)
Utils::StyleHelper::setPanelWidget(m_leftToolBar, false);
Utils::StyleHelper::setPanelWidgetSingleRow(m_leftToolBar, false);
m_leftToolBar->setFixedHeight(Theme::toolbarSize());
+ m_leftToolBar->setStyleSheet("QToolBarExtension {margin-top: 5px;}");
Utils::StyleHelper::setPanelWidget(m_rightToolBar, false);
Utils::StyleHelper::setPanelWidgetSingleRow(m_rightToolBar, false);
m_rightToolBar->setFixedHeight(Theme::toolbarSize());
m_rightToolBar->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding);
+ m_rightToolBar->setStyleSheet("QToolBarExtension {margin-top: 5px;}");
auto stretchToolbar = new QToolBar(this);
Utils::StyleHelper::setPanelWidget(stretchToolbar, false);
diff --git a/src/plugins/qmldesigner/components/integration/designdocument.cpp b/src/plugins/qmldesigner/components/integration/designdocument.cpp
index fecaaefadf..089efb87cd 100644
--- a/src/plugins/qmldesigner/components/integration/designdocument.cpp
+++ b/src/plugins/qmldesigner/components/integration/designdocument.cpp
@@ -9,6 +9,7 @@
#include <auxiliarydataproperties.h>
#include <metainfo.h>
+#include <model/modelresourcemanagement.h>
#include <nodeinstanceview.h>
#include <nodelistproperty.h>
#include <rewritingexception.h>
@@ -62,7 +63,8 @@ namespace QmlDesigner {
*/
DesignDocument::DesignDocument(ProjectStorage<Sqlite::Database> &projectStorage,
ExternalDependenciesInterface &externalDependencies)
- : m_documentModel(Model::create("QtQuick.Item", 1, 0))
+ : m_documentModel(
+ Model::create("QtQuick.Item", 1, 0, nullptr, std::make_unique<ModelResourceManagement>()))
, m_subComponentManager(new SubComponentManager(m_documentModel.get(), externalDependencies))
, m_rewriterView(new RewriterView(externalDependencies, RewriterView::Amend))
, m_documentLoaded(false)
@@ -149,7 +151,11 @@ const AbstractView *DesignDocument::view() const
ModelPointer DesignDocument::createInFileComponentModel()
{
- auto model = Model::create("QtQuick.Item", 1, 0);
+ auto model = Model::create("QtQuick.Item",
+ 1,
+ 0,
+ nullptr,
+ std::make_unique<ModelResourceManagement>());
model->setFileUrl(m_documentModel->fileUrl());
model->setMetaInfo(m_documentModel->metaInfo());
@@ -205,8 +211,7 @@ void DesignDocument::moveNodesToPosition(const QList<ModelNode> &nodes, const st
targetNode = view.firstSelectedModelNode();
// in case we copy and paste a selection we paste in the parent item
- if ((view.selectedModelNodes().count() == movingNodes.count())
- && targetNode.hasParentProperty()) {
+ if ((view.selectedModelNodes().size() == movingNodes.size()) && targetNode.hasParentProperty()) {
targetNode = targetNode.parentProperty().parentModelNode();
} else if (view.selectedModelNodes().isEmpty()) {
// if selection is empty and copied nodes are all 3D nodes, paste them under the active scene
@@ -366,7 +371,7 @@ void DesignDocument::loadDocument(QPlainTextEdit *edit)
connect(m_documentTextModifier.data(), &TextModifier::textChanged, this, &DesignDocument::updateQrcFiles);
- m_documentModel->setTextModifier(m_documentTextModifier.data());
+ m_rewriterView->setTextModifier(m_documentTextModifier.data());
m_inFileComponentTextModifier.reset();
@@ -386,6 +391,8 @@ void DesignDocument::changeToDocumentModel()
if (edit)
edit->document()->clearUndoRedoStacks();
+ m_rewriterView->setTextModifier(m_documentTextModifier.data());
+
m_inFileComponentModel.reset();
m_inFileComponentTextModifier.reset();
@@ -426,7 +433,8 @@ void DesignDocument::changeToInFileComponentModel(ComponentTextModifier *textMod
edit->document()->clearUndoRedoStacks();
m_inFileComponentModel = createInFileComponentModel();
- m_inFileComponentModel->setTextModifier(m_inFileComponentTextModifier.data());
+
+ m_rewriterView->setTextModifier(m_inFileComponentTextModifier.data());
viewManager().attachRewriterView();
viewManager().attachViewsExceptRewriterAndComponetView();
diff --git a/src/plugins/qmldesigner/components/integration/designdocumentview.cpp b/src/plugins/qmldesigner/components/integration/designdocumentview.cpp
index 4a1c92ad0a..9d0deef713 100644
--- a/src/plugins/qmldesigner/components/integration/designdocumentview.cpp
+++ b/src/plugins/qmldesigner/components/integration/designdocumentview.cpp
@@ -227,7 +227,7 @@ void DesignDocumentView::copyModelNodes(const QList<ModelNode> &nodesToCopy,
DesignDocumentView view{externalDependencies};
copyModel->attachView(&view);
- if (selectedNodes.count() == 1) {
+ if (selectedNodes.size() == 1) {
const ModelNode &selectedNode = selectedNodes.constFirst();
if (!selectedNode.isValid())
@@ -253,7 +253,6 @@ void DesignDocumentView::copyModelNodes(const QList<ModelNode> &nodesToCopy,
view.toClipboard();
}
-
}
}// namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/itemlibrary/assetimportupdatetreeitem.cpp b/src/plugins/qmldesigner/components/itemlibrary/assetimportupdatetreeitem.cpp
index 6fa6ec4c34..a5d84605dd 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/assetimportupdatetreeitem.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/assetimportupdatetreeitem.cpp
@@ -32,7 +32,7 @@ void AssetImportUpdateTreeItem::clear()
int AssetImportUpdateTreeItem::childCount() const
{
- return m_children.count();
+ return m_children.size();
}
int AssetImportUpdateTreeItem::rowOfItem() const
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryaddimportmodel.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryaddimportmodel.cpp
index 41a9c6b5f4..66afa19f8b 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryaddimportmodel.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryaddimportmodel.cpp
@@ -28,12 +28,12 @@ ItemLibraryAddImportModel::~ItemLibraryAddImportModel()
int ItemLibraryAddImportModel::rowCount(const QModelIndex & /*parent*/) const
{
- return m_importList.count();
+ return m_importList.size();
}
QVariant ItemLibraryAddImportModel::data(const QModelIndex &index, int role) const
{
- if (!index.isValid() || index.row() >= m_importList.count())
+ if (!index.isValid() || index.row() >= m_importList.size())
return {};
Import import = m_importList[index.row()];
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp
index 91f403f218..f8a9fd9771 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp
@@ -109,7 +109,7 @@ ItemLibraryAssetImportDialog::ItemLibraryAssetImportDialog(
connect(ui->buttonBox->button(QDialogButtonBox::Ok), &QPushButton::clicked,
this, &ItemLibraryAssetImportDialog::onImport);
- ui->buttonBox->button(QDialogButtonBox::Close)->setDefault(true);
+ ui->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
ui->advancedSettingsButton->setStyleSheet(
"QPushButton#advancedSettingsButton {background-color: transparent}");
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp
index d141b88dc8..99f07cb8a8 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp
@@ -216,7 +216,7 @@ void ItemLibraryAssetImporter::parseFiles(const QStringList &filePaths,
addInfo(progressTitle);
notifyProgress(0, progressTitle);
uint count = 0;
- double quota = 100.0 / filePaths.count();
+ double quota = 100.0 / filePaths.size();
std::function<void(double)> progress = [this, quota, &count, &progressTitle](double value) {
notifyProgress(qRound(quota * (count + value)), progressTitle);
};
@@ -709,7 +709,7 @@ void ItemLibraryAssetImporter::finalizeQuick3DImport()
try {
RewriterTransaction transaction = model->rewriterView()->beginRewriterTransaction(
QByteArrayLiteral("ItemLibraryAssetImporter::finalizeQuick3DImport"));
- bool success = Utils::addImportsWithCheck(m_requiredImports, model);
+ bool success = ModelUtils::addImportsWithCheck(m_requiredImports, model);
if (!success)
addError(tr("Failed to insert import statement into qml document."));
transaction.commit();
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycategoriesmodel.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycategoriesmodel.cpp
index 187bd38e2f..824027e555 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycategoriesmodel.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarycategoriesmodel.cpp
@@ -27,12 +27,12 @@ ItemLibraryCategoriesModel::~ItemLibraryCategoriesModel()
int ItemLibraryCategoriesModel::rowCount(const QModelIndex &) const
{
- return m_categoryList.count();
+ return m_categoryList.size();
}
QVariant ItemLibraryCategoriesModel::data(const QModelIndex &index, int role) const
{
- if (!index.isValid() || index.row() >= m_categoryList.count()) {
+ if (!index.isValid() || index.row() >= m_categoryList.size()) {
qWarning() << Q_FUNC_INFO << "invalid index requested";
return {};
}
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryitemsmodel.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryitemsmodel.cpp
index 8ee40b6d24..65330af023 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryitemsmodel.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryitemsmodel.cpp
@@ -21,7 +21,7 @@ ItemLibraryItemsModel::~ItemLibraryItemsModel()
int ItemLibraryItemsModel::rowCount(const QModelIndex &) const
{
- return m_itemList.count();
+ return m_itemList.size();
}
QVariant ItemLibraryItemsModel::data(const QModelIndex &index, int role) const
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp
index 21f2e6aa55..3f611a0dbb 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp
@@ -228,12 +228,12 @@ ItemLibraryModel::~ItemLibraryModel()
int ItemLibraryModel::rowCount(const QModelIndex & /*parent*/) const
{
- return m_importList.count();
+ return m_importList.size();
}
QVariant ItemLibraryModel::data(const QModelIndex &index, int role) const
{
- if (!index.isValid() || index.row() >= m_importList.count())
+ if (!index.isValid() || index.row() >= m_importList.size())
return {};
if (m_roleNames.contains(role)) {
@@ -317,15 +317,17 @@ void ItemLibraryModel::update(ItemLibraryInfo *itemLibraryInfo, Model *model)
ProjectExplorer::Project *project = ProjectExplorer::ProjectManager::projectForFile(qmlFileName);
QString projectName = project ? project->displayName() : "";
- QString materialBundlePrefix = QLatin1String(Constants::COMPONENT_BUNDLES_FOLDER).mid(1);
- materialBundlePrefix.append(".MaterialBundle");
+ QStringList excludedImports {
+ QLatin1String(Constants::COMPONENT_BUNDLES_FOLDER).mid(1) + ".MaterialBundle",
+ QLatin1String(Constants::COMPONENT_BUNDLES_FOLDER).mid(1) + ".EffectBundle"
+ };
// create import sections
const Imports usedImports = model->usedImports();
QHash<QString, ItemLibraryImport *> importHash;
for (const Import &import : model->imports()) {
if (import.url() != projectName) {
- if (import.url() == materialBundlePrefix)
+ if (excludedImports.contains(import.url()))
continue;
bool addNew = true;
bool isQuick3DAsset = import.url().startsWith("Quick3DAssets.");
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp
index 445372e24b..1cbde45ba0 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp
@@ -82,7 +82,7 @@ bool ItemLibraryWidget::eventFilter(QObject *obj, QEvent *event)
// 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()
- && !Utils::addImportWithCheck(entry.requiredImport(), m_model)) {
+ && !ModelUtils::addImportWithCheck(entry.requiredImport(), m_model)) {
qWarning() << __FUNCTION__ << "Required import adding failed:"
<< entry.requiredImport();
}
@@ -217,7 +217,7 @@ QString ItemLibraryWidget::getDependencyImport(const Import &import)
const QStringList splitImport = import.url().split('.');
- if (splitImport.count() > 1) {
+ if (splitImport.size() > 1) {
if (prefixDependencies.contains(splitImport.first()))
return splitImport.first();
}
diff --git a/src/plugins/qmldesigner/components/listmodeleditor/listmodeleditormodel.cpp b/src/plugins/qmldesigner/components/listmodeleditor/listmodeleditormodel.cpp
index a1b25c37c8..b6009edc77 100644
--- a/src/plugins/qmldesigner/components/listmodeleditor/listmodeleditormodel.cpp
+++ b/src/plugins/qmldesigner/components/listmodeleditor/listmodeleditormodel.cpp
@@ -29,10 +29,10 @@ public:
QVariant maybeConvertToNumber(const QVariant &value)
{
- if (value.type() == QVariant::Bool)
+ if (value.typeId() == QVariant::Bool)
return value;
- if (value.type() == QVariant::String) {
+ if (value.typeId() == QVariant::String) {
const QString text = value.toString();
if (text == "true")
return QVariant(true);
diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.cpp
index d4aedb1cec..81ec4cbb3a 100644
--- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.cpp
+++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.cpp
@@ -4,6 +4,7 @@
#include "materialbrowsermodel.h"
#include "designmodewidget.h"
+#include "materialbrowserview.h"
#include "qmldesignerplugin.h"
#include "qmlobjectnode.h"
#include "variantproperty.h"
@@ -13,8 +14,9 @@
namespace QmlDesigner {
-MaterialBrowserModel::MaterialBrowserModel(QObject *parent)
+MaterialBrowserModel::MaterialBrowserModel(MaterialBrowserView *view, QObject *parent)
: QAbstractListModel(parent)
+ , m_view(view)
{
}
@@ -24,12 +26,12 @@ MaterialBrowserModel::~MaterialBrowserModel()
int MaterialBrowserModel::rowCount(const QModelIndex &) const
{
- return m_materialList.count();
+ return m_materialList.size();
}
QVariant MaterialBrowserModel::data(const QModelIndex &index, int role) const
{
- QTC_ASSERT(index.isValid() && index.row() < m_materialList.count(), return {});
+ QTC_ASSERT(index.isValid() && index.row() < m_materialList.size(), return {});
QTC_ASSERT(roleNames().contains(role), return {});
QByteArray roleName = roleNames().value(role);
@@ -223,7 +225,7 @@ void MaterialBrowserModel::refreshSearch()
// if selected material goes invisible, select nearest material
if (!isVisible(m_selectedIndex)) {
int inc = 1;
- int incCap = m_materialList.count();
+ int incCap = m_materialList.size();
while (!isEmpty && inc < incCap) {
if (isVisible(m_selectedIndex - inc)) {
selectMaterial(m_selectedIndex - inc);
@@ -459,10 +461,13 @@ void MaterialBrowserModel::pasteMaterialProperties(int idx)
void MaterialBrowserModel::deleteMaterial(int idx)
{
- if (isValidIndex(idx)) {
+ if (m_view && isValidIndex(idx)) {
ModelNode node = m_materialList[idx];
- if (node.isValid())
- QmlObjectNode(node).destroy();
+ if (node.isValid()) {
+ m_view->executeInTransaction(__FUNCTION__, [&] {
+ node.destroy();
+ });
+ }
}
}
diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.h b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.h
index 23e6a68973..24c3439438 100644
--- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.h
+++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsermodel.h
@@ -12,6 +12,8 @@
namespace QmlDesigner {
+class MaterialBrowserView;
+
class MaterialBrowserModel : public QAbstractListModel
{
Q_OBJECT
@@ -28,7 +30,7 @@ class MaterialBrowserModel : public QAbstractListModel
Q_PROPERTY(QStringList customMaterialSections MEMBER m_customMaterialSections NOTIFY materialSectionsChanged)
public:
- MaterialBrowserModel(QObject *parent = nullptr);
+ MaterialBrowserModel(MaterialBrowserView *view, QObject *parent = nullptr);
~MaterialBrowserModel() override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
@@ -125,6 +127,8 @@ private:
bool m_hasMaterialLibrary = false;
bool m_allPropsCopied = true;
QString m_copiedMaterialType;
+
+ QPointer<MaterialBrowserView> m_view;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.cpp
index 4ed241abf9..ec95f3e5d3 100644
--- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.cpp
+++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.cpp
@@ -5,6 +5,7 @@
#include "designmodewidget.h"
#include "imageutils.h"
+#include "materialbrowserview.h"
#include "qmldesignerplugin.h"
#include "qmlobjectnode.h"
#include "variantproperty.h"
@@ -13,8 +14,9 @@
namespace QmlDesigner {
-MaterialBrowserTexturesModel::MaterialBrowserTexturesModel(QObject *parent)
+MaterialBrowserTexturesModel::MaterialBrowserTexturesModel(MaterialBrowserView *view, QObject *parent)
: QAbstractListModel(parent)
+ , m_view(view)
{
}
@@ -24,12 +26,12 @@ MaterialBrowserTexturesModel::~MaterialBrowserTexturesModel()
int MaterialBrowserTexturesModel::rowCount(const QModelIndex &) const
{
- return m_textureList.count();
+ return m_textureList.size();
}
QVariant MaterialBrowserTexturesModel::data(const QModelIndex &index, int role) const
{
- QTC_ASSERT(index.isValid() && index.row() < m_textureList.count(), return {});
+ QTC_ASSERT(index.isValid() && index.row() < m_textureList.size(), return {});
QTC_ASSERT(roleNames().contains(role), return {});
if (role == RoleTexSource) {
@@ -124,7 +126,7 @@ void MaterialBrowserTexturesModel::refreshSearch()
// if selected texture goes invisible, select nearest one
if (!isVisible(m_selectedIndex)) {
int inc = 1;
- int incCap = m_textureList.count();
+ int incCap = m_textureList.size();
while (!isEmpty && inc < incCap) {
if (isVisible(m_selectedIndex - inc)) {
selectTexture(m_selectedIndex - inc);
@@ -292,10 +294,13 @@ void MaterialBrowserTexturesModel::duplicateTexture(int idx)
void MaterialBrowserTexturesModel::deleteTexture(int idx)
{
- if (isValidIndex(idx)) {
+ if (m_view && isValidIndex(idx)) {
ModelNode node = m_textureList[idx];
- if (node.isValid())
- QmlObjectNode(node).destroy();
+ if (node.isValid()) {
+ m_view->executeInTransaction(__FUNCTION__, [&] {
+ node.destroy();
+ });
+ }
}
}
diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.h b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.h
index 9cb7c5ac18..8836d3b5db 100644
--- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.h
+++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.h
@@ -10,6 +10,8 @@
namespace QmlDesigner {
+class MaterialBrowserView;
+
class MaterialBrowserTexturesModel : public QAbstractListModel
{
Q_OBJECT
@@ -20,7 +22,7 @@ class MaterialBrowserTexturesModel : public QAbstractListModel
Q_PROPERTY(bool hasSceneEnv READ hasSceneEnv NOTIFY hasSceneEnvChanged)
public:
- MaterialBrowserTexturesModel(QObject *parent = nullptr);
+ MaterialBrowserTexturesModel(MaterialBrowserView *view, QObject *parent = nullptr);
~MaterialBrowserTexturesModel() override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
@@ -89,6 +91,8 @@ private:
bool m_hasSingleModelSelection = false;
bool m_hasSceneEnv = false;
+ QPointer<MaterialBrowserView> m_view;
+
enum {
RoleTexHasDynamicProps = Qt::UserRole + 1,
RoleTexInternalId,
diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp
index e2bb82216b..98a1a5a5de 100644
--- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp
+++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp
@@ -141,8 +141,8 @@ bool MaterialBrowserWidget::eventFilter(QObject *obj, QEvent *event)
MaterialBrowserWidget::MaterialBrowserWidget(AsynchronousImageCache &imageCache,
MaterialBrowserView *view)
: m_materialBrowserView(view)
- , m_materialBrowserModel(new MaterialBrowserModel(this))
- , m_materialBrowserTexturesModel(new MaterialBrowserTexturesModel(this))
+ , m_materialBrowserModel(new MaterialBrowserModel(view, this))
+ , m_materialBrowserTexturesModel(new MaterialBrowserTexturesModel(view, this))
, m_quickWidget(new StudioQuickWidget(this))
, m_previewImageProvider(new PreviewImageProvider())
{
@@ -204,7 +204,7 @@ MaterialBrowserWidget::MaterialBrowserWidget(AsynchronousImageCache &imageCache,
reloadQmlSource();
- setFocusProxy(m_quickWidget.data());
+ setFocusProxy(m_quickWidget->quickWidget());
}
void MaterialBrowserWidget::updateMaterialPreview(const ModelNode &node, const QPixmap &pixmap)
diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.cpp b/src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.cpp
index a99d4133af..4a4057d8ab 100644
--- a/src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.cpp
+++ b/src/plugins/qmldesigner/components/materialeditor/materialeditorcontextobject.cpp
@@ -510,18 +510,9 @@ QStringList MaterialEditorContextObject::allStatesForId(const QString &id)
return {};
}
-bool MaterialEditorContextObject::isBlocked(const QString &propName) const
+bool MaterialEditorContextObject::isBlocked(const QString &) const
{
- if (!m_selectedMaterial.isValid())
- return false;
-
- if (!m_model || !m_model->rewriterView())
- return false;
-
- if (QmlObjectNode(m_selectedMaterial).isBlocked(propName.toUtf8()))
- return true;
-
- return false;
+ return false;
}
void MaterialEditorContextObject::goIntoComponent()
diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditorqmlbackend.cpp b/src/plugins/qmldesigner/components/materialeditor/materialeditorqmlbackend.cpp
index edae2377bf..fe84c0c184 100644
--- a/src/plugins/qmldesigner/components/materialeditor/materialeditorqmlbackend.cpp
+++ b/src/plugins/qmldesigner/components/materialeditor/materialeditorqmlbackend.cpp
@@ -31,7 +31,7 @@
static QObject *variantToQObject(const QVariant &value)
{
- if (value.userType() == QMetaType::QObjectStar || value.userType() > QMetaType::User)
+ if (value.typeId() == QMetaType::QObjectStar || value.typeId() > QMetaType::User)
return *(QObject **)value.constData();
return nullptr;
@@ -143,7 +143,7 @@ void MaterialEditorQmlBackend::createPropertyEditorValue(const QmlObjectNode &qm
void MaterialEditorQmlBackend::setValue(const QmlObjectNode &, const PropertyName &name, const QVariant &value)
{
// Vector*D values need to be split into their subcomponents
- if (value.type() == QVariant::Vector2D) {
+ if (value.typeId() == QVariant::Vector2D) {
const char *suffix[2] = {"_x", "_y"};
auto vecValue = value.value<QVector2D>();
for (int i = 0; i < 2; ++i) {
@@ -154,7 +154,7 @@ void MaterialEditorQmlBackend::setValue(const QmlObjectNode &, const PropertyNam
if (propertyValue)
propertyValue->setValue(QVariant(vecValue[i]));
}
- } else if (value.type() == QVariant::Vector3D) {
+ } else if (value.typeId() == QVariant::Vector3D) {
const char *suffix[3] = {"_x", "_y", "_z"};
auto vecValue = value.value<QVector3D>();
for (int i = 0; i < 3; ++i) {
@@ -165,7 +165,7 @@ void MaterialEditorQmlBackend::setValue(const QmlObjectNode &, const PropertyNam
if (propertyValue)
propertyValue->setValue(QVariant(vecValue[i]));
}
- } else if (value.type() == QVariant::Vector4D) {
+ } else if (value.typeId() == QVariant::Vector4D) {
const char *suffix[4] = {"_x", "_y", "_z", "_w"};
auto vecValue = value.value<QVector4D>();
for (int i = 0; i < 4; ++i) {
diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp b/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp
index 55c587f3cb..933686febd 100644
--- a/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp
+++ b/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp
@@ -442,8 +442,11 @@ void MaterialEditorView::handleToolBarAction(int action)
}
case MaterialEditorContextObject::DeleteCurrentMaterial: {
- if (m_selectedMaterial.isValid())
- m_selectedMaterial.destroy();
+ if (m_selectedMaterial.isValid()) {
+ executeInTransaction(__FUNCTION__, [&] {
+ m_selectedMaterial.destroy();
+ });
+ }
break;
}
diff --git a/src/plugins/qmldesigner/components/navigator/choosefrompropertylistdialog.cpp b/src/plugins/qmldesigner/components/navigator/choosefrompropertylistdialog.cpp
index 91c300e87a..304ff91fcd 100644
--- a/src/plugins/qmldesigner/components/navigator/choosefrompropertylistdialog.cpp
+++ b/src/plugins/qmldesigner/components/navigator/choosefrompropertylistdialog.cpp
@@ -115,10 +115,10 @@ ChooseFromPropertyListDialog::ChooseFromPropertyListDialog(const QStringList &pr
: QDialog(parent)
, m_ui(new Ui::ChooseFromPropertyListDialog)
{
- if (propNames.count() == 1) {
- m_selectedProperty = propNames.first().toLatin1();
- m_isSoloProperty = true;
- return;
+ if (propNames.size() == 1) {
+ m_selectedProperty = propNames.first().toLatin1();
+ m_isSoloProperty = true;
+ return;
}
m_ui->setupUi(this);
setWindowTitle(tr("Select Property"));
diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
index 16dd224286..8b7f1f8a61 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
+++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
@@ -69,13 +69,12 @@ static QList<ModelNode> modelNodesFromMimeData(const QMimeData *mineData, Abstra
bool fitsToTargetProperty(const NodeAbstractProperty &targetProperty,
const QList<ModelNode> &modelNodeList)
{
- bool const canBeContainer =
- NodeHints::fromModelNode(targetProperty.parentModelNode()).canBeContainerFor(modelNodeList.first());
- return !(targetProperty.isNodeProperty() &&
- modelNodeList.count() > 1) && canBeContainer;
+ const bool canBeContainer = NodeHints::fromModelNode(targetProperty.parentModelNode())
+ .canBeContainerFor(modelNodeList.first());
+ return !(targetProperty.isNodeProperty() && modelNodeList.size() > 1) && canBeContainer;
}
-static inline QString msgUnknownItem(const QString &t)
+inline static QString msgUnknownItem(const QString &t)
{
return NavigatorTreeModel::tr("Unknown component: %1").arg(t);
}
@@ -289,7 +288,7 @@ Qt::ItemFlags NavigatorTreeModel::flags(const QModelIndex &index) const
return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
}
-void static appendForcedNodes(const NodeListProperty &property, QList<ModelNode> &list)
+static void appendForcedNodes(const NodeListProperty &property, QList<ModelNode> &list)
{
const QSet<ModelNode> set = QSet<ModelNode>(list.constBegin(), list.constEnd());
for (const ModelNode &node : property.parentModelNode().directSubModelNodes()) {
@@ -411,7 +410,8 @@ int NavigatorTreeModel::rowCount(const QModelIndex &parent) const
if (modelNode.defaultNodeListProperty().isValid()) {
rows = filteredList(modelNode.defaultNodeListProperty(),
m_showOnlyVisibleItems,
- m_reverseItemOrder).count();
+ m_reverseItemOrder)
+ .size();
}
return rows;
@@ -451,12 +451,13 @@ void NavigatorTreeModel::setView(NavigatorView *view)
QStringList NavigatorTreeModel::mimeTypes() const
{
- const static QStringList types({Constants::MIME_TYPE_MODELNODE_LIST,
+ static const QStringList types({Constants::MIME_TYPE_MODELNODE_LIST,
Constants::MIME_TYPE_ITEM_LIBRARY_INFO,
Constants::MIME_TYPE_TEXTURE,
Constants::MIME_TYPE_MATERIAL,
Constants::MIME_TYPE_BUNDLE_TEXTURE,
Constants::MIME_TYPE_BUNDLE_MATERIAL,
+ Constants::MIME_TYPE_BUNDLE_EFFECT,
Constants::MIME_TYPE_ASSETS});
return types;
@@ -565,6 +566,10 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
ModelNode targetNode(modelNodeForIndex(dropModelIndex));
if (targetNode.isValid())
m_view->emitCustomNotification("drop_bundle_material", {targetNode}); // To ContentLibraryView
+ } else if (mimeData->hasFormat(Constants::MIME_TYPE_BUNDLE_EFFECT)) {
+ ModelNode targetNode(modelNodeForIndex(dropModelIndex));
+ if (targetNode.isValid())
+ m_view->emitCustomNotification("drop_bundle_effect", {targetNode}); // To ContentLibraryView
} else if (mimeData->hasFormat(Constants::MIME_TYPE_ASSETS)) {
const QStringList assetsPaths = QString::fromUtf8(mimeData->data(Constants::MIME_TYPE_ASSETS)).split(',');
NodeAbstractProperty targetProperty;
@@ -777,21 +782,6 @@ void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, in
if (newQmlObjectNode.isValid())
m_view->setSelectedModelNode(newQmlObjectNode.modelNode());
}
-
- const QStringList copyFiles = itemLibraryEntry.extraFilePaths();
- if (!copyFiles.isEmpty()) {
- // Files are copied into the same directory as the current qml document
- for (const auto &copyFile : copyFiles) {
- QFileInfo fi(copyFile);
- const QString targetFile = DocumentManager::currentFilePath().toFileInfo().dir()
- .absoluteFilePath(fi.fileName());
- // We don't want to overwrite existing default files
- if (!QFileInfo::exists(targetFile)) {
- if (!QFile::copy(copyFile, targetFile))
- qWarning() << QStringLiteral("Copying extra file '%1' failed.").arg(copyFile);
- }
- }
- }
}
}
@@ -900,7 +890,7 @@ ModelNode NavigatorTreeModel::handleItemLibraryFontDrop(const QString &fontFamil
void NavigatorTreeModel::addImport(const QString &importName)
{
- if (!Utils::addImportWithCheck(importName, m_view->model()))
+ if (!ModelUtils::addImportWithCheck(importName, m_view->model()))
qWarning() << __FUNCTION__ << "Adding import failed:" << importName;
}
@@ -943,7 +933,7 @@ ModelNode NavigatorTreeModel::handleItemLibraryShaderDrop(const QString &shaderP
// set shader properties
PropertyName prop = "shader";
- QString type = "QByteArray";
+ QString type = "QUrl";
QVariant val = relPath;
itemLibraryEntry.addProperty(prop, type, val);
prop = "stage";
diff --git a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
index f1a00a36c7..ceccf25554 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
+++ b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp
@@ -42,7 +42,7 @@
#include <QPixmap>
#include <QTimer>
-static inline void setScenePos(const QmlDesigner::ModelNode &modelNode,const QPointF &pos)
+inline static void setScenePos(const QmlDesigner::ModelNode &modelNode, const QPointF &pos)
{
if (modelNode.hasParentProperty() && QmlDesigner::QmlItemNode::isValidQmlItemNode(modelNode.parentProperty().parentModelNode())) {
QmlDesigner::QmlItemNode parentNode = modelNode.parentProperty().parentQmlObjectNode().toQmlItemNode();
@@ -58,7 +58,7 @@ static inline void setScenePos(const QmlDesigner::ModelNode &modelNode,const QPo
}
}
-static inline void moveNodesUp(const QList<QmlDesigner::ModelNode> &nodes)
+inline static void moveNodesUp(const QList<QmlDesigner::ModelNode> &nodes)
{
for (const auto &node : nodes) {
if (!node.isRootNode() && node.parentProperty().isNodeListProperty()) {
@@ -73,7 +73,7 @@ static inline void moveNodesUp(const QList<QmlDesigner::ModelNode> &nodes)
}
}
-static inline void moveNodesDown(const QList<QmlDesigner::ModelNode> &nodes)
+inline static void moveNodesDown(const QList<QmlDesigner::ModelNode> &nodes)
{
for (const auto &node : nodes) {
if (!node.isRootNode() && node.parentProperty().isNodeListProperty()) {
@@ -280,7 +280,7 @@ void NavigatorView::dragStarted(QMimeData *mimeData)
m_widget->update();
} else if (mimeData->hasFormat(Constants::MIME_TYPE_ASSETS)) {
const QStringList assetsPaths = QString::fromUtf8(mimeData->data(Constants::MIME_TYPE_ASSETS)).split(',');
- if (assetsPaths.count() > 0) {
+ if (assetsPaths.size() > 0) {
auto assetTypeAndData = AssetsLibraryWidget::getAssetTypeAndData(assetsPaths[0]);
QString assetType = assetTypeAndData.first;
if (assetType == Constants::MIME_TYPE_ASSET_EFFECT) {
@@ -517,7 +517,7 @@ void NavigatorView::propagateInstanceErrorToExplorer(const ModelNode &modelNode)
void NavigatorView::leftButtonClicked()
{
- if (selectedModelNodes().count() > 1)
+ if (selectedModelNodes().size() > 1)
return; //Semantics are unclear for multi selection.
bool blocked = blockSelectionChangedSignal(true);
@@ -541,14 +541,15 @@ void NavigatorView::leftButtonClicked()
void NavigatorView::rightButtonClicked()
{
- if (selectedModelNodes().count() > 1)
+ if (selectedModelNodes().size() > 1)
return; //Semantics are unclear for multi selection.
bool blocked = blockSelectionChangedSignal(true);
bool reverse = QmlDesignerPlugin::settings().value(DesignerSettingsKey::NAVIGATOR_REVERSE_ITEM_ORDER).toBool();
for (const ModelNode &node : selectedModelNodes()) {
- if (!node.isRootNode() && node.parentProperty().isNodeListProperty() && node.parentProperty().count() > 1) {
+ if (!node.isRootNode() && node.parentProperty().isNodeListProperty()
+ && node.parentProperty().count() > 1) {
int index = node.parentProperty().indexOf(node);
bool indexOk = false;
diff --git a/src/plugins/qmldesigner/components/pathtool/pathitem.cpp b/src/plugins/qmldesigner/components/pathtool/pathitem.cpp
index 10c93ad559..801be712ad 100644
--- a/src/plugins/qmldesigner/components/pathtool/pathitem.cpp
+++ b/src/plugins/qmldesigner/components/pathtool/pathitem.cpp
@@ -587,7 +587,7 @@ QAction *PathItem::createClosedPathAction(QMenu *contextMenu) const
closedPathAction->setText(tr("Closed Path"));
contextMenu->addAction(closedPathAction);
- if (m_cubicSegments.count() == 1)
+ if (m_cubicSegments.size() == 1)
closedPathAction->setDisabled(true);
return closedPathAction;
@@ -617,7 +617,7 @@ void PathItem::createCubicSegmentContextMenu(CubicSegment &cubicSegment, const Q
straightLinePointAction->setText(tr("Make Curve Segment Straight"));
contextMenu.addAction(straightLinePointAction);
- if (m_cubicSegments.count() == 1 && isClosedPath())
+ if (m_cubicSegments.size() == 1 && isClosedPath())
straightLinePointAction->setDisabled(true);
QAction *closedPathAction = createClosedPathAction(&contextMenu);
@@ -649,7 +649,7 @@ void PathItem::createEditPointContextMenu(const ControlPoint &controlPoint, cons
QAction *closedPathAction = createClosedPathAction(&contextMenu);
- if (m_cubicSegments.count() <= 1 || (m_cubicSegments.count() == 2 && isClosedPath()))
+ if (m_cubicSegments.size() <= 1 || (m_cubicSegments.size() == 2 && isClosedPath()))
removeEditPointAction->setDisabled(true);
QAction *activatedAction = contextMenu.exec(menuPosition);
@@ -663,7 +663,7 @@ void PathItem::createEditPointContextMenu(const ControlPoint &controlPoint, cons
const QList<ControlPoint> PathItem::controlPoints() const
{
QList<ControlPoint> controlPointList;
- controlPointList.reserve((m_cubicSegments.count() * 4));
+ controlPointList.reserve((m_cubicSegments.size() * 4));
if (!m_cubicSegments.isEmpty())
controlPointList.append(m_cubicSegments.constFirst().firstControlPoint());
@@ -914,9 +914,9 @@ void PathItem::removeEditPoint(const ControlPoint &controlPoint)
{
QList<CubicSegment> cubicSegments = cubicSegmentsContainingControlPoint(controlPoint, m_cubicSegments);
- if (cubicSegments.count() == 1) {
+ if (cubicSegments.size() == 1) {
m_cubicSegments.removeOne(cubicSegments.constFirst());
- } else if (cubicSegments.count() == 2){
+ } else if (cubicSegments.size() == 2) {
CubicSegment mergedCubicSegment = CubicSegment::create();
const CubicSegment &firstCubicSegment = cubicSegments.at(0);
const CubicSegment &secondCubicSegment = cubicSegments.at(1);
diff --git a/src/plugins/qmldesigner/components/pathtool/pathselectionmanipulator.cpp b/src/plugins/qmldesigner/components/pathtool/pathselectionmanipulator.cpp
index 6d62057848..c1c2fd725a 100644
--- a/src/plugins/qmldesigner/components/pathtool/pathselectionmanipulator.cpp
+++ b/src/plugins/qmldesigner/components/pathtool/pathselectionmanipulator.cpp
@@ -54,12 +54,12 @@ static ControlPoint getControlPoint(const QList<ControlPoint> &selectedPoints, c
int controlPointIndex = selectedPoints.indexOf(controlPoint);
if (controlPointIndex >= 0) {
int offsetIndex = controlPointIndex + indexOffset;
- if (offsetIndex >= 0 && offsetIndex < selectedPoints.count())
+ if (offsetIndex >= 0 && offsetIndex < selectedPoints.size())
return selectedPoints.at(offsetIndex);
else if (isClosedPath) {
if (offsetIndex == -1)
return selectedPoints.constLast();
- else if (offsetIndex < selectedPoints.count())
+ else if (offsetIndex < selectedPoints.size())
return selectedPoints.at(1);
}
}
diff --git a/src/plugins/qmldesigner/components/propertyeditor/aligndistribute.cpp b/src/plugins/qmldesigner/components/propertyeditor/aligndistribute.cpp
index 5d8400b47e..f14e423c9f 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/aligndistribute.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/aligndistribute.cpp
@@ -30,7 +30,7 @@ bool AlignDistribute::multiSelection() const
if (!m_qmlObjectNode.isValid())
return false;
- return m_qmlObjectNode.view()->selectedModelNodes().count() > 1;
+ return m_qmlObjectNode.view()->selectedModelNodes().size() > 1;
}
bool AlignDistribute::selectionHasAnchors() const
@@ -210,7 +210,7 @@ bool compareByDepth(const ModelNode &node1, const ModelNode &node2)
return false;
}
-static inline QRectF getBoundingRect(const QList<ModelNode> &modelNodeList)
+inline static QRectF getBoundingRect(const QList<ModelNode> &modelNodeList)
{
QRectF boundingRect;
for (const ModelNode &modelNode : modelNodeList) {
@@ -222,7 +222,7 @@ static inline QRectF getBoundingRect(const QList<ModelNode> &modelNodeList)
return boundingRect;
}
-static inline QSizeF getSummedSize(const QList<ModelNode> &modelNodeList)
+inline static QSizeF getSummedSize(const QList<ModelNode> &modelNodeList)
{
QSizeF summedSize = QSizeF(0, 0);
for (const ModelNode &modelNode : modelNodeList) {
@@ -234,7 +234,7 @@ static inline QSizeF getSummedSize(const QList<ModelNode> &modelNodeList)
return summedSize;
}
-static inline qreal getInstanceSceneX(const QmlItemNode &qmlItemNode)
+inline static qreal getInstanceSceneX(const QmlItemNode &qmlItemNode)
{
const qreal x = qmlItemNode.modelValue("x").toReal();
if (qmlItemNode.hasInstanceParentItem())
@@ -242,7 +242,7 @@ static inline qreal getInstanceSceneX(const QmlItemNode &qmlItemNode)
return x;
}
-static inline qreal getInstanceSceneY(const QmlItemNode &qmlItemNode)
+inline static qreal getInstanceSceneY(const QmlItemNode &qmlItemNode)
{
const qreal y = qmlItemNode.modelValue("y").toReal();
if (qmlItemNode.hasInstanceParentItem())
diff --git a/src/plugins/qmldesigner/components/propertyeditor/dynamicpropertiesproxymodel.cpp b/src/plugins/qmldesigner/components/propertyeditor/dynamicpropertiesproxymodel.cpp
index 977488a107..046f95ed73 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/dynamicpropertiesproxymodel.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/dynamicpropertiesproxymodel.cpp
@@ -152,7 +152,7 @@ void DynamicPropertiesProxyModel::createProperty(const QString &name, const QStr
TypeName typeName = type.toUtf8();
const auto selectedNodes = dynamicPropertiesModel()->selectedNodes();
- if (selectedNodes.count() == 1) {
+ if (selectedNodes.size() == 1) {
const ModelNode modelNode = selectedNodes.constFirst();
if (modelNode.isValid()) {
if (modelNode.hasProperty(name.toUtf8())) {
diff --git a/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp b/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp
index 67ee0ec15c..570927a863 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/gradientmodel.cpp
@@ -100,11 +100,11 @@ int GradientModel::addStop(qreal position, const QColor &color)
const QList<QmlDesigner::ModelNode> stopNodes = gradientNode.nodeListProperty("stops").toModelNodeList();
- for (int i = 0; i < stopNodes.count(); i++) {
+ for (int i = 0; i < stopNodes.size(); i++) {
if (QmlDesigner::QmlObjectNode(stopNodes.at(i)).modelValue("position").toReal() < position)
properPos = i + 1;
}
- gradientNode.nodeListProperty("stops").slide(stopNodes.count() - 1, properPos);
+ gradientNode.nodeListProperty("stops").slide(stopNodes.size() - 1, properPos);
setupModel();
resetPuppet();
diff --git a/src/plugins/qmldesigner/components/propertyeditor/gradientpresetlistmodel.cpp b/src/plugins/qmldesigner/components/propertyeditor/gradientpresetlistmodel.cpp
index 5b25f56f51..b4b4177332 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/gradientpresetlistmodel.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/gradientpresetlistmodel.cpp
@@ -28,12 +28,12 @@ GradientPresetListModel::~GradientPresetListModel()
int GradientPresetListModel::rowCount(const QModelIndex & /*parent*/) const
{
- return m_items.count();
+ return m_items.size();
}
QVariant GradientPresetListModel::data(const QModelIndex &index, int role) const
{
- if (index.isValid() && (index.row() >= 0) && (index.row() < m_items.count())) {
+ if (index.isValid() && (index.row() >= 0) && (index.row() < m_items.size())) {
if (m_roleNames.contains(role)) {
QVariant value = m_items.at(index.row())
.getProperty(static_cast<GradientPresetItem::Property>(role));
diff --git a/src/plugins/qmldesigner/components/propertyeditor/itemfiltermodel.cpp b/src/plugins/qmldesigner/components/propertyeditor/itemfiltermodel.cpp
index c5d9a23d7e..aa1d41888b 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/itemfiltermodel.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/itemfiltermodel.cpp
@@ -61,6 +61,19 @@ void ItemFilterModel::setSelectedItems(const QStringList &selectedItems)
emit selectedItemsChanged();
}
+void ItemFilterModel::setValidationRoles(const QStringList &validationRoles)
+{
+ auto tmp = validationRoles;
+ tmp.removeDuplicates();
+
+ if (m_validationRoles == tmp)
+ return;
+
+ m_validationRoles = tmp;
+ setupValidationItems();
+ emit validationRolesChanged();
+}
+
QString ItemFilterModel::typeFilter() const
{
return m_typeFilter;
@@ -76,6 +89,29 @@ QStringList ItemFilterModel::selectedItems() const
return m_selectedItems;
}
+QStringList ItemFilterModel::itemModel() const
+{
+ AbstractView *view = m_modelNode.view();
+ if (!view || !view->model())
+ return {};
+
+ QStringList retval;
+ for (const auto &internalId : std::as_const(m_modelInternalIds))
+ retval << view->modelNodeForInternalId(internalId).id();
+
+ return retval;
+}
+
+QStringList ItemFilterModel::validationRoles() const
+{
+ return m_validationRoles;
+}
+
+QStringList ItemFilterModel::validationItems() const
+{
+ return m_validationItems;
+}
+
void ItemFilterModel::registerDeclarativeType()
{
qmlRegisterType<ItemFilterModel>("HelperWidgets", 2, 0, "ItemFilterModel");
@@ -154,17 +190,33 @@ void ItemFilterModel::setupModel()
endResetModel();
emit itemModelChanged();
+
+ setupValidationItems();
}
-QStringList ItemFilterModel::itemModel() const
+void ItemFilterModel::setupValidationItems()
{
- AbstractView *view = m_modelNode.view();
- if (!view || !view->model())
- return {};
+ QStringList validationItems;
- QStringList retval;
- for (const auto &internalId : std::as_const(m_modelInternalIds))
- retval << view->modelNodeForInternalId(internalId).id();
+ for (const QString &role : m_validationRoles) {
+ int r = roleNames().key(role.toUtf8(), -1);
- return retval;
+ if (r == -1)
+ continue;
+
+ for (int i = 0; i < rowCount(); ++i) {
+ QVariant item = data(index(i), r);
+ if (item.canConvert<QString>())
+ validationItems.append(item.toString());
+ }
+ }
+
+ validationItems.removeDuplicates();
+
+ if (m_validationItems == validationItems)
+ return;
+
+ m_validationItems = validationItems;
+
+ emit validationItemsChanged();
}
diff --git a/src/plugins/qmldesigner/components/propertyeditor/itemfiltermodel.h b/src/plugins/qmldesigner/components/propertyeditor/itemfiltermodel.h
index cb7ae13177..eaf23820d4 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/itemfiltermodel.h
+++ b/src/plugins/qmldesigner/components/propertyeditor/itemfiltermodel.h
@@ -25,6 +25,10 @@ class ItemFilterModel : public QAbstractListModel
Q_PROPERTY(QStringList selectedItems READ selectedItems WRITE setSelectedItems NOTIFY
selectedItemsChanged)
+ Q_PROPERTY(QStringList validationRoles READ validationRoles WRITE setValidationRoles NOTIFY
+ validationRolesChanged)
+ Q_PROPERTY(QStringList validationItems READ validationItems NOTIFY validationItemsChanged)
+
public:
enum { IdRole = Qt::DisplayRole, NameRole = Qt::UserRole, IdAndNameRole, EnabledRole };
@@ -34,17 +38,18 @@ public:
void setTypeFilter(const QString &typeFilter);
void setSelectionOnly(bool value);
void setSelectedItems(const QStringList &selectedItems);
+ void setValidationRoles(const QStringList &validationRoles);
QString typeFilter() const;
bool selectionOnly() const;
QStringList selectedItems() const;
- void setupModel();
QStringList itemModel() const;
+ QStringList validationRoles() const;
+ QStringList validationItems() const;
static void registerDeclarativeType();
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;
signals:
@@ -53,8 +58,12 @@ signals:
void itemModelChanged();
void selectionOnlyChanged();
void selectedItemsChanged();
+ void validationRolesChanged();
+ void validationItemsChanged();
private:
+ void setupModel();
+ void setupValidationItems();
QVariant modelNodeBackend() const;
QmlDesigner::ModelNode modelNodeForRow(const int &row) const;
@@ -64,6 +73,9 @@ private:
QmlDesigner::ModelNode m_modelNode;
bool m_selectionOnly;
QStringList m_selectedItems;
+
+ QStringList m_validationRoles;
+ QStringList m_validationItems;
};
QML_DECLARE_TYPE(ItemFilterModel)
diff --git a/src/plugins/qmldesigner/components/propertyeditor/listvalidator.cpp b/src/plugins/qmldesigner/components/propertyeditor/listvalidator.cpp
new file mode 100644
index 0000000000..c1eaa48c3f
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/listvalidator.cpp
@@ -0,0 +1,58 @@
+// 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 "listvalidator.h"
+
+ListValidator::ListValidator(QObject *parent)
+ : QValidator{parent}
+{}
+
+QValidator::State ListValidator::validate(QString &input, int &) const
+{
+ if (input.isEmpty())
+ return QValidator::Intermediate;
+
+ State state = QValidator::Invalid;
+
+ for (const QString &item : m_filterList) {
+ if (item.compare(input, Qt::CaseSensitive) == 0)
+ return QValidator::Acceptable;
+
+ if (item.compare(input, Qt::CaseInsensitive) == 0)
+ return QValidator::Intermediate;
+
+ if (item.contains(input, Qt::CaseInsensitive))
+ state = QValidator::Intermediate;
+ }
+
+ return state;
+}
+
+void ListValidator::fixup(QString &input) const
+{
+ for (const QString &item : m_filterList) {
+ if (item.compare(input, Qt::CaseInsensitive) == 0) {
+ input = item;
+ return;
+ }
+ }
+}
+
+void ListValidator::setFilterList(const QStringList &filterList)
+{
+ if (m_filterList == filterList)
+ return;
+
+ m_filterList = filterList;
+ emit filterListChanged();
+}
+
+QStringList ListValidator::filterList() const
+{
+ return m_filterList;
+}
+
+void ListValidator::registerDeclarativeType()
+{
+ qmlRegisterType<ListValidator>("HelperWidgets", 2, 0, "ListValidator");
+}
diff --git a/src/plugins/qmldesigner/components/propertyeditor/listvalidator.h b/src/plugins/qmldesigner/components/propertyeditor/listvalidator.h
new file mode 100644
index 0000000000..46e8e4649f
--- /dev/null
+++ b/src/plugins/qmldesigner/components/propertyeditor/listvalidator.h
@@ -0,0 +1,33 @@
+// 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 <QQmlEngine>
+#include <QValidator>
+
+class ListValidator : public QValidator
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QStringList filterList READ filterList WRITE setFilterList NOTIFY filterListChanged)
+
+public:
+ explicit ListValidator(QObject *parent = nullptr);
+
+ QValidator::State validate(QString &data, int &pos) const override;
+ void fixup(QString &input) const override;
+
+ void setFilterList(const QStringList &filterList);
+ QStringList filterList() const;
+
+ static void registerDeclarativeType();
+
+signals:
+ void filterListChanged();
+
+private:
+ QStringList m_filterList;
+};
+
+QML_DECLARE_TYPE(ListValidator)
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.cpp
index a8aebbfb07..8c9b19d62e 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorcontextobject.cpp
@@ -7,6 +7,8 @@
#include <abstractview.h>
#include <nodemetainfo.h>
#include <rewritingexception.h>
+#include <qmldesignerconstants.h>
+#include <qml3dnode.h>
#include <qmldesignerplugin.h>
#include <qmlmodelnodeproxy.h>
#include <qmlobjectnode.h>
@@ -408,7 +410,13 @@ QQmlComponent *PropertyEditorContextObject::specificQmlComponent()
m_qmlComponent = new QQmlComponent(m_qmlContext->engine(), this);
- m_qmlComponent->setData(m_specificQmlData.toUtf8(), QUrl::fromLocalFile(QStringLiteral("specfics.qml")));
+ m_qmlComponent->setData(m_specificQmlData.toUtf8(), QUrl::fromLocalFile("specifics.qml"));
+
+ const bool showError = qEnvironmentVariableIsSet(Constants::ENVIRONMENT_SHOW_QML_ERRORS);
+ if (showError && !m_specificQmlData.isEmpty() && !m_qmlComponent->errors().isEmpty()) {
+ const QString errMsg = m_qmlComponent->errors().constFirst().toString();
+ Core::AsynchronousMessageBox::warning(tr("Invalid QML source"), errMsg);
+ }
return m_qmlComponent;
}
@@ -590,10 +598,8 @@ bool PropertyEditorContextObject::isBlocked(const QString &propName) const
{
if (m_model && m_model->rewriterView()) {
const QList<ModelNode> nodes = m_model->rewriterView()->selectedModelNodes();
- QScopedPointer<QmlObjectNode> objNode;
for (const auto &node : nodes) {
- objNode.reset(QmlObjectNode::getQmlObjectNodeOfCorrectType(node));
- if (objNode->isBlocked(propName.toUtf8()))
+ if (Qml3DNode qml3DNode{node}; qml3DNode.isBlocked(propName.toUtf8()))
return true;
}
}
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp
index 909530dbc3..3b991a5f62 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp
@@ -19,6 +19,7 @@
#include <theme.h>
#include <coreplugin/icore.h>
+#include <coreplugin/messagebox.h>
#include <utils/algorithm.h>
#include <utils/environment.h>
#include <utils/fileutils.h>
@@ -40,7 +41,7 @@ static Q_LOGGING_CATEGORY(propertyEditorBenchmark, "qtc.propertyeditor.load", Qt
static QmlJS::SimpleReaderNode::Ptr s_templateConfiguration = QmlJS::SimpleReaderNode::Ptr();
-static inline QString propertyTemplatesPath()
+inline static QString propertyTemplatesPath()
{
return QmlDesigner::PropertyEditorQmlBackend::propertyEditorResourcesPath() + QStringLiteral("/PropertyTemplates/");
}
@@ -70,7 +71,7 @@ QStringList variantToStringList(const QVariant &variant) {
static QObject *variantToQObject(const QVariant &value)
{
- if (value.userType() == QMetaType::QObjectStar || value.userType() > QMetaType::User)
+ if (value.typeId() == QMetaType::QObjectStar || value.typeId() > QMetaType::User)
return *(QObject **)value.constData();
return nullptr;
@@ -322,7 +323,7 @@ void PropertyEditorQmlBackend::createPropertyEditorValue(const QmlObjectNode &qm
void PropertyEditorQmlBackend::setValue(const QmlObjectNode & , const PropertyName &name, const QVariant &value)
{
// Vector*D values need to be split into their subcomponents
- if (value.type() == QVariant::Vector2D) {
+ if (value.typeId() == QVariant::Vector2D) {
const char *suffix[2] = {"_x", "_y"};
auto vecValue = value.value<QVector2D>();
for (int i = 0; i < 2; ++i) {
@@ -333,7 +334,7 @@ void PropertyEditorQmlBackend::setValue(const QmlObjectNode & , const PropertyNa
if (propertyValue)
propertyValue->setValue(QVariant(vecValue[i]));
}
- } else if (value.type() == QVariant::Vector3D) {
+ } else if (value.typeId() == QVariant::Vector3D) {
const char *suffix[3] = {"_x", "_y", "_z"};
auto vecValue = value.value<QVector3D>();
for (int i = 0; i < 3; ++i) {
@@ -344,7 +345,7 @@ void PropertyEditorQmlBackend::setValue(const QmlObjectNode & , const PropertyNa
if (propertyValue)
propertyValue->setValue(QVariant(vecValue[i]));
}
- } else if (value.type() == QVariant::Vector4D) {
+ } else if (value.typeId() == QVariant::Vector4D) {
const char *suffix[4] = {"_x", "_y", "_z", "_w"};
auto vecValue = value.value<QVector4D>();
for (int i = 0; i < 4; ++i) {
@@ -372,23 +373,35 @@ void PropertyEditorQmlBackend::setExpression(const PropertyName &propName, const
propertyValue->setExpression(exp);
}
-QQmlContext *PropertyEditorQmlBackend::context() {
+QQmlContext *PropertyEditorQmlBackend::context()
+{
return m_view->rootContext();
}
-PropertyEditorContextObject* PropertyEditorQmlBackend::contextObject() {
+PropertyEditorContextObject *PropertyEditorQmlBackend::contextObject()
+{
return m_contextObject.data();
}
-QQuickWidget *PropertyEditorQmlBackend::widget() {
+QQuickWidget *PropertyEditorQmlBackend::widget()
+{
return m_view;
}
-void PropertyEditorQmlBackend::setSource(const QUrl& url) {
+void PropertyEditorQmlBackend::setSource(const QUrl &url)
+{
m_view->setSource(url);
+
+ const bool showError = qEnvironmentVariableIsSet(Constants::ENVIRONMENT_SHOW_QML_ERRORS);
+
+ if (showError && !m_view->errors().isEmpty()) {
+ const QString errMsg = m_view->errors().constFirst().toString();
+ Core::AsynchronousMessageBox::warning(PropertyEditorView::tr("Invalid QML source"), errMsg);
+ }
}
-Internal::QmlAnchorBindingProxy &PropertyEditorQmlBackend::backendAnchorBinding() {
+Internal::QmlAnchorBindingProxy &PropertyEditorQmlBackend::backendAnchorBinding()
+{
return m_backendAnchorBinding;
}
@@ -482,7 +495,8 @@ void PropertyEditorQmlBackend::setup(const QmlObjectNode &qmlObjectNode, const Q
if (!qmlObjectNode.isValid())
return;
- context()->setContextProperty(QLatin1String("propertyCount"), QVariant(qmlObjectNode.modelNode().properties().count()));
+ context()->setContextProperty(QLatin1String("propertyCount"),
+ QVariant(qmlObjectNode.modelNode().properties().size()));
QStringList stateNames = qmlObjectNode.allStateNames();
stateNames.prepend("base state");
@@ -849,7 +863,7 @@ NodeMetaInfo PropertyEditorQmlBackend::findCommonAncestor(const ModelNode &node)
AbstractView *view = node.view();
- if (view->selectedModelNodes().count() > 1) {
+ if (view->selectedModelNodes().size() > 1) {
NodeMetaInfo commonClass = node.metaInfo();
for (const ModelNode &currentNode : view->selectedModelNodes()) {
if (currentNode.metaInfo().isValid() && !currentNode.metaInfo().isBasedOn(commonClass))
@@ -964,7 +978,7 @@ QString PropertyEditorQmlBackend::locateQmlFile(const NodeMetaInfo &info, const
const QDir importDir(info.importDirectoryPath() + Constants::QML_DESIGNER_SUBFOLDER);
const QDir importDirVersion(info.importDirectoryPath() + QStringLiteral(".") + QString::number(info.majorVersion()) + Constants::QML_DESIGNER_SUBFOLDER);
- const QString relativePathWithoutEnding = relativePath.left(relativePath.count() - 4);
+ const QString relativePathWithoutEnding = relativePath.left(relativePath.size() - 4);
const QString relativePathWithVersion = QString("%1_%2_%3.qml").arg(relativePathWithoutEnding
).arg(info.majorVersion()).arg(info.minorVersion());
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp
index 6a9ce6164a..3f3ddaaf16 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp
@@ -41,7 +41,7 @@ QVariant PropertyEditorValue::value() const
static bool cleverDoubleCompare(const QVariant &value1, const QVariant &value2)
{
- if (value1.type() == QVariant::Double && value2.type() == QVariant::Double) {
+ if (value1.typeId() == QVariant::Double && value2.typeId() == QVariant::Double) {
// ignore slight changes on doubles
if (qFuzzyCompare(value1.toDouble(), value2.toDouble()))
return true;
@@ -51,16 +51,16 @@ static bool cleverDoubleCompare(const QVariant &value1, const QVariant &value2)
static bool cleverColorCompare(const QVariant &value1, const QVariant &value2)
{
- if (value1.type() == QVariant::Color && value2.type() == QVariant::Color) {
+ if (value1.typeId() == QVariant::Color && value2.typeId() == QVariant::Color) {
QColor c1 = value1.value<QColor>();
QColor c2 = value2.value<QColor>();
return c1.name() == c2.name() && c1.alpha() == c2.alpha();
}
- if (value1.type() == QVariant::String && value2.type() == QVariant::Color)
+ if (value1.typeId() == QVariant::String && value2.typeId() == QVariant::Color)
return cleverColorCompare(QVariant(QColor(value1.toString())), value2);
- if (value1.type() == QVariant::Color && value2.type() == QVariant::String)
+ if (value1.typeId() == QVariant::Color && value2.typeId() == QVariant::String)
return cleverColorCompare(value1, QVariant(QColor(value2.toString())));
return false;
@@ -71,7 +71,7 @@ static bool cleverColorCompare(const QVariant &value1, const QVariant &value2)
static void fixAmbigousColorNames(const ModelNode &modelNode, const PropertyName &name, QVariant *value)
{
if (auto metaInfo = modelNode.metaInfo(); metaInfo.property(name).propertyType().isColor()) {
- if (value->type() == QVariant::Color) {
+ if (value->typeId() == QVariant::Color) {
QColor color = value->value<QColor>();
int alpha = color.alpha();
color = QColor(color.name());
@@ -623,16 +623,13 @@ void PropertyEditorNodeWrapper::changeValue(const QString &propertyName)
if (name.isNull())
return;
- if (m_modelNode.isValid()) {
- QScopedPointer<QmlObjectNode> qmlObjectNode{
- QmlObjectNode::getQmlObjectNodeOfCorrectType(m_modelNode)};
-
+ if (auto qmlObjectNode = QmlObjectNode{m_modelNode}) {
auto valueObject = qvariant_cast<PropertyEditorValue *>(m_valuesPropertyMap.value(QString::fromLatin1(name)));
if (valueObject->value().isValid())
- qmlObjectNode->setVariantProperty(name, valueObject->value());
+ qmlObjectNode.setVariantProperty(name, valueObject->value());
else
- qmlObjectNode->removeProperty(name);
+ qmlObjectNode.removeProperty(name);
}
}
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp
index 2cf47789e4..5d00f373c4 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp
@@ -249,7 +249,7 @@ void PropertyEditorView::changeExpression(const QString &propertyName)
PropertyName underscoreName(name);
underscoreName.replace('.', '_');
- QScopedPointer<QmlObjectNode> qmlObjectNode {QmlObjectNode::getQmlObjectNodeOfCorrectType(m_selectedNode)};
+ QmlObjectNode qmlObjectNode{m_selectedNode};
PropertyEditorValue *value = m_qmlBackEndForCurrentType->propertyValueForName(QString::fromLatin1(underscoreName));
if (!value) {
@@ -257,46 +257,46 @@ void PropertyEditorView::changeExpression(const QString &propertyName)
return;
}
- if (auto property = qmlObjectNode->modelNode().metaInfo().property(name)) {
+ if (auto property = qmlObjectNode.modelNode().metaInfo().property(name)) {
const auto &propertType = property.propertyType();
if (propertType.isColor()) {
if (QColor(value->expression().remove('"')).isValid()) {
- qmlObjectNode->setVariantProperty(name, QColor(value->expression().remove('"')));
+ qmlObjectNode.setVariantProperty(name, QColor(value->expression().remove('"')));
return;
}
} else if (propertType.isBool()) {
if (isTrueFalseLiteral(value->expression())) {
if (value->expression().compare("true", Qt::CaseInsensitive) == 0)
- qmlObjectNode->setVariantProperty(name, true);
+ qmlObjectNode.setVariantProperty(name, true);
else
- qmlObjectNode->setVariantProperty(name, false);
+ qmlObjectNode.setVariantProperty(name, false);
return;
}
} else if (propertType.isInteger()) {
bool ok;
int intValue = value->expression().toInt(&ok);
if (ok) {
- qmlObjectNode->setVariantProperty(name, intValue);
+ qmlObjectNode.setVariantProperty(name, intValue);
return;
}
} else if (propertType.isFloat()) {
bool ok;
qreal realValue = value->expression().toDouble(&ok);
if (ok) {
- qmlObjectNode->setVariantProperty(name, realValue);
+ qmlObjectNode.setVariantProperty(name, realValue);
return;
}
} else if (propertType.isVariant()) {
bool ok;
qreal realValue = value->expression().toDouble(&ok);
if (ok) {
- qmlObjectNode->setVariantProperty(name, realValue);
+ qmlObjectNode.setVariantProperty(name, realValue);
return;
} else if (isTrueFalseLiteral(value->expression())) {
if (value->expression().compare("true", Qt::CaseInsensitive) == 0)
- qmlObjectNode->setVariantProperty(name, true);
+ qmlObjectNode.setVariantProperty(name, true);
else
- qmlObjectNode->setVariantProperty(name, false);
+ qmlObjectNode.setVariantProperty(name, false);
return;
}
}
@@ -307,9 +307,9 @@ void PropertyEditorView::changeExpression(const QString &propertyName)
return;
}
- if (qmlObjectNode->expression(name) != value->expression()
- || !qmlObjectNode->propertyAffectedByCurrentState(name))
- qmlObjectNode->setBindingProperty(name, value->expression());
+ if (qmlObjectNode.expression(name) != value->expression()
+ || !qmlObjectNode.propertyAffectedByCurrentState(name))
+ qmlObjectNode.setBindingProperty(name, value->expression());
}); /* end of transaction */
}
@@ -477,13 +477,10 @@ void PropertyEditorView::setupQmlBackend()
m_stackedWidget->addWidget(currentQmlBackend->widget());
m_qmlBackendHash.insert(qmlFile.toString(), currentQmlBackend);
- QScopedPointer<QmlObjectNode> qmlObjectNode;
if (m_selectedNode.isValid()) {
- qmlObjectNode.reset(QmlObjectNode::getQmlObjectNodeOfCorrectType(m_selectedNode));
- Q_ASSERT(qmlObjectNode->isValid());
- currentQmlBackend->setup(*qmlObjectNode, currentStateName, qmlSpecificsFile, this);
- } else {
- qmlObjectNode.reset(new QmlObjectNode);
+ QmlObjectNode qmlObjectNode{m_selectedNode};
+ Q_ASSERT(qmlObjectNode.isValid());
+ currentQmlBackend->setup(qmlObjectNode, currentStateName, qmlSpecificsFile, this);
}
if (specificQmlData.isEmpty())
@@ -492,15 +489,11 @@ void PropertyEditorView::setupQmlBackend()
currentQmlBackend->contextObject()->setSpecificQmlData(specificQmlData);
currentQmlBackend->setSource(qmlFile);
} else {
- QScopedPointer<QmlObjectNode> qmlObjectNode;
- if (m_selectedNode.isValid())
- qmlObjectNode.reset(QmlObjectNode::getQmlObjectNodeOfCorrectType(m_selectedNode));
- else
- qmlObjectNode.reset(new QmlObjectNode);
+ QmlObjectNode qmlObjectNode{m_selectedNode};
if (specificQmlData.isEmpty())
currentQmlBackend->contextObject()->setSpecificQmlData(specificQmlData);
- currentQmlBackend->setup(*qmlObjectNode, currentStateName, qmlSpecificsFile, this);
+ currentQmlBackend->setup(qmlObjectNode, currentStateName, qmlSpecificsFile, this);
currentQmlBackend->contextObject()->setSpecificQmlData(specificQmlData);
}
@@ -527,10 +520,8 @@ void PropertyEditorView::commitVariantValueToModel(const PropertyName &propertyN
RewriterTransaction transaction = beginRewriterTransaction("PropertyEditorView::commitVariantValueToMode");
for (const ModelNode &node : m_selectedNode.view()->selectedModelNodes()) {
- if (QmlObjectNode::isValidQmlObjectNode(node)) {
- QScopedPointer<QmlObjectNode>{QmlObjectNode::getQmlObjectNodeOfCorrectType(node)}
- ->setVariantProperty(propertyName, value);
- }
+ if (auto qmlObjectNode = QmlObjectNode(node))
+ qmlObjectNode.setVariantProperty(propertyName, value);
}
transaction.commit();
}
@@ -646,9 +637,20 @@ void PropertyEditorView::propertiesRemoved(const QList<AbstractProperty> &proper
if (node == m_selectedNode || QmlObjectNode(m_selectedNode).propertyChangeForCurrentState() == node) {
m_locked = true;
- PropertyEditorValue *value = m_qmlBackEndForCurrentType->propertyValueForName(QString::fromUtf8(property.name()));
- if (value)
+
+ PropertyName propertyName = property.name();
+ propertyName.replace('.', '_');
+
+ PropertyEditorValue *value = m_qmlBackEndForCurrentType->propertyValueForName(
+ QString::fromUtf8(propertyName));
+
+ if (value) {
value->resetValue();
+ m_qmlBackEndForCurrentType
+ ->setValue(m_selectedNode,
+ property.name(),
+ QmlObjectNode(m_selectedNode).instanceValue(property.name()));
+ }
m_locked = false;
if (propertyIsAttachedLayoutProperty(property.name())) {
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.cpp b/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.cpp
index f121489916..96ec5f92e7 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.cpp
@@ -50,7 +50,7 @@ bool QmlModelNodeProxy::multiSelection() const
if (!m_qmlObjectNode.isValid())
return false;
- return m_qmlObjectNode.view()->selectedModelNodes().count() > 1;
+ return m_qmlObjectNode.view()->selectedModelNodes().size() > 1;
}
QString QmlModelNodeProxy::nodeId() const
diff --git a/src/plugins/qmldesigner/components/propertyeditor/quick2propertyeditorview.cpp b/src/plugins/qmldesigner/components/propertyeditor/quick2propertyeditorview.cpp
index 610c0e2731..1c0071ee91 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/quick2propertyeditorview.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/quick2propertyeditorview.cpp
@@ -6,17 +6,17 @@
#include <qmldesignerconstants.h>
#include "aligndistribute.h"
-#include "assetimageprovider.h"
#include "annotationeditor/annotationeditor.h"
+#include "assetimageprovider.h"
#include "bindingeditor/actioneditor.h"
#include "bindingeditor/bindingeditor.h"
#include "colorpalettebackend.h"
-#include "selectiondynamicpropertiesproxymodel.h"
#include "fileresourcesmodel.h"
#include "gradientmodel.h"
#include "gradientpresetcustomlistmodel.h"
#include "gradientpresetdefaultlistmodel.h"
#include "itemfiltermodel.h"
+#include "listvalidator.h"
#include "propertychangesmodel.h"
#include "propertyeditorcontextobject.h"
#include "propertyeditorqmlbackend.h"
@@ -24,6 +24,7 @@
#include "propertymodel.h"
#include "qmlanchorbindingproxy.h"
#include "richtexteditor/richtexteditorproxy.h"
+#include "selectiondynamicpropertiesproxymodel.h"
#include "theme.h"
#include "tooltip.h"
@@ -50,6 +51,7 @@ void Quick2PropertyEditorView::registerQmlTypes()
GradientPresetDefaultListModel::registerDeclarativeType();
GradientPresetCustomListModel::registerDeclarativeType();
ItemFilterModel::registerDeclarativeType();
+ ListValidator::registerDeclarativeType();
ColorPaletteBackend::registerDeclarativeType();
Internal::QmlAnchorBindingProxy::registerDeclarativeType();
BindingEditor::registerDeclarativeType();
@@ -61,8 +63,8 @@ void Quick2PropertyEditorView::registerQmlTypes()
RichTextEditorProxy::registerDeclarativeType();
SelectionDynamicPropertiesProxyModel::registerDeclarativeType();
DynamicPropertyRow::registerDeclarativeType();
- Experimental::PropertyChangesModel::registerDeclarativeType();
- Experimental::PropertyModel::registerDeclarativeType();
+ PropertyChangesModel::registerDeclarativeType();
+ PropertyModel::registerDeclarativeType();
const QString resourcePath = PropertyEditorQmlBackend::propertyEditorResourcesPath();
diff --git a/src/plugins/qmldesigner/components/stateseditornew/propertychangesmodel.cpp b/src/plugins/qmldesigner/components/stateseditor/propertychangesmodel.cpp
index d559aea1ca..f0f177ed9e 100644
--- a/src/plugins/qmldesigner/components/stateseditornew/propertychangesmodel.cpp
+++ b/src/plugins/qmldesigner/components/stateseditor/propertychangesmodel.cpp
@@ -1,27 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2022 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
+// 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 "propertychangesmodel.h"
@@ -39,7 +17,6 @@ enum {
};
namespace QmlDesigner {
-namespace Experimental {
PropertyChangesModel::PropertyChangesModel(QObject *parent)
: QAbstractListModel(parent)
@@ -164,5 +141,4 @@ QVariant PropertyChangesModel::modelNodeBackend() const
return QVariant();
}
-} // namespace Experimental
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/stateseditornew/propertychangesmodel.h b/src/plugins/qmldesigner/components/stateseditor/propertychangesmodel.h
index b73d4dad69..6686131aff 100644
--- a/src/plugins/qmldesigner/components/stateseditornew/propertychangesmodel.h
+++ b/src/plugins/qmldesigner/components/stateseditor/propertychangesmodel.h
@@ -1,27 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2022 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
+// 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
@@ -31,7 +9,6 @@
#include <modelnode.h>
namespace QmlDesigner {
-namespace Experimental {
class StatesEditorView;
@@ -82,5 +59,4 @@ private:
QPointer<StatesEditorView> m_view;
};
-} // namespace Experimental
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/stateseditornew/propertymodel.cpp b/src/plugins/qmldesigner/components/stateseditor/propertymodel.cpp
index 35dea7cb23..0a72d60ef7 100644
--- a/src/plugins/qmldesigner/components/stateseditornew/propertymodel.cpp
+++ b/src/plugins/qmldesigner/components/stateseditor/propertymodel.cpp
@@ -1,27 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2022 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
+// 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 "propertymodel.h"
@@ -44,7 +22,6 @@ enum {
};
namespace QmlDesigner {
-namespace Experimental {
PropertyModel::PropertyModel(QObject *parent)
: QAbstractListModel(parent)
@@ -188,5 +165,4 @@ void PropertyModel::setupModel()
m_properties = propertyChanges.targetProperties();
}
-} // namespace Experimental
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/stateseditornew/propertymodel.h b/src/plugins/qmldesigner/components/stateseditor/propertymodel.h
index 492b1362c0..c9d8e93c3f 100644
--- a/src/plugins/qmldesigner/components/stateseditornew/propertymodel.h
+++ b/src/plugins/qmldesigner/components/stateseditor/propertymodel.h
@@ -1,27 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2022 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
+// 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
@@ -31,7 +9,6 @@
#include <modelnode.h>
namespace QmlDesigner {
-namespace Experimental {
class PropertyModel : public QAbstractListModel
{
@@ -74,5 +51,4 @@ private:
QList<AbstractProperty> m_properties;
};
-} // namespace Experimental
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditorimageprovider.cpp b/src/plugins/qmldesigner/components/stateseditor/stateseditorimageprovider.cpp
index 55fcf61932..f0a7d0bf86 100644
--- a/src/plugins/qmldesigner/components/stateseditor/stateseditorimageprovider.cpp
+++ b/src/plugins/qmldesigner/components/stateseditor/stateseditorimageprovider.cpp
@@ -1,16 +1,18 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// 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 "stateseditorimageprovider.h"
#include "nodeinstanceview.h"
#include <QDebug>
-namespace QmlDesigner::Internal {
+namespace QmlDesigner {
+namespace Internal {
StatesEditorImageProvider::StatesEditorImageProvider()
: QQuickImageProvider(QQuickImageProvider::Image)
-{}
+{
+}
QImage StatesEditorImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
{
@@ -25,8 +27,7 @@ QImage StatesEditorImageProvider::requestImage(const QString &id, QSize *size, c
bool canBeConverted;
int instanceId = imageId.toInt(&canBeConverted);
if (canBeConverted && m_nodeInstanceView->hasModelNodeForInternalId(instanceId)) {
- image = m_nodeInstanceView->statePreviewImage(
- m_nodeInstanceView->modelNodeForInternalId(instanceId));
+ image = m_nodeInstanceView->statePreviewImage(m_nodeInstanceView->modelNodeForInternalId(instanceId));
}
}
}
@@ -52,4 +53,5 @@ void StatesEditorImageProvider::setNodeInstanceView(const NodeInstanceView *node
m_nodeInstanceView = nodeInstanceView;
}
-} // QmlDesigner::Internal
+} // namespace Internal
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditorimageprovider.h b/src/plugins/qmldesigner/components/stateseditor/stateseditorimageprovider.h
index 0bfb0bf330..1bd4432a95 100644
--- a/src/plugins/qmldesigner/components/stateseditor/stateseditorimageprovider.h
+++ b/src/plugins/qmldesigner/components/stateseditor/stateseditorimageprovider.h
@@ -1,12 +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
+// 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 "abstractview.h"
-#include <QPointer>
#include <QQuickImageProvider>
+#include <QPointer>
namespace QmlDesigner {
namespace Internal {
diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp b/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp
index 96ec3fa8e6..0b53af121b 100644
--- a/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp
+++ b/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp
@@ -1,31 +1,39 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// 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 "stateseditormodel.h"
#include "stateseditorview.h"
-#include <QDebug>
-
#include <bindingproperty.h>
#include <modelnode.h>
#include <nodelistproperty.h>
+#include <nodemetainfo.h>
#include <rewriterview.h>
#include <variantproperty.h>
#include <coreplugin/icore.h>
#include <coreplugin/messagebox.h>
+#include <utils/algorithm.h>
+#include <utils/qtcassert.h>
+
+#include <QDebug>
#include <QWidget>
-enum { debug = false };
+enum {
+ debug = false
+};
namespace QmlDesigner {
StatesEditorModel::StatesEditorModel(StatesEditorView *view)
: QAbstractListModel(view)
, m_statesEditorView(view)
- , m_updateCounter(0)
-{}
+ , m_hasExtend(false)
+ , m_extendedStates()
+{
+ QObject::connect(this, &StatesEditorModel::dataChanged, [this]() { emit baseStateChanged(); });
+}
int StatesEditorModel::count() const
{
@@ -38,8 +46,8 @@ QModelIndex StatesEditorModel::index(int row, int column, const QModelIndex &par
return {};
int internalNodeId = 0;
- if (row > 0 && row < rowCount() - 1) // first and last rows are base state, add state
- internalNodeId = m_statesEditorView->acitveStatesGroupNode()
+ if (row > 0)
+ internalNodeId = m_statesEditorView->activeStatesGroupNode()
.nodeListProperty("states")
.at(row - 1)
.internalId();
@@ -52,17 +60,19 @@ int StatesEditorModel::rowCount(const QModelIndex &parent) const
if (parent.isValid() || m_statesEditorView.isNull() || !m_statesEditorView->model())
return 0;
- if (!m_statesEditorView->acitveStatesGroupNode().hasNodeListProperty("states"))
- return 2; // base state + add new state
+ if (!m_statesEditorView->activeStatesGroupNode().hasNodeListProperty("states"))
+ return 1; // base state
- return m_statesEditorView->acitveStatesGroupNode().nodeListProperty("states").count()
- + 2; // 2 = base state + add new state
+ return m_statesEditorView->activeStatesGroupNode().nodeListProperty("states").count() + 1;
}
void StatesEditorModel::reset()
{
QAbstractListModel::beginResetModel();
QAbstractListModel::endResetModel();
+
+ evaluateExtend();
+ emit baseStateChanged();
}
QVariant StatesEditorModel::data(const QModelIndex &index, int role) const
@@ -101,20 +111,34 @@ QVariant StatesEditorModel::data(const QModelIndex &index, int role) const
return index.internalId();
case HasWhenCondition:
- return stateNode.hasProperty("when");
+ return stateNode.isValid() && stateNode.hasProperty("when");
- case WhenConditionString:
- return stateNode.bindingProperty("when").expression();
+ case WhenConditionString: {
+ if (stateNode.isValid() && stateNode.hasBindingProperty("when"))
+ return stateNode.bindingProperty("when").expression();
+ else
+ return QString();
+ }
case IsDefault: {
- return QmlModelState(stateNode).isDefault();
+ QmlModelState modelState(stateNode);
+ if (modelState.isValid())
+ return modelState.isDefault();
+ return false;
}
case ModelHasDefaultState:
return hasDefaultState();
- case StateType:
- return index.row() == rowCount() - 1 ? "add" : "state";
+ case HasExtend:
+ return stateNode.isValid() && stateNode.hasProperty("extend");
+
+ case ExtendString: {
+ if (stateNode.isValid() && stateNode.hasVariantProperty("extend"))
+ return stateNode.variantProperty("extend").value();
+ else
+ return QString();
+ }
}
return QVariant();
@@ -129,7 +153,8 @@ QHash<int, QByteArray> StatesEditorModel::roleNames() const
{WhenConditionString, "whenConditionString"},
{IsDefault, "isDefault"},
{ModelHasDefaultState, "modelHasDefaultState"},
- {StateType, "type"}};
+ {HasExtend, "hasExtend"},
+ {ExtendString, "extendString"}};
return roleNames;
}
@@ -155,9 +180,6 @@ void StatesEditorModel::removeState(int stateIndex)
if (stateIndex >= 0) {
beginRemoveRows(QModelIndex(), 0, stateIndex);
endRemoveRows();
-
- beginResetModel();
- endResetModel();
}
}
@@ -166,12 +188,13 @@ void StatesEditorModel::renameState(int internalNodeId, const QString &newName)
if (newName == m_statesEditorView->currentStateName())
return;
- if (newName.isEmpty() || !m_statesEditorView->validStateName(newName)) {
- QTimer::singleShot(0, [newName] {
+ if (newName.isEmpty() ||! m_statesEditorView->validStateName(newName)) {
+ QTimer::singleShot(0, this, [newName] {
Core::AsynchronousMessageBox::warning(
- tr("Invalid State Name"),
- newName.isEmpty() ? tr("The empty string as a name is reserved for the base state.")
- : tr("Name already used in another state."));
+ tr("Invalid state name"),
+ newName.isEmpty() ?
+ tr("The empty string as a name is reserved for the base state.") :
+ tr("Name already used in another state"));
});
reset();
} else {
@@ -198,9 +221,14 @@ QStringList StatesEditorModel::autoComplete(const QString &text, int pos, bool e
return QStringList();
}
-QVariant StatesEditorModel::stateModelNode()
+QVariant StatesEditorModel::stateModelNode(int internalNodeId)
{
- return QVariant::fromValue(m_statesEditorView->currentStateNode());
+ if (!m_statesEditorView->model())
+ return QVariant();
+
+ ModelNode node = m_statesEditorView->modelNodeForInternalId(internalNodeId);
+
+ return QVariant::fromValue(m_statesEditorView->modelNodeForInternalId(internalNodeId));
}
void StatesEditorModel::setStateAsDefault(int internalNodeId)
@@ -233,4 +261,193 @@ bool StatesEditorModel::hasAnnotation(int internalNodeId) const
return m_statesEditorView->hasAnnotation(internalNodeId);
}
+QStringList StatesEditorModel::stateGroups() const
+{
+ if (!m_statesEditorView->isAttached())
+ return {};
+
+ const auto groupMetaInfo = m_statesEditorView->model()->qtQuickStateGroupMetaInfo();
+
+ auto stateGroups = Utils::transform(m_statesEditorView->allModelNodesOfType(groupMetaInfo),
+ [](const ModelNode &node) { return node.displayName(); });
+ stateGroups.prepend(tr("Default"));
+ return stateGroups;
+}
+
+QString StatesEditorModel::activeStateGroup() const
+{
+ if (auto stateGroup = m_statesEditorView->activeStatesGroupNode())
+ return stateGroup.displayName();
+
+ return {};
+}
+
+void StatesEditorModel::setActiveStateGroup(const QString &name)
+{
+ if (!m_statesEditorView->isAttached())
+ return;
+
+ const auto groupMetaInfo = m_statesEditorView->model()->qtQuickStateGroupMetaInfo();
+
+ auto modelNode = Utils::findOrDefault(m_statesEditorView->allModelNodesOfType(groupMetaInfo),
+ [&name](const ModelNode &node) {
+ return node.displayName() == name;
+ });
+
+ QTC_ASSERT(!modelNode.isValid(), return );
+
+ if (modelNode.isValid())
+ m_statesEditorView->setActiveStatesGroupNode(modelNode);
+}
+
+int StatesEditorModel::activeStateGroupIndex() const
+{
+ return m_statesEditorView->activeStatesGroupIndex();
+}
+
+void StatesEditorModel::setActiveStateGroupIndex(int index)
+{
+ m_statesEditorView->setActiveStatesGroupIndex(index);
+}
+
+bool StatesEditorModel::renameActiveStateGroup(const QString &name)
+{
+ auto stateGroup = m_statesEditorView->activeStatesGroupNode();
+
+ if (!stateGroup.isValid() || stateGroup.isRootNode())
+ return false;
+
+ if (!QmlDesigner::ModelNode::isValidId(name) || m_statesEditorView->hasId(name)) {
+ QString errMsg = QmlDesigner::ModelNode::getIdValidityErrorMessage(name);
+ if (!errMsg.isEmpty())
+ Core::AsynchronousMessageBox::warning(tr("Invalid ID"), errMsg);
+ else
+ Core::AsynchronousMessageBox::warning(tr("Invalid ID"),
+ tr("%1 already exists.").arg(name));
+ return false;
+ }
+
+ stateGroup.setIdWithRefactoring(name);
+ emit stateGroupsChanged();
+ return true;
+}
+
+void StatesEditorModel::addStateGroup(const QString &name)
+{
+ m_statesEditorView->executeInTransaction("createStateGroup", [this, name]() {
+ const TypeName typeName = "QtQuick.StateGroup";
+ auto metaInfo = m_statesEditorView->model()->metaInfo(typeName);
+ int minorVersion = metaInfo.minorVersion();
+ int majorVersion = metaInfo.majorVersion();
+ auto stateGroupNode = m_statesEditorView->createModelNode(typeName,
+ majorVersion,
+ minorVersion);
+ stateGroupNode.setIdWithoutRefactoring(m_statesEditorView->model()->generateNewId(name));
+
+ m_statesEditorView->rootModelNode().defaultNodeAbstractProperty().reparentHere(
+ stateGroupNode);
+ m_statesEditorView->setActiveStatesGroupNode(stateGroupNode);
+ });
+}
+
+void StatesEditorModel::removeStateGroup()
+{
+ if (m_statesEditorView->activeStatesGroupNode().isRootNode())
+ return;
+
+ m_statesEditorView->executeInTransaction("removeStateGroup", [this]() {
+ m_statesEditorView->activeStatesGroupNode().destroy();
+ });
+}
+
+QVariantMap StatesEditorModel::get(int idx) const
+{
+ const QHash<int, QByteArray> &names = roleNames();
+ QHash<int, QByteArray>::const_iterator i = names.constBegin();
+
+ QVariantMap res;
+ QModelIndex modelIndex = index(idx);
+
+ while (i != names.constEnd()) {
+ QVariant data = modelIndex.data(i.key());
+
+ res[QString::fromUtf8(i.value())] = data;
+ ++i;
+ }
+ return res;
+}
+
+QVariantMap StatesEditorModel::baseState() const
+{
+ return get(0);
+}
+
+bool StatesEditorModel::hasExtend() const
+{
+ return m_hasExtend;
+}
+
+QStringList StatesEditorModel::extendedStates() const
+{
+ return m_extendedStates;
+}
+
+void StatesEditorModel::move(int from, int to)
+{
+ // This does not alter the code (rewriter) which means the reordering is not presistent
+
+ if (from == to)
+ return;
+
+ int specialIndex = (from < to ? to + 1 : to);
+ beginMoveRows(QModelIndex(), from, from, QModelIndex(), specialIndex);
+ endMoveRows();
+}
+
+void StatesEditorModel::drop(int from, int to)
+{
+ m_statesEditorView->moveStates(from, to);
+}
+
+void StatesEditorModel::evaluateExtend()
+{
+ bool hasExtend = m_statesEditorView->hasExtend();
+
+ if (m_hasExtend != hasExtend) {
+ m_hasExtend = hasExtend;
+ emit hasExtendChanged();
+ }
+
+ auto extendedStates = m_statesEditorView->extendedStates();
+
+ if (extendedStates.size() != m_extendedStates.size()) {
+ m_extendedStates = extendedStates;
+ emit extendedStatesChanged();
+ return;
+ }
+
+ for (int i = 0; i != m_extendedStates.size(); ++i) {
+ if (extendedStates[i] != m_extendedStates[i]) {
+ m_extendedStates = extendedStates;
+ emit extendedStatesChanged();
+ return;
+ }
+ }
+}
+
+bool StatesEditorModel::canAddNewStates() const
+{
+ return m_canAddNewStates;
+}
+
+void StatesEditorModel::setCanAddNewStates(bool b)
+{
+ if (b == m_canAddNewStates)
+ return;
+
+ m_canAddNewStates = b;
+
+ emit canAddNewStatesChanged();
+}
+
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.h b/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.h
index 832f0cdbff..8eff287c86 100644
--- a/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.h
+++ b/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.h
@@ -1,5 +1,5 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// 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
@@ -14,6 +14,9 @@ class StatesEditorModel : public QAbstractListModel
{
Q_OBJECT
+ Q_PROPERTY(bool canAddNewStates READ canAddNewStates WRITE setCanAddNewStates NOTIFY
+ canAddNewStatesChanged)
+
enum {
StateNameRole = Qt::DisplayRole,
StateImageSourceRole = Qt::UserRole,
@@ -22,13 +25,14 @@ class StatesEditorModel : public QAbstractListModel
WhenConditionString,
IsDefault,
ModelHasDefaultState,
- StateType
+ HasExtend,
+ ExtendString
};
public:
StatesEditorModel(StatesEditorView *view);
- int count() const;
+ Q_INVOKABLE int count() const;
QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
@@ -41,7 +45,8 @@ public:
Q_INVOKABLE void setWhenCondition(int internalNodeId, const QString &condition);
Q_INVOKABLE void resetWhenCondition(int internalNodeId);
Q_INVOKABLE QStringList autoComplete(const QString &text, int pos, bool explicitComplete);
- Q_INVOKABLE QVariant stateModelNode();
+ Q_INVOKABLE QVariant stateModelNode(int internalNodeId);
+
Q_INVOKABLE void setStateAsDefault(int internalNodeId);
Q_INVOKABLE void resetDefaultState();
Q_INVOKABLE bool hasDefaultState() const;
@@ -49,14 +54,58 @@ public:
Q_INVOKABLE void removeAnnotation(int internalNodeId);
Q_INVOKABLE bool hasAnnotation(int internalNodeId) const;
+ QStringList stateGroups() const;
+ QString activeStateGroup() const;
+ void setActiveStateGroup(const QString &name);
+ int activeStateGroupIndex() const;
+ void setActiveStateGroupIndex(int index);
+
+ Q_INVOKABLE bool renameActiveStateGroup(const QString &name);
+
+ Q_INVOKABLE void addStateGroup(const QString &name);
+ Q_INVOKABLE void removeStateGroup();
+
+ Q_INVOKABLE QVariantMap get(int idx) const;
+
+ QVariantMap baseState() const;
+ bool hasExtend() const;
+ QStringList extendedStates() const;
+
+ Q_PROPERTY(QVariantMap baseState READ baseState NOTIFY baseStateChanged)
+ Q_PROPERTY(QStringList extendedStates READ extendedStates NOTIFY extendedStatesChanged)
+
+ Q_PROPERTY(bool hasExtend READ hasExtend NOTIFY hasExtendChanged)
+
+ Q_PROPERTY(QString activeStateGroup READ activeStateGroup WRITE setActiveStateGroup NOTIFY
+ activeStateGroupChanged)
+ Q_PROPERTY(int activeStateGroupIndex READ activeStateGroupIndex WRITE setActiveStateGroupIndex
+ NOTIFY activeStateGroupIndexChanged)
+ Q_PROPERTY(QStringList stateGroups READ stateGroups NOTIFY stateGroupsChanged)
+
+ Q_INVOKABLE void move(int from, int to);
+ Q_INVOKABLE void drop(int from, int to);
+
void reset();
+ void evaluateExtend();
+
+ bool canAddNewStates() const;
+ void setCanAddNewStates(bool b);
signals:
void changedToState(int n);
+ void baseStateChanged();
+ void hasExtendChanged();
+ void extendedStatesChanged();
+ void activeStateGroupChanged();
+ void activeStateGroupIndexChanged();
+ void stateGroupsChanged();
+ void canAddNewStatesChanged();
private:
QPointer<StatesEditorView> m_statesEditorView;
- int m_updateCounter;
+ bool m_hasExtend;
+ QStringList m_extendedStates;
+ bool m_canAddNewStates = false;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp
index ea9bed7489..03cd658f22 100644
--- a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp
+++ b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp
@@ -1,21 +1,29 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// 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 "stateseditorview.h"
-
+#include "propertychangesmodel.h"
#include "stateseditormodel.h"
#include "stateseditorwidget.h"
-#include <rewritingexception.h>
+#include <QDebug>
+#include <QRegularExpression>
+#include <QMessageBox>
+#include <cmath>
+#include <memory>
+
+#include <nodemetainfo.h>
+
#include <bindingproperty.h>
+#include <customnotifications.h>
#include <nodelistproperty.h>
-#include <nodemetainfo.h>
+#include <rewritingexception.h>
#include <variantproperty.h>
+
#include <qmldesignerconstants.h>
#include <qmldesignerplugin.h>
#include <qmlitemnode.h>
#include <qmlstate.h>
-
#include <annotationeditor/annotationeditor.h>
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
@@ -34,8 +42,9 @@ namespace QmlDesigner {
We always have 'one' current state, where we get updates from (see sceneChanged()). In case
the current state is the base state, we render the base state + all other states.
*/
+
StatesEditorView::StatesEditorView(ExternalDependenciesInterface &externalDependencies)
- : AbstractView{externalDependencies}
+ : AbstractView(externalDependencies)
, m_statesEditorModel(new StatesEditorModel(this))
, m_lastIndex(-1)
, m_editor(nullptr)
@@ -57,32 +66,215 @@ WidgetInfo StatesEditorView::widgetInfo()
m_statesEditorWidget = new StatesEditorWidget(this, m_statesEditorModel.data());
return createWidgetInfo(m_statesEditorWidget.data(),
- QLatin1String("StatesEditor"),
+ "StatesEditor",
WidgetInfo::BottomPane,
0,
- tr("States"),
- tr("States view"));
+ tr("States"));
}
-void StatesEditorView::rootNodeTypeChanged(const QString & /*type*/,
- int /*majorVersion*/,
- int /*minorVersion*/)
+void StatesEditorView::rootNodeTypeChanged(const QString &/*type*/, int /*majorVersion*/, int /*minorVersion*/)
{
checkForStatesAvailability();
}
-ModelNode StatesEditorView::acitveStatesGroupNode() const
+ModelNode StatesEditorView::activeStatesGroupNode() const
{
return m_activeStatesGroupNode;
}
-void StatesEditorView::setAcitveStatesGroupNode(const ModelNode &modelNode)
+void StatesEditorView::setActiveStatesGroupNode(const ModelNode &modelNode)
{
if (m_activeStatesGroupNode == modelNode)
return;
m_activeStatesGroupNode = modelNode;
resetModel();
+
+ checkForStatesAvailability();
+
+ emit m_statesEditorModel->activeStateGroupChanged();
+ emit m_statesEditorModel->activeStateGroupIndexChanged();
+}
+
+int StatesEditorView::activeStatesGroupIndex() const
+{
+ if (!model())
+ return -1;
+
+ return Utils::indexOf(allModelNodesOfType(model()->qtQuickStateGroupMetaInfo()),
+ [this](const ModelNode &node) { return node == m_activeStatesGroupNode; })
+ + 1;
+}
+
+void StatesEditorView::setActiveStatesGroupIndex(int index)
+{
+ if (!model())
+ return;
+
+ if (index > 0) {
+ const ModelNode statesGroup = allModelNodesOfType(model()->qtQuickStateGroupMetaInfo())
+ .at(index - 1);
+ if (statesGroup.isValid())
+ setActiveStatesGroupNode(statesGroup);
+ } else {
+ setActiveStatesGroupNode(rootModelNode());
+ }
+}
+
+void StatesEditorView::registerPropertyChangesModel(PropertyChangesModel *model)
+{
+ m_propertyChangedModels.insert(model);
+}
+
+void StatesEditorView::deregisterPropertyChangesModel(PropertyChangesModel *model)
+{
+ m_propertyChangedModels.remove(model);
+}
+
+void StatesEditorView::synchonizeCurrentStateFromWidget()
+{
+ if (!model())
+ return;
+
+ if (m_block)
+ return;
+
+ int internalId = m_statesEditorWidget->currentStateInternalId();
+
+ if (internalId > 0 && hasModelNodeForInternalId(internalId)) {
+ ModelNode node = modelNodeForInternalId(internalId);
+ QmlModelState modelState(node);
+ if (modelState.isValid() && modelState != currentState())
+ setCurrentState(modelState);
+ } else {
+ setCurrentState(baseState());
+ }
+}
+
+void StatesEditorView::createNewState()
+{
+ // can happen when root node is e.g. a ListModel
+ if (!QmlVisualNode::isValidQmlVisualNode(activeStatesGroupNode())
+ && m_activeStatesGroupNode.type() != "QtQuick.StateGroup")
+ return;
+
+ QmlDesignerPlugin::emitUsageStatistics(Constants::EVENT_STATE_ADDED);
+
+ QStringList modelStateNames = activeStateGroup().names();
+
+ QString newStateName;
+ int index = 1;
+ while (true) {
+ newStateName = QString(QStringLiteral("State%1")).arg(index++);
+ if (!modelStateNames.contains(newStateName))
+ break;
+ }
+
+ executeInTransaction("createNewState", [this, newStateName]() {
+ activeStatesGroupNode().validId();
+
+ ModelNode newState = activeStateGroup().addState(newStateName);
+ setCurrentState(newState);
+ });
+}
+
+void StatesEditorView::cloneState(int nodeId)
+{
+ if (!(nodeId > 0 && hasModelNodeForInternalId(nodeId)))
+ return;
+
+ ModelNode stateNode(modelNodeForInternalId(nodeId));
+ QTC_ASSERT(stateNode.simplifiedTypeName() == "State", return );
+
+ QmlModelState modelState(stateNode);
+ if (!modelState.isValid() || modelState.isBaseState())
+ return;
+
+ QmlDesignerPlugin::emitUsageStatistics(Constants::EVENT_STATE_CLONED);
+
+ QString newName = modelState.name();
+
+ // Strip out numbers at the end of the string
+ QRegularExpression regEx(QLatin1String("[0-9]+$"));
+ const QRegularExpressionMatch match = regEx.match(newName);
+ if (match.hasMatch() && (match.capturedStart() + match.capturedLength() == newName.length()))
+ newName = newName.left(match.capturedStart());
+
+ int i = 1;
+ QStringList stateNames = activeStateGroup().names();
+ while (stateNames.contains(newName + QString::number(i)))
+ i++;
+ const QString newStateName = newName + QString::number(i);
+
+ QmlModelState newState;
+
+ executeInTransaction("cloneState", [newStateName, modelState, &newState]() {
+ newState = modelState.duplicate(newStateName);
+ });
+
+ ModelNode newNode = newState.modelNode();
+ int from = newNode.parentProperty().indexOf(newNode);
+ int to = stateNode.parentProperty().indexOf(stateNode) + 1;
+
+ // When duplicating an extended state the new state needs to be added after the extend group.
+ if (!modelState.hasExtend()) {
+ auto modelNodeList = activeStatesGroupNode().nodeListProperty("states").toModelNodeList();
+ for (; to != modelNodeList.count(); ++to) {
+ QmlModelState currentState(modelNodeList.at(to));
+ if (!currentState.isValid() || currentState.isBaseState() || !currentState.hasExtend())
+ break;
+ }
+ }
+
+ executeInTransaction("moveState", [this, &newState, from, to]() {
+ activeStatesGroupNode().nodeListProperty("states").slide(from, to);
+ setCurrentState(newState);
+ });
+}
+
+void StatesEditorView::extendState(int nodeId)
+{
+ if (!(nodeId > 0 && hasModelNodeForInternalId(nodeId)))
+ return;
+
+ ModelNode stateNode(modelNodeForInternalId(nodeId));
+ QTC_ASSERT(stateNode.simplifiedTypeName() == "State", return );
+
+ QmlModelState modelState(stateNode);
+ if (!modelState.isValid() || modelState.isBaseState())
+ return;
+
+ QmlDesignerPlugin::emitUsageStatistics(Constants::EVENT_STATE_EXTENDED);
+
+ QString newName = modelState.name();
+
+ // Strip out numbers at the end of the string
+ QRegularExpression regEx(QLatin1String("[0-9]+$"));
+ const QRegularExpressionMatch match = regEx.match(newName);
+ if (match.hasMatch() && (match.capturedStart() + match.capturedLength() == newName.length()))
+ newName = newName.left(match.capturedStart());
+
+ int i = 1;
+ QStringList stateNames = activeStateGroup().names();
+ while (stateNames.contains(newName + QString::number(i)))
+ i++;
+ const QString newStateName = newName + QString::number(i);
+
+ QmlModelState newState;
+
+ executeInTransaction("extendState", [this, newStateName, modelState, &newState]() {
+ newState = activeStateGroup().addState(newStateName);
+ newState.setExtend(modelState.name());
+ });
+
+ ModelNode newNode = newState.modelNode();
+ int from = newNode.parentProperty().indexOf(newNode);
+ int to = stateNode.parentProperty().indexOf(stateNode) + 1;
+
+ executeInTransaction("moveState", [this, &newState, from, to]() {
+ activeStatesGroupNode().nodeListProperty("states").slide(from, to);
+ setCurrentState(newState);
+ });
}
void StatesEditorView::removeState(int nodeId)
@@ -90,7 +282,7 @@ void StatesEditorView::removeState(int nodeId)
try {
if (nodeId > 0 && hasModelNodeForInternalId(nodeId)) {
ModelNode stateNode(modelNodeForInternalId(nodeId));
- Q_ASSERT(stateNode.metaInfo().isQtQuickState());
+ QTC_ASSERT(stateNode.simplifiedTypeName() == "State", return );
QmlModelState modelState(stateNode);
if (modelState.isValid()) {
@@ -147,6 +339,9 @@ void StatesEditorView::removeState(int nodeId)
NodeListProperty parentProperty = stateNode.parentProperty().toNodeListProperty();
+ if (modelState.isDefault())
+ m_statesEditorModel->resetDefaultState();
+
if (parentProperty.count() <= 1) {
setCurrentState(baseState());
} else if (parentProperty.isValid()) {
@@ -164,106 +359,97 @@ void StatesEditorView::removeState(int nodeId)
}
}
-void StatesEditorView::synchonizeCurrentStateFromWidget()
+void StatesEditorView::resetModel()
{
- if (!model())
- return;
-
- if (m_block)
+ if (m_bulkChange) {
+ m_modelDirty = true;
return;
+ }
- int internalId = m_statesEditorWidget->currentStateInternalId();
+ if (m_statesEditorModel)
+ m_statesEditorModel->reset();
- if (internalId > 0 && hasModelNodeForInternalId(internalId)) {
- ModelNode node = modelNodeForInternalId(internalId);
- QmlModelState modelState(node);
- if (modelState.isValid() && modelState != currentState())
- setCurrentState(modelState);
- } else {
- setCurrentState(baseState());
+ if (m_statesEditorWidget) {
+ if (currentState().isBaseState())
+ m_statesEditorWidget->setCurrentStateInternalId(0);
+ else
+ m_statesEditorWidget->setCurrentStateInternalId(currentState().modelNode().internalId());
}
+
+ m_modelDirty = false;
}
-void StatesEditorView::createNewState()
+void StatesEditorView::resetPropertyChangesModels()
{
- if (currentState().isBaseState())
- addState();
- else
- duplicateCurrentState();
+ if (m_bulkChange) {
+ m_propertyChangesDirty = true;
+ return;
+ }
+
+ std::for_each(m_propertyChangedModels.begin(),
+ m_propertyChangedModels.end(),
+ [](PropertyChangesModel *model) { model->reset(); });
+
+ m_propertyChangesDirty = false;
}
-void StatesEditorView::addState()
+void StatesEditorView::resetExtend()
{
- // can happen when root node is e.g. a ListModel
- if (!QmlVisualNode::isValidQmlVisualNode(acitveStatesGroupNode())
- && m_activeStatesGroupNode.type() != "QtQuick.StateGroup")
+ if (m_bulkChange) {
+ m_extendDirty = true;
return;
+ }
- QmlDesignerPlugin::emitUsageStatistics(Constants::EVENT_STATE_ADDED);
+ m_statesEditorModel->evaluateExtend();
- QStringList modelStateNames = activeStateGroup().names();
+ m_extendDirty = false;
+}
- QString newStateName;
- int index = 1;
- while (true) {
- newStateName = QString(QStringLiteral("State%1")).arg(index++);
- if (!modelStateNames.contains(newStateName))
- break;
+void StatesEditorView::resetStateGroups()
+{
+ if (m_bulkChange) {
+ m_stateGroupsDirty = true;
+ return;
}
- executeInTransaction("addState", [this, newStateName]() {
- acitveStatesGroupNode().validId();
+ emit m_statesEditorModel->stateGroupsChanged();
- ModelNode newState = activeStateGroup().addState(newStateName);
- setCurrentState(newState);
- });
+ m_stateGroupsDirty = false;
}
-void StatesEditorView::resetModel()
+void StatesEditorView::checkForStatesAvailability()
{
- if (m_statesEditorModel)
- m_statesEditorModel->reset();
-
if (m_statesEditorWidget) {
- if (currentState().isBaseState())
- m_statesEditorWidget->setCurrentStateInternalId(0);
- else
- m_statesEditorWidget->setCurrentStateInternalId(currentState().modelNode().internalId());
+ const bool isVisual = activeStatesGroupNode().metaInfo().isBasedOn(
+ model()->qtQuickItemMetaInfo(), model()->qtQuick3DNodeMetaInfo());
+ const bool isRoot = activeStatesGroupNode().isRootNode();
+ m_statesEditorModel->setCanAddNewStates(isVisual || !isRoot);
}
}
-void StatesEditorView::duplicateCurrentState()
+void StatesEditorView::beginBulkChange()
{
- QmlModelState state = currentState();
+ m_bulkChange = true;
+}
- Q_ASSERT(!state.isBaseState());
+void StatesEditorView::endBulkChange()
+{
+ if (!m_bulkChange)
+ return;
- QString newName = state.name();
+ m_bulkChange = false;
- // Strip out numbers at the end of the string
- QRegularExpression regEx(QLatin1String("[0-9]+$"));
- const QRegularExpressionMatch match = regEx.match(newName);
- if (match.hasMatch() && (match.capturedStart() + match.capturedLength() == newName.length()))
- newName = newName.left(match.capturedStart());
+ if (m_modelDirty)
+ resetModel();
- int i = 1;
- QStringList stateNames = activeStateGroup().names();
- while (stateNames.contains(newName + QString::number(i)))
- i++;
- const QString newStateName = newName + QString::number(i);
+ if (m_propertyChangesDirty)
+ resetPropertyChangesModels();
- executeInTransaction("addState", [this, newStateName, state]() {
- QmlModelState newState = state.duplicate(newStateName);
- setCurrentState(newState);
- });
-}
+ if (m_extendDirty)
+ resetExtend();
-void StatesEditorView::checkForStatesAvailability()
-{
- if (m_statesEditorWidget) {
- const bool isVisual = QmlVisualNode::isValidQmlVisualNode(acitveStatesGroupNode());
- m_statesEditorWidget->showAddNewStatesButton(isVisual);
- }
+ if (m_stateGroupsDirty)
+ resetStateGroups();
}
void StatesEditorView::setCurrentState(const QmlModelState &state)
@@ -282,7 +468,7 @@ QmlModelState StatesEditorView::baseState() const
QmlModelStateGroup StatesEditorView::activeStateGroup() const
{
- return QmlModelStateGroup(acitveStatesGroupNode());
+ return QmlModelStateGroup(activeStatesGroupNode());
}
bool StatesEditorView::validStateName(const QString &name) const
@@ -297,6 +483,35 @@ bool StatesEditorView::validStateName(const QString &name) const
return true;
}
+bool StatesEditorView::hasExtend() const
+{
+ if (!model())
+ return false;
+
+ const QList<QmlModelState> modelStates = activeStateGroup().allStates();
+ for (const QmlModelState &state : modelStates) {
+ if (state.hasExtend())
+ return true;
+ }
+ return false;
+}
+
+QStringList StatesEditorView::extendedStates() const
+{
+ if (!model())
+ return QStringList();
+
+ QStringList states;
+
+ const QList<QmlModelState> modelStates = activeStateGroup().allStates();
+ for (const QmlModelState &state : modelStates) {
+ if (state.hasExtend())
+ states.append(state.extend());
+ }
+ states.removeDuplicates();
+ return states;
+}
+
QString StatesEditorView::currentStateName() const
{
return currentState().isValid() ? currentState().name() : QString();
@@ -305,20 +520,33 @@ QString StatesEditorView::currentStateName() const
void StatesEditorView::renameState(int internalNodeId, const QString &newName)
{
if (hasModelNodeForInternalId(internalNodeId)) {
- QmlModelState state(modelNodeForInternalId(internalNodeId));
+ QmlModelState renamedState(modelNodeForInternalId(internalNodeId));
try {
- if (state.isValid() && state.name() != newName) {
- // Jump to base state for the change
- QmlModelState oldState = currentState();
- setCurrentState(baseState());
- const bool updateDefault = state.isDefault();
-
- state.setName(newName.trimmed());
-
- if (updateDefault)
- state.setAsDefault();
-
- setCurrentState(oldState);
+ if (renamedState.isValid() && renamedState.name() != newName) {
+ executeInTransaction("renameState", [this, &renamedState, &newName]() {
+ // Jump to base state for the change
+ QmlModelState oldState = currentState();
+ setCurrentState(baseState());
+ const bool updateDefault = renamedState.isDefault();
+
+ // If state is extended rename all references
+ QList<QmlModelState> states;
+ const QList<QmlModelState> modelStates = activeStateGroup().allStates();
+ for (const QmlModelState &state : modelStates) {
+ if (state.hasExtend() && state.extend() == renamedState.name())
+ states.append(state);
+ }
+
+ renamedState.setName(newName.trimmed());
+
+ for (QmlModelState &state : states)
+ state.setExtend(newName.trimmed());
+
+ if (updateDefault)
+ renamedState.setAsDefault();
+
+ setCurrentState(oldState);
+ });
}
} catch (const RewritingException &e) {
e.showException();
@@ -357,7 +585,9 @@ void StatesEditorView::resetWhenCondition(int internalNodeId)
if (hasModelNodeForInternalId(internalNodeId)) {
QmlModelState state(modelNodeForInternalId(internalNodeId));
try {
- state.modelNode().removeProperty("when");
+ if (state.isValid() && state.modelNode().hasProperty("when"))
+ state.modelNode().removeProperty("when");
+
} catch (const RewritingException &e) {
e.showException();
}
@@ -393,8 +623,8 @@ void StatesEditorView::resetDefaultState()
const QScopeGuard cleanup([&] { m_block = false; });
try {
- if (acitveStatesGroupNode().hasProperty("state"))
- acitveStatesGroupNode().removeProperty("state");
+ if (activeStatesGroupNode().hasProperty("state"))
+ activeStatesGroupNode().removeProperty("state");
} catch (const RewritingException &e) {
e.showException();
@@ -403,7 +633,7 @@ void StatesEditorView::resetDefaultState()
bool StatesEditorView::hasDefaultState() const
{
- return acitveStatesGroupNode().hasProperty("state");
+ return activeStatesGroupNode().hasProperty("state");
}
void StatesEditorView::setAnnotation(int internalNodeId)
@@ -418,7 +648,9 @@ void StatesEditorView::setAnnotation(int internalNodeId)
QmlModelState state(modelNodeForInternalId(internalNodeId));
try {
if (state.isValid()) {
- if (ModelNode modelNode = state.modelNode()) {
+ ModelNode modelNode = state.modelNode();
+
+ if (modelNode.isValid()) {
if (!m_editor)
m_editor = new AnnotationEditor(this);
@@ -444,9 +676,8 @@ void StatesEditorView::removeAnnotation(int internalNodeId)
if (hasModelNodeForInternalId(internalNodeId)) {
QmlModelState state(modelNodeForInternalId(internalNodeId));
try {
- if (state.isValid()) {
+ if (state.isValid())
state.removeAnnotation();
- }
} catch (const RewritingException &e) {
e.showException();
@@ -456,11 +687,13 @@ void StatesEditorView::removeAnnotation(int internalNodeId)
bool StatesEditorView::hasAnnotation(int internalNodeId) const
{
+ if (!model())
+ return false;
+
if (hasModelNodeForInternalId(internalNodeId)) {
QmlModelState state(modelNodeForInternalId(internalNodeId));
- if (state.isValid()) {
+ if (state.isValid())
return state.hasAnnotation();
- }
}
return false;
@@ -471,7 +704,7 @@ void StatesEditorView::modelAttached(Model *model)
if (model == AbstractView::model())
return;
- Q_ASSERT(model);
+ QTC_ASSERT(model, return );
AbstractView::modelAttached(model);
m_activeStatesGroupNode = rootModelNode();
@@ -482,6 +715,10 @@ void StatesEditorView::modelAttached(Model *model)
checkForStatesAvailability();
resetModel();
+ resetStateGroups();
+
+ emit m_statesEditorModel->activeStateGroupChanged();
+ emit m_statesEditorModel->activeStateGroupIndexChanged();
}
void StatesEditorView::modelAboutToBeDetached(Model *model)
@@ -493,12 +730,17 @@ void StatesEditorView::modelAboutToBeDetached(Model *model)
void StatesEditorView::propertiesRemoved(const QList<AbstractProperty> &propertyList)
{
for (const AbstractProperty &property : propertyList) {
- if (property.name() == "states"
- && property.parentModelNode() == activeStateGroup().modelNode())
+ if (property.name() == "states" && property.parentModelNode() == activeStateGroup().modelNode())
resetModel();
- if (property.name() == "when"
+ if ((property.name() == "when" || property.name() == "name")
&& QmlModelState::isValidQmlModelState(property.parentModelNode()))
resetModel();
+ if (property.name() == "extend")
+ resetExtend();
+ if (property.parentModelNode().simplifiedTypeName() == "PropertyChanges"
+ || (property.name() == "changes"
+ && property.parentModelNode().simplifiedTypeName() == "State"))
+ resetPropertyChangesModels();
}
}
@@ -512,16 +754,38 @@ void StatesEditorView::nodeAboutToBeRemoved(const ModelNode &removedNode)
}
if (currentState().isValid() && removedNode == currentState())
setCurrentState(baseState());
+
+ if (removedNode.simplifiedTypeName() == "PropertyChanges")
+ m_propertyChangesRemoved = true;
+
+ if (removedNode.simplifiedTypeName() == "StateGroup") {
+ if (removedNode == activeStatesGroupNode())
+ setActiveStatesGroupNode(rootModelNode());
+
+ m_stateGroupRemoved = true;
+ }
}
void StatesEditorView::nodeRemoved(const ModelNode & /*removedNode*/,
const NodeAbstractProperty &parentProperty,
PropertyChangeFlags /*propertyChange*/)
{
- if (parentProperty.isValid() && parentProperty.parentModelNode() == activeStateGroup().modelNode()
+ if (parentProperty.isValid()
+ && parentProperty.parentModelNode() == activeStateGroup().modelNode()
&& parentProperty.name() == "states") {
m_statesEditorModel->removeState(m_lastIndex);
m_lastIndex = -1;
+ resetModel();
+ }
+
+ if (m_propertyChangesRemoved) {
+ m_propertyChangesRemoved = false;
+ resetPropertyChangesModels();
+ }
+
+ if (m_stateGroupRemoved) {
+ m_stateGroupRemoved = false;
+ resetStateGroups();
}
}
@@ -534,6 +798,9 @@ void StatesEditorView::nodeAboutToBeReparented(const ModelNode &node,
&& oldPropertyParent.parentModelNode() == activeStateGroup().modelNode()
&& oldPropertyParent.name() == "states")
m_lastIndex = oldPropertyParent.indexOf(node);
+
+ if (node.simplifiedTypeName() == "StateGroup")
+ resetStateGroups();
}
void StatesEditorView::nodeReparented(const ModelNode &node,
@@ -543,10 +810,11 @@ void StatesEditorView::nodeReparented(const ModelNode &node,
{
if (oldPropertyParent.isValid()
&& oldPropertyParent.parentModelNode() == activeStateGroup().modelNode()
- && oldPropertyParent.name() == "states")
+ && oldPropertyParent.name() == "states") {
m_statesEditorModel->removeState(m_lastIndex);
-
- m_lastIndex = -1;
+ resetModel();
+ m_lastIndex = -1;
+ }
if (newPropertyParent.isValid()
&& newPropertyParent.parentModelNode() == activeStateGroup().modelNode()
@@ -554,23 +822,31 @@ void StatesEditorView::nodeReparented(const ModelNode &node,
int index = newPropertyParent.indexOf(node);
m_statesEditorModel->insertState(index);
}
+
+ if (node.simplifiedTypeName() == "PropertyChanges")
+ resetPropertyChangesModels();
}
void StatesEditorView::nodeOrderChanged(const NodeListProperty &listProperty)
{
+ if (m_block)
+ return;
+
if (listProperty.isValid() && listProperty.parentModelNode() == activeStateGroup().modelNode()
&& listProperty.name() == "states")
resetModel();
}
-void StatesEditorView::bindingPropertiesChanged(
- const QList<BindingProperty> &propertyList,
- [[maybe_unused]] AbstractView::PropertyChangeFlags propertyChange)
+void StatesEditorView::bindingPropertiesChanged(const QList<BindingProperty> &propertyList, AbstractView::PropertyChangeFlags propertyChange)
{
+ Q_UNUSED(propertyChange)
+
for (const BindingProperty &property : propertyList) {
if (property.name() == "when"
&& QmlModelState::isValidQmlModelState(property.parentModelNode()))
resetModel();
+ if (property.parentModelNode().simplifiedTypeName() == "PropertyChanges")
+ resetPropertyChangesModels();
}
}
@@ -590,9 +866,36 @@ void StatesEditorView::variantPropertiesChanged(const QList<VariantProperty> &pr
else if (property.name() == "state"
&& property.parentModelNode() == activeStateGroup().modelNode())
resetModel();
+ else if (property.name() == "extend")
+ resetExtend();
+
+ if (property.parentModelNode().simplifiedTypeName() == "PropertyChanges")
+ resetPropertyChangesModels();
}
}
+void StatesEditorView::customNotification(const AbstractView * /*view*/,
+ const QString &identifier,
+ const QList<ModelNode> & /*nodeList*/,
+ const QList<QVariant> & /*data*/)
+{
+ if (identifier == StartRewriterAmend)
+ beginBulkChange();
+
+ if (identifier == EndRewriterAmend)
+ endBulkChange();
+}
+
+void StatesEditorView::rewriterBeginTransaction()
+{
+ beginBulkChange();
+}
+
+void StatesEditorView::rewriterEndTransaction()
+{
+ endBulkChange();
+}
+
void StatesEditorView::currentStateChanged(const ModelNode &node)
{
QmlModelState newQmlModelState(node);
@@ -627,4 +930,20 @@ void StatesEditorView::instancesPreviewImageChanged(const QVector<ModelNode> &no
m_statesEditorModel->updateState(minimumIndex, maximumIndex);
}
+void StatesEditorView::moveStates(int from, int to)
+{
+ if (m_block)
+ return;
+
+ m_block = true;
+ auto guard = qScopeGuard([&]() { m_block = false; });
+
+ if (!activeStatesGroupNode().hasNodeListProperty("states"))
+ return;
+
+ executeInTransaction("moveState", [this, from, to]() {
+ activeStatesGroupNode().nodeListProperty("states").slide(from - 1, to - 1);
+ });
+}
+
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.h b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.h
index 52329b940d..502e5d2ac6 100644
--- a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.h
+++ b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.h
@@ -1,5 +1,5 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// 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
@@ -7,14 +7,17 @@
#include <qmlstate.h>
+#include <QSet>
+
namespace QmlDesigner {
+class AnnotationEditor;
+
class StatesEditorModel;
class StatesEditorWidget;
-class AnnotationEditor;
+class PropertyChangesModel;
-class StatesEditorView : public AbstractView
-{
+class StatesEditorView : public AbstractView {
Q_OBJECT
public:
@@ -31,11 +34,15 @@ public:
void removeAnnotation(int internalNodeId);
bool hasAnnotation(int internalNodeId) const;
bool validStateName(const QString &name) const;
+ bool hasExtend() const;
+ QStringList extendedStates() const;
QString currentStateName() const;
void setCurrentState(const QmlModelState &state);
QmlModelState baseState() const;
QmlModelStateGroup activeStateGroup() const;
+ void moveStates(int from, int to);
+
// AbstractView
void modelAttached(Model *model) override;
void modelAboutToBeDetached(Model *model) override;
@@ -58,6 +65,13 @@ public:
void variantPropertiesChanged(const QList<VariantProperty> &propertyList,
PropertyChangeFlags propertyChange) override;
+ void customNotification(const AbstractView *view,
+ const QString &identifier,
+ const QList<ModelNode> &nodeList,
+ const QList<QVariant> &data) override;
+ void rewriterBeginTransaction() override;
+ void rewriterEndTransaction() override;
+
// AbstractView
void currentStateChanged(const ModelNode &node) override;
@@ -67,21 +81,33 @@ public:
void rootNodeTypeChanged(const QString &type, int majorVersion, int minorVersion) override;
- ModelNode acitveStatesGroupNode() const;
- void setAcitveStatesGroupNode(const ModelNode &modelNode);
+ ModelNode activeStatesGroupNode() const;
+ void setActiveStatesGroupNode(const ModelNode &modelNode);
+
+ int activeStatesGroupIndex() const;
+ void setActiveStatesGroupIndex(int index);
+
+ void registerPropertyChangesModel(PropertyChangesModel *model);
+ void deregisterPropertyChangesModel(PropertyChangesModel *model);
public slots:
void synchonizeCurrentStateFromWidget();
void createNewState();
+ void cloneState(int nodeId);
+ void extendState(int nodeId);
void removeState(int nodeId);
private:
- StatesEditorWidget *statesEditorWidget() const;
void resetModel();
- void addState();
- void duplicateCurrentState();
+ void resetPropertyChangesModels();
+ void resetExtend();
+ void resetStateGroups();
+
void checkForStatesAvailability();
+ void beginBulkChange();
+ void endBulkChange();
+
private:
QPointer<StatesEditorModel> m_statesEditorModel;
QPointer<StatesEditorWidget> m_statesEditorWidget;
@@ -89,6 +115,18 @@ private:
bool m_block = false;
QPointer<AnnotationEditor> m_editor;
ModelNode m_activeStatesGroupNode;
+
+ bool m_propertyChangesRemoved = false;
+ bool m_stateGroupRemoved = false;
+
+ bool m_bulkChange = false;
+
+ bool m_modelDirty = false;
+ bool m_extendDirty = false;
+ bool m_propertyChangesDirty = false;
+ bool m_stateGroupsDirty = false;
+
+ QSet<PropertyChangesModel *> m_propertyChangedModels;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.cpp b/src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.cpp
index 5c12772752..d0d5e88f5c 100644
--- a/src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.cpp
+++ b/src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.cpp
@@ -1,10 +1,10 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// 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 "stateseditorwidget.h"
-#include "stateseditorimageprovider.h"
#include "stateseditormodel.h"
#include "stateseditorview.h"
+#include "stateseditorimageprovider.h"
#include <designersettings.h>
#include <theme.h>
@@ -13,10 +13,9 @@
#include <invalidqmlsourceexception.h>
-#include <coreplugin/icore.h>
#include <coreplugin/messagebox.h>
+#include <coreplugin/icore.h>
-#include <utils/environment.h>
#include <utils/qtcassert.h>
#include <utils/stylehelper.h>
@@ -31,14 +30,16 @@
#include <QQmlEngine>
#include <QQuickItem>
-enum { debug = false };
+enum {
+ debug = false
+};
namespace QmlDesigner {
static QString propertyEditorResourcesPath()
{
#ifdef SHARE_QML_PATH
- if (Utils::qtcEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
+ if (qEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
return QLatin1String(SHARE_QML_PATH) + "/propertyEditorQmlSources";
#endif
return Core::ICore::resourcePath("qmldesigner/propertyEditorQmlSources").toString();
@@ -63,11 +64,6 @@ void StatesEditorWidget::setNodeInstanceView(const NodeInstanceView *nodeInstanc
m_imageProvider->setNodeInstanceView(nodeInstanceView);
}
-void StatesEditorWidget::showAddNewStatesButton(bool showAddNewStatesButton)
-{
- rootContext()->setContextProperty(QLatin1String("canAddNewStates"), showAddNewStatesButton);
-}
-
StatesEditorWidget::StatesEditorWidget(StatesEditorView *statesEditorView,
StatesEditorModel *statesEditorModel)
: m_statesEditorView(statesEditorView)
@@ -80,21 +76,23 @@ StatesEditorWidget::StatesEditorWidget(StatesEditorView *statesEditorView,
engine()->addImageProvider(QStringLiteral("qmldesigner_stateseditor"), m_imageProvider);
engine()->addImportPath(qmlSourcesPath());
engine()->addImportPath(propertyEditorResourcesPath() + "/imports");
+ engine()->addImportPath(qmlSourcesPath() + "/imports");
- m_qmlSourceUpdateShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_F4), this);
+ m_qmlSourceUpdateShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_F10), this);
connect(m_qmlSourceUpdateShortcut, &QShortcut::activated, this, &StatesEditorWidget::reloadQmlSource);
+ quickWidget()->setObjectName(Constants::OBJECT_NAME_STATES_EDITOR);
setResizeMode(QQuickWidget::SizeRootObjectToView);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
- rootContext()->setContextProperties(
- QVector<QQmlContext::PropertyPair>{{{"statesEditorModel"},
- QVariant::fromValue(statesEditorModel)},
- {{"canAddNewStates"}, true}});
+ auto map = registerPropertyMap("StatesEditorBackend");
+ map->setProperties({{"statesEditorModel", QVariant::fromValue(statesEditorModel)}});
Theme::setupTheme(engine());
setWindowTitle(tr("States", "Title of Editor widget"));
+ setMinimumWidth(195);
+ setMinimumHeight(195);
// init the first load of the QML UI elements
reloadQmlSource();
@@ -105,16 +103,17 @@ StatesEditorWidget::~StatesEditorWidget() = default;
QString StatesEditorWidget::qmlSourcesPath()
{
#ifdef SHARE_QML_PATH
- if (Utils::qtcEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
- return QLatin1String(SHARE_QML_PATH) + "/statesEditorQmlSources";
+ if (qEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
+ return QLatin1String(SHARE_QML_PATH) + "/stateseditor";
#endif
- return Core::ICore::resourcePath("qmldesigner/statesEditorQmlSources").toString();
+ return Core::ICore::resourcePath("qmldesigner/stateseditor").toString();
}
void StatesEditorWidget::showEvent(QShowEvent *event)
{
StudioQuickWidget::showEvent(event);
update();
+ QMetaObject::invokeMethod(rootObject(), "showEvent");
}
void StatesEditorWidget::focusOutEvent(QFocusEvent *focusEvent)
@@ -132,9 +131,8 @@ void StatesEditorWidget::focusInEvent(QFocusEvent *focusEvent)
void StatesEditorWidget::reloadQmlSource()
{
- QString statesListQmlFilePath = qmlSourcesPath() + QStringLiteral("/StatesList.qml");
- QTC_ASSERT(QFileInfo::exists(statesListQmlFilePath), return);
- engine()->clearComponentCache();
+ QString statesListQmlFilePath = qmlSourcesPath() + QStringLiteral("/Main.qml");
+ QTC_ASSERT(QFileInfo::exists(statesListQmlFilePath), return );
setSource(QUrl::fromLocalFile(statesListQmlFilePath));
if (!rootObject()) {
@@ -152,8 +150,19 @@ void StatesEditorWidget::reloadQmlSource()
SIGNAL(currentStateInternalIdChanged()),
m_statesEditorView.data(),
SLOT(synchonizeCurrentStateFromWidget()));
- connect(rootObject(), SIGNAL(createNewState()), m_statesEditorView.data(), SLOT(createNewState()));
- connect(rootObject(), SIGNAL(deleteState(int)), m_statesEditorView.data(), SLOT(removeState(int)));
+ connect(rootObject(),
+ SIGNAL(createNewState()),
+ m_statesEditorView.data(),
+ SLOT(createNewState()));
+ connect(rootObject(), SIGNAL(cloneState(int)), m_statesEditorView.data(), SLOT(cloneState(int)));
+ connect(rootObject(),
+ SIGNAL(extendState(int)),
+ m_statesEditorView.data(),
+ SLOT(extendState(int)));
+ connect(rootObject(),
+ SIGNAL(deleteState(int)),
+ m_statesEditorView.data(),
+ SLOT(removeState(int)));
m_statesEditorView.data()->synchonizeCurrentStateFromWidget();
}
diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.h b/src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.h
index fb83872a13..395cdbfac2 100644
--- a/src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.h
+++ b/src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.h
@@ -1,5 +1,5 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// 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
@@ -15,13 +15,12 @@ QT_END_NAMESPACE
namespace QmlDesigner {
+class NodeInstanceView;
+
class StatesEditorModel;
class StatesEditorView;
-class NodeInstanceView;
-namespace Internal {
-class StatesEditorImageProvider;
-}
+namespace Internal { class StatesEditorImageProvider; }
class StatesEditorWidget : public StudioQuickWidget
{
@@ -35,8 +34,6 @@ public:
void setCurrentStateInternalId(int internalId);
void setNodeInstanceView(const NodeInstanceView *nodeInstanceView);
- void showAddNewStatesButton(bool showAddNewStatesButton);
-
static QString qmlSourcesPath();
protected:
diff --git a/src/plugins/qmldesigner/components/stateseditornew/stateseditorimageprovider.cpp b/src/plugins/qmldesigner/components/stateseditornew/stateseditorimageprovider.cpp
deleted file mode 100644
index d2d9ebdf4c..0000000000
--- a/src/plugins/qmldesigner/components/stateseditornew/stateseditorimageprovider.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2022 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "stateseditorimageprovider.h"
-#include "nodeinstanceview.h"
-
-#include <QDebug>
-
-namespace QmlDesigner {
-namespace Experimental {
-namespace Internal {
-
-StatesEditorImageProvider::StatesEditorImageProvider()
- : QQuickImageProvider(QQuickImageProvider::Image)
-{
-}
-
-QImage StatesEditorImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
-{
- QImage image;
-
- bool nodeInstanceViewIsDetached = m_nodeInstanceView.isNull() || !m_nodeInstanceView->model();
- if (!nodeInstanceViewIsDetached) {
- QString imageId = id.split(QLatin1Char('-')).constFirst();
- if (imageId == QLatin1String("baseState")) {
- image = m_nodeInstanceView->statePreviewImage(m_nodeInstanceView->rootModelNode());
- } else {
- bool canBeConverted;
- int instanceId = imageId.toInt(&canBeConverted);
- if (canBeConverted && m_nodeInstanceView->hasModelNodeForInternalId(instanceId)) {
- image = m_nodeInstanceView->statePreviewImage(m_nodeInstanceView->modelNodeForInternalId(instanceId));
- }
- }
- }
-
- if (image.isNull()) {
- //creating white QImage
- QSize newSize = requestedSize;
- if (newSize.isEmpty())
- newSize = QSize (100, 100);
-
- QImage image(newSize, QImage::Format_ARGB32);
- image.fill(0xFFFFFFFF);
- return image;
- }
-
- *size = image.size();
-
- return image;
-}
-
-void StatesEditorImageProvider::setNodeInstanceView(const NodeInstanceView *nodeInstanceView)
-{
- m_nodeInstanceView = nodeInstanceView;
-}
-
-} // namespace Internal
-} // namespace Experimental
-} // namespace QmlDesigner
-
diff --git a/src/plugins/qmldesigner/components/stateseditornew/stateseditorimageprovider.h b/src/plugins/qmldesigner/components/stateseditornew/stateseditorimageprovider.h
deleted file mode 100644
index c89e9ea723..0000000000
--- a/src/plugins/qmldesigner/components/stateseditornew/stateseditorimageprovider.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2022 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include"abstractview.h"
-
-#include <QQuickImageProvider>
-#include <QPointer>
-
-namespace QmlDesigner {
-namespace Experimental {
-namespace Internal {
-
-class StatesEditorView;
-
-class StatesEditorImageProvider : public QQuickImageProvider
-{
-public:
- StatesEditorImageProvider();
-
- QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize) override;
-
- void setNodeInstanceView(const NodeInstanceView *nodeInstanceView);
-
-private:
- QPointer<const NodeInstanceView> m_nodeInstanceView;
-};
-
-} // namespace Internal
-} // namespace Experimental
-} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/stateseditornew/stateseditormodel.cpp b/src/plugins/qmldesigner/components/stateseditornew/stateseditormodel.cpp
deleted file mode 100644
index 398bdfb6f6..0000000000
--- a/src/plugins/qmldesigner/components/stateseditornew/stateseditormodel.cpp
+++ /dev/null
@@ -1,462 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2022 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "stateseditormodel.h"
-#include "stateseditorview.h"
-
-#include <bindingproperty.h>
-#include <modelnode.h>
-#include <nodelistproperty.h>
-#include <nodemetainfo.h>
-#include <rewriterview.h>
-#include <variantproperty.h>
-
-#include <coreplugin/icore.h>
-#include <coreplugin/messagebox.h>
-
-#include <utils/algorithm.h>
-#include <utils/qtcassert.h>
-
-#include <QDebug>
-#include <QWidget>
-
-enum {
- debug = false
-};
-
-namespace QmlDesigner {
-namespace Experimental {
-
-StatesEditorModel::StatesEditorModel(StatesEditorView *view)
- : QAbstractListModel(view)
- , m_statesEditorView(view)
- , m_hasExtend(false)
- , m_extendedStates()
-{
- QObject::connect(this, &StatesEditorModel::dataChanged, [this]() { emit baseStateChanged(); });
-}
-
-int StatesEditorModel::count() const
-{
- return rowCount();
-}
-
-QModelIndex StatesEditorModel::index(int row, int column, const QModelIndex &parent) const
-{
- if (m_statesEditorView.isNull())
- return {};
-
- int internalNodeId = 0;
- if (row > 0)
- internalNodeId = m_statesEditorView->activeStatesGroupNode()
- .nodeListProperty("states")
- .at(row - 1)
- .internalId();
-
- return hasIndex(row, column, parent) ? createIndex(row, column, internalNodeId) : QModelIndex();
-}
-
-int StatesEditorModel::rowCount(const QModelIndex &parent) const
-{
- if (parent.isValid() || m_statesEditorView.isNull() || !m_statesEditorView->model())
- return 0;
-
- if (!m_statesEditorView->activeStatesGroupNode().hasNodeListProperty("states"))
- return 1; // base state
-
- return m_statesEditorView->activeStatesGroupNode().nodeListProperty("states").count() + 1;
-}
-
-void StatesEditorModel::reset()
-{
- QAbstractListModel::beginResetModel();
- QAbstractListModel::endResetModel();
-
- evaluateExtend();
- emit baseStateChanged();
-}
-
-QVariant StatesEditorModel::data(const QModelIndex &index, int role) const
-{
- if (index.parent().isValid() || index.column() != 0 || m_statesEditorView.isNull()
- || !m_statesEditorView->hasModelNodeForInternalId(index.internalId()))
- return QVariant();
-
- ModelNode stateNode;
-
- if (index.internalId() > 0)
- stateNode = m_statesEditorView->modelNodeForInternalId(index.internalId());
-
- switch (role) {
- case StateNameRole: {
- if (index.row() == 0) {
- return tr("base state", "Implicit default state");
- } else {
- if (stateNode.hasVariantProperty("name"))
- return stateNode.variantProperty("name").value();
- else
- return QVariant();
- }
- }
-
- case StateImageSourceRole: {
- static int randomNumber = 0;
- randomNumber++;
- if (index.row() == 0)
- return QString("image://qmldesigner_stateseditor/baseState-%1").arg(randomNumber);
- else
- return QString("image://qmldesigner_stateseditor/%1-%2").arg(index.internalId()).arg(randomNumber);
- }
-
- case InternalNodeId:
- return index.internalId();
-
- case HasWhenCondition:
- return stateNode.isValid() && stateNode.hasProperty("when");
-
- case WhenConditionString: {
- if (stateNode.isValid() && stateNode.hasBindingProperty("when"))
- return stateNode.bindingProperty("when").expression();
- else
- return QString();
- }
-
- case IsDefault: {
- QmlModelState modelState(stateNode);
- if (modelState.isValid())
- return modelState.isDefault();
- return false;
- }
-
- case ModelHasDefaultState:
- return hasDefaultState();
-
- case HasExtend:
- return stateNode.isValid() && stateNode.hasProperty("extend");
-
- case ExtendString: {
- if (stateNode.isValid() && stateNode.hasVariantProperty("extend"))
- return stateNode.variantProperty("extend").value();
- else
- return QString();
- }
- }
-
- return QVariant();
-}
-
-QHash<int, QByteArray> StatesEditorModel::roleNames() const
-{
- static QHash<int, QByteArray> roleNames{{StateNameRole, "stateName"},
- {StateImageSourceRole, "stateImageSource"},
- {InternalNodeId, "internalNodeId"},
- {HasWhenCondition, "hasWhenCondition"},
- {WhenConditionString, "whenConditionString"},
- {IsDefault, "isDefault"},
- {ModelHasDefaultState, "modelHasDefaultState"},
- {HasExtend, "hasExtend"},
- {ExtendString, "extendString"}};
- return roleNames;
-}
-
-void StatesEditorModel::insertState(int stateIndex)
-{
- if (stateIndex >= 0) {
- const int updateIndex = stateIndex + 1;
- beginInsertRows(QModelIndex(), updateIndex, updateIndex);
- endInsertRows();
-
- emit dataChanged(index(updateIndex, 0), index(updateIndex, 0));
- }
-}
-
-void StatesEditorModel::updateState(int beginIndex, int endIndex)
-{
- if (beginIndex >= 0 && endIndex >= 0)
- emit dataChanged(index(beginIndex, 0), index(endIndex, 0));
-}
-
-void StatesEditorModel::removeState(int stateIndex)
-{
- if (stateIndex >= 0) {
- beginRemoveRows(QModelIndex(), 0, stateIndex);
- endRemoveRows();
- }
-}
-
-void StatesEditorModel::renameState(int internalNodeId, const QString &newName)
-{
- if (newName == m_statesEditorView->currentStateName())
- return;
-
- if (newName.isEmpty() ||! m_statesEditorView->validStateName(newName)) {
- QTimer::singleShot(0, this, [newName] {
- Core::AsynchronousMessageBox::warning(
- tr("Invalid state name"),
- newName.isEmpty() ?
- tr("The empty string as a name is reserved for the base state.") :
- tr("Name already used in another state"));
- });
- reset();
- } else {
- m_statesEditorView->renameState(internalNodeId, newName);
- }
-}
-
-void StatesEditorModel::setWhenCondition(int internalNodeId, const QString &condition)
-{
- m_statesEditorView->setWhenCondition(internalNodeId, condition);
-}
-
-void StatesEditorModel::resetWhenCondition(int internalNodeId)
-{
- m_statesEditorView->resetWhenCondition(internalNodeId);
-}
-
-QStringList StatesEditorModel::autoComplete(const QString &text, int pos, bool explicitComplete)
-{
- Model *model = m_statesEditorView->model();
- if (model && model->rewriterView())
- return model->rewriterView()->autoComplete(text, pos, explicitComplete);
-
- return QStringList();
-}
-
-QVariant StatesEditorModel::stateModelNode(int internalNodeId)
-{
- if (!m_statesEditorView->model())
- return QVariant();
-
- ModelNode node = m_statesEditorView->modelNodeForInternalId(internalNodeId);
-
- return QVariant::fromValue(m_statesEditorView->modelNodeForInternalId(internalNodeId));
-}
-
-void StatesEditorModel::setStateAsDefault(int internalNodeId)
-{
- m_statesEditorView->setStateAsDefault(internalNodeId);
-}
-
-void StatesEditorModel::resetDefaultState()
-{
- m_statesEditorView->resetDefaultState();
-}
-
-bool StatesEditorModel::hasDefaultState() const
-{
- return m_statesEditorView->hasDefaultState();
-}
-
-void StatesEditorModel::setAnnotation(int internalNodeId)
-{
- m_statesEditorView->setAnnotation(internalNodeId);
-}
-
-void StatesEditorModel::removeAnnotation(int internalNodeId)
-{
- m_statesEditorView->removeAnnotation(internalNodeId);
-}
-
-bool StatesEditorModel::hasAnnotation(int internalNodeId) const
-{
- return m_statesEditorView->hasAnnotation(internalNodeId);
-}
-
-QStringList StatesEditorModel::stateGroups() const
-{
- if (!m_statesEditorView->isAttached())
- return {};
-
- const auto groupMetaInfo = m_statesEditorView->model()->qtQuickStateGroupMetaInfo();
-
- auto stateGroups = Utils::transform(m_statesEditorView->allModelNodesOfType(groupMetaInfo),
- [](const ModelNode &node) { return node.displayName(); });
- stateGroups.prepend(tr("Default"));
- return stateGroups;
-}
-
-QString StatesEditorModel::activeStateGroup() const
-{
- if (auto stateGroup = m_statesEditorView->activeStatesGroupNode())
- return stateGroup.displayName();
-
- return {};
-}
-
-void StatesEditorModel::setActiveStateGroup(const QString &name)
-{
- if (!m_statesEditorView->isAttached())
- return;
-
- const auto groupMetaInfo = m_statesEditorView->model()->qtQuickStateGroupMetaInfo();
-
- auto modelNode = Utils::findOrDefault(m_statesEditorView->allModelNodesOfType(groupMetaInfo),
- [&name](const ModelNode &node) {
- return node.displayName() == name;
- });
-
- QTC_ASSERT(!modelNode.isValid(), return );
-
- if (modelNode.isValid())
- m_statesEditorView->setActiveStatesGroupNode(modelNode);
-}
-
-int StatesEditorModel::activeStateGroupIndex() const
-{
- return m_statesEditorView->activeStatesGroupIndex();
-}
-
-void StatesEditorModel::setActiveStateGroupIndex(int index)
-{
- m_statesEditorView->setActiveStatesGroupIndex(index);
-}
-
-bool StatesEditorModel::renameActiveStateGroup(const QString &name)
-{
- auto stateGroup = m_statesEditorView->activeStatesGroupNode();
-
- if (!stateGroup.isValid() || stateGroup.isRootNode())
- return false;
-
- if (!QmlDesigner::ModelNode::isValidId(name) || m_statesEditorView->hasId(name)) {
- QString errMsg = QmlDesigner::ModelNode::getIdValidityErrorMessage(name);
- if (!errMsg.isEmpty())
- Core::AsynchronousMessageBox::warning(tr("Invalid ID"), errMsg);
- else
- Core::AsynchronousMessageBox::warning(tr("Invalid ID"),
- tr("%1 already exists.").arg(name));
- return false;
- }
-
- stateGroup.setIdWithRefactoring(name);
- emit stateGroupsChanged();
- return true;
-}
-
-void StatesEditorModel::addStateGroup(const QString &name)
-{
- m_statesEditorView->executeInTransaction("createStateGroup", [this, name]() {
- const TypeName typeName = "QtQuick.StateGroup";
- auto metaInfo = m_statesEditorView->model()->metaInfo(typeName);
- int minorVersion = metaInfo.minorVersion();
- int majorVersion = metaInfo.majorVersion();
- auto stateGroupNode = m_statesEditorView->createModelNode(typeName,
- majorVersion,
- minorVersion);
- stateGroupNode.setIdWithoutRefactoring(m_statesEditorView->model()->generateNewId(name));
-
- m_statesEditorView->rootModelNode().defaultNodeAbstractProperty().reparentHere(
- stateGroupNode);
- m_statesEditorView->setActiveStatesGroupNode(stateGroupNode);
- });
-}
-
-void StatesEditorModel::removeStateGroup()
-{
- if (m_statesEditorView->activeStatesGroupNode().isRootNode())
- return;
-
- m_statesEditorView->executeInTransaction("removeStateGroup", [this]() {
- m_statesEditorView->activeStatesGroupNode().destroy();
- });
-}
-
-QVariantMap StatesEditorModel::get(int idx) const
-{
- const QHash<int, QByteArray> &names = roleNames();
- QHash<int, QByteArray>::const_iterator i = names.constBegin();
-
- QVariantMap res;
- QModelIndex modelIndex = index(idx);
-
- while (i != names.constEnd()) {
- QVariant data = modelIndex.data(i.key());
-
- res[QString::fromUtf8(i.value())] = data;
- ++i;
- }
- return res;
-}
-
-QVariantMap StatesEditorModel::baseState() const
-{
- return get(0);
-}
-
-bool StatesEditorModel::hasExtend() const
-{
- return m_hasExtend;
-}
-
-QStringList StatesEditorModel::extendedStates() const
-{
- return m_extendedStates;
-}
-
-void StatesEditorModel::move(int from, int to)
-{
- // This does not alter the code (rewriter) which means the reordering is not presistent
-
- if (from == to)
- return;
-
- int specialIndex = (from < to ? to + 1 : to);
- beginMoveRows(QModelIndex(), from, from, QModelIndex(), specialIndex);
- endMoveRows();
-}
-
-void StatesEditorModel::drop(int from, int to)
-{
- m_statesEditorView->moveStates(from, to);
-}
-
-void StatesEditorModel::evaluateExtend()
-{
- bool hasExtend = m_statesEditorView->hasExtend();
-
- if (m_hasExtend != hasExtend) {
- m_hasExtend = hasExtend;
- emit hasExtendChanged();
- }
-
- auto extendedStates = m_statesEditorView->extendedStates();
-
- if (extendedStates.size() != m_extendedStates.size()) {
- m_extendedStates = extendedStates;
- emit extendedStatesChanged();
- return;
- }
-
- for (int i = 0; i != m_extendedStates.size(); ++i) {
- if (extendedStates[i] != m_extendedStates[i]) {
- m_extendedStates = extendedStates;
- emit extendedStatesChanged();
- return;
- }
- }
-}
-
-} // namespace Experimental
-} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/stateseditornew/stateseditormodel.h b/src/plugins/qmldesigner/components/stateseditornew/stateseditormodel.h
deleted file mode 100644
index c1f1287838..0000000000
--- a/src/plugins/qmldesigner/components/stateseditornew/stateseditormodel.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2022 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <QAbstractListModel>
-#include <QPointer>
-
-namespace QmlDesigner {
-namespace Experimental {
-
-class StatesEditorView;
-
-class StatesEditorModel : public QAbstractListModel
-{
- Q_OBJECT
-
- enum {
- StateNameRole = Qt::DisplayRole,
- StateImageSourceRole = Qt::UserRole,
- InternalNodeId,
- HasWhenCondition,
- WhenConditionString,
- IsDefault,
- ModelHasDefaultState,
- HasExtend,
- ExtendString
- };
-
-public:
- StatesEditorModel(StatesEditorView *view);
-
- Q_INVOKABLE int count() const;
- QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const 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;
-
- void insertState(int stateIndex);
- void removeState(int stateIndex);
- void updateState(int beginIndex, int endIndex);
- Q_INVOKABLE void renameState(int internalNodeId, const QString &newName);
- Q_INVOKABLE void setWhenCondition(int internalNodeId, const QString &condition);
- Q_INVOKABLE void resetWhenCondition(int internalNodeId);
- Q_INVOKABLE QStringList autoComplete(const QString &text, int pos, bool explicitComplete);
- Q_INVOKABLE QVariant stateModelNode(int internalNodeId);
-
- Q_INVOKABLE void setStateAsDefault(int internalNodeId);
- Q_INVOKABLE void resetDefaultState();
- Q_INVOKABLE bool hasDefaultState() const;
- Q_INVOKABLE void setAnnotation(int internalNodeId);
- Q_INVOKABLE void removeAnnotation(int internalNodeId);
- Q_INVOKABLE bool hasAnnotation(int internalNodeId) const;
-
- QStringList stateGroups() const;
- QString activeStateGroup() const;
- void setActiveStateGroup(const QString &name);
- int activeStateGroupIndex() const;
- void setActiveStateGroupIndex(int index);
-
- Q_INVOKABLE bool renameActiveStateGroup(const QString &name);
-
- Q_INVOKABLE void addStateGroup(const QString &name);
- Q_INVOKABLE void removeStateGroup();
-
- Q_INVOKABLE QVariantMap get(int idx) const;
-
- QVariantMap baseState() const;
- bool hasExtend() const;
- QStringList extendedStates() const;
-
- Q_PROPERTY(QVariantMap baseState READ baseState NOTIFY baseStateChanged)
- Q_PROPERTY(QStringList extendedStates READ extendedStates NOTIFY extendedStatesChanged)
-
- Q_PROPERTY(bool hasExtend READ hasExtend NOTIFY hasExtendChanged)
-
- Q_PROPERTY(QString activeStateGroup READ activeStateGroup WRITE setActiveStateGroup NOTIFY
- activeStateGroupChanged)
- Q_PROPERTY(int activeStateGroupIndex READ activeStateGroupIndex WRITE setActiveStateGroupIndex
- NOTIFY activeStateGroupIndexChanged)
- Q_PROPERTY(QStringList stateGroups READ stateGroups NOTIFY stateGroupsChanged)
-
- Q_INVOKABLE void move(int from, int to);
- Q_INVOKABLE void drop(int from, int to);
-
- void reset();
- void evaluateExtend();
-
-signals:
- void changedToState(int n);
- void baseStateChanged();
- void hasExtendChanged();
- void extendedStatesChanged();
- void activeStateGroupChanged();
- void activeStateGroupIndexChanged();
- void stateGroupsChanged();
-
-private:
- QPointer<StatesEditorView> m_statesEditorView;
- bool m_hasExtend;
- QStringList m_extendedStates;
-};
-
-} // namespace Experimental
-} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/stateseditornew/stateseditorview.cpp b/src/plugins/qmldesigner/components/stateseditornew/stateseditorview.cpp
deleted file mode 100644
index b35bd21477..0000000000
--- a/src/plugins/qmldesigner/components/stateseditornew/stateseditorview.cpp
+++ /dev/null
@@ -1,964 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2022 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "stateseditorview.h"
-#include "propertychangesmodel.h"
-#include "stateseditormodel.h"
-#include "stateseditorwidget.h"
-
-#include <QDebug>
-#include <QMessageBox>
-#include <QRegularExpression>
-#include <QScopeGuard>
-
-#include <cmath>
-#include <memory>
-
-#include <nodemetainfo.h>
-
-#include <bindingproperty.h>
-#include <customnotifications.h>
-#include <nodelistproperty.h>
-#include <rewritingexception.h>
-#include <variantproperty.h>
-
-#include <qmldesignerconstants.h>
-#include <qmldesignerplugin.h>
-#include <qmlitemnode.h>
-#include <qmlstate.h>
-#include <annotationeditor/annotationeditor.h>
-#include <utils/algorithm.h>
-#include <utils/qtcassert.h>
-
-namespace QmlDesigner {
-namespace Experimental {
-
-/**
- We always have 'one' current state, where we get updates from (see sceneChanged()). In case
- the current state is the base state, we render the base state + all other states.
- */
-
-StatesEditorView::StatesEditorView(ExternalDependenciesInterface &externalDependencies)
- : AbstractView(externalDependencies)
- , m_statesEditorModel(new StatesEditorModel(this))
- , m_lastIndex(-1)
- , m_editor(nullptr)
-{
- Q_ASSERT(m_statesEditorModel);
- // base state
-}
-
-StatesEditorView::~StatesEditorView()
-{
- if (m_editor)
- delete m_editor;
- delete m_statesEditorWidget.data();
-}
-
-WidgetInfo StatesEditorView::widgetInfo()
-{
- if (!m_statesEditorWidget)
- m_statesEditorWidget = new StatesEditorWidget(this, m_statesEditorModel.data());
-
- return createWidgetInfo(m_statesEditorWidget.data(),
- "StatesEditor",
- WidgetInfo::BottomPane,
- 0,
- tr("States"));
-}
-
-void StatesEditorView::rootNodeTypeChanged(const QString &/*type*/, int /*majorVersion*/, int /*minorVersion*/)
-{
- checkForStatesAvailability();
-}
-
-ModelNode StatesEditorView::activeStatesGroupNode() const
-{
- return m_activeStatesGroupNode;
-}
-
-void StatesEditorView::setActiveStatesGroupNode(const ModelNode &modelNode)
-{
- if (m_activeStatesGroupNode == modelNode)
- return;
-
- m_activeStatesGroupNode = modelNode;
- resetModel();
-
- checkForStatesAvailability();
-
- emit m_statesEditorModel->activeStateGroupChanged();
- emit m_statesEditorModel->activeStateGroupIndexChanged();
-}
-
-int StatesEditorView::activeStatesGroupIndex() const
-{
- if (!model())
- return -1;
-
- return Utils::indexOf(allModelNodesOfType(model()->qtQuickStateGroupMetaInfo()),
- [this](const ModelNode &node) { return node == m_activeStatesGroupNode; })
- + 1;
-}
-
-void StatesEditorView::setActiveStatesGroupIndex(int index)
-{
- if (!model())
- return;
-
- if (index > 0) {
- const ModelNode statesGroup = allModelNodesOfType(model()->qtQuickStateGroupMetaInfo())
- .at(index - 1);
- if (statesGroup.isValid())
- setActiveStatesGroupNode(statesGroup);
- } else {
- setActiveStatesGroupNode(rootModelNode());
- }
-}
-
-void StatesEditorView::registerPropertyChangesModel(PropertyChangesModel *model)
-{
- m_propertyChangedModels.insert(model);
-}
-
-void StatesEditorView::deregisterPropertyChangesModel(PropertyChangesModel *model)
-{
- m_propertyChangedModels.remove(model);
-}
-
-void StatesEditorView::synchonizeCurrentStateFromWidget()
-{
- if (!model())
- return;
-
- if (m_block)
- return;
-
- int internalId = m_statesEditorWidget->currentStateInternalId();
-
- if (internalId > 0 && hasModelNodeForInternalId(internalId)) {
- ModelNode node = modelNodeForInternalId(internalId);
- QmlModelState modelState(node);
- if (modelState.isValid() && modelState != currentState())
- setCurrentState(modelState);
- } else {
- setCurrentState(baseState());
- }
-}
-
-void StatesEditorView::createNewState()
-{
- // can happen when root node is e.g. a ListModel
- if (!QmlVisualNode::isValidQmlVisualNode(activeStatesGroupNode())
- && m_activeStatesGroupNode.type() != "QtQuick.StateGroup")
- return;
-
- QmlDesignerPlugin::emitUsageStatistics(Constants::EVENT_STATE_ADDED);
-
- QStringList modelStateNames = activeStateGroup().names();
-
- QString newStateName;
- int index = 1;
- while (true) {
- newStateName = QString(QStringLiteral("State%1")).arg(index++);
- if (!modelStateNames.contains(newStateName))
- break;
- }
-
- executeInTransaction("createNewState", [this, newStateName]() {
- activeStatesGroupNode().validId();
-
- ModelNode newState = activeStateGroup().addState(newStateName);
- setCurrentState(newState);
- });
-}
-
-void StatesEditorView::cloneState(int nodeId)
-{
- if (!(nodeId > 0 && hasModelNodeForInternalId(nodeId)))
- return;
-
- ModelNode stateNode(modelNodeForInternalId(nodeId));
- QTC_ASSERT(stateNode.simplifiedTypeName() == "State", return );
-
- QmlModelState modelState(stateNode);
- if (!modelState.isValid() || modelState.isBaseState())
- return;
-
- QmlDesignerPlugin::emitUsageStatistics(Constants::EVENT_STATE_CLONED);
-
- QString newName = modelState.name();
-
- // Strip out numbers at the end of the string
- QRegularExpression regEx(QLatin1String("[0-9]+$"));
- const QRegularExpressionMatch match = regEx.match(newName);
- if (match.hasMatch() && (match.capturedStart() + match.capturedLength() == newName.length()))
- newName = newName.left(match.capturedStart());
-
- int i = 1;
- QStringList stateNames = activeStateGroup().names();
- while (stateNames.contains(newName + QString::number(i)))
- i++;
- const QString newStateName = newName + QString::number(i);
-
- QmlModelState newState;
-
- executeInTransaction("cloneState", [newStateName, modelState, &newState]() {
- newState = modelState.duplicate(newStateName);
- });
-
- ModelNode newNode = newState.modelNode();
- int from = newNode.parentProperty().indexOf(newNode);
- int to = stateNode.parentProperty().indexOf(stateNode) + 1;
-
- // When duplicating an extended state the new state needs to be added after the extend group.
- if (!modelState.hasExtend()) {
- auto modelNodeList = activeStatesGroupNode().nodeListProperty("states").toModelNodeList();
- for (; to != modelNodeList.count(); ++to) {
- QmlModelState currentState(modelNodeList.at(to));
- if (!currentState.isValid() || currentState.isBaseState() || !currentState.hasExtend())
- break;
- }
- }
-
- executeInTransaction("moveState", [this, &newState, from, to]() {
- activeStatesGroupNode().nodeListProperty("states").slide(from, to);
- setCurrentState(newState);
- });
-}
-
-void StatesEditorView::extendState(int nodeId)
-{
- if (!(nodeId > 0 && hasModelNodeForInternalId(nodeId)))
- return;
-
- ModelNode stateNode(modelNodeForInternalId(nodeId));
- QTC_ASSERT(stateNode.simplifiedTypeName() == "State", return );
-
- QmlModelState modelState(stateNode);
- if (!modelState.isValid() || modelState.isBaseState())
- return;
-
- QmlDesignerPlugin::emitUsageStatistics(Constants::EVENT_STATE_EXTENDED);
-
- QString newName = modelState.name();
-
- // Strip out numbers at the end of the string
- QRegularExpression regEx(QLatin1String("[0-9]+$"));
- const QRegularExpressionMatch match = regEx.match(newName);
- if (match.hasMatch() && (match.capturedStart() + match.capturedLength() == newName.length()))
- newName = newName.left(match.capturedStart());
-
- int i = 1;
- QStringList stateNames = activeStateGroup().names();
- while (stateNames.contains(newName + QString::number(i)))
- i++;
- const QString newStateName = newName + QString::number(i);
-
- QmlModelState newState;
-
- executeInTransaction("extendState", [this, newStateName, modelState, &newState]() {
- newState = activeStateGroup().addState(newStateName);
- newState.setExtend(modelState.name());
- });
-
- ModelNode newNode = newState.modelNode();
- int from = newNode.parentProperty().indexOf(newNode);
- int to = stateNode.parentProperty().indexOf(stateNode) + 1;
-
- executeInTransaction("moveState", [this, &newState, from, to]() {
- activeStatesGroupNode().nodeListProperty("states").slide(from, to);
- setCurrentState(newState);
- });
-}
-
-void StatesEditorView::removeState(int nodeId)
-{
- try {
- if (nodeId > 0 && hasModelNodeForInternalId(nodeId)) {
- ModelNode stateNode(modelNodeForInternalId(nodeId));
- QTC_ASSERT(stateNode.simplifiedTypeName() == "State", return );
-
- QmlModelState modelState(stateNode);
- if (modelState.isValid()) {
- QStringList lockedTargets;
- const auto propertyChanges = modelState.propertyChanges();
-
- // confirm removing not empty states
- if (!propertyChanges.isEmpty()) {
- QMessageBox msgBox;
- msgBox.setTextFormat(Qt::RichText);
- msgBox.setIcon(QMessageBox::Question);
- msgBox.setWindowTitle(tr("Remove State"));
- msgBox.setText(
- tr("This state is not empty. Are you sure you want to remove it?"));
- msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
- msgBox.setDefaultButton(QMessageBox::Yes);
-
- if (msgBox.exec() == QMessageBox::Cancel)
- return;
- }
-
- // confirm removing states with locked targets
- for (const QmlPropertyChanges &change : propertyChanges) {
- const ModelNode target = change.target();
- QTC_ASSERT(target.isValid(), continue);
- if (target.locked())
- lockedTargets.push_back(target.id());
- }
-
- if (!lockedTargets.empty()) {
- Utils::sort(lockedTargets);
- QString detailedText = QString("<b>" + tr("Locked components:") + "</b><br>");
-
- for (const auto &id : std::as_const(lockedTargets))
- detailedText.append("- " + id + "<br>");
-
- detailedText.chop(QString("<br>").size());
-
- QMessageBox msgBox;
- msgBox.setTextFormat(Qt::RichText);
- msgBox.setIcon(QMessageBox::Question);
- msgBox.setWindowTitle(tr("Remove State"));
- msgBox.setText(QString(tr("Removing this state will modify locked components.")
- + "<br><br>%1")
- .arg(detailedText));
- msgBox.setInformativeText(tr("Continue by removing the state?"));
- msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
- msgBox.setDefaultButton(QMessageBox::Ok);
-
- if (msgBox.exec() == QMessageBox::Cancel)
- return;
- }
- }
-
- NodeListProperty parentProperty = stateNode.parentProperty().toNodeListProperty();
-
- if (parentProperty.count() <= 1) {
- setCurrentState(baseState());
- } else if (parentProperty.isValid()) {
- int index = parentProperty.indexOf(stateNode);
- if (index == 0)
- setCurrentState(parentProperty.at(1));
- else
- setCurrentState(parentProperty.at(index - 1));
- }
-
- stateNode.destroy();
- }
- } catch (const RewritingException &e) {
- e.showException();
- }
-}
-
-void StatesEditorView::resetModel()
-{
- if (m_bulkChange) {
- m_modelDirty = true;
- return;
- }
-
- if (m_statesEditorModel)
- m_statesEditorModel->reset();
-
- if (m_statesEditorWidget) {
- if (currentState().isBaseState())
- m_statesEditorWidget->setCurrentStateInternalId(0);
- else
- m_statesEditorWidget->setCurrentStateInternalId(currentState().modelNode().internalId());
- }
-
- m_modelDirty = false;
-}
-
-void StatesEditorView::resetPropertyChangesModels()
-{
- if (m_bulkChange) {
- m_propertyChangesDirty = true;
- return;
- }
-
- std::for_each(m_propertyChangedModels.begin(),
- m_propertyChangedModels.end(),
- [](PropertyChangesModel *model) { model->reset(); });
-
- m_propertyChangesDirty = false;
-}
-
-void StatesEditorView::resetExtend()
-{
- if (m_bulkChange) {
- m_extendDirty = true;
- return;
- }
-
- m_statesEditorModel->evaluateExtend();
-
- m_extendDirty = false;
-}
-
-void StatesEditorView::resetStateGroups()
-{
- if (m_bulkChange) {
- m_stateGroupsDirty = true;
- return;
- }
-
- emit m_statesEditorModel->stateGroupsChanged();
-
- m_stateGroupsDirty = false;
-}
-
-void StatesEditorView::checkForStatesAvailability()
-{
- if (m_statesEditorWidget) {
- const bool isVisual = activeStatesGroupNode().metaInfo().isBasedOn(
- model()->qtQuickItemMetaInfo(), model()->qtQuick3DNodeMetaInfo());
- const bool isRoot = activeStatesGroupNode().isRootNode();
- m_statesEditorWidget->showAddNewStatesButton(isVisual || !isRoot);
- }
-}
-
-void StatesEditorView::beginBulkChange()
-{
- m_bulkChange = true;
-}
-
-void StatesEditorView::endBulkChange()
-{
- if (!m_bulkChange)
- return;
-
- m_bulkChange = false;
-
- if (m_modelDirty)
- resetModel();
-
- if (m_propertyChangesDirty)
- resetPropertyChangesModels();
-
- if (m_extendDirty)
- resetExtend();
-
- if (m_stateGroupsDirty)
- resetStateGroups();
-}
-
-void StatesEditorView::setCurrentState(const QmlModelState &state)
-{
- if (!model() && !state.isValid())
- return;
-
- if (currentStateNode() != state.modelNode())
- setCurrentStateNode(state.modelNode());
-}
-
-QmlModelState StatesEditorView::baseState() const
-{
- return QmlModelState::createBaseState(this);
-}
-
-QmlModelStateGroup StatesEditorView::activeStateGroup() const
-{
- return QmlModelStateGroup(activeStatesGroupNode());
-}
-
-bool StatesEditorView::validStateName(const QString &name) const
-{
- if (name == tr("base state"))
- return false;
- const QList<QmlModelState> modelStates = activeStateGroup().allStates();
- for (const QmlModelState &state : modelStates) {
- if (state.name() == name)
- return false;
- }
- return true;
-}
-
-bool StatesEditorView::hasExtend() const
-{
- if (!model())
- return false;
-
- const QList<QmlModelState> modelStates = activeStateGroup().allStates();
- for (const QmlModelState &state : modelStates) {
- if (state.hasExtend())
- return true;
- }
- return false;
-}
-
-QStringList StatesEditorView::extendedStates() const
-{
- if (!model())
- return QStringList();
-
- QStringList states;
-
- const QList<QmlModelState> modelStates = activeStateGroup().allStates();
- for (const QmlModelState &state : modelStates) {
- if (state.hasExtend())
- states.append(state.extend());
- }
- states.removeDuplicates();
- return states;
-}
-
-QString StatesEditorView::currentStateName() const
-{
- return currentState().isValid() ? currentState().name() : QString();
-}
-
-void StatesEditorView::renameState(int internalNodeId, const QString &newName)
-{
- if (hasModelNodeForInternalId(internalNodeId)) {
- QmlModelState renamedState(modelNodeForInternalId(internalNodeId));
- try {
- if (renamedState.isValid() && renamedState.name() != newName) {
- executeInTransaction("renameState", [this, &renamedState, &newName]() {
- // Jump to base state for the change
- QmlModelState oldState = currentState();
- setCurrentState(baseState());
- const bool updateDefault = renamedState.isDefault();
-
- // If state is extended rename all references
- QList<QmlModelState> states;
- const QList<QmlModelState> modelStates = activeStateGroup().allStates();
- for (const QmlModelState &state : modelStates) {
- if (state.hasExtend() && state.extend() == renamedState.name())
- states.append(state);
- }
-
- renamedState.setName(newName.trimmed());
-
- for (QmlModelState &state : states)
- state.setExtend(newName.trimmed());
-
- if (updateDefault)
- renamedState.setAsDefault();
-
- setCurrentState(oldState);
- });
- }
- } catch (const RewritingException &e) {
- e.showException();
- }
- }
-}
-
-void StatesEditorView::setWhenCondition(int internalNodeId, const QString &condition)
-{
- if (m_block)
- return;
-
- m_block = true;
- const QScopeGuard cleanup([&] { m_block = false; });
-
- if (hasModelNodeForInternalId(internalNodeId)) {
- QmlModelState state(modelNodeForInternalId(internalNodeId));
- try {
- if (state.isValid())
- state.modelNode().bindingProperty("when").setExpression(condition);
-
- } catch (const Exception &e) {
- e.showException();
- }
- }
-}
-
-void StatesEditorView::resetWhenCondition(int internalNodeId)
-{
- if (m_block)
- return;
-
- m_block = true;
- const QScopeGuard cleanup([&] { m_block = false; });
-
- if (hasModelNodeForInternalId(internalNodeId)) {
- QmlModelState state(modelNodeForInternalId(internalNodeId));
- try {
- if (state.isValid() && state.modelNode().hasProperty("when"))
- state.modelNode().removeProperty("when");
-
- } catch (const RewritingException &e) {
- e.showException();
- }
- }
-}
-
-void StatesEditorView::setStateAsDefault(int internalNodeId)
-{
- if (m_block)
- return;
-
- m_block = true;
- const QScopeGuard cleanup([&] { m_block = false; });
-
- if (hasModelNodeForInternalId(internalNodeId)) {
- QmlModelState state(modelNodeForInternalId(internalNodeId));
- try {
- if (state.isValid())
- state.setAsDefault();
-
- } catch (const RewritingException &e) {
- e.showException();
- }
- }
-}
-
-void StatesEditorView::resetDefaultState()
-{
- if (m_block)
- return;
-
- m_block = true;
- const QScopeGuard cleanup([&] { m_block = false; });
-
- try {
- if (activeStatesGroupNode().hasProperty("state"))
- activeStatesGroupNode().removeProperty("state");
-
- } catch (const RewritingException &e) {
- e.showException();
- }
-}
-
-bool StatesEditorView::hasDefaultState() const
-{
- return activeStatesGroupNode().hasProperty("state");
-}
-
-void StatesEditorView::setAnnotation(int internalNodeId)
-{
- if (m_block)
- return;
-
- m_block = true;
- const QScopeGuard cleanup([&] { m_block = false; });
-
- if (hasModelNodeForInternalId(internalNodeId)) {
- QmlModelState state(modelNodeForInternalId(internalNodeId));
- try {
- if (state.isValid()) {
- ModelNode modelNode = state.modelNode();
-
- if (modelNode.isValid()) {
- if (!m_editor)
- m_editor = new AnnotationEditor(this);
-
- m_editor->setModelNode(modelNode);
- m_editor->showWidget();
- }
- }
-
- } catch (const RewritingException &e) {
- e.showException();
- }
- }
-}
-
-void StatesEditorView::removeAnnotation(int internalNodeId)
-{
- if (m_block)
- return;
-
- m_block = true;
- const QScopeGuard cleanup([&] { m_block = false; });
-
- if (hasModelNodeForInternalId(internalNodeId)) {
- QmlModelState state(modelNodeForInternalId(internalNodeId));
- try {
- if (state.isValid())
- state.removeAnnotation();
-
- } catch (const RewritingException &e) {
- e.showException();
- }
- }
-}
-
-bool StatesEditorView::hasAnnotation(int internalNodeId) const
-{
- if (!model())
- return false;
-
- if (hasModelNodeForInternalId(internalNodeId)) {
- QmlModelState state(modelNodeForInternalId(internalNodeId));
- if (state.isValid())
- return state.hasAnnotation();
- }
-
- return false;
-}
-
-void StatesEditorView::modelAttached(Model *model)
-{
- if (model == AbstractView::model())
- return;
-
- QTC_ASSERT(model, return );
- AbstractView::modelAttached(model);
-
- m_activeStatesGroupNode = rootModelNode();
-
- if (m_statesEditorWidget)
- m_statesEditorWidget->setNodeInstanceView(nodeInstanceView());
-
- checkForStatesAvailability();
-
- resetModel();
- resetStateGroups();
-
- emit m_statesEditorModel->activeStateGroupChanged();
- emit m_statesEditorModel->activeStateGroupIndexChanged();
-}
-
-void StatesEditorView::modelAboutToBeDetached(Model *model)
-{
- AbstractView::modelAboutToBeDetached(model);
- resetModel();
-}
-
-void StatesEditorView::propertiesRemoved(const QList<AbstractProperty>& propertyList)
-{
- for (const AbstractProperty &property : propertyList) {
- if (property.name() == "states" && property.parentModelNode() == activeStateGroup().modelNode())
- resetModel();
- if ((property.name() == "when" || property.name() == "name")
- && QmlModelState::isValidQmlModelState(property.parentModelNode()))
- resetModel();
- if (property.name() == "extend")
- resetExtend();
- if (property.parentModelNode().simplifiedTypeName() == "PropertyChanges"
- || (property.name() == "changes"
- && property.parentModelNode().simplifiedTypeName() == "State"))
- resetPropertyChangesModels();
- }
-}
-
-void StatesEditorView::nodeAboutToBeRemoved(const ModelNode &removedNode)
-{
- if (removedNode.hasParentProperty()) {
- const NodeAbstractProperty propertyParent = removedNode.parentProperty();
- if (propertyParent.parentModelNode() == activeStateGroup().modelNode()
- && propertyParent.name() == "states")
- m_lastIndex = propertyParent.indexOf(removedNode);
- }
- if (currentState().isValid() && removedNode == currentState())
- setCurrentState(baseState());
-
- if (removedNode.simplifiedTypeName() == "PropertyChanges")
- m_propertyChangesRemoved = true;
-
- if (removedNode.simplifiedTypeName() == "StateGroup") {
- if (removedNode == activeStatesGroupNode())
- setActiveStatesGroupNode(rootModelNode());
-
- m_stateGroupRemoved = true;
- }
-}
-
-void StatesEditorView::nodeRemoved(const ModelNode & /*removedNode*/,
- const NodeAbstractProperty &parentProperty,
- PropertyChangeFlags /*propertyChange*/)
-{
- if (parentProperty.isValid()
- && parentProperty.parentModelNode() == activeStateGroup().modelNode()
- && parentProperty.name() == "states") {
- m_statesEditorModel->removeState(m_lastIndex);
- m_lastIndex = -1;
- resetModel();
- }
-
- if (m_propertyChangesRemoved) {
- m_propertyChangesRemoved = false;
- resetPropertyChangesModels();
- }
-
- if (m_stateGroupRemoved) {
- m_stateGroupRemoved = false;
- resetStateGroups();
- }
-}
-
-void StatesEditorView::nodeAboutToBeReparented(const ModelNode &node,
- const NodeAbstractProperty & /*newPropertyParent*/,
- const NodeAbstractProperty &oldPropertyParent,
- AbstractView::PropertyChangeFlags /*propertyChange*/)
-{
- if (oldPropertyParent.isValid()
- && oldPropertyParent.parentModelNode() == activeStateGroup().modelNode()
- && oldPropertyParent.name() == "states")
- m_lastIndex = oldPropertyParent.indexOf(node);
-
- if (node.simplifiedTypeName() == "StateGroup")
- resetStateGroups();
-}
-
-void StatesEditorView::nodeReparented(const ModelNode &node,
- const NodeAbstractProperty &newPropertyParent,
- const NodeAbstractProperty &oldPropertyParent,
- AbstractView::PropertyChangeFlags /*propertyChange*/)
-{
- if (oldPropertyParent.isValid()
- && oldPropertyParent.parentModelNode() == activeStateGroup().modelNode()
- && oldPropertyParent.name() == "states") {
- m_statesEditorModel->removeState(m_lastIndex);
- resetModel();
- m_lastIndex = -1;
- }
-
- if (newPropertyParent.isValid()
- && newPropertyParent.parentModelNode() == activeStateGroup().modelNode()
- && newPropertyParent.name() == "states") {
- int index = newPropertyParent.indexOf(node);
- m_statesEditorModel->insertState(index);
- }
-
- if (node.simplifiedTypeName() == "PropertyChanges")
- resetPropertyChangesModels();
-}
-
-void StatesEditorView::nodeOrderChanged(const NodeListProperty &listProperty)
-{
- if (m_block)
- return;
-
- if (listProperty.isValid() && listProperty.parentModelNode() == activeStateGroup().modelNode()
- && listProperty.name() == "states")
- resetModel();
-}
-
-void StatesEditorView::bindingPropertiesChanged(const QList<BindingProperty> &propertyList, AbstractView::PropertyChangeFlags propertyChange)
-{
- Q_UNUSED(propertyChange)
-
- for (const BindingProperty &property : propertyList) {
- if (property.name() == "when"
- && QmlModelState::isValidQmlModelState(property.parentModelNode()))
- resetModel();
- if (property.parentModelNode().simplifiedTypeName() == "PropertyChanges")
- resetPropertyChangesModels();
- }
-}
-
-void StatesEditorView::variantPropertiesChanged(const QList<VariantProperty> &propertyList,
- AbstractView::PropertyChangeFlags /*propertyChange*/)
-{
- if (m_block)
- return;
-
- m_block = true;
- const QScopeGuard cleanup([&] { m_block = false; });
-
- for (const VariantProperty &property : propertyList) {
- if (property.name() == "name"
- && QmlModelState::isValidQmlModelState(property.parentModelNode()))
- resetModel();
- else if (property.name() == "state"
- && property.parentModelNode() == activeStateGroup().modelNode())
- resetModel();
- else if (property.name() == "extend")
- resetExtend();
-
- if (property.parentModelNode().simplifiedTypeName() == "PropertyChanges")
- resetPropertyChangesModels();
- }
-}
-
-void StatesEditorView::customNotification(const AbstractView * /*view*/,
- const QString &identifier,
- const QList<ModelNode> & /*nodeList*/,
- const QList<QVariant> & /*data*/)
-{
- if (identifier == StartRewriterAmend)
- beginBulkChange();
-
- if (identifier == EndRewriterAmend)
- endBulkChange();
-}
-
-void StatesEditorView::rewriterBeginTransaction()
-{
- beginBulkChange();
-}
-
-void StatesEditorView::rewriterEndTransaction()
-{
- endBulkChange();
-}
-
-void StatesEditorView::currentStateChanged(const ModelNode &node)
-{
- QmlModelState newQmlModelState(node);
-
- if (newQmlModelState.isBaseState())
- m_statesEditorWidget->setCurrentStateInternalId(0);
- else
- m_statesEditorWidget->setCurrentStateInternalId(newQmlModelState.modelNode().internalId());
-}
-
-void StatesEditorView::instancesPreviewImageChanged(const QVector<ModelNode> &nodeList)
-{
- if (!model())
- return;
-
- int minimumIndex = 10000;
- int maximumIndex = -1;
- for (const ModelNode &node : nodeList) {
- if (node.isRootNode()) {
- minimumIndex = qMin(minimumIndex, 0);
- maximumIndex = qMax(maximumIndex, 0);
- } else {
- int index = activeStateGroup().allStates().indexOf(QmlModelState(node)) + 1;
- if (index > 0) {
- minimumIndex = qMin(minimumIndex, index);
- maximumIndex = qMax(maximumIndex, index);
- }
- }
- }
-
- if (maximumIndex >= 0)
- m_statesEditorModel->updateState(minimumIndex, maximumIndex);
-}
-
-void StatesEditorView::moveStates(int from, int to)
-{
- if (m_block)
- return;
-
- m_block = true;
- const QScopeGuard cleanup([&] { m_block = false; });
-
- if (!activeStatesGroupNode().hasNodeListProperty("states"))
- return;
-
- executeInTransaction("moveState", [this, from, to]() {
- activeStatesGroupNode().nodeListProperty("states").slide(from - 1, to - 1);
- });
-}
-
-} // namespace Experimental
-} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/stateseditornew/stateseditorview.h b/src/plugins/qmldesigner/components/stateseditornew/stateseditorview.h
deleted file mode 100644
index 57adacd87b..0000000000
--- a/src/plugins/qmldesigner/components/stateseditornew/stateseditorview.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2022 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <abstractview.h>
-
-#include <qmlstate.h>
-
-#include <QSet>
-
-namespace QmlDesigner {
-
-class AnnotationEditor;
-
-namespace Experimental {
-
-class StatesEditorModel;
-class StatesEditorWidget;
-class PropertyChangesModel;
-
-class StatesEditorView : public AbstractView {
- Q_OBJECT
-
-public:
- explicit StatesEditorView(ExternalDependenciesInterface &externalDependencies);
- ~StatesEditorView() override;
-
- void renameState(int internalNodeId,const QString &newName);
- void setWhenCondition(int internalNodeId, const QString &condition);
- void resetWhenCondition(int internalNodeId);
- void setStateAsDefault(int internalNodeId);
- void resetDefaultState();
- bool hasDefaultState() const;
- void setAnnotation(int internalNodeId);
- void removeAnnotation(int internalNodeId);
- bool hasAnnotation(int internalNodeId) const;
- bool validStateName(const QString &name) const;
- bool hasExtend() const;
- QStringList extendedStates() const;
- QString currentStateName() const;
- void setCurrentState(const QmlModelState &state);
- QmlModelState baseState() const;
- QmlModelStateGroup activeStateGroup() const;
-
- void moveStates(int from, int to);
-
- // AbstractView
- void modelAttached(Model *model) override;
- void modelAboutToBeDetached(Model *model) override;
- void propertiesRemoved(const QList<AbstractProperty>& propertyList) override;
- void nodeAboutToBeRemoved(const ModelNode &removedNode) override;
- void nodeRemoved(const ModelNode &removedNode,
- const NodeAbstractProperty &parentProperty,
- PropertyChangeFlags propertyChange) override;
- void nodeAboutToBeReparented(const ModelNode &node,
- const NodeAbstractProperty &newPropertyParent,
- const NodeAbstractProperty &oldPropertyParent,
- AbstractView::PropertyChangeFlags propertyChange) override;
- void nodeReparented(const ModelNode &node,
- const NodeAbstractProperty &newPropertyParent,
- const NodeAbstractProperty &oldPropertyParent,
- AbstractView::PropertyChangeFlags propertyChange) override;
- void nodeOrderChanged(const NodeListProperty &listProperty) override;
- void bindingPropertiesChanged(const QList<BindingProperty> &propertyList,
- PropertyChangeFlags propertyChange) override;
- void variantPropertiesChanged(const QList<VariantProperty> &propertyList,
- PropertyChangeFlags propertyChange) override;
-
- void customNotification(const AbstractView *view,
- const QString &identifier,
- const QList<ModelNode> &nodeList,
- const QList<QVariant> &data) override;
- void rewriterBeginTransaction() override;
- void rewriterEndTransaction() override;
-
- // AbstractView
- void currentStateChanged(const ModelNode &node) override;
-
- void instancesPreviewImageChanged(const QVector<ModelNode> &nodeList) override;
-
- WidgetInfo widgetInfo() override;
-
- void rootNodeTypeChanged(const QString &type, int majorVersion, int minorVersion) override;
-
- ModelNode activeStatesGroupNode() const;
- void setActiveStatesGroupNode(const ModelNode &modelNode);
-
- int activeStatesGroupIndex() const;
- void setActiveStatesGroupIndex(int index);
-
- void registerPropertyChangesModel(PropertyChangesModel *model);
- void deregisterPropertyChangesModel(PropertyChangesModel *model);
-
-public slots:
- void synchonizeCurrentStateFromWidget();
- void createNewState();
- void cloneState(int nodeId);
- void extendState(int nodeId);
- void removeState(int nodeId);
-
-private:
- void resetModel();
- void resetPropertyChangesModels();
- void resetExtend();
- void resetStateGroups();
-
- void checkForStatesAvailability();
-
- void beginBulkChange();
- void endBulkChange();
-
-private:
- QPointer<StatesEditorModel> m_statesEditorModel;
- QPointer<StatesEditorWidget> m_statesEditorWidget;
- int m_lastIndex;
- bool m_block = false;
- QPointer<AnnotationEditor> m_editor;
- ModelNode m_activeStatesGroupNode;
-
- bool m_propertyChangesRemoved = false;
- bool m_stateGroupRemoved = false;
-
- bool m_bulkChange = false;
-
- bool m_modelDirty = false;
- bool m_extendDirty = false;
- bool m_propertyChangesDirty = false;
- bool m_stateGroupsDirty = false;
-
- QSet<PropertyChangesModel *> m_propertyChangedModels;
-};
-
-} // namespace Experimental
-} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/stateseditornew/stateseditorwidget.cpp b/src/plugins/qmldesigner/components/stateseditornew/stateseditorwidget.cpp
deleted file mode 100644
index e07ba02ae0..0000000000
--- a/src/plugins/qmldesigner/components/stateseditornew/stateseditorwidget.cpp
+++ /dev/null
@@ -1,200 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2022 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "stateseditorwidget.h"
-#include "stateseditormodel.h"
-#include "stateseditorview.h"
-#include "stateseditorimageprovider.h"
-
-#include <designersettings.h>
-#include <theme.h>
-#include <qmldesignerconstants.h>
-#include <qmldesignerplugin.h>
-
-#include <invalidqmlsourceexception.h>
-
-#include <coreplugin/messagebox.h>
-#include <coreplugin/icore.h>
-
-#include <utils/qtcassert.h>
-#include <utils/stylehelper.h>
-
-#include <QApplication>
-
-#include <QBoxLayout>
-#include <QFileInfo>
-#include <QKeySequence>
-#include <QShortcut>
-
-#include <QQmlContext>
-#include <QQmlEngine>
-#include <QQuickItem>
-
-enum {
- debug = false
-};
-
-namespace QmlDesigner {
-namespace Experimental {
-
-static QString propertyEditorResourcesPath()
-{
-#ifdef SHARE_QML_PATH
- if (qEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
- return QLatin1String(SHARE_QML_PATH) + "/propertyEditorQmlSources";
-#endif
- return Core::ICore::resourcePath("qmldesigner/propertyEditorQmlSources").toString();
-}
-
-int StatesEditorWidget::currentStateInternalId() const
-{
- QTC_ASSERT(rootObject(), return -1);
- QTC_ASSERT(rootObject()->property("currentStateInternalId").isValid(), return -1);
-
- return rootObject()->property("currentStateInternalId").toInt();
-}
-
-void StatesEditorWidget::setCurrentStateInternalId(int internalId)
-{
- QTC_ASSERT(rootObject(), return);
- rootObject()->setProperty("currentStateInternalId", internalId);
-}
-
-void StatesEditorWidget::setNodeInstanceView(const NodeInstanceView *nodeInstanceView)
-{
- m_imageProvider->setNodeInstanceView(nodeInstanceView);
-}
-
-void StatesEditorWidget::showAddNewStatesButton(bool showAddNewStatesButton)
-{
- rootContext()->setContextProperty(QLatin1String("canAddNewStates"), showAddNewStatesButton);
-}
-
-StatesEditorWidget::StatesEditorWidget(StatesEditorView *statesEditorView,
- StatesEditorModel *statesEditorModel)
- : m_statesEditorView(statesEditorView)
- , m_imageProvider(nullptr)
- , m_qmlSourceUpdateShortcut(nullptr)
-{
- m_imageProvider = new Internal::StatesEditorImageProvider;
- m_imageProvider->setNodeInstanceView(statesEditorView->nodeInstanceView());
-
- engine()->addImageProvider(QStringLiteral("qmldesigner_stateseditor"), m_imageProvider);
- engine()->addImportPath(qmlSourcesPath());
- engine()->addImportPath(propertyEditorResourcesPath() + "/imports");
- engine()->addImportPath(qmlSourcesPath() + "/imports");
-
- m_qmlSourceUpdateShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_F10), this);
- connect(m_qmlSourceUpdateShortcut, &QShortcut::activated, this, &StatesEditorWidget::reloadQmlSource);
-
- setObjectName(Constants::OBJECT_NAME_STATES_EDITOR);
- setResizeMode(QQuickWidget::SizeRootObjectToView);
- setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
-
- rootContext()->setContextProperties(
- QVector<QQmlContext::PropertyPair>{{{"statesEditorModel"},
- QVariant::fromValue(statesEditorModel)},
- {{"canAddNewStates"}, true}});
-
- Theme::setupTheme(engine());
-
- setWindowTitle(tr("States New", "Title of Editor widget"));
- setMinimumWidth(195);
- setMinimumHeight(195);
-
- // init the first load of the QML UI elements
- reloadQmlSource();
-}
-
-StatesEditorWidget::~StatesEditorWidget() = default;
-
-QString StatesEditorWidget::qmlSourcesPath()
-{
-#ifdef SHARE_QML_PATH
- if (qEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
- return QLatin1String(SHARE_QML_PATH) + "/newstateseditor";
-#endif
- return Core::ICore::resourcePath("qmldesigner/newstateseditor").toString();
-}
-
-void StatesEditorWidget::showEvent(QShowEvent *event)
-{
- QQuickWidget::showEvent(event);
- update();
- QMetaObject::invokeMethod(rootObject(), "showEvent");
-}
-
-void StatesEditorWidget::focusOutEvent(QFocusEvent *focusEvent)
-{
- QmlDesignerPlugin::emitUsageStatisticsTime(Constants::EVENT_STATESEDITOR_TIME,
- m_usageTimer.elapsed());
- QQuickWidget::focusOutEvent(focusEvent);
-}
-
-void StatesEditorWidget::focusInEvent(QFocusEvent *focusEvent)
-{
- m_usageTimer.restart();
- QQuickWidget::focusInEvent(focusEvent);
-}
-
-void StatesEditorWidget::reloadQmlSource()
-{
- QString statesListQmlFilePath = qmlSourcesPath() + QStringLiteral("/Main.qml");
- QTC_ASSERT(QFileInfo::exists(statesListQmlFilePath), return );
- setSource(QUrl::fromLocalFile(statesListQmlFilePath));
-
- if (!rootObject()) {
- QString errorString;
- for (const QQmlError &error : errors())
- errorString += "\n" + error.toString();
-
- Core::AsynchronousMessageBox::warning(tr("Cannot Create QtQuick View"),
- tr("StatesEditorWidget: %1 cannot be created.%2")
- .arg(qmlSourcesPath(), errorString));
- return;
- }
-
- connect(rootObject(),
- SIGNAL(currentStateInternalIdChanged()),
- m_statesEditorView.data(),
- SLOT(synchonizeCurrentStateFromWidget()));
- connect(rootObject(),
- SIGNAL(createNewState()),
- m_statesEditorView.data(),
- SLOT(createNewState()));
- connect(rootObject(), SIGNAL(cloneState(int)), m_statesEditorView.data(), SLOT(cloneState(int)));
- connect(rootObject(),
- SIGNAL(extendState(int)),
- m_statesEditorView.data(),
- SLOT(extendState(int)));
- connect(rootObject(),
- SIGNAL(deleteState(int)),
- m_statesEditorView.data(),
- SLOT(removeState(int)));
- m_statesEditorView.data()->synchonizeCurrentStateFromWidget();
-}
-
-} // namespace Experimental
-} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/stateseditornew/stateseditorwidget.h b/src/plugins/qmldesigner/components/stateseditornew/stateseditorwidget.h
deleted file mode 100644
index 0b8ca901e0..0000000000
--- a/src/plugins/qmldesigner/components/stateseditornew/stateseditorwidget.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2022 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <QElapsedTimer>
-#include <QPointer>
-#include <QQmlPropertyMap>
-#include <QQuickWidget>
-
-QT_BEGIN_NAMESPACE
-class QShortcut;
-QT_END_NAMESPACE
-
-namespace QmlDesigner {
-
-class NodeInstanceView;
-
-namespace Experimental {
-
-class StatesEditorModel;
-class StatesEditorView;
-
-namespace Internal { class StatesEditorImageProvider; }
-
-class StatesEditorWidget : public QQuickWidget
-{
- Q_OBJECT
-
-public:
- StatesEditorWidget(StatesEditorView *m_statesEditorView, StatesEditorModel *statesEditorModel);
- ~StatesEditorWidget() override;
-
- int currentStateInternalId() const;
- void setCurrentStateInternalId(int internalId);
- void setNodeInstanceView(const NodeInstanceView *nodeInstanceView);
-
- void showAddNewStatesButton(bool showAddNewStatesButton);
-
- static QString qmlSourcesPath();
-
-protected:
- void showEvent(QShowEvent *) override;
- void focusOutEvent(QFocusEvent *focusEvent) override;
- void focusInEvent(QFocusEvent *focusEvent) override;
-
-private:
- void reloadQmlSource();
-
-private:
- QPointer<StatesEditorView> m_statesEditorView;
- Internal::StatesEditorImageProvider *m_imageProvider;
- QShortcut *m_qmlSourceUpdateShortcut;
- QElapsedTimer m_usageTimer;
-};
-
-} // namespace Experimental
-} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/textureeditor/textureeditorcontextobject.cpp b/src/plugins/qmldesigner/components/textureeditor/textureeditorcontextobject.cpp
index 1148e31e2b..8d1b03bddd 100644
--- a/src/plugins/qmldesigner/components/textureeditor/textureeditorcontextobject.cpp
+++ b/src/plugins/qmldesigner/components/textureeditor/textureeditorcontextobject.cpp
@@ -315,17 +315,8 @@ QStringList TextureEditorContextObject::allStatesForId(const QString &id)
return {};
}
-bool TextureEditorContextObject::isBlocked(const QString &propName) const
+bool TextureEditorContextObject::isBlocked(const QString &) const
{
- if (!m_selectedTexture.isValid())
- return false;
-
- if (!m_model || !m_model->rewriterView())
- return false;
-
- if (QmlObjectNode(m_selectedTexture).isBlocked(propName.toUtf8()))
- return true;
-
return false;
}
diff --git a/src/plugins/qmldesigner/components/textureeditor/textureeditorqmlbackend.cpp b/src/plugins/qmldesigner/components/textureeditor/textureeditorqmlbackend.cpp
index e54909049e..1325ade10c 100644
--- a/src/plugins/qmldesigner/components/textureeditor/textureeditorqmlbackend.cpp
+++ b/src/plugins/qmldesigner/components/textureeditor/textureeditorqmlbackend.cpp
@@ -34,7 +34,7 @@
static QObject *variantToQObject(const QVariant &value)
{
- if (value.userType() == QMetaType::QObjectStar || value.userType() > QMetaType::User)
+ if (value.typeId() == QMetaType::QObjectStar || value.typeId() > QMetaType::User)
return *(QObject **)value.constData();
return nullptr;
@@ -109,7 +109,7 @@ void TextureEditorQmlBackend::createPropertyEditorValue(const QmlObjectNode &qml
void TextureEditorQmlBackend::setValue(const QmlObjectNode &, const PropertyName &name, const QVariant &value)
{
// Vector*D values need to be split into their subcomponents
- if (value.type() == QVariant::Vector2D) {
+ if (value.typeId() == QVariant::Vector2D) {
const char *suffix[2] = {"_x", "_y"};
auto vecValue = value.value<QVector2D>();
for (int i = 0; i < 2; ++i) {
@@ -120,7 +120,7 @@ void TextureEditorQmlBackend::setValue(const QmlObjectNode &, const PropertyName
if (propertyValue)
propertyValue->setValue(QVariant(vecValue[i]));
}
- } else if (value.type() == QVariant::Vector3D) {
+ } else if (value.typeId() == QVariant::Vector3D) {
const char *suffix[3] = {"_x", "_y", "_z"};
auto vecValue = value.value<QVector3D>();
for (int i = 0; i < 3; ++i) {
@@ -131,7 +131,7 @@ void TextureEditorQmlBackend::setValue(const QmlObjectNode &, const PropertyName
if (propertyValue)
propertyValue->setValue(QVariant(vecValue[i]));
}
- } else if (value.type() == QVariant::Vector4D) {
+ } else if (value.typeId() == QVariant::Vector4D) {
const char *suffix[4] = {"_x", "_y", "_z", "_w"};
auto vecValue = value.value<QVector4D>();
for (int i = 0; i < 4; ++i) {
diff --git a/src/plugins/qmldesigner/components/textureeditor/textureeditorview.cpp b/src/plugins/qmldesigner/components/textureeditor/textureeditorview.cpp
index 221de40509..98601ce45e 100644
--- a/src/plugins/qmldesigner/components/textureeditor/textureeditorview.cpp
+++ b/src/plugins/qmldesigner/components/textureeditor/textureeditorview.cpp
@@ -141,7 +141,7 @@ void TextureEditorView::changeValue(const QString &name)
if (name == "state" && castedValue.toString() == "base state")
castedValue = "";
- if (castedValue.type() == QVariant::Color) {
+ if (castedValue.typeId() == QVariant::Color) {
QColor color = castedValue.value<QColor>();
QColor newColor = QColor(color.name());
newColor.setAlpha(color.alpha());
@@ -389,8 +389,11 @@ void TextureEditorView::handleToolBarAction(int action)
}
case TextureEditorContextObject::DeleteCurrentTexture: {
- if (m_selectedTexture.isValid())
- m_selectedTexture.destroy();
+ if (m_selectedTexture.isValid()) {
+ executeInTransaction(__FUNCTION__, [&] {
+ m_selectedTexture.destroy();
+ });
+ }
break;
}
diff --git a/src/plugins/qmldesigner/components/timelineeditor/canvas.cpp b/src/plugins/qmldesigner/components/timelineeditor/canvas.cpp
index f82d2098c6..66f207bd83 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/canvas.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/canvas.cpp
@@ -134,7 +134,7 @@ void Canvas::paintCurve(QPainter *painter, const EasingCurve &curve, const QColo
void Canvas::paintControlPoints(QPainter *painter, const EasingCurve &curve)
{
QVector<QPointF> points = curve.toCubicSpline();
- int count = points.count();
+ int count = points.size();
if (count <= 1)
return;
diff --git a/src/plugins/qmldesigner/components/timelineeditor/easingcurve.cpp b/src/plugins/qmldesigner/components/timelineeditor/easingcurve.cpp
index 92f7590503..ae9833e46e 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/easingcurve.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/easingcurve.cpp
@@ -49,7 +49,7 @@ void EasingCurve::registerStreamOperators()
int EasingCurve::count() const
{
- return toCubicSpline().count();
+ return toCubicSpline().size();
}
int EasingCurve::active() const
@@ -59,7 +59,7 @@ int EasingCurve::active() const
int EasingCurve::segmentCount() const
{
- return toCubicSpline().count() / 3;
+ return toCubicSpline().size() / 3;
}
bool EasingCurve::isLegal() const
@@ -127,10 +127,10 @@ bool EasingCurve::fromString(const QString &code)
if (code.startsWith(QLatin1Char('[')) && code.endsWith(QLatin1Char(']'))) {
const auto stringList = code.mid(1, code.size() - 2).split(QLatin1Char(','), Qt::SkipEmptyParts);
- if (stringList.count() >= 6 && (stringList.count() % 6 == 0)) {
+ if (stringList.size() >= 6 && (stringList.size() % 6 == 0)) {
bool checkX, checkY;
QVector<QPointF> points;
- for (int i = 0; i < stringList.count(); ++i) {
+ for (int i = 0; i < stringList.size(); ++i) {
QPointF point;
point.rx() = stringList[i].toDouble(&checkX);
point.ry() = stringList[++i].toDouble(&checkY);
@@ -146,7 +146,7 @@ bool EasingCurve::fromString(const QString &code)
QEasingCurve easingCurve(QEasingCurve::BezierSpline);
- for (int i = 0; i < points.count() / 3; ++i) {
+ for (int i = 0; i < points.size() / 3; ++i) {
easingCurve.addCubicBezierSegment(points.at(i * 3),
points.at(i * 3 + 1),
points.at(i * 3 + 2));
@@ -176,7 +176,7 @@ QPainterPath EasingCurve::path() const
QVector<QPointF> controlPoints = toCubicSpline();
- int numSegments = controlPoints.count() / 3;
+ int numSegments = controlPoints.size() / 3;
for (int i = 0; i < numSegments; i++) {
QPointF p1 = controlPoints.at(i * 3);
QPointF p2 = controlPoints.at(i * 3 + 1);
@@ -202,7 +202,7 @@ QPointF EasingCurve::point(int idx) const
{
QVector<QPointF> controlPoints = toCubicSpline();
- QTC_ASSERT(controlPoints.count() > idx || idx < 0, return QPointF());
+ QTC_ASSERT(controlPoints.size() > idx || idx < 0, return QPointF());
return controlPoints.at(idx);
}
@@ -259,7 +259,7 @@ void EasingCurve::makeSmooth(int idx)
before = controlPoints.at(idx - 3);
QPointF after = end();
- if ((idx + 3) < controlPoints.count())
+ if ((idx + 3) < controlPoints.size())
after = controlPoints.at(idx + 3);
QPointF tangent = (after - before) / 6;
@@ -269,7 +269,7 @@ void EasingCurve::makeSmooth(int idx)
if (idx > 0)
controlPoints[idx - 1] = thisPoint - tangent;
- if (idx + 1 < controlPoints.count())
+ if (idx + 1 < controlPoints.size())
controlPoints[idx + 1] = thisPoint + tangent;
fromCubicSpline(controlPoints);
@@ -288,7 +288,7 @@ void EasingCurve::breakTangent(int idx)
before = controlPoints.at(idx - 3);
QPointF after = end();
- if ((idx + 3) < controlPoints.count())
+ if ((idx + 3) < controlPoints.size())
after = controlPoints.at(idx + 3);
QPointF thisPoint = controlPoints.at(idx);
@@ -296,7 +296,7 @@ void EasingCurve::breakTangent(int idx)
if (idx > 0)
controlPoints[idx - 1] = (before - thisPoint) / 3 + thisPoint;
- if (idx + 1 < controlPoints.count())
+ if (idx + 1 < controlPoints.size())
controlPoints[idx + 1] = (after - thisPoint) / 3 + thisPoint;
fromCubicSpline(controlPoints);
@@ -326,7 +326,7 @@ void EasingCurve::addPoint(const QPointF &point)
}
QPointF after = end();
- if ((splitIndex + 3) < controlPoints.count()) {
+ if ((splitIndex + 3) < controlPoints.size()) {
after = controlPoints.at(splitIndex + 3);
}
@@ -394,7 +394,7 @@ void EasingCurve::fromCubicSpline(const QVector<QPointF> &points)
{
QEasingCurve tmp(QEasingCurve::BezierSpline);
- int numSegments = points.count() / 3;
+ int numSegments = points.size() / 3;
for (int i = 0; i < numSegments; ++i) {
tmp.addCubicBezierSegment(points.at(i * 3), points.at(i * 3 + 1), points.at(i * 3 + 2));
}
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelineanimationform.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelineanimationform.cpp
index d7b700dde8..83551378ee 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/timelineanimationform.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelineanimationform.cpp
@@ -292,7 +292,7 @@ void TimelineAnimationForm::populateStateComboBox()
if (m_animation.signalHandlerProperty("onFinished").isValid()) {
const QString source = m_animation.signalHandlerProperty("onFinished").source();
const QStringList list = source.split("=");
- if (list.count() == 2) {
+ if (list.size() == 2) {
QString name = list.last().trimmed();
name.chop(1);
name.remove(0, 1);
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinecontrols.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinecontrols.cpp
index d9f3dd4d16..708bd8c4d3 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/timelinecontrols.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinecontrols.cpp
@@ -78,7 +78,7 @@ QVariant FloatControl::controlValue() const
void FloatControl::setControlValue(const QVariant &value)
{
- if (value.userType() != QMetaType::Float && value.userType() != QMetaType::Double)
+ if (value.typeId() != QMetaType::Float && value.typeId() != QMetaType::Double)
return;
QSignalBlocker blocker(this);
@@ -129,7 +129,7 @@ QVariant ColorControl::controlValue() const
void ColorControl::setControlValue(const QVariant &value)
{
- if (value.userType() != QMetaType::QColor)
+ if (value.typeId() != QMetaType::QColor)
return;
m_color = qvariant_cast<QColor>(value);
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinegraphicsscene.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinegraphicsscene.cpp
index ddddc7c753..f116d96223 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/timelinegraphicsscene.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinegraphicsscene.cpp
@@ -386,7 +386,7 @@ bool AbstractScrollGraphicsScene::isKeyframeSelected(TimelineKeyframeItem *keyfr
bool AbstractScrollGraphicsScene::multipleKeyframesSelected() const
{
- return m_selectedKeyframes.count() > 1;
+ return m_selectedKeyframes.size() > 1;
}
void TimelineGraphicsScene::invalidateSectionForTarget(const ModelNode &target)
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.cpp
index 8c0a9c9d73..6dcb39f2a0 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.cpp
@@ -105,7 +105,7 @@ static void editValue(const ModelNode &frameNode, const std::pair<qreal, qreal>
if (newFrame != frame)
frameNode.variantProperty("frame").setValue(newFrame);
- int userType = value.userType();
+ int userType = value.typeId();
QVariant newValue = dialog->value();
if (newValue.canConvert(userType)) {
@@ -264,7 +264,7 @@ bool TimelinePropertyItem::isSelected() const
QString convertVariant(const QVariant &variant)
{
- if (variant.userType() == QMetaType::QColor)
+ if (variant.typeId() == QMetaType::QColor)
return variant.toString();
return QString::number(variant.toFloat(), 'f', 2);
@@ -335,9 +335,8 @@ void TimelinePropertyItem::changePropertyValue(const QVariant &value)
QTimer::singleShot(0, deferredFunc);
} else {
- QScopedPointer<QmlObjectNode> objectNode {
- QmlObjectNode::getQmlObjectNodeOfCorrectType(m_frames.target())};
- objectNode->setVariantProperty(m_frames.propertyName(), value);
+ if (auto qmlObjectNode = QmlObjectNode(m_frames.target()))
+ qmlObjectNode.setVariantProperty(m_frames.propertyName(), value);
}
}
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinesectionitem.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinesectionitem.cpp
index 4604e9e3b8..7a733c3729 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/timelinesectionitem.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinesectionitem.cpp
@@ -420,7 +420,7 @@ void TimelineSectionItem::invalidateHeight()
visible = false;
} else {
height = TimelineConstants::sectionHeight
- + m_timeline.keyframeGroupsForTarget(m_targetNode).count()
+ + m_timeline.keyframeGroupsForTarget(m_targetNode).size()
* TimelineConstants::sectionHeight;
visible = true;
}
@@ -801,7 +801,7 @@ void TimelineRulerSectionItem::extendPlaybackLoop(const QList<qreal> &positions,
qreal right = m_playbackLoopEnd;
if (reset) {
- if (positions.count() >= 2) {
+ if (positions.size() >= 2) {
left = m_duration;
right = 0;
} else {
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelineselectiontool.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelineselectiontool.cpp
index 68aeefcd23..230ab401a7 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/timelineselectiontool.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelineselectiontool.cpp
@@ -169,7 +169,7 @@ void TimelineSelectionTool::aboutToSelect(SelectionMode mode, QList<QGraphicsIte
void TimelineSelectionTool::commitSelection(SelectionMode mode)
{
- if (m_playbackLoopTimeSteps.count())
+ if (m_playbackLoopTimeSteps.size())
qobject_cast<TimelineGraphicsScene *>(scene())->layoutRuler()->extendPlaybackLoop(m_playbackLoopTimeSteps,
mode == SelectionMode::Toggle); // TODO: Highlighting items with selection tool is set or added to loop range. Select shortcut for this QDS-4941
scene()->selectKeyframes(mode, m_aboutToSelectBuffer);
diff --git a/src/plugins/qmldesigner/components/toolbar/toolbarbackend.cpp b/src/plugins/qmldesigner/components/toolbar/toolbarbackend.cpp
index 1b9f1e3271..c917dfe8a8 100644
--- a/src/plugins/qmldesigner/components/toolbar/toolbarbackend.cpp
+++ b/src/plugins/qmldesigner/components/toolbar/toolbarbackend.cpp
@@ -86,7 +86,7 @@ CrumbleBarModel::CrumbleBarModel(QObject *)
int CrumbleBarModel::rowCount(const QModelIndex &) const
{
- return crumbleBar()->path().count();
+ return crumbleBar()->path().size();
}
QHash<int, QByteArray> CrumbleBarModel::roleNames() const
@@ -148,7 +148,7 @@ WorkspaceModel::WorkspaceModel(QObject *)
int WorkspaceModel::rowCount(const QModelIndex &) const
{
if (designModeWidget() && designModeWidget()->dockManager())
- return designModeWidget()->dockManager()->workspaces().count();
+ return designModeWidget()->dockManager()->workspaces().size();
return 0;
}
@@ -476,7 +476,7 @@ void ToolBarBackend::setCurrentStyle(int index)
QmlDesignerPlugin::emitUsageStatistics(Constants::EVENT_STATUSBAR_SET_STYLE);
const QList<StyleWidgetEntry> items = ChangeStyleWidgetAction::getAllStyleItems();
- QTC_ASSERT(items.count() > index, return );
+ QTC_ASSERT(items.size() > index, return);
QTC_ASSERT(index > 0, return );
QTC_ASSERT(currentDesignDocument(), return );
@@ -499,7 +499,7 @@ void ToolBarBackend::setCurrentKit(int index)
const auto kits = ProjectExplorer::KitManager::kits();
- QTC_ASSERT(kits.count() > index, return );
+ QTC_ASSERT(kits.size() > index, return);
QTC_ASSERT(index >= 0, return );
const auto kit = kits.at(index);
diff --git a/src/plugins/qmldesigner/components/transitioneditor/transitioneditorsectionitem.cpp b/src/plugins/qmldesigner/components/transitioneditor/transitioneditorsectionitem.cpp
index d331e82b40..a5ec84fad2 100644
--- a/src/plugins/qmldesigner/components/transitioneditor/transitioneditorsectionitem.cpp
+++ b/src/plugins/qmldesigner/components/transitioneditor/transitioneditorsectionitem.cpp
@@ -441,7 +441,7 @@ void TransitionEditorSectionItem::invalidateHeight()
model->qtQuickPropertyAnimationMetaInfo());
height = TimelineConstants::sectionHeight
- + propertyAnimations.count() * TimelineConstants::sectionHeight;
+ + propertyAnimations.size() * TimelineConstants::sectionHeight;
visible = true;
}
diff --git a/src/plugins/qmldesigner/components/transitioneditor/transitioneditorview.cpp b/src/plugins/qmldesigner/components/transitioneditor/transitioneditorview.cpp
index 03ebf4738e..c24ebc1ce3 100644
--- a/src/plugins/qmldesigner/components/transitioneditor/transitioneditorview.cpp
+++ b/src/plugins/qmldesigner/components/transitioneditor/transitioneditorview.cpp
@@ -201,7 +201,7 @@ ModelNode TransitionEditorView::addNewTransition()
const ModelNode target = change.target();
if (auto targetMetaInfo = target.metaInfo()) {
const QString targetId = target.id();
- for (const VariantProperty &property : change.modelNode().variantProperties()) {
+ for (const AbstractProperty &property : change.modelNode().properties()) {
auto type = targetMetaInfo.property(property.name()).propertyType();
if (type.isInteger() || type.isColor() || type.isFloat())
diff --git a/src/plugins/qmldesigner/components/transitioneditor/transitionform.cpp b/src/plugins/qmldesigner/components/transitioneditor/transitionform.cpp
index 9613be5178..c58bdf61d5 100644
--- a/src/plugins/qmldesigner/components/transitioneditor/transitionform.cpp
+++ b/src/plugins/qmldesigner/components/transitioneditor/transitionform.cpp
@@ -66,7 +66,7 @@ TransitionForm::TransitionForm(QWidget *parent)
QTC_ASSERT(m_transition.isValid(), return );
const QmlItemNode root(m_transition.view()->rootModelNode());
QTC_ASSERT(root.isValid(), return );
- const int stateCount = root.states().names().count();
+ const int stateCount = root.states().names().size();
QStringList stateNames;
@@ -76,7 +76,7 @@ TransitionForm::TransitionForm(QWidget *parent)
}
QString toValue;
- if (stateCount == stateNames.count())
+ if (stateCount == stateNames.size())
toValue = "*";
else
toValue = stateNames.join(",");
@@ -90,7 +90,7 @@ TransitionForm::TransitionForm(QWidget *parent)
QTC_ASSERT(m_transition.isValid(), return );
const QmlItemNode root(m_transition.view()->rootModelNode());
QTC_ASSERT(root.isValid(), return );
- const int stateCount = root.states().names().count();
+ const int stateCount = root.states().names().size();
QStringList stateNames;
@@ -100,7 +100,7 @@ TransitionForm::TransitionForm(QWidget *parent)
}
QString fromValue;
- if (stateCount == stateNames.count())
+ if (stateCount == stateNames.size())
fromValue = "*";
else
fromValue = stateNames.join(",");
diff --git a/src/plugins/qmldesigner/designercore/imagecache/imagecacheconnectionmanager.cpp b/src/plugins/qmldesigner/designercore/imagecache/imagecacheconnectionmanager.cpp
index ee40b3ec31..20728b445e 100644
--- a/src/plugins/qmldesigner/designercore/imagecache/imagecacheconnectionmanager.cpp
+++ b/src/plugins/qmldesigner/designercore/imagecache/imagecacheconnectionmanager.cpp
@@ -47,7 +47,7 @@ void ImageCacheConnectionManager::dispatchCommand(const QVariant &command,
{
static const int capturedDataCommandType = QMetaType::type("CapturedDataCommand");
- if (command.userType() == capturedDataCommandType) {
+ if (command.typeId() == capturedDataCommandType) {
m_captureCallback(command.value<CapturedDataCommand>().image);
m_capturedDataArrived = true;
}
diff --git a/src/plugins/qmldesigner/designercore/imagecache/imagecachestorage.h b/src/plugins/qmldesigner/designercore/imagecache/imagecachestorage.h
index 37131012d6..0306349b23 100644
--- a/src/plugins/qmldesigner/designercore/imagecache/imagecachestorage.h
+++ b/src/plugins/qmldesigner/designercore/imagecache/imagecachestorage.h
@@ -30,6 +30,7 @@ public:
: database(database)
{
transaction.commit();
+ database.walCheckpointFull();
}
ImageEntry fetchImage(Utils::SmallStringView name, Sqlite::TimeStamp minimumTimeStamp) const override
@@ -157,16 +158,10 @@ private:
Initializer(DatabaseType &database)
{
if (!database.isInitialized()) {
- Sqlite::ExclusiveTransaction transaction{database};
-
createImagesTable(database);
database.setVersion(1);
- transaction.commit();
-
database.setIsInitialized(true);
-
- database.walCheckpointFull();
} else if (database.version() < 1) {
updateTableToVersion1(database);
}
@@ -203,13 +198,9 @@ private:
void updateTableToVersion1(DatabaseType &database)
{
- Sqlite::ExclusiveTransaction transaction{database};
-
database.execute("DELETE FROM images");
database.execute("ALTER TABLE images ADD COLUMN midSizeImage");
database.setVersion(1);
-
- transaction.commit();
}
};
@@ -277,8 +268,8 @@ private:
public:
DatabaseType &database;
+ Sqlite::ExclusiveNonThrowingDestructorTransaction<DatabaseType> transaction{database};
Initializer initializer{database};
- Sqlite::ImmediateNonThrowingDestructorTransaction<DatabaseType> transaction{database};
mutable ReadStatement<1, 2> selectImageStatement{
"SELECT image FROM images WHERE name=?1 AND mtime >= ?2", database};
mutable ReadStatement<1, 2> selectMidSizeImageStatement{
diff --git a/src/plugins/qmldesigner/designercore/include/abstractproperty.h b/src/plugins/qmldesigner/designercore/include/abstractproperty.h
index c22402202d..6074858265 100644
--- a/src/plugins/qmldesigner/designercore/include/abstractproperty.h
+++ b/src/plugins/qmldesigner/designercore/include/abstractproperty.h
@@ -19,7 +19,7 @@ namespace QmlDesigner {
class InternalProperty;
using InternalNodePointer = std::shared_ptr<InternalNode>;
- using InternalPropertyPointer = QSharedPointer<InternalProperty>;
+ using InternalPropertyPointer = std::shared_ptr<InternalProperty>;
}
class Model;
@@ -45,9 +45,6 @@ class QMLDESIGNERCORE_EXPORT AbstractProperty
friend ModelNode;
friend Internal::ModelPrivate;
- friend QMLDESIGNERCORE_EXPORT bool operator ==(const AbstractProperty &property1, const AbstractProperty &property2);
- friend QMLDESIGNERCORE_EXPORT bool operator !=(const AbstractProperty &property1, const AbstractProperty &property2);
-
public:
AbstractProperty() = default;
AbstractProperty(const AbstractProperty &) = default;
@@ -82,6 +79,8 @@ public:
bool isSignalHandlerProperty() const;
bool isSignalDeclarationProperty() const;
+ PropertyType type() const;
+
bool isDynamic() const;
TypeName dynamicTypeName() const;
@@ -107,10 +106,27 @@ public:
return ::qHash(property.m_internalNode.get()) ^ ::qHash(property.m_propertyName);
}
+ friend bool operator==(const AbstractProperty &first, const AbstractProperty &second)
+ {
+ return first.m_internalNode == second.m_internalNode
+ && first.m_propertyName == second.m_propertyName;
+ }
+
+ friend bool operator!=(const AbstractProperty &first, const AbstractProperty &second)
+ {
+ return !(first == second);
+ }
+
+ friend bool operator<(const AbstractProperty &first, const AbstractProperty &second)
+ {
+ return std::tie(first.m_internalNode, first.m_propertyName)
+ < std::tie(second.m_internalNode, second.m_propertyName);
+ }
+
protected:
AbstractProperty(const PropertyName &propertyName, const Internal::InternalNodePointer &internalNode, Model* model, AbstractView *view);
AbstractProperty(const Internal::InternalPropertyPointer &property, Model* model, AbstractView *view);
- Internal::InternalNodePointer internalNode() const;
+ Internal::InternalNodePointer internalNode() const { return m_internalNode; }
Internal::ModelPrivate *privateModel() const;
private:
@@ -120,8 +136,8 @@ private:
QPointer<AbstractView> m_view;
};
-QMLDESIGNERCORE_EXPORT bool operator ==(const AbstractProperty &property1, const AbstractProperty &property2);
-QMLDESIGNERCORE_EXPORT bool operator !=(const AbstractProperty &property1, const AbstractProperty &property2);
+using AbstractProperties = QList<AbstractProperty>;
+
QMLDESIGNERCORE_EXPORT QTextStream& operator<<(QTextStream &stream, const AbstractProperty &property);
QMLDESIGNERCORE_EXPORT QDebug operator<<(QDebug debug, const AbstractProperty &AbstractProperty);
}
diff --git a/src/plugins/qmldesigner/designercore/include/abstractview.h b/src/plugins/qmldesigner/designercore/include/abstractview.h
index 0c3df94030..9035aba0fd 100644
--- a/src/plugins/qmldesigner/designercore/include/abstractview.h
+++ b/src/plugins/qmldesigner/designercore/include/abstractview.h
@@ -119,6 +119,7 @@ public:
bool hasModelNodeForInternalId(qint32 internalId) const;
QList<ModelNode> allModelNodes() const;
+ QList<ModelNode> allModelNodesUnordered() const;
QList<ModelNode> allModelNodesOfType(const NodeMetaInfo &typeName) const;
void emitDocumentMessage(const QList<DocumentMessage> &errors, const QList<DocumentMessage> &warnings = {});
@@ -161,7 +162,8 @@ public:
virtual void variantPropertiesChanged(const QList<VariantProperty> &propertyList,
PropertyChangeFlags propertyChange);
virtual void bindingPropertiesAboutToBeChanged(const QList<BindingProperty> &propertyList);
- virtual void bindingPropertiesChanged(const QList<BindingProperty> &propertyList, PropertyChangeFlags propertyChange);
+ virtual void bindingPropertiesChanged(const QList<BindingProperty> &propertyList,
+ PropertyChangeFlags propertyChange);
virtual void signalHandlerPropertiesChanged(const QVector<SignalHandlerProperty> &propertyList,
PropertyChangeFlags propertyChange);
virtual void signalDeclarationPropertiesChanged(const QVector<SignalDeclarationProperty> &propertyList,
@@ -304,5 +306,6 @@ private:
};
QMLDESIGNERCORE_EXPORT QList<Internal::InternalNodePointer> toInternalNodeList(const QList<ModelNode> &nodeList);
-QMLDESIGNERCORE_EXPORT QList<ModelNode> toModelNodeList(const QList<Internal::InternalNodePointer> &nodeList, AbstractView *view);
+QMLDESIGNERCORE_EXPORT QList<ModelNode> toModelNodeList(
+ const QList<Internal::InternalNodePointer> &nodeList, Model *model, AbstractView *view);
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/include/bindingproperty.h b/src/plugins/qmldesigner/designercore/include/bindingproperty.h
index 904866f041..3ddf554c2c 100644
--- a/src/plugins/qmldesigner/designercore/include/bindingproperty.h
+++ b/src/plugins/qmldesigner/designercore/include/bindingproperty.h
@@ -40,9 +40,17 @@ public:
static QVariant convertToLiteral(const TypeName &typeName, const QString &expression);
protected:
- BindingProperty(const PropertyName &propertyName, const Internal::InternalNodePointer &internalNode, Model* model, AbstractView *view);
+ BindingProperty(const PropertyName &propertyName,
+ const Internal::InternalNodePointer &internalNode,
+ Model *model,
+ AbstractView *view);
+
+private:
+ ModelNode resolveBinding(const QString &binding, ModelNode currentNode) const;
};
+using BindingProperties = QList<BindingProperty>;
+
bool compareBindingProperties(const QmlDesigner::BindingProperty &bindingProperty01, const QmlDesigner::BindingProperty &bindingProperty02);
QMLDESIGNERCORE_EXPORT QTextStream& operator<<(QTextStream &stream, const BindingProperty &property);
diff --git a/src/plugins/qmldesigner/designercore/include/model.h b/src/plugins/qmldesigner/designercore/include/model.h
index c2cd807a8a..3dbb0cceac 100644
--- a/src/plugins/qmldesigner/designercore/include/model.h
+++ b/src/plugins/qmldesigner/designercore/include/model.h
@@ -34,6 +34,7 @@ class AbstractView;
class NodeStateChangeSet;
class MetaInfo;
class NodeMetaInfo;
+class NodeMetaInfoPrivate;
class ModelState;
class NodeAnchors;
class AbstractProperty;
@@ -43,15 +44,18 @@ class TextModifier;
using PropertyListType = QList<QPair<PropertyName, QVariant>>;
+enum class BypassModelResourceManagement { No, Yes };
+
class QMLDESIGNERCORE_EXPORT Model : public QObject
{
friend ModelNode;
+ friend NodeMetaInfo;
+ friend NodeMetaInfoPrivate;
friend AbstractProperty;
friend AbstractView;
friend Internal::ModelPrivate;
friend Internal::WriteLocker;
friend ModelDeleter;
- friend class NodeMetaInfoPrivate;
Q_OBJECT
@@ -101,7 +105,9 @@ public:
bool hasNodeMetaInfo(const TypeName &typeName, int majorVersion = -1, int minorVersion = -1) const;
void setMetaInfo(const MetaInfo &metaInfo);
+ NodeMetaInfo flowViewFlowActionAreaMetaInfo() const;
NodeMetaInfo flowViewFlowDecisionMetaInfo() const;
+ NodeMetaInfo flowViewFlowItemMetaInfo() const;
NodeMetaInfo flowViewFlowTransitionMetaInfo() const;
NodeMetaInfo flowViewFlowWildcardMetaInfo() const;
NodeMetaInfo fontMetaInfo() const;
@@ -117,12 +123,14 @@ public:
NodeMetaInfo qtQuickImageMetaInfo() const;
NodeMetaInfo qtQuickItemMetaInfo() const;
NodeMetaInfo qtQuickPropertyAnimationMetaInfo() const;
+ NodeMetaInfo qtQuickPropertyChangesMetaInfo() const;
NodeMetaInfo qtQuickRectangleMetaInfo() const;
NodeMetaInfo qtQuickStateGroupMetaInfo() const;
NodeMetaInfo qtQuickTextEditMetaInfo() const;
NodeMetaInfo qtQuickTextMetaInfo() const;
NodeMetaInfo qtQuickTimelineKeyframeGroupMetaInfo() const;
NodeMetaInfo qtQuickTimelineTimelineMetaInfo() const;
+ NodeMetaInfo qtQuickTransistionMetaInfo() const;
NodeMetaInfo vector2dMetaInfo() const;
NodeMetaInfo vector3dMetaInfo() const;
NodeMetaInfo vector4dMetaInfo() const;
@@ -130,7 +138,18 @@ public:
void attachView(AbstractView *view);
void detachView(AbstractView *view, ViewNotification emitDetachNotify = NotifyView);
- QList<ModelNode> allModelNodes() const;
+ QList<ModelNode> allModelNodesUnordered();
+ ModelNode rootModelNode();
+
+ ModelNode modelNodeForId(const QString &id);
+ QHash<QStringView, ModelNode> idModelNodeDict();
+
+ ModelNode createModelNode(const TypeName &typeName);
+
+ void removeModelNodes(ModelNodes nodes,
+ BypassModelResourceManagement = BypassModelResourceManagement::No);
+ void removeProperties(AbstractProperties properties,
+ BypassModelResourceManagement = BypassModelResourceManagement::No);
// Editing sub-components:
@@ -155,8 +174,6 @@ public:
Model *metaInfoProxyModel() const;
- TextModifier *textModifier() const;
- void setTextModifier(TextModifier *textModifier);
void setDocumentMessages(const QList<DocumentMessage> &errors,
const QList<DocumentMessage> &warnings);
diff --git a/src/plugins/qmldesigner/designercore/include/modelfwd.h b/src/plugins/qmldesigner/designercore/include/modelfwd.h
index 6671249995..44154ce10b 100644
--- a/src/plugins/qmldesigner/designercore/include/modelfwd.h
+++ b/src/plugins/qmldesigner/designercore/include/modelfwd.h
@@ -39,4 +39,14 @@ using ProjectStorageType = ProjectStorageInterface;
using ProjectStorageType = ProjectStorage<Sqlite::Database>;
#endif
+enum class PropertyType {
+ None,
+ Variant,
+ Node,
+ NodeList,
+ Binding,
+ SignalHandler,
+ SignalDeclaration
+};
+
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/include/modelnode.h b/src/plugins/qmldesigner/designercore/include/modelnode.h
index e9891da620..657093b0ac 100644
--- a/src/plugins/qmldesigner/designercore/include/modelnode.h
+++ b/src/plugins/qmldesigner/designercore/include/modelnode.h
@@ -28,7 +28,7 @@ namespace Internal {
class InternalProperty;
using InternalNodePointer = std::shared_ptr<InternalNode>;
- using InternalPropertyPointer = QSharedPointer<InternalProperty>;
+ using InternalPropertyPointer = std::shared_ptr<InternalProperty>;
}
class NodeMetaInfo;
class BindingProperty;
@@ -58,10 +58,7 @@ inline constexpr AuxiliaryDataKeyView transitionExpandedPropery{AuxiliaryDataTyp
class QMLDESIGNERCORE_EXPORT ModelNode
{
- friend QMLDESIGNERCORE_EXPORT bool operator ==(const ModelNode &firstNode, const ModelNode &secondNode);
- friend QMLDESIGNERCORE_EXPORT bool operator !=(const ModelNode &firstNode, const ModelNode &secondNode);
friend QMLDESIGNERCORE_EXPORT QDebug operator<<(QDebug debug, const ModelNode &modelNode);
- friend QMLDESIGNERCORE_EXPORT bool operator <(const ModelNode &firstNode, const ModelNode &secondNode);
friend QMLDESIGNERCORE_EXPORT QList<Internal::InternalNodePointer> toInternalNodeList(const QList<ModelNode> &nodeList);
friend Model;
friend AbstractView;
@@ -77,7 +74,7 @@ public:
NodeWithComponentSource = 2
};
- ModelNode();
+ ModelNode() = default;
ModelNode(const Internal::InternalNodePointer &internalNode, Model *model, const AbstractView *view);
ModelNode(const ModelNode &modelNode, AbstractView *view);
ModelNode(const ModelNode &) = default;
@@ -176,7 +173,7 @@ public:
void selectNode();
void deselectNode();
- static int variantUserType();
+ static int variantTypeId();
QVariant toVariant() const;
std::optional<QVariant> auxiliaryData(AuxiliaryDataKeyView key) const;
@@ -254,6 +251,21 @@ public:
friend auto qHash(const ModelNode &node) { return ::qHash(node.m_internalNode.get()); }
+ friend bool operator==(const ModelNode &firstNode, const ModelNode &secondNode)
+ {
+ return firstNode.m_internalNode == secondNode.m_internalNode;
+ }
+
+ friend bool operator!=(const ModelNode &firstNode, const ModelNode &secondNode)
+ {
+ return !(firstNode == secondNode);
+ }
+
+ friend bool operator<(const ModelNode &firstNode, const ModelNode &secondNode)
+ {
+ return firstNode.m_internalNode < secondNode.m_internalNode;
+ }
+
private: // functions
Internal::InternalNodePointer internalNode() const;
@@ -265,9 +277,6 @@ private: // variables
QPointer<AbstractView> m_view;
};
-QMLDESIGNERCORE_EXPORT bool operator ==(const ModelNode &firstNode, const ModelNode &secondNode);
-QMLDESIGNERCORE_EXPORT bool operator !=(const ModelNode &firstNode, const ModelNode &secondNode);
-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);
diff --git a/src/plugins/qmldesigner/designercore/include/nodeabstractproperty.h b/src/plugins/qmldesigner/designercore/include/nodeabstractproperty.h
index d96840e51f..f4db733987 100644
--- a/src/plugins/qmldesigner/designercore/include/nodeabstractproperty.h
+++ b/src/plugins/qmldesigner/designercore/include/nodeabstractproperty.h
@@ -9,7 +9,7 @@ namespace QmlDesigner {
namespace Internal {
class InternalNodeAbstractProperty;
- using InternalNodeAbstractPropertyPointer = QSharedPointer<InternalNodeAbstractProperty>;
+ using InternalNodeAbstractPropertyPointer = std::shared_ptr<InternalNodeAbstractProperty>;
}
class QMLDESIGNERCORE_EXPORT NodeAbstractProperty : public AbstractProperty
diff --git a/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h b/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h
index 93b4e82a2a..fd7f21d090 100644
--- a/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h
+++ b/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h
@@ -67,7 +67,8 @@ public:
using Pointer = QWeakPointer<NodeInstanceView>;
explicit NodeInstanceView(ConnectionManagerInterface &connectionManager,
- ExternalDependenciesInterface &externalDependencies);
+ ExternalDependenciesInterface &externalDependencies,
+ bool qsbEnabled = false);
~NodeInstanceView() override;
void modelAttached(Model *model) override;
@@ -289,6 +290,7 @@ private:
QTimer m_rotBlockTimer;
QSize m_captureImageMinimumSize{150, 150};
QSize m_captureImageMaximumSize{1000, 1000};
+ bool m_qsbEnabled = false;
};
} // namespace ProxyNodeInstanceView
diff --git a/src/plugins/qmldesigner/designercore/include/nodelistproperty.h b/src/plugins/qmldesigner/designercore/include/nodelistproperty.h
index e0c25eb6c4..334a2a2758 100644
--- a/src/plugins/qmldesigner/designercore/include/nodelistproperty.h
+++ b/src/plugins/qmldesigner/designercore/include/nodelistproperty.h
@@ -16,7 +16,7 @@ namespace QmlDesigner {
namespace Internal {
class ModelPrivate;
class InternalNodeListProperty;
-using InternalNodeListPropertyPointer = QSharedPointer<InternalNodeListProperty>;
+using InternalNodeListPropertyPointer = std::shared_ptr<InternalNodeListProperty>;
class NodeListPropertyIterator
{
diff --git a/src/plugins/qmldesigner/designercore/include/nodemetainfo.h b/src/plugins/qmldesigner/designercore/include/nodemetainfo.h
index c7d1e2a342..55ce166d90 100644
--- a/src/plugins/qmldesigner/designercore/include/nodemetainfo.h
+++ b/src/plugins/qmldesigner/designercore/include/nodemetainfo.h
@@ -14,6 +14,7 @@
#include <QString>
#include <QIcon>
+#include <memory>
#include <optional>
#include <vector>
@@ -26,11 +27,12 @@ namespace QmlDesigner {
class MetaInfo;
class Model;
class AbstractProperty;
+class NodeMetaInfoPrivate;
class QMLDESIGNERCORE_EXPORT NodeMetaInfo
{
public:
- NodeMetaInfo() = default;
+ NodeMetaInfo();
NodeMetaInfo(Model *model, const TypeName &typeName, int majorVersion, int minorVersion);
NodeMetaInfo(TypeId typeId, NotNullPointer<const ProjectStorageType> projectStorage)
: m_typeId{typeId}
@@ -39,10 +41,17 @@ public:
NodeMetaInfo(NotNullPointer<const ProjectStorageType> projectStorage)
: m_projectStorage{projectStorage}
{}
+
+ NodeMetaInfo(const NodeMetaInfo &);
+ NodeMetaInfo &operator=(const NodeMetaInfo &);
+ NodeMetaInfo(NodeMetaInfo &&);
+ NodeMetaInfo &operator=(NodeMetaInfo &&);
~NodeMetaInfo();
bool isValid() const;
explicit operator bool() const { return isValid(); }
+
+ TypeId id() const { return m_typeId; }
bool isFileComponent() const;
bool hasProperty(::Utils::SmallStringView propertyName) const;
PropertyMetaInfos properties() const;
@@ -197,7 +206,7 @@ private:
TypeId m_typeId;
NotNullPointer<const ProjectStorageType> m_projectStorage = {};
mutable std::optional<Storage::Info::Type> m_typeData;
- QSharedPointer<class NodeMetaInfoPrivate> m_privateData;
+ std::shared_ptr<NodeMetaInfoPrivate> m_privateData;
};
using NodeMetaInfos = std::vector<NodeMetaInfo>;
diff --git a/src/plugins/qmldesigner/designercore/include/propertymetainfo.h b/src/plugins/qmldesigner/designercore/include/propertymetainfo.h
index a3c928bc36..99a704a406 100644
--- a/src/plugins/qmldesigner/designercore/include/propertymetainfo.h
+++ b/src/plugins/qmldesigner/designercore/include/propertymetainfo.h
@@ -9,21 +9,22 @@
#include <projectstorage/projectstoragetypes.h>
#include <projectstorageids.h>
-#include <QSharedPointer>
#include <QString>
+#include <memory>
#include <optional>
#include <vector>
namespace QmlDesigner {
class NodeMetaInfo;
+class NodeMetaInfoPrivate;
class QMLDESIGNERCORE_EXPORT PropertyMetaInfo
{
public:
- PropertyMetaInfo() = default;
- PropertyMetaInfo(QSharedPointer<class NodeMetaInfoPrivate> nodeMetaInfoPrivateData,
+ PropertyMetaInfo();
+ PropertyMetaInfo(std::shared_ptr<NodeMetaInfoPrivate> nodeMetaInfoPrivateData,
const PropertyName &propertyName);
PropertyMetaInfo([[maybe_unused]] PropertyDeclarationId id,
[[maybe_unused]] NotNullPointer<const ProjectStorageType> projectStorage)
@@ -32,6 +33,10 @@ public:
, m_id{id}
#endif
{}
+ PropertyMetaInfo(const PropertyMetaInfo &);
+ PropertyMetaInfo &operator=(const PropertyMetaInfo &);
+ PropertyMetaInfo(PropertyMetaInfo &&);
+ PropertyMetaInfo &operator=(PropertyMetaInfo &&);
~PropertyMetaInfo();
explicit operator bool() const { return isValid(); }
@@ -44,6 +49,9 @@ public:
return bool(m_nodeMetaInfoPrivateData);
#endif
}
+
+ PropertyDeclarationId id() const { return m_id; }
+
PropertyName name() const;
NodeMetaInfo propertyType() const;
bool isWritable() const;
@@ -74,7 +82,7 @@ private:
mutable std::optional<Storage::Info::PropertyDeclaration> m_propertyData;
PropertyDeclarationId m_id;
#ifndef QDS_USE_PROJECTSTORAGE
- QSharedPointer<class NodeMetaInfoPrivate> m_nodeMetaInfoPrivateData;
+ std::shared_ptr<NodeMetaInfoPrivate> m_nodeMetaInfoPrivateData;
PropertyName m_propertyName;
#endif
};
diff --git a/src/plugins/qmldesigner/designercore/include/propertynode.h b/src/plugins/qmldesigner/designercore/include/propertynode.h
index 2489bac3c0..2df0b195a4 100644
--- a/src/plugins/qmldesigner/designercore/include/propertynode.h
+++ b/src/plugins/qmldesigner/designercore/include/propertynode.h
@@ -12,7 +12,7 @@ class QMLDESIGNERCORE_EXPORT PropertyNode // : public BaseModelNode
public:
PropertyNode();
-// static int variantUserType() { return qMetaTypeId<InternalNode::Pointer>(); }
+// static int variantTypeId() { return qMetaTypeId<InternalNode::Pointer>(); }
// static QVariant toVariant(const InternalNode::Pointer &internalNodePointer) { return QVariant::fromValue(internalNodePointer); }
};
diff --git a/src/plugins/qmldesigner/designercore/include/qml3dnode.h b/src/plugins/qmldesigner/designercore/include/qml3dnode.h
index ffcc2ea7ff..280691c7a9 100644
--- a/src/plugins/qmldesigner/designercore/include/qml3dnode.h
+++ b/src/plugins/qmldesigner/designercore/include/qml3dnode.h
@@ -25,14 +25,13 @@ class QMLDESIGNERCORE_EXPORT Qml3DNode : public QmlVisualNode
public:
Qml3DNode() : QmlVisualNode() {}
Qml3DNode(const ModelNode &modelNode) : QmlVisualNode(modelNode) {}
- bool isValid() const override;
+ bool isValid() const;
+ explicit operator bool() const { return isValid(); }
static bool isValidQml3DNode(const ModelNode &modelNode);
static bool isValidVisualRoot(const ModelNode &modelNode);
- // From QmlObjectNode
- void setVariantProperty(const PropertyName &name, const QVariant &value) override;
- void setBindingProperty(const PropertyName &name, const QString &expression) override;
- bool isBlocked(const PropertyName &propName) const override;
+ bool handleEulerRotation(const PropertyName &name);
+ bool isBlocked(const PropertyName &propName) const;
friend auto qHash(const Qml3DNode &node) { return qHash(node.modelNode()); }
diff --git a/src/plugins/qmldesigner/designercore/include/qmlchangeset.h b/src/plugins/qmldesigner/designercore/include/qmlchangeset.h
index f7c6b8e56a..67d7a91084 100644
--- a/src/plugins/qmldesigner/designercore/include/qmlchangeset.h
+++ b/src/plugins/qmldesigner/designercore/include/qmlchangeset.h
@@ -21,7 +21,7 @@ public:
bool restoreEntryValues() const;
void setRestoreEntryValues(bool value);
QList<AbstractProperty> targetProperties() const;
- bool isValid() const override;
+ bool isValid() const;
explicit operator bool() const { return isValid(); }
static bool isValidQmlModelStateOperation(const ModelNode &modelNode);
};
@@ -31,7 +31,7 @@ class QMLDESIGNERCORE_EXPORT QmlPropertyChanges : public QmlModelStateOperation
public:
QmlPropertyChanges() : QmlModelStateOperation() {}
QmlPropertyChanges(const ModelNode &modelNode) : QmlModelStateOperation(modelNode) {}
- bool isValid() const override;
+ bool isValid() const;
explicit operator bool() const { return isValid(); }
static bool isValidQmlPropertyChanges(const ModelNode &modelNode);
void removeProperty(const PropertyName &name);
diff --git a/src/plugins/qmldesigner/designercore/include/qmlconnections.h b/src/plugins/qmldesigner/designercore/include/qmlconnections.h
index f8db7642b0..5dfc33ce61 100644
--- a/src/plugins/qmldesigner/designercore/include/qmlconnections.h
+++ b/src/plugins/qmldesigner/designercore/include/qmlconnections.h
@@ -20,7 +20,8 @@ public:
QmlConnections();
QmlConnections(const ModelNode &modelNode);
- bool isValid() const override;
+ explicit operator bool() const { return isValid(); }
+ bool isValid() const;
static bool isValidQmlConnections(const ModelNode &modelNode);
void destroy();
diff --git a/src/plugins/qmldesigner/designercore/include/qmlitemnode.h b/src/plugins/qmldesigner/designercore/include/qmlitemnode.h
index f95a97258b..5816d60ce1 100644
--- a/src/plugins/qmldesigner/designercore/include/qmlitemnode.h
+++ b/src/plugins/qmldesigner/designercore/include/qmlitemnode.h
@@ -27,7 +27,7 @@ class QMLDESIGNERCORE_EXPORT QmlItemNode : public QmlVisualNode
public:
QmlItemNode() = default;
QmlItemNode(const ModelNode &modelNode) : QmlVisualNode(modelNode) {}
- bool isValid() const override;
+ bool isValid() const;
explicit operator bool() const { return isValid(); }
static bool isValidQmlItemNode(const ModelNode &modelNode);
@@ -84,7 +84,7 @@ public:
bool instanceHasAnchors() const;
bool instanceHasShowContent() const;
- bool instanceCanReparent() const override;
+ bool instanceCanReparent() const;
bool instanceIsAnchoredBySibling() const;
bool instanceIsAnchoredByChildren() const;
bool instanceIsMovable() const;
@@ -149,7 +149,7 @@ class QMLDESIGNERCORE_EXPORT QmlFlowTargetNode final : public QmlItemNode
{
public:
QmlFlowTargetNode(const ModelNode &modelNode) : QmlItemNode(modelNode) {}
- bool isValid() const override;
+ bool isValid() const;
explicit operator bool() const { return isValid(); }
void assignTargetItem(const QmlFlowTargetNode &node);
@@ -165,7 +165,7 @@ class QMLDESIGNERCORE_EXPORT QmlFlowActionAreaNode final : public QmlItemNode
{
public:
QmlFlowActionAreaNode(const ModelNode &modelNode) : QmlItemNode(modelNode) {}
- bool isValid() const override;
+ bool isValid() const;
explicit operator bool() const { return isValid(); }
static bool isValidQmlFlowActionAreaNode(const ModelNode &modelNode);
ModelNode targetTransition() const;
@@ -178,7 +178,7 @@ class QMLDESIGNERCORE_EXPORT QmlFlowItemNode final : public QmlItemNode
{
public:
QmlFlowItemNode(const ModelNode &modelNode) : QmlItemNode(modelNode) {}
- bool isValid() const override;
+ bool isValid() const;
explicit operator bool() const { return isValid(); }
static bool isValidQmlFlowItemNode(const ModelNode &modelNode);
QList<QmlFlowActionAreaNode> flowActionAreas() const;
@@ -191,7 +191,7 @@ class QMLDESIGNERCORE_EXPORT QmlFlowViewNode final : public QmlItemNode
{
public:
QmlFlowViewNode(const ModelNode &modelNode) : QmlItemNode(modelNode) {}
- bool isValid() const override;
+ bool isValid() const;
explicit operator bool() const { return isValid(); }
static bool isValidQmlFlowViewNode(const ModelNode &modelNode);
QList<QmlFlowItemNode> flowItems() const;
diff --git a/src/plugins/qmldesigner/designercore/include/qmlmodelnodefacade.h b/src/plugins/qmldesigner/designercore/include/qmlmodelnodefacade.h
index 27c4c86cc0..0a81e00c90 100644
--- a/src/plugins/qmldesigner/designercore/include/qmlmodelnodefacade.h
+++ b/src/plugins/qmldesigner/designercore/include/qmlmodelnodefacade.h
@@ -4,7 +4,9 @@
#pragma once
#include <qmldesignercorelib_global.h>
+
#include <modelnode.h>
+#include <nodemetainfo.h>
namespace QmlDesigner {
@@ -14,27 +16,58 @@ 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;
+ bool isValid() const;
explicit operator bool() const { return isValid(); }
QmlModelNodeFacade() = default;
AbstractView *view() const;
Model *model() const;
+ NodeMetaInfo metaInfo() const { return m_modelNode.metaInfo(); }
static const NodeInstanceView *nodeInstanceView(const ModelNode &modelNode);
const NodeInstanceView *nodeInstanceView() const;
bool isRootNode() const;
static void enableUglyWorkaroundForIsValidQmlModelNodeFacadeInTests();
+ friend bool operator==(const QmlModelNodeFacade &firstNode, const QmlModelNodeFacade &secondNode)
+ {
+ return firstNode.m_modelNode == secondNode.m_modelNode;
+ }
+
+ friend bool operator==(const QmlModelNodeFacade &firstNode, const ModelNode &secondNode)
+ {
+ return firstNode.m_modelNode == secondNode;
+ }
+
+ friend bool operator==(const ModelNode &firstNode, const QmlModelNodeFacade &secondNode)
+ {
+ return firstNode == secondNode.m_modelNode;
+ }
+
+ friend bool operator!=(const QmlModelNodeFacade &firstNode, const QmlModelNodeFacade &secondNode)
+ {
+ return !(firstNode == secondNode);
+ }
+
+ friend bool operator!=(const QmlModelNodeFacade &firstNode, const ModelNode &secondNode)
+ {
+ return firstNode.m_modelNode != secondNode;
+ }
+
+ friend bool operator!=(const ModelNode &firstNode, const QmlModelNodeFacade &secondNode)
+ {
+ return firstNode != secondNode.m_modelNode;
+ }
+
+ friend bool operator<(const QmlModelNodeFacade &firstNode, const QmlModelNodeFacade &secondNode)
+ {
+ return firstNode.m_modelNode < secondNode.m_modelNode;
+ }
+
protected:
QmlModelNodeFacade(const ModelNode &modelNode)
: m_modelNode(modelNode)
diff --git a/src/plugins/qmldesigner/designercore/include/qmlobjectnode.h b/src/plugins/qmldesigner/designercore/include/qmlobjectnode.h
index 1eea5063c9..eb652a4010 100644
--- a/src/plugins/qmldesigner/designercore/include/qmlobjectnode.h
+++ b/src/plugins/qmldesigner/designercore/include/qmlobjectnode.h
@@ -32,7 +32,7 @@ public:
virtual ~QmlObjectNode() = default;
static bool isValidQmlObjectNode(const ModelNode &modelNode);
- bool isValid() const override;
+ bool isValid() const;
explicit operator bool() const { return isValid(); }
bool hasError() const;
@@ -52,8 +52,8 @@ public:
QmlModelState currentState() const;
QmlTimeline currentTimeline() const;
- virtual void setVariantProperty(const PropertyName &name, const QVariant &value);
- virtual void setBindingProperty(const PropertyName &name, const QString &expression);
+ void setVariantProperty(const PropertyName &name, const QVariant &value);
+ void setBindingProperty(const PropertyName &name, const QString &expression);
NodeAbstractProperty nodeAbstractProperty(const PropertyName &name) const;
NodeAbstractProperty defaultNodeAbstractProperty() const;
NodeProperty nodeProperty(const PropertyName &name) const;
@@ -76,7 +76,7 @@ public:
bool timelineIsActive() const;
QmlPropertyChanges propertyChangeForCurrentState() const;
- virtual bool instanceCanReparent() const;
+ bool instanceCanReparent() const;
bool isRootModelNode() const;
@@ -114,10 +114,6 @@ public:
QStringList allStateNames() const;
- static QmlObjectNode *getQmlObjectNodeOfCorrectType(const ModelNode &modelNode);
-
- virtual bool isBlocked(const PropertyName &propName) const;
-
friend auto qHash(const QmlObjectNode &node) { return qHash(node.modelNode()); }
QList<QmlModelState> allDefinedStates() const;
QList<QmlModelStateOperation> allInvalidStateOperations() const;
diff --git a/src/plugins/qmldesigner/designercore/include/qmlstate.h b/src/plugins/qmldesigner/designercore/include/qmlstate.h
index c5ba5c8965..58515aff3b 100644
--- a/src/plugins/qmldesigner/designercore/include/qmlstate.h
+++ b/src/plugins/qmldesigner/designercore/include/qmlstate.h
@@ -23,7 +23,6 @@ class StatesEditorView;
class QMLDESIGNERCORE_EXPORT QmlModelState final : public QmlModelNodeFacade
{
friend StatesEditorView;
- friend Experimental::StatesEditorView;
public:
QmlModelState();
@@ -45,7 +44,7 @@ public:
QList<QmlObjectNode> allAffectedNodes() const;
QString name() const;
void setName(const QString &name);
- bool isValid() const override;
+ bool isValid() const;
explicit operator bool() const { return isValid(); }
static bool isValidQmlModelState(const ModelNode &modelNode);
void destroy();
diff --git a/src/plugins/qmldesigner/designercore/include/qmltimeline.h b/src/plugins/qmldesigner/designercore/include/qmltimeline.h
index 26dc472117..7a2809f528 100644
--- a/src/plugins/qmldesigner/designercore/include/qmltimeline.h
+++ b/src/plugins/qmldesigner/designercore/include/qmltimeline.h
@@ -20,7 +20,7 @@ public:
QmlTimeline();
QmlTimeline(const ModelNode &modelNode);
- bool isValid() const override;
+ bool isValid() const;
explicit operator bool() const { return isValid(); }
static bool isValidQmlTimeline(const ModelNode &modelNode);
void destroy();
diff --git a/src/plugins/qmldesigner/designercore/include/qmltimelinekeyframegroup.h b/src/plugins/qmldesigner/designercore/include/qmltimelinekeyframegroup.h
index 76897b6235..a319c5ac31 100644
--- a/src/plugins/qmldesigner/designercore/include/qmltimelinekeyframegroup.h
+++ b/src/plugins/qmldesigner/designercore/include/qmltimelinekeyframegroup.h
@@ -19,7 +19,7 @@ public:
QmlTimelineKeyframeGroup();
QmlTimelineKeyframeGroup(const ModelNode &modelNode);
- bool isValid() const override;
+ bool isValid() const;
explicit operator bool() const { return isValid(); }
static bool isValidQmlTimelineKeyframeGroup(const ModelNode &modelNode);
void destroy();
diff --git a/src/plugins/qmldesigner/designercore/include/qmlvisualnode.h b/src/plugins/qmldesigner/designercore/include/qmlvisualnode.h
index 6827243083..69917dbc23 100644
--- a/src/plugins/qmldesigner/designercore/include/qmlvisualnode.h
+++ b/src/plugins/qmldesigner/designercore/include/qmlvisualnode.h
@@ -48,7 +48,7 @@ public:
QmlVisualNode() = default;
QmlVisualNode(const ModelNode &modelNode) : QmlObjectNode(modelNode) {}
- bool isValid() const override;
+ bool isValid() const;
explicit operator bool() const { return isValid(); }
static bool isValidQmlVisualNode(const ModelNode &modelNode);
bool isRootNode() const;
@@ -107,7 +107,6 @@ class QMLDESIGNERCORE_EXPORT QmlModelStateGroup
{
friend class QmlObjectNode;
friend class StatesEditorView;
- friend class Experimental::StatesEditorView;
public:
QmlModelStateGroup() = default;
diff --git a/src/plugins/qmldesigner/designercore/include/stringutils.h b/src/plugins/qmldesigner/designercore/include/stringutils.h
new file mode 100644
index 0000000000..38c3c260a9
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/include/stringutils.h
@@ -0,0 +1,42 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#pragma once
+
+#include <QString>
+
+namespace QmlDesigner {
+
+inline QString escape(const QString &value)
+{
+ QString result = value;
+
+ if (value.length() == 6 && value.startsWith("\\u")) //Do not double escape unicode chars
+ return value;
+
+ result.replace(QStringLiteral("\\"), QStringLiteral("\\\\"));
+ result.replace(QStringLiteral("\""), QStringLiteral("\\\""));
+ result.replace(QStringLiteral("\t"), QStringLiteral("\\t"));
+ result.replace(QStringLiteral("\r"), QStringLiteral("\\r"));
+ result.replace(QStringLiteral("\n"), QStringLiteral("\\n"));
+
+ return result;
+}
+
+inline QString deescape(const QString &value)
+{
+ QString result = value;
+
+ if (value.length() == 6 && value.startsWith("\\u")) //Ignore unicode chars
+ return value;
+
+ result.replace(QStringLiteral("\\\\"), QStringLiteral("\\"));
+ result.replace(QStringLiteral("\\\""), QStringLiteral("\""));
+ result.replace(QStringLiteral("\\t"), QStringLiteral("\t"));
+ result.replace(QStringLiteral("\\r"), QStringLiteral("\r"));
+ result.replace(QStringLiteral("\\n"), QStringLiteral("\n"));
+
+ return result;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/baseconnectionmanager.cpp b/src/plugins/qmldesigner/designercore/instances/baseconnectionmanager.cpp
index 15f84e92c9..39da5f99ba 100644
--- a/src/plugins/qmldesigner/designercore/instances/baseconnectionmanager.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/baseconnectionmanager.cpp
@@ -107,8 +107,8 @@ void BaseConnectionManager::readDataStream(Connection &connection)
connection.blockSize = 0;
#ifdef NANOTRACE_ENABLED
- if (command.userType() != QMetaType::type("PuppetAliveCommand")) {
- if (command.userType() == QMetaType::type("SyncNanotraceCommand")) {
+ if (command.typeId() != QMetaType::type("PuppetAliveCommand")) {
+ if (command.typeId() == QMetaType::type("SyncNanotraceCommand")) {
SyncNanotraceCommand cmd = command.value<SyncNanotraceCommand>();
NANOTRACE_INSTANT_ARGS("Sync", "readCommand",
{"name", cmd.name().toStdString()},
diff --git a/src/plugins/qmldesigner/designercore/instances/capturingconnectionmanager.cpp b/src/plugins/qmldesigner/designercore/instances/capturingconnectionmanager.cpp
index b2b8f297f7..77b087e8c9 100644
--- a/src/plugins/qmldesigner/designercore/instances/capturingconnectionmanager.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/capturingconnectionmanager.cpp
@@ -55,7 +55,7 @@ void CapturingConnectionManager::writeCommand(const QVariant &command)
InteractiveConnectionManager::writeCommand(command);
if (m_captureFileForTest.isWritable()) {
- qDebug() << "command name: " << QMetaType::typeName(command.userType());
+ qDebug() << "command name: " << QMetaType::typeName(command.typeId());
writeCommandToIODevice(command, &m_captureFileForTest, writeCommandCounter());
qDebug() << "\tcatpure file offset: " << m_captureFileForTest.pos();
}
diff --git a/src/plugins/qmldesigner/designercore/instances/interactiveconnectionmanager.cpp b/src/plugins/qmldesigner/designercore/instances/interactiveconnectionmanager.cpp
index 33dad3c37d..cd36cac76d 100644
--- a/src/plugins/qmldesigner/designercore/instances/interactiveconnectionmanager.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/interactiveconnectionmanager.cpp
@@ -70,7 +70,7 @@ void InteractiveConnectionManager::dispatchCommand(const QVariant &command, Conn
{
static const int puppetAliveCommandType = QMetaType::type("PuppetAliveCommand");
- if (command.userType() == puppetAliveCommandType) {
+ if (command.typeId() == puppetAliveCommandType) {
puppetAlive(connection);
} else {
BaseConnectionManager::dispatchCommand(command, connection);
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp
index 7ed2906338..414a05683e 100644
--- a/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp
@@ -296,7 +296,7 @@ QVariant NodeInstance::property(const PropertyName &name) const
if (index != -1) {
PropertyName parentPropName = name.left(index);
QVariant varValue = d->propertyValues.value(parentPropName);
- if (varValue.type() == QVariant::Vector2D) {
+ if (varValue.typeId() == QVariant::Vector2D) {
auto value = varValue.value<QVector2D>();
char subProp = name.right(1)[0];
float subValue = 0.f;
@@ -312,7 +312,7 @@ QVariant NodeInstance::property(const PropertyName &name) const
break;
}
return QVariant(subValue);
- } else if (varValue.type() == QVariant::Vector3D) {
+ } else if (varValue.typeId() == QVariant::Vector3D) {
auto value = varValue.value<QVector3D>();
char subProp = name.right(1)[0];
float subValue = 0.f;
@@ -331,7 +331,7 @@ QVariant NodeInstance::property(const PropertyName &name) const
break;
}
return QVariant(subValue);
- } else if (varValue.type() == QVariant::Vector4D) {
+ } else if (varValue.typeId() == QVariant::Vector4D) {
auto value = varValue.value<QVector4D>();
char subProp = name.right(1)[0];
float subValue = 0.f;
@@ -417,9 +417,9 @@ void NodeInstance::setProperty(const PropertyName &name, const QVariant &value)
QVariant oldValue = d->propertyValues.value(parentPropName);
QVariant newValueVar;
bool update = false;
- if (oldValue.type() == QVariant::Vector2D) {
+ if (oldValue.typeId() == QVariant::Vector2D) {
QVector2D newValue;
- if (oldValue.type() == QVariant::Vector2D)
+ if (oldValue.typeId() == QVariant::Vector2D)
newValue = oldValue.value<QVector2D>();
if (name.endsWith(".x")) {
newValue.setX(value.toFloat());
@@ -429,9 +429,9 @@ void NodeInstance::setProperty(const PropertyName &name, const QVariant &value)
update = true;
}
newValueVar = newValue;
- } else if (oldValue.type() == QVariant::Vector3D) {
+ } else if (oldValue.typeId() == QVariant::Vector3D) {
QVector3D newValue;
- if (oldValue.type() == QVariant::Vector3D)
+ if (oldValue.typeId() == QVariant::Vector3D)
newValue = oldValue.value<QVector3D>();
if (name.endsWith(".x")) {
newValue.setX(value.toFloat());
@@ -444,9 +444,9 @@ void NodeInstance::setProperty(const PropertyName &name, const QVariant &value)
update = true;
}
newValueVar = newValue;
- } else if (oldValue.type() == QVariant::Vector4D) {
+ } else if (oldValue.typeId() == QVariant::Vector4D) {
QVector4D newValue;
- if (oldValue.type() == QVariant::Vector4D)
+ if (oldValue.typeId() == QVariant::Vector4D)
newValue = oldValue.value<QVector4D>();
if (name.endsWith(".x")) {
newValue.setX(value.toFloat());
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp
index 2893d0e131..8b80a9c4af 100644
--- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp
@@ -107,37 +107,38 @@ void NodeInstanceServerProxy::dispatchCommand(const QVariant &command)
static const int puppetToCreatorCommandType = QMetaType::type("PuppetToCreatorCommand");
static const int SyncNanotraceCommandType = QMetaType::type("SyncNanotraceCommand");
- qCInfo(instanceViewBenchmark) << "dispatching command" << command.userType() << command.typeName();
- if (command.userType() == informationChangedCommandType) {
+ qCInfo(instanceViewBenchmark) << "dispatching command" << command.typeId() << command.typeName();
+ if (command.typeId() == informationChangedCommandType) {
nodeInstanceClient()->informationChanged(command.value<InformationChangedCommand>());
- } else if (command.userType() == valuesChangedCommandType) {
+ } else if (command.typeId() == valuesChangedCommandType) {
nodeInstanceClient()->valuesChanged(command.value<ValuesChangedCommand>());
- } else if (command.userType() == valuesModifiedCommandType) {
+ } else if (command.typeId() == valuesModifiedCommandType) {
nodeInstanceClient()->valuesModified(command.value<ValuesModifiedCommand>());
- } else if (command.userType() == pixmapChangedCommandType) {
+ } else if (command.typeId() == pixmapChangedCommandType) {
nodeInstanceClient()->pixmapChanged(command.value<PixmapChangedCommand>());
- } else if (command.userType() == childrenChangedCommandType) {
+ } else if (command.typeId() == childrenChangedCommandType) {
nodeInstanceClient()->childrenChanged(command.value<ChildrenChangedCommand>());
- } else if (command.userType() == statePreviewImageChangedCommandType) {
+ } else if (command.typeId() == statePreviewImageChangedCommandType) {
nodeInstanceClient()->statePreviewImagesChanged(command.value<StatePreviewImageChangedCommand>());
- } else if (command.userType() == componentCompletedCommandType) {
+ } else if (command.typeId() == componentCompletedCommandType) {
nodeInstanceClient()->componentCompleted(command.value<ComponentCompletedCommand>());
- } else if (command.userType() == tokenCommandType) {
+ } else if (command.typeId() == tokenCommandType) {
nodeInstanceClient()->token(command.value<TokenCommand>());
- } else if (command.userType() == debugOutputCommandType) {
+ } else if (command.typeId() == debugOutputCommandType) {
nodeInstanceClient()->debugOutput(command.value<DebugOutputCommand>());
- } else if (command.userType() == changeSelectionCommandType) {
+ } else if (command.typeId() == changeSelectionCommandType) {
nodeInstanceClient()->selectionChanged(command.value<ChangeSelectionCommand>());
- } else if (command.userType() == puppetToCreatorCommandType) {
+ } else if (command.typeId() == puppetToCreatorCommandType) {
nodeInstanceClient()->handlePuppetToCreatorCommand(command.value<PuppetToCreatorCommand>());
- } else if (command.userType() == SyncNanotraceCommandType) {
+ } else if (command.typeId() == SyncNanotraceCommandType) {
// ignore.
} else {
QTC_ASSERT(false, );
Q_ASSERT(false);
}
- qCInfo(instanceViewBenchmark) << "dispatching command" << "done" << command.userType();
+ qCInfo(instanceViewBenchmark) << "dispatching command"
+ << "done" << command.typeId();
}
NodeInstanceClientInterface *NodeInstanceServerProxy::nodeInstanceClient() const
@@ -173,7 +174,7 @@ QString NodeInstanceServerProxy::qrcMappingString() const
void NodeInstanceServerProxy::writeCommand(const QVariant &command)
{
#ifdef NANOTRACE_ENABLED
- if (command.userType() == QMetaType::type("SyncNanotraceCommand")) {
+ if (command.typeId() == QMetaType::type("SyncNanotraceCommand")) {
SyncNanotraceCommand cmd = command.value<SyncNanotraceCommand>();
NANOTRACE_INSTANT_ARGS("Sync", "writeCommand",
{"name", cmd.name().toStdString()},
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
index 3befd6ec52..fee28a9dd3 100644
--- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
@@ -124,13 +124,15 @@ namespace QmlDesigner {
\sa ~NodeInstanceView, setRenderOffScreen()
*/
NodeInstanceView::NodeInstanceView(ConnectionManagerInterface &connectionManager,
- ExternalDependenciesInterface &externalDependencies)
+ ExternalDependenciesInterface &externalDependencies,
+ bool qsbEnabled)
: AbstractView{externalDependencies}
, m_connectionManager(connectionManager)
, m_externalDependencies(externalDependencies)
, m_baseStatePreviewImage(QSize(100, 100), QImage::Format_ARGB32)
, m_restartProcessTimerId(0)
, m_fileSystemWatcher(new QFileSystemWatcher(this))
+ , m_qsbEnabled(qsbEnabled)
{
m_baseStatePreviewImage.fill(0xFFFFFF);
@@ -201,7 +203,7 @@ NodeInstanceView::~NodeInstanceView()
//\{
-bool static isSkippedRootNode(const ModelNode &node)
+static bool isSkippedRootNode(const ModelNode &node)
{
static const PropertyNameList skipList({"Qt.ListModel", "QtQuick.ListModel", "Qt.ListModel", "QtQuick.ListModel"});
@@ -211,8 +213,7 @@ bool static isSkippedRootNode(const ModelNode &node)
return false;
}
-
-bool static isSkippedNode(const ModelNode &node)
+static bool isSkippedNode(const ModelNode &node)
{
static const PropertyNameList skipList({"QtQuick.XmlRole", "Qt.XmlRole", "QtQuick.ListElement", "Qt.ListElement"});
@@ -222,7 +223,7 @@ bool static isSkippedNode(const ModelNode &node)
return false;
}
-bool static parentTakesOverRendering(const ModelNode &modelNode)
+static bool parentTakesOverRendering(const ModelNode &modelNode)
{
ModelNode currentNode = modelNode;
@@ -257,10 +258,7 @@ void NodeInstanceView::modelAttached(Model *model)
activateState(newStateInstance);
}
- // If model gets attached on non-main thread of the application, do not attempt to monitor
- // file changes. Such models are typically short lived for specific purpose, and timers
- // will not work at all, if the thread is not based on QThread.
- if (Utils::isMainThread()) {
+ if (m_qsbEnabled) {
m_generateQsbFilesTimer.stop();
m_qsbTargets.clear();
updateQsbPathToFilterMap();
@@ -1463,10 +1461,10 @@ void NodeInstanceView::valuesModified(const ValuesModifiedCommand &command)
if (hasInstanceForId(container.instanceId())) {
NodeInstance instance = instanceForId(container.instanceId());
if (instance.isValid()) {
- QScopedPointer<QmlObjectNode> node {
- QmlObjectNode::getQmlObjectNodeOfCorrectType(instance.modelNode())};
- if (node->modelValue(container.name()) != container.value())
- node->setVariantProperty(container.name(), container.value());
+ if (auto qmlObjectNode = QmlObjectNode(instance.modelNode())) {
+ if (qmlObjectNode.modelValue(container.name()) != container.value())
+ qmlObjectNode.setVariantProperty(container.name(), container.value());
+ }
}
}
}
@@ -1503,7 +1501,7 @@ void NodeInstanceView::pixmapChanged(const PixmapChangedCommand &command)
}
}
- m_nodeInstanceServer->benchmark(Q_FUNC_INFO + QString::number(renderImageChangeSet.count()));
+ m_nodeInstanceServer->benchmark(Q_FUNC_INFO + QString::number(renderImageChangeSet.size()));
if (!renderImageChangeSet.isEmpty())
emitInstancesRenderImageChanged(Utils::toList(renderImageChangeSet));
@@ -1542,7 +1540,7 @@ void NodeInstanceView::informationChanged(const InformationChangedCommand &comma
QMultiHash<ModelNode, InformationName> informationChangeHash = informationChanged(command.informations());
- m_nodeInstanceServer->benchmark(Q_FUNC_INFO + QString::number(informationChangeHash.count()));
+ m_nodeInstanceServer->benchmark(Q_FUNC_INFO + QString::number(informationChangeHash.size()));
if (!informationChangeHash.isEmpty())
emitInstanceInformationsChange(informationChangeHash);
@@ -1615,7 +1613,7 @@ void NodeInstanceView::componentCompleted(const ComponentCompletedCommand &comma
nodeVector.append(modelNodeForInternalId(instanceId));
}
- m_nodeInstanceServer->benchmark(Q_FUNC_INFO + QString::number(nodeVector.count()));
+ m_nodeInstanceServer->benchmark(Q_FUNC_INFO + QString::number(nodeVector.size()));
if (!nodeVector.isEmpty())
emitInstancesCompleted(nodeVector);
diff --git a/src/plugins/qmldesigner/designercore/metainfo/metainfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/metainfo.cpp
index 144df14448..abecca1788 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/metainfo.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/metainfo.cpp
@@ -128,8 +128,7 @@ void MetaInfoPrivate::parseItemLibraryDescriptions(const ExternalDependenciesInt
Internal::MetaInfoReader reader(*m_q);
try {
reader.readMetaInfoFile(path.toString());
- } catch (const InvalidMetaInfoException &e) {
- Q_UNUSED(e);
+ } catch ([[maybe_unused]] const InvalidMetaInfoException &e) {
#ifndef UNIT_TESTS
qWarning() << e.description();
const QString errorMessage = path.toString() + QLatin1Char('\n') + QLatin1Char('\n')
diff --git a/src/plugins/qmldesigner/designercore/metainfo/metainforeader.cpp b/src/plugins/qmldesigner/designercore/metainfo/metainforeader.cpp
index f418d003e1..a56221f643 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/metainforeader.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/metainforeader.cpp
@@ -289,7 +289,7 @@ inline QString deEscape(const QString &value)
inline QVariant deEscapeVariant(const QVariant &value)
{
- if (value.type() == QVariant::String)
+ if (value.typeId() == QVariant::String)
return deEscape(value.toString());
return value;
}
diff --git a/src/plugins/qmldesigner/designercore/metainfo/nodehints.cpp b/src/plugins/qmldesigner/designercore/metainfo/nodehints.cpp
index 0a4f84f320..ece5b4bf6f 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/nodehints.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/nodehints.cpp
@@ -266,7 +266,7 @@ QPair<QString, QVariant> NodeHints::setParentProperty() const
QStringList list = str.split(":");
- if (list.count() != 2)
+ if (list.size() != 2)
return {};
return qMakePair(list.first().trimmed(), parseValue(list.last().trimmed()));
diff --git a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp
index 7ca3aedff2..fd25d9c450 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp
@@ -336,7 +336,7 @@ private:
const ContextPtr m_context;
};
-static inline bool isValueType(const TypeName &type)
+inline static bool isValueType(const TypeName &type)
{
static const PropertyTypeList objectValuesList({"QFont",
"QPoint",
@@ -356,7 +356,7 @@ static inline bool isValueType(const TypeName &type)
return objectValuesList.contains(type);
}
-static inline bool isValueType(const QString &type)
+inline static bool isValueType(const QString &type)
{
static const QStringList objectValuesList({"QFont",
"QPoint",
@@ -587,8 +587,11 @@ QVector<PropertyInfo> getObjectTypes(const ObjectValue *objectValue, const Conte
class NodeMetaInfoPrivate
{
public:
- using Pointer = QSharedPointer<NodeMetaInfoPrivate>;
- NodeMetaInfoPrivate() = default;
+ using Pointer = std::shared_ptr<NodeMetaInfoPrivate>;
+ NodeMetaInfoPrivate() = delete;
+ NodeMetaInfoPrivate(Model *model, TypeName type, int maj = -1, int min = -1);
+ NodeMetaInfoPrivate(const NodeMetaInfoPrivate &) = delete;
+ NodeMetaInfoPrivate &operator=(const NodeMetaInfoPrivate &) = delete;
~NodeMetaInfoPrivate() = default;
bool isValid() const;
@@ -621,13 +624,15 @@ public:
QString componentFileName() const;
QString importDirectoryPath() const;
- static Pointer create(Model *model, const TypeName &type, int maj = -1, int min = -1);
+ static std::shared_ptr<NodeMetaInfoPrivate> create(Model *model,
+ const TypeName &type,
+ int maj = -1,
+ int min = -1);
QSet<QByteArray> &prototypeCachePositives();
QSet<QByteArray> &prototypeCacheNegatives();
private:
- NodeMetaInfoPrivate(Model *model, TypeName type, int maj = -1, int min = -1);
const CppComponentValue *getCppComponentValue() const;
const ObjectValue *getObjectValue() const;
@@ -713,20 +718,23 @@ PropertyName NodeMetaInfoPrivate::defaultPropertyName() const
return PropertyName("data");
}
-static inline TypeName stringIdentifier( const TypeName &type, int maj, int min)
+inline static TypeName stringIdentifier(const TypeName &type, int maj, int min)
{
return type + QByteArray::number(maj) + '_' + QByteArray::number(min);
}
-NodeMetaInfoPrivate::Pointer NodeMetaInfoPrivate::create(Model *model, const TypeName &type, int major, int minor)
+std::shared_ptr<NodeMetaInfoPrivate> NodeMetaInfoPrivate::create(Model *model,
+ const TypeName &type,
+ int major,
+ int minor)
{
- auto &&cache = model->d->m_nodeMetaInfoCache;
+ auto &cache = model->d->nodeMetaInfoCache();
if (auto found = cache.find(stringIdentifier(type, major, minor)); found != cache.end())
return *found;
- Pointer newData(new NodeMetaInfoPrivate(model, type, major, minor));
+ auto newData = std::make_shared<NodeMetaInfoPrivate>(model, type, major, minor);
if (newData->isValid())
- model->d->m_nodeMetaInfoCache.insert(stringIdentifier(type, major, minor), newData);
+ cache.insert(stringIdentifier(type, major, minor), newData);
return newData;
}
@@ -931,7 +939,7 @@ bool NodeMetaInfoPrivate::isPropertyWritable(const PropertyName &propertyName) c
if (isValueType(objectType))
return true;
- QSharedPointer<NodeMetaInfoPrivate> objectInfo(create(m_model, objectType));
+ auto objectInfo = create(m_model, objectType);
if (objectInfo->isValid())
return objectInfo->isPropertyWritable(rawPropertyName);
else
@@ -947,7 +955,6 @@ bool NodeMetaInfoPrivate::isPropertyWritable(const PropertyName &propertyName) c
return true; //all properties of components are writable
}
-
bool NodeMetaInfoPrivate::isPropertyList(const PropertyName &propertyName) const
{
if (!isValid())
@@ -964,7 +971,7 @@ bool NodeMetaInfoPrivate::isPropertyList(const PropertyName &propertyName) const
if (isValueType(objectType))
return false;
- QSharedPointer<NodeMetaInfoPrivate> objectInfo(create(m_model, objectType));
+ auto objectInfo = create(m_model, objectType);
if (objectInfo->isValid())
return objectInfo->isPropertyList(rawPropertyName);
else
@@ -999,7 +1006,7 @@ bool NodeMetaInfoPrivate::isPropertyPointer(const PropertyName &propertyName) co
if (isValueType(objectType))
return false;
- QSharedPointer<NodeMetaInfoPrivate> objectInfo(create(m_model, objectType));
+ auto objectInfo = create(m_model, objectType);
if (objectInfo->isValid())
return objectInfo->isPropertyPointer(rawPropertyName);
else
@@ -1031,7 +1038,7 @@ bool NodeMetaInfoPrivate::isPropertyEnum(const PropertyName &propertyName) const
if (isValueType(objectType))
return false;
- QSharedPointer<NodeMetaInfoPrivate> objectInfo(create(m_model, objectType));
+ auto objectInfo = create(m_model, objectType);
if (objectInfo->isValid())
return objectInfo->isPropertyEnum(rawPropertyName);
else
@@ -1157,7 +1164,6 @@ Model *NodeMetaInfoPrivate::model() const
return m_model;
}
-
QStringList NodeMetaInfoPrivate::keysForEnum(const QString &enumName) const
{
if (!isValid())
@@ -1245,7 +1251,6 @@ QStringList NodeMetaInfoPrivate::lookupNameComponent() const
return tempString.split('.');
}
-
bool NodeMetaInfoPrivate::isValid() const
{
return m_isValid && context() && document();
@@ -1349,7 +1354,6 @@ void NodeMetaInfoPrivate::setupPrototypes()
}
}
-
QList<TypeDescription> NodeMetaInfoPrivate::prototypes() const
{
return m_prototypes;
@@ -1393,6 +1397,12 @@ void NodeMetaInfoPrivate::initialiseProperties()
m_slots = getSlots(m_objectValue, context());
}
+NodeMetaInfo::NodeMetaInfo() = default;
+NodeMetaInfo::NodeMetaInfo(const NodeMetaInfo &) = default;
+NodeMetaInfo &NodeMetaInfo::operator=(const NodeMetaInfo &) = default;
+NodeMetaInfo::NodeMetaInfo(NodeMetaInfo &&) = default;
+NodeMetaInfo &NodeMetaInfo::operator=(NodeMetaInfo &&) = default;
+
NodeMetaInfo::NodeMetaInfo(Model *model, const TypeName &type, int maj, int min)
: m_privateData(NodeMetaInfoPrivate::create(model, type, maj, min))
{
@@ -1411,7 +1421,7 @@ bool NodeMetaInfo::isValid() const
bool NodeMetaInfo::isFileComponent() const
{
if constexpr (useProjectStorage())
- return bool(typeData().traits & Storage::TypeTraits::IsFileComponent);
+ return isValid() && bool(typeData().traits & Storage::TypeTraits::IsFileComponent);
else
return isValid() && m_privateData->isFileComponent();
}
@@ -1419,19 +1429,23 @@ bool NodeMetaInfo::isFileComponent() const
bool NodeMetaInfo::hasProperty(Utils::SmallStringView propertyName) const
{
if constexpr (useProjectStorage())
- return bool(m_projectStorage->propertyDeclarationId(m_typeId, propertyName));
+ return isValid() && bool(m_projectStorage->propertyDeclarationId(m_typeId, propertyName));
else
return isValid() && m_privateData->properties().contains(propertyName);
}
PropertyMetaInfos NodeMetaInfo::properties() const
{
- if constexpr (useProjectStorage()) {
- return Utils::transform<PropertyMetaInfos>(
- m_projectStorage->propertyDeclarationIds(m_typeId), [&](auto id) {
- return PropertyMetaInfo{id, m_projectStorage};
- });
+ if (!isValid())
+ return {};
+ if constexpr (useProjectStorage()) {
+ if (isValid()) {
+ return Utils::transform<PropertyMetaInfos>(
+ m_projectStorage->propertyDeclarationIds(m_typeId), [&](auto id) {
+ return PropertyMetaInfo{id, m_projectStorage};
+ });
+ }
} else {
const auto &properties = m_privateData->properties();
@@ -1439,19 +1453,23 @@ PropertyMetaInfos NodeMetaInfo::properties() const
propertyMetaInfos.reserve(static_cast<std::size_t>(properties.size()));
for (const auto &name : properties)
- propertyMetaInfos.emplace_back(m_privateData, name);
+ propertyMetaInfos.push_back({m_privateData, name});
return propertyMetaInfos;
}
+
+ return {};
}
PropertyMetaInfos NodeMetaInfo::localProperties() const
{
if constexpr (useProjectStorage()) {
- return Utils::transform<PropertyMetaInfos>(
- m_projectStorage->localPropertyDeclarationIds(m_typeId), [&](auto id) {
- return PropertyMetaInfo{id, m_projectStorage};
- });
+ if (isValid()) {
+ return Utils::transform<PropertyMetaInfos>(
+ m_projectStorage->localPropertyDeclarationIds(m_typeId), [&](auto id) {
+ return PropertyMetaInfo{id, m_projectStorage};
+ });
+ }
} else {
const auto &properties = m_privateData->localProperties();
@@ -1463,15 +1481,21 @@ PropertyMetaInfos NodeMetaInfo::localProperties() const
return propertyMetaInfos;
}
+
+ return {};
}
PropertyMetaInfo NodeMetaInfo::property(const PropertyName &propertyName) const
{
if constexpr (useProjectStorage()) {
- return {m_projectStorage->propertyDeclarationId(m_typeId, propertyName), m_projectStorage};
+ if (isValid()) {
+ return {m_projectStorage->propertyDeclarationId(m_typeId, propertyName),
+ m_projectStorage};
+ }
} else {
- if (hasProperty(propertyName))
+ if (hasProperty(propertyName)) {
return PropertyMetaInfo{m_privateData, propertyName};
+ }
}
return {};
@@ -1480,10 +1504,13 @@ PropertyMetaInfo NodeMetaInfo::property(const PropertyName &propertyName) const
PropertyNameList NodeMetaInfo::signalNames() const
{
if constexpr (useProjectStorage()) {
- return Utils::transform<PropertyNameList>(m_projectStorage->signalDeclarationNames(m_typeId),
- [&](const auto &name) {
- return name.toQByteArray();
- });
+ if (isValid()) {
+ return Utils::transform<PropertyNameList>(m_projectStorage->signalDeclarationNames(
+ m_typeId),
+ [&](const auto &name) {
+ return name.toQByteArray();
+ });
+ }
} else {
if (isValid())
return m_privateData->signalNames();
@@ -1495,10 +1522,13 @@ PropertyNameList NodeMetaInfo::signalNames() const
PropertyNameList NodeMetaInfo::slotNames() const
{
if constexpr (useProjectStorage()) {
- return Utils::transform<PropertyNameList>(m_projectStorage->functionDeclarationNames(m_typeId),
- [&](const auto &name) {
- return name.toQByteArray();
- });
+ if (isValid()) {
+ return Utils::transform<PropertyNameList>(m_projectStorage->functionDeclarationNames(
+ m_typeId),
+ [&](const auto &name) {
+ return name.toQByteArray();
+ });
+ }
} else {
if (isValid())
return m_privateData->slotNames();
@@ -1510,9 +1540,11 @@ PropertyNameList NodeMetaInfo::slotNames() const
PropertyName NodeMetaInfo::defaultPropertyName() const
{
if constexpr (useProjectStorage()) {
- if (auto name = m_projectStorage->propertyName(typeData().defaultPropertyId))
- return name->toQByteArray();
- return {};
+ if (isValid()) {
+ if (auto name = m_projectStorage->propertyName(typeData().defaultPropertyId)) {
+ return name->toQByteArray();
+ }
+ }
} else {
if (isValid())
return m_privateData->defaultPropertyName();
@@ -1524,10 +1556,14 @@ PropertyName NodeMetaInfo::defaultPropertyName() const
PropertyMetaInfo NodeMetaInfo::defaultProperty() const
{
if constexpr (useProjectStorage()) {
- return PropertyMetaInfo(typeData().defaultPropertyId, m_projectStorage);
+ if (isValid()) {
+ return PropertyMetaInfo(typeData().defaultPropertyId, m_projectStorage);
+ }
} else {
return property(defaultPropertyName());
}
+
+ return {};
}
bool NodeMetaInfo::hasDefaultProperty() const
{
@@ -2801,8 +2837,14 @@ bool NodeMetaInfo::isEnumeration() const
return false;
}
+PropertyMetaInfo::PropertyMetaInfo() = default;
+PropertyMetaInfo::PropertyMetaInfo(const PropertyMetaInfo &) = default;
+PropertyMetaInfo &PropertyMetaInfo::operator=(const PropertyMetaInfo &) = default;
+PropertyMetaInfo::PropertyMetaInfo(PropertyMetaInfo &&) = default;
+PropertyMetaInfo &PropertyMetaInfo::operator=(PropertyMetaInfo &&) = default;
+
PropertyMetaInfo::PropertyMetaInfo(
- [[maybe_unused]] QSharedPointer<NodeMetaInfoPrivate> nodeMetaInfoPrivateData,
+ [[maybe_unused]] std::shared_ptr<NodeMetaInfoPrivate> nodeMetaInfoPrivateData,
[[maybe_unused]] const PropertyName &propertyName)
#ifndef QDS_USE_PROJECTSTORAGE
: m_nodeMetaInfoPrivateData{nodeMetaInfoPrivateData}
@@ -2829,10 +2871,14 @@ NodeMetaInfo PropertyMetaInfo::propertyType() const
PropertyName PropertyMetaInfo::name() const
{
- if constexpr (useProjectStorage())
- return PropertyName(Utils::SmallStringView(propertyData().name));
- else
- return propertyName();
+ if (isValid()) {
+ if constexpr (useProjectStorage())
+ return PropertyName(Utils::SmallStringView(propertyData().name));
+ else
+ return propertyName();
+ }
+
+ return {};
}
bool PropertyMetaInfo::isWritable() const
@@ -2890,8 +2936,7 @@ QVariant PropertyMetaInfo::castedValue(const QVariant &value) const
QVariant::Type typeId = nodeMetaInfoPrivateData()->variantTypeId(propertyName());
- if (variant.type() == QVariant::UserType
- && variant.userType() == ModelNode::variantUserType()) {
+ if (variant.typeId() == QVariant::UserType && variant.typeId() == ModelNode::variantTypeId()) {
return variant;
} else if (typeId == QVariant::UserType && typeName == "QVariant") {
return variant;
@@ -2899,7 +2944,7 @@ QVariant PropertyMetaInfo::castedValue(const QVariant &value) const
return variant;
} else if (typeId == QVariant::UserType && typeName == "var") {
return variant;
- } else if (variant.type() == QVariant::List) {
+ } else if (variant.typeId() == QVariant::List) {
// TODO: check the contents of the list
return variant;
} else if (typeName == "var" || typeName == "variant") {
@@ -2925,11 +2970,11 @@ QVariant PropertyMetaInfo::castedValue(const QVariant &value) const
const TypeId &typeId = propertyData().typeId;
- if (value.type() == QVariant::UserType && value.userType() == ModelNode::variantUserType()) {
+ if (value.typeId() == QVariant::UserType && value.typeId() == ModelNode::variantTypeId()) {
return value;
} else if (typeId == m_projectStorage->builtinTypeId<QVariant>()) {
return value;
- } else if (value.type() == QVariant::List) {
+ } else if (value.typeId() == QVariant::List) {
// TODO: check the contents of the list
return value;
} else if (typeId == m_projectStorage->builtinTypeId<double>()) {
@@ -2983,7 +3028,7 @@ TypeName PropertyMetaInfo::propertyTypeName() const
const NodeMetaInfoPrivate *PropertyMetaInfo::nodeMetaInfoPrivateData() const
{
#ifndef QDS_USE_PROJECTSTORAGE
- return m_nodeMetaInfoPrivateData.data();
+ return m_nodeMetaInfoPrivateData.get();
#else
return nullptr;
#endif
diff --git a/src/plugins/qmldesigner/designercore/model/abstractproperty.cpp b/src/plugins/qmldesigner/designercore/model/abstractproperty.cpp
index 00541e12e2..e2e5800cab 100644
--- a/src/plugins/qmldesigner/designercore/model/abstractproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/abstractproperty.cpp
@@ -29,7 +29,6 @@ AbstractProperty::AbstractProperty(const PropertyName &propertyName, const Inter
m_model(model),
m_view(view)
{
- Q_ASSERT(!m_model || m_view);
Q_ASSERT_X(!m_propertyName.contains(' '), Q_FUNC_INFO, "a property name cannot contain a space");
}
@@ -52,11 +51,6 @@ AbstractProperty::AbstractProperty(const AbstractProperty &property, AbstractVie
AbstractProperty::~AbstractProperty() = default;
-Internal::InternalNodePointer AbstractProperty::internalNode() const
-{
- return m_internalNode;
-}
-
Internal::ModelPrivate *AbstractProperty::privateModel() const
{
return m_model ? m_model->d.get() : nullptr;
@@ -296,6 +290,17 @@ bool AbstractProperty::isSignalDeclarationProperty() const
return false;
}
+PropertyType AbstractProperty::type() const
+{
+ if (!isValid())
+ return PropertyType::None;
+
+ if (internalNode()->hasProperty(name()))
+ return internalNode()->property(name())->propertyType();
+
+ return PropertyType::None;
+}
+
bool AbstractProperty::isBindingProperty() const
{
if (!isValid())
@@ -325,32 +330,13 @@ TypeName AbstractProperty::dynamicTypeName() const
return TypeName();
}
-/*!
- Returns whether \a property1 and \a property2 reference the same property in
- the same node.
-*/
-bool operator ==(const AbstractProperty &property1, const AbstractProperty &property2)
-{
- return (property1.m_model == property2.m_model)
- && (property1.m_internalNode == property2.m_internalNode)
- && (property1.m_propertyName == property2.m_propertyName);
-}
-
-/*!
- Returns whether \a property1 and \a property2 do not reference the same
- property in the same node.
- */
-bool operator !=(const AbstractProperty &property1, const AbstractProperty &property2)
-{
- return !(property1 == property2);
-}
-
QDebug operator<<(QDebug debug, const AbstractProperty &property)
{
- return debug.nospace() << "AbstractProperty(" << (property.isValid() ? property.name() : PropertyName("invalid")) << ')';
+ return debug.nospace() << "AbstractProperty("
+ << (property.isValid() ? property.name() : PropertyName("invalid")) << ')';
}
-QTextStream& operator<<(QTextStream &stream, const AbstractProperty &property)
+QTextStream &operator<<(QTextStream &stream, const AbstractProperty &property)
{
stream << "AbstractProperty(" << property.name() << ')';
@@ -358,4 +344,3 @@ QTextStream& operator<<(QTextStream &stream, const AbstractProperty &property)
}
} // namespace QmlDesigner
-
diff --git a/src/plugins/qmldesigner/designercore/model/abstractview.cpp b/src/plugins/qmldesigner/designercore/model/abstractview.cpp
index 9967d49ee7..a8ad4b76e7 100644
--- a/src/plugins/qmldesigner/designercore/model/abstractview.cpp
+++ b/src/plugins/qmldesigner/designercore/model/abstractview.cpp
@@ -380,14 +380,16 @@ void AbstractView::dragEnded() {}
QList<ModelNode> AbstractView::toModelNodeList(const QList<Internal::InternalNode::Pointer> &nodeList) const
{
- return QmlDesigner::toModelNodeList(nodeList, const_cast<AbstractView*>(this));
+ return QmlDesigner::toModelNodeList(nodeList, m_model, const_cast<AbstractView *>(this));
}
-QList<ModelNode> toModelNodeList(const QList<Internal::InternalNode::Pointer> &nodeList, AbstractView *view)
+QList<ModelNode> toModelNodeList(const QList<Internal::InternalNode::Pointer> &nodeList,
+ Model *model,
+ AbstractView *view)
{
QList<ModelNode> newNodeList;
for (const Internal::InternalNode::Pointer &node : nodeList)
- newNodeList.append(ModelNode(node, view->model(), view));
+ newNodeList.append(ModelNode(node, model, view));
return newNodeList;
}
@@ -438,7 +440,7 @@ bool AbstractView::hasSelectedModelNodes() const
bool AbstractView::hasSingleSelectedModelNode() const
{
- return model()->d->selectedNodes().count() == 1;
+ return model()->d->selectedNodes().size() == 1;
}
bool AbstractView::isSelectedModelNode(const ModelNode &modelNode) const
@@ -623,7 +625,12 @@ void AbstractView::setEnabled(bool b)
QList<ModelNode> AbstractView::allModelNodes() const
{
QTC_ASSERT(model(), return {});
- return toModelNodeList(model()->d->allNodes());
+ return toModelNodeList(model()->d->allNodesOrdered());
+}
+
+QList<ModelNode> AbstractView::allModelNodesUnordered() const
+{
+ return toModelNodeList(model()->d->allNodesUnordered());
}
QList<ModelNode> AbstractView::allModelNodesOfType(const NodeMetaInfo &type) const
diff --git a/src/plugins/qmldesigner/designercore/model/bindingproperty.cpp b/src/plugins/qmldesigner/designercore/model/bindingproperty.cpp
index 45d4e4cf20..558f6849be 100644
--- a/src/plugins/qmldesigner/designercore/model/bindingproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/bindingproperty.cpp
@@ -7,6 +7,7 @@
#include "internalnode_p.h"
#include "model.h"
#include "model_p.h"
+
namespace QmlDesigner {
bool compareBindingProperties(const QmlDesigner::BindingProperty &bindingProperty01, const QmlDesigner::BindingProperty &bindingProperty02)
@@ -47,16 +48,15 @@ void BindingProperty::setExpression(const QString &expression)
if (expression.isEmpty())
return;
- if (internalNode()->hasProperty(name())) { //check if oldValue != value
- Internal::InternalProperty::Pointer internalProperty = internalNode()->property(name());
- if (internalProperty->isBindingProperty()
- && internalProperty->toBindingProperty()->expression() == expression)
-
+ if (auto internalProperty = internalNode()->property(name())) {
+ auto bindingProperty = internalProperty->to<PropertyType::Binding>();
+ //check if oldValue != value
+ if (bindingProperty && bindingProperty->expression() == expression)
return;
- }
- if (internalNode()->hasProperty(name()) && !internalNode()->property(name())->isBindingProperty())
- privateModel()->removePropertyAndRelatedResources(internalNode()->property(name()));
+ if (!bindingProperty)
+ privateModel()->removePropertyAndRelatedResources(internalProperty);
+ }
privateModel()->setBindingProperty(internalNode(), name(), expression);
}
@@ -70,7 +70,7 @@ QString BindingProperty::expression() const
return QString();
}
-static ModelNode resolveBinding(const QString &binding, ModelNode currentNode, AbstractView* view)
+ModelNode BindingProperty::resolveBinding(const QString &binding, ModelNode currentNode) const
{
int index = 0;
QString element = binding.split(QLatin1Char('.')).at(0);
@@ -85,16 +85,14 @@ static ModelNode resolveBinding(const QString &binding, ModelNode currentNode, A
} else if (currentNode.hasProperty(element.toUtf8())) {
if (currentNode.property(element.toUtf8()).isNodeProperty())
currentNode = currentNode.nodeProperty(element.toUtf8()).modelNode();
- else if (view->hasId(element))
- currentNode = view->modelNodeForId(element); //id
else
- return ModelNode(); //binding not valid
+ return ModelNode(privateModel()->nodeForId(element), model(), view());
} else {
- currentNode = view->modelNodeForId(element); //id
+ currentNode = ModelNode(privateModel()->nodeForId(element), model(), view());
}
index++;
- if (index < binding.split(QLatin1Char('.')).count())
+ if (index < binding.split(QLatin1Char('.')).size())
element = binding.split(QLatin1Char('.')).at(index);
else
element.clear();
@@ -111,10 +109,15 @@ ModelNode BindingProperty::resolveToModelNode() const
if (!isValid())
return {};
- return resolveBinding(expression(), parentModelNode(), view());
+ QString binding = expression();
+
+ if (binding.isEmpty())
+ return {};
+
+ return resolveBinding(binding, parentModelNode());
}
-static inline QStringList commaSeparatedSimplifiedStringList(const QString &string)
+inline static QStringList commaSeparatedSimplifiedStringList(const QString &string)
{
const QStringList stringList = string.split(QStringLiteral(","));
QStringList simpleList;
@@ -130,13 +133,17 @@ AbstractProperty BindingProperty::resolveToProperty() const
return {};
QString binding = expression();
+
+ if (binding.isEmpty())
+ return {};
+
ModelNode node = parentModelNode();
QString element;
if (binding.contains(QLatin1Char('.'))) {
element = binding.split(QLatin1Char('.')).constLast();
QString nodeBinding = binding;
nodeBinding.chop(element.length());
- node = resolveBinding(nodeBinding, parentModelNode(), view());
+ node = resolveBinding(nodeBinding, parentModelNode());
} else {
element = binding;
}
@@ -160,15 +167,19 @@ QList<ModelNode> BindingProperty::resolveToModelNodeList() const
if (!isValid())
return {};
+ QString binding = expression();
+
+ if (binding.isEmpty())
+ return {};
+
QList<ModelNode> returnList;
if (isList()) {
- QString string = expression();
- string.chop(1);
- string.remove(0, 1);
- const QStringList simplifiedList = commaSeparatedSimplifiedStringList(string);
+ binding.chop(1);
+ binding.remove(0, 1);
+ const QStringList simplifiedList = commaSeparatedSimplifiedStringList(binding);
for (const QString &nodeId : simplifiedList) {
- if (view()->hasId(nodeId))
- returnList.append(view()->modelNodeForId(nodeId));
+ if (auto internalNode = privateModel()->nodeForId(nodeId))
+ returnList.append(ModelNode{internalNode, model(), view()});
}
}
return returnList;
@@ -262,11 +273,9 @@ bool BindingProperty::isAliasExport() const
{
if (!isValid())
return false;
- return parentModelNode() == parentModelNode().view()->rootModelNode()
- && isDynamic()
- && dynamicTypeName() == "alias"
- && name() == expression().toUtf8()
- && parentModelNode().view()->modelNodeForId(expression()).isValid();
+ return parentModelNode() == parentModelNode().model()->rootModelNode() && isDynamic()
+ && dynamicTypeName() == "alias" && name() == expression().toUtf8()
+ && parentModelNode().model()->modelNodeForId(expression()).isValid();
}
static bool isTrueFalseLiteral(const QString &expression)
@@ -330,20 +339,19 @@ void BindingProperty::setDynamicTypeNameAndExpression(const TypeName &typeName,
if (typeName.isEmpty())
return;
- if (internalNode()->hasProperty(name())) { //check if oldValue != value
- Internal::InternalProperty::Pointer internalProperty = internalNode()->property(name());
- if (internalProperty->isBindingProperty()
- && internalProperty->toBindingProperty()->expression() == expression
- && internalProperty->toBindingProperty()->dynamicTypeName() == typeName) {
-
+ if (auto internalProperty = internalNode()->property(name())) {
+ auto bindingProperty = internalProperty->to<PropertyType::Binding>();
+ //check if oldValue != value
+ if (bindingProperty && bindingProperty->expression() == expression
+ && internalProperty->dynamicTypeName() == typeName) {
return;
}
- }
- if (internalNode()->hasProperty(name()) && !internalNode()->property(name())->isBindingProperty())
- privateModel()->removePropertyAndRelatedResources(internalNode()->property(name()));
+ if (!bindingProperty)
+ privateModel()->removePropertyAndRelatedResources(internalProperty);
+ }
- privateModel()->setDynamicBindingProperty(internalNode(), name(), typeName, expression);
+ privateModel()->setDynamicBindingProperty(internalNode(), name(), typeName, expression);
}
QDebug operator<<(QDebug debug, const BindingProperty &property)
diff --git a/src/plugins/qmldesigner/designercore/model/internalbindingproperty.cpp b/src/plugins/qmldesigner/designercore/model/internalbindingproperty.cpp
index 28cd56a790..6a3eee1975 100644
--- a/src/plugins/qmldesigner/designercore/model/internalbindingproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/internalbindingproperty.cpp
@@ -6,22 +6,12 @@
namespace QmlDesigner {
namespace Internal {
-InternalBindingProperty::InternalBindingProperty(const PropertyName &name, const InternalNodePointer &propertyOwner)
- : InternalProperty(name, propertyOwner)
+InternalBindingProperty::InternalBindingProperty(const PropertyName &name,
+ const InternalNodePointer &propertyOwner)
+ : InternalProperty(name, propertyOwner, PropertyType::Binding)
{
}
-
-InternalBindingProperty::Pointer InternalBindingProperty::create(const PropertyName &name, const InternalNodePointer &propertyOwner)
-{
- auto newPointer(new InternalBindingProperty(name, propertyOwner));
- InternalBindingProperty::Pointer smartPointer(newPointer);
-
- newPointer->setInternalWeakPointer(smartPointer);
-
- return smartPointer;
-}
-
bool InternalBindingProperty::isValid() const
{
return InternalProperty::isValid() && isBindingProperty();
@@ -36,11 +26,6 @@ void InternalBindingProperty::setExpression(const QString &expression)
m_expression = expression;
}
-bool InternalBindingProperty::isBindingProperty() const
-{
- return true;
-}
-
void InternalBindingProperty::setDynamicExpression(const TypeName &type, const QString &expression)
{
setExpression(expression);
diff --git a/src/plugins/qmldesigner/designercore/model/internalbindingproperty.h b/src/plugins/qmldesigner/designercore/model/internalbindingproperty.h
index 202434bec8..9ad0e19fc9 100644
--- a/src/plugins/qmldesigner/designercore/model/internalbindingproperty.h
+++ b/src/plugins/qmldesigner/designercore/model/internalbindingproperty.h
@@ -11,9 +11,10 @@ namespace Internal {
class InternalBindingProperty : public InternalProperty
{
public:
- using Pointer = QSharedPointer<InternalBindingProperty>;
+ using Pointer = std::shared_ptr<InternalBindingProperty>;
+ static constexpr PropertyType type = PropertyType::Binding;
- static Pointer create(const PropertyName &name, const InternalNodePointer &propertyOwner);
+ InternalBindingProperty(const PropertyName &name, const InternalNodePointer &propertyOwner);
bool isValid() const override;
@@ -22,11 +23,7 @@ public:
void setDynamicExpression(const TypeName &type, const QString &expression);
-
- bool isBindingProperty() const override;
-
protected:
- InternalBindingProperty(const PropertyName &name, const InternalNodePointer &propertyOwner);
private:
QString m_expression;
diff --git a/src/plugins/qmldesigner/designercore/model/internalnode.cpp b/src/plugins/qmldesigner/designercore/model/internalnode.cpp
index 003ab8d31c..0c81d2ab28 100644
--- a/src/plugins/qmldesigner/designercore/model/internalnode.cpp
+++ b/src/plugins/qmldesigner/designercore/model/internalnode.cpp
@@ -1,11 +1,14 @@
// 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 "internalbindingproperty.h"
#include "internalnode_p.h"
+#include "internalnodeabstractproperty.h"
+#include "internalnodelistproperty.h"
+#include "internalnodeproperty.h"
#include "internalproperty.h"
+#include "internalsignalhandlerproperty.h"
#include "internalvariantproperty.h"
-#include "internalnodeproperty.h"
-#include "internalnodelistproperty.h"
#include <QDebug>
@@ -17,11 +20,11 @@ namespace Internal {
InternalNodeAbstractProperty::Pointer InternalNode::parentProperty() const
{
- return m_parentProperty;
+ return m_parentProperty.lock();
}
void InternalNode::setParentProperty(const InternalNodeAbstractProperty::Pointer &parent)
{
- InternalNodeAbstractProperty::Pointer parentProperty = m_parentProperty.toStrongRef();
+ InternalNodeAbstractProperty::Pointer parentProperty = m_parentProperty.lock();
if (parentProperty)
parentProperty->remove(shared_from_this());
@@ -33,11 +36,11 @@ void InternalNode::setParentProperty(const InternalNodeAbstractProperty::Pointer
void InternalNode::resetParentProperty()
{
- InternalNodeAbstractProperty::Pointer parentProperty = m_parentProperty.toStrongRef();
+ InternalNodeAbstractProperty::Pointer parentProperty = m_parentProperty.lock();
if (parentProperty)
parentProperty->remove(shared_from_this());
- m_parentProperty.clear();
+ m_parentProperty.reset();
}
namespace {
@@ -111,117 +114,10 @@ AuxiliaryDatasForType InternalNode::auxiliaryData(AuxiliaryDataType type) const
return data;
}
-InternalProperty::Pointer InternalNode::property(const PropertyName &name) const
-{
- return m_namePropertyHash.value(name);
-}
-
-InternalBindingProperty::Pointer InternalNode::bindingProperty(const PropertyName &name) const
-{
- InternalProperty::Pointer property = m_namePropertyHash.value(name);
- if (property->isBindingProperty())
- return property.staticCast<InternalBindingProperty>();
-
- return InternalBindingProperty::Pointer();
-}
-
-InternalSignalHandlerProperty::Pointer InternalNode::signalHandlerProperty(const PropertyName &name) const
-{
- InternalProperty::Pointer property = m_namePropertyHash.value(name);
- if (property->isSignalHandlerProperty())
- return property.staticCast<InternalSignalHandlerProperty>();
-
- return InternalSignalHandlerProperty::Pointer();
-}
-
-InternalSignalDeclarationProperty::Pointer InternalNode::signalDeclarationProperty(const PropertyName &name) const
-{
- InternalProperty::Pointer property = m_namePropertyHash.value(name);
- if (property->isSignalDeclarationProperty())
- return property.staticCast<InternalSignalDeclarationProperty>();
-
- return InternalSignalDeclarationProperty::Pointer();
-}
-
-InternalVariantProperty::Pointer InternalNode::variantProperty(const PropertyName &name) const
-{
- InternalProperty::Pointer property = m_namePropertyHash.value(name);
- if (property->isVariantProperty())
- return property.staticCast<InternalVariantProperty>();
-
- return InternalVariantProperty::Pointer();
-}
-
-void InternalNode::addBindingProperty(const PropertyName &name)
-{
- InternalProperty::Pointer newProperty(InternalBindingProperty::create(name, shared_from_this()));
- m_namePropertyHash.insert(name, newProperty);
-}
-
-void InternalNode::addSignalHandlerProperty(const PropertyName &name)
-{
- InternalProperty::Pointer newProperty(
- InternalSignalHandlerProperty::create(name, shared_from_this()));
- m_namePropertyHash.insert(name, newProperty);
-}
-
-void InternalNode::addSignalDeclarationProperty(const PropertyName &name)
-{
- InternalProperty::Pointer newProperty(
- InternalSignalDeclarationProperty::create(name, shared_from_this()));
- m_namePropertyHash.insert(name, newProperty);
-}
-
-InternalNodeListProperty::Pointer InternalNode::nodeListProperty(const PropertyName &name) const
-{
- InternalProperty::Pointer property = m_namePropertyHash.value(name);
- if (property && property->isNodeListProperty())
- return property.staticCast<InternalNodeListProperty>();
-
- return InternalNodeListProperty::Pointer();
-}
-
-InternalNodeAbstractProperty::Pointer InternalNode::nodeAbstractProperty(const PropertyName &name) const
-{
- InternalProperty::Pointer property = m_namePropertyHash.value(name);
- if (property && property->isNodeAbstractProperty())
- return property.staticCast<InternalNodeAbstractProperty>();
-
- return InternalNodeProperty::Pointer();
-}
-
-InternalNodeProperty::Pointer InternalNode::nodeProperty(const PropertyName &name) const
-{
- InternalProperty::Pointer property = m_namePropertyHash.value(name);
- if (property->isNodeProperty())
- return property.staticCast<InternalNodeProperty>();
-
- return InternalNodeProperty::Pointer();
-}
-
-void InternalNode::addVariantProperty(const PropertyName &name)
-{
- InternalProperty::Pointer newProperty(InternalVariantProperty::create(name, shared_from_this()));
- m_namePropertyHash.insert(name, newProperty);
-}
-
-void InternalNode::addNodeProperty(const PropertyName &name, const TypeName &dynamicTypeName)
-{
- InternalNodeProperty::Pointer newProperty(InternalNodeProperty::create(name, shared_from_this()));
- newProperty->setDynamicTypeName(dynamicTypeName);
- m_namePropertyHash.insert(name, newProperty);
-}
-
-void InternalNode::addNodeListProperty(const PropertyName &name)
-{
- InternalProperty::Pointer newProperty(InternalNodeListProperty::create(name, shared_from_this()));
- m_namePropertyHash.insert(name, newProperty);
-}
-
void InternalNode::removeProperty(const PropertyName &name)
{
InternalProperty::Pointer property = m_namePropertyHash.take(name);
- Q_ASSERT(!property.isNull());
+ Q_ASSERT(property);
}
PropertyNameList InternalNode::propertyNameList() const
@@ -250,13 +146,12 @@ QList<InternalNodeAbstractProperty::Pointer> InternalNode::nodeAbstractPropertyL
const QList<InternalProperty::Pointer> properties = propertyList();
for (const InternalProperty::Pointer &property : properties) {
if (property->isNodeAbstractProperty())
- abstractPropertyList.append(property->toNodeAbstractProperty());
+ abstractPropertyList.append(property->toProperty<InternalNodeAbstractProperty>());
}
return abstractPropertyList;
}
-
QList<InternalNode::Pointer> InternalNode::allSubNodes() const
{
QList<InternalNode::Pointer> nodeList;
@@ -280,4 +175,4 @@ QList<InternalNode::Pointer> InternalNode::allDirectSubNodes() const
}
} // namespace Internal
-}
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/model/internalnode_p.h b/src/plugins/qmldesigner/designercore/model/internalnode_p.h
index ddcb3c9cbb..8b3ff86d2b 100644
--- a/src/plugins/qmldesigner/designercore/model/internalnode_p.h
+++ b/src/plugins/qmldesigner/designercore/model/internalnode_p.h
@@ -34,7 +34,7 @@ class InternalProperty;
class InternalNode;
using InternalNodePointer = std::shared_ptr<InternalNode>;
-using InternalPropertyPointer = QSharedPointer<InternalProperty>;
+using InternalPropertyPointer = std::shared_ptr<InternalProperty>;
class InternalNode : public std::enable_shared_from_this<InternalNode>
{
@@ -44,8 +44,6 @@ public:
using Pointer = std::shared_ptr<InternalNode>;
using WeakPointer = std::weak_ptr<InternalNode>;
- explicit InternalNode() = default;
-
explicit InternalNode(TypeName typeName, int majorVersion, int minorVersion, qint32 internalId)
: typeName(std::move(typeName))
, majorVersion(majorVersion)
@@ -67,21 +65,101 @@ public:
AuxiliaryDatasForType auxiliaryData(AuxiliaryDataType type) const;
AuxiliaryDatasView auxiliaryData() const { return std::as_const(m_auxiliaryDatas); }
- InternalProperty::Pointer property(const PropertyName &name) const;
- InternalBindingProperty::Pointer bindingProperty(const PropertyName &name) const;
- InternalSignalHandlerProperty::Pointer signalHandlerProperty(const PropertyName &name) const;
- InternalSignalDeclarationProperty::Pointer signalDeclarationProperty(const PropertyName &name) const;
- InternalVariantProperty::Pointer variantProperty(const PropertyName &name) const;
- InternalNodeListProperty::Pointer nodeListProperty(const PropertyName &name) const;
- InternalNodeAbstractProperty::Pointer nodeAbstractProperty(const PropertyName &name) const;
- InternalNodeProperty::Pointer nodeProperty(const PropertyName &name) const;
-
- void addBindingProperty(const PropertyName &name);
- void addSignalHandlerProperty(const PropertyName &name);
- void addSignalDeclarationProperty(const PropertyName &name);
- void addNodeListProperty(const PropertyName &name);
- void addVariantProperty(const PropertyName &name);
- void addNodeProperty(const PropertyName &name, const TypeName &dynamicTypeName);
+ template<typename Type>
+ typename Type::Pointer property(const PropertyName &name) const
+ {
+ auto property = m_namePropertyHash.value(name);
+ if (property && property->propertyType() == Type::type)
+ return std::static_pointer_cast<Type>(property);
+
+ return {};
+ }
+
+ InternalProperty::Pointer property(const PropertyName &name) const
+ {
+ return m_namePropertyHash.value(name);
+ }
+
+ auto bindingProperty(const PropertyName &name) const
+ {
+ return property<InternalBindingProperty>(name);
+ }
+
+ auto signalHandlerProperty(const PropertyName &name) const
+ {
+ return property<InternalSignalHandlerProperty>(name);
+ }
+
+ auto signalDeclarationProperty(const PropertyName &name) const
+ {
+ return property<InternalSignalDeclarationProperty>(name);
+ }
+
+ auto variantProperty(const PropertyName &name) const
+ {
+ return property<InternalVariantProperty>(name);
+ }
+
+ auto nodeListProperty(const PropertyName &name) const
+ {
+ return property<InternalNodeListProperty>(name);
+ }
+
+ InternalNodeAbstractProperty::Pointer nodeAbstractProperty(const PropertyName &name) const
+ {
+ auto property = m_namePropertyHash.value(name);
+ if (property
+ && (property->propertyType() == PropertyType::NodeList
+ || property->propertyType() == PropertyType::Node)) {
+ return std::static_pointer_cast<InternalNodeAbstractProperty>(property);
+ }
+ return {};
+ }
+
+ InternalNodeProperty::Pointer nodeProperty(const PropertyName &name) const
+ {
+ return property<InternalNodeProperty>(name);
+ }
+
+ template<typename Type>
+ auto &addProperty(const PropertyName &name)
+ {
+ auto newProperty = std::make_shared<Type>(name, shared_from_this());
+ auto inserted = m_namePropertyHash.insert(name, std::move(newProperty));
+
+ return *inserted->get();
+ }
+
+ void addBindingProperty(const PropertyName &name)
+ {
+ addProperty<InternalBindingProperty>(name);
+ }
+
+ void addSignalHandlerProperty(const PropertyName &name)
+ {
+ addProperty<InternalSignalHandlerProperty>(name);
+ }
+
+ void addSignalDeclarationProperty(const PropertyName &name)
+ {
+ addProperty<InternalSignalDeclarationProperty>(name);
+ }
+
+ void addNodeListProperty(const PropertyName &name)
+ {
+ addProperty<InternalNodeListProperty>(name);
+ }
+
+ void addVariantProperty(const PropertyName &name)
+ {
+ addProperty<InternalVariantProperty>(name);
+ }
+
+ void addNodeProperty(const PropertyName &name, const TypeName &dynamicTypeName)
+ {
+ auto &property = addProperty<InternalNodeProperty>(name);
+ property.setDynamicTypeName(dynamicTypeName);
+ }
PropertyNameList propertyNameList() const;
@@ -105,13 +183,7 @@ public:
return firstNode->internalId < secondNode->internalId;
}
- friend size_t qHash(const InternalNodePointer &node)
- {
- if (!node)
- return ::qHash(-1);
-
- return ::qHash(node->internalId);
- }
+ friend size_t qHash(const InternalNodePointer &node) { return ::qHash(node.get()); }
protected:
void removeProperty(const PropertyName &name);
diff --git a/src/plugins/qmldesigner/designercore/model/internalnodeabstractproperty.cpp b/src/plugins/qmldesigner/designercore/model/internalnodeabstractproperty.cpp
index e2b753604f..6dff33436e 100644
--- a/src/plugins/qmldesigner/designercore/model/internalnodeabstractproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/internalnodeabstractproperty.cpp
@@ -7,16 +7,13 @@
namespace QmlDesigner {
namespace Internal {
-InternalNodeAbstractProperty::InternalNodeAbstractProperty(const PropertyName &name, const InternalNode::Pointer &propertyOwner)
- : InternalProperty(name, propertyOwner)
+InternalNodeAbstractProperty::InternalNodeAbstractProperty(const PropertyName &name,
+ const InternalNode::Pointer &propertyOwner,
+ PropertyType propertyType)
+ : InternalProperty(name, propertyOwner, propertyType)
{
}
-bool InternalNodeAbstractProperty::isNodeAbstractProperty() const
-{
- return true;
-}
-
bool InternalNodeAbstractProperty::isValid() const
{
return InternalProperty::isValid() && isNodeAbstractProperty();
diff --git a/src/plugins/qmldesigner/designercore/model/internalnodeabstractproperty.h b/src/plugins/qmldesigner/designercore/model/internalnodeabstractproperty.h
index 7867025da9..72e01d019b 100644
--- a/src/plugins/qmldesigner/designercore/model/internalnodeabstractproperty.h
+++ b/src/plugins/qmldesigner/designercore/model/internalnodeabstractproperty.h
@@ -14,10 +14,8 @@ class InternalNodeAbstractProperty : public InternalProperty
friend InternalNode;
public:
- using Pointer = QSharedPointer<InternalNodeAbstractProperty>;
- using WeakPointer = QWeakPointer<InternalNodeAbstractProperty>;
-
- bool isNodeAbstractProperty() const override;
+ using Pointer = std::shared_ptr<InternalNodeAbstractProperty>;
+ using WeakPointer = std::weak_ptr<InternalNodeAbstractProperty>;
virtual QList<InternalNodePointer> allSubNodes() const = 0;
virtual QList<InternalNodePointer> directSubNodes() const = 0;
@@ -31,7 +29,9 @@ public:
using InternalProperty::remove; // keep the virtual remove(...) function around
protected:
- InternalNodeAbstractProperty(const PropertyName &name, const InternalNodePointer &propertyOwner);
+ InternalNodeAbstractProperty(const PropertyName &name,
+ const InternalNodePointer &propertyOwner,
+ PropertyType propertyType);
virtual void remove(const InternalNodePointer &node) = 0;
virtual void add(const InternalNodePointer &node) = 0;
};
diff --git a/src/plugins/qmldesigner/designercore/model/internalnodelistproperty.cpp b/src/plugins/qmldesigner/designercore/model/internalnodelistproperty.cpp
index e47b8588cc..f5c4662785 100644
--- a/src/plugins/qmldesigner/designercore/model/internalnodelistproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/internalnodelistproperty.cpp
@@ -8,21 +8,12 @@
namespace QmlDesigner {
namespace Internal {
-InternalNodeListProperty::InternalNodeListProperty(const PropertyName &name, const InternalNodePointer &propertyOwner)
- : InternalNodeAbstractProperty(name, propertyOwner)
+InternalNodeListProperty::InternalNodeListProperty(const PropertyName &name,
+ const InternalNodePointer &propertyOwner)
+ : InternalNodeAbstractProperty(name, propertyOwner, PropertyType::NodeList)
{
}
-InternalNodeListProperty::Pointer InternalNodeListProperty::create(const PropertyName &name, const InternalNodePointer &propertyOwner)
-{
- auto newPointer(new InternalNodeListProperty(name, propertyOwner));
- InternalProperty::Pointer smartPointer(newPointer);
-
- newPointer->setInternalWeakPointer(smartPointer.toWeakRef());
-
- return smartPointer.staticCast<InternalNodeListProperty>();
-}
-
bool InternalNodeListProperty::isValid() const
{
return InternalProperty::isValid() && isNodeListProperty();
@@ -35,7 +26,7 @@ bool InternalNodeListProperty::isEmpty() const
int InternalNodeListProperty::count() const
{
- return m_nodeList.count();
+ return m_nodeList.size();
}
int InternalNodeListProperty::indexOf(const InternalNode::Pointer &node) const
@@ -46,11 +37,6 @@ int InternalNodeListProperty::indexOf(const InternalNode::Pointer &node) const
return m_nodeList.indexOf(node);
}
-bool InternalNodeListProperty::isNodeListProperty() const
-{
- return true;
-}
-
void InternalNodeListProperty::add(const InternalNode::Pointer &internalNode)
{
Q_ASSERT(!m_nodeList.contains(internalNode));
diff --git a/src/plugins/qmldesigner/designercore/model/internalnodelistproperty.h b/src/plugins/qmldesigner/designercore/model/internalnodelistproperty.h
index 7f4dced451..2e15fdf8ae 100644
--- a/src/plugins/qmldesigner/designercore/model/internalnodelistproperty.h
+++ b/src/plugins/qmldesigner/designercore/model/internalnodelistproperty.h
@@ -14,9 +14,10 @@ namespace Internal {
class InternalNodeListProperty final : public InternalNodeAbstractProperty
{
public:
- using Pointer = QSharedPointer<InternalNodeListProperty>;
+ using Pointer = std::shared_ptr<InternalNodeListProperty>;
+ static constexpr PropertyType type = PropertyType::NodeList;
- static Pointer create(const PropertyName &name, const InternalNodePointer &propertyOwner);
+ InternalNodeListProperty(const PropertyName &name, const InternalNodePointer &propertyOwner);
bool isValid() const override;
@@ -26,13 +27,13 @@ public:
int indexOf(const InternalNodePointer &node) const override;
const InternalNodePointer &at(int index) const
{
- Q_ASSERT(index >= 0 && index < m_nodeList.count());
+ Q_ASSERT(index >= 0 && index < m_nodeList.size());
return m_nodeList[index];
}
InternalNodePointer &at(int index)
{
- Q_ASSERT(index >= 0 && index < m_nodeList.count());
+ Q_ASSERT(index >= 0 && index < m_nodeList.size());
return m_nodeList[index];
}
@@ -43,8 +44,6 @@ public:
return *found;
}
- bool isNodeListProperty() const override;
-
QList<InternalNodePointer> allSubNodes() const override;
QList<InternalNodePointer> directSubNodes() const override;
const QList<InternalNodePointer> &nodeList() const;
@@ -54,7 +53,6 @@ public:
QList<InternalNodePointer>::iterator end() { return m_nodeList.end(); }
protected:
- InternalNodeListProperty(const PropertyName &name, const InternalNodePointer &propertyOwner);
void add(const InternalNodePointer &node) override;
void remove(const InternalNodePointer &node) override;
diff --git a/src/plugins/qmldesigner/designercore/model/internalnodeproperty.cpp b/src/plugins/qmldesigner/designercore/model/internalnodeproperty.cpp
index 508a3d75db..0dd286e765 100644
--- a/src/plugins/qmldesigner/designercore/model/internalnodeproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/internalnodeproperty.cpp
@@ -7,21 +7,12 @@
namespace QmlDesigner {
namespace Internal {
-InternalNodeProperty::InternalNodeProperty(const PropertyName &name, const InternalNode::Pointer &propertyOwner)
- : InternalNodeAbstractProperty(name, propertyOwner)
+InternalNodeProperty::InternalNodeProperty(const PropertyName &name,
+ const InternalNode::Pointer &propertyOwner)
+ : InternalNodeAbstractProperty(name, propertyOwner, PropertyType::Node)
{
}
-InternalNodeProperty::Pointer InternalNodeProperty::create(const PropertyName &name, const InternalNode::Pointer &propertyOwner)
-{
- auto newPointer = new InternalNodeProperty(name, propertyOwner);
- InternalNodeProperty::Pointer smartPointer(newPointer);
-
- newPointer->setInternalWeakPointer(smartPointer);
-
- return smartPointer;
-}
-
bool InternalNodeProperty::isEmpty() const
{
return !m_node;
@@ -48,11 +39,6 @@ bool InternalNodeProperty::isValid() const
return InternalProperty::isValid() && isNodeProperty();
}
-bool InternalNodeProperty::isNodeProperty() const
-{
- return true;
-}
-
InternalNode::Pointer InternalNodeProperty::node() const
{
return m_node;
diff --git a/src/plugins/qmldesigner/designercore/model/internalnodeproperty.h b/src/plugins/qmldesigner/designercore/model/internalnodeproperty.h
index 905a3eccfe..65b9b895e8 100644
--- a/src/plugins/qmldesigner/designercore/model/internalnodeproperty.h
+++ b/src/plugins/qmldesigner/designercore/model/internalnodeproperty.h
@@ -11,24 +11,22 @@ namespace Internal {
class InternalNodeProperty : public InternalNodeAbstractProperty
{
public:
- using Pointer = QSharedPointer<InternalNodeProperty>;
+ using Pointer = std::shared_ptr<InternalNodeProperty>;
+ static constexpr PropertyType type = PropertyType::Node;
- static Pointer create(const PropertyName &name, const InternalNodePointer &propertyOwner);
+ InternalNodeProperty(const PropertyName &name, const InternalNodePointer &node);
bool isValid() const override;
bool isEmpty() const override;
int count() const override;
int indexOf(const InternalNodePointer &node) const override;
- bool isNodeProperty() const override;
QList<InternalNodePointer> allSubNodes() const override;
QList<InternalNodePointer> directSubNodes() const override;
InternalNodePointer node() const;
-
protected:
- InternalNodeProperty(const PropertyName &name, const InternalNodePointer &node);
void add(const InternalNodePointer &node) override;
void remove(const InternalNodePointer &node) override;
diff --git a/src/plugins/qmldesigner/designercore/model/internalproperty.cpp b/src/plugins/qmldesigner/designercore/model/internalproperty.cpp
index 8b15b1f777..076c14fa9b 100644
--- a/src/plugins/qmldesigner/designercore/model/internalproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/internalproperty.cpp
@@ -18,26 +18,15 @@ InternalProperty::InternalProperty() = default;
InternalProperty::~InternalProperty() = default;
-InternalProperty::InternalProperty(const PropertyName &name, const InternalNode::Pointer &propertyOwner)
- : m_name(name),
- m_propertyOwner(propertyOwner)
+InternalProperty::InternalProperty(const PropertyName &name,
+ const InternalNode::Pointer &propertyOwner,
+ PropertyType propertyType)
+ : m_name(name)
+ , m_propertyOwner(propertyOwner)
+ , m_propertyType{propertyType}
{
- Q_ASSERT_X(!name.isEmpty(), Q_FUNC_INFO, "Name of property cannot be empty");
}
-InternalProperty::Pointer InternalProperty::internalPointer() const
-{
- Q_ASSERT(!m_internalPointer.isNull());
- return m_internalPointer.toStrongRef();
-}
-
-void InternalProperty::setInternalWeakPointer(const Pointer &pointer)
-{
- Q_ASSERT(!pointer.isNull());
- m_internalPointer = pointer;
-}
-
-
bool InternalProperty::isValid() const
{
return !m_propertyOwner.expired() && !m_name.isEmpty();
@@ -48,90 +37,11 @@ PropertyName InternalProperty::name() const
return m_name;
}
-bool InternalProperty::isBindingProperty() const
-{
- return false;
-}
-
-bool InternalProperty::isVariantProperty() const
-{
- return false;
-}
-
-QSharedPointer<InternalBindingProperty> InternalProperty::toBindingProperty() const
-{
- Q_ASSERT(internalPointer().dynamicCast<InternalBindingProperty>());
- return internalPointer().staticCast<InternalBindingProperty>();
-}
-
-
-bool InternalProperty::isNodeListProperty() const
-{
- return false;
-}
-
-bool InternalProperty::isNodeProperty() const
-{
- return false;
-}
-
-bool InternalProperty::isNodeAbstractProperty() const
-{
- return false;
-}
-
-bool InternalProperty::isSignalHandlerProperty() const
-{
- return false;
-}
-
-bool InternalProperty::isSignalDeclarationProperty() const
-{
- return false;
-}
-
-QSharedPointer<InternalVariantProperty> InternalProperty::toVariantProperty() const
-
-{
- Q_ASSERT(internalPointer().dynamicCast<InternalVariantProperty>());
- return internalPointer().staticCast<InternalVariantProperty>();
-}
-
InternalNode::Pointer InternalProperty::propertyOwner() const
{
return m_propertyOwner.lock();
}
-QSharedPointer<InternalNodeListProperty> InternalProperty::toNodeListProperty() const
-{
- Q_ASSERT(internalPointer().dynamicCast<InternalNodeListProperty>());
- return internalPointer().staticCast<InternalNodeListProperty>();
-}
-
-QSharedPointer<InternalNodeProperty> InternalProperty::toNodeProperty() const
-{
- Q_ASSERT(internalPointer().dynamicCast<InternalNodeProperty>());
- return internalPointer().staticCast<InternalNodeProperty>();
-}
-
-QSharedPointer<InternalNodeAbstractProperty> InternalProperty::toNodeAbstractProperty() const
-{
- Q_ASSERT(internalPointer().dynamicCast<InternalNodeAbstractProperty>());
- return internalPointer().staticCast<InternalNodeAbstractProperty>();
-}
-
-QSharedPointer<InternalSignalHandlerProperty> InternalProperty::toSignalHandlerProperty() const
-{
- Q_ASSERT(internalPointer().dynamicCast<InternalSignalHandlerProperty>());
- return internalPointer().staticCast<InternalSignalHandlerProperty>();
-}
-
-QSharedPointer<InternalSignalDeclarationProperty> InternalProperty::toSignalDeclarationProperty() const
-{
- Q_ASSERT(internalPointer().dynamicCast<InternalSignalDeclarationProperty>());
- return internalPointer().staticCast<InternalSignalDeclarationProperty>();
-}
-
void InternalProperty::remove()
{
propertyOwner()->removeProperty(name());
@@ -148,7 +58,6 @@ void InternalProperty::setDynamicTypeName(const TypeName &name)
m_dynamicType = name;
}
-
void InternalProperty::resetDynamicTypeName()
{
m_dynamicType.clear();
diff --git a/src/plugins/qmldesigner/designercore/model/internalproperty.h b/src/plugins/qmldesigner/designercore/model/internalproperty.h
index 2038fb40e5..1f24b82509 100644
--- a/src/plugins/qmldesigner/designercore/model/internalproperty.h
+++ b/src/plugins/qmldesigner/designercore/model/internalproperty.h
@@ -6,7 +6,6 @@
#include "qmldesignercorelib_global.h"
#include <QVariant>
-#include <QSharedPointer>
#include <memory>
@@ -25,10 +24,55 @@ class InternalNode;
using InternalNodePointer = std::shared_ptr<InternalNode>;
-class QMLDESIGNERCORE_EXPORT InternalProperty
+template<PropertyType propertyType>
+struct TypeLookup
+{};
+
+template<>
+struct TypeLookup<PropertyType::Binding>
+{
+ using Type = InternalBindingProperty;
+};
+
+template<>
+struct TypeLookup<PropertyType::Node>
+{
+ using Type = InternalNodeProperty;
+};
+
+template<>
+struct TypeLookup<PropertyType::NodeList>
+{
+ using Type = InternalNodeListProperty;
+};
+
+template<>
+struct TypeLookup<PropertyType::None>
+{};
+
+template<>
+struct TypeLookup<PropertyType::SignalDeclaration>
+{
+ using Type = InternalSignalDeclarationProperty;
+};
+
+template<>
+struct TypeLookup<PropertyType::SignalHandler>
+{
+ using Type = InternalSignalHandlerProperty;
+};
+
+template<>
+struct TypeLookup<PropertyType::Variant>
+{
+ using Type = InternalVariantProperty;
+};
+
+class QMLDESIGNERCORE_EXPORT InternalProperty : public std::enable_shared_from_this<InternalProperty>
{
public:
- using Pointer = QSharedPointer<InternalProperty>;
+ friend InternalNode;
+ using Pointer = std::shared_ptr<InternalProperty>;
InternalProperty();
virtual ~InternalProperty();
@@ -37,21 +81,37 @@ public:
PropertyName name() const;
- virtual bool isBindingProperty() const;
- virtual bool isVariantProperty() const;
- virtual bool isNodeListProperty() const;
- virtual bool isNodeProperty() const;
- virtual bool isNodeAbstractProperty() const;
- virtual bool isSignalHandlerProperty() const;
- virtual bool isSignalDeclarationProperty() const;
-
- QSharedPointer<InternalBindingProperty> toBindingProperty() const;
- QSharedPointer<InternalVariantProperty> toVariantProperty() const;
- QSharedPointer<InternalNodeListProperty> toNodeListProperty() const;
- QSharedPointer<InternalNodeProperty> toNodeProperty() const;
- QSharedPointer<InternalNodeAbstractProperty> toNodeAbstractProperty() const;
- QSharedPointer<InternalSignalHandlerProperty> toSignalHandlerProperty() const;
- QSharedPointer<InternalSignalDeclarationProperty> toSignalDeclarationProperty() const;
+ bool isBindingProperty() const { return m_propertyType == PropertyType::Binding; }
+ bool isVariantProperty() const { return m_propertyType == PropertyType::Variant; }
+ bool isNodeListProperty() const { return m_propertyType == PropertyType::NodeList; }
+ bool isNodeProperty() const { return m_propertyType == PropertyType::Node; }
+ bool isNodeAbstractProperty() const
+ {
+ return m_propertyType == PropertyType::Node || m_propertyType == PropertyType::NodeList;
+ }
+ bool isSignalHandlerProperty() const { return m_propertyType == PropertyType::SignalHandler; }
+ bool isSignalDeclarationProperty() const
+ {
+ return m_propertyType == PropertyType::SignalDeclaration;
+ }
+ PropertyType propertyType() const { return m_propertyType; }
+
+ template<typename Type>
+ auto toProperty()
+ {
+ Q_ASSERT(std::dynamic_pointer_cast<Type>(shared_from_this()));
+ return std::static_pointer_cast<Type>(shared_from_this());
+ }
+
+ template<PropertyType propertyType>
+ auto to()
+ {
+ if (propertyType == m_propertyType)
+ return std::static_pointer_cast<typename TypeLookup<propertyType>::Type>(
+ shared_from_this());
+
+ return std::shared_ptr<typename TypeLookup<propertyType>::Type>{};
+ }
InternalNodePointer propertyOwner() const;
@@ -62,15 +122,17 @@ public:
void resetDynamicTypeName();
protected: // functions
- InternalProperty(const PropertyName &name, const InternalNodePointer &propertyOwner);
- Pointer internalPointer() const;
- void setInternalWeakPointer(const Pointer &pointer);
+ InternalProperty(const PropertyName &name,
+ const InternalNodePointer &propertyOwner,
+ PropertyType propertyType);
+
void setDynamicTypeName(const TypeName &name);
+
private:
- QWeakPointer<InternalProperty> m_internalPointer;
PropertyName m_name;
TypeName m_dynamicType;
std::weak_ptr<InternalNode> m_propertyOwner;
+ PropertyType m_propertyType = PropertyType::None;
};
} // namespace Internal
diff --git a/src/plugins/qmldesigner/designercore/model/internalsignalhandlerproperty.cpp b/src/plugins/qmldesigner/designercore/model/internalsignalhandlerproperty.cpp
index ef24622928..70aade63a6 100644
--- a/src/plugins/qmldesigner/designercore/model/internalsignalhandlerproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/internalsignalhandlerproperty.cpp
@@ -6,22 +6,12 @@
namespace QmlDesigner {
namespace Internal {
-InternalSignalHandlerProperty::InternalSignalHandlerProperty(const PropertyName &name, const InternalNodePointer &propertyOwner)
- : InternalProperty(name, propertyOwner)
+InternalSignalHandlerProperty::InternalSignalHandlerProperty(const PropertyName &name,
+ const InternalNodePointer &propertyOwner)
+ : InternalProperty(name, propertyOwner, PropertyType::SignalHandler)
{
}
-
-InternalSignalHandlerProperty::Pointer InternalSignalHandlerProperty::create(const PropertyName &name, const InternalNodePointer &propertyOwner)
-{
- auto newPointer(new InternalSignalHandlerProperty(name, propertyOwner));
- InternalSignalHandlerProperty::Pointer smartPointer(newPointer);
-
- newPointer->setInternalWeakPointer(smartPointer);
-
- return smartPointer;
-}
-
bool InternalSignalHandlerProperty::isValid() const
{
return InternalProperty::isValid() && isSignalHandlerProperty();
@@ -36,23 +26,6 @@ void InternalSignalHandlerProperty::setSource(const QString &source)
m_source = source;
}
-bool InternalSignalHandlerProperty::isSignalHandlerProperty() const
-{
- return true;
-}
-
-InternalSignalDeclarationProperty::Pointer InternalSignalDeclarationProperty::create(const PropertyName &name, const InternalNodePointer &propertyOwner)
-{
- auto newPointer(new InternalSignalDeclarationProperty(name, propertyOwner));
- InternalSignalDeclarationProperty::Pointer smartPointer(newPointer);
-
- newPointer->setInternalWeakPointer(smartPointer);
-
- newPointer->setDynamicTypeName("signal");
-
- return smartPointer;
-}
-
bool InternalSignalDeclarationProperty::isValid() const
{
return InternalProperty::isValid() && isSignalDeclarationProperty();
@@ -68,14 +41,11 @@ void InternalSignalDeclarationProperty::setSignature(const QString &signature)
m_signature = signature;
}
-bool InternalSignalDeclarationProperty::isSignalDeclarationProperty() const
-{
- return true;
-}
-
-InternalSignalDeclarationProperty::InternalSignalDeclarationProperty(const PropertyName &name, const InternalNodePointer &propertyOwner)
- : InternalProperty(name, propertyOwner)
+InternalSignalDeclarationProperty::InternalSignalDeclarationProperty(
+ const PropertyName &name, const InternalNodePointer &propertyOwner)
+ : InternalProperty(name, propertyOwner, PropertyType::SignalDeclaration)
{
+ setDynamicTypeName("signal");
}
} // namespace Internal
diff --git a/src/plugins/qmldesigner/designercore/model/internalsignalhandlerproperty.h b/src/plugins/qmldesigner/designercore/model/internalsignalhandlerproperty.h
index 5fbf665fc6..f0d88e2d23 100644
--- a/src/plugins/qmldesigner/designercore/model/internalsignalhandlerproperty.h
+++ b/src/plugins/qmldesigner/designercore/model/internalsignalhandlerproperty.h
@@ -11,20 +11,16 @@ namespace Internal {
class InternalSignalHandlerProperty : public InternalProperty
{
public:
- using Pointer = QSharedPointer<InternalSignalHandlerProperty>;
+ using Pointer = std::shared_ptr<InternalSignalHandlerProperty>;
+ static constexpr PropertyType type = PropertyType::SignalHandler;
- static Pointer create(const PropertyName &name, const InternalNodePointer &propertyOwner);
+ InternalSignalHandlerProperty(const PropertyName &name, const InternalNodePointer &propertyOwner);
bool isValid() const override;
QString source() const;
void setSource(const QString &source);
- bool isSignalHandlerProperty() const override;
-
-protected:
- InternalSignalHandlerProperty(const PropertyName &name, const InternalNodePointer &propertyOwner);
-
private:
QString m_source;
};
@@ -32,20 +28,17 @@ private:
class InternalSignalDeclarationProperty : public InternalProperty
{
public:
- using Pointer = QSharedPointer<InternalSignalDeclarationProperty>;
+ using Pointer = std::shared_ptr<InternalSignalDeclarationProperty>;
+ static constexpr PropertyType type = PropertyType::SignalDeclaration;
- static Pointer create(const PropertyName &name, const InternalNodePointer &propertyOwner);
+ InternalSignalDeclarationProperty(const PropertyName &name,
+ const InternalNodePointer &propertyOwner);
bool isValid() const override;
QString signature() const;
void setSignature(const QString &source);
- bool isSignalDeclarationProperty() const override;
-
-protected:
- InternalSignalDeclarationProperty(const PropertyName &name, const InternalNodePointer &propertyOwner);
-
private:
QString m_signature;
};
diff --git a/src/plugins/qmldesigner/designercore/model/internalvariantproperty.cpp b/src/plugins/qmldesigner/designercore/model/internalvariantproperty.cpp
index 612a41e8b6..53a0347c17 100644
--- a/src/plugins/qmldesigner/designercore/model/internalvariantproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/internalvariantproperty.cpp
@@ -6,21 +6,12 @@
namespace QmlDesigner {
namespace Internal {
-InternalVariantProperty::InternalVariantProperty(const PropertyName &name, const InternalNodePointer &node)
- : InternalProperty(name, node)
+InternalVariantProperty::InternalVariantProperty(const PropertyName &name,
+ const InternalNodePointer &node)
+ : InternalProperty(name, node, PropertyType::Variant)
{
}
-InternalVariantProperty::Pointer InternalVariantProperty::create(const PropertyName &name, const InternalNodePointer &propertyOwner)
-{
- auto newPointer(new InternalVariantProperty(name, propertyOwner));
- InternalVariantProperty::Pointer smartPointer(newPointer);
-
- newPointer->setInternalWeakPointer(smartPointer);
-
- return smartPointer;
-}
-
QVariant InternalVariantProperty::value() const
{
return m_value;
@@ -31,11 +22,6 @@ void InternalVariantProperty::setValue(const QVariant &value)
m_value = value;
}
-bool InternalVariantProperty::isVariantProperty() const
-{
- return true;
-}
-
void InternalVariantProperty::setDynamicValue(const TypeName &type, const QVariant &value)
{
setValue(value);
diff --git a/src/plugins/qmldesigner/designercore/model/internalvariantproperty.h b/src/plugins/qmldesigner/designercore/model/internalvariantproperty.h
index 521009b834..f9bb85d38d 100644
--- a/src/plugins/qmldesigner/designercore/model/internalvariantproperty.h
+++ b/src/plugins/qmldesigner/designercore/model/internalvariantproperty.h
@@ -11,9 +11,10 @@ namespace Internal {
class InternalVariantProperty : public InternalProperty
{
public:
- using Pointer = QSharedPointer<InternalVariantProperty>;
+ using Pointer = std::shared_ptr<InternalVariantProperty>;
+ static constexpr PropertyType type = PropertyType::Variant;
- static Pointer create(const PropertyName &name, const InternalNodePointer &propertyOwner);
+ InternalVariantProperty(const PropertyName &name, const InternalNodePointer &propertyOwner);
bool isValid() const override;
@@ -22,11 +23,6 @@ public:
void setDynamicValue(const TypeName &type, const QVariant &value);
- bool isVariantProperty() const override;
-
-protected:
- InternalVariantProperty(const PropertyName &name, const InternalNodePointer &propertyOwner);
-
private:
QVariant m_value;
};
diff --git a/src/plugins/qmldesigner/designercore/model/model.cpp b/src/plugins/qmldesigner/designercore/model/model.cpp
index 844454ae55..12a8c09183 100644
--- a/src/plugins/qmldesigner/designercore/model/model.cpp
+++ b/src/plugins/qmldesigner/designercore/model/model.cpp
@@ -8,10 +8,13 @@
#include "abstractview.h"
#include "auxiliarydataproperties.h"
+#include "internalbindingproperty.h"
#include "internalnodeabstractproperty.h"
#include "internalnodelistproperty.h"
+#include "internalnodeproperty.h"
#include "internalproperty.h"
#include "internalsignalhandlerproperty.h"
+#include "internalvariantproperty.h"
#include "metainfo.h"
#include "nodeinstanceview.h"
#include "nodemetainfo.h"
@@ -23,7 +26,6 @@
#include "rewriterview.h"
#include "rewritingexception.h"
#include "signalhandlerproperty.h"
-#include "textmodifier.h"
#include "variantproperty.h"
#include <projectstorage/projectstorage.h>
@@ -277,7 +279,7 @@ InternalNodePointer ModelPrivate::createNode(const TypeName &typeName,
for (const auto &auxiliaryData : auxiliaryDatas)
newNode->setAuxiliaryData(AuxiliaryDataKeyView{auxiliaryData.first}, auxiliaryData.second);
- m_nodeSet.insert(newNode);
+ m_nodes.push_back(newNode);
m_internalIdNodeHash.insert(newNode->internalId, newNode);
if (!nodeSource.isNull())
@@ -303,7 +305,7 @@ void ModelPrivate::removeNodeFromModel(const InternalNodePointer &node)
if (!node->id.isEmpty())
m_idNodeHash.remove(node->id);
node->isValid = false;
- m_nodeSet.remove(node);
+ m_nodes.removeOne(node);
m_internalIdNodeHash.remove(node->internalId);
}
@@ -319,15 +321,9 @@ void ModelPrivate::handleResourceSet(const ModelResourceSet &resourceSet)
removeNode(node.m_internalNode);
}
- for (const AbstractProperty &property : resourceSet.removeProperties) {
- if (property)
- removeProperty(property.m_internalNode->property(property.m_propertyName));
- }
+ removeProperties(toInternalProperties(resourceSet.removeProperties));
- for (const auto &[property, expression] : resourceSet.setExpressions) {
- if (property)
- setBindingProperty(property.m_internalNode, property.m_propertyName, expression);
- }
+ setBindingProperties(resourceSet.setExpressions);
}
void ModelPrivate::removeAllSubNodes(const InternalNodePointer &node)
@@ -338,10 +334,12 @@ void ModelPrivate::removeAllSubNodes(const InternalNodePointer &node)
void ModelPrivate::removeNodeAndRelatedResources(const InternalNodePointer &node)
{
- if (m_resourceManagement)
- handleResourceSet(m_resourceManagement->removeNode(ModelNode{node, m_model, nullptr}));
- else
+ if (m_resourceManagement) {
+ handleResourceSet(
+ m_resourceManagement->removeNodes({ModelNode{node, m_model, nullptr}}, m_model));
+ } else {
removeNode(node);
+ }
}
void ModelPrivate::removeNode(const InternalNodePointer &node)
@@ -935,7 +933,7 @@ void ModelPrivate::notifyNodeAboutToBeReparent(const InternalNodePointer &node,
if (!oldPropertyName.isEmpty() && oldParent->isValid)
oldProperty = NodeAbstractProperty(oldPropertyName, oldParent, m_model, view);
- if (!newPropertyParent.isNull())
+ if (newPropertyParent)
newProperty = NodeAbstractProperty(newPropertyParent, m_model, view);
ModelNode modelNode(node, m_model, view);
@@ -956,7 +954,7 @@ void ModelPrivate::notifyNodeReparent(const InternalNodePointer &node,
if (!oldPropertyName.isEmpty() && oldParent->isValid)
oldProperty = NodeAbstractProperty(oldPropertyName, oldParent, m_model, view);
- if (!newPropertyParent.isNull())
+ if (newPropertyParent)
newProperty = NodeAbstractProperty(newPropertyParent, m_model, view);
ModelNode modelNode(node, m_model, view);
@@ -1055,6 +1053,39 @@ QVector<InternalNodePointer> ModelPrivate::toInternalNodeVector(const QVector<Mo
return newNodeVector;
}
+QList<InternalPropertyPointer> ModelPrivate::toInternalProperties(const AbstractProperties &properties)
+{
+ QList<InternalPropertyPointer> internalProperties;
+ internalProperties.reserve(properties.size());
+
+ for (const auto &property : properties) {
+ if (property.m_internalNode) {
+ if (auto internalProperty = property.m_internalNode->property(property.m_propertyName))
+ internalProperties.push_back(internalProperty);
+ }
+ }
+
+ return internalProperties;
+}
+
+QList<std::tuple<InternalBindingPropertyPointer, QString>> ModelPrivate::toInternalBindingProperties(
+ const ModelResourceSet::SetExpressions &setExpressions)
+{
+ QList<std::tuple<InternalBindingPropertyPointer, QString>> internalProperties;
+ internalProperties.reserve(setExpressions.size());
+
+ for (const auto &setExpression : setExpressions) {
+ const auto &property = setExpression.property;
+ if (property.m_internalNode) {
+ if (auto internalProperty = property.m_internalNode->bindingProperty(
+ property.m_propertyName))
+ internalProperties.emplace_back(internalProperty, setExpression.expression);
+ }
+ }
+
+ return internalProperties;
+}
+
void ModelPrivate::changeSelectedNodes(const QList<InternalNodePointer> &newSelectedNodeList,
const QList<InternalNodePointer> &oldSelectedNodeList)
{
@@ -1102,7 +1133,7 @@ void ModelPrivate::deselectNode(const InternalNodePointer &node)
void ModelPrivate::removePropertyWithoutNotification(const InternalPropertyPointer &property)
{
if (property->isNodeAbstractProperty()) {
- const auto &&allSubNodes = property->toNodeAbstractProperty()->allSubNodes();
+ const auto &&allSubNodes = property->toProperty<InternalNodeAbstractProperty>()->allSubNodes();
for (const InternalNodePointer &node : allSubNodes)
removeNodeFromModel(node);
}
@@ -1123,25 +1154,38 @@ static QList<PropertyPair> toPropertyPairList(const QList<InternalPropertyPointe
void ModelPrivate::removePropertyAndRelatedResources(const InternalPropertyPointer &property)
{
- if (m_resourceManagement)
+ if (m_resourceManagement) {
handleResourceSet(
- m_resourceManagement->removeProperty(AbstractProperty{property, m_model, nullptr}));
- else
+ m_resourceManagement->removeProperties({AbstractProperty{property, m_model, nullptr}},
+ m_model));
+ } else {
removeProperty(property);
+ }
}
void ModelPrivate::removeProperty(const InternalPropertyPointer &property)
{
- notifyPropertiesAboutToBeRemoved({property});
+ removeProperties({property});
+}
- const QList<PropertyPair> propertyPairList = toPropertyPairList({property});
+void ModelPrivate::removeProperties(const QList<InternalPropertyPointer> &properties)
+{
+ if (properties.isEmpty())
+ return;
+
+ notifyPropertiesAboutToBeRemoved(properties);
+
+ const QList<PropertyPair> propertyPairList = toPropertyPairList(properties);
- removePropertyWithoutNotification(property);
+ for (const auto &property : properties)
+ removePropertyWithoutNotification(property);
notifyPropertiesRemoved(propertyPairList);
}
-void ModelPrivate::setBindingProperty(const InternalNodePointer &node, const PropertyName &name, const QString &expression)
+void ModelPrivate::setBindingProperty(const InternalNodePointer &node,
+ const PropertyName &name,
+ const QString &expression)
{
AbstractView::PropertyChangeFlags propertyChange = AbstractView::NoAdditionalChanges;
if (!node->hasProperty(name)) {
@@ -1155,6 +1199,22 @@ void ModelPrivate::setBindingProperty(const InternalNodePointer &node, const Pro
notifyBindingPropertiesChanged({bindingProperty}, propertyChange);
}
+void ModelPrivate::setBindingProperties(const ModelResourceSet::SetExpressions &setExpressions)
+{
+ if (setExpressions.isEmpty())
+ return;
+
+ AbstractView::PropertyChangeFlags propertyChange = AbstractView::NoAdditionalChanges;
+
+ auto bindingPropertiesWithExpressions = toInternalBindingProperties(setExpressions);
+ auto bindingProperties = Utils::transform(bindingPropertiesWithExpressions,
+ [](const auto &entry) { return std::get<0>(entry); });
+ notifyBindingPropertiesAboutToBeChanged(bindingProperties);
+ for (const auto &[bindingProperty, expression] : bindingPropertiesWithExpressions)
+ bindingProperty->setExpression(expression);
+ notifyBindingPropertiesChanged(bindingProperties, propertyChange);
+}
+
void ModelPrivate::setSignalHandlerProperty(const InternalNodePointer &node, const PropertyName &name, const QString &source)
{
AbstractView::PropertyChangeFlags propertyChange = AbstractView::NoAdditionalChanges;
@@ -1250,7 +1310,7 @@ void ModelPrivate::reparentNode(const InternalNodePointer &parentNode,
}
InternalNodeAbstractPropertyPointer newParentProperty(parentNode->nodeAbstractProperty(name));
- Q_ASSERT(!newParentProperty.isNull());
+ Q_ASSERT(newParentProperty);
notifyNodeAboutToBeReparent(childNode, newParentProperty, oldParentNode, oldParentPropertyName, propertyChange);
@@ -1305,7 +1365,7 @@ void ModelPrivate::setNodeSource(const InternalNodePointer &node, const QString
void ModelPrivate::changeNodeOrder(const InternalNodePointer &parentNode, const PropertyName &listPropertyName, int from, int to)
{
InternalNodeListPropertyPointer nodeList(parentNode->nodeListProperty(listPropertyName));
- Q_ASSERT(!nodeList.isNull());
+ Q_ASSERT(nodeList);
nodeList->slide(from, to);
const InternalNodePointer internalNode = nodeList->nodeList().at(to);
@@ -1376,8 +1436,7 @@ bool ModelPrivate::hasNodeForInternalId(qint32 internalId) const
{
return m_internalIdNodeHash.contains(internalId);
}
-
-QList<InternalNodePointer> ModelPrivate::allNodes() const
+QList<InternalNodePointer> ModelPrivate::allNodesOrdered() const
{
if (!m_rootInternalNode || !m_rootInternalNode->isValid)
return {};
@@ -1388,10 +1447,14 @@ QList<InternalNodePointer> ModelPrivate::allNodes() const
nodeList.append(m_rootInternalNode);
nodeList.append(m_rootInternalNode->allSubNodes());
// FIXME: This is horribly expensive compared to a loop.
- nodeList.append(Utils::toList(m_nodeSet - Utils::toSet(nodeList)));
+ nodeList.append(Utils::toList(Utils::toSet(m_nodes) - Utils::toSet(nodeList)));
return nodeList;
}
+QList<InternalNodePointer> ModelPrivate::allNodesUnordered() const
+{
+ return m_nodes;
+}
bool ModelPrivate::isWriteLocked() const
{
@@ -1786,16 +1849,6 @@ Model *Model::metaInfoProxyModel() const
return const_cast<Model *>(this);
}
-TextModifier *Model::textModifier() const
-{
- return d->m_textModifier.data();
-}
-
-void Model::setTextModifier(TextModifier *textModifier)
-{
- d->m_textModifier = textModifier;
-}
-
void Model::setDocumentMessages(const QList<DocumentMessage> &errors,
const QList<DocumentMessage> &warnings)
{
@@ -1921,6 +1974,26 @@ NodeMetaInfo Model::qtQuickPropertyAnimationMetaInfo() const
}
}
+NodeMetaInfo Model::qtQuickPropertyChangesMetaInfo() const
+{
+ if constexpr (useProjectStorage()) {
+ using namespace Storage::Info;
+ return createNodeMetaInfo<QtQuick, PropertyChanges>();
+ } else {
+ return metaInfo("QtQuick.PropertyChanges");
+ }
+}
+
+NodeMetaInfo Model::flowViewFlowActionAreaMetaInfo() const
+{
+ if constexpr (useProjectStorage()) {
+ using namespace Storage::Info;
+ return createNodeMetaInfo<FlowView, FlowActionArea>();
+ } else {
+ return metaInfo("FlowView.FlowActionArea");
+ }
+}
+
NodeMetaInfo Model::flowViewFlowDecisionMetaInfo() const
{
if constexpr (useProjectStorage()) {
@@ -1931,6 +2004,16 @@ NodeMetaInfo Model::flowViewFlowDecisionMetaInfo() const
}
}
+NodeMetaInfo Model::flowViewFlowItemMetaInfo() const
+{
+ if constexpr (useProjectStorage()) {
+ using namespace Storage::Info;
+ return createNodeMetaInfo<FlowView, FlowItem>();
+ } else {
+ return metaInfo("FlowView.FlowItem");
+ }
+}
+
NodeMetaInfo Model::flowViewFlowWildcardMetaInfo() const
{
if constexpr (useProjectStorage()) {
@@ -2041,6 +2124,16 @@ NodeMetaInfo Model::qtQuickTimelineTimelineMetaInfo() const
}
}
+NodeMetaInfo Model::qtQuickTransistionMetaInfo() const
+{
+ if constexpr (useProjectStorage()) {
+ using namespace Storage::Info;
+ return createNodeMetaInfo<QtQuick, Transition>();
+ } else {
+ return metaInfo("QtQuick.Transition");
+ }
+}
+
NodeMetaInfo Model::qtQuickConnectionsMetaInfo() const
{
if constexpr (useProjectStorage()) {
@@ -2204,9 +2297,105 @@ void Model::detachView(AbstractView *view, ViewNotification emitDetachNotify)
d->detachView(view, emitNotify);
}
-QList<ModelNode> Model::allModelNodes() const
+namespace {
+QList<ModelNode> toModelNodeList(const QList<Internal::InternalNode::Pointer> &nodeList, Model *model)
+{
+ QList<ModelNode> newNodeList;
+ for (const Internal::InternalNode::Pointer &node : nodeList)
+ newNodeList.append(ModelNode(node, model, nullptr));
+
+ return newNodeList;
+}
+} // namespace
+
+QList<ModelNode> Model::allModelNodesUnordered()
+{
+ return toModelNodeList(d->allNodesUnordered(), this);
+}
+
+ModelNode Model::rootModelNode()
+{
+ return ModelNode{d->rootNode(), this, nullptr};
+}
+
+ModelNode Model::modelNodeForId(const QString &id)
+{
+ return ModelNode(d->nodeForId(id), this, nullptr);
+}
+
+QHash<QStringView, ModelNode> Model::idModelNodeDict()
+{
+ QHash<QStringView, ModelNode> idModelNodes;
+
+ for (const auto &[key, internalNode] : d->m_idNodeHash.asKeyValueRange())
+ idModelNodes.insert(key, ModelNode(internalNode, this, nullptr));
+
+ return idModelNodes;
+}
+
+namespace {
+ModelNode createNode(Model *model,
+ Internal::ModelPrivate *d,
+ const TypeName &typeName,
+ int majorVersion,
+ int minorVersion)
+{
+ return ModelNode(d->createNode(typeName, majorVersion, minorVersion, {}, {}, {}, {}, {}),
+ model,
+ nullptr);
+}
+} // namespace
+
+ModelNode Model::createModelNode(const TypeName &typeName)
+{
+ if constexpr (useProjectStorage()) {
+ return createNode(this, d.get(), typeName, -1, -1);
+ } else {
+ const NodeMetaInfo m = metaInfo(typeName);
+ return createNode(this, d.get(), typeName, m.majorVersion(), m.minorVersion());
+ }
+}
+
+void Model::removeModelNodes(ModelNodes nodes, BypassModelResourceManagement bypass)
+{
+ nodes.erase(std::remove_if(nodes.begin(), nodes.end(), [](auto &&node) { return !node; }),
+ nodes.end());
+
+ if (nodes.empty())
+ return;
+
+ std::sort(nodes.begin(), nodes.end());
+
+ ModelResourceSet set;
+
+ if (d->m_resourceManagement && bypass == BypassModelResourceManagement::No)
+ set = d->m_resourceManagement->removeNodes(std::move(nodes), this);
+ else
+ set = {std::move(nodes), {}, {}};
+
+ d->handleResourceSet(set);
+}
+
+void Model::removeProperties(AbstractProperties properties, BypassModelResourceManagement bypass)
{
- return QmlDesigner::toModelNodeList(d->allNodes(), nullptr);
+ properties.erase(std::remove_if(properties.begin(),
+ properties.end(),
+ [](auto &&property) { return !property; }),
+ properties.end());
+
+ if (properties.empty())
+ return;
+
+ std::sort(properties.begin(), properties.end());
+
+ ModelResourceSet set;
+
+ if (d->m_resourceManagement && bypass == BypassModelResourceManagement::No)
+ set = d->m_resourceManagement->removeProperties(std::move(properties), this);
+ else
+ set = {{}, std::move(properties), {}};
+
+ d->handleResourceSet(set);
}
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/model/model_p.h b/src/plugins/qmldesigner/designercore/model/model_p.h
index b802d703f2..5c69e75616 100644
--- a/src/plugins/qmldesigner/designercore/model/model_p.h
+++ b/src/plugins/qmldesigner/designercore/model/model_p.h
@@ -10,6 +10,8 @@
#include "modelnode.h"
#include "skipiterator.h"
+#include <nodemetainfo.h>
+
#include <QList>
#include <QPointer>
#include <QSet>
@@ -42,13 +44,13 @@ class InternalNodeAbstractProperty;
class InternalNodeListProperty;
using InternalNodePointer = std::shared_ptr<InternalNode>;
-using InternalPropertyPointer = QSharedPointer<InternalProperty>;
-using InternalBindingPropertyPointer = QSharedPointer<InternalBindingProperty>;
-using InternalSignalHandlerPropertyPointer = QSharedPointer<InternalSignalHandlerProperty>;
-using InternalSignalDeclarationPropertyPointer = QSharedPointer<InternalSignalDeclarationProperty>;
-using InternalVariantPropertyPointer = QSharedPointer<InternalVariantProperty>;
-using InternalNodeAbstractPropertyPointer = QSharedPointer<InternalNodeAbstractProperty>;
-using InternalNodeListPropertyPointer = QSharedPointer<InternalNodeListProperty>;
+using InternalPropertyPointer = std::shared_ptr<InternalProperty>;
+using InternalBindingPropertyPointer = std::shared_ptr<InternalBindingProperty>;
+using InternalSignalHandlerPropertyPointer = std::shared_ptr<InternalSignalHandlerProperty>;
+using InternalSignalDeclarationPropertyPointer = std::shared_ptr<InternalSignalDeclarationProperty>;
+using InternalVariantPropertyPointer = std::shared_ptr<InternalVariantProperty>;
+using InternalNodeAbstractPropertyPointer = std::shared_ptr<InternalNodeAbstractProperty>;
+using InternalNodeListPropertyPointer = std::shared_ptr<InternalNodeListProperty>;
using PropertyPair = QPair<InternalNodePointer, PropertyName>;
class ModelPrivate;
@@ -93,7 +95,6 @@ class ModelPrivate : public QObject
friend Model;
friend Internal::WriteLocker;
- friend NodeMetaInfoPrivate;
public:
ModelPrivate(Model *model,
@@ -244,8 +245,12 @@ public:
void setPropertyValue(const InternalNodePointer &node,const PropertyName &name, const QVariant &value);
void removePropertyAndRelatedResources(const InternalPropertyPointer &property);
void removeProperty(const InternalPropertyPointer &property);
+ void removeProperties(const QList<InternalPropertyPointer> &properties);
- void setBindingProperty(const InternalNodePointer &node, const PropertyName &name, const QString &expression);
+ void setBindingProperty(const InternalNodePointer &node,
+ const PropertyName &name,
+ const QString &expression);
+ void setBindingProperties(const ModelResourceSet::SetExpressions &setExpressions);
void setSignalHandlerProperty(const InternalNodePointer &node, const PropertyName &name, const QString &source);
void setSignalDeclarationProperty(const InternalNodePointer &node, const PropertyName &name, const QString &signature);
void setVariantProperty(const InternalNodePointer &node, const PropertyName &name, const QVariant &value);
@@ -266,7 +271,8 @@ public:
InternalNodePointer nodeForInternalId(qint32 internalId) const;
bool hasNodeForInternalId(qint32 internalId) const;
- QList<InternalNodePointer> allNodes() const;
+ QList<InternalNodePointer> allNodesUnordered() const;
+ QList<InternalNodePointer> allNodesOrdered() const;
bool isWriteLocked() const;
@@ -281,6 +287,13 @@ public:
InternalNodePointer currentStateNode() const;
InternalNodePointer currentTimelineNode() const;
+ void handleResourceSet(const ModelResourceSet &resourceSet);
+
+ QHash<TypeName, std::shared_ptr<NodeMetaInfoPrivate>> &nodeMetaInfoCache()
+ {
+ return m_nodeMetaInfoCache;
+ }
+
private:
void removePropertyWithoutNotification(const InternalPropertyPointer &property);
void removeAllSubNodes(const InternalNodePointer &node);
@@ -289,8 +302,10 @@ 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;
+ static QList<InternalPropertyPointer> toInternalProperties(const AbstractProperties &properties);
+ static QList<std::tuple<InternalBindingPropertyPointer, QString>> toInternalBindingProperties(
+ const ModelResourceSet::SetExpressions &setExpressions);
EnabledViewRange enabledViews() const;
- void handleResourceSet(const ModelResourceSet &resourceSet);
public:
NotNullPointer<ProjectStorageType> projectStorage = nullptr;
@@ -305,7 +320,7 @@ private:
QList<InternalNodePointer> m_selectedInternalNodeList;
QHash<QString,InternalNodePointer> m_idNodeHash;
QHash<qint32, InternalNodePointer> m_internalIdNodeHash;
- QSet<InternalNodePointer> m_nodeSet;
+ QList<InternalNodePointer> m_nodes;
InternalNodePointer m_currentStateNode;
InternalNodePointer m_rootInternalNode;
InternalNodePointer m_currentTimelineNode;
@@ -313,9 +328,8 @@ private:
QUrl m_fileUrl;
QPointer<RewriterView> m_rewriterView;
QPointer<NodeInstanceView> m_nodeInstanceView;
- QPointer<TextModifier> m_textModifier;
QPointer<Model> m_metaInfoProxyModel;
- QHash<TypeName, QSharedPointer<NodeMetaInfoPrivate>> m_nodeMetaInfoCache;
+ QHash<TypeName, std::shared_ptr<NodeMetaInfoPrivate>> m_nodeMetaInfoCache;
bool m_writeLock = false;
qint32 m_internalIdCounter = 1;
};
diff --git a/src/plugins/qmldesigner/designercore/model/modelnode.cpp b/src/plugins/qmldesigner/designercore/model/modelnode.cpp
index 7e64f4c4bf..45c076022d 100644
--- a/src/plugins/qmldesigner/designercore/model/modelnode.cpp
+++ b/src/plugins/qmldesigner/designercore/model/modelnode.cpp
@@ -3,15 +3,15 @@
#include "modelnode.h"
+#include "annotation.h"
+#include "bindingproperty.h"
#include "internalnode_p.h"
#include "model_p.h"
-#include "variantproperty.h"
-#include "bindingproperty.h"
-#include "signalhandlerproperty.h"
#include "nodeabstractproperty.h"
#include "nodelistproperty.h"
#include "nodeproperty.h"
-#include "annotation.h"
+#include "signalhandlerproperty.h"
+#include "variantproperty.h"
#include <auxiliarydataproperties.h>
#include <model.h>
@@ -51,33 +51,20 @@ childNode.addProperty("pos", QPoint(2, 12));
All the manipulation functions are generating undo commands internally.
*/
-
-
/*! \brief internal constructor
*/
-ModelNode::ModelNode(const InternalNodePointer &internalNode, Model *model, const AbstractView *view):
- m_internalNode(internalNode),
- m_model(model),
- m_view(const_cast<AbstractView*>(view))
-{
-}
+ModelNode::ModelNode(const InternalNodePointer &internalNode, Model *model, const AbstractView *view)
+ : m_internalNode(internalNode)
+ , m_model(model)
+ , m_view(const_cast<AbstractView *>(view))
+{}
ModelNode::ModelNode(const ModelNode &modelNode, AbstractView *view)
- : m_internalNode(modelNode.m_internalNode),
- m_model(modelNode.model()),
- m_view(view)
-{
-}
-
-/*! \brief contructs a invalid model node
-\return invalid node
-\see invalid
-*/
-ModelNode::ModelNode():
- m_internalNode(new InternalNode)
-{
-}
+ : m_internalNode(modelNode.m_internalNode)
+ , m_model(modelNode.model())
+ , m_view(view)
+{}
/*! \brief does nothing
*/
@@ -102,7 +89,7 @@ QString ModelNode::validId()
return id();
}
-static bool idIsQmlKeyWord(const QString& id)
+static bool idIsQmlKeyWord(const QString &id)
{
static const QSet<QString> keywords = {"as", "break", "case", "catch",
"continue", "debugger", "default", "delete",
@@ -116,49 +103,22 @@ static bool idIsQmlKeyWord(const QString& id)
return keywords.contains(id);
}
-static bool isIdToAvoid(const QString& id)
-{
- static const QSet<QString> ids = {
- "top",
- "bottom",
- "left",
- "right",
- "width",
- "height",
- "x",
- "y",
- "opacity",
- "parent",
- "item",
- "flow",
- "color",
- "margin",
- "padding",
- "border",
- "font",
- "text",
- "source",
- "state",
- "visible",
- "focus",
- "data",
- "clip",
- "layer",
- "scale",
- "enabled",
- "anchors",
- "texture",
- "shaderInfo",
- "sprite",
- "spriteSequence",
- "baseState",
- "rect"
- };
+static bool isIdToAvoid(const QString &id)
+{
+ static const QSet<QString> ids = {"top", "bottom", "left", "right",
+ "width", "height", "x", "y",
+ "opacity", "parent", "item", "flow",
+ "color", "margin", "padding", "border",
+ "font", "text", "source", "state",
+ "visible", "focus", "data", "clip",
+ "layer", "scale", "enabled", "anchors",
+ "texture", "shaderInfo", "sprite", "spriteSequence",
+ "baseState", "rect"};
return ids.contains(id);
}
-static bool idContainsWrongLetter(const QString& id)
+static bool idContainsWrongLetter(const QString &id)
{
static QRegularExpression idExpr(QStringLiteral("^[a-z_][a-zA-Z0-9_]*$"));
return !id.contains(idExpr);
@@ -200,7 +160,7 @@ bool ModelNode::hasId() const
return !m_internalNode->id.isEmpty();
}
-void ModelNode::setIdWithRefactoring(const QString& id)
+void ModelNode::setIdWithRefactoring(const QString &id)
{
if (isValid()) {
if (model()->rewriterView() && !id.isEmpty()
@@ -323,13 +283,15 @@ NodeAbstractProperty ModelNode::parentProperty() const
if (!isValid())
return {};
- if (m_internalNode->parentProperty().isNull())
+ if (!m_internalNode->parentProperty())
return {};
- return NodeAbstractProperty(m_internalNode->parentProperty()->name(), m_internalNode->parentProperty()->propertyOwner(), m_model.data(), view());
+ return NodeAbstractProperty(m_internalNode->parentProperty()->name(),
+ m_internalNode->parentProperty()->propertyOwner(),
+ m_model.data(),
+ view());
}
-
/*! \brief the command id is used to compress the some commands together.
\param newParentNode parent of this node will be set to this node
\param commandId integer which is used to descripe commands which should compressed together to one command
@@ -387,7 +349,7 @@ bool ModelNode::hasParentProperty() const
if (!isValid())
return false;
- if (m_internalNode->parentProperty().isNull())
+ if (!m_internalNode->parentProperty())
return false;
return true;
@@ -543,7 +505,6 @@ QList<AbstractProperty> ModelNode::properties() const
return propertyList;
}
-
/*! \brief returns a list of all VariantProperties
\return list of all VariantProperties
@@ -594,7 +555,6 @@ QList<NodeListProperty> ModelNode::nodeListProperties() const
return propertyList;
}
-
/*! \brief returns a list of all BindingProperties
\return list of all BindingProperties
@@ -694,35 +654,13 @@ void ModelNode::destroy()
removeModelNodeFromSelection(*this);
model()->d->removeNodeAndRelatedResources(m_internalNode);
}
+
//\}
/*! \name Property Manipulation
* This functions interact with properties.
*/
-
-/*!
- \brief Returns if the two nodes reference the same entity in the same model
- */
-bool operator ==(const ModelNode &firstNode, const ModelNode &secondNode)
-{
- return firstNode.internalId() == secondNode.internalId();
-}
-
-/*!
- \brief Returns if the two nodes do not reference the same entity in the same model
- */
-bool operator !=(const ModelNode &firstNode, const ModelNode &secondNode)
-{
- return firstNode.internalId() != secondNode.internalId();
-}
-
-bool operator <(const ModelNode &firstNode, const ModelNode &secondNode)
-{
- return firstNode.internalId() < secondNode.internalId();
-}
-
-
Internal::InternalNodePointer ModelNode::internalNode() const
{
return m_internalNode;
@@ -747,7 +685,6 @@ AbstractView *ModelNode::view() const
return m_view.data();
}
-
/*!
\brief returns all ModelNodes that are direct children of this ModelNode
The list contains every ModelNode that belongs to one of this ModelNodes
@@ -759,7 +696,7 @@ QList<ModelNode> ModelNode::directSubModelNodes() const
if (!isValid())
return {};
- return toModelNodeList(m_internalNode->allDirectSubNodes(), view());
+ return toModelNodeList(m_internalNode->allDirectSubNodes(), model(), view());
}
QList<ModelNode> ModelNode::directSubModelNodesOfType(const NodeMetaInfo &type) const
@@ -788,7 +725,7 @@ QList<ModelNode> ModelNode::allSubModelNodes() const
if (!isValid())
return {};
- return toModelNodeList(internalNode()->allSubNodes(), view());
+ return toModelNodeList(internalNode()->allSubNodes(), model(), view());
}
QList<ModelNode> ModelNode::allSubModelNodesAndThisNode() const
@@ -937,7 +874,7 @@ static bool recursiveAncestor(const ModelNode &possibleAncestor, const ModelNode
if (node.hasParentProperty()) {
if (node.parentProperty().parentModelNode() == possibleAncestor)
- return true;
+ return true;
return recursiveAncestor(possibleAncestor, node.parentProperty().parentModelNode());
}
@@ -952,10 +889,8 @@ bool ModelNode::isAncestorOf(const ModelNode &node) const
QDebug operator<<(QDebug debug, const ModelNode &modelNode)
{
if (modelNode.isValid()) {
- debug.nospace() << "ModelNode("
- << modelNode.internalId() << ", "
- << modelNode.type() << ", "
- << modelNode.id() << ')';
+ debug.nospace() << "ModelNode(" << modelNode.internalId() << ", " << modelNode.type()
+ << ", " << modelNode.id() << ')';
} else {
debug.nospace() << "ModelNode(invalid)";
}
@@ -963,12 +898,12 @@ QDebug operator<<(QDebug debug, const ModelNode &modelNode)
return debug.space();
}
-QTextStream& operator<<(QTextStream &stream, const ModelNode &modelNode)
+QTextStream &operator<<(QTextStream &stream, const ModelNode &modelNode)
{
if (modelNode.isValid()) {
stream << "ModelNode("
- << "type: " << modelNode.type() << ", "
- << "id: " << modelNode.id() << ')';
+ << "type: " << modelNode.type() << ", "
+ << "id: " << modelNode.id() << ')';
} else {
stream << "ModelNode(invalid)";
}
@@ -998,7 +933,7 @@ void ModelNode::deselectNode()
view()->setSelectedModelNodes(selectedNodeList);
}
-int ModelNode::variantUserType()
+int ModelNode::variantTypeId()
{
return qMetaTypeId<ModelNode>();
}
@@ -1016,8 +951,7 @@ std::optional<QVariant> ModelNode::auxiliaryData(AuxiliaryDataKeyView key) const
return m_internalNode->auxiliaryData(key);
}
-std::optional<QVariant> ModelNode::auxiliaryData(AuxiliaryDataType type,
- Utils::SmallStringView name) const
+std::optional<QVariant> ModelNode::auxiliaryData(AuxiliaryDataType type, Utils::SmallStringView name) const
{
return auxiliaryData({type, name});
}
@@ -1330,7 +1264,7 @@ static ModelNode lowestCommonAncestor(const ModelNode &node1,
{
Q_ASSERT(node1.isValid() && node2.isValid());
- auto depthOfNode = [] (const ModelNode &node) -> int {
+ auto depthOfNode = [](const ModelNode &node) -> int {
int depth = 0;
ModelNode parentNode = node;
while (!parentNode.isRootNode()) {
@@ -1341,9 +1275,8 @@ static ModelNode lowestCommonAncestor(const ModelNode &node1,
};
if (node1 == node2) {
- depthOfLCA = (depthOfNode1 < 0)
- ? ((depthOfNode2 < 0) ? depthOfNode(node1) : depthOfNode2)
- : depthOfNode1;
+ depthOfLCA = (depthOfNode1 < 0) ? ((depthOfNode2 < 0) ? depthOfNode(node1) : depthOfNode2)
+ : depthOfNode1;
return node1;
}
@@ -1360,7 +1293,7 @@ static ModelNode lowestCommonAncestor(const ModelNode &node1,
ModelNode nodeLower = node1;
ModelNode nodeHigher = node2;
int depthLower = (depthOfNode1 < 0) ? depthOfNode(nodeLower) : depthOfNode1;
- int depthHigher = (depthOfNode2 < 0) ? depthOfNode(nodeHigher) :depthOfNode2;
+ int depthHigher = (depthOfNode2 < 0) ? depthOfNode(nodeHigher) : depthOfNode2;
if (depthLower > depthHigher) {
std::swap(depthLower, depthHigher);
@@ -1407,9 +1340,8 @@ QList<ModelNode> ModelNode::pruneChildren(const QList<ModelNode> &nodes)
QList<ModelNode> forwardNodes;
QList<ModelNode> backNodes;
- auto pushIfIsNotChild = [] (QList<ModelNode> &container, const ModelNode &node) {
- bool hasAncestor = Utils::anyOf(container,
- [node] (const ModelNode &testNode) -> bool {
+ auto pushIfIsNotChild = [](QList<ModelNode> &container, const ModelNode &node) {
+ bool hasAncestor = Utils::anyOf(container, [node](const ModelNode &testNode) -> bool {
return testNode.isAncestorOf(node);
});
if (!hasAncestor)
@@ -1427,13 +1359,19 @@ QList<ModelNode> ModelNode::pruneChildren(const QList<ModelNode> &nodes)
return backNodes;
}
-void ModelNode::setScriptFunctions(const QStringList &scriptFunctionList)
+void ModelNode::setScriptFunctions(const QStringList &scriptFunctionList)
{
+ if (!isValid())
+ return;
+
model()->d->setScriptFunctions(m_internalNode, scriptFunctionList);
}
-QStringList ModelNode::scriptFunctions() const
+QStringList ModelNode::scriptFunctions() const
{
+ if (!isValid())
+ return {};
+
return m_internalNode->scriptFunctions;
}
@@ -1528,8 +1466,7 @@ bool ModelNode::isComponent() const
if (metaInfo().isQtQuickLoader()) {
if (hasNodeListProperty("component")) {
-
- /*
+ /*
* The component property should be a NodeProperty, but currently is a NodeListProperty, because
* the default property is always implcitly a NodeListProperty. This is something that has to be fixed.
*/
@@ -1542,7 +1479,8 @@ bool ModelNode::isComponent() const
}
if (hasNodeProperty("sourceComponent")) {
- if (nodeProperty("sourceComponent").modelNode().nodeSourceType() == ModelNode::NodeWithComponentSource)
+ if (nodeProperty("sourceComponent").modelNode().nodeSourceType()
+ == ModelNode::NodeWithComponentSource)
return true;
if (nodeProperty("sourceComponent").modelNode().metaInfo().isFileComponent())
return true;
@@ -1560,8 +1498,9 @@ QIcon ModelNode::typeIcon() const
if (isValid()) {
// if node has no own icon, search for it in the itemlibrary
const ItemLibraryInfo *libraryInfo = model()->metaInfo().itemLibraryInfo();
- QList <ItemLibraryEntry> itemLibraryEntryList = libraryInfo->entriesForType(
- type(), majorVersion(), minorVersion());
+ QList<ItemLibraryEntry> itemLibraryEntryList = libraryInfo->entriesForType(type(),
+ majorVersion(),
+ minorVersion());
if (!itemLibraryEntryList.isEmpty())
return itemLibraryEntryList.constFirst().typeIcon();
else if (metaInfo().isValid())
@@ -1579,4 +1518,4 @@ QString ModelNode::behaviorPropertyName() const
return m_internalNode->behaviorPropertyName;
}
-}
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/model/modelresourcemanagement.cpp b/src/plugins/qmldesigner/designercore/model/modelresourcemanagement.cpp
new file mode 100644
index 0000000000..a61f1001f9
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/model/modelresourcemanagement.cpp
@@ -0,0 +1,796 @@
+// 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 "modelresourcemanagement.h"
+
+#include <abstractview.h>
+#include <bindingproperty.h>
+#include <nodelistproperty.h>
+#include <nodemetainfo.h>
+#include <variantproperty.h>
+
+#include <utils/algorithm.h>
+#include <utils/set_algorithm.h>
+
+#include <QHash>
+#include <QRegularExpression>
+
+#include <functional>
+
+namespace QmlDesigner {
+
+namespace {
+
+enum class CheckRecursive { No, Yes };
+
+class NodeActions;
+
+template<typename ActionCall>
+void forEachAction(NodeActions &nodeActions, ActionCall actionCall);
+
+struct Base
+{
+ Base(ModelResourceSet &resourceSet, NodeActions &nodeActions)
+ : resourceSet{resourceSet}
+ , nodeActions{nodeActions}
+ {}
+
+ void removeNodes(ModelNodes newModelNodes, CheckRecursive checkRecursive)
+ {
+ if (newModelNodes.empty())
+ return;
+
+ auto oldModelNodes = removeNodes(newModelNodes);
+
+ if (checkRecursive == CheckRecursive::Yes)
+ checkNewModelNodes(newModelNodes, oldModelNodes);
+ }
+
+ void checkModelNodes(ModelNodes newModelNodes)
+ {
+ if (newModelNodes.empty())
+ return;
+
+ std::sort(newModelNodes.begin(), newModelNodes.end());
+
+ checkNewModelNodes(newModelNodes, resourceSet.removeModelNodes);
+ }
+
+ void removeProperties(AbstractProperties newProperties, CheckRecursive checkRecursive)
+ {
+ if (newProperties.empty())
+ return;
+
+ auto oldProperties = removeProperties(newProperties);
+
+ if (checkRecursive == CheckRecursive::Yes)
+ checkNewProperties(newProperties, oldProperties);
+ }
+
+ void addSetExpressions(ModelResourceSet::SetExpressions newSetExpressions)
+ {
+ auto &setExpressions = resourceSet.setExpressions;
+ setExpressions.append(std::move(newSetExpressions));
+ }
+
+ void handleNodes(const ModelNodes &) {}
+
+ void handleProperties(const AbstractProperties &) {}
+
+ void finally() {}
+
+private:
+ ModelNodes removeNodes(ModelNodes &newModelNodes)
+ {
+ std::sort(newModelNodes.begin(), newModelNodes.end());
+
+ newModelNodes.erase(std::unique(newModelNodes.begin(), newModelNodes.end()),
+ newModelNodes.end());
+
+ auto oldModelNodes = std::move(resourceSet.removeModelNodes);
+ resourceSet.removeModelNodes = {};
+ resourceSet.removeModelNodes.reserve(oldModelNodes.size() + newModelNodes.size());
+
+ std::set_union(newModelNodes.begin(),
+ newModelNodes.end(),
+ oldModelNodes.begin(),
+ oldModelNodes.end(),
+ std::back_inserter(resourceSet.removeModelNodes));
+
+ return oldModelNodes;
+ }
+
+ AbstractProperties removeProperties(AbstractProperties &newProperties)
+ {
+ std::sort(newProperties.begin(), newProperties.end());
+
+ newProperties.erase(std::unique(newProperties.begin(), newProperties.end()),
+ newProperties.end());
+
+ auto oldProperties = std::move(resourceSet.removeProperties);
+ resourceSet.removeProperties = {};
+ resourceSet.removeProperties.reserve(oldProperties.size() + newProperties.size());
+
+ std::set_union(newProperties.begin(),
+ newProperties.end(),
+ oldProperties.begin(),
+ oldProperties.end(),
+ std::back_inserter(resourceSet.removeProperties));
+
+ return oldProperties;
+ }
+
+ void checkNewModelNodes(const ModelNodes &newModelNodes, const ModelNodes &oldModelNodes)
+ {
+ ModelNodes addedModelNodes;
+ addedModelNodes.reserve(newModelNodes.size());
+
+ std::set_difference(newModelNodes.begin(),
+ newModelNodes.end(),
+ oldModelNodes.begin(),
+ oldModelNodes.end(),
+ std::back_inserter(addedModelNodes));
+
+ if (addedModelNodes.size())
+ forEachAction(nodeActions, [&](auto &action) { action.handleNodes(addedModelNodes); });
+ }
+
+ void checkNewProperties(const AbstractProperties &newProperties,
+ const AbstractProperties &oldProperties)
+ {
+ AbstractProperties addedProperties;
+ addedProperties.reserve(newProperties.size());
+
+ std::set_difference(newProperties.begin(),
+ newProperties.end(),
+ oldProperties.begin(),
+ oldProperties.end(),
+ std::back_inserter(addedProperties));
+
+ if (addedProperties.size())
+ forEachAction(nodeActions,
+ [&](auto &action) { action.handleProperties(addedProperties); });
+ }
+
+private:
+ ModelResourceSet &resourceSet;
+ NodeActions &nodeActions;
+};
+
+struct CheckChildNodes : public Base
+{
+ using Base::Base;
+
+ void handleNodes(const ModelNodes &nodes)
+ {
+ ModelNodes childNodes;
+ for (const ModelNode &node : nodes)
+ childNodes.append(node.directSubModelNodes());
+
+ checkModelNodes(childNodes);
+ }
+};
+
+struct CheckNodesInNodeAbstractProperties : public Base
+{
+ using Base::Base;
+
+ ModelNodes collectNodes(const AbstractProperties &properties)
+ {
+ ModelNodes modelNodes;
+
+ for (const AbstractProperty &property : properties) {
+ if (property.isNodeAbstractProperty())
+ modelNodes.append(property.toNodeAbstractProperty().directSubNodes());
+ }
+
+ return modelNodes;
+ }
+
+ void handleProperties(const AbstractProperties &properties)
+ {
+ checkModelNodes(collectNodes(properties));
+ }
+};
+
+struct RemoveLayerEnabled : public Base
+{
+ using Base::Base;
+
+ AbstractProperties collectProperties(const ModelNodes &nodes)
+ {
+ AbstractProperties properties;
+
+ for (const ModelNode &node : nodes) {
+ if (node.parentProperty().name() == "layer.effect") {
+ auto layerEnabledProperty = node.parentProperty().parentModelNode().property(
+ "layer.enabled");
+ if (layerEnabledProperty.exists())
+ properties.push_back(layerEnabledProperty);
+ }
+ }
+
+ return properties;
+ }
+
+ void handleNodes(const ModelNodes &nodes)
+ {
+ removeProperties(collectProperties(nodes), CheckRecursive::No);
+ }
+};
+
+struct NodeDependency
+{
+ ModelNode target;
+ ModelNode source;
+
+ friend bool operator<(const NodeDependency &first, const NodeDependency &second)
+ {
+ return std::tie(first.target, first.source) < std::tie(second.target, second.source);
+ }
+
+ friend bool operator<(const NodeDependency &first, const ModelNode &second)
+ {
+ return first.target < second;
+ }
+
+ friend bool operator<(const ModelNode &first, const NodeDependency &second)
+ {
+ return first < second.target;
+ }
+};
+
+using NodeDependencies = std::vector<NodeDependency>;
+
+struct BindingDependency
+{
+ ModelNode target;
+ BindingProperty property;
+
+ friend bool operator<(const BindingDependency &first, const BindingDependency &second)
+ {
+ return std::tie(first.target, first.property) < std::tie(second.target, second.property);
+ }
+
+ friend bool operator<(const BindingDependency &first, const ModelNode &second)
+ {
+ return first.target < second;
+ }
+
+ friend bool operator<(const ModelNode &first, const BindingDependency &second)
+ {
+ return first < second.target;
+ }
+};
+
+using BindingDependencies = std::vector<BindingDependency>;
+
+struct NameNode
+{
+ QString name;
+ ModelNode node;
+
+ friend bool operator<(const NameNode &first, const NameNode &second)
+ {
+ return first.name < second.name;
+ }
+};
+
+using NameNodes = std::vector<NameNode>;
+
+struct NodesProperty
+{
+ ModelNode source;
+ PropertyName name;
+ ModelNodes targets;
+ bool isChanged = false;
+
+ friend bool operator<(const NodesProperty &first, const NodesProperty &second)
+ {
+ return first.source < second.source;
+ }
+};
+
+using NodesProperties = std::vector<NodesProperty>;
+
+struct RemoveDependentBindings : public Base
+{
+ RemoveDependentBindings(ModelResourceSet &resourceSet,
+ NodeActions &nodeActions,
+ BindingDependencies dependencies)
+ : Base{resourceSet, nodeActions}
+ , dependencies{std::move(dependencies)}
+ {}
+
+ AbstractProperties collectProperties(const ModelNodes &nodes)
+ {
+ AbstractProperties properties;
+ ::Utils::set_greedy_intersection(dependencies.begin(),
+ dependencies.end(),
+ nodes.begin(),
+ nodes.end(),
+ ::Utils::make_iterator([&](const BindingDependency &dependency) {
+ properties.push_back(dependency.property);
+ }));
+
+ return properties;
+ }
+
+ void handleNodes(const ModelNodes &nodes)
+ {
+ removeProperties(collectProperties(nodes), CheckRecursive::No);
+ }
+
+ BindingDependencies dependencies;
+};
+
+struct RemoveDependencies : public Base
+{
+ RemoveDependencies(ModelResourceSet &resourceSet,
+ NodeActions &nodeActions,
+ NodeDependencies dependencies)
+ : Base{resourceSet, nodeActions}
+ , dependencies{std::move(dependencies)}
+ {}
+
+ ModelNodes collectNodes(const ModelNodes &nodes) const
+ {
+ ModelNodes targetNodes;
+ ::Utils::set_greedy_intersection(dependencies.begin(),
+ dependencies.end(),
+ nodes.begin(),
+ nodes.end(),
+ ::Utils::make_iterator([&](const NodeDependency &dependency) {
+ targetNodes.push_back(dependency.source);
+ }));
+
+ return targetNodes;
+ }
+
+ void handleNodes(const ModelNodes &nodes)
+ {
+ removeNodes(collectNodes(nodes), CheckRecursive::No);
+ }
+
+ NodeDependencies dependencies;
+};
+
+struct RemoveTargetsSources : public Base
+{
+ RemoveTargetsSources(ModelResourceSet &resourceSet,
+ NodeActions &nodeActions,
+ NodeDependencies dependencies,
+ NodesProperties nodesProperties)
+ : Base{resourceSet, nodeActions}
+ , dependencies{std::move(dependencies)}
+ , nodesProperties{std::move(nodesProperties)}
+ {}
+
+ static void removeDependency(NodesProperties &removedTargetNodesInProperties,
+ const NodeDependency &dependency)
+ {
+ auto found = std::find_if(removedTargetNodesInProperties.begin(),
+ removedTargetNodesInProperties.end(),
+ [&](const auto &nodeProperty) {
+ return nodeProperty.source == dependency.source;
+ });
+
+ if (found == removedTargetNodesInProperties.end())
+ removedTargetNodesInProperties.push_back({dependency.source, "", {dependency.target}});
+ else
+ found->targets.push_back(dependency.target);
+ }
+
+ NodesProperties collectRemovedDependencies(const ModelNodes &nodes)
+ {
+ NodesProperties removedTargetNodesInProperties;
+
+ ModelNodes targetNodes;
+ ::Utils::set_greedy_intersection(dependencies.begin(),
+ dependencies.end(),
+ nodes.begin(),
+ nodes.end(),
+ ::Utils::make_iterator([&](const NodeDependency &dependency) {
+ removeDependency(removedTargetNodesInProperties,
+ dependency);
+ }));
+
+ std::sort(removedTargetNodesInProperties.begin(), removedTargetNodesInProperties.end());
+
+ return removedTargetNodesInProperties;
+ }
+
+ ModelNodes collectNodesToBeRemoved(const ModelNodes &nodes)
+ {
+ ModelNodes nodesToBeRemoved;
+
+ auto removeTargets = [&](auto &first, auto &second) {
+ auto newEnd = std::remove_if(first.targets.begin(),
+ first.targets.end(),
+ [&](const ModelNode &node) {
+ return std::find(second.targets.begin(),
+ second.targets.end(),
+ node)
+ != second.targets.end();
+ });
+ if (newEnd != first.targets.end()) {
+ first.isChanged = true;
+ first.targets.erase(newEnd, first.targets.end());
+
+ if (first.targets.empty())
+ nodesToBeRemoved.push_back(first.source);
+ }
+ };
+
+ NodesProperties removedTargetNodesInProperties = collectRemovedDependencies(nodes);
+ ::Utils::set_intersection_compare(nodesProperties.begin(),
+ nodesProperties.end(),
+ removedTargetNodesInProperties.begin(),
+ removedTargetNodesInProperties.end(),
+ removeTargets,
+ std::less<NodesProperty>{});
+
+ return nodesToBeRemoved;
+ }
+
+ void handleNodes(const ModelNodes &nodes)
+ {
+ removeNodes(collectNodesToBeRemoved(nodes), CheckRecursive::No);
+ }
+
+ QString createExpression(const NodesProperty &nodesProperty)
+ {
+ QString expression = "[";
+ const ModelNode &last = nodesProperty.targets.back();
+ for (const ModelNode &node : nodesProperty.targets) {
+ expression += node.id();
+ if (node != last)
+ expression += ", ";
+ }
+ expression += "]";
+
+ return expression;
+ }
+
+ void finally()
+ {
+ ModelResourceSet::SetExpressions setExpressions;
+
+ for (const NodesProperty &nodesProperty : nodesProperties) {
+ if (nodesProperty.isChanged && nodesProperty.targets.size()) {
+ setExpressions.push_back({nodesProperty.source.bindingProperty(nodesProperty.name),
+ createExpression(nodesProperty)});
+ }
+ }
+
+ addSetExpressions(std::move(setExpressions));
+ }
+
+ NodeDependencies dependencies;
+ NodesProperties nodesProperties;
+};
+
+struct DependenciesSet
+{
+ NodeDependencies nodeDependencies;
+ NodeDependencies targetsDependencies;
+ NodesProperties targetsNodesProperties;
+ BindingDependencies bindingDependencies;
+};
+
+struct BindingFilter
+{
+ BindingFilter(BindingDependencies &dependencies, Model *model)
+ : dependencies{dependencies}
+ , idModelNodeDict{model->idModelNodeDict()}
+ , wordsRegex{"[[:<:]](\\w+)[[:>:]]"}
+ {}
+
+ void filterBindingProperty(const BindingProperty &property)
+ {
+ const QString &expression = property.expression();
+ auto iterator = wordsRegex.globalMatch(expression);
+
+ while (iterator.hasNext()) {
+ auto match = iterator.next();
+ auto word = match.capturedView();
+ if (auto modelNode = idModelNodeDict.value(word))
+ dependencies.push_back({modelNode, property});
+ }
+ }
+
+ void operator()(const NodeMetaInfo &, const ModelNode &node)
+ {
+ for (const BindingProperty &property : node.bindingProperties())
+ filterBindingProperty(property);
+ }
+
+ void finally() { std::sort(dependencies.begin(), dependencies.end()); }
+
+ BindingDependencies &dependencies;
+ QHash<QStringView, ModelNode> idModelNodeDict;
+ QRegularExpression wordsRegex;
+};
+
+struct TargetFilter
+{
+ TargetFilter(NodeDependencies &dependencies, Model *model)
+ : flowViewFlowActionAreaMetaInfo{model->flowViewFlowActionAreaMetaInfo()}
+ , flowViewFlowTransitionMetaInfo{model->flowViewFlowTransitionMetaInfo()}
+ , qtQuickPropertyChangesMetaInfo{model->qtQuickPropertyChangesMetaInfo()}
+ , qtQuickTimelineKeyframeGroupMetaInfo{model->qtQuickTimelineKeyframeGroupMetaInfo()}
+ , qtQuickPropertyAnimationMetaInfo{model->qtQuickPropertyAnimationMetaInfo()}
+ , dependencies{dependencies}
+ {}
+
+ static std::optional<ModelNode> resolveBinding(const ModelNode &node,
+ const PropertyName &propertyName)
+ {
+ auto property = node.bindingProperty(propertyName);
+ if (property.exists()) {
+ if (ModelNode targetNode = property.resolveToModelNode())
+ return targetNode;
+ }
+
+ return {};
+ }
+
+ bool hasTargetProperty(const NodeMetaInfo &metaInfo) const
+ {
+ return metaInfo.isBasedOn(qtQuickPropertyChangesMetaInfo,
+ qtQuickTimelineKeyframeGroupMetaInfo,
+ flowViewFlowActionAreaMetaInfo,
+ qtQuickPropertyAnimationMetaInfo);
+ }
+
+ bool hasToOrFromProperty(const NodeMetaInfo &metaInfo)
+ {
+ return metaInfo.isBasedOn(flowViewFlowTransitionMetaInfo);
+ }
+
+ void operator()(const NodeMetaInfo &metaInfo, const ModelNode &node)
+ {
+ if (hasTargetProperty(metaInfo)) {
+ if (auto targetNode = resolveBinding(node, "target"))
+ dependencies.push_back({std::move(*targetNode), node});
+ } else if (hasToOrFromProperty(metaInfo)) {
+ if (auto toNode = resolveBinding(node, "to"))
+ dependencies.push_back({std::move(*toNode), node});
+ if (auto fromNode = resolveBinding(node, "from"))
+ dependencies.push_back({std::move(*fromNode), node});
+ }
+ }
+
+ void finally() { std::sort(dependencies.begin(), dependencies.end()); }
+
+ NodeMetaInfo flowViewFlowActionAreaMetaInfo;
+ NodeMetaInfo flowViewFlowTransitionMetaInfo;
+ NodeMetaInfo qtQuickPropertyChangesMetaInfo;
+ NodeMetaInfo qtQuickTimelineKeyframeGroupMetaInfo;
+ NodeMetaInfo qtQuickPropertyAnimationMetaInfo;
+ NodeDependencies &dependencies;
+};
+
+template<typename Predicate>
+struct TargetsFilter
+{
+ TargetsFilter(Predicate predicate,
+ NodeDependencies &dependencies,
+ NodesProperties &targetsNodesProperties)
+ : predicate{std::move(predicate)}
+ , dependencies{dependencies}
+ , targetsNodesProperties{targetsNodesProperties}
+ {}
+
+ static ModelNodes resolveTargets(const ModelNode &node)
+ {
+ auto targetProperty = node.bindingProperty("targets");
+ if (targetProperty.exists())
+ return targetProperty.resolveToModelNodeList();
+
+ return {};
+ }
+
+ void operator()(const NodeMetaInfo &metaInfo, const ModelNode &node)
+ {
+ if (predicate(metaInfo)) {
+ const auto targetNodes = resolveTargets(node);
+ if (targetNodes.size()) {
+ targetsNodesProperties.push_back({node, "targets", targetNodes});
+ for (auto &&targetNode : targetNodes)
+ dependencies.push_back({targetNode, node});
+ }
+ }
+ }
+
+ void finally()
+ {
+ std::sort(dependencies.begin(), dependencies.end());
+ std::sort(targetsNodesProperties.begin(), targetsNodesProperties.end());
+ }
+
+ Predicate predicate;
+ NodeDependencies &dependencies;
+ NodesProperties &targetsNodesProperties;
+};
+
+void addDependency(NameNodes &dependencies, const ModelNode &node, const PropertyName &propertyName)
+{
+ if (auto property = node.variantProperty(propertyName); property.exists()) {
+ QString stateName = property.value().toString();
+ if (stateName.size() && stateName != "*")
+ dependencies.push_back({stateName, node});
+ }
+}
+
+struct StateFilter
+{
+ StateFilter(NameNodes &dependencies)
+ : dependencies{dependencies}
+ {}
+
+ void operator()(const NodeMetaInfo &metaInfo, const ModelNode &node)
+ {
+ if (metaInfo.isQtQuickState())
+ addDependency(dependencies, node, "name");
+ }
+
+ void finally() { std::sort(dependencies.begin(), dependencies.end()); }
+
+ NameNodes &dependencies;
+};
+
+struct TransitionFilter
+{
+ TransitionFilter(NodeDependencies &dependencies, NameNodes &stateNodes)
+ : stateNodes{stateNodes}
+ , dependencies{dependencies}
+ {}
+
+ void operator()(const NodeMetaInfo &metaInfo, const ModelNode &node)
+ {
+ if (metaInfo.isQtQuickTransition()) {
+ addDependency(transitionNodes, node, "to");
+ addDependency(transitionNodes, node, "from");
+ }
+ }
+
+ void finally()
+ {
+ std::sort(transitionNodes.begin(), transitionNodes.end());
+
+ auto removeTransition = [&](const auto &first, const auto &second) {
+ dependencies.push_back({second.node, first.node});
+ };
+
+ ::Utils::set_greedy_intersection_compare(transitionNodes.begin(),
+ transitionNodes.end(),
+ stateNodes.begin(),
+ stateNodes.end(),
+ removeTransition,
+ std::less<NameNode>{});
+ std::sort(dependencies.begin(), dependencies.end());
+ }
+
+ NameNodes transitionNodes;
+ NameNodes &stateNodes;
+ NodeDependencies &dependencies;
+};
+
+DependenciesSet createDependenciesSet(Model *model)
+{
+ const ModelNodes nodes = model->allModelNodesUnordered();
+
+ DependenciesSet set;
+ NameNodes stateNames;
+
+ auto flowViewFlowActionAreaMetaInfo = model->flowViewFlowActionAreaMetaInfo();
+ auto flowViewFlowDecisionMetaInfo = model->flowViewFlowDecisionMetaInfo();
+ auto flowViewFlowWildcardMetaInfo = model->flowViewFlowWildcardMetaInfo();
+ auto qtQuickPropertyChangesMetaInfo = model->qtQuickPropertyChangesMetaInfo();
+ auto qtQuickTimelineKeyframeGroupMetaInfo = model->qtQuickTimelineKeyframeGroupMetaInfo();
+ auto qtQuickPropertyAnimationMetaInfo = model->qtQuickPropertyAnimationMetaInfo();
+
+ auto filters = std::make_tuple(
+ TargetFilter{set.nodeDependencies, model},
+ TargetsFilter{[&](auto &&metaInfo) {
+ return metaInfo.isBasedOn(flowViewFlowDecisionMetaInfo,
+ flowViewFlowWildcardMetaInfo,
+ qtQuickPropertyAnimationMetaInfo);
+ },
+ set.targetsDependencies,
+ set.targetsNodesProperties},
+ StateFilter{stateNames},
+ TransitionFilter{set.nodeDependencies, stateNames},
+ BindingFilter{set.bindingDependencies, model});
+
+ for (const ModelNode &node : nodes) {
+ auto metaInfo = node.metaInfo();
+ std::apply([&](auto &&...filter) { (filter(metaInfo, node), ...); }, filters);
+ }
+
+ std::apply([&](auto &&...filter) { (filter.finally(), ...); }, filters);
+
+ return set;
+}
+
+using NodeActionsTuple = std::tuple<CheckChildNodes,
+ CheckNodesInNodeAbstractProperties,
+ RemoveLayerEnabled,
+ RemoveDependentBindings,
+ RemoveDependencies,
+ RemoveTargetsSources>;
+
+class NodeActions : public NodeActionsTuple
+{
+ NodeActions(const NodeActions &) = delete;
+ NodeActions &opertor(const NodeActions &) = delete;
+ NodeActions(NodeActions &&) = delete;
+ NodeActions &opertor(NodeActions &&) = delete;
+
+ using NodeActionsTuple::NodeActionsTuple;
+};
+
+template<typename ActionCall>
+void forEachAction(NodeActions &nodeActions, ActionCall actionCall)
+{
+ std::apply([&](auto &...action) { (actionCall(action), ...); },
+ static_cast<NodeActionsTuple &>(nodeActions));
+}
+
+} // namespace
+
+ModelResourceSet ModelResourceManagement::removeNodes(ModelNodes nodes, Model *model) const
+{
+ std::sort(nodes.begin(), nodes.end());
+
+ ModelResourceSet resourceSet;
+
+ DependenciesSet set = createDependenciesSet(model);
+
+ NodeActions nodeActions = {
+ CheckChildNodes{resourceSet, nodeActions},
+ CheckNodesInNodeAbstractProperties{resourceSet, nodeActions},
+ RemoveLayerEnabled{resourceSet, nodeActions},
+ RemoveDependentBindings{resourceSet, nodeActions, std::move(set.bindingDependencies)},
+ RemoveDependencies{resourceSet, nodeActions, std::move(set.nodeDependencies)},
+ RemoveTargetsSources{resourceSet,
+ nodeActions,
+ std::move(set.targetsDependencies),
+ std::move(set.targetsNodesProperties)}};
+
+ Base{resourceSet, nodeActions}.removeNodes(nodes, CheckRecursive::Yes);
+
+ forEachAction(nodeActions, [&](auto &action) { action.finally(); });
+
+ return resourceSet;
+}
+
+ModelResourceSet ModelResourceManagement::removeProperties(AbstractProperties properties,
+ Model *model) const
+{
+ std::sort(properties.begin(), properties.end());
+
+ ModelResourceSet resourceSet;
+
+ DependenciesSet set = createDependenciesSet(model);
+
+ NodeActions nodeActions = {
+ CheckChildNodes{resourceSet, nodeActions},
+ CheckNodesInNodeAbstractProperties{resourceSet, nodeActions},
+ RemoveLayerEnabled{resourceSet, nodeActions},
+ RemoveDependentBindings{resourceSet, nodeActions, std::move(set.bindingDependencies)},
+ RemoveDependencies{resourceSet, nodeActions, std::move(set.nodeDependencies)},
+ RemoveTargetsSources{resourceSet,
+ nodeActions,
+ std::move(set.targetsDependencies),
+ std::move(set.targetsNodesProperties)}};
+
+ Base{resourceSet, nodeActions}.removeProperties(properties, CheckRecursive::Yes);
+
+ forEachAction(nodeActions, [&](auto &action) { action.finally(); });
+
+ return resourceSet;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/model/modelresourcemanagement.h b/src/plugins/qmldesigner/designercore/model/modelresourcemanagement.h
new file mode 100644
index 0000000000..4d50504726
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/model/modelresourcemanagement.h
@@ -0,0 +1,20 @@
+// 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 "modelresourcemanagementinterface.h"
+
+#include <bindingproperty.h>
+#include <modelnode.h>
+
+namespace QmlDesigner {
+
+class ModelResourceManagement final : public ModelResourceManagementInterface
+{
+public:
+ ModelResourceSet removeNodes(ModelNodes nodes, Model *model) const override;
+ ModelResourceSet removeProperties(AbstractProperties properties, Model *model) const override;
+};
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/model/modelresourcemanagementfwd.h b/src/plugins/qmldesigner/designercore/model/modelresourcemanagementfwd.h
new file mode 100644
index 0000000000..4031fdd918
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/model/modelresourcemanagementfwd.h
@@ -0,0 +1,27 @@
+// 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 "../include/qmldesignercorelib_exports.h"
+
+#include <bindingproperty.h>
+
+namespace QmlDesigner {
+
+struct ModelResourceSet
+{
+ struct SetExpression
+ {
+ BindingProperty property;
+ QString expression;
+ };
+
+ using SetExpressions = QList<SetExpression>;
+
+ QList<ModelNode> removeModelNodes;
+ QList<AbstractProperty> removeProperties;
+ QList<SetExpression> setExpressions;
+};
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/model/modelresourcemanagementinterface.h b/src/plugins/qmldesigner/designercore/model/modelresourcemanagementinterface.h
index b2188132d6..94047d95b0 100644
--- a/src/plugins/qmldesigner/designercore/model/modelresourcemanagementinterface.h
+++ b/src/plugins/qmldesigner/designercore/model/modelresourcemanagementinterface.h
@@ -5,23 +5,13 @@
#include <qmldesignercorelib_exports.h>
+#include "modelresourcemanagementfwd.h"
+
#include <bindingproperty.h>
+#include <modelnode.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:
@@ -33,7 +23,7 @@ public:
ModelResourceManagementInterface(ModelResourceManagementInterface &&) = default;
ModelResourceManagementInterface &operator=(ModelResourceManagementInterface &&) = default;
- virtual ModelResourceSet removeNode(const ModelNode &node) const = 0;
- virtual ModelResourceSet removeProperty(const AbstractProperty &property) const = 0;
+ virtual ModelResourceSet removeNodes(ModelNodes nodes, Model *model) const = 0;
+ virtual ModelResourceSet removeProperties(AbstractProperties properties, Model *model) const = 0;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/model/modelutils.cpp b/src/plugins/qmldesigner/designercore/model/modelutils.cpp
index 2e454527b8..70da6f98b9 100644
--- a/src/plugins/qmldesigner/designercore/model/modelutils.cpp
+++ b/src/plugins/qmldesigner/designercore/model/modelutils.cpp
@@ -3,11 +3,13 @@
#include "modelutils.h"
+#include <nodemetainfo.h>
+
#include <utils/expected.h>
#include <algorithm>
-namespace QmlDesigner::Utils {
+namespace QmlDesigner::ModelUtils {
namespace {
@@ -90,4 +92,14 @@ bool addImportsWithCheck(const QStringList &importNames,
return true;
}
-} // namespace QmlDesigner::Utils
+PropertyMetaInfo metainfo(const AbstractProperty &property)
+{
+ return metainfo(property.parentModelNode(), property.name());
+}
+
+PropertyMetaInfo metainfo(const ModelNode &node, const PropertyName &propertyName)
+{
+ return node.metaInfo().property(propertyName);
+}
+
+} // namespace QmlDesigner::ModelUtils
diff --git a/src/plugins/qmldesigner/designercore/model/modelutils.h b/src/plugins/qmldesigner/designercore/model/modelutils.h
index 58055f3906..578a7adb44 100644
--- a/src/plugins/qmldesigner/designercore/model/modelutils.h
+++ b/src/plugins/qmldesigner/designercore/model/modelutils.h
@@ -10,7 +10,11 @@
#include <functional>
-namespace QmlDesigner::Utils {
+namespace QmlDesigner {
+class PropertyMetaInfo;
+}
+
+namespace QmlDesigner::ModelUtils {
QMLDESIGNERCORE_EXPORT bool addImportsWithCheck(const QStringList &importNames,
const std::function<bool(const Import &)> &predicate,
@@ -21,4 +25,8 @@ QMLDESIGNERCORE_EXPORT bool addImportWithCheck(const QString &importName,
Model *model);
QMLDESIGNERCORE_EXPORT bool addImportWithCheck(const QString &importName, Model *model);
-} // namespace QmlDesigner::Utils
+QMLDESIGNERCORE_EXPORT PropertyMetaInfo metainfo(const AbstractProperty &property);
+QMLDESIGNERCORE_EXPORT PropertyMetaInfo metainfo(const ModelNode &node,
+ const PropertyName &propertyName);
+
+} // namespace QmlDesigner::ModelUtils
diff --git a/src/plugins/qmldesigner/designercore/model/nodeabstractproperty.cpp b/src/plugins/qmldesigner/designercore/model/nodeabstractproperty.cpp
index 60b4e77dc6..0688ff1c25 100644
--- a/src/plugins/qmldesigner/designercore/model/nodeabstractproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/nodeabstractproperty.cpp
@@ -70,16 +70,16 @@ void NodeAbstractProperty::reparentHere(const ModelNode &modelNode, bool isNode
if (modelNode.hasParentProperty() && modelNode.parentProperty().isDynamic())
return;
- if (internalNode()->hasProperty(name()) && !internalNode()->property(name())->isNodeAbstractProperty())
- privateModel()->removePropertyAndRelatedResources(internalNode()->property(name()));
+ auto internalProperty = internalNode()->property(name());
+ if (internalProperty && !internalProperty->isNodeAbstractProperty())
+ privateModel()->removePropertyAndRelatedResources(internalProperty);
if (modelNode.hasParentProperty()) {
Internal::InternalNodeAbstractProperty::Pointer oldParentProperty = modelNode.internalNode()->parentProperty();
privateModel()->reparentNode(internalNode(), name(), modelNode.internalNode(), isNodeList, dynamicTypeName);
- Q_ASSERT(!oldParentProperty.isNull());
-
+ Q_ASSERT(oldParentProperty);
} else {
privateModel()->reparentNode(internalNode(), name(), modelNode.internalNode(), isNodeList, dynamicTypeName);
@@ -91,7 +91,7 @@ bool NodeAbstractProperty::isEmpty() const
if (isValid()) {
Internal::InternalNodeAbstractProperty::Pointer property = internalNode()->nodeAbstractProperty(
name());
- if (property.isNull())
+ if (!property)
return true;
else
return property->isEmpty();
@@ -105,7 +105,7 @@ int NodeAbstractProperty::indexOf(const ModelNode &node) const
if (isValid()) {
Internal::InternalNodeAbstractProperty::Pointer property = internalNode()->nodeAbstractProperty(
name());
- if (property.isNull())
+ if (!property)
return 0;
return property->indexOf(node.internalNode());
@@ -119,7 +119,7 @@ NodeAbstractProperty NodeAbstractProperty::parentProperty() const
if (!isValid())
return {};
- if (internalNode()->parentProperty().isNull())
+ if (!internalNode()->parentProperty())
return {};
return NodeAbstractProperty(internalNode()->parentProperty()->name(), internalNode()->parentProperty()->propertyOwner(), model(), view());
@@ -128,7 +128,7 @@ NodeAbstractProperty NodeAbstractProperty::parentProperty() const
int NodeAbstractProperty::count() const
{
Internal::InternalNodeAbstractProperty::Pointer property = internalNode()->nodeAbstractProperty(name());
- if (property.isNull())
+ if (!property)
return 0;
else
return property->count();
@@ -141,7 +141,7 @@ QList<ModelNode> NodeAbstractProperty::allSubNodes()
return {};
Internal::InternalNodeAbstractProperty::Pointer property = internalNode()->nodeAbstractProperty(name());
- return QmlDesigner::toModelNodeList(property->allSubNodes(), view());
+ return QmlDesigner::toModelNodeList(property->allSubNodes(), model(), view());
}
QList<ModelNode> NodeAbstractProperty::directSubNodes() const
@@ -151,7 +151,7 @@ QList<ModelNode> NodeAbstractProperty::directSubNodes() const
return {};
Internal::InternalNodeAbstractProperty::Pointer property = internalNode()->nodeAbstractProperty(name());
- return QmlDesigner::toModelNodeList(property->directSubNodes(), view());
+ return QmlDesigner::toModelNodeList(property->directSubNodes(), model(), view());
}
/*!
diff --git a/src/plugins/qmldesigner/designercore/model/nodelistproperty.cpp b/src/plugins/qmldesigner/designercore/model/nodelistproperty.cpp
index 5f36efc618..0822786467 100644
--- a/src/plugins/qmldesigner/designercore/model/nodelistproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/nodelistproperty.cpp
@@ -15,6 +15,9 @@ namespace QmlDesigner {
Internal::NodeListPropertyIterator::value_type Internal::NodeListPropertyIterator::operator*() const
{
+ if (!m_nodeListProperty)
+ return {};
+
return {m_nodeListProperty->at(m_currentIndex), m_model, m_view};
}
@@ -41,11 +44,9 @@ Internal::InternalNodeListPropertyPointer &NodeListProperty::internalNodeListPro
if (m_internalNodeListProperty)
return m_internalNodeListProperty;
- if (internalNode()->hasProperty(name())) {
- Internal::InternalProperty::Pointer internalProperty = internalNode()->property(name());
- if (internalProperty->isNodeListProperty())
- m_internalNodeListProperty = internalProperty->toNodeListProperty();
- }
+ auto internalProperty = internalNode()->nodeListProperty(name());
+ if (internalProperty)
+ m_internalNodeListProperty = internalProperty;
return m_internalNodeListProperty;
}
@@ -65,9 +66,7 @@ QList<ModelNode> NodeListProperty::toModelNodeList() const
return {};
if (internalNodeListProperty())
- return internalNodesToModelNodes(m_internalNodeListProperty->toNodeListProperty()->nodeList(),
- model(),
- view());
+ return internalNodesToModelNodes(m_internalNodeListProperty->nodeList(), model(), view());
return QList<ModelNode>();
}
@@ -162,7 +161,7 @@ NodeListProperty::iterator NodeListProperty::rotate(NodeListProperty::iterator f
privateModel()->notifyNodeOrderChanged(m_internalNodeListProperty);
- return {iter - begin, internalNodeListProperty().data(), model(), view()};
+ return {iter - begin, internalNodeListProperty().get(), model(), view()};
}
void NodeListProperty::reverse(NodeListProperty::iterator first, NodeListProperty::iterator last)
@@ -212,15 +211,21 @@ Internal::NodeListPropertyIterator NodeListProperty::end()
Internal::NodeListPropertyIterator NodeListProperty::begin() const
{
- return {0, internalNodeListProperty().data(), model(), view()};
+ if (!isValid())
+ return {};
+
+ return {0, internalNodeListProperty().get(), model(), view()};
}
Internal::NodeListPropertyIterator NodeListProperty::end() const
{
+ if (!isValid())
+ return {};
+
auto nodeListProperty = internalNodeListProperty();
auto size = nodeListProperty ? nodeListProperty->size() : 0;
- return {size, nodeListProperty.data(), model(), view()};
+ return {size, nodeListProperty.get(), model(), view()};
}
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/model/nodeproperty.cpp b/src/plugins/qmldesigner/designercore/model/nodeproperty.cpp
index 4af8428e6b..a628c96b7d 100644
--- a/src/plugins/qmldesigner/designercore/model/nodeproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/nodeproperty.cpp
@@ -24,11 +24,10 @@ void NodeProperty::setModelNode(const ModelNode &modelNode)
if (!modelNode.isValid())
return;
- if (internalNode()->hasProperty(name())) { //check if oldValue != value
- Internal::InternalProperty::Pointer internalProperty = internalNode()->property(name());
- if (internalProperty->isNodeProperty()
- && internalProperty->toNodeProperty()->node() == modelNode.internalNode())
- return;
+ auto internalProperty = internalNode()->nodeProperty(name());
+ if (internalProperty
+ && internalProperty->node() == modelNode.internalNode()) { //check if oldValue != value
+ return;
}
if (internalNode()->hasProperty(name()) && !internalNode()->property(name())->isNodeProperty())
@@ -42,11 +41,9 @@ ModelNode NodeProperty::modelNode() const
if (!isValid())
return {};
- if (internalNode()->hasProperty(name())) { //check if oldValue != value
- Internal::InternalProperty::Pointer internalProperty = internalNode()->property(name());
- if (internalProperty->isNodeProperty())
- return ModelNode(internalProperty->toNodeProperty()->node(), model(), view());
- }
+ auto internalProperty = internalNode()->nodeProperty(name());
+ if (internalProperty) //check if oldValue != value
+ return ModelNode(internalProperty->node(), model(), view());
return ModelNode();
}
diff --git a/src/plugins/qmldesigner/designercore/model/propertycontainer.cpp b/src/plugins/qmldesigner/designercore/model/propertycontainer.cpp
index 8cd55cac4b..cd7cebbb73 100644
--- a/src/plugins/qmldesigner/designercore/model/propertycontainer.cpp
+++ b/src/plugins/qmldesigner/designercore/model/propertycontainer.cpp
@@ -41,7 +41,7 @@ PropertyName PropertyContainer::name() const
QVariant PropertyContainer::value() const
{
- if (m_value.type() == QVariant::String)
+ if (m_value.typeId() == QVariant::String)
m_value = PropertyParser::read(m_type, m_value.toString());
return m_value;
}
diff --git a/src/plugins/qmldesigner/designercore/model/qml3dnode.cpp b/src/plugins/qmldesigner/designercore/model/qml3dnode.cpp
index e8d3aa1556..4db2567e36 100644
--- a/src/plugins/qmldesigner/designercore/model/qml3dnode.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qml3dnode.cpp
@@ -41,26 +41,15 @@ bool Qml3DNode::isValidVisualRoot(const ModelNode &modelNode)
&& (modelNode.metaInfo().isQtQuick3DNode() || modelNode.metaInfo().isQtQuick3DMaterial());
}
-void Qml3DNode::setVariantProperty(const PropertyName &name, const QVariant &value)
+bool Qml3DNode::handleEulerRotation(const PropertyName &name)
{
if (isBlocked(name))
- return;
+ return false;
if (name.startsWith("eulerRotation"))
handleEulerRotationSet();
- QmlObjectNode::setVariantProperty(name, value);
-}
-
-void Qml3DNode::setBindingProperty(const PropertyName &name, const QString &expression)
-{
- if (isBlocked(name))
- return;
-
- if (name.startsWith("eulerRotation"))
- handleEulerRotationSet();
-
- QmlObjectNode::setBindingProperty(name, expression);
+ return true;
}
bool Qml3DNode::isBlocked(const PropertyName &propName) const
diff --git a/src/plugins/qmldesigner/designercore/model/qmlchangeset.cpp b/src/plugins/qmldesigner/designercore/model/qmlchangeset.cpp
index 134c4bf1c2..889a5a3865 100644
--- a/src/plugins/qmldesigner/designercore/model/qmlchangeset.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qmlchangeset.cpp
@@ -85,7 +85,7 @@ void QmlPropertyChanges::removeProperty(const PropertyName &name)
if (name == "name")
return;
modelNode().removeProperty(name);
- if (modelNode().variantProperties().isEmpty() && modelNode().bindingProperties().count() < 2)
+ if (modelNode().variantProperties().isEmpty() && modelNode().bindingProperties().size() < 2)
modelNode().destroy();
}
diff --git a/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp
index 2c990a5036..175d329118 100644
--- a/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp
@@ -309,7 +309,7 @@ bool QmlItemNode::instanceHasShowContent() const
bool QmlItemNode::instanceCanReparent() const
{
- return QmlObjectNode::instanceCanReparent() && !anchors().instanceHasAnchors() && !instanceIsAnchoredBySibling();
+ return isInBaseState() && !anchors().instanceHasAnchors() && !instanceIsAnchoredBySibling();
}
bool QmlItemNode::instanceIsAnchoredBySibling() const
diff --git a/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp
index 0a7039ff13..b2694b9951 100644
--- a/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp
@@ -14,6 +14,7 @@
#include "qmlstate.h"
#include "qmltimelinekeyframegroup.h"
#include "qmlvisualnode.h"
+#include "stringutils.h"
#include "variantproperty.h"
#include <auxiliarydataproperties.h>
@@ -34,6 +35,9 @@ void QmlObjectNode::setVariantProperty(const PropertyName &name, const QVariant
if (!isValid())
return;
+ if (metaInfo().isQtQuick3DNode() && !Qml3DNode(modelNode()).handleEulerRotation(name))
+ return;
+
if (timelineIsActive() && currentTimeline().isRecording()) {
modelNode().validId();
@@ -78,6 +82,9 @@ void QmlObjectNode::setBindingProperty(const PropertyName &name, const QString &
if (!isValid())
return;
+ if (metaInfo().isQtQuick3DNode() && !Qml3DNode(modelNode()).handleEulerRotation(name))
+ return;
+
if (isInBaseState()) {
modelNode().bindingProperty(name).setExpression(expression); //basestate
} else {
@@ -250,7 +257,7 @@ QString QmlObjectNode::stripedTranslatableText(const PropertyName &name) const
const QRegularExpressionMatch match = regularExpressionPattern.match(
modelNode().bindingProperty(name).expression());
if (match.hasMatch())
- return match.captured(2);
+ return deescape(match.captured(2));
return instanceValue(name).toString();
}
return instanceValue(name).toString();
@@ -295,7 +302,10 @@ bool QmlObjectNode::timelineIsActive() const
bool QmlObjectNode::instanceCanReparent() const
{
- return isInBaseState();
+ if (auto qmlItemNode = QmlItemNode{modelNode()})
+ return qmlItemNode.instanceCanReparent();
+ else
+ return isInBaseState();
}
QmlPropertyChanges QmlObjectNode::propertyChangeForCurrentState() const
@@ -312,102 +322,6 @@ QmlPropertyChanges QmlObjectNode::propertyChangeForCurrentState() const
return currentState().propertyChanges(modelNode());
}
-static void removeStateOperationsForChildren(const QmlObjectNode &node)
-{
- if (node.isValid()) {
- for (QmlModelStateOperation stateOperation : node.allAffectingStatesOperations()) {
- stateOperation.modelNode().destroy(); //remove of belonging StatesOperations
- }
-
- for (const QmlObjectNode childNode : node.modelNode().directSubModelNodes()) {
- removeStateOperationsForChildren(childNode);
- }
- }
-}
-
-static void removeAnimationsFromAnimation(const ModelNode &animation)
-{
- QTC_ASSERT(animation.isValid(), return );
-
- auto model = animation.model();
- const QList<ModelNode> propertyAnimations = animation.subModelNodesOfType(
- model->qtQuickPropertyAnimationMetaInfo());
-
- for (const ModelNode &child : propertyAnimations) {
- if (!child.hasBindingProperty("target")) {
- ModelNode nonConst = animation;
- nonConst.destroy();
- return;
- }
- }
-}
-
-static void removeAnimationsFromTransition(const ModelNode &transition, const QmlObjectNode &node)
-{
- QTC_ASSERT(node.isValid(), return);
- QTC_ASSERT(transition.isValid(), return);
-
- const auto children = transition.directSubModelNodes();
- for (const ModelNode &parallel : children)
- removeAnimationsFromAnimation(parallel);
-}
-
-static void removeDanglingAnimationsFromTransitions(const QmlObjectNode &node)
-{
- QTC_ASSERT(node.isValid(), return);
-
- auto root = node.view()->rootModelNode();
-
- if (root.isValid() && root.hasProperty("transitions")) {
- NodeAbstractProperty transitions = root.nodeAbstractProperty("transitions");
- if (transitions.isValid()) {
- const auto transitionNodes = transitions.directSubNodes();
- for (const auto &transition : transitionNodes)
- removeAnimationsFromTransition(transition, node);
- }
- }
-}
-
-static void removeAliasExports(const QmlObjectNode &node)
-{
-
- PropertyName propertyName = node.id().toUtf8();
-
- ModelNode rootNode = node.view()->rootModelNode();
- bool hasAliasExport = !propertyName.isEmpty()
- && rootNode.isValid()
- && rootNode.hasBindingProperty(propertyName)
- && rootNode.bindingProperty(propertyName).isAliasExport();
-
- if (hasAliasExport)
- rootNode.removeProperty(propertyName);
-
-
- const QList<ModelNode> nodes = node.modelNode().directSubModelNodes();
- for (const ModelNode &childNode : nodes) {
- removeAliasExports(childNode);
- }
-
-}
-
-static void removeLayerEnabled(const ModelNode &node)
-{
- QTC_ASSERT(node.isValid(), return );
- if (node.parentProperty().isValid() && node.parentProperty().name() == "layer.effect") {
- ModelNode parent = node.parentProperty().parentModelNode();
- if (parent.isValid() && parent.hasProperty("layer.enabled"))
- parent.removeProperty("layer.enabled");
- }
-}
-
-static void deleteAllReferencesToNodeAndChildren(const ModelNode &node)
-{
- BindingProperty::deleteAllReferencesTo(node);
- const auto subNodes = node.allSubModelNodes();
- for (const ModelNode &child : subNodes)
- BindingProperty::deleteAllReferencesTo(child);
-}
-
/*!
Deletes this object's node and its dependencies from the model.
Everything that belongs to this Object, the ModelNode, and ChangeOperations
@@ -415,47 +329,7 @@ static void deleteAllReferencesToNodeAndChildren(const ModelNode &node)
*/
void QmlObjectNode::destroy()
{
- if (!isValid())
- return;
-
- removeLayerEnabled(modelNode());
- removeAliasExports(modelNode());
-
- for (QmlModelStateOperation stateOperation : allAffectingStatesOperations()) {
- stateOperation.modelNode().destroy(); //remove of belonging StatesOperations
- }
-
- QVector<ModelNode> timelineNodes;
- const auto allNodes = view()->allModelNodes();
- for (const auto &timelineNode : allNodes) {
- if (QmlTimeline::isValidQmlTimeline(timelineNode))
- timelineNodes.append(timelineNode);
- }
-
- const auto subNodes = modelNode().allSubModelNodesAndThisNode();
- for (auto &timelineNode : std::as_const(timelineNodes)) {
- QmlTimeline timeline(timelineNode);
- for (const auto &subNode : subNodes)
- timeline.destroyKeyframesForTarget(subNode);
- }
-
- bool wasFlowEditorTarget = false;
- if (QmlFlowTargetNode::isFlowEditorTarget(modelNode())) {
- QmlFlowTargetNode(modelNode()).destroyTargets();
- wasFlowEditorTarget = true;
- }
-
- removeStateOperationsForChildren(modelNode());
- deleteAllReferencesToNodeAndChildren(modelNode());
-
- removeDanglingAnimationsFromTransitions(modelNode());
-
- QmlFlowViewNode root(view()->rootModelNode());
-
modelNode().destroy();
-
- if (wasFlowEditorTarget && root.isValid())
- root.removeDanglingTransitions();
}
void QmlObjectNode::ensureAliasExport()
@@ -525,7 +399,7 @@ QList<QmlModelStateOperation> QmlObjectNode::allAffectingStatesOperations() cons
return returnList;
}
-static QList<QmlVisualNode> allQmlVisualNodesRecursive(const QmlItemNode &qmlItemNode)
+static QList<QmlVisualNode> allQmlVisualNodesRecursive(const QmlVisualNode &qmlItemNode)
{
QList<QmlVisualNode> qmlVisualNodeList;
@@ -663,15 +537,17 @@ QVariant QmlObjectNode::instanceValue(const ModelNode &modelNode, const Property
QString QmlObjectNode::generateTranslatableText([[maybe_unused]] const QString &text,
const DesignerSettings &settings)
{
+ const QString escapedText = escape(text);
+
if (settings.value(DesignerSettingsKey::TYPE_OF_QSTR_FUNCTION).toInt())
switch (settings.value(DesignerSettingsKey::TYPE_OF_QSTR_FUNCTION).toInt()) {
- case 0: return QString(QStringLiteral("qsTr(\"%1\")")).arg(text);
- case 1: return QString(QStringLiteral("qsTrId(\"%1\")")).arg(text);
- case 2: return QString(QStringLiteral("qsTranslate(\"%1\", \"context\")")).arg(text);
+ case 0: return QString(QStringLiteral("qsTr(\"%1\")")).arg(escapedText);
+ case 1: return QString(QStringLiteral("qsTrId(\"%1\")")).arg(escapedText);
+ case 2: return QString(QStringLiteral("qsTranslate(\"%1\", \"context\")")).arg(escapedText);
default:
break;
}
- return QString(QStringLiteral("qsTr(\"%1\")")).arg(text);
+ return QString(QStringLiteral("qsTr(\"%1\")")).arg(escapedText);
}
QString QmlObjectNode::stripedTranslatableTextFunction(const QString &text)
@@ -680,7 +556,7 @@ QString QmlObjectNode::stripedTranslatableTextFunction(const QString &text)
QLatin1String("^qsTr(|Id|anslate)\\(\"(.*)\"\\)$"));
const QRegularExpressionMatch match = regularExpressionPattern.match(text);
if (match.hasMatch())
- return match.captured(2);
+ return deescape(match.captured(2));
return text;
}
@@ -837,19 +713,4 @@ QStringList QmlObjectNode::allStateNames() const
return nodeInstance().allStateNames();
}
-QmlObjectNode *QmlObjectNode::getQmlObjectNodeOfCorrectType(const ModelNode &modelNode)
-{
- // Create QmlObjectNode of correct type for the modelNode
- // Note: Currently we are only interested in differentiating 3D nodes, so no check for
- // visual nodes is done for efficiency reasons
- if (modelNode.isValid() && modelNode.metaInfo().isQtQuick3DNode())
- return new Qml3DNode(modelNode);
- return new QmlObjectNode(modelNode);
-}
-
-bool QmlObjectNode::isBlocked([[maybe_unused]] const PropertyName &propName) const
-{
- return false;
-}
-
} //QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/model/qmltextgenerator.cpp b/src/plugins/qmldesigner/designercore/model/qmltextgenerator.cpp
index af9b6a2425..e5721d21c3 100644
--- a/src/plugins/qmldesigner/designercore/model/qmltextgenerator.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qmltextgenerator.cpp
@@ -3,19 +3,20 @@
#include "qmltextgenerator.h"
-#include <QVariant>
#include <QColor>
-#include <QVector4D>
-#include <QVector3D>
+#include <QVariant>
#include <QVector2D>
+#include <QVector3D>
+#include <QVector4D>
#include "bindingproperty.h"
-#include "signalhandlerproperty.h"
-#include "nodeproperty.h"
+#include "model.h"
#include "nodelistproperty.h"
+#include "nodeproperty.h"
+#include "signalhandlerproperty.h"
+#include "stringutils.h"
#include "variantproperty.h"
#include <nodemetainfo.h>
-#include "model.h"
using namespace QmlDesigner;
using namespace QmlDesigner::Internal;
@@ -114,14 +115,10 @@ QString QmlTextGenerator::toQml(const AbstractProperty &property, int indentDept
if (property.name() == "id")
return stringValue;
-
- if (false) {
- }
if (variantProperty.holdsEnumeration()) {
return variantProperty.enumeration().toString();
} else {
-
- switch (value.userType()) {
+ switch (value.typeId()) {
case QMetaType::Bool:
if (value.toBool())
return QStringLiteral("true");
@@ -284,20 +281,3 @@ QString QmlTextGenerator::propertyToQml(const AbstractProperty &property, int in
return result;
}
-
-QString QmlTextGenerator::escape(const QString &value)
-{
- QString result = value;
-
- if (value.size() == 6 && value.startsWith("\\u")) //Do not dobule escape unicode chars
- return result;
-
- result.replace(QStringLiteral("\\"), QStringLiteral("\\\\"));
-
- result.replace(QStringLiteral("\""), QStringLiteral("\\\""));
- result.replace(QStringLiteral("\t"), QStringLiteral("\\t"));
- result.replace(QStringLiteral("\r"), QStringLiteral("\\r"));
- result.replace(QStringLiteral("\n"), QStringLiteral("\\n"));
-
- return result;
-}
diff --git a/src/plugins/qmldesigner/designercore/model/qmltextgenerator.h b/src/plugins/qmldesigner/designercore/model/qmltextgenerator.h
index 6b114ebe1b..971d6a2d1d 100644
--- a/src/plugins/qmldesigner/designercore/model/qmltextgenerator.h
+++ b/src/plugins/qmldesigner/designercore/model/qmltextgenerator.h
@@ -32,8 +32,6 @@ private:
QString propertiesToQml(const ModelNode &node, int indentDepth) const;
QString propertyToQml(const AbstractProperty &property, int indentDepth) const;
- static QString escape(const QString &value);
-
private:
PropertyNameList m_propertyOrder;
TextEditor::TabSettings m_tabSettings;
diff --git a/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp
index 3831a90d97..2bfbe86031 100644
--- a/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp
@@ -417,6 +417,20 @@ QmlObjectNode QmlVisualNode::createQmlObjectNode(AbstractView *view,
newQmlObjectNode.setBindingProperty(property, parent.validId());
}
+ const QStringList copyFiles = itemLibraryEntry.extraFilePaths();
+ if (!copyFiles.isEmpty()) {
+ // Files are copied into the same directory as the current qml document
+ for (const auto &copyFileStr : copyFiles) {
+ Utils::FilePath sourceFile = Utils::FilePath::fromString(copyFileStr);
+ Utils::FilePath qmlFilePath = Utils::FilePath::fromString(
+ view->model()->fileUrl().toLocalFile()).absolutePath();
+ Utils::FilePath targetFile = qmlFilePath.pathAppended(sourceFile.fileName());
+ // We don't want to overwrite existing default files
+ if (!targetFile.exists() && !sourceFile.copyFile(targetFile))
+ qWarning() << QStringLiteral("Copying extra file '%1' failed.").arg(copyFileStr);
+ }
+ }
+
return newQmlObjectNode;
}
diff --git a/src/plugins/qmldesigner/designercore/model/rewriterview.cpp b/src/plugins/qmldesigner/designercore/model/rewriterview.cpp
index 53a0f4de59..60067a6bc9 100644
--- a/src/plugins/qmldesigner/designercore/model/rewriterview.cpp
+++ b/src/plugins/qmldesigner/designercore/model/rewriterview.cpp
@@ -88,9 +88,6 @@ void RewriterView::modelAttached(Model *model)
{
m_modelAttachPending = false;
- if (model && model->textModifier())
- setTextModifier(model->textModifier());
-
AbstractView::modelAttached(model);
ModelAmender differenceHandler(m_textToModelMerger.data());
@@ -954,12 +951,12 @@ const QmlJS::Document *RewriterView::document() const
return textToModelMerger()->document();
}
-static inline QString getUrlFromType(const QString& typeName)
+inline static QString getUrlFromType(const QString &typeName)
{
QStringList nameComponents = typeName.split('.');
QString result;
- for (int i = 0; i < (nameComponents.count() - 1); i++) {
+ for (int i = 0; i < (nameComponents.size() - 1); i++) {
result += nameComponents.at(i);
}
diff --git a/src/plugins/qmldesigner/designercore/model/signalhandlerproperty.cpp b/src/plugins/qmldesigner/designercore/model/signalhandlerproperty.cpp
index 4690044fa6..a260a2a0ef 100644
--- a/src/plugins/qmldesigner/designercore/model/signalhandlerproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/signalhandlerproperty.cpp
@@ -32,22 +32,24 @@ void SignalHandlerProperty::setSource(const QString &source)
if (source.isEmpty())
return;
- if (internalNode()->hasProperty(name())) { //check if oldValue != value
- Internal::InternalProperty::Pointer internalProperty = internalNode()->property(name());
- if (internalProperty->isSignalHandlerProperty()
- && internalProperty->toSignalHandlerProperty()->source() == source)
-
+ if (auto internalProperty = internalNode()->property(name())) {
+ auto signalHandlerProperty = internalProperty->to<PropertyType::SignalHandler>();
+ //check if oldValue != value
+ if (signalHandlerProperty && signalHandlerProperty->source() == source)
return;
- }
- if (internalNode()->hasProperty(name()) && !internalNode()->property(name())->isSignalHandlerProperty())
- privateModel()->removePropertyAndRelatedResources(internalNode()->property(name()));
+ if (!signalHandlerProperty)
+ privateModel()->removePropertyAndRelatedResources(internalProperty);
+ }
privateModel()->setSignalHandlerProperty(internalNode(), name(), source);
}
QString SignalHandlerProperty::source() const
{
+ if (!isValid())
+ return {};
+
if (internalNode()->hasProperty(name())
&& internalNode()->property(name())->isSignalHandlerProperty())
return internalNode()->signalHandlerProperty(name())->source();
@@ -109,23 +111,25 @@ void SignalDeclarationProperty::setSignature(const QString &signature)
if (signature.isEmpty())
return;
- if (internalNode()->hasProperty(name())) { //check if oldValue != value
- Internal::InternalProperty::Pointer internalProperty = internalNode()->property(name());
- if (internalProperty->isSignalDeclarationProperty()
- && internalProperty->toSignalDeclarationProperty()->signature() == signature)
-
+ if (auto internalProperty = internalNode()->property(name())) {
+ auto signalDeclarationProperty = internalProperty->to<PropertyType::SignalDeclaration>();
+ //check if oldValue != value
+ if (signalDeclarationProperty && signalDeclarationProperty->signature() == signature)
return;
- }
- if (internalNode()->hasProperty(name()) && !internalNode()->property(name())->isSignalDeclarationProperty())
- privateModel()->removePropertyAndRelatedResources(internalNode()->property(name()));
+ if (!signalDeclarationProperty)
+ privateModel()->removePropertyAndRelatedResources(internalProperty);
+ }
privateModel()->setSignalDeclarationProperty(internalNode(), name(), signature);
}
QString SignalDeclarationProperty::signature() const
{
- if (internalNode() && internalNode()->hasProperty(name())
+ if (!isValid())
+ return {};
+
+ if (internalNode()->hasProperty(name())
&& internalNode()->property(name())->isSignalDeclarationProperty())
return internalNode()->signalDeclarationProperty(name())->signature();
diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
index 3b5df397ea..3108e26a61 100644
--- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
+++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
@@ -12,6 +12,7 @@
#include "itemlibraryinfo.h"
#include "metainfo.h"
#include "modelnodepositionstorage.h"
+#include "modelutils.h"
#include "nodemetainfo.h"
#include "nodeproperty.h"
#include "propertyparser.h"
@@ -132,7 +133,7 @@ QString deEscape(const QString &value)
result.replace(QStringLiteral("\\\\"), QStringLiteral("\\"));
result.replace(QStringLiteral("\\\""), QStringLiteral("\""));
result.replace(QStringLiteral("\\t"), QStringLiteral("\t"));
- result.replace(QStringLiteral("\\r"), QStringLiteral("\\\r"));
+ result.replace(QStringLiteral("\\r"), QStringLiteral("\r"));
result.replace(QStringLiteral("\\n"), QStringLiteral("\n"));
return result;
@@ -165,10 +166,13 @@ bool isHexDigit(ushort c)
QString fixEscapedUnicodeChar(const QString &value) //convert "\u2939"
{
- if (value.size() == 6 && value.at(0) == QLatin1Char('\\') && value.at(1) == QLatin1Char('u') &&
- isHexDigit(value.at(2).unicode()) && isHexDigit(value.at(3).unicode()) &&
- isHexDigit(value.at(4).unicode()) && isHexDigit(value.at(5).unicode())) {
- return convertUnicode(value.at(2).unicode(), value.at(3).unicode(), value.at(4).unicode(), value.at(5).unicode());
+ if (value.size() == 6 && value.at(0) == QLatin1Char('\\') && value.at(1) == QLatin1Char('u')
+ && isHexDigit(value.at(2).unicode()) && isHexDigit(value.at(3).unicode())
+ && isHexDigit(value.at(4).unicode()) && isHexDigit(value.at(5).unicode())) {
+ return convertUnicode(value.at(2).unicode(),
+ value.at(3).unicode(),
+ value.at(4).unicode(),
+ value.at(5).unicode());
}
return value;
}
@@ -362,8 +366,8 @@ bool compareJavaScriptExpression(const QString &expression1, const QString &expr
bool smartVeryFuzzyCompare(const QVariant &value1, const QVariant &value2)
{
//we ignore slight changes on doubles and only check three digits
- const auto type1 = static_cast<QMetaType::Type>(value1.type());
- const auto type2 = static_cast<QMetaType::Type>(value2.type());
+ const auto type1 = static_cast<QMetaType::Type>(value1.typeId());
+ const auto type2 = static_cast<QMetaType::Type>(value2.typeId());
if (type1 == QMetaType::Double
|| type2 == QMetaType::Double
|| type1 == QMetaType::Float
@@ -387,13 +391,23 @@ bool smartVeryFuzzyCompare(const QVariant &value1, const QVariant &value2)
return false;
}
+ void removeModelNode(const QmlDesigner::ModelNode &modelNode)
+ {
+ modelNode.model()->removeModelNodes({modelNode},
+ QmlDesigner::BypassModelResourceManagement::Yes);
+ }
bool smartColorCompare(const QVariant &value1, const QVariant &value2)
{
- if ((value1.type() == QVariant::Color) || (value2.type() == QVariant::Color))
+ if ((value1.typeId() == QVariant::Color) || (value2.typeId() == QVariant::Color))
return value1.value<QColor>().rgba() == value2.value<QColor>().rgba();
return false;
}
+ void removeProperty(const QmlDesigner::AbstractProperty &modelProperty)
+ {
+ modelProperty.model()->removeProperties({modelProperty},
+ QmlDesigner::BypassModelResourceManagement::Yes);
+ }
bool equals(const QVariant &a, const QVariant &b)
{
if (a.canConvert<QmlDesigner::Enumeration>() && b.canConvert<QmlDesigner::Enumeration>())
@@ -573,25 +587,64 @@ public:
return true;
}
- bool isArrayProperty(const Value *value, const ObjectValue *containingObject, const QString &name)
+ bool isArrayProperty(const AbstractProperty &property)
{
- if (!value)
- return false;
- const ObjectValue *objectValue = value->asObjectValue();
- if (objectValue && objectValue->prototype(m_context) == m_context->valueOwner()->arrayPrototype())
- return true;
+ return ModelUtils::metainfo(property).isListProperty();
+ }
- PrototypeIterator iter(containingObject, m_context);
- while (iter.hasNext()) {
- const ObjectValue *proto = iter.next();
- if (proto->lookupMember(name, m_context) == m_context->valueOwner()->arrayPrototype())
- return true;
- if (const CppComponentValue *qmlIter = value_cast<CppComponentValue>(proto)) {
- if (qmlIter->isListProperty(name))
- return true;
- }
+ QVariant convertToVariant(const ModelNode &node,
+ const QString &astValue,
+ const QString &propertyPrefix,
+ AST::UiQualifiedId *propertyId)
+ {
+ const QString propertyName = propertyPrefix.isEmpty()
+ ? toString(propertyId)
+ : propertyPrefix + "." + toString(propertyId);
+
+
+ const PropertyMetaInfo propertyMetaInfo = node.metaInfo().property(propertyName.toUtf8());
+ const bool hasQuotes = astValue.trimmed().left(1) == QStringLiteral("\"")
+ && astValue.trimmed().right(1) == QStringLiteral("\"");
+ const QString cleanedValue = fixEscapedUnicodeChar(deEscape(stripQuotes(astValue.trimmed())));
+ if (!propertyMetaInfo.isValid()) {
+ qCInfo(texttomodelMergerDebug)
+ << Q_FUNC_INFO << "Unknown property"
+ << propertyPrefix + QLatin1Char('.') + toString(propertyId) << "on line"
+ << propertyId->identifierToken.startLine << "column"
+ << propertyId->identifierToken.startColumn;
+ return hasQuotes ? QVariant(cleanedValue) : cleverConvert(cleanedValue);
}
- return false;
+
+ const NodeMetaInfo &propertyTypeMetaInfo = propertyMetaInfo.propertyType();
+
+ if (propertyTypeMetaInfo.isColor())
+ return PropertyParser::read(QVariant::Color, cleanedValue);
+ else if (propertyTypeMetaInfo.isUrl())
+ return PropertyParser::read(QVariant::Url, cleanedValue);
+ else if (propertyTypeMetaInfo.isVector2D())
+ return PropertyParser::read(QVariant::Vector2D, cleanedValue);
+ else if (propertyTypeMetaInfo.isVector3D())
+ return PropertyParser::read(QVariant::Vector3D, cleanedValue);
+ else if (propertyTypeMetaInfo.isVector4D())
+ return PropertyParser::read(QVariant::Vector4D, cleanedValue);
+
+ QVariant value(cleanedValue);
+ if (propertyTypeMetaInfo.isBool()) {
+ value.convert(QVariant::Bool);
+ return value;
+ } else if (propertyTypeMetaInfo.isInteger()) {
+ value.convert(QVariant::Int);
+ return value;
+ } else if (propertyTypeMetaInfo.isFloat()) {
+ value.convert(QVariant::Double);
+ return value;
+ } else if (propertyTypeMetaInfo.isString()) {
+ // nothing to do
+ } else { //property alias et al
+ if (!hasQuotes)
+ return cleverConvert(cleanedValue);
+ }
+ return value;
}
QVariant convertToVariant(const QString &astValue, const QString &propertyPrefix, AST::UiQualifiedId *propertyId)
@@ -1255,12 +1308,13 @@ void TextToModelMerger::syncNode(ModelNode &modelNode,
} else {
const Value *propertyType = nullptr;
const ObjectValue *containingObject = nullptr;
- QString name;
- if (context->lookupProperty(QString(), binding->qualifiedId, &propertyType, &containingObject, &name)
- || isPropertyChangesType(typeName)
- || isConnectionsType(typeName)) {
+ if (context->lookupProperty({},
+ binding->qualifiedId,
+ &propertyType,
+ &containingObject)
+ || isPropertyChangesType(typeName) || isConnectionsType(typeName)) {
AbstractProperty modelProperty = modelNode.property(astPropertyName.toUtf8());
- if (context->isArrayProperty(propertyType, containingObject, name))
+ if (context->isArrayProperty(modelProperty))
syncArrayProperty(modelProperty, {member}, context, differenceHandler);
else
syncNodeProperty(modelProperty, binding, context, TypeName(), differenceHandler);
@@ -1447,7 +1501,10 @@ QmlDesigner::PropertyName TextToModelMerger::syncScriptBinding(ModelNode &modelN
syncVariantProperty(modelProperty, variantValue, TypeName(), differenceHandler);
return astPropertyName.toUtf8();
} else {
- const QVariant variantValue = context->convertToVariant(astValue, prefix, script->qualifiedId);
+ const QVariant variantValue = context->convertToVariant(modelNode,
+ astValue,
+ prefix,
+ script->qualifiedId);
if (variantValue.isValid()) {
AbstractProperty modelProperty = modelNode.property(astPropertyName.toUtf8());
syncVariantProperty(modelProperty, variantValue, TypeName(), differenceHandler);
@@ -2018,7 +2075,7 @@ void ModelAmender::shouldBeNodeProperty(AbstractProperty &modelProperty,
void ModelAmender::modelNodeAbsentFromQml(ModelNode &modelNode)
{
- modelNode.destroy();
+ removeModelNode(modelNode);
}
ModelNode ModelAmender::listPropertyMissingModelNode(NodeListProperty &modelProperty,
@@ -2095,7 +2152,7 @@ void ModelAmender::typeDiffers(bool isRootNode,
Q_ASSERT(nodeIndex >= 0);
}
- modelNode.destroy();
+ removeModelNode(modelNode);
const ModelNode &newNode = m_merger->createModelNode(typeName,
majorVersion,
@@ -2115,7 +2172,7 @@ void ModelAmender::typeDiffers(bool isRootNode,
void ModelAmender::propertyAbsentFromQml(AbstractProperty &modelProperty)
{
- modelProperty.parentModelNode().removeProperty(modelProperty.name());
+ removeProperty(modelProperty);
}
void ModelAmender::idsDiffer(ModelNode &modelNode, const QString &qmlId)
diff --git a/src/plugins/qmldesigner/designercore/model/variantproperty.cpp b/src/plugins/qmldesigner/designercore/model/variantproperty.cpp
index c879ec7a34..859bb0691e 100644
--- a/src/plugins/qmldesigner/designercore/model/variantproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/variantproperty.cpp
@@ -36,27 +36,29 @@ void VariantProperty::setValue(const QVariant &value)
if (isDynamic())
qWarning() << "Calling VariantProperty::setValue on dynamic property.";
+ if (auto internalProperty = internalNode()->property(name())) {
+ auto variantProperty = internalProperty->to<PropertyType::Variant>();
- if (internalNode()->hasProperty(name())) { //check if oldValue != value
- Internal::InternalProperty::Pointer internalProperty = internalNode()->property(name());
- if (internalProperty->isVariantProperty()
- && internalProperty->toVariantProperty()->value() == value
- && dynamicTypeName().isEmpty())
-
+ //check if oldValue != value
+ if (variantProperty && variantProperty->value() == value
+ && variantProperty->dynamicTypeName().isEmpty()) {
return;
- }
+ }
- if (internalNode()->hasProperty(name()) && !internalNode()->property(name())->isVariantProperty())
- privateModel()->removePropertyAndRelatedResources(internalNode()->property(name()));
+ if (!variantProperty)
+ privateModel()->removePropertyAndRelatedResources(internalProperty);
+ }
privateModel()->setVariantProperty(internalNode(), name(), value);
}
QVariant VariantProperty::value() const
{
- if (isValid() && internalNode()->hasProperty(name())
- && internalNode()->property(name())->isVariantProperty())
- return internalNode()->variantProperty(name())->value();
+ if (isValid()) {
+ auto property = internalNode()->variantProperty(name());
+ if (property)
+ return property->value();
+ }
return QVariant();
}
@@ -86,19 +88,18 @@ void VariantProperty::setDynamicTypeNameAndValue(const TypeName &type, const QVa
Internal::WriteLocker locker(model());
- if (internalNode()->hasProperty(name())) { //check if oldValue != value
- Internal::InternalProperty::Pointer internalProperty = internalNode()->property(name());
- if (internalProperty->isVariantProperty()
- && internalProperty->toVariantProperty()->value() == value
- && internalProperty->toVariantProperty()->dynamicTypeName() == type)
-
+ //check if oldValue != value
+ if (auto internalProperty = internalNode()->property(name())) {
+ auto variantProperty = internalProperty->to<PropertyType::Variant>();
+ if (variantProperty && variantProperty->value() == value
+ && internalProperty->dynamicTypeName() == type)
return;
- }
- if (internalNode()->hasProperty(name()) && !internalNode()->property(name())->isVariantProperty())
- privateModel()->removePropertyAndRelatedResources(internalNode()->property(name()));
+ if (!variantProperty)
+ privateModel()->removePropertyAndRelatedResources(internalProperty);
+ }
- privateModel()->setDynamicVariantProperty(internalNode(), name(), type, value);
+ privateModel()->setDynamicVariantProperty(internalNode(), name(), type, value);
}
void VariantProperty::setDynamicTypeNameAndEnumeration(const TypeName &type, const EnumerationName &enumerationName)
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h
index 974ebdf6aa..337145638c 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h
@@ -38,8 +38,13 @@ public:
ProjectStorage(Database &database, bool isInitialized)
: database{database}
+ , exclusiveTransaction{database}
, initializer{database, isInitialized}
{
+ exclusiveTransaction.commit();
+
+ database.walCheckpointFull();
+
moduleCache.populate();
}
@@ -494,7 +499,7 @@ private:
static bool moduleNameLess(Utils::SmallStringView first, Utils::SmallStringView second) noexcept
{
- return Utils::reverseCompare(first, second) < 0;
+ return first < second;
}
using ModuleCache = StorageCache<Utils::PathString,
@@ -513,9 +518,7 @@ private:
auto fetchModuleName(ModuleId id)
{
- return Sqlite::withDeferredTransaction(database, [&] {
- return fetchModuleNameUnguarded(id);
- });
+ return Sqlite::withDeferredTransaction(database, [&] { return fetchModuleNameUnguarded(id); });
}
auto fetchAllModules() const
@@ -936,8 +939,6 @@ private:
std::move(aliasPropertyNameTail));
updateAliasPropertyDeclarationToNullStatement.write(propertyDeclarationId);
-
- return Sqlite::CallbackControl::Continue;
};
selectAliasPropertiesDeclarationForPropertiesWithTypeIdStatement.readCallback(callback,
@@ -955,8 +956,6 @@ private:
{
auto callback = [&](TypeId typeId, ImportedTypeNameId prototypeNameId) {
relinkablePrototypes.emplace_back(typeId, prototypeNameId);
-
- return Sqlite::CallbackControl::Continue;
};
updatePrototypeIdToNullStatement.readCallback(callback, prototypeId);
@@ -966,8 +965,6 @@ private:
{
auto callback = [&](TypeId typeId, ImportedTypeNameId extensionNameId) {
relinkableExtensions.emplace_back(typeId, extensionNameId);
-
- return Sqlite::CallbackControl::Continue;
};
updateExtensionIdToNullStatement.readCallback(callback, extensionId);
@@ -1040,6 +1037,7 @@ private:
},
TypeCompare<PropertyDeclaration>{});
}
+
template<typename Callable>
void relinkPrototypes(Prototypes &relinkablePrototypes,
const TypeIds &deletedTypeIds,
@@ -1080,7 +1078,6 @@ private:
relinkablePropertyDeclarations,
relinkablePrototypes,
relinkableExtensions);
- return Sqlite::CallbackControl::Continue;
};
selectNotUpdatedTypesInSourcesStatement.readCallback(callback,
@@ -1553,10 +1550,10 @@ private:
int majorVersion,
int minorVersion,
ModuleExportedImportId moduleExportedImportId) {
- Storage::Synchronization::Import additionImport{
- exportedModuleId,
- Storage::Version{majorVersion, minorVersion},
- import.sourceId};
+ Storage::Synchronization::Import additionImport{exportedModuleId,
+ Storage::Version{majorVersion,
+ minorVersion},
+ import.sourceId};
auto exportedImportKind = importKind == Storage::Synchronization::ImportKind::Import
? Storage::Synchronization::ImportKind::ModuleExportedImport
@@ -1566,8 +1563,6 @@ private:
exportedImportKind,
import.moduleId,
moduleExportedImportId);
-
- return Sqlite::CallbackControl::Continue;
};
selectModuleExportedImportsForModuleIdStatement.readCallback(callback,
@@ -1964,8 +1959,6 @@ private:
auto callback = [=](TypeId currentTypeId) {
if (typeId == currentTypeId)
throw PrototypeChainCycle{};
-
- return Sqlite::CallbackControl::Continue;
};
selectTypeIdsForPrototypeChainIdStatement.readCallback(callback, typeId);
@@ -1976,8 +1969,6 @@ private:
auto callback = [=](PropertyDeclarationId currentPropertyDeclarationId) {
if (propertyDeclarationId == currentPropertyDeclarationId)
throw AliasChainCycle{};
-
- return Sqlite::CallbackControl::Continue;
};
selectPropertyDeclarationIdsForAliasChainStatement.readCallback(callback,
@@ -2209,8 +2200,6 @@ private:
auto &functionDeclaration = functionDeclarations.emplace_back(name, returnType);
functionDeclaration.parameters = selectFunctionParameterDeclarationsStatement.template values<
Storage::Synchronization::ParameterDeclaration>(8, functionDeclarationId);
-
- return Sqlite::CallbackControl::Continue;
};
selectFunctionDeclarationsForTypeIdWithoutSignatureStatement.readCallback(callback, typeId);
@@ -2226,8 +2215,6 @@ private:
auto &signalDeclaration = signalDeclarations.emplace_back(name);
signalDeclaration.parameters = selectSignalParameterDeclarationsStatement.template values<
Storage::Synchronization::ParameterDeclaration>(8, signalDeclarationId);
-
- return Sqlite::CallbackControl::Continue;
};
selectSignalDeclarationsForTypeIdWithoutSignatureStatement.readCallback(callback, typeId);
@@ -2245,8 +2232,6 @@ private:
name,
selectEnumeratorDeclarationStatement.template values<
Storage::Synchronization::EnumeratorDeclaration>(8, enumerationDeclarationId));
-
- return Sqlite::CallbackControl::Continue;
};
selectEnumerationDeclarationsForTypeIdWithoutEnumeratorDeclarationsStatement
@@ -2261,8 +2246,6 @@ private:
Initializer(Database &database, bool isInitialized)
{
if (!isInitialized) {
- Sqlite::ExclusiveTransaction transaction{database};
-
auto moduleIdColumn = createModulesTable(database);
createSourceContextsTable(database);
createSourcesTable(database);
@@ -2276,10 +2259,6 @@ private:
createDocumentImportsTable(database, moduleIdColumn);
createFileStatusesTable(database);
createProjectDatasTable(database);
-
- transaction.commit();
-
- database.walCheckpointFull();
}
database.setIsInitialized(true);
}
@@ -2617,6 +2596,7 @@ private:
public:
Database &database;
+ Sqlite::ExclusiveNonThrowingDestructorTransaction<Database> exclusiveTransaction;
Initializer initializer;
mutable ModuleCache moduleCache{ModuleStorageAdapter{*this}};
Storage::Info::CommonTypeCache<ProjectStorageInterface> commonTypeCache_{*this};
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragesqlitefunctionregistry.cpp b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragesqlitefunctionregistry.cpp
deleted file mode 100644
index 5f50c5bcda..0000000000
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragesqlitefunctionregistry.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#include "projectstoragesqlitefunctionregistry.h"
-
-#include "sqlite.h"
-
-namespace QmlDesigner {
-
-extern "C" {
-namespace {
-void unqualifiedTypeName(sqlite3_context *context, int, sqlite3_value **arguments)
-{
- auto argument = arguments[0];
-
- auto errorText = "unqualifiedTypeName only accepts text";
-
- if (sqlite3_value_type(argument) != SQLITE_TEXT) {
- sqlite3_result_error(context, errorText, int(std::char_traits<char>::length(errorText)));
- return;
- }
-
- auto size = sqlite3_value_bytes(argument);
-
- auto content = reinterpret_cast<const char *>(sqlite3_value_text(argument));
-
- auto begin = content;
- auto end = content + size;
-
- auto rbegin = std::make_reverse_iterator(end);
- auto rend = std::make_reverse_iterator(begin);
-
- auto found = std::find(rbegin, rend, '.').base();
-
- auto unqualifiedSize = end - found;
-
- sqlite3_result_text(context, found, int(unqualifiedSize), SQLITE_STATIC);
-}
-
-void registerUnqualifiedTypeName(sqlite3 *database)
-{
- sqlite3_create_function(database,
- "unqualifiedTypeName",
- 1,
- SQLITE_UTF8 | SQLITE_DETERMINISTIC | SQLITE_INNOCUOUS,
- nullptr,
- unqualifiedTypeName,
- nullptr,
- nullptr);
-}
-} // namespace
-}
-
-ProjectStorageSqliteFunctionRegistry::ProjectStorageSqliteFunctionRegistry(Sqlite::Database &database)
-{
- auto databaseHandle = database.backend().sqliteDatabaseHandle();
-
- registerUnqualifiedTypeName(databaseHandle);
-}
-
-} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragesqlitefunctionregistry.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragesqlitefunctionregistry.h
deleted file mode 100644
index 64836dd686..0000000000
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragesqlitefunctionregistry.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#pragma once
-
-#include <sqlitedatabase.h>
-
-namespace QmlDesigner {
-
-class ProjectStorageSqliteFunctionRegistry
-{
-public:
- ProjectStorageSqliteFunctionRegistry(Sqlite::Database &database);
-};
-
-} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h
index 22778ac932..519d11a920 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h
@@ -32,7 +32,7 @@ class ProjectStorage;
class QmlDocumentParserInterface;
class QmlTypesParserInterface;
-class ProjectStorageUpdater : public ProjectStoragePathWatcherNotifierInterface
+class ProjectStorageUpdater final : public ProjectStoragePathWatcherNotifierInterface
{
public:
using PathCache = SourcePathCache<ProjectStorage<Sqlite::Database>, NonLockingMutex>;
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h b/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h
index 2896d54ebe..96f28a4585 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h
@@ -12,7 +12,7 @@ namespace QmlDesigner {
template<typename ProjectStorage, typename Mutex>
class SourcePathCache;
-class QmlDocumentParser : public QmlDocumentParserInterface
+class QmlDocumentParser final : public QmlDocumentParserInterface
{
public:
using ProjectStorage = QmlDesigner::ProjectStorage<Sqlite::Database>;
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h
index c1d9a3a0d4..6fcf82a2bb 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h
@@ -18,7 +18,7 @@ class ProjectStorage;
template<typename ProjectStorage, typename Mutex>
class SourcePathCache;
-class QmlTypesParser : public QmlTypesParserInterface
+class QmlTypesParser final : public QmlTypesParserInterface
{
public:
using ProjectStorage = QmlDesigner::ProjectStorage<Sqlite::Database>;
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/sourcepathcache.h b/src/plugins/qmldesigner/designercore/projectstorage/sourcepathcache.h
index bc7e2f9ec1..0327ddcae0 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/sourcepathcache.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/sourcepathcache.h
@@ -143,7 +143,10 @@ private:
static bool sourceContextLess(Utils::SmallStringView first, Utils::SmallStringView second) noexcept
{
- return Utils::reverseCompare(first, second) < 0;
+ return std::lexicographical_compare(first.rbegin(),
+ first.rend(),
+ second.rbegin(),
+ second.rend());
}
static bool sourceLess(Cache::SourceNameView first, Cache::SourceNameView second) noexcept
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/sourcepathcachetypes.h b/src/plugins/qmldesigner/designercore/projectstorage/sourcepathcachetypes.h
index 8bbd5badaf..5feaf30d00 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/sourcepathcachetypes.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/sourcepathcachetypes.h
@@ -35,6 +35,7 @@ public:
class SourceNameEntry
{
public:
+ SourceNameEntry() = default;
SourceNameEntry(Utils::SmallStringView sourceName, SourceContextId sourceContextId)
: sourceName(sourceName)
, sourceContextId(sourceContextId)
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/storagecache.h b/src/plugins/qmldesigner/designercore/projectstorage/storagecache.h
index 945a6e38e5..f2d6841052 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/storagecache.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/storagecache.h
@@ -47,12 +47,12 @@ class StorageCache
template<typename IntegerType>
constexpr explicit StorageCacheIndex(IntegerType id) noexcept
- : id{static_cast<int>(id)}
+ : id{static_cast<std::size_t>(id)}
{}
constexpr StorageCacheIndex operator=(std::ptrdiff_t newId) noexcept
{
- id = static_cast<int>(newId);
+ id = static_cast<std::size_t>(newId);
return *this;
}
@@ -77,12 +77,15 @@ class StorageCache
return first.id >= second.id;
}
- constexpr bool isValid() const noexcept { return id >= 0; }
+ constexpr bool isValid() const noexcept
+ {
+ return id != std::numeric_limits<std::size_t>::max();
+ }
explicit operator std::size_t() const noexcept { return static_cast<std::size_t>(id); }
public:
- int id = -1;
+ std::size_t id = std::numeric_limits<std::size_t>::max();
};
public:
@@ -149,7 +152,7 @@ public:
});
if (found != m_entries.end())
- max_id = static_cast<std::size_t>(found->id) + 1;
+ max_id = static_cast<std::size_t>(found->id);
m_indices.resize(max_id);
@@ -184,7 +187,7 @@ public:
return first.id < second.id;
});
- auto max_id = static_cast<std::size_t>(found->id) + 1;
+ auto max_id = static_cast<std::size_t>(found->id);
if (max_id > m_indices.size())
m_indices.resize(max_id);
@@ -247,10 +250,11 @@ public:
{
std::shared_lock<Mutex> sharedLock(m_mutex);
- if (IndexType::create(static_cast<IndexDatabaseType>(m_indices.size())) > id) {
- if (auto indirectionIndex = m_indices.at(static_cast<std::size_t>(id));
- indirectionIndex.isValid())
+ if (IndexType::create(static_cast<IndexDatabaseType>(m_indices.size()) + 1) > id) {
+ if (StorageCacheIndex indirectionIndex = m_indices.at(static_cast<std::size_t>(id) - 1);
+ indirectionIndex.isValid()) {
return m_entries.at(static_cast<std::size_t>(indirectionIndex)).value;
+ }
}
sharedLock.unlock();
@@ -271,7 +275,9 @@ public:
for (IndexType id : ids) {
values.emplace_back(
- m_entries.at(static_cast<std::size_t>(m_indices.at(static_cast<std::size_t>(id)))).value);
+ m_entries
+ .at(static_cast<std::size_t>(m_indices.at(static_cast<std::size_t>(id) - 1)))
+ .value);
}
return values;
}
@@ -284,23 +290,63 @@ private:
void updateIndices()
{
auto begin = m_entries.cbegin();
- for (auto current = begin; current != m_entries.cend(); ++current)
- m_indices[static_cast<std::size_t>(current->id)] = std::distance(begin, current);
+ for (auto current = begin; current != m_entries.cend(); ++current) {
+ if (current->id)
+ m_indices[static_cast<std::size_t>(current->id) - 1] = std::distance(begin, current);
+ }
}
- auto find(ViewType view)
+ template<typename Entries>
+ static auto find(Entries &&entries, ViewType view)
{
- auto found = std::lower_bound(m_entries.begin(), m_entries.end(), view, compare);
+ auto begin = entries.begin();
+ auto end = entries.end();
+ auto found = std::lower_bound(begin, end, view, compare);
- if (found == m_entries.end())
- return m_entries.end();
+ if (found == entries.end()) {
+ return entries.end();
+ }
+
+ auto value = *found;
- if (*found == view)
+ if (value == view) {
return found;
+ }
- return m_entries.end();
+ return entries.end();
}
+ IndexType id(ViewType view) const
+ {
+ std::shared_lock<Mutex> sharedLock(m_mutex);
+
+ auto found = find(view);
+
+ if (found != m_entries.end()) {
+ return found->id;
+ }
+
+ return IndexType();
+ }
+
+ ResultType value(IndexType id) const
+ {
+ std::shared_lock<Mutex> sharedLock(m_mutex);
+
+ if (IndexType::create(static_cast<IndexDatabaseType>(m_indices.size()) + 1) > id) {
+ if (StorageCacheIndex indirectionIndex = m_indices.at(static_cast<std::size_t>(id) - 1);
+ indirectionIndex.isValid()) {
+ return m_entries.at(static_cast<std::size_t>(indirectionIndex)).value;
+ }
+ }
+
+ return ResultType();
+ }
+
+ auto find(ViewType view) const { return find(m_entries, view); }
+
+ auto find(ViewType view) { return find(m_entries, view); }
+
void incrementLargerOrEqualIndicesByOne(StorageCacheIndex newIndirectionIndex)
{
std::transform(m_indices.begin(), m_indices.end(), m_indices.begin(), [&](StorageCacheIndex index) {
@@ -322,14 +368,14 @@ private:
incrementLargerOrEqualIndicesByOne(newIndirectionIndex);
- auto indirectionIndex = static_cast<std::size_t>(id);
+ auto indirectionIndex = static_cast<std::size_t>(id) - 1;
ensureSize(indirectionIndex);
m_indices.at(indirectionIndex) = newIndirectionIndex;
return inserted;
}
- void checkEntries()
+ void checkEntries() const
{
for (const auto &entry : m_entries) {
if (entry.value != value(entry.id) || entry.id != id(entry.value))
diff --git a/src/plugins/qmldesigner/documentwarningwidget.cpp b/src/plugins/qmldesigner/documentwarningwidget.cpp
index d7bd70d5e3..49eb5acd46 100644
--- a/src/plugins/qmldesigner/documentwarningwidget.cpp
+++ b/src/plugins/qmldesigner/documentwarningwidget.cpp
@@ -121,13 +121,13 @@ QString DocumentWarningWidget::generateNavigateLinks()
{
static const QString link("<a href=\"%1\">%2</a>");
QStringList links;
- if (m_messages.count() > 1) {
+ if (m_messages.size() > 1) {
if (m_currentMessage != 0)
links << link.arg(QLatin1String("previous"), tr("Previous"));
else
links << tr("Previous");
- if (m_messages.count() - 1 > m_currentMessage)
+ if (m_messages.size() - 1 > m_currentMessage)
links << link.arg(QLatin1String("next"), tr("Next"));
else
links << tr("Next");
diff --git a/src/plugins/qmldesigner/generateresource.cpp b/src/plugins/qmldesigner/generateresource.cpp
index 439e124b70..be7f536662 100644
--- a/src/plugins/qmldesigner/generateresource.cpp
+++ b/src/plugins/qmldesigner/generateresource.cpp
@@ -288,7 +288,7 @@ void GenerateResource::generateMenuEntry(QObject *parent)
bool found = false;
QString compareString = "./" + relativepath.trimmed();
- for (int i = 0; i < fileList.count(); ++i)
+ for (int i = 0; i < fileList.size(); ++i)
if (fileList.at(i).fileName == compareString) {
fileList[i].inProject = true;
found = true;
@@ -424,7 +424,7 @@ void GenerateResource::generateMenuEntry(QObject *parent)
bool found = false;
QString compareString = "./" + relativepath.trimmed();
- for (int i = 0; i < fileList.count(); ++i)
+ for (int i = 0; i < fileList.size(); ++i)
if (fileList.at(i).fileName == compareString) {
fileList[i].inProject = true;
found = true;
diff --git a/src/plugins/qmldesigner/qmldesignerconstants.h b/src/plugins/qmldesigner/qmldesignerconstants.h
index d38dad74c7..1e16848c6b 100644
--- a/src/plugins/qmldesigner/qmldesignerconstants.h
+++ b/src/plugins/qmldesigner/qmldesignerconstants.h
@@ -80,6 +80,7 @@ const char MIME_TYPE_ITEM_LIBRARY_INFO[] = "application/vnd.qtdesignstudio.iteml
const char MIME_TYPE_ASSETS[] = "application/vnd.qtdesignstudio.assets";
const char MIME_TYPE_MATERIAL[] = "application/vnd.qtdesignstudio.material";
const char MIME_TYPE_TEXTURE[] = "application/vnd.qtdesignstudio.texture";
+const char MIME_TYPE_BUNDLE_EFFECT[] = "application/vnd.qtdesignstudio.bundleeffect";
const char MIME_TYPE_BUNDLE_MATERIAL[] = "application/vnd.qtdesignstudio.bundlematerial";
const char MIME_TYPE_BUNDLE_TEXTURE[] = "application/vnd.qtdesignstudio.bundletexture";
const char MIME_TYPE_ASSET_IMAGE[] = "application/vnd.qtdesignstudio.asset.image";
@@ -99,6 +100,7 @@ const int MODELNODE_PREVIEW_IMAGE_DIMENSIONS = 150;
const char EVENT_TIMELINE_ADDED[] = "timelineAdded";
const char EVENT_TRANSITION_ADDED[] = "transitionAdded";
const char EVENT_STATE_ADDED[] = "stateAdded";
+const char EVENT_STATE_ADDED_AND_CLONED[] = "stateAddedAndCloned";
const char EVENT_STATE_CLONED[] = "stateCloned";
const char EVENT_STATE_EXTENDED[] = "stateExtended";
const char EVENT_CONNECTION_ADDED[] = "connectionAdded";
@@ -162,6 +164,8 @@ const char OBJECT_NAME_NEW_DIALOG[] = "QQuickWidgetQDSNewDialog";
const char OBJECT_NAME_SPLASH_SCREEN[] = "QQuickWidgetSplashScreen";
const char OBJECT_NAME_WELCOME_PAGE[] = "QQuickWidgetQDSWelcomePage";
+const char ENVIRONMENT_SHOW_QML_ERRORS[] = "QMLDESIGNER_SHOW_QML_ERRORS";
+
namespace Internal {
enum { debug = 0 };
}
diff --git a/src/plugins/qmldesigner/qmldesignerplugin.cpp b/src/plugins/qmldesigner/qmldesignerplugin.cpp
index c83f830072..b586c5d5ad 100644
--- a/src/plugins/qmldesigner/qmldesignerplugin.cpp
+++ b/src/plugins/qmldesigner/qmldesignerplugin.cpp
@@ -131,6 +131,20 @@ QtQuickDesignerFactory::QtQuickDesignerFactory()
} // namespace Internal
+struct TraceIdentifierData
+{
+ TraceIdentifierData(const QString &_identifier, const QString &_newIdentifer, int _duration)
+ : identifier(_identifier), newIdentifer(_newIdentifer), maxDuration(_duration)
+ {}
+
+ TraceIdentifierData() = default;
+
+ QString identifier;
+ QString newIdentifer;
+ int maxDuration;
+ int time = 0;
+};
+
class QmlDesignerPluginPrivate
{
public:
@@ -145,6 +159,9 @@ public:
bool blockEditorChange = false;
Utils::UniqueObjectPtr<QToolBar> toolBar;
Utils::UniqueObjectPtr<QWidget> statusBar;
+ QHash<QString, TraceIdentifierData> m_traceIdentifierDataHash;
+ QHash<QString, TraceIdentifierData> m_activeTraceIdentifierDataHash;
+ QElapsedTimer timer;
};
QmlDesignerPlugin *QmlDesignerPlugin::m_instance = nullptr;
@@ -249,6 +266,7 @@ bool QmlDesignerPlugin::initialize(const QStringList & /*arguments*/, QString *e
if (!Utils::HostOsInfo::canCreateOpenGLContext(errorMessage))
return false;
d = new QmlDesignerPluginPrivate;
+ d->timer.start();
if (QmlProjectManager::QmlProject::isQtDesignStudio())
GenerateResource::generateMenuEntry(this);
@@ -284,58 +302,7 @@ bool QmlDesignerPlugin::initialize(const QStringList & /*arguments*/, QString *e
bool QmlDesignerPlugin::delayedInitialize()
{
- // adding default path to item library plugins
- const QString postfix = Utils::HostOsInfo::isMacHost() ? QString("/QmlDesigner")
- : QString("/qmldesigner");
- const QStringList pluginPaths =
- Utils::transform(ExtensionSystem::PluginManager::pluginPaths(), [postfix](const QString &p) {
- return QString(p + postfix);
- });
-
- 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));
- timelineView->registerActions();
-
- d->viewManager.registerView(
- std::make_unique<CurveEditorView>(d->externalDependencies));
-
- auto eventlistView = d->viewManager.registerView(
- std::make_unique<EventListPluginView>(d->externalDependencies));
- eventlistView->registerActions();
-
- auto transitionEditorView = d->viewManager.registerView(
- std::make_unique<TransitionEditorView>(d->externalDependencies));
- transitionEditorView->registerActions();
-
- d->viewManager.registerFormEditorTool(std::make_unique<SourceTool>());
- d->viewManager.registerFormEditorTool(std::make_unique<ColorTool>());
- d->viewManager.registerFormEditorTool(std::make_unique<TextTool>());
- d->viewManager.registerFormEditorTool(
- std::make_unique<PathTool>(d->externalDependencies));
- d->viewManager.registerFormEditorTool(std::make_unique<TransitionTool>());
-
- if (QmlProjectManager::QmlProject::isQtDesignStudio()) {
- d->mainWidget.initialize();
-
- emitUsageStatistics("StandaloneMode");
- if (QmlProjectManager::QmlProject::isQtDesignStudioStartedFromQtC())
- emitUsageStatistics("QDSlaunchedFromQtC");
- emitUsageStatistics("qdsStartupCount");
-
- FoundLicense license = checkLicense();
- if (license == FoundLicense::enterprise)
- Core::ICore::appendAboutInformation(tr("License: Enterprise"));
- else if (license == FoundLicense::professional)
- Core::ICore::appendAboutInformation(tr("License: Professional"));
-
- if (!licensee().isEmpty())
- Core::ICore::appendAboutInformation(tr("Licensee: %1").arg(licensee()));
- }
-
+ enforceDelayedInitialize();
return true;
}
@@ -352,6 +319,10 @@ void QmlDesignerPlugin::extensionsInitialized()
actionManager.createDefaultAddResourceHandler();
actionManager.createDefaultModelNodePreviewImageHandlers();
actionManager.polishActions();
+
+ registerCombinedTracedPoints(Constants::EVENT_STATE_ADDED,
+ Constants::EVENT_STATE_CLONED,
+ Constants::EVENT_STATE_ADDED_AND_CLONED);
}
ExtensionSystem::IPlugin::ShutdownFlag QmlDesignerPlugin::aboutToShutdown()
@@ -452,6 +423,8 @@ void QmlDesignerPlugin::showDesigner()
{
QTC_ASSERT(!d->documentManager.hasCurrentDesignDocument(), return);
+ enforceDelayedInitialize();
+
d->mainWidget.initialize();
const Utils::FilePath fileName = Core::EditorManager::currentEditor()->document()->filePath();
@@ -612,6 +585,70 @@ Model *QmlDesignerPlugin::currentModel() const
return currentDesignDocument()->currentModel();
}
+QmlDesignerPluginPrivate *QmlDesignerPlugin::privateInstance()
+{
+ QTC_ASSERT(instance(), return nullptr);
+ return instance()->d;
+}
+
+void QmlDesignerPlugin::enforceDelayedInitialize()
+{
+ if (m_delayedInitialized)
+ return;
+
+ // adding default path to item library plugins
+ const QString postfix = Utils::HostOsInfo::isMacHost() ? QString("/QmlDesigner")
+ : QString("/qmldesigner");
+ const QStringList pluginPaths = Utils::transform(ExtensionSystem::PluginManager::pluginPaths(),
+ [postfix](const QString &p) {
+ return QString(p + postfix);
+ });
+
+ 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));
+ timelineView->registerActions();
+
+ d->viewManager.registerView(std::make_unique<CurveEditorView>(d->externalDependencies));
+
+ auto eventlistView = d->viewManager.registerView(
+ std::make_unique<EventListPluginView>(d->externalDependencies));
+ eventlistView->registerActions();
+
+ auto transitionEditorView = d->viewManager.registerView(
+ std::make_unique<TransitionEditorView>(d->externalDependencies));
+ transitionEditorView->registerActions();
+
+ d->viewManager.registerFormEditorTool(std::make_unique<SourceTool>());
+ d->viewManager.registerFormEditorTool(std::make_unique<ColorTool>());
+ d->viewManager.registerFormEditorTool(std::make_unique<TextTool>());
+ d->viewManager.registerFormEditorTool(std::make_unique<PathTool>(d->externalDependencies));
+ d->viewManager.registerFormEditorTool(std::make_unique<TransitionTool>());
+
+ if (QmlProjectManager::QmlProject::isQtDesignStudio()) {
+ d->mainWidget.initialize();
+
+ emitUsageStatistics("StandaloneMode");
+ if (QmlProjectManager::QmlProject::isQtDesignStudioStartedFromQtC())
+ emitUsageStatistics("QDSlaunchedFromQtC");
+ emitUsageStatistics("qdsStartupCount");
+
+ FoundLicense license = checkLicense();
+ if (license == FoundLicense::enterprise)
+ Core::ICore::appendAboutInformation(tr("License: Enterprise"));
+ else if (license == FoundLicense::professional)
+ Core::ICore::appendAboutInformation(tr("License: Professional"));
+
+ if (!licensee().isEmpty())
+ Core::ICore::appendAboutInformation(tr("Licensee: %1").arg(licensee()));
+ }
+
+ m_delayedInitialized = true;
+}
+
DesignDocument *QmlDesignerPlugin::currentDesignDocument() const
{
if (d)
@@ -673,6 +710,35 @@ void QmlDesignerPlugin::emitUsageStatistics(const QString &identifier)
{
QTC_ASSERT(instance(), return);
emit instance()->usageStatisticsNotifier(normalizeIdentifier(identifier));
+
+ TraceIdentifierData activeData = privateInstance()->m_activeTraceIdentifierDataHash.value(
+ identifier);
+
+ if (activeData.time) {
+ const int currentTime = privateInstance()->timer.elapsed();
+ const int currentDuration = (currentTime - activeData.time);
+ if (currentDuration < activeData.maxDuration)
+ instance()->emitUsageStatisticsUsageDuration(activeData.newIdentifer, currentDuration);
+
+ privateInstance()->m_activeTraceIdentifierDataHash.remove(identifier);
+ }
+
+ TraceIdentifierData data = privateInstance()->m_traceIdentifierDataHash.value(identifier);
+
+ if (!data.identifier.isEmpty()) {
+ data.time = privateInstance()->timer.elapsed();
+ privateInstance()->m_activeTraceIdentifierDataHash.insert(data.identifier, data);
+ }
+
+ const auto values = privateInstance()->m_activeTraceIdentifierDataHash.values();
+ for (const auto &activeData : values) {
+ const int currentTime = privateInstance()->timer.elapsed();
+ const int currentDuration = (currentTime - activeData.time);
+
+ if (currentDuration > activeData.maxDuration) {
+ privateInstance()->m_activeTraceIdentifierDataHash.remove(activeData.identifier);
+ }
+ }
}
void QmlDesignerPlugin::emitUsageStatisticsContextAction(const QString &identifier)
@@ -727,6 +793,18 @@ void QmlDesignerPlugin::trackWidgetFocusTime(QWidget *widget, const QString &ide
});
}
+void QmlDesignerPlugin::registerCombinedTracedPoints(const QString &identifierFirst,
+ const QString &identifierSecond,
+ const QString &newIdentifier,
+ int maxDuration)
+{
+ QTC_ASSERT(privateInstance(), return );
+ privateInstance()->m_traceIdentifierDataHash.insert(identifierFirst,
+ TraceIdentifierData(identifierSecond,
+ newIdentifier,
+ maxDuration));
+}
+
void QmlDesignerPlugin::lauchFeedbackPopup(const QString &identifier)
{
if (Core::ModeManager::currentModeId() == Core::Constants::MODE_DESIGN)
@@ -792,6 +870,12 @@ void QmlDesignerPlugin::emitUsageStatisticsTime(const QString &identifier, int e
emit instance()->usageStatisticsUsageTimer(normalizeIdentifier(identifier), elapsed);
}
+void QmlDesignerPlugin::emitUsageStatisticsUsageDuration(const QString &identifier, int elapsed)
+{
+ QTC_ASSERT(instance(), return );
+ emit instance()->usageStatisticsUsageDuration(identifier, elapsed);
+}
+
QmlDesignerPlugin *QmlDesignerPlugin::instance()
{
return m_instance;
diff --git a/src/plugins/qmldesigner/qmldesignerplugin.h b/src/plugins/qmldesigner/qmldesignerplugin.h
index ee078b273a..455810fa20 100644
--- a/src/plugins/qmldesigner/qmldesignerplugin.h
+++ b/src/plugins/qmldesigner/qmldesignerplugin.h
@@ -76,17 +76,25 @@ public:
static void emitUsageStatisticsContextAction(const QString &identifier);
static void emitUsageStatisticsHelpRequested(const QString &identifier);
static void emitUsageStatisticsTime(const QString &identifier, int elapsed);
+ static void emitUsageStatisticsUsageDuration(const QString &identifier, int elapsed);
static AsynchronousImageCache &imageCache();
static void registerPreviewImageProvider(QQmlEngine *engine);
static void trackWidgetFocusTime(QWidget *widget, const QString &identifier);
+ static void registerCombinedTracedPoints(const QString &identifierFirst,
+ const QString &identifierSecond,
+ const QString &newIdentifier,
+ int maxDuration = 10000);
signals:
void usageStatisticsNotifier(const QString &identifier);
void usageStatisticsUsageTimer(const QString &identifier, int elapsed);
- void usageStatisticsInsertFeedback(const QString &identifier, const QString &feedback, int rating);
+ void usageStatisticsUsageDuration(const QString &identifier, int elapsed);
+ void usageStatisticsInsertFeedback(const QString &identifier,
+ const QString &feedback,
+ int rating);
void assetChanged(const QString &assetPath);
private slots:
@@ -110,11 +118,14 @@ private: // functions
RewriterView *rewriterView() const;
Model *currentModel() const;
QQuickWidget *m_feedbackWidget = nullptr;
+ static QmlDesignerPluginPrivate *privateInstance();
+ void enforceDelayedInitialize();
private: // variables
QmlDesignerPluginPrivate *d = nullptr;
static QmlDesignerPlugin *m_instance;
QElapsedTimer m_usageTimer;
+ bool m_delayedInitialized = false;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qtquickplugin/images/mouse-area-icon.png b/src/plugins/qmldesigner/qtquickplugin/images/mouse-area-icon.png
index 791e5f9520..fe316caf8d 100644
--- a/src/plugins/qmldesigner/qtquickplugin/images/mouse-area-icon.png
+++ b/src/plugins/qmldesigner/qtquickplugin/images/mouse-area-icon.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qtquickplugin/images/mouse-area-icon16.png b/src/plugins/qmldesigner/qtquickplugin/images/mouse-area-icon16.png
index f426957af3..bc8725fb5f 100644
--- a/src/plugins/qmldesigner/qtquickplugin/images/mouse-area-icon16.png
+++ b/src/plugins/qmldesigner/qtquickplugin/images/mouse-area-icon16.png
Binary files differ
diff --git a/src/plugins/qmldesigner/qtquickplugin/images/mouse-area-icon@2x.png b/src/plugins/qmldesigner/qtquickplugin/images/mouse-area-icon@2x.png
index 14607fb896..04a25e13db 100644
--- a/src/plugins/qmldesigner/qtquickplugin/images/mouse-area-icon@2x.png
+++ b/src/plugins/qmldesigner/qtquickplugin/images/mouse-area-icon@2x.png
Binary files differ
diff --git a/src/plugins/qmldesigner/utils/filedownloader.cpp b/src/plugins/qmldesigner/utils/filedownloader.cpp
index 7825be5081..38f0caeeb3 100644
--- a/src/plugins/qmldesigner/utils/filedownloader.cpp
+++ b/src/plugins/qmldesigner/utils/filedownloader.cpp
@@ -9,6 +9,7 @@
#include <QDir>
#include <QQmlEngine>
#include <QRandomGenerator>
+#include <QSslSocket>
namespace QmlDesigner {
@@ -38,6 +39,27 @@ bool FileDownloader::deleteFileAtTheEnd() const
return m_targetFilePath.isEmpty();
}
+QNetworkRequest FileDownloader::makeRequest() const
+{
+ QUrl url = m_url;
+
+ if (url.scheme() == "https") {
+#ifndef QT_NO_SSL
+ if (!QSslSocket::supportsSsl())
+#endif
+ {
+ qWarning() << "SSL is not available. HTTP will be used instead of HTTPS.";
+ url.setScheme("http");
+ }
+ }
+
+ auto request = QNetworkRequest(url);
+ request.setAttribute(QNetworkRequest::RedirectPolicyAttribute,
+ QNetworkRequest::UserVerifiedRedirectPolicy);
+
+ return request;
+}
+
void FileDownloader::start()
{
emit downloadStarting();
@@ -48,9 +70,7 @@ void FileDownloader::start()
m_outputFile.setFileName(tempFileName);
m_outputFile.open(QIODevice::WriteOnly);
- auto request = QNetworkRequest(m_url);
- request.setAttribute(QNetworkRequest::RedirectPolicyAttribute,
- QNetworkRequest::UserVerifiedRedirectPolicy);
+ QNetworkRequest request = makeRequest();
QNetworkReply *reply = Utils::NetworkAccessManager::instance()->get(request);
m_reply = reply;
@@ -114,6 +134,13 @@ void FileDownloader::start()
return;
}
+ if (m_overwriteTarget && QFileInfo().exists(m_targetFilePath)) {
+ if (!QFile::remove(m_targetFilePath)) {
+ emit downloadFailed();
+ return;
+ }
+ }
+
if (!QFileInfo().exists(m_targetFilePath) && !m_outputFile.rename(m_targetFilePath)) {
emit downloadFailed();
return;
@@ -183,6 +210,19 @@ bool FileDownloader::downloadEnabled() const
return m_downloadEnabled;
}
+bool FileDownloader::overwriteTarget() const
+{
+ return m_overwriteTarget;
+}
+
+void FileDownloader::setOverwriteTarget(bool value)
+{
+ if (value != m_overwriteTarget) {
+ m_overwriteTarget = value;
+ emit overwriteTargetChanged();
+ }
+}
+
bool FileDownloader::finished() const
{
return m_finished;
@@ -235,9 +275,7 @@ void FileDownloader::doProbeUrl()
return;
}
- auto request = QNetworkRequest(m_url);
- request.setAttribute(QNetworkRequest::RedirectPolicyAttribute,
- QNetworkRequest::UserVerifiedRedirectPolicy);
+ QNetworkRequest request = makeRequest();
QNetworkReply *reply = Utils::NetworkAccessManager::instance()->head(request);
QNetworkReply::connect(reply, &QNetworkReply::redirected, [reply](const QUrl &) {
diff --git a/src/plugins/qmldesigner/utils/filedownloader.h b/src/plugins/qmldesigner/utils/filedownloader.h
index 4ecb6b4967..6027338af0 100644
--- a/src/plugins/qmldesigner/utils/filedownloader.h
+++ b/src/plugins/qmldesigner/utils/filedownloader.h
@@ -26,6 +26,7 @@ class FileDownloader : public QObject
Q_PROPERTY(QString outputFile READ outputFile NOTIFY outputFileChanged)
Q_PROPERTY(QDateTime lastModified READ lastModified NOTIFY lastModifiedChanged)
Q_PROPERTY(bool available READ available NOTIFY availableChanged)
+ Q_PROPERTY(bool overwriteTarget READ overwriteTarget WRITE setOverwriteTarget NOTIFY overwriteTargetChanged)
public:
explicit FileDownloader(QObject *parent = nullptr);
@@ -47,6 +48,9 @@ public:
void setDownloadEnabled(bool value);
bool downloadEnabled() const;
+ bool overwriteTarget() const;
+ void setOverwriteTarget(bool value);
+
void setProbeUrl(bool value);
bool probeUrl() const;
@@ -69,10 +73,12 @@ signals:
void downloadCanceled();
void probeUrlChanged();
void targetFilePathChanged();
+ void overwriteTargetChanged();
private:
void doProbeUrl();
bool deleteFileAtTheEnd() const;
+ QNetworkRequest makeRequest() const;
QUrl m_url;
bool m_probeUrl = false;
@@ -85,6 +91,7 @@ private:
QNetworkReply *m_reply = nullptr;
bool m_downloadEnabled = false;
+ bool m_overwriteTarget = false;
QString m_targetFilePath;
};
diff --git a/src/plugins/qmldesigner/utils/fileextractor.cpp b/src/plugins/qmldesigner/utils/fileextractor.cpp
index 7c32381b69..e2ba28e887 100644
--- a/src/plugins/qmldesigner/utils/fileextractor.cpp
+++ b/src/plugins/qmldesigner/utils/fileextractor.cpp
@@ -3,6 +3,7 @@
#include "fileextractor.h"
#include <QQmlEngine>
+#include <QRandomGenerator>
#include <QStorageInfo>
#include <extensionsystem/pluginmanager.h>
@@ -198,6 +199,13 @@ QString FileExtractor::sourceFile() const
void FileExtractor::extract()
{
+ if (m_targetPath.isEmpty()) {
+ auto uniqueText = QByteArray::number(QRandomGenerator::global()->generate(), 16);
+ QString tempFileName = QDir::tempPath() + "/.qds_" + uniqueText + "_extract_" + m_archiveName + "_dir";
+
+ m_targetPath = Utils::FilePath::fromString(tempFileName);
+ }
+
m_targetFolder = m_targetPath.toString() + "/" + m_archiveName;
// If the target directory already exists, remove it and its content
diff --git a/src/plugins/qmldesigner/utils/multifiledownloader.cpp b/src/plugins/qmldesigner/utils/multifiledownloader.cpp
index 6a8ac9761e..6a452d6b09 100644
--- a/src/plugins/qmldesigner/utils/multifiledownloader.cpp
+++ b/src/plugins/qmldesigner/utils/multifiledownloader.cpp
@@ -24,7 +24,7 @@ void MultiFileDownloader::setDownloader(FileDownloader *downloader)
QObject::connect(m_downloader, &FileDownloader::progressChanged, this, [this]() {
double curProgress = m_downloader->progress() / 100.0;
- double totalProgress = (m_nextFile + curProgress) / m_files.count();
+ double totalProgress = (m_nextFile + curProgress) / m_files.size();
m_progress = totalProgress * 100;
emit progressChanged();
});
diff --git a/src/plugins/qmldesignerbase/utils/designersettings.cpp b/src/plugins/qmldesignerbase/utils/designersettings.cpp
index fe1ee169c7..7071cfffbd 100644
--- a/src/plugins/qmldesignerbase/utils/designersettings.cpp
+++ b/src/plugins/qmldesignerbase/utils/designersettings.cpp
@@ -85,11 +85,11 @@ void DesignerSettings::fromSettings(QSettings *settings)
restoreValue(settings, DesignerSettingsKey::EDIT3DVIEW_GRID_COLOR, "#aaaaaa");
restoreValue(settings, DesignerSettingsKey::SMOOTH_RENDERING, false);
restoreValue(settings, DesignerSettingsKey::SHOW_DEBUG_SETTINGS, false);
- restoreValue(settings, DesignerSettingsKey::OLD_STATES_EDITOR, false);
restoreValue(settings, DesignerSettingsKey::EDITOR_ZOOM_FACTOR, 1.0);
restoreValue(settings, DesignerSettingsKey::ACTIONS_MERGE_TEMPLATE_ENABLED, false);
restoreValue(settings, DesignerSettingsKey::DOWNLOADABLE_BUNDLES_URL,
"https://cdn.qt.io/designstudio/bundles");
+ restoreValue(settings, DesignerSettingsKey::CONTENT_LIBRARY_NEW_FLAG_EXPIRATION_DAYS, 3);
settings->endGroup();
settings->endGroup();
diff --git a/src/plugins/qmldesignerbase/utils/designersettings.h b/src/plugins/qmldesignerbase/utils/designersettings.h
index 78b4370526..2e2e90c83f 100644
--- a/src/plugins/qmldesignerbase/utils/designersettings.h
+++ b/src/plugins/qmldesignerbase/utils/designersettings.h
@@ -57,10 +57,10 @@ inline constexpr char ALWAYS_DESIGN_MODE[] = "AlwaysDesignMode";
inline constexpr char DISABLE_ITEM_LIBRARY_UPDATE_TIMER[] = "DisableItemLibraryUpdateTimer";
inline constexpr char ASK_BEFORE_DELETING_ASSET[] = "AskBeforeDeletingAsset";
inline constexpr char SMOOTH_RENDERING[] = "SmoothRendering";
-inline constexpr char OLD_STATES_EDITOR[] = "ForceOldStatesEditor";
inline constexpr char EDITOR_ZOOM_FACTOR[] = "EditorZoomFactor";
inline constexpr char ACTIONS_MERGE_TEMPLATE_ENABLED[] = "ActionsMergeTemplateEnabled";
inline constexpr char DOWNLOADABLE_BUNDLES_URL[] = "DownloadableBundlesLocation";
+inline constexpr char CONTENT_LIBRARY_NEW_FLAG_EXPIRATION_DAYS[] = "ContentLibraryNewFlagExpirationInDays";
}
class QMLDESIGNERBASE_EXPORT DesignerSettings
diff --git a/src/plugins/qmlprojectmanager/buildsystem/projectitem/converters.cpp b/src/plugins/qmlprojectmanager/buildsystem/projectitem/converters.cpp
index 0097611a4d..7f01e33f43 100644
--- a/src/plugins/qmlprojectmanager/buildsystem/projectitem/converters.cpp
+++ b/src/plugins/qmlprojectmanager/buildsystem/projectitem/converters.cpp
@@ -10,7 +10,8 @@ namespace QmlProjectManager::Converters {
using PropsPair = QPair<QString, QStringList>;
struct FileProps
{
- const PropsPair image{"image", QStringList{"*.jpeg", "*.jpg", "*.png", "*.svg", "*.hdr", ".ktx"}};
+ const PropsPair image{"image",
+ QStringList{"*.jpeg", "*.jpg", "*.png", "*.svg", "*.hdr", ".ktx"}};
const PropsPair qml{"qml", QStringList{"*.qml"}};
const PropsPair qmlDir{"qmldir", QStringList{"qmldir"}};
const PropsPair javaScr{"javaScript", QStringList{"*.js", "*.ts"}};
@@ -43,7 +44,7 @@ QString jsonToQmlProject(const QJsonObject &rootObject)
auto appendBreak = [&ts]() { ts << Qt::endl; };
auto appendComment = [&ts, &indentationLevel](const QString &comment) {
- ts << QString(" ").repeated(indentationLevel * 4) << "\\\\ " << comment << Qt::endl;
+ ts << QString(" ").repeated(indentationLevel * 4) << "// " << comment << Qt::endl;
};
auto appendItem =
@@ -153,10 +154,14 @@ QString jsonToQmlProject(const QJsonObject &rootObject)
}
{ // append ShaderTool object
- startObject("ShaderTool");
- appendString("args", shaderConfig["args"].toVariant().toStringList().join(" "));
- appendArray("files", shaderConfig["files"].toVariant().toStringList());
- endObject();
+ if (!shaderConfig["args"].toVariant().toStringList().isEmpty()) {
+ startObject("ShaderTool");
+ appendString("args",
+ shaderConfig["args"].toVariant().toStringList().join(" ").replace(
+ "\"", "\\\""));
+ appendArray("files", shaderConfig["files"].toVariant().toStringList());
+ endObject();
+ }
}
{ // append files objects
@@ -190,7 +195,7 @@ QJsonObject qmlProjectTojson(const Utils::FilePath &projectFile)
}
if (rootNode->name() != QLatin1String("Project")) {
- qCritical() << "Cannot find root 'Proejct' item in the project file: " << projectFile;
+ qCritical() << "Cannot find root 'Project' item in the project file: " << projectFile;
return {};
}
@@ -216,18 +221,22 @@ QJsonObject qmlProjectTojson(const Utils::FilePath &projectFile)
// convert the the non-object props
for (const QString &propName : rootNode->propertyNames()) {
QJsonObject *currentObj = &rootObject;
- QString objKey = propName;
+ QString objKey = QString(propName).remove("QDS.", Qt::CaseInsensitive);
QJsonValue value = rootNode->property(propName).value.toJsonValue();
- if (propName.contains("language", Qt::CaseInsensitive)) {
+ if (propName.startsWith("mcu.", Qt::CaseInsensitive)) {
+ currentObj = &mcuObject;
+ objKey = QString(propName).remove("MCU.");
+ } else if (propName.contains("language", Qt::CaseInsensitive)) {
currentObj = &languageObject;
- if (propName.toLower() == "multilanguagesupport") // fixing the camelcase
+ if (propName.contains("multilanguagesupport", Qt::CaseInsensitive))
+ // fixing the camelcase
objKey = "multiLanguageSupport";
} else if (propName.contains("version", Qt::CaseInsensitive)) {
currentObj = &versionObject;
- if (propName.toLower() == "qdsversion")
+ if (propName.contains("qdsversion", Qt::CaseInsensitive))
objKey = "designStudio";
- else if (propName.toLower() == "quickversion")
+ else if (propName.contains("quickversion", Qt::CaseInsensitive))
objKey = "qtQuick";
} else if (propName.contains("widgetapp", Qt::CaseInsensitive)
|| propName.contains("fileselector", Qt::CaseInsensitive)
@@ -265,7 +274,8 @@ QJsonObject qmlProjectTojson(const Utils::FilePath &projectFile)
FileProps fileProps;
const QString childNodeName = childNode->name().toLower();
const QmlJS::SimpleReaderNode::Property childNodeFilter = childNode->property("filter");
- const QmlJS::SimpleReaderNode::Property childNodeDirectory = childNode->property("directory");
+ const QmlJS::SimpleReaderNode::Property childNodeDirectory = childNode->property(
+ "directory");
const QmlJS::SimpleReaderNode::Property childNodeFiles = childNode->property("files");
const QString childNodeFilterValue = childNodeFilter.value.toString();
@@ -304,12 +314,12 @@ QJsonObject qmlProjectTojson(const Utils::FilePath &projectFile)
// populate & update filters
if (filters.isEmpty()) {
- filters = QJsonArray::fromStringList(propsPair.second); // populate the filters with the predefined ones
+ filters = QJsonArray::fromStringList(
+ propsPair.second); // populate the filters with the predefined ones
}
if (childNodeFilter.isValid()) { // append filters from qmlproject (merge)
- const QStringList filtersFromProjectFile = childNodeFilterValue.split(
- ";");
+ const QStringList filtersFromProjectFile = childNodeFilterValue.split(";");
for (const QString &filter : filtersFromProjectFile) {
if (!filters.contains(QJsonValue(filter))) {
filters.append(QJsonValue(filter));
@@ -337,7 +347,8 @@ QJsonObject qmlProjectTojson(const Utils::FilePath &projectFile)
targetObject.insert("files", files);
fileGroupsObject.insert(propsPair.first, targetObject);
} else if (childNode->name().contains("shadertool", Qt::CaseInsensitive)) {
- QStringList quotedArgs = childNode->property("args").value.toString().split('\"', Qt::SkipEmptyParts);
+ QStringList quotedArgs
+ = childNode->property("args").value.toString().split('\"', Qt::SkipEmptyParts);
QStringList args;
for (int i = 0; i < quotedArgs.size(); ++i) {
// Each odd arg in this list is a single quoted argument, which we should
@@ -351,7 +362,8 @@ QJsonObject qmlProjectTojson(const Utils::FilePath &projectFile)
shaderToolObject.insert("args", QJsonArray::fromStringList(args));
shaderToolObject.insert("files", childNode->property("files").value.toJsonValue());
} else {
- rootObject.insert(toCamelCase(childNode->name()), nodeToJsonObject(childNode));
+ rootObject.insert(toCamelCase(childNode->name().remove("qds.", Qt::CaseInsensitive)),
+ nodeToJsonObject(childNode));
}
}
@@ -361,7 +373,8 @@ QJsonObject qmlProjectTojson(const Utils::FilePath &projectFile)
rootObject.insert("runConfig", runConfigObject);
rootObject.insert("deployment", deploymentObject);
rootObject.insert("mcuConfig", mcuObject);
- rootObject.insert("shaderTool", shaderToolObject);
+ if (!shaderToolObject.isEmpty())
+ rootObject.insert("shaderTool", shaderToolObject);
rootObject.insert("fileVersion", 1);
return rootObject;
}
diff --git a/src/plugins/qmlprojectmanager/buildsystem/projectitem/qmlprojectitem.h b/src/plugins/qmlprojectmanager/buildsystem/projectitem/qmlprojectitem.h
index 83ef5ca000..214614f536 100644
--- a/src/plugins/qmlprojectmanager/buildsystem/projectitem/qmlprojectitem.h
+++ b/src/plugins/qmlprojectmanager/buildsystem/projectitem/qmlprojectitem.h
@@ -7,11 +7,11 @@
#include <utils/environment.h>
+#include <QJsonObject>
#include <QObject>
#include <QSet>
-#include <QStringList>
#include <QSharedPointer>
-#include <QJsonObject>
+#include <QStringList>
#include <memory>
#include <vector>
@@ -30,7 +30,6 @@ public:
bool isQt4McuProject() const;
-
QString versionQt() const;
void setVersionQt(const QString &version);
@@ -102,7 +101,7 @@ private:
// runtime variables
Utils::FilePath m_projectFile; // design studio project file
- QJsonObject m_project; // root project object
+ QJsonObject m_project; // root project object
const bool m_skipRewrite;
// initializing functions
diff --git a/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.cpp b/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.cpp
index bce1b5babc..307b6d6145 100644
--- a/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.cpp
+++ b/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.cpp
@@ -5,6 +5,7 @@
#include "../qmlprojectconstants.h"
#include "../qmlprojectmanagertr.h"
+#include "../qmlproject.h"
#include <QtCore5Compat/qtextcodec.h>
#include <qmljs/qmljsmodelmanagerinterface.h>
@@ -82,11 +83,11 @@ QmlBuildSystem::QmlBuildSystem(Target *target)
updateDeploymentData();
registerMenuButtons();
- connect(target->project(), &Project::activeTargetChanged, [this](Target *target) {
+ connect(target->project(), &Project::activeTargetChanged, this, [this](Target *target) {
refresh(RefreshOptions::NoFileRefresh);
updateMcuBuildStep(target, qtForMCUs());
});
- connect(target->project(), &Project::projectFileIsDirty, [this]() {
+ connect(target->project(), &Project::projectFileIsDirty, this, [this]() {
refresh(RefreshOptions::Project);
updateMcuBuildStep(project()->activeTarget(), qtForMCUs());
});
@@ -155,6 +156,11 @@ bool QmlBuildSystem::updateProjectFile()
return true;
}
+QmlProject *QmlBuildSystem::qmlProject() const
+{
+ return qobject_cast<QmlProject *>(project());
+}
+
void QmlBuildSystem::triggerParsing()
{
refresh(RefreshOptions::Project);
@@ -284,14 +290,14 @@ bool QmlBuildSystem::setFileSettingInProjectFile(const QString &setting,
const QString relativePath = mainFilePath.relativeChildPath(projectDir).path();
if (fileContent.indexOf(settingQmlCode) < 0) {
- QString addedText = QString("\n %1 \"%2\"\n").arg(settingQmlCode).arg(relativePath);
+ QString addedText = QString("\n %1 \"%2\"\n").arg(settingQmlCode, relativePath);
auto index = fileContent.lastIndexOf("}");
fileContent.insert(index, addedText);
} else {
QString originalFileName = oldFile;
originalFileName.replace(".", "\\.");
const QRegularExpression expression(
- QString("%1\\s*\"(%2)\"").arg(settingQmlCode).arg(originalFileName));
+ QString("%1\\s*\"(%2)\"").arg(settingQmlCode, originalFileName));
const QRegularExpressionMatch match = expression.match(fileContent);
@@ -315,14 +321,85 @@ void QmlBuildSystem::setBlockFilesUpdate(bool newBlockFilesUpdate)
m_blockFilesUpdate = newBlockFilesUpdate;
}
+Utils::FilePath QmlBuildSystem::getStartupQmlFileWithFallback() const
+{
+ const auto currentProject = project();
+
+ if (!currentProject)
+ return {};
+
+ if (!target())
+ return {};
+
+ const auto getFirstFittingFile = [](const Utils::FilePaths &files) -> Utils::FilePath {
+ for (const auto &file : files) {
+ if (file.exists())
+ return file;
+ }
+ return {};
+ };
+
+ const QStringView uiqmlstr = u"ui.qml";
+ const QStringView qmlstr = u"qml";
+
+ //we will check mainUiFile and mainFile twice:
+ //first priority if it's ui.qml file, second if it's just a qml file
+ const Utils::FilePath mainUiFile = mainUiFilePath();
+ if (mainUiFile.exists() && mainUiFile.completeSuffix() == uiqmlstr)
+ return mainUiFile;
+
+ const Utils::FilePath mainQmlFile = mainFilePath();
+ if (mainQmlFile.exists() && mainQmlFile.completeSuffix() == uiqmlstr)
+ return mainQmlFile;
+
+ const Utils::FilePaths uiFiles = currentProject->files([&](const ProjectExplorer::Node *node) {
+ return node->filePath().completeSuffix() == uiqmlstr;
+ });
+ if (!uiFiles.isEmpty()) {
+ if (const auto file = getFirstFittingFile(uiFiles); !file.isEmpty())
+ return file;
+ }
+
+ //check the suffix of mainUiFiles again, since there are no ui.qml files:
+ if (mainUiFile.exists() && mainUiFile.completeSuffix() == qmlstr)
+ return mainUiFile;
+
+ if (mainQmlFile.exists() && mainQmlFile.completeSuffix() == qmlstr)
+ return mainQmlFile;
+
+ //maybe it's also worth priotizing qml files containing common words like "Screen"?
+ const Utils::FilePaths qmlFiles = currentProject->files([&](const ProjectExplorer::Node *node) {
+ return node->filePath().completeSuffix() == qmlstr;
+ });
+ if (!qmlFiles.isEmpty()) {
+ if (const auto file = getFirstFittingFile(qmlFiles); !file.isEmpty())
+ return file;
+ }
+
+ //if no source files exist in the project, lets try to open the .qmlproject file itself
+ const Utils::FilePath projectFile = projectFilePath();
+ if (projectFile.exists())
+ return projectFile;
+
+ return {};
+}
+
Utils::FilePath QmlBuildSystem::mainFilePath() const
{
- return projectDirectory().pathAppended(mainFile());
+ const QString fileName = mainFile();
+ if (fileName.isEmpty() || fileName.isNull()) {
+ return {};
+ }
+ return projectDirectory().pathAppended(fileName);
}
Utils::FilePath QmlBuildSystem::mainUiFilePath() const
{
- return projectDirectory().pathAppended(mainUiFile());
+ const QString fileName = mainUiFile();
+ if (fileName.isEmpty() || fileName.isNull()) {
+ return {};
+ }
+ return projectDirectory().pathAppended(fileName);
}
bool QmlBuildSystem::setMainFileInProjectFile(const Utils::FilePath &newMainFilePath)
diff --git a/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.h b/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.h
index 0a0e9cfcba..2d689a1971 100644
--- a/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.h
+++ b/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.h
@@ -94,6 +94,8 @@ public:
bool blockFilesUpdate() const;
void setBlockFilesUpdate(bool newBlockFilesUpdate);
+ Utils::FilePath getStartupQmlFileWithFallback() const;
+
signals:
void projectChanged();
diff --git a/src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.cpp b/src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.cpp
index 5a3bedf098..9603562dc6 100644
--- a/src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.cpp
+++ b/src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.cpp
@@ -20,6 +20,10 @@
#include <qmlprojectmanager/qmlproject.h>
#include <qmlprojectmanager/qmlprojectmanagerconstants.h>
+#include <extensionsystem/iplugin.h>
+#include <extensionsystem/pluginmanager.h>
+#include <extensionsystem/pluginspec.h>
+
#include <utils/fileutils.h>
#include <QAction>
@@ -37,6 +41,27 @@ namespace QmlProjectManager {
namespace GenerateCmake {
+static bool isQmlDesigner(const ExtensionSystem::PluginSpec *spec)
+{
+ if (!spec)
+ return false;
+
+ return spec->name().contains("QmlDesigner");
+}
+
+static void trackUsage(const QString &id)
+{
+ const auto plugins = ExtensionSystem::PluginManager::plugins();
+ const auto it = std::find_if(plugins.begin(), plugins.end(), &isQmlDesigner);
+ if (it != plugins.end()) {
+ QObject *qmlDesignerPlugin = (*it)->plugin();
+ QMetaObject::invokeMethod(qmlDesignerPlugin,
+ "usageStatisticsNotifier",
+ Qt::DirectConnection,
+ Q_ARG(QString, id));
+ }
+}
+
bool operator==(const GeneratableFile &left, const GeneratableFile &right)
{
return (left.filePath == right.filePath && left.content == right.content);
@@ -100,6 +125,7 @@ void generateMenuEntry(QObject *parent)
void onGenerateCmakeLists()
{
+ trackUsage("generateCMakeProjectDialogOpened");
FilePath rootDir = ProjectExplorer::ProjectManager::startupProject()->projectDirectory();
int projectDirErrors = isProjectCorrectlyFormed(rootDir);
@@ -122,6 +148,8 @@ void onGenerateCmakeLists()
cmakeGen.filterFileQueue(confirmedFiles);
cmakeGen.execute();
}
+
+ trackUsage("generateCMakeProjectExecuted");
}
bool isErrorFatal(int error)
diff --git a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmaincpp.tpl b/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmaincpp.tpl
index cedd80d76d..0ff9201d91 100644
--- a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmaincpp.tpl
+++ b/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmaincpp.tpl
@@ -13,7 +13,7 @@ int main(int argc, char *argv[])
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
- const QUrl url(u"qrc:Main/main.qml"_qs);
+ const QUrl url(u"qrc:/qt/qml/Main/main.qml"_qs);
QObject::connect(
&engine, &QQmlApplicationEngine::objectCreated, &app,
[url](QObject *obj, const QUrl &objUrl) {
diff --git a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmodulecmakelists.tpl b/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmodulecmakelists.tpl
index e193ebf5ba..93573a1ed7 100644
--- a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmodulecmakelists.tpl
+++ b/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmodulecmakelists.tpl
@@ -7,5 +7,6 @@ qt_add_library(%2 STATIC)
qt6_add_qml_module(%2
URI "%3"
VERSION 1.0
+ RESOURCE_PREFIX "/qt/qml"
%4
)
diff --git a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmodules.tpl b/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmodules.tpl
index a1fdb4071d..2b74c49af3 100644
--- a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmodules.tpl
+++ b/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmodules.tpl
@@ -4,6 +4,7 @@
qt6_add_qml_module(%1
URI "Main"
VERSION 1.0
+ RESOURCE_PREFIX "/qt/qml"
NO_PLUGIN
QML_FILES main.qml
)
diff --git a/src/plugins/qmlprojectmanager/qmlproject.cpp b/src/plugins/qmlprojectmanager/qmlproject.cpp
index 45aedb0177..12e1b9f7cb 100644
--- a/src/plugins/qmlprojectmanager/qmlproject.cpp
+++ b/src/plugins/qmlprojectmanager/qmlproject.cpp
@@ -67,40 +67,24 @@ void QmlProject::parsingFinished(const Target *target, bool success)
// trigger only once
disconnect(this, &QmlProject::anyParsingFinished, this, &QmlProject::parsingFinished);
- // FIXME: what to do in this case?
if (!target || !success || !activeTarget())
return;
- auto targetActive = activeTarget();
- auto qmlBuildSystem = qobject_cast<QmlProjectManager::QmlBuildSystem *>(
- targetActive->buildSystem());
-
- const Utils::FilePath mainUiFile = qmlBuildSystem->mainUiFilePath();
-
- if (mainUiFile.completeSuffix() == "ui.qml" && mainUiFile.exists()) {
- QTimer::singleShot(1000, [mainUiFile]() {
- Core::EditorManager::openEditor(mainUiFile, Utils::Id());
- });
+ const auto qmlBuildSystem = qobject_cast<QmlProjectManager::QmlBuildSystem *>(
+ activeTarget()->buildSystem());
+ if (!qmlBuildSystem)
return;
- }
-
- Utils::FilePaths uiFiles = collectUiQmlFilesForFolder(
- projectDirectory().pathAppended("content"));
- if (uiFiles.isEmpty()) {
- uiFiles = collectUiQmlFilesForFolder(projectDirectory());
- if (uiFiles.isEmpty())
- return;
- }
-
- Utils::FilePath currentFile;
- if (auto cd = Core::EditorManager::currentDocument())
- currentFile = cd->filePath();
- if (currentFile.isEmpty() || !isKnownFile(currentFile)) {
- QTimer::singleShot(1000, [uiFiles]() {
- Core::EditorManager::openEditor(uiFiles.first(), Utils::Id());
+ const auto openFile = [&](const Utils::FilePath file) {
+ //why is this timer needed here?
+ QTimer::singleShot(1000, this, [file] {
+ Core::EditorManager::openEditor(file, Utils::Id());
});
- }
+ };
+
+ const Utils::FilePath fileToOpen = qmlBuildSystem->getStartupQmlFileWithFallback();
+ if (!fileToOpen.isEmpty() && fileToOpen.exists() && !fileToOpen.isDir())
+ openFile(fileToOpen);
}
Project::RestoreResult QmlProject::fromMap(const QVariantMap &map, QString *errorMessage)
@@ -175,6 +159,14 @@ Utils::FilePaths QmlProject::collectUiQmlFilesForFolder(const Utils::FilePath &f
return uiFiles;
}
+Utils::FilePaths QmlProject::collectQmlFiles() const
+{
+ const Utils::FilePaths qmlFiles = files([&](const Node *node) {
+ return node->filePath().completeSuffix() == "qml";
+ });
+ return qmlFiles;
+}
+
Tasks QmlProject::projectIssues(const Kit *k) const
{
Tasks result = Project::projectIssues(k);
diff --git a/src/plugins/studiowelcome/studiowelcomeplugin.cpp b/src/plugins/studiowelcome/studiowelcomeplugin.cpp
index 7769f5f470..f2123cd2b2 100644
--- a/src/plugins/studiowelcome/studiowelcomeplugin.cpp
+++ b/src/plugins/studiowelcome/studiowelcomeplugin.cpp
@@ -102,30 +102,20 @@ static StudioWelcomePlugin *s_pluginInstance = nullptr;
static Utils::FilePath getMainUiFileWithFallback()
{
- auto project = ProjectExplorer::ProjectManager::startupProject();
+ const auto project = ProjectExplorer::ProjectManager::startupProject();
if (!project)
return {};
if (!project->activeTarget())
return {};
- auto qmlBuildSystem = qobject_cast<QmlProjectManager::QmlBuildSystem *>(
+ const auto qmlBuildSystem = qobject_cast<QmlProjectManager::QmlBuildSystem *>(
project->activeTarget()->buildSystem());
if (!qmlBuildSystem)
return {};
- auto mainUiFile = qmlBuildSystem->mainUiFilePath();
- if (mainUiFile.exists())
- return mainUiFile;
-
- const Utils::FilePaths uiFiles = project->files([&](const ProjectExplorer::Node *node) {
- return node->filePath().completeSuffix() == "ui.qml";
- });
- if (!uiFiles.isEmpty())
- return uiFiles.first();
-
- return {};
+ return qmlBuildSystem->getStartupQmlFileWithFallback();
}
std::unique_ptr<QSettings> makeUserFeedbackSettings()
@@ -254,14 +244,16 @@ public:
return;
m_blockOpenRecent = true;
- const FilePath projectFile = FilePath::fromVariant(data(index(row, 0), ProjectModel::FilePathRole));
+ const FilePath projectFile = FilePath::fromVariant(
+ data(index(row, 0), ProjectModel::FilePathRole));
if (projectFile.exists()) {
const ProjectExplorerPlugin::OpenProjectResult result
= ProjectExplorer::ProjectExplorerPlugin::openProject(projectFile);
if (!result && !result.alreadyOpen().isEmpty()) {
- const auto mainUiFile = getMainUiFileWithFallback();
- if (mainUiFile.exists())
- Core::EditorManager::openEditor(mainUiFile, Utils::Id());
+ const auto fileToOpen = getMainUiFileWithFallback();
+ if (!fileToOpen.isEmpty() && fileToOpen.exists() && !fileToOpen.isDir()) {
+ Core::EditorManager::openEditor(fileToOpen, Utils::Id());
+ }
};
}
@@ -413,20 +405,25 @@ static QString tags(const FilePath &projectFilePath)
const QByteArray data = reader.data();
- bool mcu = data.contains("qtForMCUs: true");
+ const bool isQt6 = data.contains("qt6Project: true");
+ const bool isMcu = data.contains("qtForMCUs: true");
- if (data.contains("qt6Project: true"))
+ if (isQt6)
ret.append("Qt 6");
- else if (mcu)
- ret.append("Qt For MCU");
else
ret.append("Qt 5");
+ if (isMcu)
+ ret.append("Qt For MCU");
+
return ret.join(",");
}
QVariant ProjectModel::data(const QModelIndex &index, int role) const
{
+ if (index.row() >= ProjectExplorer::ProjectExplorerPlugin::recentProjects().count())
+ return {};
+
const ProjectExplorer::RecentProjectsEntry data =
ProjectExplorer::ProjectExplorerPlugin::recentProjects().at(index.row());
switch (role) {
diff --git a/src/tools/qml2puppet/instances/nodeinstanceclientproxy.cpp b/src/tools/qml2puppet/instances/nodeinstanceclientproxy.cpp
index ffafb7bb00..489c8c840b 100644
--- a/src/tools/qml2puppet/instances/nodeinstanceclientproxy.cpp
+++ b/src/tools/qml2puppet/instances/nodeinstanceclientproxy.cpp
@@ -79,6 +79,7 @@ NodeInstanceClientProxy::NodeInstanceClientProxy(QObject *parent)
: QObject(parent)
, m_inputIoDevice(nullptr)
, m_outputIoDevice(nullptr)
+ , m_localSocket(nullptr)
, m_writeCommandCounter(0)
, m_synchronizeId(-1)
{
@@ -101,6 +102,7 @@ void NodeInstanceClientProxy::initializeSocket()
m_inputIoDevice = localSocket;
m_outputIoDevice = localSocket;
+ m_localSocket = localSocket;
}
void NodeInstanceClientProxy::initializeCapturedStream(const QString &fileName)
@@ -145,28 +147,28 @@ bool compareCommands(const QVariant &command, const QVariant &controlCommand)
static const int debugOutputCommandType = QMetaType::type("DebugOutputCommand");
static const int changeSelectionCommandType = QMetaType::type("ChangeSelectionCommand");
- if (command.userType() == controlCommand.userType()) {
- if (command.userType() == informationChangedCommandType)
+ if (command.typeId() == controlCommand.typeId()) {
+ if (command.typeId() == informationChangedCommandType)
return command.value<InformationChangedCommand>() == controlCommand.value<InformationChangedCommand>();
- else if (command.userType() == valuesChangedCommandType)
+ else if (command.typeId() == valuesChangedCommandType)
return command.value<ValuesChangedCommand>() == controlCommand.value<ValuesChangedCommand>();
- else if (command.userType() == valuesModifiedCommandType)
+ else if (command.typeId() == valuesModifiedCommandType)
return command.value<ValuesModifiedCommand>() == controlCommand.value<ValuesModifiedCommand>();
- else if (command.userType() == pixmapChangedCommandType)
+ else if (command.typeId() == pixmapChangedCommandType)
return command.value<PixmapChangedCommand>() == controlCommand.value<PixmapChangedCommand>();
- else if (command.userType() == childrenChangedCommandType)
+ else if (command.typeId() == childrenChangedCommandType)
return command.value<ChildrenChangedCommand>() == controlCommand.value<ChildrenChangedCommand>();
- else if (command.userType() == statePreviewImageChangedCommandType)
+ else if (command.typeId() == statePreviewImageChangedCommandType)
return command.value<StatePreviewImageChangedCommand>() == controlCommand.value<StatePreviewImageChangedCommand>();
- else if (command.userType() == componentCompletedCommandType)
+ else if (command.typeId() == componentCompletedCommandType)
return command.value<ComponentCompletedCommand>() == controlCommand.value<ComponentCompletedCommand>();
- else if (command.userType() == synchronizeCommandType)
+ else if (command.typeId() == synchronizeCommandType)
return command.value<SynchronizeCommand>() == controlCommand.value<SynchronizeCommand>();
- else if (command.userType() == tokenCommandType)
+ else if (command.typeId() == tokenCommandType)
return command.value<TokenCommand>() == controlCommand.value<TokenCommand>();
- else if (command.userType() == debugOutputCommandType)
+ else if (command.typeId() == debugOutputCommandType)
return command.value<DebugOutputCommand>() == controlCommand.value<DebugOutputCommand>();
- else if (command.userType() == changeSelectionCommandType)
+ else if (command.typeId() == changeSelectionCommandType)
return command.value<ChangeSelectionCommand>()
== controlCommand.value<ChangeSelectionCommand>();
}
@@ -188,8 +190,8 @@ void NodeInstanceClientProxy::writeCommand(const QVariant &command)
}
} else if (m_outputIoDevice) {
#ifdef NANOTRACE_ENABLED
- if (command.userType() != QMetaType::type("PuppetAliveCommand")) {
- if (command.userType() == QMetaType::type("SyncNanotraceCommand")) {
+ if (command.typeId() != QMetaType::type("PuppetAliveCommand")) {
+ if (command.typeId() == QMetaType::type("SyncNanotraceCommand")) {
SyncNanotraceCommand cmd = command.value<SyncNanotraceCommand>();
NANOTRACE_INSTANT_ARGS("Sync", "writeCommand",
{"name", cmd.name().toStdString()},
@@ -288,6 +290,8 @@ void NodeInstanceClientProxy::sceneCreated(const SceneCreatedCommand &command)
void NodeInstanceClientProxy::flush()
{
+ if (m_localSocket)
+ m_localSocket->flush();
}
void NodeInstanceClientProxy::synchronizeWithClientProcess()
@@ -391,8 +395,8 @@ void NodeInstanceClientProxy::readDataStream()
QVariant command = readCommandFromIOStream(m_inputIoDevice, &readCommandCounter, &blockSize);
#ifdef NANOTRACE_ENABLED
- if (command.userType() != QMetaType::type("EndNanotraceCommand")) {
- if (command.userType() == QMetaType::type("SyncNanotraceCommand")) {
+ if (command.typeId() != QMetaType::type("EndNanotraceCommand")) {
+ if (command.typeId() == QMetaType::type("SyncNanotraceCommand")) {
SyncNanotraceCommand cmd = command.value<SyncNanotraceCommand>();
NANOTRACE_INSTANT_ARGS("Sync", "readCommand",
{"name", cmd.name().toStdString()},
@@ -570,7 +574,7 @@ void NodeInstanceClientProxy::dispatchCommand(const QVariant &command)
static const int startNanotraceCommandType = QMetaType::type("StartNanotraceCommand");
static const int endNanotraceCommandType = QMetaType::type("EndNanotraceCommand");
- const int commandType = command.userType();
+ const int commandType = command.typeId();
if (commandType == inputEventCommandType)
inputEvent(command.value<InputEventCommand>());
@@ -620,13 +624,13 @@ void NodeInstanceClientProxy::dispatchCommand(const QVariant &command)
} else if (commandType == changeSelectionCommandType) {
ChangeSelectionCommand changeSelectionCommand = command.value<ChangeSelectionCommand>();
changeSelection(changeSelectionCommand);
- } else if (command.userType() == changeLanguageCommand) {
+ } else if (command.typeId() == changeLanguageCommand) {
changeLanguage(command.value<ChangeLanguageCommand>());
- } else if (command.userType() == changePreviewImageSizeCommand) {
+ } else if (command.typeId() == changePreviewImageSizeCommand) {
changePreviewImageSize(command.value<ChangePreviewImageSizeCommand>());
- } else if (command.userType() == startNanotraceCommandType) {
+ } else if (command.typeId() == startNanotraceCommandType) {
startNanotrace(command.value<StartNanotraceCommand>());
- } else if (command.userType() == endNanotraceCommandType) {
+ } else if (command.typeId() == endNanotraceCommandType) {
NANOTRACE_SHUTDOWN();
} else {
Q_ASSERT(false);
diff --git a/src/tools/qml2puppet/instances/nodeinstanceclientproxy.h b/src/tools/qml2puppet/instances/nodeinstanceclientproxy.h
index 8015dd0192..46d7eebfe6 100644
--- a/src/tools/qml2puppet/instances/nodeinstanceclientproxy.h
+++ b/src/tools/qml2puppet/instances/nodeinstanceclientproxy.h
@@ -117,6 +117,7 @@ private:
QTimer m_puppetAliveTimer;
QIODevice *m_inputIoDevice;
QIODevice *m_outputIoDevice;
+ QLocalSocket *m_localSocket;
std::unique_ptr<NodeInstanceServerInterface> m_nodeInstanceServer;
quint32 m_writeCommandCounter;
int m_synchronizeId;
diff --git a/src/tools/qml2puppet/mockfiles/qt5/EditView3D.qml b/src/tools/qml2puppet/mockfiles/qt5/EditView3D.qml
index bc8ef4e46b..1860e70efb 100644
--- a/src/tools/qml2puppet/mockfiles/qt5/EditView3D.qml
+++ b/src/tools/qml2puppet/mockfiles/qt5/EditView3D.qml
@@ -181,20 +181,20 @@ Item {
}
}
- function alignCamerasToView()
+ function alignCamerasToView(cameraNodes)
{
if (editView) {
- cameraControl.alignCameras(selectedNodes);
+ cameraControl.alignCameras(cameraNodes);
var propertyNames = ["position", "eulerRotation"];
- viewRoot.changeObjectProperty(selectedNodes, propertyNames);
- viewRoot.commitObjectProperty(selectedNodes, propertyNames);
+ viewRoot.changeObjectProperty(cameraNodes, propertyNames);
+ viewRoot.commitObjectProperty(cameraNodes, propertyNames);
}
}
- function alignViewToCamera()
+ function alignViewToCamera(cameraNodes)
{
if (editView)
- cameraControl.alignView(selectedNodes);
+ cameraControl.alignView(cameraNodes);
}
function updateViewStates(viewStates)
diff --git a/src/tools/qml2puppet/mockfiles/qt6/EditView3D.qml b/src/tools/qml2puppet/mockfiles/qt6/EditView3D.qml
index fad4ae822f..964f47941b 100644
--- a/src/tools/qml2puppet/mockfiles/qt6/EditView3D.qml
+++ b/src/tools/qml2puppet/mockfiles/qt6/EditView3D.qml
@@ -175,20 +175,20 @@ Item {
}
}
- function alignCamerasToView()
+ function alignCamerasToView(cameraNodes)
{
if (editView) {
- cameraControl.alignCameras(selectedNodes);
+ cameraControl.alignCameras(cameraNodes);
var propertyNames = ["position", "eulerRotation"];
- viewRoot.changeObjectProperty(selectedNodes, propertyNames);
- viewRoot.commitObjectProperty(selectedNodes, propertyNames);
+ viewRoot.changeObjectProperty(cameraNodes, propertyNames);
+ viewRoot.commitObjectProperty(cameraNodes, propertyNames);
}
}
- function alignViewToCamera()
+ function alignViewToCamera(cameraNodes)
{
if (editView)
- cameraControl.alignView(selectedNodes);
+ cameraControl.alignView(cameraNodes);
}
function updateViewStates(viewStates)
diff --git a/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.cpp b/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.cpp
index 52a3f6d74a..bfa2fcb1ae 100644
--- a/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.cpp
+++ b/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.cpp
@@ -520,8 +520,8 @@ void GeneralHelper::storeToolState(const QString &sceneId, const QString &tool,
handlePendingToolStateUpdate();
QVariant theState;
// Convert JS arrays to QVariantLists for easier handling down the line
- // metaType().id() which only exist in Qt6 is the same as userType()
- if (state.userType() != QMetaType::QString && state.canConvert(QMetaType::QVariantList))
+ // metaType().id() which only exist in Qt6 is the same as typeId()
+ if (state.typeId() != QMetaType::QString && state.canConvert(QMetaType::QVariantList))
theState = state.value<QVariantList>();
else
theState = state;
diff --git a/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.cpp b/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.cpp
index aff80c62af..3d6445e240 100644
--- a/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.cpp
+++ b/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.cpp
@@ -1058,6 +1058,21 @@ QList<ServerNodeInstance> NodeInstanceServer::allView3DInstances() const
return view3Ds;
}
+QList<ServerNodeInstance> NodeInstanceServer::allCameraInstances() const
+{
+ QList<ServerNodeInstance> cameras;
+ std::copy_if(nodeInstances().cbegin(),
+ nodeInstances().cend(),
+ std::back_inserter(cameras),
+ [](const ServerNodeInstance &instance) {
+ return instance.isValid()
+ && ServerNodeInstance::isSubclassOf(instance.internalObject(),
+ QByteArrayLiteral("QQuick3DCamera"));
+ });
+
+ return cameras;
+}
+
void NodeInstanceServer::setStateInstance(const ServerNodeInstance &stateInstance)
{
m_activeStateInstance = stateInstance;
@@ -1194,7 +1209,7 @@ ValuesChangedCommand NodeInstanceServer::createValuesChangedCommand(const QList<
const QList<PropertyName> propertyNames = instance.propertyNames();
for (const PropertyName &propertyName : propertyNames) {
QVariant propertyValue = instance.property(propertyName);
- if (supportedVariantType(propertyValue.userType())) {
+ if (supportedVariantType(propertyValue.typeId())) {
valueVector.append(PropertyValueContainer(instance.instanceId(), propertyName,
propertyValue, PropertyName()));
}
@@ -1236,13 +1251,13 @@ ValuesChangedCommand NodeInstanceServer::createValuesChangedCommand(const QVecto
if (instance.isValid()) {
QVariant propertyValue = instance.property(propertyName);
- bool isValid = QMetaType::isRegistered(propertyValue.userType())
- && supportedVariantType(propertyValue.type());
- if (!isValid && propertyValue.userType() == 0) {
+ bool isValid = QMetaType::isRegistered(propertyValue.typeId())
+ && supportedVariantType(propertyValue.typeId());
+ if (!isValid && propertyValue.typeId() == 0) {
// If the property is QVariant type, invalid variant can be a valid value
const QMetaObject *mo = instance.internalObject()->metaObject();
const int idx = mo->indexOfProperty(propertyName);
- isValid = idx >= 0 && mo->property(idx).userType() == QMetaType::QVariant;
+ isValid = idx >= 0 && mo->property(idx).typeId() == QMetaType::QVariant;
}
if (isValid) {
valueVector.append(PropertyValueContainer(instance.instanceId(), propertyName,
@@ -1265,8 +1280,8 @@ ValuesModifiedCommand NodeInstanceServer::createValuesModifiedCommand(
const QVariant propertyValue = property.propertyValue;
if (instance.isValid()) {
- if (QMetaType::isRegistered(propertyValue.userType())
- && supportedVariantType(propertyValue.type())) {
+ if (QMetaType::isRegistered(propertyValue.typeId())
+ && supportedVariantType(propertyValue.typeId())) {
valueVector.append(PropertyValueContainer(instance.instanceId(),
propertyName,
propertyValue,
diff --git a/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.h b/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.h
index 0fed4790ba..f4eee1e874 100644
--- a/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.h
+++ b/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.h
@@ -180,6 +180,7 @@ public:
QList<ServerNodeInstance> allGroupStateInstances() const;
QList<ServerNodeInstance> allView3DInstances() const;
+ QList<ServerNodeInstance> allCameraInstances() const;
void notifyPropertyChange(qint32 instanceid, const PropertyName &propertyName);
diff --git a/src/tools/qml2puppet/qml2puppet/instances/objectnodeinstance.cpp b/src/tools/qml2puppet/qml2puppet/instances/objectnodeinstance.cpp
index 48b42e7029..24ac400411 100644
--- a/src/tools/qml2puppet/qml2puppet/instances/objectnodeinstance.cpp
+++ b/src/tools/qml2puppet/qml2puppet/instances/objectnodeinstance.cpp
@@ -843,7 +843,7 @@ QObject *ObjectNodeInstance::createComponentWrap(const QString &nodeSource, cons
//The component might also be shipped with Creator.
//To avoid trouble with import "." we use the component shipped with Creator.
-static inline QString fixComponentPathForIncompatibleQt(const QString &componentPath)
+inline static QString fixComponentPathForIncompatibleQt(const QString &componentPath)
{
QString result = componentPath;
const QLatin1String importString("/imports/");
diff --git a/src/tools/qml2puppet/qml2puppet/instances/qt5bakelightsnodeinstanceserver.cpp b/src/tools/qml2puppet/qml2puppet/instances/qt5bakelightsnodeinstanceserver.cpp
index 4287808c8a..2a1aff912a 100644
--- a/src/tools/qml2puppet/qml2puppet/instances/qt5bakelightsnodeinstanceserver.cpp
+++ b/src/tools/qml2puppet/qml2puppet/instances/qt5bakelightsnodeinstanceserver.cpp
@@ -97,10 +97,11 @@ void Qt5BakeLightsNodeInstanceServer::bakeLights()
switch (status) {
case QQuick3DLightmapBaker::BakingStatus::Progress:
case QQuick3DLightmapBaker::BakingStatus::Warning:
- case QQuick3DLightmapBaker::BakingStatus::Error:
+ case QQuick3DLightmapBaker::BakingStatus::Error: {
nodeInstanceClient()->handlePuppetToCreatorCommand(
- {PuppetToCreatorCommand::BakeLightsProgress, msg.value_or("")});
- break;
+ {PuppetToCreatorCommand::BakeLightsProgress, msg.value_or("")});
+ nodeInstanceClient()->flush();
+ } break;
case QQuick3DLightmapBaker::BakingStatus::Cancelled:
abort(tr("Baking cancelled."));
break;
diff --git a/src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp b/src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp
index 0d7b4fa215..b4c47a0a2a 100644
--- a/src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp
+++ b/src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp
@@ -179,6 +179,7 @@ void Qt5InformationNodeInstanceServer::createAuxiliaryQuickView(const QUrl &url,
#else
viewData.renderControl = new QQuickRenderControl;
viewData.window = new QQuickWindow(viewData.renderControl);
+ setPipelineCacheConfig(viewData.window);
viewData.renderControl->initialize();
#endif
QQmlComponent component(engine());
@@ -654,7 +655,7 @@ Qt5InformationNodeInstanceServer::propertyToPropertyValueTriples(
QVector<InstancePropertyValueTriple> result;
InstancePropertyValueTriple propTriple;
- if (variant.type() == QVariant::Vector3D) {
+ if (variant.typeId() == QVariant::Vector3D) {
auto vector3d = variant.value<QVector3D>();
if (vector3d.isNull())
@@ -950,6 +951,18 @@ void Qt5InformationNodeInstanceServer::removeNode3D(QObject *node)
m_active3DView = nullptr;
updateActiveSceneToEditView3D();
}
+ if (m_selectedCameras.contains(node)) {
+ m_selectedCameras.remove(node);
+ } else {
+ auto cit = m_selectedCameras.constBegin();
+ while (cit != m_selectedCameras.constEnd()) {
+ if (cit.value().contains(node)) {
+ m_selectedCameras[cit.key()].removeOne(node);
+ break;
+ }
+ ++cit;
+ }
+ }
}
void Qt5InformationNodeInstanceServer::resolveSceneRoots()
@@ -1130,6 +1143,16 @@ void Qt5InformationNodeInstanceServer::doRender3DEditView()
m_render3DEditViewTimer.start(17); // 16.67ms = ~60fps, rounds up to 17
--m_need3DEditViewRender;
}
+#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 1)
+ else {
+ static bool pipelineSaved = false;
+ if (!pipelineSaved) {
+ // Store pipeline cache for quicker initialization in future
+ savePipelineCacheData();
+ pipelineSaved = true;
+ }
+ }
+#endif
#ifdef FPS_COUNTER
// Force constant rendering for accurate fps count
@@ -2173,6 +2196,7 @@ void Qt5InformationNodeInstanceServer::changeSelection(const ChangeSelectionComm
QVariantList selectedObjs;
QObject *firstSceneRoot = nullptr;
ServerNodeInstance firstInstance;
+ QObjectList selectedCameras;
#ifdef QUICK3D_PARTICLES_MODULE
QList<QQuick3DParticleSystem *> selectedParticleSystems;
#endif
@@ -2215,15 +2239,20 @@ void Qt5InformationNodeInstanceServer::changeSelection(const ChangeSelectionComm
if (node) {
const auto childItems = node->childItems();
for (const auto &childItem : childItems) {
- if (qobject_cast<QQuick3DNode *>(childItem) && !hasInstanceForObject(childItem))
+ if (qobject_cast<QQuick3DNode *>(childItem))
return true;
}
}
#endif
return false;
};
- if (object && (firstSceneRoot != object || isSelectableAsRoot()))
+ if (object && (firstSceneRoot != object || isSelectableAsRoot())) {
selectedObjs << objectToVariant(object);
+#ifdef QUICK3D_MODULE
+ if (qobject_cast<QQuick3DCamera *>(object))
+ selectedCameras << object;
+#endif
+ }
}
}
@@ -2241,6 +2270,11 @@ void Qt5InformationNodeInstanceServer::changeSelection(const ChangeSelectionComm
updateActiveSceneToEditView3D();
}
+ // Only update selected cameras if there are cameras in selection.
+ // This way m_selectedCameras retains previous camera selection.
+ if (!selectedCameras.isEmpty())
+ m_selectedCameras.insert(m_active3DScene, selectedCameras);
+
// Ensure the UI has enough selection box items. If it doesn't yet have them, which can be the
// case when the first selection processed is a multiselection, we wait a bit as
// using the new boxes immediately leads to visual glitches.
@@ -2297,6 +2331,45 @@ void Qt5InformationNodeInstanceServer::setSceneEnvironmentColor(const PropertyVa
#endif
}
+// Returns list of camera objects to align
+// If m_selectedCameras contains cameras, return those
+// If no cameras have been selected yet, return camera associated with current view3D, if any
+// If scene is not View3D scene, return first camera in the scene
+QVariantList Qt5InformationNodeInstanceServer::alignCameraList() const
+{
+#ifdef QUICK3D_MODULE
+ QVariantList cameras;
+ if (m_selectedCameras.contains(m_active3DScene)) {
+ const QObjectList cameraList = m_selectedCameras[m_active3DScene];
+ for (const auto camera : cameraList) {
+ if (hasInstanceForObject(camera) && find3DSceneRoot(camera) == m_active3DScene)
+ cameras.append(objectToVariant(camera));
+ }
+ }
+
+ if (cameras.isEmpty()) {
+ if (auto activeView = qobject_cast<QQuick3DViewport *>(m_active3DView)) {
+ if (auto camera = activeView->camera()) {
+ if (hasInstanceForObject(camera) && find3DSceneRoot(camera) == m_active3DScene)
+ cameras.append(objectToVariant(camera));
+ }
+ }
+ }
+
+ if (cameras.isEmpty()) {
+ const QList<ServerNodeInstance> allCameras = allCameraInstances();
+ for (const auto &camera : allCameras) {
+ if (find3DSceneRoot(camera) == m_active3DScene) {
+ cameras.append(objectToVariant(camera.internalObject()));
+ break;
+ }
+ }
+ }
+
+ return cameras;
+#endif
+}
+
void Qt5InformationNodeInstanceServer::changePropertyValues(const ChangeValuesCommand &command)
{
bool hasDynamicProperties = false;
@@ -2375,10 +2448,12 @@ void Qt5InformationNodeInstanceServer::view3DAction(const View3DActionCommand &c
QMetaObject::invokeMethod(m_editView3DData.rootItem, "fitToView");
break;
case View3DActionType::AlignCamerasToView:
- QMetaObject::invokeMethod(m_editView3DData.rootItem, "alignCamerasToView");
+ QMetaObject::invokeMethod(m_editView3DData.rootItem, "alignCamerasToView",
+ Q_ARG(QVariant, alignCameraList()));
break;
case View3DActionType::AlignViewToCamera:
- QMetaObject::invokeMethod(m_editView3DData.rootItem, "alignViewToCamera");
+ QMetaObject::invokeMethod(m_editView3DData.rootItem, "alignViewToCamera",
+ Q_ARG(QVariant, alignCameraList()));
break;
case View3DActionType::SelectionModeToggle:
updatedToolState.insert("selectionMode", command.isEnabled() ? 1 : 0);
diff --git a/src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.h b/src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.h
index c8b6c1c250..8d02b586c2 100644
--- a/src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.h
+++ b/src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.h
@@ -135,6 +135,7 @@ private:
void handleParticleSystemDeselected();
#endif
void setSceneEnvironmentColor(const PropertyValueContainer &container);
+ QVariantList alignCameraList() const;
RenderViewData m_editView3DData;
RenderViewData m_modelNode3DImageViewData;
@@ -172,6 +173,9 @@ private:
int m_need3DEditViewRender = 0;
QSet<QObject *> m_dynamicObjectConstructors;
+ // Current or previous camera selections for each scene
+ QHash<QObject *, QObjectList> m_selectedCameras; // key: scene root, value: camera node
+
struct PreviewData {
QString env;
QString envValue;
diff --git a/src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceserver.cpp b/src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceserver.cpp
index 74481d150f..e520079a5d 100644
--- a/src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceserver.cpp
+++ b/src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceserver.cpp
@@ -41,6 +41,14 @@
#include <QtQuick/private/qquickitem_p.h>
#endif
+#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 1)
+#include <QDir>
+#include <QFile>
+#include <QQuickGraphicsConfiguration>
+#include <QStandardPaths>
+#include <QTimer>
+#endif
+
namespace QmlDesigner {
Qt5NodeInstanceServer::Qt5NodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient)
@@ -90,6 +98,7 @@ void Qt5NodeInstanceServer::initializeView()
#else
m_viewData.renderControl = new QQuickRenderControl;
m_viewData.window = new QQuickWindow(m_viewData.renderControl);
+ setPipelineCacheConfig(m_viewData.window);
m_viewData.renderControl->initialize();
m_qmlEngine = new QQmlEngine;
#endif
@@ -160,6 +169,20 @@ void Qt5NodeInstanceServer::setupScene(const CreateSceneCommand &command)
setupInstances(command);
resizeCanvasToRootItem();
+
+#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 1)
+ if (!m_pipelineCacheLocation.isEmpty()) {
+ QString fileId = command.fileUrl.toLocalFile();
+ fileId.remove(':');
+ fileId.remove('/');
+ fileId.remove('.');
+ m_pipelineCacheFile = QStringLiteral("%1/%2").arg(m_pipelineCacheLocation, fileId);
+
+ QFile cacheFile(m_pipelineCacheFile);
+ if (cacheFile.open(QIODevice::ReadOnly))
+ m_pipelineCacheData = cacheFile.readAll();
+ }
+#endif
}
QList<QQuickItem*> subItems(QQuickItem *parentItem)
@@ -185,7 +208,61 @@ const QList<QQuickItem*> Qt5NodeInstanceServer::allItems() const
bool Qt5NodeInstanceServer::rootIsRenderable3DObject() const
{
return rootNodeInstance().isSubclassOf("QQuick3DNode")
- || rootNodeInstance().isSubclassOf("QQuick3DMaterial");
+ || rootNodeInstance().isSubclassOf("QQuick3DMaterial");
+}
+
+void Qt5NodeInstanceServer::savePipelineCacheData()
+{
+#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 1)
+ if (!m_viewData.rhi)
+ return;
+
+ QByteArray pipelineData = m_viewData.rhi->pipelineCacheData();
+
+ if (pipelineData.isEmpty())
+ return;
+
+ char count = 0;
+ if (!m_pipelineCacheData.isEmpty())
+ count = m_pipelineCacheData[m_pipelineCacheData.size() - 1];
+ pipelineData.append(++count);
+
+ const bool needWrite = m_pipelineCacheData.size() != pipelineData.size()
+ && !m_pipelineCacheFile.isEmpty();
+
+ if (needWrite) {
+ m_pipelineCacheData = pipelineData;
+
+ QTimer::singleShot(0, this, [this]() {
+ QFile cacheFile(m_pipelineCacheFile);
+
+ // Cache file can grow indefinitely, so let's just purge it every so often.
+ // The count is stored as the last char in the data.
+ char count = m_pipelineCacheData[m_pipelineCacheData.size() - 1];
+ if (count > 25)
+ cacheFile.remove();
+ else if (cacheFile.open(QIODevice::WriteOnly | QIODevice::Truncate))
+ cacheFile.write(m_pipelineCacheData);
+ });
+ }
+#endif
+}
+
+void Qt5NodeInstanceServer::setPipelineCacheConfig([[maybe_unused]] QQuickWindow *w)
+{
+#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 1)
+ // This dummy file is not actually used for cache as we manage cache save/load ourselves,
+ // but some file needs to be set to enable pipeline caching
+ const QString cachePath = QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
+ m_pipelineCacheLocation = QStringLiteral("%1/%2").arg(cachePath, "pipecache");
+ QDir(m_pipelineCacheLocation).mkpath(".");
+ const QString dummyCache = m_pipelineCacheLocation + "/dummycache";
+
+ QQuickGraphicsConfiguration config = w->graphicsConfiguration();
+ config.setPipelineCacheSaveFile(dummyCache);
+ config.setAutomaticPipelineCache(false);
+ w->setGraphicsConfiguration(config);
+#endif
}
bool Qt5NodeInstanceServer::initRhi([[maybe_unused]] RenderViewData &viewData)
@@ -204,6 +281,10 @@ bool Qt5NodeInstanceServer::initRhi([[maybe_unused]] RenderViewData &viewData)
qWarning() << __FUNCTION__ << "Rhi is null";
return false;
}
+#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 1)
+ if (!m_pipelineCacheData.isEmpty())
+ viewData.rhi->setPipelineCacheData(m_pipelineCacheData.left(m_pipelineCacheData.size() - 1));
+#endif
}
auto cleanRhiResources = [&viewData]() {
diff --git a/src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceserver.h b/src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceserver.h
index ccbcc5c1e3..b76e639897 100644
--- a/src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceserver.h
+++ b/src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceserver.h
@@ -59,6 +59,8 @@ protected:
void setupScene(const CreateSceneCommand &command) override;
const QList<QQuickItem*> allItems() const;
bool rootIsRenderable3DObject() const;
+ void savePipelineCacheData();
+ void setPipelineCacheConfig(QQuickWindow *w);
struct RenderViewData {
QPointer<QQuickWindow> window = nullptr;
@@ -80,6 +82,9 @@ protected:
private:
RenderViewData m_viewData;
+ QByteArray m_pipelineCacheData;
+ QString m_pipelineCacheLocation;
+ QString m_pipelineCacheFile;
std::unique_ptr<QQuickDesignerSupport> m_designerSupport;
QQmlEngine *m_qmlEngine = nullptr;
};
diff --git a/src/tools/qml2puppet/qmlprivategate/qmlprivategate.cpp b/src/tools/qml2puppet/qmlprivategate/qmlprivategate.cpp
index 7fd4e75dc2..a8c715c995 100644
--- a/src/tools/qml2puppet/qmlprivategate/qmlprivategate.cpp
+++ b/src/tools/qml2puppet/qmlprivategate/qmlprivategate.cpp
@@ -110,8 +110,8 @@ PropertyNameList allPropertyNamesInline(QObject *object,
inspectedObjects,
depth + 1));
}
- } else if (QQmlGadgetPtrWrapper *valueType
- = QQmlGadgetPtrWrapper::instance(qmlEngine(object), metaProperty.userType())) {
+ } else if (QQmlGadgetPtrWrapper *valueType = QQmlGadgetPtrWrapper::instance(
+ qmlEngine(object), metaProperty.typeId())) {
valueType->setValue(metaProperty.read(object));
propertyNameList.append(baseName
+ QQuickDesignerSupport::PropertyName(metaProperty.name()));
@@ -224,8 +224,7 @@ static QString qmlDesignerRCPath()
QVariant fixResourcePaths(const QVariant &value)
{
- if (value.type() == QVariant::Url)
- {
+ if (value.typeId() == QVariant::Url) {
const QUrl url = value.toUrl();
if (url.scheme() == QLatin1String("qrc")) {
const QString path = QLatin1String("qrc:") + url.path();
@@ -246,7 +245,7 @@ QVariant fixResourcePaths(const QVariant &value)
}
}
}
- if (value.type() == QVariant::String) {
+ if (value.typeId() == QVariant::String) {
const QString str = value.toString();
if (str.contains(QLatin1String("qrc:"))) {
if (!qmlDesignerRCPath().isEmpty()) {