aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThe Qt Project <gerrit-noreply@qt-project.org>2024-01-18 12:32:01 +0000
committerThe Qt Project <gerrit-noreply@qt-project.org>2024-01-18 12:32:01 +0000
commit5772a85751b905fa070f9c11fc930cb256c231c5 (patch)
treee93dd6cb9e9a0d340f0ebbc8e833f0b601492c70
parentd51e116ac4219f90ce8ca35e032f4387fe581a6f (diff)
parent399f7a1968c7d64580bdd209c4747a6979e07c93 (diff)
Merge "Merge remote-tracking branch 'origin/qds/dev'"
-rw-r--r--doc/qtdesignstudio/images/apply-effect-maker-effect.webpbin35166 -> 50768 bytes
-rw-r--r--doc/qtdesignstudio/images/figma-binding-reset.pngbin0 -> 368 bytes
-rw-r--r--doc/qtdesignstudio/images/qt-figma-bridge-settings.pngbin17958 -> 14428 bytes
-rw-r--r--doc/qtdesignstudio/images/qt-figma-bridge.pngbin8853 -> 9890 bytes
-rw-r--r--doc/qtdesignstudio/images/qt-sketch-bridge-settings.pngbin25614 -> 27738 bytes
-rw-r--r--doc/qtdesignstudio/images/qtcreator-workspace-attaching-views.webpbin38358 -> 90330 bytes
-rw-r--r--doc/qtdesignstudio/images/qtds-running-emulator.pngbin228819 -> 0 bytes
-rw-r--r--doc/qtdesignstudio/images/qtds-running-emulator.webpbin0 -> 148974 bytes
-rw-r--r--doc/qtdesignstudio/images/studio-qtquick-3d-default-material.webpbin13236 -> 46670 bytes
-rw-r--r--doc/qtdesignstudio/images/studio-qtquick-3d-material.webpbin35562 -> 93398 bytes
-rw-r--r--doc/qtdesignstudio/src/prototyping/qtquick-live-preview-android.qdoc2
-rw-r--r--doc/qtdesignstudio/src/qtbridge/qtbridge-figma-using.qdoc21
-rw-r--r--doc/qtdesignstudio/src/qtbridge/qtbridge-sketch-using.qdoc8
-rw-r--r--doc/qtdesignstudio/src/views/qtquick-designer.qdoc6
-rw-r--r--doc/qtdesignstudio/src/views/studio-workspaces.qdoc10
-rwxr-xr-xscripts/build.py7
-rwxr-xr-xscripts/build_plugin.py6
-rw-r--r--share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionDetailsEditDelegate.qml192
-rw-r--r--share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionDetailsToolbar.qml3
-rw-r--r--share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionDetailsView.qml194
-rw-r--r--share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionView.qml5
-rw-r--r--share/qtcreator/qmldesigner/collectionEditorQmlSource/ColorViewDelegate.qml282
-rw-r--r--share/qtcreator/qmldesigner/collectionEditorQmlSource/EditPropertyDialog.qml12
-rw-r--r--share/qtcreator/qmldesigner/collectionEditorQmlSource/ImportDialog.qml5
-rw-r--r--share/qtcreator/qmldesigner/collectionEditorQmlSource/NewCollectionDialog.qml7
-rw-r--r--share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibrary.qml7
-rw-r--r--share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryEffect.qml2
-rw-r--r--share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterial.qml2
-rw-r--r--share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexture.qml2
-rw-r--r--share/qtcreator/qmldesigner/contentLibraryQmlSource/UnimportBundleMaterialDialog.qml1
-rw-r--r--share/qtcreator/qmldesigner/edit3dQmlSource/BakeLightsProgressDialog.qml1
-rw-r--r--share/qtcreator/qmldesigner/edit3dQmlSource/BakeLightsSetupDialog.qml1
-rw-r--r--share/qtcreator/qmldesigner/edit3dQmlSource/SnapConfigurationDialog.qml1
-rw-r--r--share/qtcreator/qmldesigner/effectMakerQmlSources/BlurHelper.qml5
-rw-r--r--share/qtcreator/qmldesigner/effectMakerQmlSources/EffectCompositionNode.qml3
-rw-r--r--share/qtcreator/qmldesigner/effectMakerQmlSources/EffectCompositionNodeUniform.qml3
-rw-r--r--share/qtcreator/qmldesigner/effectMakerQmlSources/EffectMaker.qml4
-rw-r--r--share/qtcreator/qmldesigner/effectMakerQmlSources/EffectMakerPreview.qml5
-rw-r--r--share/qtcreator/qmldesigner/effectMakerQmlSources/EffectMakerTopBar.qml3
-rw-r--r--share/qtcreator/qmldesigner/effectMakerQmlSources/EffectNode.qml3
-rw-r--r--share/qtcreator/qmldesigner/effectMakerQmlSources/EffectNodesComboBox.qml3
-rw-r--r--share/qtcreator/qmldesigner/effectMakerQmlSources/PreviewImagesComboBox.qml3
-rw-r--r--share/qtcreator/qmldesigner/effectMakerQmlSources/SaveAsDialog.qml3
-rw-r--r--share/qtcreator/qmldesigner/effectMakerQmlSources/ValueBool.qml3
-rw-r--r--share/qtcreator/qmldesigner/effectMakerQmlSources/ValueColor.qml3
-rw-r--r--share/qtcreator/qmldesigner/effectMakerQmlSources/ValueDefine.qml3
-rw-r--r--share/qtcreator/qmldesigner/effectMakerQmlSources/ValueFloat.qml3
-rw-r--r--share/qtcreator/qmldesigner/effectMakerQmlSources/ValueImage.qml3
-rw-r--r--share/qtcreator/qmldesigner/effectMakerQmlSources/ValueInt.qml3
-rw-r--r--share/qtcreator/qmldesigner/effectMakerQmlSources/ValueVec2.qml3
-rw-r--r--share/qtcreator/qmldesigner/effectMakerQmlSources/ValueVec3.qml3
-rw-r--r--share/qtcreator/qmldesigner/effectMakerQmlSources/ValueVec4.qml3
-rw-r--r--share/qtcreator/qmldesigner/insight/Main.qml5
-rw-r--r--share/qtcreator/qmldesigner/itemLibraryQmlSources/AddModuleView.qml9
-rw-r--r--share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemDelegate.qml10
-rw-r--r--share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemsView.qml8
-rw-r--r--share/qtcreator/qmldesigner/materialBrowserQmlSource/ChooseMaterialProperty.qml1
-rw-r--r--share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml7
-rw-r--r--share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowserItemName.qml9
-rw-r--r--share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialItem.qml9
-rw-r--r--share/qtcreator/qmldesigner/materialBrowserQmlSource/TextureItem.qml1
-rw-r--r--share/qtcreator/qmldesigner/materialEditorQmlSources/EmptyMaterialEditorPane.qml5
-rw-r--r--share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorPane.qml3
-rw-r--r--share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorToolBar.qml9
-rw-r--r--share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorTopSection.qml7
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AnchorRow.qml12
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/AbstractButtonSection.qml9
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ButtonSection.qml9
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ButtonSpecifics.qml9
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ControlSpecifics.qml9
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/QtObjectPane.qml5
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/emptyPane.qml13
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick3D/Object3DPane.qml5
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ButtonRowButton.qml7
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml2
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditorPopup.qml4
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComponentSection.qml13
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExpressionTextField.qml11
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExtendedFunctionLogic.qml9
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPresetList.qml1
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPresetTabContent.qml13
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/IconButton.qml7
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/LineEdit.qml7
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/PropertyEditorPane.qml7
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/RoundedPanel.qml7
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ScrollView.qml2
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml11
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/UrlChooser.qml1
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/qmldir1
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ColorEditor.qml1
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/PopupDialog.qml2
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSpinBox.qml17
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SearchBox.qml3
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TopLevelComboBox.qml1
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/impl/ColorEditorPopup.qml1
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml2
-rw-r--r--share/qtcreator/qmldesigner/textureEditorQmlSource/EmptyTextureEditorPane.qml5
-rw-r--r--share/qtcreator/qmldesigner/textureEditorQmlSource/TextureEditorPane.qml3
-rw-r--r--share/qtcreator/qmldesigner/textureEditorQmlSource/TextureEditorToolBar.qml7
-rw-r--r--share/qtcreator/qmldesigner/toolbar/Main.qml8
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/BrandBar.qml64
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/CheckButton.ui.qml108
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/CustomDialog.qml42
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/CustomDialogButtonBox.qml25
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/CustomGrid.qml41
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/CustomScrollBar.qml98
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/CustomScrollView.qml25
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/DialogButton.qml89
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/DownloadButton.qml134
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/DownloadPanel.qml79
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/DownloadProgressBar.qml80
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/MainGridStack.qml166
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/MainScreen.qml318
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/PushButton.ui.qml108
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/RangeMapper.qml42
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/SocialButton.qml129
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/StringMapper.qml68
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/Tag.qml28
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/TagArea.qml43
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/TestControlPanel.qml153
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/ThumbnailDelegate.qml630
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/TourDialogButton.qml69
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/TourModel.qml73
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/TourProgressBar.qml41
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/TourRestartButton.qml84
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/TourThumbnailDelegate.qml164
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/TwirlButton.qml118
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/TwitterButton.qml125
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/WelcomePage.qml52
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/WelcomeScreen.qmlproject49
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/YoutubeButton.qml201
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/fonts/fonts.txt1
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/images/adding-assets.pngbin0 -> 50422 bytes
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/images/animation-2d.pngbin0 -> 38099 bytes
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/images/border-arc.pngbin0 -> 38012 bytes
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/images/complex-shapes.pngbin0 -> 35416 bytes
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/images/congratulations.pngbin0 -> 99531 bytes
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/images/connecting-components.pngbin0 -> 49204 bytes
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/images/ds.pngbin0 -> 10132 bytes
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/images/ellipse-pie.pngbin0 -> 38807 bytes
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/images/newThumbnail.pngbin0 -> 1799 bytes
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/images/noPreview.pngbin0 -> 8429 bytes
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/images/place_holder.pngbin0 -> 1841 bytes
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/images/sorting-components.pngbin0 -> 43563 bytes
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/images/states.pngbin0 -> 42497 bytes
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/images/thumbnailImage.pngbin0 -> 13760 bytes
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/images/thumbnail_test.pngbin0 -> 32580 bytes
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/images/top-toolbar.pngbin0 -> 40275 bytes
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/images/twitterDarkNormal.pngbin0 -> 1300 bytes
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/images/twitterHover.pngbin0 -> 1435 bytes
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/images/twitterLightNormal.pngbin0 -> 1099 bytes
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/images/welcome-page.pngbin0 -> 41619 bytes
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/images/workspaces.pngbin0 -> 48805 bytes
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/images/youtubeDarkHover.pngbin0 -> 2619 bytes
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/images/youtubeDarkNormal.pngbin0 -> 2826 bytes
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/images/youtubeLightHover.pngbin0 -> 3927 bytes
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/images/youtubeLightNormal.pngbin0 -> 2941 bytes
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/imports/UiTour/Highlight.ui.qml61
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/imports/UiTour/Slide.qml118
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/imports/UiTour/SlideNavButton.qml71
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/imports/UiTour/SlidePlayer.qml132
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/imports/UiTour/SlideShow.qml85
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/imports/UiTour/StrongHighlight.ui.qml107
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/imports/UiTour/gradientRect.webpbin0 -> 38420 bytes
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/imports/UiTour/qmldir6
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/imports/WelcomeScreen/Constants.qml189
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/imports/WelcomeScreen/designer/plugin.metainfo13
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/imports/WelcomeScreen/qmldir2
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/main.qml22
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/main.qml.qml10
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/mockData/ExampleCheckout/FileDownloader.qml16
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/mockData/ExampleCheckout/FileExtractor.qml21
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/mockData/ExampleCheckout/qmldir2
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/mockData/projectmodel/ProjectModel.qml117
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/mockData/projectmodel/qmldir1
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/mockData/usagestatistics/UsageStatisticModel.qml8
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/mockData/usagestatistics/qmldir1
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/qtquickcontrols2.conf2
-rw-r--r--share/qtcreator/qmldesigner/workspacePresets/Advanced-3D.wrk2
-rw-r--r--share/qtcreator/qmldesigner/workspacePresets/Animation-2D.wrk2
-rw-r--r--share/qtcreator/qmldesigner/workspacePresets/Animation-3D.wrk2
-rw-r--r--share/qtcreator/qmldesigner/workspacePresets/Basic.wrk2
-rw-r--r--share/qtcreator/qmldesigner/workspacePresets/Code.wrk2
-rw-r--r--share/qtcreator/qmldesigner/workspacePresets/Essentials-3D.wrk2
-rw-r--r--share/qtcreator/qmldesigner/workspacePresets/Essentials.wrk2
-rw-r--r--share/qtcreator/qmldesigner/workspacePresets/UX-Design.wrk2
-rw-r--r--share/qtcreator/qmldesigner/workspacePresets/Views-All.wrk2
-rw-r--r--src/libs/advanceddockingsystem/dockmanager.cpp62
-rw-r--r--src/libs/advanceddockingsystem/dockmanager.h8
-rw-r--r--src/libs/advanceddockingsystem/workspace.cpp18
-rw-r--r--src/libs/advanceddockingsystem/workspace.h4
-rw-r--r--src/libs/advanceddockingsystem/workspacemodel.cpp6
-rw-r--r--src/libs/advanceddockingsystem/workspacemodel.h2
-rw-r--r--src/libs/qmljs/qmljsinterpreter.h5
-rw-r--r--src/libs/qmljs/qmljslink.cpp1
-rw-r--r--src/plugins/clangformat/clangformatbaseindenter.cpp1
-rw-r--r--src/plugins/cppeditor/cpptoolsreuse.cpp1
-rw-r--r--src/plugins/effectmakernew/compositionnode.cpp3
-rw-r--r--src/plugins/effectmakernew/effectmakermodel.cpp129
-rw-r--r--src/plugins/effectmakernew/effectmakermodel.h2
-rw-r--r--src/plugins/mcusupport/mcusupportimportprovider.cpp25
-rw-r--r--src/plugins/mcusupport/mcusupportimportprovider.h3
-rw-r--r--src/plugins/projectexplorer/abi.cpp19
-rw-r--r--src/plugins/qmldesigner/CMakeLists.txt1
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectiondetails.cpp44
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectiondetails.h6
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectiondetailsmodel.cpp164
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectiondetailsmodel.h6
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectiondetailssortfiltermodel.cpp4
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectioneditorconstants.h4
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.cpp211
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.h16
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectionimporttools.cpp113
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectionimporttools.h18
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectionlistmodel.cpp9
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectionsourcemodel.cpp47
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectionsourcemodel.h2
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectionview.cpp15
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectionwidget.cpp21
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/datastoremodelnode.cpp207
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/datastoremodelnode.h9
-rw-r--r--src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp36
-rw-r--r--src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp2
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp18
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/propertytreemodel.cpp33
-rw-r--r--src/plugins/qmldesigner/components/connectioneditor/propertytreemodel.h13
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp23
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditoritem.h5
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditorview.cpp30
-rw-r--r--src/plugins/qmldesigner/components/formeditor/formeditorview.h3
-rw-r--r--src/plugins/qmldesigner/components/toolbar/toolbarbackend.cpp14
-rw-r--r--src/plugins/qmldesigner/components/toolbar/toolbarbackend.h3
-rw-r--r--src/plugins/qmldesigner/designercore/include/qmlitemnode.h2
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp20
-rw-r--r--src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.cpp6
-rw-r--r--src/plugins/qmldesigner/designmodewidget.cpp35
-rw-r--r--src/plugins/qmldesigner/designmodewidget.h1
-rw-r--r--src/plugins/qmlprojectmanager/qmlproject.cpp13
-rw-r--r--src/plugins/qmlprojectmanager/qmlproject.h2
-rw-r--r--src/plugins/qtsupport/baseqtversion.cpp9
-rw-r--r--src/plugins/studiowelcome/studiowelcomeplugin.cpp3
242 files changed, 6205 insertions, 849 deletions
diff --git a/doc/qtdesignstudio/images/apply-effect-maker-effect.webp b/doc/qtdesignstudio/images/apply-effect-maker-effect.webp
index 64c89bf92b..732a54eb8a 100644
--- a/doc/qtdesignstudio/images/apply-effect-maker-effect.webp
+++ b/doc/qtdesignstudio/images/apply-effect-maker-effect.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/figma-binding-reset.png b/doc/qtdesignstudio/images/figma-binding-reset.png
new file mode 100644
index 0000000000..55fed02207
--- /dev/null
+++ b/doc/qtdesignstudio/images/figma-binding-reset.png
Binary files differ
diff --git a/doc/qtdesignstudio/images/qt-figma-bridge-settings.png b/doc/qtdesignstudio/images/qt-figma-bridge-settings.png
index 0e91ceb5c8..e19eb3cd3a 100644
--- a/doc/qtdesignstudio/images/qt-figma-bridge-settings.png
+++ b/doc/qtdesignstudio/images/qt-figma-bridge-settings.png
Binary files differ
diff --git a/doc/qtdesignstudio/images/qt-figma-bridge.png b/doc/qtdesignstudio/images/qt-figma-bridge.png
index 9e2f9d16a9..1233ed03d5 100644
--- a/doc/qtdesignstudio/images/qt-figma-bridge.png
+++ b/doc/qtdesignstudio/images/qt-figma-bridge.png
Binary files differ
diff --git a/doc/qtdesignstudio/images/qt-sketch-bridge-settings.png b/doc/qtdesignstudio/images/qt-sketch-bridge-settings.png
index 9ce32618b9..60ab727607 100644
--- a/doc/qtdesignstudio/images/qt-sketch-bridge-settings.png
+++ b/doc/qtdesignstudio/images/qt-sketch-bridge-settings.png
Binary files differ
diff --git a/doc/qtdesignstudio/images/qtcreator-workspace-attaching-views.webp b/doc/qtdesignstudio/images/qtcreator-workspace-attaching-views.webp
index ee6d6f54aa..130ee78bb7 100644
--- a/doc/qtdesignstudio/images/qtcreator-workspace-attaching-views.webp
+++ b/doc/qtdesignstudio/images/qtcreator-workspace-attaching-views.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/qtds-running-emulator.png b/doc/qtdesignstudio/images/qtds-running-emulator.png
deleted file mode 100644
index b8d7470166..0000000000
--- a/doc/qtdesignstudio/images/qtds-running-emulator.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtdesignstudio/images/qtds-running-emulator.webp b/doc/qtdesignstudio/images/qtds-running-emulator.webp
new file mode 100644
index 0000000000..38fb172747
--- /dev/null
+++ b/doc/qtdesignstudio/images/qtds-running-emulator.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/studio-qtquick-3d-default-material.webp b/doc/qtdesignstudio/images/studio-qtquick-3d-default-material.webp
index 0306408df1..4b7bc1a20c 100644
--- a/doc/qtdesignstudio/images/studio-qtquick-3d-default-material.webp
+++ b/doc/qtdesignstudio/images/studio-qtquick-3d-default-material.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/studio-qtquick-3d-material.webp b/doc/qtdesignstudio/images/studio-qtquick-3d-material.webp
index 1c5b1cecf2..43c4303cf8 100644
--- a/doc/qtdesignstudio/images/studio-qtquick-3d-material.webp
+++ b/doc/qtdesignstudio/images/studio-qtquick-3d-material.webp
Binary files differ
diff --git a/doc/qtdesignstudio/src/prototyping/qtquick-live-preview-android.qdoc b/doc/qtdesignstudio/src/prototyping/qtquick-live-preview-android.qdoc
index 69840eb0b2..2012baf1bd 100644
--- a/doc/qtdesignstudio/src/prototyping/qtquick-live-preview-android.qdoc
+++ b/doc/qtdesignstudio/src/prototyping/qtquick-live-preview-android.qdoc
@@ -162,7 +162,7 @@
Now the emulator runs, the qtdesignviewer APK delivered with the \QDS installation
is uploaded, and the project is uploaded and shown in the emulator.
- \image qtds-running-emulator.png
+ \image qtds-running-emulator.webp
Note the following:
\list
diff --git a/doc/qtdesignstudio/src/qtbridge/qtbridge-figma-using.qdoc b/doc/qtdesignstudio/src/qtbridge/qtbridge-figma-using.qdoc
index 5dd5f6d8bd..8b93a1e268 100644
--- a/doc/qtdesignstudio/src/qtbridge/qtbridge-figma-using.qdoc
+++ b/doc/qtdesignstudio/src/qtbridge/qtbridge-figma-using.qdoc
@@ -124,10 +124,14 @@
\li Purpose
\row
\li \uicontrol ID
- \li \QBF automatically proposes identifiers for all groups and layers.
+ \li \QBF automatically derives identifiers for all groups and layers
+ from layer name.
You can change them in this field. Use unique and descriptive IDs
to avoid duplicate IDs when the layer and the respective artwork
are imported into \QDS.
+ \note Once the ID is edited, the automatic assignment of ID from
+ layer name stops for this layer. Use \inlineimage figma-binding-reset.png
+ button next to \uicontrol ID to reset the ID back to automatic assignment.
\row
\li \uicontrol {Export as}
\li Determines how to export the group or layer:
@@ -146,6 +150,8 @@
into one component.
\li \uicontrol Skipped completely skips the selected layer.
\endlist
+ \note Use \inlineimage figma-binding-reset.png button next to
+ \uicontrol {Export as} to reset to default value.
\row
\li \uicontrol {Custom Component Type}
\li Determines the \l{Component Types}{component type} to morph this
@@ -205,13 +211,8 @@
\li Exports the component generated from this layer as an alias in the
parent component.
\row
- \li \uicontrol Visible
- \li Determines the visibility of the layer.
- \row
- \li \uicontrol Clip
- \li Enables clipping in the component generated from the layer. The
- generated component will clip its own painting, as well as the
- painting of its children, to its bounding rectangle.
+ \li \uicontrol {Start Screen}
+ \li Sets the component to be the starting component in \QDS project.
\endtable
\section2 Settings
@@ -240,6 +241,10 @@
\li Exports vectors as components of the type \l{SVG Path Item} from the
Qt Quick Studio Components module.
\row
+ \li \uicontrol {Create page hierarchy}
+ \li Organize the generated UI in \QDS under the directory named after the
+ parent page of the respective component.
+ \row
\li \uicontrol {Reset plugin data}
\li Resets all settings for all layers and groups (also in the
\uicontrol Home tab) to default values. This means that you
diff --git a/doc/qtdesignstudio/src/qtbridge/qtbridge-sketch-using.qdoc b/doc/qtdesignstudio/src/qtbridge/qtbridge-sketch-using.qdoc
index 27b1e0e8b9..06f23a2996 100644
--- a/doc/qtdesignstudio/src/qtbridge/qtbridge-sketch-using.qdoc
+++ b/doc/qtdesignstudio/src/qtbridge/qtbridge-sketch-using.qdoc
@@ -278,6 +278,14 @@
\note The factor is independent of the asset scale settings, that is, 2x assets shall
have a size of 5x when a scale factor of 2.5 is selected.
+ \section1 Organizing
+
+ Select the \uicontrol {Organize output in pages} to organize the generated UI inside
+ the directory named after the parent page of the respective component. The default behavior
+ is to generate UI inside the directory selected during import in \QDS.
+ \note Using invalid characters or reservered file names for the page name will result into
+ imports errors as page name is used for the directory name to organize the UI files in \QDS .
+
\section1 Exporting Library Symbols
\QBSK can handle symbols used from a local library. Before you use \QBSK to export a document
diff --git a/doc/qtdesignstudio/src/views/qtquick-designer.qdoc b/doc/qtdesignstudio/src/views/qtquick-designer.qdoc
index dbf07849f0..9f706ed014 100644
--- a/doc/qtdesignstudio/src/views/qtquick-designer.qdoc
+++ b/doc/qtdesignstudio/src/views/qtquick-designer.qdoc
@@ -225,6 +225,12 @@
\li
\li \l{Managing Workspaces}
\row
+ \li \inlineimage icons/lockoff.png
+ / \inlineimage icons/lockon.png
+ \li Toggles the views to locked or movable in \QDS.
+ \li
+ \li \l{Managing Workspaces}
+ \row
\li \uicontrol Share
\li Shares the application online using Qt Design Viewer.
\li
diff --git a/doc/qtdesignstudio/src/views/studio-workspaces.qdoc b/doc/qtdesignstudio/src/views/studio-workspaces.qdoc
index 35fcf8418f..2b6d2e2e27 100644
--- a/doc/qtdesignstudio/src/views/studio-workspaces.qdoc
+++ b/doc/qtdesignstudio/src/views/studio-workspaces.qdoc
@@ -14,10 +14,11 @@
To detach views:
\list
+ \li Toggle \inlineimage icons/lockon.png
+ to \inlineimage icons/lockoff.png
+ at the top toolbar.
\li Double-click the title bar of the view.
\li Start dragging the view to another position.
- \li Select the \inlineimage icons/detach-group-icon.png
- (\uicontrol {Detach Group}) button.
\endlist
You can move detached views or groups of views anywhere on the screen.
@@ -32,6 +33,11 @@
To open closed views, select \uicontrol View > \uicontrol Views.
+ \note To lock all views, toggle
+ \inlineimage icons/lockoff.png
+ to \inlineimage icons/lockon.png
+ at the top toolbar.
+
\section1 Saving Workspaces
The changes you make to a workspace are saved when you exit \QDS.
diff --git a/scripts/build.py b/scripts/build.py
index 6cd795a744..66d5d25d43 100755
--- a/scripts/build.py
+++ b/scripts/build.py
@@ -60,7 +60,8 @@ def get_arguments():
parser.add_argument('--no-cdb',
help='Skip cdbextension and the python dependency packaging step (Windows)',
action='store_true', default=(not common.is_windows_platform()))
- parser.add_argument('--no-qbs', help='Skip building Qbs as part of Qt Creator', action='store_true', default=False);
+ parser.add_argument('--no-qbs', help='Skip building Qbs as part of Qt Creator',
+ action='store_true', default=False);
parser.add_argument('--no-docs', help='Skip documentation generation',
action='store_true', default=False)
parser.add_argument('--no-build-date', help='Does not show build date in about dialog, for reproducible builds',
@@ -75,6 +76,8 @@ def get_arguments():
action='store_true', default=False)
parser.add_argument('--with-cpack', help='Create packages with cpack',
action='store_true', default=False)
+ parser.add_argument('--with-sdk-tool', help='Builds a internal sdk-tool (not standalone) which is used in Qt Design Studio builds',
+ action='store_true', default=False)
parser.add_argument('--add-path', help='Prepends a CMAKE_PREFIX_PATH to the build',
action='append', dest='prefix_paths', default=[])
parser.add_argument('--add-module-path', help='Prepends a CMAKE_MODULE_PATH to the build',
@@ -171,7 +174,7 @@ def build_qtcreator(args, paths):
'-DWITH_DOCS=' + cmake_option(not args.no_docs),
'-DBUILD_QBS=' + cmake_option(build_qbs),
'-DBUILD_DEVELOPER_DOCS=' + cmake_option(not args.no_docs),
- '-DBUILD_EXECUTABLE_SDKTOOL=OFF',
+ '-DBUILD_EXECUTABLE_SDKTOOL=' + cmake_option(args.with_sdk_tool),
'-DQTC_FORCE_XCB=ON',
'-DWITH_TESTS=' + cmake_option(args.with_tests)]
cmake_args += common_cmake_arguments(args)
diff --git a/scripts/build_plugin.py b/scripts/build_plugin.py
index 4f4ddfdcb0..9469fc5dfe 100755
--- a/scripts/build_plugin.py
+++ b/scripts/build_plugin.py
@@ -147,15 +147,15 @@ def package(args, paths):
if common.is_windows_platform() and args.sign_command:
command = shlex.split(args.sign_command)
common.check_print_call(command + [paths.install])
- common.check_print_call(['7z', 'a', '-mmt2', os.path.join(paths.result, args.name + '.7z'), '*'],
+ common.check_print_call(['7z', 'a', '-mmt' + args.zip_threads, os.path.join(paths.result, args.name + '.7z'), '*'],
paths.install)
if os.path.exists(paths.dev_install): # some plugins might not provide anything in Devel
- common.check_print_call(['7z', 'a', '-mmt2',
+ common.check_print_call(['7z', 'a', '-mmt' + args.zip_threads,
os.path.join(paths.result, args.name + '_dev.7z'), '*'],
paths.dev_install)
# check for existence - the DebugInfo install target doesn't work for telemetry plugin
if args.with_debug_info and os.path.exists(paths.debug_install):
- common.check_print_call(['7z', 'a', '-mmt2',
+ common.check_print_call(['7z', 'a', '-mmt' + args.zip_threads,
os.path.join(paths.result, args.name + '-debug.7z'), '*'],
paths.debug_install)
if common.is_mac_platform() and common.codesign_call():
diff --git a/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionDetailsEditDelegate.qml b/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionDetailsEditDelegate.qml
index 44058419be..e368bb0933 100644
--- a/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionDetailsEditDelegate.qml
+++ b/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionDetailsEditDelegate.qml
@@ -3,7 +3,6 @@
import QtQuick
import CollectionDetails 1.0 as CollectionDetails
-import HelperWidgets 2.0 as HelperWidgets
import StudioControls 1.0 as StudioControls
import StudioHelpers as StudioHelpers
import StudioTheme 1.0 as StudioTheme
@@ -11,119 +10,106 @@ import QtQuick.Templates as T
Item {
id: root
- required property var columnType
- property var __modifier : textEditor
- property bool __changesAccepted: true
+ required property var columnType
TableView.onCommit: {
- if (root.__changesAccepted)
- edit = __modifier.editor.editValue
- }
-
- Component.onCompleted: {
- __changesAccepted = true
- if (edit && edit !== "")
- root.__modifier.editor.editValue = edit
+ if (editorLoader.changesAccepted && edit !== editorLoader.acceptedValue)
+ edit = editorLoader.acceptedValue
}
onActiveFocusChanged: {
- if (root.activeFocus)
- root.__modifier.editor.forceActiveFocus()
- }
-
- Connections {
- id: modifierFocusConnection
-
- target: root.__modifier.editor
-
- function onActiveFocusChanged() {
- if (!modifierFocusConnection.target.activeFocus)
- root.TableView.commit()
+ if (root.activeFocus && !editorLoader.triggered && editorLoader.item) {
+ editorLoader.triggered = true
+ editorLoader.item.open()
}
+
+ // active focus should be checked again, because it might be affected by editorLoader.item
+ if (root.activeFocus && editorLoader.editor)
+ editorLoader.editor.forceActiveFocus()
}
- EditorPopup {
- id: textEditor
+ Loader {
+ id: editorLoader
- editor: textField
+ active: true
- StudioControls.TextField {
- id: textField
+ property var editor: editorLoader.item ? editorLoader.item.editor : null
+ property var editValue: editorLoader.editor ? editorLoader.editor.editValue : null
+ property var acceptedValue: null
+ property bool changesAccepted: true
+ property bool triggered: false
- property alias editValue: textField.text
+ Connections {
+ id: modifierFocusConnection
- actionIndicator.visible: false
- translationIndicatorVisible: false
+ target: editorLoader.editor
+ enabled: editorLoader.item !== undefined
- onRejected: root.__changesAccepted = false
+ function onActiveFocusChanged() {
+ if (!modifierFocusConnection.target.activeFocus) {
+ editorLoader.acceptedValue = editorLoader.editValue
+ root.TableView.commit()
+ }
+ }
}
- }
- EditorPopup {
- id: numberEditor
+ Component {
+ id: textEditor
- editor: numberField
+ EditorPopup {
+ editor: textField
- StudioControls.RealSpinBox {
- id: numberField
+ StudioControls.TextField {
+ id: textField
- property alias editValue: numberField.realValue
+ property alias editValue: textField.text
- actionIndicator.visible: false
- realFrom: -9e9
- realTo: 9e9
- realStepSize: 1.0
- decimals: 6
- }
- }
+ actionIndicator.visible: false
+ translationIndicatorVisible: false
- EditorPopup {
- id: boolEditor
+ onRejected: editorLoader.changesAccepted = false
+ }
+ }
+ }
- editor: boolField
+ Component {
+ id: numberEditor
- StudioControls.CheckBox {
- id: boolField
+ EditorPopup {
- property alias editValue: boolField.checked
+ editor: numberField
- actionIndicatorVisible: false
- }
- }
+ StudioControls.RealSpinBox {
+ id: numberField
- EditorPopup {
- id: colorEditor
+ property alias editValue: numberField.realValue
- editor: colorPicker
-
- implicitHeight: colorPicker.height + topPadding + bottomPadding
- implicitWidth: colorPicker.width + leftPadding + rightPadding
- padding: 8
-
- StudioHelpers.ColorBackend {
- id: colorBackend
+ actionIndicator.visible: false
+ realFrom: -9e9
+ realTo: 9e9
+ realStepSize: 1.0
+ decimals: 6
+ trailingZeroes: false
+ }
+ }
}
- StudioControls.ColorEditorPopup {
- id: colorPicker
+ Component {
+ id: boolEditor
- property alias editValue: colorBackend.color
- color: colorBackend.color
+ EditorPopup {
- width: 200
+ editor: boolField
- Keys.onEnterPressed: colorPicker.focus = false
+ StudioControls.CheckBox {
+ id: boolField
- onActivateColor: function(color) {
- colorBackend.activateColor(color)
- }
- }
+ property alias editValue: boolField.checked
- background: Rectangle {
- color: StudioTheme.Values.themeControlBackgroundInteraction
- border.color: StudioTheme.Values.themeInteraction
- border.width: StudioTheme.Values.border
+ actionIndicatorVisible: false
+ }
+ }
}
}
@@ -135,7 +121,7 @@ Item {
implicitHeight: contentHeight
implicitWidth: contentWidth
- enabled: visible
+ focus: true
visible: false
Connections {
@@ -144,6 +130,8 @@ Item {
function onActiveFocusChanged() {
if (!editorPopup.editor.activeFocus)
editorPopup.close()
+ else if (edit)
+ editorPopup.editor.editValue = edit
}
}
@@ -151,7 +139,7 @@ Item {
target: editorPopup.editor.Keys
function onEscapePressed() {
- root.__changesAccepted = false
+ editorLoader.changesAccepted = false
editorPopup.close()
}
}
@@ -165,14 +153,8 @@ Item {
&& columnType !== CollectionDetails.DataType.Number
PropertyChanges {
- target: root
- __modifier: textEditor
- }
-
- PropertyChanges {
- target: textEditor
- visible: true
- focus: true
+ target: editorLoader
+ sourceComponent: textEditor
}
},
State {
@@ -180,14 +162,8 @@ Item {
when: columnType === CollectionDetails.DataType.Number
PropertyChanges {
- target: root
- __modifier: numberEditor
- }
-
- PropertyChanges {
- target: numberEditor
- visible: true
- focus: true
+ target: editorLoader
+ sourceComponent: numberEditor
}
},
State {
@@ -195,14 +171,8 @@ Item {
when: columnType === CollectionDetails.DataType.Boolean
PropertyChanges {
- target: root
- __modifier: boolEditor
- }
-
- PropertyChanges {
- target: boolEditor
- visible: true
- focus: true
+ target: editorLoader
+ sourceComponent: boolEditor
}
},
State {
@@ -210,14 +180,8 @@ Item {
when: columnType === CollectionDetails.DataType.Color
PropertyChanges {
- target: root
- __modifier: colorEditor
- }
-
- PropertyChanges {
- target: colorEditor
- visible: true
- focus: true
+ target: editorLoader
+ sourceComponent: null
}
}
]
diff --git a/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionDetailsToolbar.qml b/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionDetailsToolbar.qml
index 3e268d10f4..da13f62db0 100644
--- a/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionDetailsToolbar.qml
+++ b/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionDetailsToolbar.qml
@@ -102,7 +102,7 @@ Item {
icon: StudioTheme.Constants.save_medium
tooltip: qsTr("Save changes")
enabled: root.model.collectionName !== ""
- onClicked: root.model.saveCurrentCollection()
+ onClicked: root.model.saveDataStoreCollections()
}
IconButton {
@@ -114,7 +114,6 @@ Item {
}
}
-
PlatformWidgets.FileDialog {
id: fileDialog
diff --git a/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionDetailsView.qml b/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionDetailsView.qml
index e208553a4c..598ed56229 100644
--- a/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionDetailsView.qml
+++ b/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionDetailsView.qml
@@ -6,8 +6,8 @@ import QtQuick.Controls
import QtQuick.Layouts
import CollectionDetails 1.0 as CollectionDetails
import HelperWidgets 2.0 as HelperWidgets
-import StudioTheme 1.0 as StudioTheme
import StudioControls 1.0 as StudioControls
+import StudioTheme 1.0 as StudioTheme
Rectangle {
id: root
@@ -18,7 +18,6 @@ Rectangle {
implicitWidth: 300
implicitHeight: 400
-
color: StudioTheme.Values.themeControlBackground
ColumnLayout {
@@ -114,14 +113,17 @@ Rectangle {
color: StudioTheme.Values.themeControlBackgroundInteraction
MouseArea {
+ id: topHeaderMouseArea
+
anchors.fill: parent
anchors.margins: 5
acceptedButtons: Qt.LeftButton | Qt.RightButton
+ hoverEnabled: true
onClicked: (mouse) => {
tableView.model.selectColumn(index)
if (mouse.button === Qt.RightButton) {
- let posX = index === root.model.columnCount() - 1 ? parent.width - editProperyDialog.width : 0
+ let posX = index === root.model.columnCount() - 1 ? parent.width - editPropertyDialog.width : 0
headerMenu.clickedHeaderIndex = index
headerMenu.dialogPos = parent.mapToGlobal(posX, parent.height)
@@ -130,9 +132,17 @@ Rectangle {
}
}
- HelperWidgets.ToolTipArea {
- anchors.fill: parent
- text: root.model.propertyType(index)
+ ToolTip {
+ id: topHeaderToolTip
+
+ property bool expectedToBeShown: topHeaderMouseArea.containsMouse
+ visible: expectedToBeShown && text !== ""
+ delay: 1000
+
+ onExpectedToBeShownChanged: {
+ if (expectedToBeShown)
+ text = root.model.propertyType(index)
+ }
}
}
@@ -148,8 +158,8 @@ Rectangle {
StudioControls.MenuItem {
text: qsTr("Edit")
- onTriggered: editProperyDialog.openDialog(headerMenu.clickedHeaderIndex,
- headerMenu.dialogPos)
+ onTriggered: editPropertyDialog.openDialog(headerMenu.clickedHeaderIndex,
+ headerMenu.dialogPos)
}
StudioControls.MenuItem {
@@ -206,11 +216,22 @@ Rectangle {
delegate: Rectangle {
id: itemCell
+
+ clip: true
implicitWidth: 100
- implicitHeight: itemText.height
- border.color: dataTypeWarning !== CollectionDetails.Warning.None ?
- StudioTheme.Values.themeWarning : StudioTheme.Values.themeControlBackgroundInteraction
+ implicitHeight: StudioTheme.Values.baseHeight
+ color: itemSelected ? StudioTheme.Values.themeControlBackgroundInteraction
+ : StudioTheme.Values.themeControlBackground
border.width: 1
+ border.color: {
+ if (dataTypeWarning !== CollectionDetails.Warning.None)
+ return StudioTheme.Values.themeWarning
+
+ if (itemSelected)
+ return StudioTheme.Values.themeControlOutlineInteraction
+
+ return StudioTheme.Values.themeControlBackgroundInteraction
+ }
HelperWidgets.ToolTipArea {
anchors.fill: parent
@@ -220,59 +241,125 @@ Rectangle {
acceptedButtons: Qt.NoButton
}
- Text {
- id: itemText
-
- text: display
- color: StudioTheme.Values.themePlaceholderTextColorInteraction
- width: parent.width
- leftPadding: 5
- topPadding: 3
- bottomPadding: 3
- font.pixelSize: StudioTheme.Values.baseFontSize
- horizontalAlignment: Text.AlignLeft
- verticalAlignment: Text.AlignVCenter
- elide: Text.ElideRight
+ MouseArea {
+ anchors.fill: parent
+ acceptedButtons: Qt.RightButton
+ onClicked: (mouse) => {
+ let row = index % tableView.model.rowCount()
+
+ tableView.model.selectRow(row)
+ cellContextMenu.popup()
+ }
+ }
+
+ Loader {
+ id: cellContentLoader
+
+ property int cellColumnType: columnType ? columnType : 0
+
+ Component {
+ id: cellText
+
+ Text {
+ text: display
+ color: itemSelected ? StudioTheme.Values.themeInteraction
+ : StudioTheme.Values.themePlaceholderTextColorInteraction
+ leftPadding: 5
+ topPadding: 3
+ bottomPadding: 3
+ font.pixelSize: StudioTheme.Values.baseFontSize
+ horizontalAlignment: Text.AlignLeft
+ verticalAlignment: Text.AlignVCenter
+ elide: Text.ElideRight
+ }
+ }
+
+ Component {
+ id: colorEditorComponent
+
+ ColorViewDelegate {}
+ }
+
+ function resetSource() {
+ if (columnType === CollectionDetails.DataType.Color)
+ cellContentLoader.sourceComponent = colorEditorComponent
+ else
+ cellContentLoader.sourceComponent = cellText
+ }
+
+ Component.onCompleted: resetSource()
+ onCellColumnTypeChanged: resetSource()
}
TableView.editDelegate: CollectionDetailsEditDelegate {
anchors {
- top: itemText.top
- left: itemText.left
+ top: itemCell.top
+ left: itemCell.left
}
}
- states: [
- State {
- name: "default"
- when: !itemSelected
+ StudioControls.Menu {
+ id: cellContextMenu
- PropertyChanges {
- target: itemCell
- color: StudioTheme.Values.themeControlBackground
- }
+ width: 140
+
+ StudioControls.MenuItem {
+ HelperWidgets.IconLabel {
+ icon: StudioTheme.Constants.addrowabove_medium
+
+ anchors.left: parent.left
+ anchors.leftMargin: 10
+ anchors.verticalCenter: parent.verticalCenter
- PropertyChanges {
- target: itemText
- color: StudioTheme.Values.themePlaceholderTextColorInteraction
+ Text {
+ text: qsTr("Add row above")
+ color: StudioTheme.Values.themeTextColor
+ anchors.left: parent.right
+ anchors.leftMargin: 10
+ }
}
- },
- State {
- name: "selected"
- when: itemSelected
-
- PropertyChanges {
- target: itemCell
- color: StudioTheme.Values.themeControlBackgroundInteraction
- border.color: StudioTheme.Values.themeControlBackground
+
+ onTriggered: root.model.insertRow(root.model.selectedRow)
+ }
+
+ StudioControls.MenuItem {
+ HelperWidgets.IconLabel {
+ icon: StudioTheme.Constants.addrowabove_medium
+
+ anchors.left: parent.left
+ anchors.leftMargin: 10
+ anchors.verticalCenter: parent.verticalCenter
+
+ Text {
+ text: qsTr("Add row below")
+ color: StudioTheme.Values.themeTextColor
+ anchors.left: parent.right
+ anchors.leftMargin: 10
+ }
}
- PropertyChanges {
- target: itemText
- color: StudioTheme.Values.themeInteraction
+ onTriggered: root.model.insertRow(root.model.selectedRow + 1)
+ }
+
+ StudioControls.MenuItem {
+ HelperWidgets.IconLabel {
+ icon: StudioTheme.Constants.addrowabove_medium
+
+ anchors.left: parent.left
+ anchors.leftMargin: 10
+ anchors.verticalCenter: parent.verticalCenter
+
+ Text {
+ text: qsTr("Delete this row")
+ color: StudioTheme.Values.themeTextColor
+ anchors.left: parent.right
+ anchors.leftMargin: 10
+ }
}
+
+ onTriggered: root.model.removeRows(root.model.selectedRow, 1)
}
- ]
+ }
}
}
@@ -388,10 +475,15 @@ Rectangle {
}
EditPropertyDialog {
- id: editProperyDialog
+ id: editPropertyDialog
model: root.model
}
+ Connections {
+ target: root.parent
+ onIsHorizontalChanged: editPropertyDialog.close()
+ }
+
StudioControls.Dialog {
id: deleteColumnDialog
diff --git a/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionView.qml b/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionView.qml
index 32f71cc231..a53453ac49 100644
--- a/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionView.qml
+++ b/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionView.qml
@@ -4,9 +4,8 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
-import QtQuickDesignerTheme 1.0
-import HelperWidgets 2.0 as HelperWidgets
-import StudioTheme 1.0 as StudioTheme
+import HelperWidgets as HelperWidgets
+import StudioTheme as StudioTheme
import CollectionEditorBackend
Item {
diff --git a/share/qtcreator/qmldesigner/collectionEditorQmlSource/ColorViewDelegate.qml b/share/qtcreator/qmldesigner/collectionEditorQmlSource/ColorViewDelegate.qml
new file mode 100644
index 0000000000..1414a2dd3a
--- /dev/null
+++ b/share/qtcreator/qmldesigner/collectionEditorQmlSource/ColorViewDelegate.qml
@@ -0,0 +1,282 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Shapes
+import QtQuick.Templates as T
+import HelperWidgets 2.0 as HelperWidgets
+import StudioTheme as StudioTheme
+import StudioControls as StudioControls
+import QtQuickDesignerTheme
+import QtQuickDesignerColorPalette
+
+Row {
+ id: colorEditor
+
+ property color color
+ property bool supportGradient: false
+ readonly property color __editColor: edit
+
+ property variant value: {
+ if (!edit)
+ return "white" // default color for Rectangle
+
+ if (colorEditor.isVector3D) {
+ return Qt.rgba(__editColor.x,
+ __editColor.y,
+ __editColor.z, 1)
+ }
+
+ return __editColor
+ }
+
+ property alias gradientPropertyName: popupDialog.gradientPropertyName
+
+ property alias gradientThumbnail: gradientThumbnail
+ property alias shapeGradientThumbnail: shapeGradientThumbnail
+
+ property bool shapeGradients: false
+ property bool isVector3D: false
+ property color originalColor
+
+ property bool __block: false
+
+ function resetShapeColor() {
+ if (edit)
+ edit = ""
+ }
+
+ function writeColor() {
+ if (colorEditor.isVector3D) {
+ edit = Qt.vector3d(colorEditor.color.r,
+ colorEditor.color.g,
+ colorEditor.color.b)
+ } else {
+ edit = colorEditor.color
+ }
+ }
+
+ function initEditor() {
+ colorEditor.syncColor()
+ }
+
+ // Syncing color from backend to frontend and block reflection
+ function syncColor() {
+ colorEditor.__block = true
+ colorEditor.color = colorEditor.value
+ hexTextField.syncColor()
+ colorEditor.__block = false
+ }
+
+ Connections {
+ id: backendConnection
+
+ target: colorEditor
+
+ function onValueChanged() {
+ if (popupDialog.isSolid())
+ colorEditor.syncColor()
+ }
+
+ function on__EditColorChanged() {
+ if (popupDialog.isSolid())
+ colorEditor.syncColor()
+ }
+ }
+
+ Timer {
+ id: colorEditorTimer
+
+ repeat: false
+ interval: 100
+ running: false
+ onTriggered: {
+ backendConnection.enabled = false
+ colorEditor.writeColor()
+ hexTextField.syncColor()
+ backendConnection.enabled = true
+ }
+ }
+
+ onColorChanged: {
+ if (colorEditor.__block)
+ return
+
+ if (!popupDialog.isInValidState)
+ return
+
+ popupDialog.commitToGradient()
+
+ // Delay setting the color to keep ui responsive
+ if (popupDialog.isSolid())
+ colorEditorTimer.restart()
+ }
+
+ Rectangle {
+ id: preview
+
+ implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ implicitHeight: StudioTheme.Values.height
+ color: colorEditor.color
+ border.color: StudioTheme.Values.themeControlOutline
+ border.width: StudioTheme.Values.border
+
+ Rectangle {
+ id: gradientThumbnail
+
+ anchors.fill: parent
+ anchors.margins: StudioTheme.Values.border
+ visible: !popupDialog.isSolid()
+ && !colorEditor.shapeGradients
+ && popupDialog.isLinearGradient()
+ }
+
+ Shape {
+ id: shape
+
+ anchors.fill: parent
+ anchors.margins: StudioTheme.Values.border
+ visible: !popupDialog.isSolid() && colorEditor.shapeGradients
+
+ ShapePath {
+ id: shapeGradientThumbnail
+
+ startX: shape.x - 1
+ startY: shape.y - 1
+ strokeWidth: -1
+ strokeColor: "green"
+
+ PathLine {
+ x: shape.x - 1
+ y: shape.height
+ }
+ PathLine {
+ x: shape.width
+ y: shape.height
+ }
+ PathLine {
+ x: shape.width
+ y: shape.y - 1
+ }
+ }
+ }
+
+ Image {
+ anchors.fill: parent
+ source: "qrc:/navigator/icon/checkers.png"
+ fillMode: Image.Tile
+ z: -1
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ popupDialog.visibility ? popupDialog.close() : popupDialog.open()
+ forceActiveFocus()
+ }
+ }
+
+ StudioControls.PopupDialog {
+ id: popupDialog
+
+ property bool isInValidState: loader.active ? popupDialog.loaderItem.isInValidState : true
+ property QtObject loaderItem: loader.item
+ property string gradientPropertyName
+
+ keepOpen: loader.item?.eyeDropperActive ?? false
+
+ width: 260
+
+ function commitToGradient() {
+ if (!loader.active)
+ return
+
+ if (colorEditor.supportGradient && popupDialog.loaderItem.gradientModel.hasGradient) {
+ var hexColor = convertColorToString(colorEditor.color)
+ hexTextField.text = hexColor
+ edit = hexColor
+ popupDialog.loaderItem.commitGradientColor()
+ }
+ }
+
+ function isSolid() {
+ if (!loader.active)
+ return true
+
+ return popupDialog.loaderItem.isSolid()
+ }
+
+ function isLinearGradient(){
+ if (!loader.active)
+ return false
+
+ return popupDialog.loaderItem.isLinearGradient()
+ }
+
+ function ensureLoader() {
+ if (!loader.active)
+ loader.active = true
+ }
+
+ function open() {
+ popupDialog.ensureLoader()
+ popupDialog.show(preview)
+ }
+
+ function determineActiveColorMode() {
+ if (loader.active && popupDialog.loaderItem)
+ popupDialog.loaderItem.determineActiveColorMode()
+ else
+ colorEditor.syncColor()
+ }
+
+ Loader {
+ id: loader
+
+ active: colorEditor.supportGradient
+
+ sourceComponent: HelperWidgets.ColorEditorPopup {
+ shapeGradients: colorEditor.shapeGradients
+ supportGradient: colorEditor.supportGradient
+ width: popupDialog.contentWidth
+ }
+
+ onLoaded: {
+ popupDialog.loaderItem.initEditor()
+ popupDialog.titleBar = loader.item.titleBarContent
+ }
+ }
+ }
+ }
+
+ HelperWidgets.LineEdit {
+ id: hexTextField
+ implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ + StudioTheme.Values.actionIndicatorWidth
+ width: hexTextField.implicitWidth
+ enabled: popupDialog.isSolid()
+ writeValueManually: true
+ validator: RegularExpressionValidator {
+ regularExpression: /#[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?/g
+ }
+ showTranslateCheckBox: false
+ showExtendedFunctionButton: false
+ indicatorVisible: false
+
+ onAccepted: colorEditor.color = hexTextField.text
+ onCommitData: {
+ colorEditor.color = hexTextField.text
+ if (popupDialog.isSolid())
+ colorEditor.writeColor()
+ }
+
+ function syncColor() {
+ hexTextField.text = colorEditor.color
+ }
+ }
+
+ Component.onCompleted: popupDialog.determineActiveColorMode()
+
+ on__EditColorChanged: popupDialog.determineActiveColorMode()
+}
diff --git a/share/qtcreator/qmldesigner/collectionEditorQmlSource/EditPropertyDialog.qml b/share/qtcreator/qmldesigner/collectionEditorQmlSource/EditPropertyDialog.qml
index 37fd92cdd6..27e3527e01 100644
--- a/share/qtcreator/qmldesigner/collectionEditorQmlSource/EditPropertyDialog.qml
+++ b/share/qtcreator/qmldesigner/collectionEditorQmlSource/EditPropertyDialog.qml
@@ -36,6 +36,11 @@ StudioControls.Dialog {
root.open()
}
+ onWidthChanged: {
+ if (visible && x > parent.width)
+ root.close()
+ }
+
onAccepted: {
if (nameTextField.text !== "" && nameTextField.text !== root.__currentName)
root.model.renameColumn(root.__propertyIndex, nameTextField.text)
@@ -50,13 +55,13 @@ StudioControls.Dialog {
Grid {
columns: 2
rows: 2
- spacing: 2
+ rowSpacing: 2
+ columnSpacing: 25
verticalItemAlignment: Grid.AlignVCenter
Text {
text: qsTr("Name")
color: StudioTheme.Values.themeTextColor
- width: 50
verticalAlignment: Text.AlignVCenter
}
@@ -129,14 +134,12 @@ StudioControls.Dialog {
Row {
height: 40
spacing: 5
- anchors.right: parent.right
HelperWidgets.Button {
id: editButton
text: qsTr("Apply")
enabled: nameTextField.text !== ""
- width: 70
anchors.bottom: parent.bottom
onClicked: root.accept()
@@ -145,7 +148,6 @@ StudioControls.Dialog {
HelperWidgets.Button {
text: qsTr("Cancel")
anchors.bottom: parent.bottom
- width: 70
onClicked: root.reject()
}
diff --git a/share/qtcreator/qmldesigner/collectionEditorQmlSource/ImportDialog.qml b/share/qtcreator/qmldesigner/collectionEditorQmlSource/ImportDialog.qml
index e7bcefff77..3f8108005c 100644
--- a/share/qtcreator/qmldesigner/collectionEditorQmlSource/ImportDialog.qml
+++ b/share/qtcreator/qmldesigner/collectionEditorQmlSource/ImportDialog.qml
@@ -4,10 +4,9 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
-import QtQuickDesignerTheme 1.0
import Qt.labs.platform as PlatformWidgets
-import HelperWidgets 2.0 as HelperWidgets
-import StudioControls 1.0 as StudioControls
+import HelperWidgets as HelperWidgets
+import StudioControls as StudioControls
import StudioTheme as StudioTheme
StudioControls.Dialog {
diff --git a/share/qtcreator/qmldesigner/collectionEditorQmlSource/NewCollectionDialog.qml b/share/qtcreator/qmldesigner/collectionEditorQmlSource/NewCollectionDialog.qml
index 5cac7fd3fc..ec87bbb872 100644
--- a/share/qtcreator/qmldesigner/collectionEditorQmlSource/NewCollectionDialog.qml
+++ b/share/qtcreator/qmldesigner/collectionEditorQmlSource/NewCollectionDialog.qml
@@ -4,12 +4,11 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
-import QtQuickDesignerTheme 1.0
import Qt.labs.platform as PlatformWidgets
-import HelperWidgets 2.0 as HelperWidgets
-import StudioControls 1.0 as StudioControls
+import HelperWidgets as HelperWidgets
+import StudioControls as StudioControls
import StudioTheme as StudioTheme
-import CollectionEditor 1.0
+import CollectionEditor
StudioControls.Dialog {
id: root
diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibrary.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibrary.qml
index 63ac2517ae..c6db8425ff 100644
--- a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibrary.qml
+++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibrary.qml
@@ -4,10 +4,9 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
-import QtQuickDesignerTheme
-import HelperWidgets 2.0 as HelperWidgets
-import StudioControls 1.0 as StudioControls
-import StudioTheme 1.0 as StudioTheme
+import HelperWidgets as HelperWidgets
+import StudioControls as StudioControls
+import StudioTheme as StudioTheme
import ContentLibraryBackend
Item {
diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryEffect.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryEffect.qml
index d418cab0db..b20cc71e15 100644
--- a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryEffect.qml
+++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryEffect.qml
@@ -3,10 +3,8 @@
import QtQuick
import QtQuick.Layouts
-import QtQuickDesignerTheme
import HelperWidgets
import QtQuick.Controls
-
import StudioTheme as StudioTheme
import ContentLibraryBackend
diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterial.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterial.qml
index 9160c91606..93b226d6ca 100644
--- a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterial.qml
+++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterial.qml
@@ -4,10 +4,8 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
-import QtQuickDesignerTheme
import HelperWidgets
import StudioTheme as StudioTheme
-
import ContentLibraryBackend
import WebFetcher
diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexture.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexture.qml
index 74ece1c015..f74f190040 100644
--- a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexture.qml
+++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexture.qml
@@ -4,10 +4,8 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
-import QtQuickDesignerTheme
import HelperWidgets
import StudioTheme as StudioTheme
-
import ContentLibraryBackend
import WebFetcher
diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/UnimportBundleMaterialDialog.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/UnimportBundleMaterialDialog.qml
index edb6ce3670..48be045d8b 100644
--- a/share/qtcreator/qmldesigner/contentLibraryQmlSource/UnimportBundleMaterialDialog.qml
+++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/UnimportBundleMaterialDialog.qml
@@ -4,7 +4,6 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
-import QtQuickDesignerTheme
import HelperWidgets
import StudioControls as StudioControls
import StudioTheme as StudioTheme
diff --git a/share/qtcreator/qmldesigner/edit3dQmlSource/BakeLightsProgressDialog.qml b/share/qtcreator/qmldesigner/edit3dQmlSource/BakeLightsProgressDialog.qml
index 259a0a1ab5..7da6aeffb1 100644
--- a/share/qtcreator/qmldesigner/edit3dQmlSource/BakeLightsProgressDialog.qml
+++ b/share/qtcreator/qmldesigner/edit3dQmlSource/BakeLightsProgressDialog.qml
@@ -4,7 +4,6 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
-import QtQuickDesignerTheme
import HelperWidgets
import StudioControls as StudioControls
import StudioTheme as StudioTheme
diff --git a/share/qtcreator/qmldesigner/edit3dQmlSource/BakeLightsSetupDialog.qml b/share/qtcreator/qmldesigner/edit3dQmlSource/BakeLightsSetupDialog.qml
index 5c202a4a60..7366bef8c1 100644
--- a/share/qtcreator/qmldesigner/edit3dQmlSource/BakeLightsSetupDialog.qml
+++ b/share/qtcreator/qmldesigner/edit3dQmlSource/BakeLightsSetupDialog.qml
@@ -4,7 +4,6 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
-import QtQuickDesignerTheme
import HelperWidgets
import StudioControls as StudioControls
import StudioTheme as StudioTheme
diff --git a/share/qtcreator/qmldesigner/edit3dQmlSource/SnapConfigurationDialog.qml b/share/qtcreator/qmldesigner/edit3dQmlSource/SnapConfigurationDialog.qml
index 43460b7f71..61551216c1 100644
--- a/share/qtcreator/qmldesigner/edit3dQmlSource/SnapConfigurationDialog.qml
+++ b/share/qtcreator/qmldesigner/edit3dQmlSource/SnapConfigurationDialog.qml
@@ -4,7 +4,6 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
-import QtQuickDesignerTheme
import HelperWidgets as HelperWidgets
import StudioControls as StudioControls
import StudioTheme as StudioTheme
diff --git a/share/qtcreator/qmldesigner/effectMakerQmlSources/BlurHelper.qml b/share/qtcreator/qmldesigner/effectMakerQmlSources/BlurHelper.qml
index 0227d0f54a..da68339603 100644
--- a/share/qtcreator/qmldesigner/effectMakerQmlSources/BlurHelper.qml
+++ b/share/qtcreator/qmldesigner/effectMakerQmlSources/BlurHelper.qml
@@ -12,6 +12,7 @@ Item {
property alias blurSrc3: blurredItemSource3
property alias blurSrc4: blurredItemSource4
property alias blurSrc5: blurredItemSource5
+ property Item source: null
component BlurItem: ShaderEffect {
property vector2d offset: Qt.vector2d((1.0 + rootItem.blurMultiplier) / width,
@@ -37,8 +38,8 @@ Item {
// Size of the first blurred item is by default half of the source.
// Increase for quality and decrease for performance & more blur.
readonly property int blurItemSize: 8
- width: Math.ceil(rootItem.width / 16) * blurItemSize
- height: Math.ceil(rootItem.height / 16) * blurItemSize
+ width: Math.ceil((rootItem.source ? rootItem.source.width : 16) / 16) * blurItemSize
+ height: Math.ceil((rootItem.source ? rootItem.source.height : 16) / 16) * blurItemSize
}
BlurItem {
id: blurredItemSource2
diff --git a/share/qtcreator/qmldesigner/effectMakerQmlSources/EffectCompositionNode.qml b/share/qtcreator/qmldesigner/effectMakerQmlSources/EffectCompositionNode.qml
index 2ccaeaf36c..c1cd4632d2 100644
--- a/share/qtcreator/qmldesigner/effectMakerQmlSources/EffectCompositionNode.qml
+++ b/share/qtcreator/qmldesigner/effectMakerQmlSources/EffectCompositionNode.qml
@@ -3,10 +3,9 @@
import QtQuick
import QtQuick.Controls
-import QtQuickDesignerTheme
import HelperWidgets as HelperWidgets
import StudioControls as StudioControls
-import StudioTheme 1.0 as StudioTheme
+import StudioTheme as StudioTheme
import EffectMakerBackend
HelperWidgets.Section {
diff --git a/share/qtcreator/qmldesigner/effectMakerQmlSources/EffectCompositionNodeUniform.qml b/share/qtcreator/qmldesigner/effectMakerQmlSources/EffectCompositionNodeUniform.qml
index d696fccc1e..9cd42633d4 100644
--- a/share/qtcreator/qmldesigner/effectMakerQmlSources/EffectCompositionNodeUniform.qml
+++ b/share/qtcreator/qmldesigner/effectMakerQmlSources/EffectCompositionNodeUniform.qml
@@ -4,10 +4,9 @@
import QtQuick
import QtQuick.Dialogs
import QtQuick.Layouts
-import QtQuickDesignerTheme
import HelperWidgets as HelperWidgets
import StudioControls as StudioControls
-import StudioTheme 1.0 as StudioTheme
+import StudioTheme as StudioTheme
import EffectMakerBackend
Item {
diff --git a/share/qtcreator/qmldesigner/effectMakerQmlSources/EffectMaker.qml b/share/qtcreator/qmldesigner/effectMakerQmlSources/EffectMaker.qml
index d3ccb36a74..d86aaad27d 100644
--- a/share/qtcreator/qmldesigner/effectMakerQmlSources/EffectMaker.qml
+++ b/share/qtcreator/qmldesigner/effectMakerQmlSources/EffectMaker.qml
@@ -65,12 +65,12 @@ Item {
EffectMakerTopBar {
onAddClicked: {
- root.onSaveChangesCallback = () => { EffectMakerBackend.effectMakerModel.clear() }
+ root.onSaveChangesCallback = () => { EffectMakerBackend.effectMakerModel.clear(true) }
if (EffectMakerBackend.effectMakerModel.hasUnsavedChanges)
saveChangesDialog.open()
else
- EffectMakerBackend.effectMakerModel.clear()
+ EffectMakerBackend.effectMakerModel.clear(true)
}
onSaveClicked: {
diff --git a/share/qtcreator/qmldesigner/effectMakerQmlSources/EffectMakerPreview.qml b/share/qtcreator/qmldesigner/effectMakerQmlSources/EffectMakerPreview.qml
index ea0b2d1295..16dc2bf3a1 100644
--- a/share/qtcreator/qmldesigner/effectMakerQmlSources/EffectMakerPreview.qml
+++ b/share/qtcreator/qmldesigner/effectMakerQmlSources/EffectMakerPreview.qml
@@ -2,10 +2,9 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
-import QtQuickDesignerTheme
import HelperWidgets as HelperWidgets
import StudioControls as StudioControls
-import StudioTheme 1.0 as StudioTheme
+import StudioTheme as StudioTheme
import EffectMakerBackend
Column {
@@ -196,7 +195,7 @@ Column {
BlurHelper {
id: blurHelper
- anchors.fill: parent
+ source: source
property int blurMax: g_propertyData.blur_helper_max_level ? g_propertyData.blur_helper_max_level : 64
property real blurMultiplier: g_propertyData.blurMultiplier ? g_propertyData.blurMultiplier : 0
}
diff --git a/share/qtcreator/qmldesigner/effectMakerQmlSources/EffectMakerTopBar.qml b/share/qtcreator/qmldesigner/effectMakerQmlSources/EffectMakerTopBar.qml
index 9c962655e3..2dfa856237 100644
--- a/share/qtcreator/qmldesigner/effectMakerQmlSources/EffectMakerTopBar.qml
+++ b/share/qtcreator/qmldesigner/effectMakerQmlSources/EffectMakerTopBar.qml
@@ -2,10 +2,9 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
-import QtQuickDesignerTheme
import HelperWidgets as HelperWidgets
import StudioControls as StudioControls
-import StudioTheme 1.0 as StudioTheme
+import StudioTheme as StudioTheme
import EffectMakerBackend
Rectangle {
diff --git a/share/qtcreator/qmldesigner/effectMakerQmlSources/EffectNode.qml b/share/qtcreator/qmldesigner/effectMakerQmlSources/EffectNode.qml
index f3fca1ccec..865b60cf82 100644
--- a/share/qtcreator/qmldesigner/effectMakerQmlSources/EffectNode.qml
+++ b/share/qtcreator/qmldesigner/effectMakerQmlSources/EffectNode.qml
@@ -3,10 +3,9 @@
import QtQuick
import QtQuick.Controls
-import QtQuickDesignerTheme
import HelperWidgets
import StudioControls as StudioControls
-import StudioTheme 1.0 as StudioTheme
+import StudioTheme as StudioTheme
import EffectMakerBackend
Rectangle {
diff --git a/share/qtcreator/qmldesigner/effectMakerQmlSources/EffectNodesComboBox.qml b/share/qtcreator/qmldesigner/effectMakerQmlSources/EffectNodesComboBox.qml
index a2187d4aba..dc6f54a5aa 100644
--- a/share/qtcreator/qmldesigner/effectMakerQmlSources/EffectNodesComboBox.qml
+++ b/share/qtcreator/qmldesigner/effectMakerQmlSources/EffectNodesComboBox.qml
@@ -2,10 +2,9 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
-import QtQuickDesignerTheme
import HelperWidgets as HelperWidgets
import StudioControls as StudioControls
-import StudioTheme 1.0 as StudioTheme
+import StudioTheme as StudioTheme
import EffectMakerBackend
StudioControls.ComboBox {
diff --git a/share/qtcreator/qmldesigner/effectMakerQmlSources/PreviewImagesComboBox.qml b/share/qtcreator/qmldesigner/effectMakerQmlSources/PreviewImagesComboBox.qml
index feadaa1d94..988b28a072 100644
--- a/share/qtcreator/qmldesigner/effectMakerQmlSources/PreviewImagesComboBox.qml
+++ b/share/qtcreator/qmldesigner/effectMakerQmlSources/PreviewImagesComboBox.qml
@@ -2,10 +2,9 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
-import QtQuickDesignerTheme
import HelperWidgets as HelperWidgets
import StudioControls as StudioControls
-import StudioTheme 1.0 as StudioTheme
+import StudioTheme as StudioTheme
import EffectMakerBackend
StudioControls.ComboBox {
diff --git a/share/qtcreator/qmldesigner/effectMakerQmlSources/SaveAsDialog.qml b/share/qtcreator/qmldesigner/effectMakerQmlSources/SaveAsDialog.qml
index 8e762cebbd..eef2411669 100644
--- a/share/qtcreator/qmldesigner/effectMakerQmlSources/SaveAsDialog.qml
+++ b/share/qtcreator/qmldesigner/effectMakerQmlSources/SaveAsDialog.qml
@@ -84,6 +84,9 @@ StudioControls.Dialog {
text: qsTr("Save")
enabled: nameText.text !== ""
onClicked: {
+ if (!enabled) // needed since this event handler can be triggered from keyboard events
+ return
+
EffectMakerBackend.effectMakerModel.saveComposition(nameText.text)
if (root.clearOnClose) {
diff --git a/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueBool.qml b/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueBool.qml
index 201f997698..f59a3a4408 100644
--- a/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueBool.qml
+++ b/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueBool.qml
@@ -2,9 +2,8 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
-import QtQuickDesignerTheme
import StudioControls as StudioControls
-import StudioTheme 1.0 as StudioTheme
+import StudioTheme as StudioTheme
import EffectMakerBackend
StudioControls.CheckBox {
diff --git a/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueColor.qml b/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueColor.qml
index 1f601f9063..5d86d3513f 100644
--- a/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueColor.qml
+++ b/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueColor.qml
@@ -2,9 +2,8 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
-import QtQuickDesignerTheme
import StudioControls as StudioControls
-import StudioTheme 1.0 as StudioTheme
+import StudioTheme as StudioTheme
import EffectMakerBackend
Row {
diff --git a/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueDefine.qml b/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueDefine.qml
index d5a6cf139a..7aa4a8a568 100644
--- a/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueDefine.qml
+++ b/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueDefine.qml
@@ -2,9 +2,8 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
-import QtQuickDesignerTheme
import StudioControls as StudioControls
-import StudioTheme 1.0 as StudioTheme
+import StudioTheme as StudioTheme
import EffectMakerBackend
Row {
diff --git a/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueFloat.qml b/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueFloat.qml
index 9c2d2c80a2..ea557b1877 100644
--- a/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueFloat.qml
+++ b/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueFloat.qml
@@ -2,9 +2,8 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
-import QtQuickDesignerTheme
import StudioControls as StudioControls
-import StudioTheme 1.0 as StudioTheme
+import StudioTheme as StudioTheme
import EffectMakerBackend
Row {
diff --git a/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueImage.qml b/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueImage.qml
index 832350ef17..a4f3ccd5ae 100644
--- a/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueImage.qml
+++ b/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueImage.qml
@@ -2,9 +2,8 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
-import QtQuickDesignerTheme
import HelperWidgets as HelperWidgets
-import StudioTheme 1.0 as StudioTheme
+import StudioTheme as StudioTheme
import EffectMakerBackend
Row {
diff --git a/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueInt.qml b/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueInt.qml
index b5db8db05e..38a95f4970 100644
--- a/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueInt.qml
+++ b/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueInt.qml
@@ -2,9 +2,8 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
-import QtQuickDesignerTheme
import StudioControls as StudioControls
-import StudioTheme 1.0 as StudioTheme
+import StudioTheme as StudioTheme
import EffectMakerBackend
Row {
diff --git a/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueVec2.qml b/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueVec2.qml
index 9207e98a62..a5c0c9db74 100644
--- a/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueVec2.qml
+++ b/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueVec2.qml
@@ -3,9 +3,8 @@
import QtQuick
import QtQuick.Layouts
-import QtQuickDesignerTheme
import StudioControls as StudioControls
-import StudioTheme 1.0 as StudioTheme
+import StudioTheme as StudioTheme
import EffectMakerBackend
RowLayout {
diff --git a/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueVec3.qml b/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueVec3.qml
index 52df4c999a..5369795a68 100644
--- a/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueVec3.qml
+++ b/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueVec3.qml
@@ -3,9 +3,8 @@
import QtQuick
import QtQuick.Layouts
-import QtQuickDesignerTheme
import StudioControls as StudioControls
-import StudioTheme 1.0 as StudioTheme
+import StudioTheme as StudioTheme
import EffectMakerBackend
RowLayout {
diff --git a/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueVec4.qml b/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueVec4.qml
index 05954e5b65..bb93cd0008 100644
--- a/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueVec4.qml
+++ b/share/qtcreator/qmldesigner/effectMakerQmlSources/ValueVec4.qml
@@ -3,9 +3,8 @@
import QtQuick
import QtQuick.Layouts
-import QtQuickDesignerTheme
import StudioControls as StudioControls
-import StudioTheme 1.0 as StudioTheme
+import StudioTheme as StudioTheme
import EffectMakerBackend
RowLayout {
diff --git a/share/qtcreator/qmldesigner/insight/Main.qml b/share/qtcreator/qmldesigner/insight/Main.qml
index 14a69ce80f..a6be9cb1be 100644
--- a/share/qtcreator/qmldesigner/insight/Main.qml
+++ b/share/qtcreator/qmldesigner/insight/Main.qml
@@ -3,9 +3,8 @@
import QtQuick
import QtQuick.Controls
-import QtQuickDesignerTheme 1.0
-import HelperWidgets 2.0 as HelperWidgets
-import StudioControls 1.0 as StudioControls
+import HelperWidgets as HelperWidgets
+import StudioControls as StudioControls
import StudioTheme as StudioTheme
Rectangle {
diff --git a/share/qtcreator/qmldesigner/itemLibraryQmlSources/AddModuleView.qml b/share/qtcreator/qmldesigner/itemLibraryQmlSources/AddModuleView.qml
index 6ed7052b8e..e036139315 100644
--- a/share/qtcreator/qmldesigner/itemLibraryQmlSources/AddModuleView.qml
+++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/AddModuleView.qml
@@ -1,11 +1,10 @@
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-import QtQuick 2.15
-import QtQuick.Controls 2.15
-import QtQuickDesignerTheme 1.0
-import HelperWidgets 2.0
-import StudioTheme 1.0 as StudioTheme
+import QtQuick
+import QtQuick.Controls
+import HelperWidgets
+import StudioTheme as StudioTheme
import ItemLibraryBackend
Column {
diff --git a/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemDelegate.qml b/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemDelegate.qml
index 1178de4a87..266dba995d 100644
--- a/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemDelegate.qml
+++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemDelegate.qml
@@ -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
-import QtQuick 2.15
-import QtQuick.Controls 2.15
-import QtQuickDesignerTheme 1.0
-import HelperWidgets 2.0
-import StudioTheme 1.0 as StudioTheme
+import QtQuick
+import QtQuick.Controls
+import HelperWidgets
+import StudioTheme as StudioTheme
import ItemLibraryBackend
+import QtQuickDesignerTheme
Item {
id: delegateRoot
diff --git a/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemsView.qml b/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemsView.qml
index cf5049d647..62c907e76f 100644
--- a/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemsView.qml
+++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/ItemsView.qml
@@ -2,11 +2,11 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import QtQuick.Layouts
-import QtQuickDesignerTheme 1.0
-import HelperWidgets 2.0 as HelperWidgets
-import StudioControls 1.0 as StudioControls
-import StudioTheme 1.0 as StudioTheme
+import HelperWidgets as HelperWidgets
+import StudioControls as StudioControls
+import StudioTheme as StudioTheme
import ItemLibraryBackend
+import QtQuickDesignerTheme
/* The view displaying the item grid.
The following Qml context properties have to be set:
- ItemLibraryModel itemLibraryModel
diff --git a/share/qtcreator/qmldesigner/materialBrowserQmlSource/ChooseMaterialProperty.qml b/share/qtcreator/qmldesigner/materialBrowserQmlSource/ChooseMaterialProperty.qml
index ddbdbfa7c8..770cde48c9 100644
--- a/share/qtcreator/qmldesigner/materialBrowserQmlSource/ChooseMaterialProperty.qml
+++ b/share/qtcreator/qmldesigner/materialBrowserQmlSource/ChooseMaterialProperty.qml
@@ -4,7 +4,6 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
-import QtQuickDesignerTheme
import HelperWidgets
import StudioControls as StudioControls
import StudioTheme as StudioTheme
diff --git a/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml b/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml
index e0dacef36b..d84570b434 100644
--- a/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml
+++ b/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml
@@ -2,10 +2,9 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
-import QtQuickDesignerTheme 1.0
-import HelperWidgets 2.0 as HelperWidgets
-import StudioControls 1.0 as StudioControls
-import StudioTheme 1.0 as StudioTheme
+import HelperWidgets as HelperWidgets
+import StudioControls as StudioControls
+import StudioTheme as StudioTheme
import MaterialBrowserBackend
Item {
diff --git a/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowserItemName.qml b/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowserItemName.qml
index 800217bac5..18dbd3b194 100644
--- a/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowserItemName.qml
+++ b/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowserItemName.qml
@@ -1,11 +1,10 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-import QtQuick 2.15
-import QtQuick.Layouts 1.15
-import QtQuickDesignerTheme 1.0
-import HelperWidgets 2.0
-import StudioTheme 1.0 as StudioTheme
+import QtQuick
+import QtQuick.Layouts
+import HelperWidgets
+import StudioTheme as StudioTheme
import MaterialBrowserBackend
TextInput {
diff --git a/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialItem.qml b/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialItem.qml
index ce1b12aeae..47eed8a7d6 100644
--- a/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialItem.qml
+++ b/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialItem.qml
@@ -1,11 +1,10 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-import QtQuick 2.15
-import QtQuick.Layouts 1.15
-import QtQuickDesignerTheme 1.0
-import HelperWidgets 2.0
-import StudioTheme 1.0 as StudioTheme
+import QtQuick
+import QtQuick.Layouts
+import HelperWidgets
+import StudioTheme as StudioTheme
import MaterialBrowserBackend
Item {
diff --git a/share/qtcreator/qmldesigner/materialBrowserQmlSource/TextureItem.qml b/share/qtcreator/qmldesigner/materialBrowserQmlSource/TextureItem.qml
index 4eaa449c62..5ed132461b 100644
--- a/share/qtcreator/qmldesigner/materialBrowserQmlSource/TextureItem.qml
+++ b/share/qtcreator/qmldesigner/materialBrowserQmlSource/TextureItem.qml
@@ -4,7 +4,6 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
-import QtQuickDesignerTheme
import HelperWidgets
import StudioTheme as StudioTheme
import MaterialBrowserBackend
diff --git a/share/qtcreator/qmldesigner/materialEditorQmlSources/EmptyMaterialEditorPane.qml b/share/qtcreator/qmldesigner/materialEditorQmlSources/EmptyMaterialEditorPane.qml
index 39b0929a44..0c6d7e39b2 100644
--- a/share/qtcreator/qmldesigner/materialEditorQmlSources/EmptyMaterialEditorPane.qml
+++ b/share/qtcreator/qmldesigner/materialEditorQmlSources/EmptyMaterialEditorPane.qml
@@ -2,9 +2,8 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
-import QtQuickDesignerTheme 1.0
-import HelperWidgets 2.0
-import StudioTheme 1.0 as StudioTheme
+import HelperWidgets
+import StudioTheme as StudioTheme
PropertyEditorPane {
id: root
diff --git a/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorPane.qml b/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorPane.qml
index 0187cde695..dde7ecd0dc 100644
--- a/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorPane.qml
+++ b/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorPane.qml
@@ -2,8 +2,7 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
-import QtQuickDesignerTheme 1.0
-import HelperWidgets 2.0
+import HelperWidgets
PropertyEditorPane {
id: itemPane
diff --git a/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorToolBar.qml b/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorToolBar.qml
index d5a9acf974..290c84317d 100644
--- a/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorToolBar.qml
+++ b/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorToolBar.qml
@@ -2,11 +2,10 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
-import QtQuickDesignerTheme 1.0
-import HelperWidgets 2.0 as HelperWidgets
-import StudioControls 1.0 as StudioControls
-import StudioTheme 1.0 as StudioTheme
-import MaterialToolBarAction 1.0
+import HelperWidgets as HelperWidgets
+import StudioControls as StudioControls
+import StudioTheme as StudioTheme
+import MaterialToolBarAction
Rectangle {
id: root
diff --git a/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorTopSection.qml b/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorTopSection.qml
index dbc023d83b..23311636bc 100644
--- a/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorTopSection.qml
+++ b/share/qtcreator/qmldesigner/materialEditorQmlSources/MaterialEditorTopSection.qml
@@ -4,10 +4,9 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
-import QtQuickDesignerTheme 1.0
-import HelperWidgets 2.0 as HelperWidgets
-import StudioControls 1.0 as StudioControls
-import StudioTheme 1.0 as StudioTheme
+import HelperWidgets as HelperWidgets
+import StudioControls as StudioControls
+import StudioTheme as StudioTheme
Column {
id: root
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AnchorRow.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AnchorRow.qml
index a6c57a73ed..34fa2f3be3 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AnchorRow.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AnchorRow.qml
@@ -1,13 +1,11 @@
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-import QtQuick 2.15
-import QtQuick.Layouts 1.15
-import HelperWidgets 2.0
-import QtQuickDesignerTheme 1.0
-
-import StudioControls 1.0 as StudioControls
-import StudioTheme 1.0 as StudioTheme
+import QtQuick
+import QtQuick.Layouts
+import HelperWidgets
+import StudioControls as StudioControls
+import StudioTheme as StudioTheme
SectionLayout {
id: anchorRow
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/AbstractButtonSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/AbstractButtonSection.qml
index e625e5c842..b4b3362aa7 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/AbstractButtonSection.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/AbstractButtonSection.qml
@@ -1,11 +1,10 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-import QtQuick 2.15
-import QtQuick.Layouts 1.15
-import HelperWidgets 2.0
-import QtQuickDesignerTheme 1.0
-import StudioTheme 1.0 as StudioTheme
+import QtQuick
+import QtQuick.Layouts
+import HelperWidgets
+import StudioTheme as StudioTheme
Section {
caption: qsTr("Button Content")
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ButtonSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ButtonSection.qml
index dbfbfd1fd4..977ac431bc 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ButtonSection.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ButtonSection.qml
@@ -1,11 +1,10 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-import QtQuick 2.15
-import QtQuick.Layouts 1.15
-import HelperWidgets 2.0
-import QtQuickDesignerTheme 1.0
-import StudioTheme 1.0 as StudioTheme
+import QtQuick
+import QtQuick.Layouts
+import HelperWidgets
+import StudioTheme as StudioTheme
Section {
id: section
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ButtonSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ButtonSpecifics.qml
index ab22345980..2c10d89ad8 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ButtonSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ButtonSpecifics.qml
@@ -1,11 +1,10 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-import QtQuick 2.15
-import QtQuick.Layouts 1.15
-import HelperWidgets 2.0
-import QtQuickDesignerTheme 1.0
-import StudioTheme 1.0 as StudioTheme
+import QtQuick
+import QtQuick.Layouts
+import HelperWidgets
+import StudioTheme as StudioTheme
Column {
anchors.left: parent.left
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ControlSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ControlSpecifics.qml
index 687053b324..dd28d662cd 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ControlSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ControlSpecifics.qml
@@ -1,11 +1,10 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-import QtQuick 2.15
-import QtQuick.Layouts 1.15
-import HelperWidgets 2.0
-import QtQuickDesignerTheme 1.0
-import StudioTheme 1.0 as StudioTheme
+import QtQuick
+import QtQuick.Layouts
+import HelperWidgets
+import StudioTheme as StudioTheme
Column {
anchors.left: parent.left
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/QtObjectPane.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/QtObjectPane.qml
index 92e157dfdc..12be7b8f34 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/QtObjectPane.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/QtObjectPane.qml
@@ -3,9 +3,8 @@
import QtQuick
import QtQuick.Layouts
-import QtQuickDesignerTheme 1.0
-import HelperWidgets 2.0
-import StudioTheme 1.0 as StudioTheme
+import HelperWidgets
+import StudioTheme as StudioTheme
PropertyEditorPane {
id: itemPane
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/emptyPane.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/emptyPane.qml
index a5dc28f6f8..3ec325d8f1 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/emptyPane.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/emptyPane.qml
@@ -1,18 +1,17 @@
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-import QtQuick 2.15
-import QtQuick.Controls 2.15 as Controls
-import QtQuick.Layouts 1.15
-import HelperWidgets 2.0
-import QtQuickDesignerTheme 1.0
-import StudioTheme 1.0 as StudioTheme
+import QtQuick
+import QtQuick.Controls as Controls
+import QtQuick.Layouts
+import HelperWidgets
+import StudioTheme as StudioTheme
Rectangle {
id: itemPane
width: 320
height: 400
- color: Theme.qmlDesignerBackgroundColorDarkAlternate()
+ color: StudioTheme.Values.themePanelBackground
ColumnLayout {
id: mainColumn
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick3D/Object3DPane.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick3D/Object3DPane.qml
index c532281d6f..e4f7554442 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick3D/Object3DPane.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick3D/Object3DPane.qml
@@ -3,9 +3,8 @@
import QtQuick
import QtQuick.Layouts
-import QtQuickDesignerTheme 1.0
-import HelperWidgets 2.0
-import StudioTheme 1.0 as StudioTheme
+import HelperWidgets
+import StudioTheme as StudioTheme
PropertyEditorPane {
id: itemPane
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ButtonRowButton.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ButtonRowButton.qml
index 3d4373cdf0..9b376a82d8 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ButtonRowButton.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ButtonRowButton.qml
@@ -1,10 +1,9 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-import QtQuick 2.15
-import QtQuick.Layouts 1.15
-import QtQuickDesignerTheme 1.0
-import StudioTheme 1.0 as StudioTheme
+import QtQuick
+import QtQuick.Layouts
+import StudioTheme as StudioTheme
Item {
id: buttonRowButton
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml
index 3262b03065..f9e72ad67d 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml
@@ -7,7 +7,6 @@ import QtQuick.Shapes
import QtQuick.Templates as T
import StudioTheme as StudioTheme
import StudioControls as StudioControls
-import QtQuickDesignerTheme
import QtQuickDesignerColorPalette
SecondColumnLayout {
@@ -36,6 +35,7 @@ SecondColumnLayout {
property alias shapeGradientThumbnail: shapeGradientThumbnail
property alias showExtendedFunctionButton: hexTextField.showExtendedFunctionButton
+ property alias showHexTextField: hexTextField.visible
property bool shapeGradients: false
property color originalColor
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditorPopup.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditorPopup.qml
index fcf2d341b8..0591d1cb5a 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditorPopup.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditorPopup.qml
@@ -5,7 +5,6 @@ import QtQuick
import QtQuick.Layouts
import QtQuick.Shapes
import QtQuick.Templates as T
-import QtQuickDesignerTheme
import StudioTheme as StudioTheme
import StudioControls as StudioControls
import QtQuickDesignerColorPalette
@@ -393,10 +392,7 @@ Column {
}
}
}
- }
- Connections {
- target: modelNodeBackend
function onSelectionChanged() {
root.initEditor()
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComponentSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComponentSection.qml
index 49809cb9d9..a29bda0ba5 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComponentSection.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComponentSection.qml
@@ -1,13 +1,12 @@
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-import QtQuick 2.15
-import QtQuick.Controls 2.15
-import QtQuick.Layouts 1.15
-import QtQuickDesignerTheme 1.0
-import QtQuick.Templates 2.15 as T
-import HelperWidgets 2.0
-import StudioTheme 1.0 as StudioTheme
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+import QtQuick.Templates as T
+import HelperWidgets
+import StudioTheme as StudioTheme
Section {
id: root
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExpressionTextField.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExpressionTextField.qml
index b968768043..7b67735188 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExpressionTextField.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExpressionTextField.qml
@@ -1,12 +1,11 @@
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-import QtQuick 2.15
-import QtQuick.Window 2.15
-import QtQuick.Controls 2.15
-import QtQuickDesignerTheme 1.0
-import StudioControls 1.0 as StudioControls
-import StudioTheme 1.0 as StudioTheme
+import QtQuick
+import QtQuick.Window
+import QtQuick.Controls
+import StudioControls as StudioControls
+import StudioTheme as StudioTheme
StudioControls.TextField {
id: textField
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExtendedFunctionLogic.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExtendedFunctionLogic.qml
index c82aa2cea5..76e6bd8f09 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExtendedFunctionLogic.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExtendedFunctionLogic.qml
@@ -1,11 +1,10 @@
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-import QtQuick 2.15
-import StudioControls 1.0 as StudioControls
-import StudioTheme 1.0 as StudioTheme
-import QtQuickDesignerTheme 1.0
-import HelperWidgets 2.0
+import QtQuick
+import StudioControls as StudioControls
+import StudioTheme as StudioTheme
+import HelperWidgets
Item {
id: extendedFunctionButton
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPresetList.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPresetList.qml
index 6af54c11b9..2503d35103 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPresetList.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPresetList.qml
@@ -4,7 +4,6 @@
import QtQuick
import QtQuick.Layouts
import Qt.labs.platform
-import QtQuickDesignerTheme
import HelperWidgets
import StudioControls as StudioControls
import StudioTheme as StudioTheme
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPresetTabContent.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPresetTabContent.qml
index 050fb64f48..d53c512c3b 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPresetTabContent.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPresetTabContent.qml
@@ -1,13 +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
-import QtQuick 2.15
-import QtQuick.Controls 2.15
-import QtQuick.Layouts 1.15
-import QtQuickDesignerTheme 1.0
-import HelperWidgets 2.0
-import StudioControls 1.0 as StudioControls
-import StudioTheme 1.0 as StudioTheme
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+import HelperWidgets
+import StudioControls as StudioControls
+import StudioTheme as StudioTheme
Rectangle {
id: tabBackground
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/IconButton.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/IconButton.qml
index 4852b05a98..008320cb92 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/IconButton.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/IconButton.qml
@@ -1,10 +1,9 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-import QtQuick 2.15
-import QtQuick.Controls 2.15
-import QtQuickDesignerTheme 1.0
-import StudioTheme 1.0 as StudioTheme
+import QtQuick
+import QtQuick.Controls
+import StudioTheme as StudioTheme
Rectangle {
id: root
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/LineEdit.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/LineEdit.qml
index dffe3d779e..96378cb6d7 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/LineEdit.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/LineEdit.qml
@@ -1,10 +1,9 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-import QtQuick 2.15
-import StudioControls 1.0 as StudioControls
-import StudioTheme 1.0 as StudioTheme
-import QtQuickDesignerTheme 1.0
+import QtQuick
+import StudioControls as StudioControls
+import StudioTheme as StudioTheme
StudioControls.TextField {
id: lineEdit
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/PropertyEditorPane.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/PropertyEditorPane.qml
index 26151ec916..f35a21f453 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/PropertyEditorPane.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/PropertyEditorPane.qml
@@ -4,16 +4,15 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
-import QtQuickDesignerTheme 1.0
-import HelperWidgets 2.0 as HelperWidgets
-import StudioTheme 1.0 as StudioTheme
+import HelperWidgets as HelperWidgets
+import StudioTheme as StudioTheme
Rectangle {
id: itemPane
width: 320
height: 400
- color: Theme.qmlDesignerBackgroundColorDarkAlternate()
+ color: StudioTheme.Values.themePanelBackground
Component.onCompleted: Controller.mainScrollView = mainScrollView
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/RoundedPanel.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/RoundedPanel.qml
index 5cfd1076bf..aec3a2e3f2 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/RoundedPanel.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/RoundedPanel.qml
@@ -1,10 +1,9 @@
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-import QtQuick 2.15
-import QtQuick.Layouts 1.15
-import QtQuickDesignerTheme 1.0
-import StudioTheme 1.0 as StudioTheme
+import QtQuick
+import QtQuick.Layouts
+import StudioTheme as StudioTheme
Rectangle {
id: panel
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ScrollView.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ScrollView.qml
index abe62052e8..707f3e5669 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ScrollView.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ScrollView.qml
@@ -28,6 +28,8 @@ Flickable {
// and set the ads focus on it.
objectName: "__mainSrollView"
+ flickDeceleration: 10000
+
HoverHandler { id: hoverHandler }
ScrollBar.horizontal: StudioControls.TransientScrollBar {
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml
index 5eb40e42cc..f078f3dd48 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml
@@ -1,12 +1,11 @@
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-import QtQuick 2.15
-import QtQuick.Controls 2.15 as Controls
-import QtQuick.Layouts 1.15
-import QtQuickDesignerTheme 1.0
-import StudioControls 1.0 as StudioControls
-import StudioTheme 1.0 as StudioTheme
+import QtQuick
+import QtQuick.Controls as Controls
+import QtQuick.Layouts
+import StudioControls as StudioControls
+import StudioTheme as StudioTheme
Item {
id: section
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/UrlChooser.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/UrlChooser.qml
index 3b00a30a1f..16d74c66f0 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/UrlChooser.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/UrlChooser.qml
@@ -7,7 +7,6 @@ import QtQuick.Controls
import HelperWidgets
import StudioControls as StudioControls
import StudioTheme as StudioTheme
-import QtQuickDesignerTheme
Row {
id: root
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/qmldir b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/qmldir
index 6fc885ac57..94c3da2718 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/qmldir
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/qmldir
@@ -10,6 +10,7 @@ ButtonRowButton 2.0 ButtonRowButton.qml
CharacterSection 2.0 CharacterSection.qml
CheckBox 2.0 CheckBox.qml
ColorEditor 2.0 ColorEditor.qml
+ColorEditorPopup 2.0 ColorEditorPopup.qml
ColorLogic 2.0 ColorLogic.qml
ComboBox 2.0 ComboBox.qml
ComponentButton 2.0 ComponentButton.qml
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ColorEditor.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ColorEditor.qml
index 458cceb31e..9069370e9c 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ColorEditor.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ColorEditor.qml
@@ -3,7 +3,6 @@
import QtQuick
import StudioTheme as StudioTheme
-import QtQuickDesignerTheme
import QtQuickDesignerColorPalette
import StudioHelpers
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/PopupDialog.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/PopupDialog.qml
index 594e115639..4da26cf494 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/PopupDialog.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/PopupDialog.qml
@@ -104,7 +104,7 @@ QtObject {
return root.maximumHeight + (2 * window.margin)
}
visible: false
- flags: Qt.FramelessWindowHint | Qt.Dialog
+ flags: Qt.FramelessWindowHint | Qt.Dialog | Qt.WindowStaysOnTopHint
color: "transparent"
onClosing: function (close) {
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSpinBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSpinBox.qml
index 19496da346..37612af13f 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSpinBox.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSpinBox.qml
@@ -37,6 +37,8 @@ T.SpinBox {
property bool drag: false
property bool sliderDrag: sliderPopup.drag
+ property bool trailingZeroes: true
+
property bool dirty: false // user modification flag
// TODO Not used anymore. Will be removed when all dependencies were removed.
@@ -204,11 +206,14 @@ T.SpinBox {
textFromValue: function (value, locale) {
locale.numberOptions = Locale.OmitGroupSeparator
- return Number(control.realValue).toLocaleString(locale, 'f', control.decimals)
+ var decimals = trailingZeroes ? control.decimals : decimalCounter(value)
+
+ return Number(control.realValue).toLocaleString(locale, 'f', decimals)
}
valueFromText: function (text, locale) {
control.setRealValue(Number.fromLocaleString(locale, spinBoxInput.text))
+
return 0
}
@@ -400,4 +405,14 @@ T.SpinBox {
if (control.realValue !== currValue)
control.realValueModified()
}
+
+ function decimalCounter(number) {
+ var strNumber = Math.abs(number).toString()
+ var decimalIndex = strNumber.indexOf('.')
+
+ // Set 'index' to a minimum of 1 if there are no fractions
+ var index = decimalIndex == -1 ? 1 : strNumber.length - decimalIndex - 1
+
+ return Math.min(index, control.decimals);
+ }
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SearchBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SearchBox.qml
index d885271ecb..efdfa49af7 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SearchBox.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SearchBox.qml
@@ -3,8 +3,7 @@
import QtQuick
import QtQuick.Templates as T
-import QtQuickDesignerTheme 1.0
-import StudioTheme 1.0 as StudioTheme
+import StudioTheme as StudioTheme
T.TextField {
id: control
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TopLevelComboBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TopLevelComboBox.qml
index 3aa5d70940..27f8333d24 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TopLevelComboBox.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TopLevelComboBox.qml
@@ -4,7 +4,6 @@
import QtQuick
import QtQuick.Templates as T
import StudioTheme as StudioTheme
-import QtQuickDesignerTheme
import StudioWindowManager
T.ComboBox {
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/impl/ColorEditorPopup.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/impl/ColorEditorPopup.qml
index ba37645239..4f46b356f3 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/impl/ColorEditorPopup.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/impl/ColorEditorPopup.qml
@@ -5,7 +5,6 @@ import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Templates as T
-import QtQuickDesignerTheme
import StudioControls as StudioControls
import StudioTheme as StudioTheme
import QtQuickDesignerColorPalette
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml
index 6b179e4229..6b2e6b75cb 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml
@@ -3,7 +3,7 @@
pragma Singleton
import QtQuick
-import QtQuickDesignerTheme 1.0
+import QtQuickDesignerTheme
QtObject {
id: values
diff --git a/share/qtcreator/qmldesigner/textureEditorQmlSource/EmptyTextureEditorPane.qml b/share/qtcreator/qmldesigner/textureEditorQmlSource/EmptyTextureEditorPane.qml
index 244f3beb83..adaf5dba56 100644
--- a/share/qtcreator/qmldesigner/textureEditorQmlSource/EmptyTextureEditorPane.qml
+++ b/share/qtcreator/qmldesigner/textureEditorQmlSource/EmptyTextureEditorPane.qml
@@ -2,9 +2,8 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
-import QtQuickDesignerTheme 1.0
-import HelperWidgets 2.0
-import StudioTheme 1.0 as StudioTheme
+import HelperWidgets
+import StudioTheme as StudioTheme
PropertyEditorPane {
id: root
diff --git a/share/qtcreator/qmldesigner/textureEditorQmlSource/TextureEditorPane.qml b/share/qtcreator/qmldesigner/textureEditorQmlSource/TextureEditorPane.qml
index ddf452d6f0..06fbfd5593 100644
--- a/share/qtcreator/qmldesigner/textureEditorQmlSource/TextureEditorPane.qml
+++ b/share/qtcreator/qmldesigner/textureEditorQmlSource/TextureEditorPane.qml
@@ -2,8 +2,7 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
-import QtQuickDesignerTheme 1.0
-import HelperWidgets 2.0
+import HelperWidgets
PropertyEditorPane {
id: itemPane
diff --git a/share/qtcreator/qmldesigner/textureEditorQmlSource/TextureEditorToolBar.qml b/share/qtcreator/qmldesigner/textureEditorQmlSource/TextureEditorToolBar.qml
index 6a61a76ef6..f7d2e502ff 100644
--- a/share/qtcreator/qmldesigner/textureEditorQmlSource/TextureEditorToolBar.qml
+++ b/share/qtcreator/qmldesigner/textureEditorQmlSource/TextureEditorToolBar.qml
@@ -2,10 +2,9 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
-import QtQuickDesignerTheme 1.0
-import HelperWidgets 2.0 as HelperWidgets
-import StudioTheme 1.0 as StudioTheme
-import TextureToolBarAction 1.0
+import HelperWidgets as HelperWidgets
+import StudioTheme as StudioTheme
+import TextureToolBarAction
Rectangle {
id: root
diff --git a/share/qtcreator/qmldesigner/toolbar/Main.qml b/share/qtcreator/qmldesigner/toolbar/Main.qml
index 63b3aef565..af83887832 100644
--- a/share/qtcreator/qmldesigner/toolbar/Main.qml
+++ b/share/qtcreator/qmldesigner/toolbar/Main.qml
@@ -3,11 +3,9 @@
import QtQuick
import QtQuick.Controls
-import StudioControls 1.0 as StudioControls
-import StudioTheme 1.0 as StudioTheme
-import QtQuickDesignerTheme 1.0
-
-import ToolBar 1.0
+import StudioControls as StudioControls
+import StudioTheme as StudioTheme
+import ToolBar
Rectangle {
id: root
diff --git a/share/qtcreator/qmldesigner/welcomepage/BrandBar.qml b/share/qtcreator/qmldesigner/welcomepage/BrandBar.qml
new file mode 100644
index 0000000000..721e2b06dd
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/BrandBar.qml
@@ -0,0 +1,64 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtQuick.Controls
+import WelcomeScreen 1.0
+
+Item {
+ id: brandBar
+ width: 850
+ height: 150
+
+ Image {
+ id: brandIcon
+ width: 100
+ height: 100
+ anchors.verticalCenter: parent.verticalCenter
+ source: "images/ds.png"
+ fillMode: Image.PreserveAspectFit
+ }
+
+ Text {
+ id: welcomeTo
+ color: Constants.currentGlobalText
+ text: qsTr("Welcome to")
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.left: brandIcon.right
+ anchors.leftMargin: 5
+ verticalAlignment: Text.AlignVCenter
+ font.pixelSize: 36
+ font.family: "titillium web"
+ }
+
+ Text {
+ id: brandLabel
+ color: Constants.currentBrand
+ text: qsTr("Qt Design Studio")
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.left: welcomeTo.right
+ anchors.leftMargin: 8
+ verticalAlignment: Text.AlignVCenter
+ font.pixelSize: 36
+ font.family: "titillium web"
+ }
+
+ Text {
+ width: 291
+ height: 55
+ color: Constants.currentGlobalText
+ text: {
+ if (Constants.communityEdition)
+ return qsTr("Community Edition")
+ if (Constants.enterpriseEdition)
+ return qsTr("Enterprise Edition")
+ return qsTr("Professional Edition")
+ }
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.left: brandLabel.right
+ anchors.leftMargin: 8
+ verticalAlignment: Text.AlignVCenter
+ font.pixelSize: 36
+ font.family: "titillium web"
+ }
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/CheckButton.ui.qml b/share/qtcreator/qmldesigner/welcomepage/CheckButton.ui.qml
new file mode 100644
index 0000000000..1e1f4557a1
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/CheckButton.ui.qml
@@ -0,0 +1,108 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtQuick.Templates
+import WelcomeScreen 1.0
+
+Button {
+ id: control
+
+ implicitWidth: Math.max(
+ buttonBackground ? buttonBackground.implicitWidth : 0,
+ textItem.implicitWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(
+ buttonBackground ? buttonBackground.implicitHeight : 0,
+ textItem.implicitHeight + topPadding + bottomPadding)
+ leftPadding: 4
+ rightPadding: 4
+
+ text: "My Button"
+ checkable: true
+ state: "normal"
+
+ property bool decorated: false
+
+ background: Rectangle {
+ id: buttonBackground
+ color: "#00000000"
+ implicitWidth: 100
+ implicitHeight: 40
+ opacity: buttonBackground.enabled ? 1 : 0.3
+ radius: 2
+ border.color: "#047eff"
+ anchors.fill: parent
+ }
+
+ contentItem: Text {
+ id: textItem
+ text: control.text
+ font.pixelSize: 18
+ opacity: textItem.enabled ? 1.0 : 0.3
+ color: "#047eff"
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ }
+
+ Rectangle {
+ id: decoration
+ width: 10
+ visible: control.decorated
+ color: Constants.currentBrand
+ border.color: Constants.currentBrand
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.rightMargin: 1
+ anchors.bottomMargin: 1
+ anchors.topMargin: 1
+ }
+
+ states: [
+ State {
+ name: "normal"
+ when: !control.down && !control.hovered && !control.checked
+
+ PropertyChanges {
+ target: buttonBackground
+ color: Constants.currentPushButtonNormalBackground
+ border.color: Constants.currentPushButtonNormalOutline
+ }
+
+ PropertyChanges {
+ target: textItem
+ color: Constants.currentGlobalText
+ }
+ },
+ State {
+ name: "hover"
+ when: control.hovered && !control.checked && !control.down
+
+ PropertyChanges {
+ target: textItem
+ color: Constants.currentGlobalText
+ }
+
+ PropertyChanges {
+ target: buttonBackground
+ color: Constants.currentPushButtonHoverBackground
+ border.color: Constants.currentPushButtonHoverOutline
+ }
+ },
+ State {
+ name: "active"
+ when: control.checked || control.down
+
+ PropertyChanges {
+ target: textItem
+ color: Constants.darkActiveGlobalText
+ }
+
+ PropertyChanges {
+ target: buttonBackground
+ color: Constants.currentBrand
+ border.color: "#00000000"
+ }
+ }
+ ]
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/CustomDialog.qml b/share/qtcreator/qmldesigner/welcomepage/CustomDialog.qml
new file mode 100644
index 0000000000..76b3c4c8e7
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/CustomDialog.qml
@@ -0,0 +1,42 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtQuick.Controls
+import WelcomeScreen 1.0
+
+Dialog {
+ id: root
+ padding: 12
+
+ background: Rectangle {
+ color: Constants.currentDialogBackground
+ border.color: Constants.currentDialogBorder
+ border.width: 1
+ }
+
+ header: Label {
+ text: root.title
+ visible: root.title
+ elide: Label.ElideRight
+ font.bold: true
+ padding: 12
+ color: Constants.currentGlobalText
+
+ background: Rectangle {
+ x: 1
+ y: 1
+ width: parent.width - 2
+ height: parent.height - 1
+ color: Constants.currentDialogBackground
+ }
+ }
+
+ footer: CustomDialogButtonBox {
+ visible: count > 0
+ }
+
+ Overlay.modal: Rectangle {
+ color: Color.transparent(Constants.currentDialogBackground, 0.5)
+ }
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/CustomDialogButtonBox.qml b/share/qtcreator/qmldesigner/welcomepage/CustomDialogButtonBox.qml
new file mode 100644
index 0000000000..8437e5dbe3
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/CustomDialogButtonBox.qml
@@ -0,0 +1,25 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtQuick.Controls
+import WelcomeScreen 1.0
+
+DialogButtonBox {
+ id: root
+ padding: 12
+ alignment: Qt.AlignRight | Qt.AlignBottom
+
+ background: Rectangle {
+ implicitHeight: 40
+ x: 1
+ y: 1
+ width: parent.width - 2
+ height: parent.height - 2
+ color: Constants.currentDialogBackground
+ }
+
+ delegate: DialogButton {
+ width: root.count === 1 ? root.availableWidth / 2 : undefined
+ }
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/CustomGrid.qml b/share/qtcreator/qmldesigner/welcomepage/CustomGrid.qml
new file mode 100644
index 0000000000..bc7c4faf4a
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/CustomGrid.qml
@@ -0,0 +1,41 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtQuick.Layouts
+import WelcomeScreen 1.0
+import DataModels 1.0
+
+Item {
+ id: gridContainer
+ width: 1460
+ height: 760
+
+ property alias hover: scrollView.outsideHover
+ property alias model: gridView.model
+ property alias delegate: gridView.delegate
+
+ Connections {
+ target: gridContainer
+ onWidthChanged: Constants.responsiveResize(gridContainer.width)
+ }
+
+ CustomScrollView {
+ id: scrollView
+ anchors.fill: parent
+
+ GridView {
+ id: gridView
+ clip: true
+ anchors.fill: parent
+ rightMargin: -Constants.gridSpacing
+ bottomMargin: -Constants.gridSpacing
+ boundsBehavior: Flickable.StopAtBounds
+ cellWidth: Constants.gridCellSize
+ cellHeight: Constants.gridCellSize
+
+ model: ExamplesModel {}
+ delegate: ThumbnailDelegate {}
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/CustomScrollBar.qml b/share/qtcreator/qmldesigner/welcomepage/CustomScrollBar.qml
new file mode 100644
index 0000000000..1cc020774f
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/CustomScrollBar.qml
@@ -0,0 +1,98 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtQuick.Templates as T
+import WelcomeScreen 1.0
+import StudioTheme 1.0 as StudioTheme
+
+T.ScrollBar {
+ id: control
+
+ property bool show: false
+ property bool otherInUse: false
+ property bool isNeeded: control.size < 1.0
+ property bool inUse: control.hovered || control.pressed
+ property int thickness: control.inUse || control.otherInUse ? 10 : 8
+
+ property bool scrollBarVisible: parent.childrenRect.height > parent.height
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding)
+
+ hoverEnabled: true
+ padding: 0
+ minimumSize: orientation === Qt.Horizontal ? height / width : width / height
+
+ opacity: 0.0
+
+ contentItem: Rectangle {
+ implicitWidth: control.thickness
+ implicitHeight: control.thickness
+ radius: width / 2
+ color: control.inUse ? Constants.currentScrollBarHandle
+ : Constants.currentScrollBarHandle_idle
+ }
+
+ background: Rectangle {
+ id: controlTrack
+ color: Constants.currentScrollBarTrack
+ opacity: control.inUse || control.otherInUse ? 0.3 : 0.0
+ radius: width / 2
+
+ Behavior on opacity {
+ PropertyAnimation {
+ duration: 100
+ easing.type: Easing.InOutQuad
+ }
+ }
+ }
+
+ states: [
+ State {
+ name: "show"
+ when: control.show
+ PropertyChanges {
+ target: control
+ opacity: 1.0
+ }
+ },
+ State {
+ name: "hide"
+ when: !control.show
+ PropertyChanges {
+ target: control
+ opacity: 0.0
+ }
+ }
+ ]
+
+ transitions: Transition {
+ from: "show"
+ SequentialAnimation {
+ PauseAnimation { duration: 450 }
+ NumberAnimation {
+ target: control
+ duration: 200
+ property: "opacity"
+ to: 0.0
+ }
+ }
+ }
+
+ Behavior on thickness {
+ PropertyAnimation {
+ duration: 100
+ easing.type: Easing.InOutQuad
+ }
+ }
+
+ Behavior on x {
+ PropertyAnimation {
+ duration: 100
+ easing.type: Easing.InOutQuad
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/CustomScrollView.qml b/share/qtcreator/qmldesigner/welcomepage/CustomScrollView.qml
new file mode 100644
index 0000000000..5526cb3e1d
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/CustomScrollView.qml
@@ -0,0 +1,25 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtQuick.Templates as T
+
+T.ScrollView {
+ id: control
+
+ property bool outsideHover: false
+
+ hoverEnabled: true
+
+ T.ScrollBar.vertical: CustomScrollBar {
+ id: verticalScrollBar
+ parent: control
+ x: control.width + (verticalScrollBar.inUse ? 4 : 5)
+ y: control.topPadding
+ height: control.availableHeight
+ orientation: Qt.Vertical
+
+ show: (control.hovered || control.focus || control.outsideHover)
+ && verticalScrollBar.isNeeded
+ }
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/DialogButton.qml b/share/qtcreator/qmldesigner/welcomepage/DialogButton.qml
new file mode 100644
index 0000000000..e7fb13e042
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/DialogButton.qml
@@ -0,0 +1,89 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtQuick.Templates
+import WelcomeScreen 1.0
+
+Button {
+ id: root
+
+ implicitWidth: Math.max(
+ background ? background.implicitWidth : 0,
+ textItem.implicitWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(
+ background ? background.implicitHeight : 0,
+ textItem.implicitHeight + topPadding + bottomPadding)
+ leftPadding: 4
+ rightPadding: 4
+
+
+ background: Rectangle {
+ id: background
+ implicitWidth: 80
+ implicitHeight: 20
+ opacity: enabled ? 1 : 0.3
+ radius: 2
+ color: Constants.currentPushButtonNormalBackground
+ border.color: Constants.currentPushButtonNormalOutline
+ anchors.fill: parent
+ }
+
+ contentItem: Text {
+ id: textItem
+ text: root.text
+ font.pixelSize: 12
+ opacity: enabled ? 1.0 : 0.3
+ color: Constants.currentGlobalText
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ }
+
+ states: [
+ State {
+ name: "default"
+ when: !root.down && !root.hovered && !root.checked
+
+ PropertyChanges {
+ target: background
+ color: Constants.currentPushButtonNormalBackground
+ border.color: Constants.currentPushButtonNormalOutline
+ }
+
+ PropertyChanges {
+ target: textItem
+ color: Constants.currentGlobalText
+ }
+ },
+ State {
+ name: "hover"
+ when: root.hovered && !root.checked && !root.down
+
+ PropertyChanges {
+ target: textItem
+ color: Constants.currentGlobalText
+ }
+
+ PropertyChanges {
+ target: background
+ color: Constants.currentPushButtonHoverBackground
+ border.color: Constants.currentPushButtonHoverOutline
+ }
+ },
+ State {
+ name: "active"
+ when: root.checked || root.down
+
+ PropertyChanges {
+ target: textItem
+ color: Constants.currentActiveGlobalText
+ }
+
+ PropertyChanges {
+ target: background
+ color: Constants.currentBrand
+ border.color: "#00000000"
+ }
+ }
+ ]
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/DownloadButton.qml b/share/qtcreator/qmldesigner/welcomepage/DownloadButton.qml
new file mode 100644
index 0000000000..07f107eb33
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/DownloadButton.qml
@@ -0,0 +1,134 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtQuick.Controls
+import WelcomeScreen 1.0
+import StudioTheme 1.0 as StudioTheme
+
+Item {
+ id: root
+ width: 30
+ height: 30
+ state: "default"
+
+ property bool dowloadPressed: false
+ property bool isHovered: mouseArea.containsMouse
+
+ property bool globalHover: false
+
+ property bool alreadyDownloaded: false
+ property bool updateAvailable: false
+ property bool downloadUnavailable: false
+
+ signal downloadClicked()
+
+ property color currentColor: {
+ if (root.updateAvailable)
+ return Constants.amberLight
+ if (root.alreadyDownloaded)
+ return Constants.greenLight
+ if (root.downloadUnavailable)
+ return Constants.redLight
+
+ return Constants.currentGlobalText
+ }
+
+ property string currentIcon: {
+ if (root.updateAvailable)
+ return StudioTheme.Constants.downloadUpdate
+ if (root.alreadyDownloaded)
+ return StudioTheme.Constants.downloaded
+ if (root.downloadUnavailable)
+ return StudioTheme.Constants.downloadUnavailable
+
+ return StudioTheme.Constants.download
+ }
+
+ property string currentToolTipText: {
+ if (root.updateAvailable)
+ return qsTr("Update available.")
+ if (root.alreadyDownloaded)
+ return qsTr("Example was already downloaded.")
+ if (root.downloadUnavailable)
+ return qsTr("Network or example is not available or the link is broken.")
+
+ return qsTr("Download the example.")
+ }
+
+ Text {
+ id: downloadIcon
+ color: root.currentColor
+ font.family: StudioTheme.Constants.iconFont.family
+ text: root.currentIcon
+ anchors.fill: parent
+ font.pixelSize: 22
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ anchors.bottomMargin: 0
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ propagateComposedEvents: true
+
+ Connections {
+ target: mouseArea
+ onClicked: root.downloadClicked()
+ }
+ }
+
+ ToolTip {
+ id: toolTip
+ y: -toolTip.height
+ visible: mouseArea.containsMouse
+ text: root.currentToolTipText
+ delay: 1000
+ height: 20
+ background: Rectangle {
+ color: Constants.currentToolTipBackground
+ border.color: Constants.currentToolTipOutline
+ border.width: 1
+ }
+ contentItem: Text {
+ color: Constants.currentToolTipText
+ text: toolTip.text
+ verticalAlignment: Text.AlignVCenter
+ }
+ }
+
+ states: [
+ State {
+ name: "default"
+ when: !mouseArea.pressed && !mouseArea.containsMouse && !root.globalHover
+ PropertyChanges {
+ target: downloadIcon
+ color: root.currentColor
+ }
+ },
+ State {
+ name: "pressed"
+ when: mouseArea.pressed && mouseArea.containsMouse
+ PropertyChanges {
+ target: downloadIcon
+ color: Constants.currentBrand
+ scale: 1.2
+ }
+ },
+ State {
+ name: "hover"
+ when: mouseArea.containsMouse && !mouseArea.pressed && !root.globalHover
+ PropertyChanges {
+ target: downloadIcon
+ scale: 1.2
+ }
+ },
+ State {
+ name: "globalHover"
+ extend: "hover"
+ when: root.globalHover && !mouseArea.pressed && !mouseArea.containsMouse
+ }
+ ]
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/DownloadPanel.qml b/share/qtcreator/qmldesigner/welcomepage/DownloadPanel.qml
new file mode 100644
index 0000000000..8cd7099787
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/DownloadPanel.qml
@@ -0,0 +1,79 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtQuick.Controls
+import WelcomeScreen 1.0
+
+Rectangle {
+ id: root
+ color: Constants.currentNormalThumbnailBackground
+
+ property alias value: progressBar.value
+ property alias text: progressLabel.text
+ property alias allowCancel: progressBar.closeButtonVisible
+
+ readonly property int pixelSize: 12
+ readonly property int textMargin: 5
+
+ signal cancelRequested
+
+ DownloadProgressBar {
+ id: progressBar
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottom: pushButton.top
+ anchors.bottomMargin: 40
+ anchors.rightMargin: 10
+ anchors.leftMargin: 10
+
+ onCancelRequested: root.cancelRequested()
+
+ Text {
+ id: progressLabel
+ color: Constants.currentGlobalText
+ text: qsTr("Progress:")
+ anchors.top: parent.bottom
+ anchors.topMargin: root.textMargin
+ anchors.left: parent.left
+ font.pixelSize: root.pixelSize
+ }
+
+ Text {
+ id: progressAmount
+ color: Constants.currentGlobalText
+ text: stringMapper.text
+ anchors.top: parent.bottom
+ anchors.topMargin: root.textMargin
+ anchors.right: percentSign.left
+ anchors.rightMargin: root.textMargin
+ font.pixelSize: root.pixelSize
+ }
+
+ Text {
+ id: percentSign
+ color: Constants.currentGlobalText
+ text: qsTr("%")
+ anchors.right: parent.right
+ anchors.top: parent.bottom
+ anchors.topMargin: root.textMargin
+ font.pixelSize: root.pixelSize
+ }
+ }
+
+ PushButton {
+ id: pushButton
+ y: 177
+ visible: progressBar.downloadFinished
+ text: qsTr("Open")
+ anchors.bottom: parent.bottom
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.bottomMargin: 40
+ }
+
+ StringMapper {
+ id: stringMapper
+ decimals: 1
+ input: root.value
+ }
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/DownloadProgressBar.qml b/share/qtcreator/qmldesigner/welcomepage/DownloadProgressBar.qml
new file mode 100644
index 0000000000..5fb0f637ca
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/DownloadProgressBar.qml
@@ -0,0 +1,80 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtQuick.Controls
+import WelcomeScreen 1.0
+import StudioTheme as StudioTheme
+
+Item {
+ id: progressBar
+ width: 272
+ height: 25
+ property bool downloadFinished: false
+ property int value: 0
+ property bool closeButtonVisible
+ //property alias numberAnimationRunning: numberAnimation.running
+
+ readonly property int margin: 4
+
+ signal cancelRequested
+
+ Rectangle {
+ id: progressBarGroove
+ color: Constants.currentNormalThumbnailLabelBackground
+ anchors.fill: parent
+ }
+
+ Rectangle {
+ id: progressBarTrack
+ width: progressBar.value * ((progressBar.width - closeButton.width) - 2 * progressBar.margin) / 100
+ color: Constants.currentBrand
+ border.color: "#002e769e"
+ anchors.left: parent.left
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.margins: progressBar.margin
+ }
+
+ Text {
+ id: closeButton
+ visible: progressBar.closeButtonVisible
+ width: 20
+ text: StudioTheme.Constants.closeCross
+ color: Constants.currentBrand
+ horizontalAlignment: Qt.AlignHCenter
+ verticalAlignment: Qt.AlignVCenter
+ font.family: StudioTheme.Constants.iconFont.family
+ font.pixelSize: StudioTheme.Values.myIconFontSize
+
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.margins: progressBar.margin
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ progressBar.cancelRequested()
+ }
+ }
+ }
+
+/*
+ NumberAnimation {
+ id: numberAnimation
+ target: progressBarTrack
+ property: "width"
+ duration: 2500
+ easing.bezierCurve: [0.197,0.543,0.348,0.279,0.417,0.562,0.437,0.757,0.548,0.731,0.616,0.748,0.728,0.789,0.735,0.982,1,1]
+ alwaysRunToEnd: true
+ to: progressBar.width
+ from: 0
+ }
+
+ Connections {
+ target: numberAnimation
+ onFinished: progressBar.downloadFinished = true
+ }
+*/
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/MainGridStack.qml b/share/qtcreator/qmldesigner/welcomepage/MainGridStack.qml
new file mode 100644
index 0000000000..73b023bddc
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/MainGridStack.qml
@@ -0,0 +1,166 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+import WelcomeScreen 1.0
+import projectmodel 1.0
+import DataModels 1.0
+import UiTour
+import StudioControls as StudioControls
+
+Item {
+ id: thumbnails
+ width: 1500
+ height: 800
+ clip: true
+
+ property alias stackLayoutCurrentIndex: gridStackLayout.currentIndex
+ property var projectModel: Constants.projectModel
+
+ Rectangle {
+ id: thumbnailGridBack
+ color: Constants.currentThumbnailGridBackground
+ anchors.fill: parent
+
+ HoverHandler { id: hoverHandler }
+
+ StackLayout {
+ id: gridStackLayout
+ visible: !Constants.isListView
+ anchors.fill: parent
+ anchors.margins: Constants.gridMargins
+ currentIndex: 0
+
+ CustomGrid {
+ id: recentGrid
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ hover: hoverHandler.hovered
+ model: thumbnails.projectModel
+ delegate: ThumbnailDelegate {
+ id: delegate
+ type: ThumbnailDelegate.Type.RecentProject
+ hasPath: true
+ thumbnailPlaceholderSource: previewUrl
+ onClicked: projectModel.openProjectAt(index)
+ onRightClicked: {
+ removeMenuItem.index = index
+ contextMenu.popup(delegate)
+ }
+ }
+
+ Text {
+ text: qsTr("Create a new project using the \"<b>Create Project</b>\" or open an existing project using the \"<b>Open Project</b>\" option. ")
+ font.pixelSize: 18
+ color: Constants.currentGlobalText
+ anchors.centerIn: parent
+ width: recentGrid.width
+ horizontalAlignment: Text.AlignHCenter
+ leftPadding: 20
+ rightPadding: 20
+ wrapMode: Text.WordWrap
+ visible: projectModel.count === 0
+ }
+
+ StudioControls.Menu {
+ id: contextMenu
+
+ StudioControls.MenuItem {
+ id: removeMenuItem
+
+ property int index: -1
+
+ text: qsTr("Remove Project from Recent Projects")
+ onTriggered: projectModel.removeFromRecentProjects(removeMenuItem.index)
+ }
+
+ StudioControls.MenuItem {
+ text: qsTr("Clear Recent Project List")
+ onTriggered: projectModel.clearRecentProjects()
+ }
+ }
+ }
+
+ CustomGrid {
+ id: examplesGrid
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ hover: hoverHandler.hovered
+ model: ExamplesModel { id: examplesModel}
+ delegate: ThumbnailDelegate {
+ type: ThumbnailDelegate.Type.Example
+ downloadable: showDownload
+ hasUpdate: showUpdate
+ downloadUrl: url
+ thumbnailPlaceholderSource: examplesModel.resolveUrl(thumbnail)
+ onClicked: projectModel.openExample(targetPath,
+ projectName,
+ qmlFileName,
+ explicitQmlproject)
+ }
+ }
+
+ CustomGrid {
+ id: tutorialsGrid
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ hover: hoverHandler.hovered
+ model: TutorialsModel { id: tutorialsModel}
+ delegate: ThumbnailDelegate {
+ type: ThumbnailDelegate.Type.Tutorial
+ thumbnailPlaceholderSource: tutorialsModel.resolveUrl(thumbnail)
+ onClicked: Qt.openUrlExternally(url)
+ }
+ }
+
+ CustomGrid {
+ id: tourGrid
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ hover: hoverHandler.hovered
+ model: TourModel {}
+ delegate: TourThumbnailDelegate {
+ id: thumbnailDelegate
+ visible: !slidePlayer.visible
+ enabled: !slidePlayer.visible
+
+ Connections {
+ target: thumbnailDelegate
+ onClicked: tourGrid.startTour(qmlFileName)
+ }
+ }
+
+ function startTour(url) {
+ slidePlayer.visible = true
+ slidePlayer.slideSource = Qt.resolvedUrl(url)
+ }
+
+ SlidePlayer {
+ id: slidePlayer
+ anchors.fill: parent
+ visible: false
+ }
+
+ TourDialogButton {
+ id: closeButton
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.rightMargin: 16
+ anchors.topMargin: 16
+ visible: slidePlayer.visible
+
+ Connections {
+ target: closeButton
+ onButtonClicked: {
+ slidePlayer.visible = false
+ slidePlayer.loaderActive = false
+ slidePlayer.loaderActive = true
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/MainScreen.qml b/share/qtcreator/qmldesigner/welcomepage/MainScreen.qml
new file mode 100644
index 0000000000..b2e09d4308
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/MainScreen.qml
@@ -0,0 +1,318 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+import WelcomeScreen 1.0
+import projectmodel 1.0
+import DataModels 1.0
+
+Rectangle {
+ id: appBackground
+ height: Constants.height
+ color: Constants.currentThemeBackground
+ width: 1842
+ //anchors.fill: parent //this is required to make it responsive but commented out to force minimum size to work
+ property int pageIndex: 0
+ property bool designMode: !(typeof (Constants.projectModel.designMode) === "undefined")
+
+ signal openUiTour
+ signal closeUiTour
+
+ function uiTourClosed() {
+ recentProjects.checked = true
+ }
+
+ TestControlPanel {
+ id: controlPanel
+ x: 1644
+ width: 220
+ height: 127
+ visible: appBackground.designMode
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.topMargin: 15
+ anchors.rightMargin: 56
+ }
+
+ ColumnLayout {
+ id: openCreatelayout
+ y: 150
+ anchors.left: parent.left
+ anchors.right: thumbnails.left
+ anchors.rightMargin: 20
+ spacing: 15
+ anchors.leftMargin: 20
+
+ PushButton {
+ id: createProject
+ height: 50
+ text: qsTr("Create Project ...")
+
+ Layout.maximumHeight: 75
+ Layout.minimumHeight: 25
+ Layout.fillWidth: true
+ Layout.preferredHeight: 50
+ decorated: true
+ onClicked: Constants.projectModel.createProject()
+ }
+
+ PushButton {
+ id: openProject
+ height: 50
+ text: qsTr("Open Project ...")
+
+ Layout.maximumHeight: 75
+ Layout.minimumHeight: 25
+ Layout.fillWidth: true
+ Layout.preferredHeight: 50
+ decorated: true
+ onClicked: Constants.projectModel.openProject()
+ }
+
+ Text {
+ id: newQtLabel
+ width: 266
+ height: 40
+ color: Constants.currentGlobalText
+ text: qsTr("New to Qt?")
+ font.pixelSize: 24
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ Layout.fillWidth: true
+ }
+
+ PushButton {
+ id: getStarted
+ height: 50
+ text: qsTr("Get Started")
+ Layout.maximumHeight: 75
+ Layout.minimumHeight: 25
+ Layout.preferredHeight: 50
+ Layout.fillWidth: true
+ onClicked: Constants.projectModel.showHelp()
+ }
+ }
+
+ ColumnLayout {
+ id: currentPageMenuLayout
+ y: 422
+ anchors.left: parent.left
+ anchors.right: thumbnails.left
+ anchors.rightMargin: 20
+ anchors.leftMargin: 20
+ spacing: 15
+
+ CheckButton {
+ id: recentProjects
+ text: qsTr("Recent Projects")
+ autoExclusive: true
+ checked: true
+ Layout.fillWidth: true
+
+ Connections {
+ target: recentProjects
+ function onClicked(mouse) { appBackground.pageIndex = 0 }
+ }
+ }
+
+ CheckButton {
+ id: examples
+ text: qsTr("Examples")
+ autoExclusive: true
+ Layout.fillWidth: true
+
+ Connections {
+ target: examples
+ function onClicked(mouse) { appBackground.pageIndex = 1 }
+ }
+ }
+
+ CheckButton {
+ id: tutorials
+ text: qsTr("Tutorials")
+ autoExclusive: true
+ Layout.fillWidth: true
+
+ Connections {
+ target: tutorials
+ function onClicked(mouse) { appBackground.pageIndex = 2 }
+ }
+ }
+
+ CheckButton {
+ id: tours
+ text: qsTr("UI Tour")
+ autoExclusive: true
+ Layout.fillWidth: true
+
+ Connections {
+ target: tours
+ function onClicked(mouse) { appBackground.pageIndex = 3 }
+ }
+ }
+ }
+
+ BrandBar {
+ id: brandBar
+ y: 0
+ anchors.left: parent.left
+ anchors.leftMargin: 20
+
+ Rectangle {
+ id: loadProgress
+ x: 4
+ y: 120
+ width: Constants.loadingProgress * 10
+ height: 4
+ color: Constants.currentGlobalText
+ opacity: Constants.loadingProgress > 90 ? (100 - Constants.loadingProgress) / 10 : 1
+ }
+ }
+
+ MainGridStack {
+ id: thumbnails
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.topMargin: 150
+ anchors.rightMargin: 56
+ anchors.bottomMargin: 54
+ anchors.leftMargin: 290
+ stackLayoutCurrentIndex: appBackground.pageIndex
+ }
+
+ RowLayout {
+ id: linkRow
+ y: 1041
+ height: 25
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ anchors.leftMargin: 290
+ anchors.rightMargin: 55
+ anchors.bottomMargin: 14
+ spacing: 0
+
+ PushButton {
+ id: userGuide
+ text: qsTr("User Guide")
+ fontpixelSize: 12
+ Layout.minimumWidth: 100
+ Layout.fillWidth: true
+ Layout.preferredHeight: 25
+ Layout.preferredWidth: 200
+ decorated: true
+ onClicked: Qt.openUrlExternally("https://doc.qt.io/qtdesignstudio/")
+ }
+
+ Item {
+ width: 200
+ height: 200
+ Layout.fillWidth: true
+ Layout.preferredWidth: 50
+ Layout.preferredHeight: 25
+ }
+
+ PushButton {
+ id: blog
+ text: qsTr("Blog")
+ fontpixelSize: 12
+ Layout.minimumWidth: 100
+ Layout.fillWidth: true
+ Layout.preferredHeight: 25
+ Layout.preferredWidth: 200
+ decorated: true
+ onClicked: Qt.openUrlExternally("https://blog.qt.io/")
+ }
+
+ Item {
+ width: 200
+ height: 200
+ Layout.fillWidth: true
+ Layout.preferredWidth: 50
+ Layout.preferredHeight: 25
+ }
+
+ PushButton {
+ id: forums
+ text: qsTr("Forums")
+ fontpixelSize: 12
+ Layout.minimumWidth: 100
+ Layout.fillWidth: true
+ Layout.preferredHeight: 25
+ Layout.preferredWidth: 200
+ decorated: true
+ onClicked: Qt.openUrlExternally("https://forum.qt.io/")
+ }
+
+ Item {
+ width: 200
+ height: 200
+ Layout.fillWidth: true
+ Layout.preferredWidth: 50
+ Layout.preferredHeight: 25
+ }
+
+ PushButton {
+ id: account
+ text: qsTr("Account")
+ fontpixelSize: 12
+ Layout.minimumWidth: 100
+ Layout.fillWidth: true
+ Layout.preferredHeight: 25
+ Layout.preferredWidth: 200
+ decorated: true
+ onClicked: Qt.openUrlExternally("https://login.qt.io/login")
+ }
+
+ Item {
+ width: 200
+ height: 200
+ Layout.fillWidth: true
+ Layout.preferredWidth: 50
+ Layout.preferredHeight: 25
+ }
+
+ PushButton {
+ id: getQt
+ text: qsTr("Get Qt")
+ fontpixelSize: 12
+ Layout.minimumWidth: 100
+ Layout.fillWidth: true
+ Layout.preferredHeight: 25
+ Layout.preferredWidth: 200
+ decorated: true
+ onClicked: Qt.openUrlExternally("https://www.qt.io/pricing")
+ }
+
+ Item {
+ width: 200
+ height: 200
+ Layout.fillWidth: true
+ Layout.preferredWidth: 50
+ Layout.preferredHeight: 25
+ }
+
+ SocialButton {
+ id: social
+ text: ""
+ Layout.minimumWidth: 100
+ Layout.fillWidth: true
+ Layout.preferredHeight: 25
+ Layout.preferredWidth: 200
+ decorated: true
+ }
+ }
+
+ BlogBanner {
+ id: blogBanner
+ anchors.left: parent.left
+ anchors.leftMargin: 20
+ anchors.right: thumbnails.left
+ anchors.rightMargin: 20
+ y: 657
+ }
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/PushButton.ui.qml b/share/qtcreator/qmldesigner/welcomepage/PushButton.ui.qml
new file mode 100644
index 0000000000..a87c0241c6
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/PushButton.ui.qml
@@ -0,0 +1,108 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtQuick.Templates
+import WelcomeScreen 1.0
+
+Button {
+ id: control
+
+ implicitWidth: Math.max(
+ buttonBackground ? buttonBackground.implicitWidth : 0,
+ textItem.implicitWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(
+ buttonBackground ? buttonBackground.implicitHeight : 0,
+ textItem.implicitHeight + topPadding + bottomPadding)
+ leftPadding: 4
+ rightPadding: 4
+
+ text: "My Button"
+ state: "normal"
+
+ property alias fontpixelSize: textItem.font.pixelSize
+ property bool decorated: false
+
+ background: Rectangle {
+ id: buttonBackground
+ color: "#00000000"
+ implicitWidth: 100
+ implicitHeight: 40
+ opacity: buttonBackground.enabled ? 1 : 0.3
+ radius: 2
+ border.color: "#047eff"
+ anchors.fill: parent
+ }
+
+ contentItem: Text {
+ id: textItem
+ text: control.text
+ font.pixelSize: 18
+ opacity: textItem.enabled ? 1.0 : 0.3
+ color: Constants.currentGlobalText
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ }
+
+ Rectangle {
+ id: decoration
+ width: 10
+ visible: control.decorated
+ color: Constants.currentBrand
+ border.color: Constants.currentBrand
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.rightMargin: 1
+ anchors.bottomMargin: 1
+ anchors.topMargin: 1
+ }
+
+ states: [
+ State {
+ name: "normal"
+ when: !control.down && !control.hovered
+
+ PropertyChanges {
+ target: buttonBackground
+ color: Constants.currentPushButtonNormalBackground
+ border.color: Constants.currentPushButtonNormalOutline
+ }
+
+ PropertyChanges {
+ target: textItem
+ color: Constants.currentGlobalText
+ }
+ },
+ State {
+ name: "hover"
+ when: control.hovered && !control.down
+
+ PropertyChanges {
+ target: textItem
+ color: Constants.currentGlobalText
+ }
+
+ PropertyChanges {
+ target: buttonBackground
+ color: Constants.currentPushButtonHoverBackground
+ border.color: Constants.currentPushButtonHoverOutline
+ }
+ },
+ State {
+ name: "press"
+ when: control.down
+
+ PropertyChanges {
+ target: textItem
+ color: Constants.darkActiveGlobalText
+ }
+
+ PropertyChanges {
+ target: buttonBackground
+ color: Constants.currentBrand
+ border.color: "#00000000"
+ }
+ }
+ ]
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/RangeMapper.qml b/share/qtcreator/qmldesigner/welcomepage/RangeMapper.qml
new file mode 100644
index 0000000000..76c67f719f
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/RangeMapper.qml
@@ -0,0 +1,42 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+
+QtObject {
+ id: object
+
+/*!
+ The input value.
+*/
+ property real input: 0
+
+/*!
+ The output value.
+*/
+ property real output: {
+ var slope = (object.outputMaximum - object.outputMinimum) / (object.inputMaximum - object.inputMinimum)
+ return object.outputMinimum + slope * (object.input - object.inputMinimum)
+ }
+
+/*!
+ The minimum input value.
+*/
+ property real inputMinimum: 0
+
+/*!
+ The maximum input value.
+*/
+ property real inputMaximum: 100
+
+/*!
+ The minimum output value.
+*/
+ property real outputMinimum: 0
+
+/*!
+ The maximum output value.
+*/
+ property real outputMaximum: 100
+
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/SocialButton.qml b/share/qtcreator/qmldesigner/welcomepage/SocialButton.qml
new file mode 100644
index 0000000000..864486966d
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/SocialButton.qml
@@ -0,0 +1,129 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtQuick.Templates
+import QtQuick.Layouts
+import WelcomeScreen 1.0
+
+Button {
+ id: control
+
+ implicitWidth: Math.max(
+ buttonBackground ? buttonBackground.implicitWidth : 0,
+ textItem.implicitWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(
+ buttonBackground ? buttonBackground.implicitHeight : 0,
+ textItem.implicitHeight + topPadding + bottomPadding)
+ leftPadding: 4
+ rightPadding: 4
+
+ text: ""
+ visible: true
+ state: "normal"
+
+ property alias fontpixelSize: textItem.font.pixelSize
+ property bool decorated: false
+
+ background: Rectangle {
+ id: buttonBackground
+ color: "#fca4a4"
+ implicitWidth: 100
+ implicitHeight: 40
+ opacity: buttonBackground.enabled ? 1 : 0.3
+ radius: 2
+ border.color: "#047eff"
+ anchors.fill: parent
+ }
+
+ contentItem: Text {
+ id: textItem
+ visible: false
+ text: qsTr("Text")
+ font.pixelSize: 12
+ }
+
+ Rectangle {
+ id: decoration
+ width: 10
+ visible: control.decorated
+ color: Constants.currentBrand
+ border.color: Constants.currentBrand
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.rightMargin: 1
+ anchors.bottomMargin: 1
+ anchors.topMargin: 1
+ }
+
+ RowLayout {
+ anchors.fill: parent
+
+ Item {
+ width: 200
+ height: 200
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ }
+
+ YoutubeButton {
+ id: youtubeButton
+ Layout.fillHeight: true
+ Layout.preferredWidth: 60
+ }
+
+ Item {
+ width: 200
+ height: 200
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ }
+
+ TwitterButton {
+ id: twitterButton
+ Layout.maximumHeight: 15
+ Layout.minimumHeight: 15
+ Layout.preferredHeight: 15
+ Layout.fillHeight: false
+ Layout.preferredWidth: 25
+ }
+
+ Item {
+ width: 200
+ height: 200
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ }
+ }
+
+ states: [
+ State {
+ name: "normal"
+ when: !youtubeButton.isHovered && !twitterButton.isHovered && !control.hovered
+
+ PropertyChanges {
+ target: buttonBackground
+ color: Constants.currentPushButtonNormalBackground
+ border.color: Constants.currentPushButtonNormalOutline
+ }
+ },
+ State {
+ name: "hover"
+ when: control.hovered || youtubeButton.isHovered || twitterButton.isHovered
+
+ PropertyChanges {
+ target: buttonBackground
+ color: Constants.currentPushButtonHoverBackground
+ border.color: Constants.currentPushButtonHoverOutline
+ }
+ }
+ ]
+}
+
+/*##^##
+Designer {
+ D{i:0;formeditorZoom:4;height:25;width:207}D{i:3;locked:true}D{i:7}D{i:9}
+}
+##^##*/
+
diff --git a/share/qtcreator/qmldesigner/welcomepage/StringMapper.qml b/share/qtcreator/qmldesigner/welcomepage/StringMapper.qml
new file mode 100644
index 0000000000..71d17117fb
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/StringMapper.qml
@@ -0,0 +1,68 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick 2.10
+
+/*!
+ \qmltype StringMapper
+ \inqmlmodule QtQuick.Studio.LogicHelper
+ \since QtQuick.Studio.LogicHelper 1.0
+ \inherits QtObject
+
+ \brief Converts numbers to strings with the defined precision.
+
+ The StringMapper type maps numbers to strings. The string mapper
+ \l input property is bound to the \c value property of a control that
+ provides the number and the \l text property of the string mapper is
+ mapped to the \c text property of type that displays the string.
+
+ Designers can use the String Mapper type in \QDS instead of writing
+ JavaScript expressions.
+
+ \section1 Example Usage
+
+ In the following example, we use \l Text type to display the numerical
+ value of a \l Slider type as a string:
+
+ \code
+ Rectangle {
+ Slider {
+ id: slider
+ value: 0.5
+ }
+ Text {
+ id: text1
+ text: stringMapper.text
+ }
+ StringMapper {
+ id: stringMapper
+ input: slider.value
+ }
+ }
+ \endcode
+*/
+
+QtObject {
+ id: object
+
+/*!
+ The value to convert to a string.
+*/
+ property real input: 0
+
+/*!
+ The number of digits after the decimal separator.
+*/
+ property int decimals: 2
+
+/*!
+ The \l input value as a string.
+*/
+ property string text: object.input.toFixed(object.decimals)
+}
+
+/*##^##
+Designer {
+ D{i:0;autoSize:true;height:480;width:640}
+}
+##^##*/
diff --git a/share/qtcreator/qmldesigner/welcomepage/Tag.qml b/share/qtcreator/qmldesigner/welcomepage/Tag.qml
new file mode 100644
index 0000000000..109cf43516
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/Tag.qml
@@ -0,0 +1,28 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtQuick.Controls
+import WelcomeScreen 1.0
+import QtQuick.Layouts 1.0
+
+Rectangle {
+ id: tagBackground
+ width: 84
+ height: 15
+ color: Constants.currentBrand
+ visible: tagLabel.text.length
+
+ property alias text: tagLabel.text
+
+ Text {
+ id: tagLabel
+ color: Constants.darkActiveGlobalText
+ text: qsTr("tag name")
+ anchors.fill: parent
+ font.pixelSize: 10
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ //font.weight: Font.ExtraLight
+ }
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/TagArea.qml b/share/qtcreator/qmldesigner/welcomepage/TagArea.qml
new file mode 100644
index 0000000000..04722d7ba8
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/TagArea.qml
@@ -0,0 +1,43 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtQuick.Controls
+import WelcomeScreen 1.0
+import QtQuick.Layouts
+
+Item {
+ id: root
+ height: (repeater.count > root.columnCount) ? root.tagHeight * 2 + root.tagSpacing
+ : root.tagHeight
+
+ property alias tags: repeater.model
+ // private
+ property int tagWidth: 75
+ property int tagHeight: 25
+ property int tagSpacing: 4
+
+ readonly property int columnCount: 3
+
+ Connections {
+ target: root
+ onWidthChanged: root.tagWidth = Math.floor((root.width - root.tagSpacing
+ * (root.columnCount - 1)) / root.columnCount)
+ }
+
+ Flow {
+ anchors.fill: parent
+ spacing: root.tagSpacing
+
+ Repeater {
+ id: repeater
+ model: ["Qt 6", "Qt for MCU", "3D"]
+
+ Tag {
+ text: modelData
+ width: root.tagWidth
+ height: root.tagHeight
+ }
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/TestControlPanel.qml b/share/qtcreator/qmldesigner/welcomepage/TestControlPanel.qml
new file mode 100644
index 0000000000..50ed31cab7
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/TestControlPanel.qml
@@ -0,0 +1,153 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+import WelcomeScreen 1.0
+import StudioTheme 1.0 as Theme
+
+Rectangle {
+ id: controlPanel
+ width: 220
+ height: 80
+ color: "#9b787878"
+ radius: 10
+
+ property bool closeOpen: true
+
+ Text {
+ id: closeOpen
+ x: 203
+ color: "#ffffff"
+ text: qsTr("X")
+ anchors.right: parent.right
+ anchors.top: parent.top
+ font.pixelSize: 12
+ horizontalAlignment: Text.AlignRight
+ anchors.rightMargin: 9
+ anchors.topMargin: 6
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+
+ Connections {
+ target: mouseArea
+ function onClicked(mouse) { controlPanel.closeOpen = !controlPanel.closeOpen }
+ }
+ }
+ }
+
+ Text {
+ id: themeSwitchLabel
+ x: 8
+ y: 50
+ color: "#ffffff"
+ text: qsTr("Theme")
+ font.pixelSize: 12
+ horizontalAlignment: Text.AlignRight
+ anchors.rightMargin: 6
+ }
+
+ Text {
+ id: lightLabel
+ x: 172
+ y: 26
+ color: "#ffffff"
+ text: qsTr("light")
+ font.pixelSize: 12
+ horizontalAlignment: Text.AlignRight
+ }
+
+ Text {
+ id: darkLabel
+ x: 65
+ y: 26
+ color: "#ffffff"
+ text: qsTr("dark")
+ font.pixelSize: 12
+ horizontalAlignment: Text.AlignRight
+ }
+
+ Slider {
+ id: themeSlider
+ x: 58
+ y: 44
+ width: 145
+ height: 28
+ snapMode: RangeSlider.SnapAlways
+ value: 0
+ from: 0
+ to: 1
+ stepSize: 1
+
+ Connections {
+ target: themeSlider
+ function onValueChanged(value) { Theme.Values.style = themeSlider.value }
+ }
+ }
+
+ CheckBox {
+ id: basicCheckBox
+ x: 60
+ y: 79
+ text: qsTr("")
+ checked: true
+ onToggled: { Constants.basic = !Constants.basic }
+ }
+
+ CheckBox {
+ id: communityCheckBox
+ x: 174
+ y: 79
+ text: qsTr("")
+ checked: false
+ onToggled: { Constants.communityEdition = !Constants.communityEdition }
+ }
+
+ Text {
+ id: basicEditionLabel
+ x: 8
+ y: 92
+ color: "#ffffff"
+ text: qsTr("Basic")
+ font.pixelSize: 12
+ horizontalAlignment: Text.AlignRight
+ anchors.rightMargin: 6
+ }
+
+ Text {
+ id: communityEditionLabel
+ x: 116
+ y: 92
+ color: "#ffffff"
+ text: qsTr("Community")
+ font.pixelSize: 12
+ horizontalAlignment: Text.AlignRight
+ anchors.rightMargin: 6
+ }
+
+ states: [
+ State {
+ name: "open"
+ when: controlPanel.closeOpen
+ },
+ State {
+ name: "close"
+ when: !controlPanel.closeOpen
+
+ PropertyChanges {
+ target: closeOpen
+ text: qsTr("<")
+ }
+
+ PropertyChanges {
+ target: controlPanel
+ width: 28
+ height: 26
+ clip: true
+ }
+ }
+ ]
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/ThumbnailDelegate.qml b/share/qtcreator/qmldesigner/welcomepage/ThumbnailDelegate.qml
new file mode 100644
index 0000000000..d50627d05e
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/ThumbnailDelegate.qml
@@ -0,0 +1,630 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+import WelcomeScreen 1.0
+import ExampleCheckout 1.0
+
+Item {
+ id: root
+ width: Constants.thumbnailSize
+ height: Constants.thumbnailSize
+ clip: true
+ state: "normal"
+
+ property bool textWrapped: false
+ property bool hasDescription: false
+ property bool hasPath: false
+ property bool hasUpdate: false
+ property bool downloadable: false
+ property int numberOfPanels: 3
+
+ enum Type {
+ RecentProject,
+ Example,
+ Tutorial
+ }
+
+ property int type: ThumbnailDelegate.Type.RecentProject
+
+ property alias projectNameLabelText: projectNameLabel.text
+ property alias projectPathLabelText: projectPathLabel.text
+ property alias thumbnailPlaceholderSource: thumbnailPlaceholder.source
+
+ property alias downloadUrl: downloader.url
+ property alias tempFile: downloader.outputFile
+ property alias completeBaseName: downloader.completeBaseName
+ property alias targetPath: extractor.targetPath
+
+ property alias bannerLabelText: updateText.text
+
+ enum Panel {
+ InBetween,
+ Download,
+ Main,
+ Details
+ }
+
+ property int currentPanel: ThumbnailDelegate.Panel.Main
+
+ signal clicked()
+ signal rightClicked()
+
+ function startDownload() {
+ twirlToDownloadAnimation.start()
+ downloadPanel.text = downloadPanel.downloadText
+ downloadPanel.allowCancel = true
+ downloadPanel.value = Qt.binding(function() { return downloader.progress })
+ downloader.start()
+ mouseArea.enabled = false
+ }
+
+ function thumbnailClicked() {
+ if (root.type === ThumbnailDelegate.Type.RecentProject
+ || root.type === ThumbnailDelegate.Type.Tutorial)
+ root.clicked() // open recent project/tutorial
+
+ if (Constants.loadingProgress < 95)
+ return
+ if (root.type === ThumbnailDelegate.Type.Example) {
+ if (root.downloadable
+ && !downloadButton.alreadyDownloaded
+ && !downloadButton.downloadUnavailable) {
+ root.startDownload()
+ } else if (downloadButton.alreadyDownloaded) {
+ root.clicked() // open example
+ }
+ }
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ propagateComposedEvents: true
+ hoverEnabled: true
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
+
+ Connections {
+ target: mouseArea
+ function onClicked(mouse) {
+ if (mouse.button === Qt.RightButton)
+ root.rightClicked()
+ else
+ root.thumbnailClicked(mouse)
+ }
+ }
+ }
+
+ CustomDialog {
+ id: overwriteDialog
+ title: qsTr("Overwrite Example?")
+ standardButtons: Dialog.Yes | Dialog.No
+ modal: true
+ anchors.centerIn: parent
+
+ onAccepted: root.startDownload()
+
+ Text {
+ width: parent.width
+ horizontalAlignment: Text.AlignHCenter
+ font.pixelSize: 12
+ color: Constants.currentGlobalText
+ text: qsTr("Example already exists.<br>Do you want to replace it?")
+ }
+ }
+
+ Item {
+ id: canvas
+ width: Constants.thumbnailSize
+ height: Constants.thumbnailSize * root.numberOfPanels
+
+ DownloadPanel {
+ id: downloadPanel
+
+ height: Constants.thumbnailSize
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottom: mainPanel.top
+ radius: 10
+ value: downloader.progress
+
+ readonly property string downloadText: qsTr("Downloading...")
+ readonly property string extractText: qsTr("Extracting...")
+
+ onCancelRequested: downloader.cancel()
+ }
+
+ Rectangle {
+ id: mainPanel
+ height: Constants.thumbnailSize
+ anchors.left: parent.left
+ anchors.right: parent.right
+ color: "#ea8c8c"
+ radius: 10
+
+ property bool multiline: (projectNameLabelMetric.width >= projectNameLabel.width)
+
+ TextMetrics {
+ id: projectNameLabelMetric
+ text: projectNameLabel.text
+ font: projectNameLabel.font
+ }
+
+ Image {
+ id: thumbnailPlaceholder
+ anchors.fill: parent
+ anchors.bottomMargin: Constants.imageBottomMargin
+ anchors.rightMargin: Constants.thumbnailMargin
+ anchors.leftMargin: Constants.thumbnailMargin
+ anchors.topMargin: Constants.thumbnailMargin
+ fillMode: Image.PreserveAspectFit
+ verticalAlignment: Image.AlignTop
+ mipmap: true
+ }
+
+ Rectangle {
+ id: projectNameBackground
+ height: mainPanel.multiline && !root.hasPath ? Constants.titleHeightMultiline
+ : Constants.titleHeight
+ color: "#e5b0e4"
+ radius: 3
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.top: thumbnailPlaceholder.bottom
+ anchors.topMargin: Constants.titleBackgroundTopMargin
+ anchors.leftMargin: Constants.thumbnailMargin
+ anchors.rightMargin: Constants.thumbnailMargin
+
+ Text {
+ id: projectNameLabel
+ color: Constants.currentGlobalText
+ text: typeof(displayName) === "undefined" ? projectName : displayName
+ elide: root.hasPath ? Text.ElideMiddle : Text.ElideRight
+ font.pixelSize: 16
+ wrapMode: Text.WordWrap
+ maximumLineCount: 2
+ clip: false
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.leftMargin: Constants.titleMargin
+ anchors.rightMargin: Constants.titleMargin
+
+ MouseArea {
+ id: projectNameMouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ // Only enable the MouseArea if label actually contains text
+ enabled: projectNameLabel.text !== "" ? true : false
+
+ Connections {
+ target: projectNameMouseArea
+ onClicked: root.thumbnailClicked()
+ }
+ }
+
+ ToolTip {
+ id: projectNameToolTip
+ y: -projectNameToolTip.height
+ visible: projectNameMouseArea.containsMouse && projectNameLabel.truncated
+ text: projectNameLabel.text
+ delay: 1000
+ height: 20
+ background: Rectangle {
+ color: Constants.currentToolTipBackground
+ border.color: Constants.currentToolTipOutline
+ border.width: 1
+ }
+ contentItem: Text {
+ color: Constants.currentToolTipText
+ text: projectNameToolTip.text
+ verticalAlignment: Text.AlignVCenter
+ }
+ }
+ }
+
+ DownloadButton {
+ id: downloadButton
+
+ anchors.right: parent.right
+ anchors.top: parent.top
+ visible: root.downloadable
+ enabled: !downloadButton.downloadUnavailable
+
+ globalHover: (mouseArea.containsMouse || projectNameMouseArea.containsMouse)
+ && !downloadButton.alreadyDownloaded
+ && !downloadButton.downloadUnavailable
+ && !downloadButton.updateAvailable
+
+ alreadyDownloaded: extractor.targetFolderExists
+ downloadUnavailable: !downloader.available
+ updateAvailable: downloader.lastModified > extractor.birthTime
+
+ FileDownloader {
+ id: downloader
+ downloadEnabled: $dataModel.downloadEnabled()
+ probeUrl: true
+
+ onFinishedChanged: {
+ downloadPanel.text = downloadPanel.extractText
+ downloadPanel.allowCancel = false
+ downloadPanel.value = Qt.binding(function() { return extractor.progress })
+ extractor.extract()
+ }
+
+ onDownloadStarting: {
+ $dataModel.usageStatisticsDownloadExample(downloader.name)
+ }
+
+ onDownloadCanceled: {
+ downloadPanel.text = ""
+ downloadPanel.value = 0
+ twirlToMainAnimation.start()
+ mouseArea.enabled = true
+ }
+ }
+
+ FileExtractor {
+ id: extractor
+ archiveName: downloader.completeBaseName
+ sourceFile: downloader.outputFile
+ targetPath: $dataModel.targetPath()
+ alwaysCreateDir: true
+ clearTargetPathContents: true
+ onFinishedChanged: {
+ twirlToMainAnimation.start()
+ root.bannerLabelText = qsTr("Recently Downloaded")
+ mouseArea.enabled = true
+ }
+ }
+
+ Connections {
+ target: downloadButton
+ onDownloadClicked: {
+ if (downloadButton.alreadyDownloaded) {
+ overwriteDialog.open()
+ } else {
+ if (downloadButton.enabled)
+ root.startDownload()
+ }
+ }
+ }
+
+ Connections {
+ target: $dataModel
+ onTargetPathMustChange: (path) => {
+ extractor.changeTargetPath(path)
+ }
+ }
+ }
+ }
+
+ Text {
+ id: projectPathLabel
+ visible: root.hasPath
+ color: Constants.currentBrand
+ text: typeof(prettyFilePath) === "undefined" ? "" : prettyFilePath
+ elide: Text.ElideLeft
+ renderType: Text.NativeRendering
+ font.pixelSize: 16
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.top: projectNameBackground.bottom
+ anchors.topMargin: 5
+ anchors.rightMargin: Constants.thumbnailMargin
+ anchors.leftMargin: Constants.thumbnailMargin
+ leftPadding: 5
+
+ MouseArea {
+ id: projectPathMouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ // Only enable the MouseArea if label actually contains text
+ enabled: projectPathLabel.text !== ""
+ }
+
+ ToolTip {
+ id: projectPathToolTip
+ y: -projectPathToolTip.height
+ visible: projectPathMouseArea.containsMouse && projectPathLabel.truncated
+ text: projectPathLabel.text
+ delay: 1000
+ height: 20
+ background: Rectangle {
+ color: Constants.currentToolTipBackground
+ border.color: Constants.currentToolTipOutline
+ border.width: 1
+ }
+ contentItem: Text {
+ color: Constants.currentToolTipText
+ text: projectPathToolTip.text
+ verticalAlignment: Text.AlignVCenter
+ }
+ }
+ }
+
+ Rectangle {
+ id: updateBackground
+ width: 200
+ height: 25
+ visible: root.bannerLabelText !== ""
+ color: Constants.currentBrand
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.topMargin: 0
+ anchors.rightMargin: Constants.thumbnailMargin
+ anchors.leftMargin: Constants.thumbnailMargin
+
+ Text {
+ id: updateText
+ color: Constants.darkActiveGlobalText
+ text: typeof(displayName) === "bannerText" ? "" : bannerText
+ anchors.fill: parent
+ font.pixelSize: 12
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ }
+ }
+ }
+
+ Rectangle {
+ id: detailsPanel
+ height: Constants.thumbnailSize
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.top: mainPanel.bottom
+ color: Constants.currentNormalThumbnailBackground
+ radius: 10
+
+ Text {
+ id: recentProjectInfo
+ color: Constants.currentGlobalText
+ text: typeof(description) === "undefined" ? "" : description
+ anchors.fill: parent
+ font.pixelSize: 12
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignTop
+ wrapMode: Text.WordWrap
+ anchors.margins: Constants.thumbnailMargin
+ anchors.topMargin: 25
+ }
+
+ TagArea {
+ id: tagArea
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: Constants.thumbnailMargin
+ anchors.rightMargin: Constants.thumbnailMargin
+ anchors.leftMargin: Constants.thumbnailMargin
+ tags: typeof(tagData) === "undefined" ? "" : tagData.split(",")
+ }
+ }
+ }
+
+ states: [
+ State {
+ name: "normal"
+ when: !mouseArea.containsMouse && !(mouseArea.pressedButtons & Qt.LeftButton)
+ && !projectPathMouseArea.containsMouse && !projectNameMouseArea.containsMouse
+ && !downloadButton.isHovered && !twirlButtonDown.isHovered
+ && !twirlButtonUp.isHovered
+
+ PropertyChanges {
+ target: mainPanel
+ color: Constants.currentNormalThumbnailBackground
+ border.width: 0
+ }
+ PropertyChanges {
+ target: detailsPanel
+ color: Constants.currentNormalThumbnailBackground
+ border.width: 0
+ }
+ PropertyChanges {
+ target: projectNameBackground
+ color: Constants.currentNormalThumbnailLabelBackground
+ }
+ PropertyChanges {
+ target: twirlButtonDown
+ parentHovered: false
+ }
+ PropertyChanges {
+ target: twirlButtonUp
+ parentHovered: false
+ }
+ },
+ State {
+ name: "hover"
+ when: (mouseArea.containsMouse || projectPathMouseArea.containsMouse
+ || projectNameMouseArea.containsMouse || downloadButton.isHovered
+ || twirlButtonDown.isHovered || twirlButtonUp.isHovered)
+ && !(mouseArea.pressedButtons & Qt.LeftButton) && !root.hasDescription
+
+ PropertyChanges {
+ target: mainPanel
+ color: Constants.currentHoverThumbnailBackground
+ border.width: 0
+ }
+ PropertyChanges {
+ target: detailsPanel
+ color: Constants.currentHoverThumbnailBackground
+ border.width: 0
+ }
+ PropertyChanges {
+ target: projectNameBackground
+ color: Constants.currentHoverThumbnailLabelBackground
+ }
+ PropertyChanges {
+ target: thumbnailPlaceholder
+ visible: true
+ }
+ PropertyChanges {
+ target: twirlButtonDown
+ parentHovered: true
+ }
+ PropertyChanges {
+ target: twirlButtonUp
+ parentHovered: true
+ }
+ },
+ State {
+ name: "press"
+ when: (mouseArea.pressedButtons & Qt.LeftButton) && !root.hasDescription
+
+ PropertyChanges {
+ target: mainPanel
+ color: Constants.currentHoverThumbnailBackground
+ border.color: Constants.currentBrand
+ border.width: 2
+ }
+ PropertyChanges {
+ target: detailsPanel
+ color: Constants.currentHoverThumbnailBackground
+ border.color: Constants.currentBrand
+ border.width: 2
+ }
+ PropertyChanges {
+ target: projectNameBackground
+ color: Constants.currentBrand
+ }
+ PropertyChanges {
+ target: thumbnailPlaceholder
+ visible: true
+ }
+ PropertyChanges {
+ target: projectNameLabel
+ color: Constants.darkActiveGlobalText
+ }
+ },
+ State {
+ name: "hoverDescription"
+ when: mouseArea.containsMouse && !(mouseArea.pressedButtons & Qt.LeftButton)
+ && root.hasDescription
+
+ PropertyChanges {
+ target: mainPanel
+ color: Constants.currentHoverThumbnailBackground
+ border.width: 0
+ }
+ PropertyChanges {
+ target: projectNameBackground
+ color: Constants.currentHoverThumbnailLabelBackground
+ }
+ PropertyChanges {
+ target: thumbnailPlaceholder
+ visible: true
+ }
+ },
+ State {
+ name: "pressDescription"
+ when: (mouseArea.pressedButtons & Qt.LeftButton) && root.hasDescription
+
+ PropertyChanges {
+ target: mainPanel
+ color: Constants.currentHoverThumbnailBackground
+ border.color: Constants.currentBrand
+ border.width: 2
+ }
+ PropertyChanges {
+ target: projectNameBackground
+ color: Constants.currentBrand
+ }
+ PropertyChanges {
+ target: thumbnailPlaceholder
+ visible: true
+ }
+ }
+ ]
+
+ TwirlButton {
+ id: twirlButtonDown
+ height: 20
+ visible: root.currentPanel === ThumbnailDelegate.Panel.Main
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+
+ Connections {
+ target: twirlButtonDown
+ onTriggerRelease: twirlToDetailsAnimation.start()
+ }
+ }
+
+ TwirlButton {
+ id: twirlButtonUp
+ height: 20
+ visible: root.currentPanel === ThumbnailDelegate.Panel.Details
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.top: parent.top
+ rotation: 180
+
+ Connections {
+ target: twirlButtonUp
+ onTriggerRelease: twirlToMainAnimation.start()
+ }
+ }
+
+ NumberAnimation {
+ id: twirlToDetailsAnimation
+ target: canvas
+ property: "y"
+ easing.bezierCurve: [0.972,-0.176,0.0271,1.16,1,1]
+ duration: 250
+ alwaysRunToEnd: true
+ to: -Constants.thumbnailSize // dynamic size because of rescale - needs to be inverted because animation goes into negative range
+ from: canvas.y
+ }
+
+ NumberAnimation {
+ id: twirlToMainAnimation
+ target: canvas
+ property: "y"
+ easing.bezierCurve: [0.972,-0.176,0.0271,1.16,1,1]
+ alwaysRunToEnd: true
+ duration: 250
+ to: 0
+ from: canvas.y
+ }
+
+ NumberAnimation {
+ id: twirlToDownloadAnimation
+ target: canvas
+ property: "y"
+ easing.bezierCurve: [0.972,-0.176,0.0271,1.16,1,1]
+ alwaysRunToEnd: true
+ duration: 250
+ to: Constants.thumbnailSize
+ from: canvas.y
+ }
+
+ Connections {
+ target: twirlToDetailsAnimation
+ onStarted: root.currentPanel = ThumbnailDelegate.Panel.InBetween
+ onFinished: {
+ root.currentPanel = ThumbnailDelegate.Panel.Details
+ canvas.y = Qt.binding(function() {return -Constants.thumbnailSize })
+ }
+ }
+
+ Connections {
+ target: twirlToMainAnimation
+ onStarted: root.currentPanel = ThumbnailDelegate.Panel.InBetween
+ onFinished: {
+ root.currentPanel = ThumbnailDelegate.Panel.Main
+ canvas.y = Qt.binding(function() {return 0 })
+ }
+ }
+
+ Connections {
+ target: twirlToDownloadAnimation
+ onStarted: root.currentPanel = ThumbnailDelegate.Panel.InBetween
+ onFinished: {
+ root.currentPanel = ThumbnailDelegate.Panel.Download
+ canvas.y = Qt.binding(function() {return Constants.thumbnailSize })
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/TourDialogButton.qml b/share/qtcreator/qmldesigner/welcomepage/TourDialogButton.qml
new file mode 100644
index 0000000000..35ace283ed
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/TourDialogButton.qml
@@ -0,0 +1,69 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtQuick.Controls
+import WelcomeScreen 1.0
+import StudioTheme 1.0 as StudioTheme
+import UiTour
+
+Item {
+ id: tourButton
+ width: 40
+ height: 40
+ property alias dialogButtonText: dialogButton.text
+
+ signal buttonClicked
+
+ Text {
+ id: dialogButton
+ color: "#ffffff"
+ font.family: StudioTheme.Constants.iconFont.family
+ text: StudioTheme.Constants.closeFile_large
+ font.pixelSize: 32
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.horizontalCenter: parent.horizontalCenter
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+
+ Connections {
+ target: mouseArea
+ onClicked: tourButton.buttonClicked()
+ }
+ }
+
+ states: [
+ State {
+ name: "normal"
+ when: !mouseArea.containsMouse && !mouseArea.pressed
+
+ PropertyChanges {
+ target: dialogButton
+ color: "#ecebeb"
+ font.pixelSize: 28
+ }
+ },
+ State {
+ name: "hover"
+ when: mouseArea.containsMouse && !mouseArea.pressed
+
+ PropertyChanges {
+ target: dialogButton
+ font.pixelSize: 29
+ }
+ },
+ State {
+ name: "press"
+ when: mouseArea.pressed
+
+ PropertyChanges {
+ target: dialogButton
+ font.pixelSize: 29
+ }
+ }
+ ]
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/TourModel.qml b/share/qtcreator/qmldesigner/welcomepage/TourModel.qml
new file mode 100644
index 0000000000..db6224f7d6
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/TourModel.qml
@@ -0,0 +1,73 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+
+ListModel {
+ ListElement {
+ qmlFileName: "tours/welcomepage-tour/WelcomeSlideShow.ui.qml"
+ thumbnail: "images/welcome-page.png"
+ title: QT_TR_NOOP("Welcome Page")
+ subtitle: QT_TR_NOOP("The welcome page of Qt Design Studio.")
+ }
+ ListElement {
+ qmlFileName: "tours/workspace-tour/WorkspaceSlideShow.ui.qml"
+ thumbnail: "images/workspaces.png"
+ title: QT_TR_NOOP("Workspaces")
+ subtitle: QT_TR_NOOP("Introduction to the most important workspaces.")
+ }
+ ListElement {
+ qmlFileName: "tours/toolbar-tour/ToolbarSlideShow.ui.qml"
+ thumbnail: "images/top-toolbar.png"
+ title: QT_TR_NOOP("Top Toolbar")
+ subtitle: QT_TR_NOOP("Short explanation of the top toolbar.")
+ }
+ ListElement {
+ qmlFileName: "tours/states-tour/StatesSlideShow.ui.qml"
+ thumbnail: "images/states.png"
+ title: QT_TR_NOOP("States")
+ subtitle: QT_TR_NOOP("An introduction to states.")
+ }
+ ListElement {
+ qmlFileName: "tours/sortcomponents-tour/SortComponentsSlideShow.ui.qml"
+ thumbnail: "images/sorting-components.png"
+ title: QT_TR_NOOP("Sorting Components")
+ subtitle: QT_TR_NOOP("A way to organize multiple components.")
+ }
+ ListElement {
+ qmlFileName: "tours/connectcomponents-tour/ConnectComponentsSlideShow.ui.qml"
+ thumbnail: "images/connecting-components.png"
+ title: QT_TR_NOOP("Connecting Components")
+ subtitle: QT_TR_NOOP("A way to connect components with actions.")
+ }
+ ListElement {
+ qmlFileName: "tours/addassets-tour/AddAssetsSlideShow.ui.qml"
+ thumbnail: "images/adding-assets.png"
+ title: QT_TR_NOOP("Adding Assets")
+ subtitle: QT_TR_NOOP("A way to add new assets to the project.")
+ }
+ ListElement {
+ qmlFileName: "tours/animation-tour/AnimationSlideShow.ui.qml"
+ thumbnail: "images/animation-2d.png"
+ title: QT_TR_NOOP("Creating 2D Animation")
+ subtitle: QT_TR_NOOP("A way to create a 2D Animation.")
+ }
+ ListElement {
+ qmlFileName: "tours/studiocomponents-border-arc-tour/StudioComponentBorderArcSlideShow.ui.qml"
+ thumbnail: "images/border-arc.png"
+ title: QT_TR_NOOP("Border and Arc")
+ subtitle: QT_TR_NOOP("Work with Border and Arc Studio Components.")
+ }
+ ListElement {
+ qmlFileName: "tours/studiocomponents-ellipse-pie-tour/StudioComponentEllipsePieSlideShow.ui.qml"
+ thumbnail: "images/ellipse-pie.png"
+ title: QT_TR_NOOP("Ellipse and Pie")
+ subtitle: QT_TR_NOOP("Work with Ellipse and Pie Studio Components.")
+ }
+ ListElement {
+ qmlFileName: "tours/studiocomponents-polygon-triangle-rectangle-tour/StudioComponentPolygonTriangleRectangleSlideShow.ui.qml"
+ thumbnail: "images/complex-shapes.png"
+ title: QT_TR_NOOP("Complex Shapes")
+ subtitle: QT_TR_NOOP("Work with Polygon, Triangle and Rectangle Studio Components.")
+ }
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/TourProgressBar.qml b/share/qtcreator/qmldesigner/welcomepage/TourProgressBar.qml
new file mode 100644
index 0000000000..bae49c0fe4
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/TourProgressBar.qml
@@ -0,0 +1,41 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtQuick.Controls
+import WelcomeScreen 1.0
+
+Item {
+ id: progressBar
+
+ property int endSlide: 10
+ property int currentSlide: 1
+
+ Rectangle {
+ id: progressBarGroove
+ color: "#272727"
+ radius: 5
+ border.color: "#00000000"
+ anchors.fill: parent
+ }
+
+ Rectangle {
+ id: progressBarTrack
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: 1
+ anchors.topMargin: 1
+ width: (progressBarGroove.width / 100) * rangeMapper.output
+ color: "#57b9fc"
+ radius: 4.5
+ }
+
+ RangeMapper {
+ id: rangeMapper
+ inputMaximum: progressBar.endSlide
+ outputMaximum: 100
+ outputMinimum: 0
+ inputMinimum: 0
+ input: progressBar.currentSlide
+ }
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/TourRestartButton.qml b/share/qtcreator/qmldesigner/welcomepage/TourRestartButton.qml
new file mode 100644
index 0000000000..55f367ffb9
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/TourRestartButton.qml
@@ -0,0 +1,84 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import WelcomeScreen 1.0
+
+Rectangle {
+ id: restart
+ height: 36
+ color: "#00ffffff"
+ radius: 18
+ border.color: "#f9f9f9"
+ border.width: 3
+ state: "normal"
+
+ signal restart()
+
+ Text {
+ id: text2
+ color: "#ffffff"
+ text: qsTrId("Restart")
+ anchors.verticalCenter: parent.verticalCenter
+ font.pixelSize: 12
+ anchors.horizontalCenter: parent.horizontalCenter
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+
+ Connections {
+ target: mouseArea
+ onClicked: restart.restart()
+ }
+ }
+
+ states: [
+ State {
+ name: "normal"
+ when: !mouseArea.containsMouse && !mouseArea.pressed
+
+ PropertyChanges {
+ target: text2
+ color: "#dedede"
+ }
+
+ PropertyChanges {
+ target: restart
+ border.color: "#dedede"
+ }
+ },
+ State {
+ name: "hover"
+ when: mouseArea.containsMouse && !mouseArea.pressed
+
+ PropertyChanges {
+ target: restart
+ color: "#00ffffff"
+ border.color: "#ffffff"
+ }
+
+ PropertyChanges {
+ target: text2
+ color: "#ffffff"
+ }
+ },
+ State {
+ name: "press"
+ when: mouseArea.pressed
+
+ PropertyChanges {
+ target: restart
+ color: "#ffffff"
+ border.color: "#ffffff"
+ }
+
+ PropertyChanges {
+ target: text2
+ color: "#000000"
+ }
+ }
+ ]
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/TourThumbnailDelegate.qml b/share/qtcreator/qmldesigner/welcomepage/TourThumbnailDelegate.qml
new file mode 100644
index 0000000000..0f61a2a3c4
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/TourThumbnailDelegate.qml
@@ -0,0 +1,164 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtQuick.Controls
+import WelcomeScreen 1.0
+
+Item {
+ id: root
+ width: Constants.thumbnailSize
+ height: Constants.thumbnailSize
+ state: "normal"
+ clip: true
+
+ property bool complete: root.currentSlide === root.endSlide
+
+ // Needs to be set from the current slide show and user progress
+ property int currentSlide: 0
+ property int endSlide: 10
+
+ signal clicked()
+
+ Rectangle {
+ id: background
+ radius: 10
+ color: Constants.currentNormalThumbnailBackground
+ anchors.fill: parent
+
+ property bool multiline: (tourNameLabelMetric.width >= tourNameLabel.width)
+
+ TextMetrics {
+ id: tourNameLabelMetric
+ text: tourNameLabel.text
+ font: tourNameLabel.font
+ }
+
+ Image {
+ id: thumbnailPlaceholder
+ source: thumbnail
+ anchors.fill: parent
+ anchors.bottomMargin: Constants.imageBottomMargin
+ anchors.rightMargin: Constants.thumbnailMargin
+ anchors.leftMargin: Constants.thumbnailMargin
+ anchors.topMargin: Constants.thumbnailMargin
+ fillMode: Image.PreserveAspectFit
+ verticalAlignment: Image.AlignTop
+ mipmap: true
+ }
+
+ Rectangle {
+ id: tourNameBackground
+ height: background.multiline ? Constants.titleHeightMultiline : Constants.titleHeight
+ color: "#e5b0e4"
+ radius: 3
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.top: thumbnailPlaceholder.bottom
+ anchors.topMargin: Constants.titleBackgroundTopMargin
+ anchors.leftMargin: Constants.thumbnailMargin
+ anchors.rightMargin: Constants.thumbnailMargin
+
+ Text {
+ id: tourNameLabel
+ color: Constants.currentGlobalText
+ font.pixelSize: 16
+ text: title
+ wrapMode: Text.WordWrap
+ maximumLineCount: 2
+ clip: false
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.leftMargin: Constants.titleMargin
+ anchors.rightMargin: Constants.titleMargin
+ }
+ }
+
+ Text {
+ id: subtitleCaption
+ color: Constants.currentGlobalText
+ text: subtitle
+ renderType: Text.NativeRendering
+ font.pixelSize: 14
+ wrapMode: Text.WordWrap
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.top: tourNameBackground.bottom
+ anchors.topMargin: 5
+ anchors.rightMargin: Constants.thumbnailMargin
+ anchors.leftMargin: Constants.thumbnailMargin
+ leftPadding: 5
+ rightPadding: 5
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+
+ Connections {
+ target: mouseArea
+ onClicked: root.clicked()
+ }
+ }
+ }
+
+ states: [
+ State {
+ name: "normal"
+ when: root.enabled && !mouseArea.containsMouse && !mouseArea.pressed && !root.complete
+
+ PropertyChanges {
+ target: background
+ color: Constants.currentNormalThumbnailBackground
+ border.width: 0
+ }
+ PropertyChanges {
+ target: tourNameBackground
+ color: Constants.currentNormalThumbnailLabelBackground
+ }
+ PropertyChanges {
+ target: mouseArea
+ enabled: true
+ }
+ },
+ State {
+ name: "hover"
+ when: root.enabled && mouseArea.containsMouse && !mouseArea.pressed && !root.complete
+
+ PropertyChanges {
+ target: background
+ color: Constants.currentHoverThumbnailBackground
+ border.width: 0
+ }
+ PropertyChanges {
+ target: tourNameBackground
+ color: Constants.currentHoverThumbnailLabelBackground
+ }
+ PropertyChanges {
+ target: mouseArea
+ enabled: true
+ }
+ },
+ State {
+ name: "press"
+ when: root.enabled && mouseArea.pressed && !root.complete
+
+ PropertyChanges {
+ target: background
+ color: Constants.currentHoverThumbnailBackground
+ border.color: Constants.currentBrand
+ border.width: 2
+ }
+ PropertyChanges {
+ target: tourNameBackground
+ color: Constants.currentBrand
+ }
+ PropertyChanges {
+ target: mouseArea
+ enabled: true
+ }
+ }
+ ]
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/TwirlButton.qml b/share/qtcreator/qmldesigner/welcomepage/TwirlButton.qml
new file mode 100644
index 0000000000..e9813ad997
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/TwirlButton.qml
@@ -0,0 +1,118 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtQuick.Controls
+import WelcomeScreen 1.0
+import QtQuick.Layouts
+import StudioTheme 1.0 as StudioTheme
+
+Item {
+ id: twirlButton
+ width: 25
+ height: 25
+ state: "normal"
+
+ property bool parentHovered: false
+ property bool isHovered: mouseArea.containsMouse
+ signal triggerRelease()
+
+ Rectangle {
+ id: background
+ color: "#eab336"
+ border.width: 0
+ anchors.fill: parent
+ }
+
+ Text {
+ id: twirlIcon
+ width: 23
+ height: 23
+ color: Constants.currentGlobalText
+ font.family: StudioTheme.Constants.iconFont.family
+ text: StudioTheme.Constants.adsDropDown
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.bottom: parent.bottom
+ font.pixelSize: 14
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ anchors.horizontalCenter: parent.horizontalCenter
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+
+ Connections {
+ target: mouseArea
+ onReleased: twirlButton.triggerRelease()
+ }
+ }
+
+ states: [
+ State {
+ name: "hidden"
+ when: !mouseArea.containsMouse && !mouseArea.pressed && !twirlButton.parentHovered
+
+ PropertyChanges {
+ target: background
+ visible: false
+ }
+ PropertyChanges {
+ target: twirlIcon
+ visible: false
+ }
+ },
+ State {
+ name: "normal"
+ when: !mouseArea.containsMouse && !mouseArea.pressed && twirlButton.parentHovered
+
+ PropertyChanges {
+ target: background
+ visible: false
+ }
+ PropertyChanges {
+ target: twirlIcon
+ visible: true
+ }
+ },
+ State {
+ name: "hover"
+ when: mouseArea.containsMouse && !mouseArea.pressed
+
+ PropertyChanges {
+ target: twirlIcon
+ scale: 1.4
+ }
+ PropertyChanges {
+ target: background
+ visible: true
+ color: Constants.currentHoverThumbnailLabelBackground
+ }
+ PropertyChanges {
+ target: twirlIcon
+ visible: true
+ }
+ },
+ State {
+ name: "press"
+ when: mouseArea.pressed
+
+ PropertyChanges {
+ target: twirlIcon
+ color: Constants.currentGlobalText
+ scale: 1.8
+ }
+ PropertyChanges {
+ target: background
+ visible: true
+ color: Constants.currentBrand
+ }
+ PropertyChanges {
+ target: twirlIcon
+ visible: true
+ }
+ }
+ ]
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/TwitterButton.qml b/share/qtcreator/qmldesigner/welcomepage/TwitterButton.qml
new file mode 100644
index 0000000000..9349fcd32c
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/TwitterButton.qml
@@ -0,0 +1,125 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import WelcomeScreen 1.0
+import StudioTheme 1.0 as StudioTheme
+
+Item {
+ id: twitterButton
+ state: "darkNormal"
+
+ property bool isHovered: mouseArea.containsMouse
+
+ Image {
+ id: twitterDarkNormal
+ anchors.fill: parent
+ source: "images/twitterDarkNormal.png"
+ fillMode: Image.PreserveAspectFit
+ }
+
+ Image {
+ id: twitterLightNormal
+ anchors.fill: parent
+ source: "images/twitterLightNormal.png"
+ fillMode: Image.PreserveAspectFit
+ }
+
+ Image {
+ id: twitterHover
+ anchors.fill: parent
+ source: "images/twitterHover.png"
+ fillMode: Image.PreserveAspectFit
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+
+ Connections {
+ target: mouseArea
+ function onClicked(mouse) { Qt.openUrlExternally("https://twitter.com/qtproject/") }
+ }
+ }
+
+ states: [
+ State {
+ name: "darkNormal"
+ when: !StudioTheme.Values.isLightTheme && !mouseArea.containsMouse && !mouseArea.pressed
+
+ PropertyChanges {
+ target: twitterDarkNormal
+ visible: true
+ }
+
+ PropertyChanges {
+ target: twitterLightNormal
+ visible: false
+ }
+
+ PropertyChanges {
+ target: twitterHover
+ visible: false
+ }
+ },
+ State {
+ name: "lightNormal"
+ when: StudioTheme.Values.isLightTheme && !mouseArea.containsMouse && !mouseArea.pressed
+
+ PropertyChanges {
+ target: twitterHover
+ visible: false
+ }
+
+ PropertyChanges {
+ target: twitterLightNormal
+ visible: true
+ }
+
+ PropertyChanges {
+ target: twitterDarkNormal
+ visible: false
+ }
+ },
+ State {
+ name: "hover"
+ when: mouseArea.containsMouse && !mouseArea.pressed
+
+ PropertyChanges {
+ target: twitterHover
+ visible: true
+ }
+
+ PropertyChanges {
+ target: twitterLightNormal
+ visible: false
+ }
+
+ PropertyChanges {
+ target: twitterDarkNormal
+ visible: false
+ }
+ },
+ State {
+ name: "press"
+ when: (mouseArea.containsMouse || !mouseArea.containsMouse) && mouseArea.pressed
+
+ PropertyChanges {
+ target: twitterHover
+ visible: true
+ scale: 1.1
+ }
+
+ PropertyChanges {
+ target: twitterLightNormal
+ visible: false
+ }
+
+ PropertyChanges {
+ target: twitterDarkNormal
+ visible: false
+ }
+ }
+ ]
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/WelcomePage.qml b/share/qtcreator/qmldesigner/welcomepage/WelcomePage.qml
new file mode 100644
index 0000000000..2f8778f2f8
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/WelcomePage.qml
@@ -0,0 +1,52 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+import WelcomeScreen 1.0
+import projectmodel 1.0
+
+Item {
+ id: appFrame
+ clip: true
+ width: Constants.width
+ height: Constants.height
+
+ property int loadingProgress: 50
+
+ onLoadingProgressChanged: Constants.loadingProgress = appFrame.loadingProgress
+
+ NumberAnimation {
+ target: appFrame
+ property: "loadingProgress"
+ from: 0
+ to: 100
+ loops: Animation.Infinite
+ running: false
+ duration: 1000
+ }
+
+ MainScreen {
+ id: screen
+ anchors.fill: parent
+ anchors.leftMargin: screen.designMode ? 0 : -45 // hide sidebar
+ }
+
+ property int pageIndex: 0
+ property int minimumWidth: 1200
+ property int minimumHeight: 720
+
+ onHeightChanged: {
+ if (appFrame.height > appFrame.minimumHeight)
+ appFrame.anchors.fill = parent
+ else if (appFrame.height < appFrame.minimumHeight)
+ appFrame.height = appFrame.minimumHeight
+ }
+ onWidthChanged: {
+ if (appFrame.width > appFrame.minimumWidth)
+ appFrame.anchors.fill = parent
+ else if (appFrame.width < appFrame.minimumWidth)
+ appFrame.width = appFrame.minimumWidth
+ }
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/WelcomeScreen.qmlproject b/share/qtcreator/qmldesigner/welcomepage/WelcomeScreen.qmlproject
new file mode 100644
index 0000000000..539db2133a
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/WelcomeScreen.qmlproject
@@ -0,0 +1,49 @@
+/* File generated by Qt Creator */
+
+import QmlProject 1.1
+
+Project {
+ mainFile: "WelcomePage.qml"
+
+ /* Include .qml, .js, and image files from current directory and subdirectories */
+ QmlFiles {
+ directory: "."
+ }
+
+ JavaScriptFiles {
+ directory: "."
+ }
+
+ ImageFiles {
+ directory: "."
+ }
+
+ Files {
+ filter: "*.conf"
+ files: ["qtquickcontrols2.conf"]
+ }
+
+ Files {
+ filter: "qmldir"
+ directory: "."
+ }
+
+ Files {
+ filter: "*.ttf;*.otf"
+ }
+
+ Environment {
+ QT_QUICK_CONTROLS_CONF: "qtquickcontrols2.conf"
+ //QT_AUTO_SCREEN_SCALE_FACTOR: "1"
+ QT_SCALE_FACTOR: "0.8"
+ QT_LOGGING_RULES: "qt.qml.connections=false"
+ }
+
+ qt6Project: true
+
+ /* List of plugin directories passed to QML runtime */
+ importPaths: [ "imports", "studioImports", "asset_imports", "mockData", "dataImports" ]
+
+ /* Required for deployment */
+ targetDirectory: "/opt/WelcomeScreen"
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/YoutubeButton.qml b/share/qtcreator/qmldesigner/welcomepage/YoutubeButton.qml
new file mode 100644
index 0000000000..ec7eb54ace
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/YoutubeButton.qml
@@ -0,0 +1,201 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtQuick.Templates
+import WelcomeScreen 1.0
+import StudioTheme 1.0 as StudioTheme
+
+Item {
+ id: youtubeButton
+ state: "darkNormal"
+
+ property bool isHovered: mouseArea.containsMouse
+
+ Image {
+ id: youtubeDarkNormal
+ anchors.fill: parent
+ source: "images/youtubeDarkNormal.png"
+ fillMode: Image.PreserveAspectFit
+ }
+
+ Image {
+ id: youtubeLightNormal
+ anchors.fill: parent
+ source: "images/youtubeLightNormal.png"
+ fillMode: Image.PreserveAspectFit
+ }
+
+ Image {
+ id: youtubeLightHover
+ anchors.fill: parent
+ source: "images/youtubeLightHover.png"
+ fillMode: Image.PreserveAspectFit
+ }
+
+ Image {
+ id: youtubeDarkHover
+ anchors.fill: parent
+ source: "images/youtubeDarkHover.png"
+ fillMode: Image.PreserveAspectFit
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+
+ Connections {
+ target: mouseArea
+ function onClicked(mouse) { Qt.openUrlExternally("https://www.youtube.com/user/QtStudios/") }
+ }
+ }
+ states: [
+ State {
+ name: "darkNormal"
+ when: !StudioTheme.Values.isLightTheme && !mouseArea.containsMouse && !mouseArea.pressed
+
+ PropertyChanges {
+ target: youtubeDarkNormal
+ visible: true
+ }
+
+ PropertyChanges {
+ target: youtubeLightNormal
+ visible: false
+ }
+
+ PropertyChanges {
+ target: youtubeLightHover
+ visible: false
+ }
+
+ PropertyChanges {
+ target: youtubeDarkHover
+ visible: false
+ }
+ },
+ State {
+ name: "lightNormal"
+ when: StudioTheme.Values.isLightTheme && !mouseArea.containsMouse && !mouseArea.pressed
+
+ PropertyChanges {
+ target: youtubeDarkHover
+ visible: false
+ }
+
+ PropertyChanges {
+ target: youtubeLightHover
+ visible: false
+ }
+
+ PropertyChanges {
+ target: youtubeLightNormal
+ visible: true
+ }
+
+ PropertyChanges {
+ target: youtubeDarkNormal
+ visible: false
+ }
+ },
+ State {
+ name: "darkHover"
+ when: !StudioTheme.Values.isLightTheme && mouseArea.containsMouse && !mouseArea.pressed
+
+ PropertyChanges {
+ target: youtubeDarkNormal
+ visible: false
+ }
+
+ PropertyChanges {
+ target: youtubeLightNormal
+ visible: false
+ }
+
+ PropertyChanges {
+ target: youtubeLightHover
+ visible: false
+ }
+
+ PropertyChanges {
+ target: youtubeDarkHover
+ visible: true
+ }
+ },
+ State {
+ name: "lightHover"
+ when: StudioTheme.Values.isLightTheme && mouseArea.containsMouse && !mouseArea.pressed
+
+ PropertyChanges {
+ target: youtubeDarkHover
+ visible: false
+ }
+
+ PropertyChanges {
+ target: youtubeLightHover
+ visible: true
+ }
+
+ PropertyChanges {
+ target: youtubeLightNormal
+ visible: false
+ }
+
+ PropertyChanges {
+ target: youtubeDarkNormal
+ visible: false
+ }
+ },
+ State {
+ name: "darkPress"
+ when: !StudioTheme.Values.isLightTheme && mouseArea.pressed
+
+ PropertyChanges {
+ target: youtubeDarkHover
+ visible: true
+ scale: 1.1
+ }
+
+ PropertyChanges {
+ target: youtubeLightHover
+ visible: false
+ }
+
+ PropertyChanges {
+ target: youtubeLightNormal
+ visible: false
+ }
+
+ PropertyChanges {
+ target: youtubeDarkNormal
+ visible: false
+ }
+ },
+ State {
+ name: "lightPress"
+ when: StudioTheme.Values.isLightTheme && mouseArea.pressed
+
+ PropertyChanges {
+ target: youtubeDarkHover
+ visible: false
+ }
+
+ PropertyChanges {
+ target: youtubeLightHover
+ visible: true
+ scale: 1.1
+ }
+
+ PropertyChanges {
+ target: youtubeLightNormal
+ visible: false
+ }
+
+ PropertyChanges {
+ target: youtubeDarkNormal
+ visible: false
+ }
+ }
+ ]
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/fonts/fonts.txt b/share/qtcreator/qmldesigner/welcomepage/fonts/fonts.txt
new file mode 100644
index 0000000000..ab96122067
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/fonts/fonts.txt
@@ -0,0 +1 @@
+Fonts in this folder are loaded automatically.
diff --git a/share/qtcreator/qmldesigner/welcomepage/images/adding-assets.png b/share/qtcreator/qmldesigner/welcomepage/images/adding-assets.png
new file mode 100644
index 0000000000..099b8d3ec3
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/images/adding-assets.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/welcomepage/images/animation-2d.png b/share/qtcreator/qmldesigner/welcomepage/images/animation-2d.png
new file mode 100644
index 0000000000..1a607e1fd9
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/images/animation-2d.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/welcomepage/images/border-arc.png b/share/qtcreator/qmldesigner/welcomepage/images/border-arc.png
new file mode 100644
index 0000000000..d1575c49f5
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/images/border-arc.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/welcomepage/images/complex-shapes.png b/share/qtcreator/qmldesigner/welcomepage/images/complex-shapes.png
new file mode 100644
index 0000000000..371295b831
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/images/complex-shapes.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/welcomepage/images/congratulations.png b/share/qtcreator/qmldesigner/welcomepage/images/congratulations.png
new file mode 100644
index 0000000000..816feb76b4
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/images/congratulations.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/welcomepage/images/connecting-components.png b/share/qtcreator/qmldesigner/welcomepage/images/connecting-components.png
new file mode 100644
index 0000000000..9f8e45cd4e
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/images/connecting-components.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/welcomepage/images/ds.png b/share/qtcreator/qmldesigner/welcomepage/images/ds.png
new file mode 100644
index 0000000000..e523ba4082
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/images/ds.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/welcomepage/images/ellipse-pie.png b/share/qtcreator/qmldesigner/welcomepage/images/ellipse-pie.png
new file mode 100644
index 0000000000..a081ea81bf
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/images/ellipse-pie.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/welcomepage/images/newThumbnail.png b/share/qtcreator/qmldesigner/welcomepage/images/newThumbnail.png
new file mode 100644
index 0000000000..046c053570
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/images/newThumbnail.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/welcomepage/images/noPreview.png b/share/qtcreator/qmldesigner/welcomepage/images/noPreview.png
new file mode 100644
index 0000000000..33641e6fb0
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/images/noPreview.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/welcomepage/images/place_holder.png b/share/qtcreator/qmldesigner/welcomepage/images/place_holder.png
new file mode 100644
index 0000000000..96e7e63796
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/images/place_holder.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/welcomepage/images/sorting-components.png b/share/qtcreator/qmldesigner/welcomepage/images/sorting-components.png
new file mode 100644
index 0000000000..19b2182d3f
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/images/sorting-components.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/welcomepage/images/states.png b/share/qtcreator/qmldesigner/welcomepage/images/states.png
new file mode 100644
index 0000000000..41f1bbaddd
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/images/states.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/welcomepage/images/thumbnailImage.png b/share/qtcreator/qmldesigner/welcomepage/images/thumbnailImage.png
new file mode 100644
index 0000000000..f54508029a
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/images/thumbnailImage.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/welcomepage/images/thumbnail_test.png b/share/qtcreator/qmldesigner/welcomepage/images/thumbnail_test.png
new file mode 100644
index 0000000000..3c4834e644
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/images/thumbnail_test.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/welcomepage/images/top-toolbar.png b/share/qtcreator/qmldesigner/welcomepage/images/top-toolbar.png
new file mode 100644
index 0000000000..33601d658b
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/images/top-toolbar.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/welcomepage/images/twitterDarkNormal.png b/share/qtcreator/qmldesigner/welcomepage/images/twitterDarkNormal.png
new file mode 100644
index 0000000000..bd2349329c
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/images/twitterDarkNormal.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/welcomepage/images/twitterHover.png b/share/qtcreator/qmldesigner/welcomepage/images/twitterHover.png
new file mode 100644
index 0000000000..a10316113d
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/images/twitterHover.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/welcomepage/images/twitterLightNormal.png b/share/qtcreator/qmldesigner/welcomepage/images/twitterLightNormal.png
new file mode 100644
index 0000000000..b6ad88c5b6
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/images/twitterLightNormal.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/welcomepage/images/welcome-page.png b/share/qtcreator/qmldesigner/welcomepage/images/welcome-page.png
new file mode 100644
index 0000000000..4c072eb2a1
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/images/welcome-page.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/welcomepage/images/workspaces.png b/share/qtcreator/qmldesigner/welcomepage/images/workspaces.png
new file mode 100644
index 0000000000..ce4b5f6158
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/images/workspaces.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/welcomepage/images/youtubeDarkHover.png b/share/qtcreator/qmldesigner/welcomepage/images/youtubeDarkHover.png
new file mode 100644
index 0000000000..a58f1cd0cf
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/images/youtubeDarkHover.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/welcomepage/images/youtubeDarkNormal.png b/share/qtcreator/qmldesigner/welcomepage/images/youtubeDarkNormal.png
new file mode 100644
index 0000000000..7c5a5cd918
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/images/youtubeDarkNormal.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/welcomepage/images/youtubeLightHover.png b/share/qtcreator/qmldesigner/welcomepage/images/youtubeLightHover.png
new file mode 100644
index 0000000000..15a16b3bb1
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/images/youtubeLightHover.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/welcomepage/images/youtubeLightNormal.png b/share/qtcreator/qmldesigner/welcomepage/images/youtubeLightNormal.png
new file mode 100644
index 0000000000..9ec959fc92
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/images/youtubeLightNormal.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/welcomepage/imports/UiTour/Highlight.ui.qml b/share/qtcreator/qmldesigner/welcomepage/imports/UiTour/Highlight.ui.qml
new file mode 100644
index 0000000000..a3bd85184a
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/imports/UiTour/Highlight.ui.qml
@@ -0,0 +1,61 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Timeline
+
+Rectangle {
+ id: root
+ width: 872
+ height: 860
+ radius: 4
+ color: "transparent"
+ border.color: "#1381e3"
+ border.width: 8
+ state: "off"
+
+ property bool active: true
+
+ states: [
+ State {
+ name: "on"
+ when: root.active
+
+ PropertyChanges {
+ target: root
+ }
+ },
+ State {
+ name: "off"
+ when: !root.active
+
+ PropertyChanges {
+ target: root
+ opacity: 0
+ }
+ }
+ ]
+
+ transitions: [
+ Transition {
+ id: transition
+ to: "*"
+ from: "*"
+ ParallelAnimation {
+ SequentialAnimation {
+ PauseAnimation { duration: 0 }
+
+ PropertyAnimation {
+ target: root
+ property: "opacity"
+ duration: 150
+ }
+ }
+ }
+ }
+ ]
+}
+
+
+
diff --git a/share/qtcreator/qmldesigner/welcomepage/imports/UiTour/Slide.qml b/share/qtcreator/qmldesigner/welcomepage/imports/UiTour/Slide.qml
new file mode 100644
index 0000000000..cb94d05ad2
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/imports/UiTour/Slide.qml
@@ -0,0 +1,118 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Timeline
+
+Item {
+ id: root
+ width: 1920
+ height: 1080
+
+ property string caption: "This is a string"
+ property string title: "this is a string"
+ property bool active: false
+
+ function prev() {
+ var states = root.stateNames()
+
+ if (states.length === 0)
+ return false
+
+ if (root.state === "")
+ return false
+
+ var index = states.indexOf(root.state)
+
+ // base state is not in the list
+ if (index > 0) {
+ root.state = states[index - 1]
+ return true
+ }
+
+ return false
+ }
+
+ function next() {
+ var states = root.stateNames()
+
+ if (states.length === 0)
+ return false
+
+ if (root.state === "") {
+ root.state = states[0]
+ return true
+ }
+
+ var index = states.indexOf(root.state)
+
+ if (index < (states.length - 1)) {
+ root.state = states[index + 1]
+ return true
+ }
+
+ return false
+ }
+
+ function stateNames() {
+ var states = []
+
+ for (var i = 0; i < root.states.length; i++) {
+ var state = root.states[i]
+ states.push(state.name)
+ }
+
+ return states
+ }
+
+ signal activated
+
+ function activate() {
+ root.active = true
+ stateGroup.state = "active"
+ root.activated()
+ }
+
+ function done() {
+ stateGroup.state = "done"
+ }
+
+ function init() {
+ root.active = false
+ stateGroup.state = "inactive"
+ }
+
+ StateGroup {
+ id: stateGroup
+ states: [
+ State {
+ name: "active"
+
+ PropertyChanges {
+ target: root
+ opacity: 1
+ visible: true
+ }
+ },
+ State {
+ name: "inactive"
+
+ PropertyChanges {
+ target: root
+ opacity: 0
+ visible: true
+ }
+ },
+ State {
+ name: "done"
+
+ PropertyChanges {
+ target: root
+ opacity: 1
+ visible: true
+ }
+ }
+ ]
+ }
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/imports/UiTour/SlideNavButton.qml b/share/qtcreator/qmldesigner/welcomepage/imports/UiTour/SlideNavButton.qml
new file mode 100644
index 0000000000..07f744e300
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/imports/UiTour/SlideNavButton.qml
@@ -0,0 +1,71 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtQuick.Controls
+import WelcomeScreen 1.0
+import StudioTheme 1.0 as StudioTheme
+import UiTour
+
+Item {
+ id: tourButton
+ width: 120
+ height: 120
+ property alias dialogButtonRotation: dialogButton.rotation
+ property alias dialogButtonFontpixelSize: dialogButton.font.pixelSize
+ property alias dialogButtonText: dialogButton.text
+
+ signal buttonClicked
+
+ Text {
+ id: dialogButton
+ color: "#ffffff"
+ text: StudioTheme.Constants.nextFile_large
+ font.family: StudioTheme.Constants.iconFont.family
+ font.pixelSize: 32
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.horizontalCenter: parent.horizontalCenter
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+
+ Connections {
+ target: mouseArea
+ onClicked: tourButton.buttonClicked()
+ }
+ }
+
+ states: [
+ State {
+ name: "normal"
+ when: !mouseArea.containsMouse && !mouseArea.pressed
+
+ PropertyChanges {
+ target: dialogButton
+ color: "#ecebeb"
+ font.pixelSize: 92
+ }
+ },
+ State {
+ name: "hover"
+ when: mouseArea.containsMouse && !mouseArea.pressed
+
+ PropertyChanges {
+ target: dialogButton
+ font.pixelSize: 96
+ }
+ },
+ State {
+ name: "press"
+ when: mouseArea.pressed
+
+ PropertyChanges {
+ target: dialogButton
+ font.pixelSize: 98
+ }
+ }
+ ]
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/imports/UiTour/SlidePlayer.qml b/share/qtcreator/qmldesigner/welcomepage/imports/UiTour/SlidePlayer.qml
new file mode 100644
index 0000000000..5664223990
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/imports/UiTour/SlidePlayer.qml
@@ -0,0 +1,132 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Shapes
+import UiTour
+
+Item {
+ id: root
+ width: 1920
+ height: 1080
+ visible: true
+
+ property alias slideSource: loader.source
+ property alias loaderActive: loader.active
+ property var mainScreen: loader.item
+
+ Image {
+ id: gradientRect
+ anchors.fill: parent
+ source: "gradientRect.webp"
+ mipmap: true
+ fillMode: Image.Stretch
+ }
+
+ RowLayout {
+ anchors.fill: parent
+
+ Item {
+ Layout.preferredWidth: 160
+ Layout.maximumWidth: 160
+ Layout.fillHeight: true
+
+ SlideNavButton {
+ id: prevSlideButton
+ dialogButtonRotation: 180
+ visible: ((mainScreen.currentSlide + 1) !== 1)
+ anchors.fill: parent
+
+ Connections {
+ target: prevSlideButton
+ onButtonClicked: mainScreen.prev()
+ }
+ }
+ }
+
+ Column {
+ id: content
+ Layout.fillWidth: true
+ Layout.preferredWidth: 120
+
+ Item {
+ id: titleFrame
+ width: content.width
+ height: 100
+
+ Text {
+ color: "#ffffff"
+ text: mainScreen.title
+ font.pixelSize: 40
+ font.bold: true
+ wrapMode: Text.WordWrap
+ anchors.centerIn: parent
+ }
+ }
+
+ Item {
+ id: slideFrame
+ width: content.width
+ height: Math.min(1080 * content.width / 1920,
+ root.height - (titleFrame.height + captionFrame.height + indicatorFrame.height))
+
+ Loader {
+ id: loader
+ source: "MySlideShow.ui.qml"
+ transformOrigin: Item.Center
+ scale: Math.min(slideFrame.width / 1920, slideFrame.height / 1080)
+ anchors.centerIn: parent
+ }
+ }
+
+ Item {
+ id: captionFrame
+ width: content.width
+ height: 140
+
+ Text {
+ id: captionText
+ color: "#ffffff"
+ text: mainScreen.caption
+ font.pixelSize: 20
+ font.bold: true
+ wrapMode: Text.WordWrap
+ anchors.fill: parent
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ }
+ }
+
+ Item {
+ id: indicatorFrame
+ width: content.width
+ height: 100
+
+ Text {
+ color: "#ffffff"
+ text: (mainScreen.currentSlide + 1) + "/" + mainScreen.progress
+ font.pixelSize: 20
+ anchors.centerIn: parent
+ }
+ }
+ }
+
+ Item {
+ Layout.preferredWidth: 160
+ Layout.maximumWidth: 160
+ Layout.fillHeight: true
+
+ SlideNavButton {
+ id: nextSlideButton
+ visible: (mainScreen.progress !== (mainScreen.currentSlide + 1))
+ anchors.fill: parent
+
+ Connections {
+ target: nextSlideButton
+ onButtonClicked: mainScreen.next()
+ }
+ }
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/imports/UiTour/SlideShow.qml b/share/qtcreator/qmldesigner/welcomepage/imports/UiTour/SlideShow.qml
new file mode 100644
index 0000000000..8e7195fcb1
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/imports/UiTour/SlideShow.qml
@@ -0,0 +1,85 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtQuick.Controls
+
+Rectangle {
+ id: root
+ width: 1920
+ height: 1080
+ color: "#00000000"
+
+ property string caption
+ property string title
+
+ property int progress: 0
+ property int currentSlide: 0
+
+ function next() {
+ if (root.currentSlide === (root.progress - 1))
+ return
+
+ var index = root.findActive()
+ var current = root.children[index]
+
+ root.currentSlide++
+
+ if (current.next()) {
+ root.caption = current.caption
+ root.title = current.title
+ return
+ }
+
+ root.children[index].init()
+ root.children[index + 1].activate()
+
+ root.caption = root.children[index + 1].caption
+ root.title = root.children[index + 1].title
+ }
+
+ function prev() {
+ if (root.currentSlide === 0)
+ return
+
+ var index = root.findActive()
+ var current = root.children[index]
+
+ root.currentSlide--
+
+ if (current.prev()) {
+ root.caption = current.caption
+ root.title = current.title
+ return
+ }
+
+ root.children[index].init()
+ root.children[index - 1].activate()
+ root.caption = root.children[index - 1].caption
+ root.title = root.children[index - 1].title
+ }
+
+ function findActive() {
+ for (var i = 0; i < root.children.length; i++) {
+ var child = root.children[i]
+ if (child.active)
+ return i
+ }
+ return -1
+ }
+
+ Component.onCompleted: {
+ for (var i = 0; i < root.children.length; i++) {
+ var child = root.children[i]
+ child.init()
+ root.progress += child.states.length
+ if (i === 0) {
+ child.visible = true
+ child.activate()
+ }
+ }
+
+ root.caption = root.children[0].caption
+ root.title = root.children[0].title
+ }
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/imports/UiTour/StrongHighlight.ui.qml b/share/qtcreator/qmldesigner/welcomepage/imports/UiTour/StrongHighlight.ui.qml
new file mode 100644
index 0000000000..7b9f315b68
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/imports/UiTour/StrongHighlight.ui.qml
@@ -0,0 +1,107 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Timeline
+
+Rectangle {
+ id: root
+ width: 600
+ height: 600
+ radius: 2
+ color: "transparent"
+ border.color: "#1381e3"
+ border.width: 8
+ state: "off"
+
+ property bool active: true
+
+ property color shadowColor: "#aa1b1b1b"
+
+ property int globalX: root.x //200
+ property int globalY: root.y //200
+ property int parentWidth: root.parent.width //1200
+ property int parentHeight: root.parent.height //1200
+
+ Rectangle {
+ z: -1
+ color: "transparent"
+ anchors.fill: parent
+ border.color: root.shadowColor
+ border.width: 3
+ }
+
+ Rectangle {
+ x: -width
+ z: -1
+ width: root.globalX
+ height: root.height
+ color: root.shadowColor
+ }
+
+ Rectangle {
+ x: root.width
+ z: -1
+ width: root.parentWidth - root.globalX - root.width
+ height: root.height
+ color: root.shadowColor
+ }
+
+ Rectangle {
+ x: -root.globalX
+ y: -root.globalY
+ z: -1
+ width: root.parentWidth
+ height: root.globalY
+ color: root.shadowColor
+ }
+
+ Rectangle {
+ x: -root.globalX
+ y: root.height
+ z: -1
+ width: root.parentWidth
+ height: root.parentHeight - root.globalY - root.height
+ color: root.shadowColor
+ }
+
+ states: [
+ State {
+ name: "on"
+ when: root.active
+
+ PropertyChanges {
+ target: root
+ }
+ },
+ State {
+ name: "off"
+ when: !root.active
+
+ PropertyChanges {
+ target: root
+ opacity: 0
+ }
+ }
+ ]
+
+ transitions: [
+ Transition {
+ id: transition
+ to: "*"
+ from: "*"
+ ParallelAnimation {
+ SequentialAnimation {
+ PauseAnimation { duration: 0 }
+
+ PropertyAnimation {
+ target: root
+ property: "opacity"
+ duration: 150
+ }
+ }
+ }
+ }
+ ]
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/imports/UiTour/gradientRect.webp b/share/qtcreator/qmldesigner/welcomepage/imports/UiTour/gradientRect.webp
new file mode 100644
index 0000000000..78c2be6dbe
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/imports/UiTour/gradientRect.webp
Binary files differ
diff --git a/share/qtcreator/qmldesigner/welcomepage/imports/UiTour/qmldir b/share/qtcreator/qmldesigner/welcomepage/imports/UiTour/qmldir
new file mode 100644
index 0000000000..cf5ba7db2f
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/imports/UiTour/qmldir
@@ -0,0 +1,6 @@
+Highlight 1.0 Highlight.ui.qml
+StrongHighlight 1.0 StrongHighlight.ui.qml
+Slide 1.0 Slide.qml
+SlideShow 1.0 SlideShow.qml
+SlidePlayer 1.0 SlidePlayer.qml
+SlideNavButton 1.0 SlideNavButton.qml
diff --git a/share/qtcreator/qmldesigner/welcomepage/imports/WelcomeScreen/Constants.qml b/share/qtcreator/qmldesigner/welcomepage/imports/WelcomeScreen/Constants.qml
new file mode 100644
index 0000000000..2e4806cff5
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/imports/WelcomeScreen/Constants.qml
@@ -0,0 +1,189 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+pragma Singleton
+
+import QtQuick
+import StudioTheme 1.0
+import projectmodel 1.0
+
+QtObject {
+ id: root
+
+ property int loadingProgress: 100
+ readonly property int width: 1842
+ readonly property int height: 1080
+ property bool communityEdition: projectModel.communityVersion
+ property bool enterpriseEdition: projectModel.enterpriseVersion
+
+ /* Edit this comment to add your custom font */
+ readonly property font font: Qt.font({
+ "family": Qt.application.font.family,
+ "pixelSize": Qt.application.font.pixelSize
+ })
+ readonly property font largeFont: Qt.font({
+ "family": Qt.application.font.family,
+ "pixelSize": Qt.application.font.pixelSize * 1.6
+ })
+
+ readonly property color backgroundColor: "#c2c2c2"
+
+ property var projectModel: ProjectModel {}
+
+ // Responsive grid stuff
+ readonly property int minColumnCount: 2
+ readonly property int minThumbnailSize: 244
+ readonly property int gridSpacing: 8
+ readonly property int scrollBarWidth: 10
+ readonly property int gridMargins: 20
+ readonly property int scrollBarTrackSize: 10
+
+ property int thumbnailSize: root.adaptiveThumbnailSize
+ property int gridCellSize: root.adaptiveThumbnailSize + root.gridSpacing
+ property int adaptiveThumbnailSize: root.minThumbnailSize // default to minimum size
+
+ function responsiveResize(width) {
+ var columnCount = Math.max(Math.floor(width / (root.minThumbnailSize + root.gridSpacing)),
+ root.minColumnCount)
+ root.adaptiveThumbnailSize = Math.floor((width + root.gridSpacing) / columnCount - root.gridSpacing)
+ }
+
+ // Thumbnail margins and sizes
+ property int thumbnailMargin: 10
+ property int imageBottomMargin: 90
+ property int titleBackgroundTopMargin: 5
+ property int titleHeight: 30
+ property int titleHeightMultiline: 52
+ property int titleMargin: 5
+
+ /// THEME
+
+ /// theme selector
+ property int currentTheme: 0
+ property bool defaultBrand: true
+ property bool basic: true
+
+ /// list view
+ property bool isListView: false
+
+ /// Current theme - USE THESE IN YOUR PROPERTY BINDINGS!
+
+ /// TRAFFIC LIGHT SYSTEM
+ property color greenLight: Values.themeGreenLight
+ property color amberLight: Values.themeAmberLight
+ property color redLight: Values.themeRedLight
+
+ /// BRAND
+ property string currentBrand: root.defaultBrand ? root.qdsBrand : root.creatorBrand
+
+ /// TEXT
+ property color currentGlobalText: Values.themeTextColor
+ property color currentActiveGlobalText: "#ffffff"
+ property string brandGlobalText: root.defaultBrand ? root.qdsGlobalText : root.creatorGlobalText
+
+ /// BACKGROUND
+ property color currentThemeBackground: Values.welcomeScreenBackground
+
+ /// DIALOG
+ property color currentDialogBackground: Values.themeThumbnailBackground
+ property color currentDialogBorder: root.currentBrand
+
+ /// BUTTONS
+ property color currentPushButtonNormalBackground: Values.themeControlBackground
+ property color currentPushButtonHoverBackground: Values.themeControlBackgroundHover
+
+ property color currentPushButtonNormalOutline: Values.themeControlOutline
+ property color currentPushButtonHoverOutline: Values.themeControlOutline
+
+ /// THUMBNAILS
+ property color currentThumbnailGridBackground: Values.themeSubPanelBackground
+
+ property color currentNormalThumbnailBackground: Values.themeThumbnailBackground
+ property color currentHoverThumbnailBackground: Values.themeControlBackgroundGlobalHover
+
+ property color currentNormalThumbnailLabelBackground: Values.themeThumbnailLabelBackground
+ property color currentHoverThumbnailLabelBackground: Values.themeControlBackgroundInteraction
+
+ /// TOOLTIP
+ property color currentToolTipBackground: Values.themeToolTipBackground
+ property color currentToolTipOutline: Values.themeToolTipOutline
+ property color currentToolTipText: Values.themeToolTipText
+
+ property color currentScrollBarTrack: Values.themeScrollBarTrack
+ property color currentScrollBarHandle: Values.themeScrollBarHandle
+ property color currentScrollBarHandle_idle: Values.themeScrollBarHandle_idle
+
+ /// GLOBAL COLORS
+
+ /// brand
+ property string creatorBrand: "#54D263"
+ property string qdsBrand: "#57B9FC"
+
+
+ /// DARK THEME COLORS
+ property string darkBackground: "#242424"
+ property string modeBarDark: "#414141"
+
+ /// globalText
+ property string darkGlobalText: "#ffffff"
+ property string darkActiveGlobalText: "#111111"
+ property string qdsGlobalText: "#ffffff"
+ property string creatorGlobalText: "#111111"
+
+ /// button
+ property string darkPushButtonNormalBackground: "#323232"
+ property string darkPushButtonNormalOutline: "#000000"
+ property string darkPushButtonHoverBackground: "#474747"
+ property string darkPushButtonHoverOutline: "#000000"
+
+ /// thumbnails
+ property string darkThumbnailGridBackground: "#040404"
+ property string darkNormalThumbnailBackground: "#292929"
+ property string darkNormalThumbnailLabelBackground: "#3D3D3D"
+ property string darkHoverThumbnailBackground: "#323232"
+ property string darkHoverThumbnailLabelBackground: "#474747"
+
+
+ /// MID THEME COLORS
+ property string midBackground: "#514e48"
+ property string modeBarMid: "#737068"
+
+ /// globalText
+ property string midGlobalText: "#ffffff"
+ property string midActiveGlobalText: "#111111"
+
+ /// button
+ property string midPushButtonNormalBackground: "#43413c"
+ property string midPushButtonNormalOutline: "#636058"
+ property string midPushButtonHoverBackground: "#504D47"
+ property string midPushButtonHoverOutline: "#737068"
+
+ /// thumbnails
+ property string midThumbnailGridBackground: "#383732"
+ property string midNormalThumbnailBackground: "#514e48"
+ property string midNormalThumbnailLabelBackground: "#43413c"
+ property string midHoverThumbnailBackground: "#5B5851"
+ property string midHoverThumbnailLabelBackground: "#43413c"
+
+
+ /// LIGHT THEME COLORS
+ property string lightBackground: "#EAEAEA"
+ property string modeBarLight: "#D1CFCF"
+
+ /// globalText
+ property string lightGlobalText: "#111111"
+ property string lightActiveGlobalText: "#ffffff"
+
+ /// button
+ property string lightPushButtonNormalBackground: "#eaeaea"
+ property string lightPushButtonNormalOutline: "#CACECE"
+ property string lightPushButtonHoverBackground: "#E5E5E5"
+ property string lightPushButtonHoverOutline: "#CACECE"
+
+ /// thumbnails
+ property string lightThumbnailGridBackground: "#EFEFEF"
+ property string lightNormalThumbnailBackground: "#F2F2F2"
+ property string lightNormalThumbnailLabelBackground: "#EBEBEB"
+ property string lightHoverThumbnailBackground: "#EAEAEA"
+ property string lightHoverThumbnailLabelBackground: "#E1E1E1"
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/imports/WelcomeScreen/designer/plugin.metainfo b/share/qtcreator/qmldesigner/welcomepage/imports/WelcomeScreen/designer/plugin.metainfo
new file mode 100644
index 0000000000..680b425c54
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/imports/WelcomeScreen/designer/plugin.metainfo
@@ -0,0 +1,13 @@
+MetaInfo {
+ Type {
+ name: "WelcomeScreen.EventListSimulator"
+ icon: ":/qtquickplugin/images/item-icon16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/imports/WelcomeScreen/qmldir b/share/qtcreator/qmldesigner/welcomepage/imports/WelcomeScreen/qmldir
new file mode 100644
index 0000000000..6984623730
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/imports/WelcomeScreen/qmldir
@@ -0,0 +1,2 @@
+singleton Constants 1.0 Constants.qml
+EventListSimulator 1.0 EventListSimulator.qml
diff --git a/share/qtcreator/qmldesigner/welcomepage/main.qml b/share/qtcreator/qmldesigner/welcomepage/main.qml
new file mode 100644
index 0000000000..d76567b035
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/main.qml
@@ -0,0 +1,22 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import WelcomeScreen 1.0
+
+Loader {
+ id: loader
+ asynchronous: false
+ source: "MainScreen.qml"
+
+ property int loadingProgress: 50
+
+ onLoadingProgressChanged: {
+ Constants.loadingProgress = loader.loadingProgress
+ }
+
+ Rectangle {
+ anchors.fill: parent
+ color: Constants.currentThemeBackground
+ }
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/main.qml.qml b/share/qtcreator/qmldesigner/welcomepage/main.qml.qml
new file mode 100644
index 0000000000..fdd65d5fb0
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/main.qml.qml
@@ -0,0 +1,10 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+
+MainScreen {
+ color: "#ffffff"
+ border.color: "#ffffff"
+
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/mockData/ExampleCheckout/FileDownloader.qml b/share/qtcreator/qmldesigner/welcomepage/mockData/ExampleCheckout/FileDownloader.qml
new file mode 100644
index 0000000000..28801f7597
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/mockData/ExampleCheckout/FileDownloader.qml
@@ -0,0 +1,16 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick 2.0
+
+QtObject {
+ property url url
+ property bool finished
+ property bool error
+ property string name
+ property string completeBaseName
+ property int progress
+ property string outputFile
+ property date lastModified
+ property bool available
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/mockData/ExampleCheckout/FileExtractor.qml b/share/qtcreator/qmldesigner/welcomepage/mockData/ExampleCheckout/FileExtractor.qml
new file mode 100644
index 0000000000..ab6ea047fe
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/mockData/ExampleCheckout/FileExtractor.qml
@@ -0,0 +1,21 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick 2.0
+
+QtObject {
+
+ property string targetPath
+ property string archiveName
+ property string detailedText
+ property string currentFile
+ property string size
+ property string count
+ property string sourceFile
+
+ property bool finished
+ property bool targetFolderExists
+
+ property int progress
+ property date birthTime
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/mockData/ExampleCheckout/qmldir b/share/qtcreator/qmldesigner/welcomepage/mockData/ExampleCheckout/qmldir
new file mode 100644
index 0000000000..d4bbe25310
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/mockData/ExampleCheckout/qmldir
@@ -0,0 +1,2 @@
+FileExtractor 1.0 FileExtractor.qml
+FileDownloader 1.0 FileDownloader.qml
diff --git a/share/qtcreator/qmldesigner/welcomepage/mockData/projectmodel/ProjectModel.qml b/share/qtcreator/qmldesigner/welcomepage/mockData/projectmodel/ProjectModel.qml
new file mode 100644
index 0000000000..dc083056dc
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/mockData/projectmodel/ProjectModel.qml
@@ -0,0 +1,117 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+
+ListModel {
+ property bool communityVersion: true
+ property bool designMode: true
+
+ ListElement {
+ displayName: "Project 01"
+ prettyFilePath: "my_file_1"
+ thumbnail: "images/thumbnail_test.png"
+ }
+
+ ListElement {
+ displayName: "Project 02"
+ prettyFilePath: "my_file_2"
+ thumbnail: "images/thumbnail_test.png"
+ }
+
+ ListElement {
+ displayName: "Project 03"
+ prettyFilePath: "my_file_3"
+ thumbnail: "images/thumbnail_test.png"
+ }
+
+ ListElement {
+ displayName: "Project 04"
+ prettyFilePath: "my_file_4"
+ thumbnail: "images/thumbnail_test.png"
+ }
+
+ ListElement {
+ displayName: "Project 05"
+ prettyFilePath: "my_file_5"
+ thumbnail: "images/thumbnail_test.png"
+ }
+
+ ListElement {
+ displayName: "Project 06"
+ prettyFilePath: "my_file_6"
+ thumbnail: "images/thumbnail_test.png"
+ }
+
+ ListElement {
+ displayName: "Project 07"
+ prettyFilePath: "my_file_7"
+ thumbnail: "images/thumbnail_test.png"
+ }
+
+ ListElement {
+ displayName: "Project 08"
+ filename: "my_file_8"
+ thumbnail: "images/thumbnail_test.png"
+ }
+
+ ListElement {
+ displayName: "Project 09"
+ filename: "my_file_9"
+ thumbnail: "images/thumbnail_test.png"
+ }
+
+ ListElement {
+ displayName: "Project 10"
+ prettyFilePath: "my_file_10"
+ thumbnail: "images/thumbnail_test.png"
+ }
+
+ ListElement {
+ displayName: "Project 11"
+ filename: "my_file_11"
+ thumbnail: "images/thumbnail_test.png"
+ }
+
+ ListElement {
+ displayName: "Project 12"
+ prettyFilePath: "my_file_12"
+ thumbnail: "images/thumbnail_test.png"
+ }
+
+ ListElement {
+ displayName: "Project 13"
+ filename: "my_file_13"
+ thumbnail: "images/thumbnail_test.png"
+ }
+
+ ListElement {
+ displayName: "Project 14"
+ prettyFilePath: "my_file_14"
+ thumbnail: "images/thumbnail_test.png"
+ }
+
+ ListElement {
+ displayName: "Project 15"
+ filename: "my_file_15"
+ thumbnail: "images/thumbnail_test.png"
+ }
+
+ ListElement {
+ displayName: "Project 16"
+ filename: "my_file_16"
+ thumbnail: "images/thumbnail_test.png"
+ }
+
+ ListElement {
+ displayName: "Project 17"
+ filename: "my_file_17"
+ thumbnail: "images/thumbnail_test.png"
+ }
+
+ ListElement {
+ displayName: "Project 18"
+ prettyFilePath: "my_file_18"
+ thumbnail: "images/thumbnail_test.png"
+ }
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/mockData/projectmodel/qmldir b/share/qtcreator/qmldesigner/welcomepage/mockData/projectmodel/qmldir
new file mode 100644
index 0000000000..0d7bc345c2
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/mockData/projectmodel/qmldir
@@ -0,0 +1 @@
+ProjectModel 1.0 ProjectModel.qml
diff --git a/share/qtcreator/qmldesigner/welcomepage/mockData/usagestatistics/UsageStatisticModel.qml b/share/qtcreator/qmldesigner/welcomepage/mockData/usagestatistics/UsageStatisticModel.qml
new file mode 100644
index 0000000000..583f80b690
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/mockData/usagestatistics/UsageStatisticModel.qml
@@ -0,0 +1,8 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+
+QtObject {
+ property bool usageStatisticEnabled: false
+}
diff --git a/share/qtcreator/qmldesigner/welcomepage/mockData/usagestatistics/qmldir b/share/qtcreator/qmldesigner/welcomepage/mockData/usagestatistics/qmldir
new file mode 100644
index 0000000000..c83a43a8ae
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/mockData/usagestatistics/qmldir
@@ -0,0 +1 @@
+UsageStatisticModel 1.0 UsageStatisticModel.qml
diff --git a/share/qtcreator/qmldesigner/welcomepage/qtquickcontrols2.conf b/share/qtcreator/qmldesigner/welcomepage/qtquickcontrols2.conf
new file mode 100644
index 0000000000..db9486764e
--- /dev/null
+++ b/share/qtcreator/qmldesigner/welcomepage/qtquickcontrols2.conf
@@ -0,0 +1,2 @@
+[Controls]
+Style=Basic
diff --git a/share/qtcreator/qmldesigner/workspacePresets/Advanced-3D.wrk b/share/qtcreator/qmldesigner/workspacePresets/Advanced-3D.wrk
index 24eace89b8..f7f232dc60 100644
--- a/share/qtcreator/qmldesigner/workspacePresets/Advanced-3D.wrk
+++ b/share/qtcreator/qmldesigner/workspacePresets/Advanced-3D.wrk
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<QtAdvancedDockingSystem version="1" userVersion="0" containers="1" displayName="3D Advanced">
+<QtAdvancedDockingSystem version="1" userVersion="0" containers="1" displayName="3D Advanced" mcusEnabled="false">
<container floating="false">
<splitter orientation="Vertical" count="2">
<splitter orientation="Horizontal" count="3">
diff --git a/share/qtcreator/qmldesigner/workspacePresets/Animation-2D.wrk b/share/qtcreator/qmldesigner/workspacePresets/Animation-2D.wrk
index 346856dd50..c7045549fc 100644
--- a/share/qtcreator/qmldesigner/workspacePresets/Animation-2D.wrk
+++ b/share/qtcreator/qmldesigner/workspacePresets/Animation-2D.wrk
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<QtAdvancedDockingSystem version="1" userVersion="0" containers="1" displayName="2D Animation">
+<QtAdvancedDockingSystem version="1" userVersion="0" containers="1" displayName="2D Animation" mcusEnabled="true">
<container floating="false">
<splitter orientation="Vertical" count="2">
<splitter orientation="Horizontal" count="3">
diff --git a/share/qtcreator/qmldesigner/workspacePresets/Animation-3D.wrk b/share/qtcreator/qmldesigner/workspacePresets/Animation-3D.wrk
index 8f1d59119c..2481c365b9 100644
--- a/share/qtcreator/qmldesigner/workspacePresets/Animation-3D.wrk
+++ b/share/qtcreator/qmldesigner/workspacePresets/Animation-3D.wrk
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<QtAdvancedDockingSystem version="1" userVersion="0" containers="1" displayName="3D Animation">
+<QtAdvancedDockingSystem version="1" userVersion="0" containers="1" displayName="3D Animation" mcusEnabled="false">
<container floating="false">
<splitter orientation="Horizontal" count="2">
<splitter orientation="Vertical" count="2">
diff --git a/share/qtcreator/qmldesigner/workspacePresets/Basic.wrk b/share/qtcreator/qmldesigner/workspacePresets/Basic.wrk
index b1edb18677..ca1ef34110 100644
--- a/share/qtcreator/qmldesigner/workspacePresets/Basic.wrk
+++ b/share/qtcreator/qmldesigner/workspacePresets/Basic.wrk
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<QtAdvancedDockingSystem version="1" userVersion="0" containers="1" displayName="Default">
+<QtAdvancedDockingSystem version="1" userVersion="0" containers="1" displayName="Default" mcusEnabled="true">
<container floating="false">
<splitter orientation="Horizontal" count="3">
<splitter orientation="Vertical" count="3">
diff --git a/share/qtcreator/qmldesigner/workspacePresets/Code.wrk b/share/qtcreator/qmldesigner/workspacePresets/Code.wrk
index 82f734432f..828b930c5f 100644
--- a/share/qtcreator/qmldesigner/workspacePresets/Code.wrk
+++ b/share/qtcreator/qmldesigner/workspacePresets/Code.wrk
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<QtAdvancedDockingSystem version="1" userVersion="0" containers="1" displayName="Code">
+<QtAdvancedDockingSystem version="1" userVersion="0" containers="1" displayName="Code" mcusEnabled="true">
<container floating="false">
<splitter orientation="Horizontal" count="3">
<splitter orientation="Vertical" count="3">
diff --git a/share/qtcreator/qmldesigner/workspacePresets/Essentials-3D.wrk b/share/qtcreator/qmldesigner/workspacePresets/Essentials-3D.wrk
index 74215ffd45..2117c61db0 100644
--- a/share/qtcreator/qmldesigner/workspacePresets/Essentials-3D.wrk
+++ b/share/qtcreator/qmldesigner/workspacePresets/Essentials-3D.wrk
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<QtAdvancedDockingSystem version="1" userVersion="0" containers="1" displayName="3D Essentials">
+<QtAdvancedDockingSystem version="1" userVersion="0" containers="1" displayName="3D Essentials" mcusEnabled="false">
<container floating="false">
<splitter orientation="Horizontal" count="3">
<splitter orientation="Vertical" count="3">
diff --git a/share/qtcreator/qmldesigner/workspacePresets/Essentials.wrk b/share/qtcreator/qmldesigner/workspacePresets/Essentials.wrk
index e11f39ec94..c71b377d8c 100644
--- a/share/qtcreator/qmldesigner/workspacePresets/Essentials.wrk
+++ b/share/qtcreator/qmldesigner/workspacePresets/Essentials.wrk
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<QtAdvancedDockingSystem version="1" containers="1" displayName="Essentials">
+<QtAdvancedDockingSystem version="1" containers="1" displayName="Essentials" mcusEnabled="true">
<container floating="false">
<splitter orientation="Horizontal" count="3">
<splitter orientation="Vertical" count="3">
diff --git a/share/qtcreator/qmldesigner/workspacePresets/UX-Design.wrk b/share/qtcreator/qmldesigner/workspacePresets/UX-Design.wrk
index 5e97336662..f6c1329a7d 100644
--- a/share/qtcreator/qmldesigner/workspacePresets/UX-Design.wrk
+++ b/share/qtcreator/qmldesigner/workspacePresets/UX-Design.wrk
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<QtAdvancedDockingSystem version="1" userVersion="0" containers="1" displayName="Design">
+<QtAdvancedDockingSystem version="1" userVersion="0" containers="1" displayName="Design" mcusEnabled="true">
<container floating="false">
<splitter orientation="Vertical" count="2">
<splitter orientation="Horizontal" count="3">
diff --git a/share/qtcreator/qmldesigner/workspacePresets/Views-All.wrk b/share/qtcreator/qmldesigner/workspacePresets/Views-All.wrk
index 6dc9548347..011ead83a6 100644
--- a/share/qtcreator/qmldesigner/workspacePresets/Views-All.wrk
+++ b/share/qtcreator/qmldesigner/workspacePresets/Views-All.wrk
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<QtAdvancedDockingSystem version="1" userVersion="0" containers="2" displayName="All Views">
+<QtAdvancedDockingSystem version="1" userVersion="0" containers="2" displayName="All Views" mcusEnabled="false">
<container floating="false">
<splitter orientation="Horizontal" count="3">
<splitter orientation="Vertical" count="3">
diff --git a/src/libs/advanceddockingsystem/dockmanager.cpp b/src/libs/advanceddockingsystem/dockmanager.cpp
index 5cae131fac..b718302f4c 100644
--- a/src/libs/advanceddockingsystem/dockmanager.cpp
+++ b/src/libs/advanceddockingsystem/dockmanager.cpp
@@ -1578,6 +1578,55 @@ bool DockManager::writeDisplayName(const FilePath &filePath, const QString &disp
return true;
}
+QString DockManager::readMcusEnabled(const FilePath &filePath)
+{
+ auto data = loadFile(filePath);
+
+ if (data.isEmpty())
+ return {};
+
+ auto tmp = data.startsWith("<?xml") ? data : qUncompress(data);
+
+ DockingStateReader reader(tmp);
+ if (!reader.readNextStartElement())
+ return {};
+
+ if (reader.name() != QLatin1String("QtAdvancedDockingSystem"))
+ return {};
+
+ return reader.attributes().value(workspaceMcusEnabledAttribute.toString()).toString();
+}
+
+bool DockManager::writeMcusEnabled(const FilePath &filePath, const QString &mcusEnabled)
+{
+ const expected_str<QByteArray> content = filePath.fileContents();
+
+ QTC_ASSERT_EXPECTED(content, return false);
+
+ QDomDocument doc;
+ QString error_msg;
+ int error_line, error_col;
+ if (!doc.setContent(*content, &error_msg, &error_line, &error_col)) {
+ qWarning() << QString("XML error on line %1, col %2: %3")
+ .arg(error_line)
+ .arg(error_col)
+ .arg(error_msg);
+ return false;
+ }
+
+ QDomElement docElem = doc.documentElement();
+ docElem.setAttribute(workspaceMcusEnabledAttribute.toString(), mcusEnabled);
+
+ const expected_str<void> result = write(filePath, doc.toByteArray(workspaceXmlFormattingIndent));
+ if (!result) {
+ qWarning() << "Could not write mcusEnabled" << mcusEnabled << "to" << filePath << ":"
+ << result.error();
+ return false;
+ }
+
+ return true;
+}
+
expected_str<void> DockManager::write(const FilePath &filePath, const QByteArray &data)
{
qCInfo(adsLog) << "Write" << filePath;
@@ -1638,6 +1687,11 @@ void DockManager::syncWorkspacePresets()
const QString name = readDisplayName(userFile);
if (name.isEmpty())
writeDisplayName(userFile, name);
+
+ const QString presetMcusEnabled = readMcusEnabled(filePath);
+ const QString mcusEnabled = readMcusEnabled(userFile);
+ if (mcusEnabled.isEmpty() || mcusEnabled != presetMcusEnabled)
+ writeMcusEnabled(userFile, presetMcusEnabled);
}
continue;
@@ -1694,4 +1748,12 @@ void DockManager::saveLockWorkspace()
d->m_settings->setValue(Constants::LOCK_WORKSPACE_SETTINGS_KEY, d->m_workspaceLocked);
}
+void DockManager::setMcusProject(bool value) {
+ m_mcusProject = value;
+}
+
+bool DockManager::mcusProject() const {
+ return m_mcusProject;
+}
+
} // namespace ADS
diff --git a/src/libs/advanceddockingsystem/dockmanager.h b/src/libs/advanceddockingsystem/dockmanager.h
index 53117b93e6..23aa21a578 100644
--- a/src/libs/advanceddockingsystem/dockmanager.h
+++ b/src/libs/advanceddockingsystem/dockmanager.h
@@ -57,6 +57,7 @@ inline constexpr QStringView workspaceFolderName{u"workspaces"};
inline constexpr QStringView workspaceFileExtension{u"wrk"};
inline constexpr QStringView workspaceOrderFileName{u"order.json"};
inline constexpr QStringView workspaceDisplayNameAttribute{u"displayName"};
+inline constexpr QStringView workspaceMcusEnabledAttribute{u"mcusEnabled"};
inline const int workspaceXmlFormattingIndent = 2;
/**
@@ -760,6 +761,8 @@ public:
static QByteArray loadFile(const Utils::FilePath &filePath);
static QString readDisplayName(const Utils::FilePath &filePath);
static bool writeDisplayName(const Utils::FilePath &filePath, const QString &displayName);
+ static QString readMcusEnabled(const Utils::FilePath &filePath);
+ static bool writeMcusEnabled(const Utils::FilePath &filePath, const QString &mcusEnabled);
/**
* This is used to limit saving of workspaces to only when they were actually presented ones,
@@ -768,6 +771,9 @@ public:
*/
void aboutToShow();
+ void setMcusProject(bool value);
+ bool mcusProject() const;
+
signals:
void aboutToUnloadWorkspace(QString fileName);
void aboutToLoadWorkspace(QString fileName);
@@ -789,6 +795,8 @@ private:
void saveStartupWorkspace();
void saveLockWorkspace();
+
+ bool m_mcusProject = false;
}; // class DockManager
} // namespace ADS
diff --git a/src/libs/advanceddockingsystem/workspace.cpp b/src/libs/advanceddockingsystem/workspace.cpp
index d3b0785d90..8022b36f17 100644
--- a/src/libs/advanceddockingsystem/workspace.cpp
+++ b/src/libs/advanceddockingsystem/workspace.cpp
@@ -28,6 +28,12 @@ Workspace::Workspace(const Utils::FilePath &filePath, bool isPreset)
} else {
m_name = name;
}
+
+ QString mcusEnabled = DockManager::readMcusEnabled(m_filePath);
+ if (mcusEnabled.isEmpty())
+ setMcusEnabled(true);
+ else
+ m_mcusEnabled = QVariant::fromValue(mcusEnabled).toBool();
}
void Workspace::setName(const QString &name)
@@ -84,6 +90,18 @@ bool Workspace::isPreset() const
return m_preset;
}
+void Workspace::setMcusEnabled(bool enabled)
+{
+ QString mcusEnabled = QVariant::fromValue(enabled).toString();
+ if (DockManager::writeMcusEnabled(filePath(), mcusEnabled))
+ m_mcusEnabled = enabled;
+}
+
+bool Workspace::isMcusEnabled() const
+{
+ return m_mcusEnabled;
+}
+
Workspace::operator QString() const
{
return QString("Workspace %1 Preset[%2] %3")
diff --git a/src/libs/advanceddockingsystem/workspace.h b/src/libs/advanceddockingsystem/workspace.h
index c23db55d6b..e89edb5539 100644
--- a/src/libs/advanceddockingsystem/workspace.h
+++ b/src/libs/advanceddockingsystem/workspace.h
@@ -30,6 +30,9 @@ public:
void setPreset(bool value);
bool isPreset() const;
+ void setMcusEnabled(bool value);
+ bool isMcusEnabled() const;
+
friend bool operator==(const Workspace &a, const Workspace &b)
{
return a.fileName() == b.fileName();
@@ -50,6 +53,7 @@ private:
QString m_name;
Utils::FilePath m_filePath;
bool m_preset = false;
+ bool m_mcusEnabled = true;
};
} // namespace ADS
diff --git a/src/libs/advanceddockingsystem/workspacemodel.cpp b/src/libs/advanceddockingsystem/workspacemodel.cpp
index 99d3bd1473..2748d85fc6 100644
--- a/src/libs/advanceddockingsystem/workspacemodel.cpp
+++ b/src/libs/advanceddockingsystem/workspacemodel.cpp
@@ -22,7 +22,7 @@ WorkspaceModel::WorkspaceModel(DockManager *manager, QObject *parent)
connect(m_manager, &DockManager::workspaceLoaded, this, &WorkspaceModel::resetWorkspaces);
}
-int WorkspaceModel::indexOfWorkspace(const QString &fileName)
+int WorkspaceModel::indexOfWorkspace(const QString &fileName) const
{
return m_manager->workspaceIndex(fileName);
}
@@ -134,6 +134,10 @@ Qt::ItemFlags WorkspaceModel::flags(const QModelIndex &index) const
{
Qt::ItemFlags defaultFlags = QAbstractTableModel::flags(index);
+ Workspace *workspace = m_manager->workspace(workspaceAt(index.row()));
+ if (m_manager->mcusProject() && !workspace->isMcusEnabled())
+ defaultFlags &= ~Qt::ItemIsEnabled;
+
if (index.isValid())
return Qt::ItemIsDragEnabled | defaultFlags;
diff --git a/src/libs/advanceddockingsystem/workspacemodel.h b/src/libs/advanceddockingsystem/workspacemodel.h
index fe868f71f5..2d6e0ef16b 100644
--- a/src/libs/advanceddockingsystem/workspacemodel.h
+++ b/src/libs/advanceddockingsystem/workspacemodel.h
@@ -21,7 +21,7 @@ public:
explicit WorkspaceModel(DockManager *manager, QObject *parent = nullptr);
- int indexOfWorkspace(const QString &fileName);
+ int indexOfWorkspace(const QString &fileName) const;
QString workspaceAt(int row) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
diff --git a/src/libs/qmljs/qmljsinterpreter.h b/src/libs/qmljs/qmljsinterpreter.h
index 3fcce78d11..8651196aef 100644
--- a/src/libs/qmljs/qmljsinterpreter.h
+++ b/src/libs/qmljs/qmljsinterpreter.h
@@ -1127,6 +1127,11 @@ public:
[[maybe_unused]] const Document *context,
[[maybe_unused]] ValueOwner *valueOwner,
[[maybe_unused]] Snapshot *snapshot) {}
+ virtual Utils::FilePaths prioritizeImportPaths([[maybe_unused]] const Document *context,
+ const Utils::FilePaths &importPaths)
+ {
+ return importPaths;
+ }
};
} // namespace QmlJS
diff --git a/src/libs/qmljs/qmljslink.cpp b/src/libs/qmljs/qmljslink.cpp
index b837037b7c..97c00e1c8d 100644
--- a/src/libs/qmljs/qmljslink.cpp
+++ b/src/libs/qmljs/qmljslink.cpp
@@ -219,6 +219,7 @@ Context::ImportsPerDocument LinkPrivate::linkImports()
document.data(),
m_valueOwner,
&m_snapshot);
+ m_importPaths = provider->prioritizeImportPaths(document.data(), m_importPaths);
}
populateImportedTypes(imports, document);
diff --git a/src/plugins/clangformat/clangformatbaseindenter.cpp b/src/plugins/clangformat/clangformatbaseindenter.cpp
index ac788c8a4b..dbbacd48a9 100644
--- a/src/plugins/clangformat/clangformatbaseindenter.cpp
+++ b/src/plugins/clangformat/clangformatbaseindenter.cpp
@@ -389,6 +389,7 @@ Utils::ChangeSet convertReplacements(const QTextDocument *doc,
.size();
QString replacementText = QString::fromStdString(replacement.getReplacementText().str());
+ replacementText.replace("\r", "");
auto sameCharAt = [&](int replacementOffset) {
if (replacementText.size() <= replacementOffset || replacementOffset < 0)
return false;
diff --git a/src/plugins/cppeditor/cpptoolsreuse.cpp b/src/plugins/cppeditor/cpptoolsreuse.cpp
index c8ce0effea..d7e403a1cc 100644
--- a/src/plugins/cppeditor/cpptoolsreuse.cpp
+++ b/src/plugins/cppeditor/cpptoolsreuse.cpp
@@ -786,6 +786,7 @@ SearchResultItems symbolOccurrencesInDeclarationComments(
QList<Text::Range> symbolOccurrencesInText(const QTextDocument &doc, QStringView text, int offset,
const QString &symbolName)
{
+ QTC_ASSERT(!symbolName.isEmpty(), return QList<Text::Range>());
QList<Text::Range> ranges;
int index = 0;
while (true) {
diff --git a/src/plugins/effectmakernew/compositionnode.cpp b/src/plugins/effectmakernew/compositionnode.cpp
index 9412153dde..811cdbcb8f 100644
--- a/src/plugins/effectmakernew/compositionnode.cpp
+++ b/src/plugins/effectmakernew/compositionnode.cpp
@@ -113,6 +113,9 @@ void CompositionNode::parse(const QString &effectName, const QString &qenPath, c
m_fragmentCode = EffectUtils::codeFromJsonArray(json.value("fragmentCode").toArray());
m_vertexCode = EffectUtils::codeFromJsonArray(json.value("vertexCode").toArray());
+ if (json.contains("enabled"))
+ m_isEnabled = json["enabled"].toBool();
+
m_id = json.value("id").toString();
if (m_id.isEmpty() && !qenPath.isEmpty()) {
QString fileName = qenPath.split('/').last();
diff --git a/src/plugins/effectmakernew/effectmakermodel.cpp b/src/plugins/effectmakernew/effectmakermodel.cpp
index 4fcb6686a7..dc71418f1d 100644
--- a/src/plugins/effectmakernew/effectmakermodel.cpp
+++ b/src/plugins/effectmakernew/effectmakermodel.cpp
@@ -87,6 +87,7 @@ bool EffectMakerModel::setData(const QModelIndex &index, const QVariant &value,
if (role == EnabledRole) {
m_nodes.at(index.row())->setIsEnabled(value.toBool());
bakeShaders();
+ setHasUnsavedChanges(true);
emit dataChanged(index, index, {role});
}
@@ -192,14 +193,17 @@ void EffectMakerModel::removeNode(int idx)
emit nodesChanged();
}
-void EffectMakerModel::clear()
+void EffectMakerModel::clear(bool clearName)
{
beginResetModel();
qDeleteAll(m_nodes);
m_nodes.clear();
endResetModel();
+
+ if (clearName)
+ setCurrentComposition("");
+
setHasUnsavedChanges(!m_currentComposition.isEmpty());
- setCurrentComposition("");
setIsEmpty(true);
emit nodesChanged();
@@ -413,6 +417,7 @@ void EffectMakerModel::setEffectError(const QString &errorMessage, int type, int
QString additionalErrorInfo = detectErrorMessage(errorMessage);
error.m_message = additionalErrorInfo + errorMessage;
m_effectErrors.insert(type, error);
+ qWarning() << QString("Effect error (line: %2): %1").arg(error.m_message, error.m_line);
Q_EMIT effectErrorChanged();
}
@@ -556,13 +561,23 @@ QString EffectMakerModel::getQmlEffectString()
{
QString s;
- s += QString("// Created with Qt Design Studio (version %1), %2\n\n")
- .arg(qApp->applicationVersion(), QDateTime::currentDateTime().toString());
- s += "import QtQuick\n";
- s += '\n';
- s += "Item {\n";
- s += " id: rootItem\n";
- s += '\n';
+ // _isEffectItem is type var to hide it from property view
+ QString header{
+R"(
+// Created with Qt Design Studio (version %1), %2
+
+import QtQuick
+
+Item {
+ id: rootItem
+
+ property var _isEffectItem
+ property Item _oldParent: null
+)"
+ };
+
+ s += header.arg(qApp->applicationVersion(), QDateTime::currentDateTime().toString());
+
if (m_shaderFeatures.enabled(ShaderFeatures::Source)) {
s += " // This is the main source for the effect\n";
s += " property Item source: null\n";
@@ -570,7 +585,7 @@ QString EffectMakerModel::getQmlEffectString()
if (m_shaderFeatures.enabled(ShaderFeatures::Time)
|| m_shaderFeatures.enabled(ShaderFeatures::Frame)) {
s += " // Enable this to animate iTime property\n";
- s += " property bool timeRunning: false\n";
+ s += " property bool timeRunning: true\n";
}
if (m_shaderFeatures.enabled(ShaderFeatures::Time)) {
s += " // When timeRunning is false, this can be used to control iTime manually\n";
@@ -580,7 +595,33 @@ QString EffectMakerModel::getQmlEffectString()
s += " // When timeRunning is false, this can be used to control iFrame manually\n";
s += " property int animatedFrame: frameAnimation.currentFrame\n";
}
- s += '\n';
+
+ QString parentChanged{
+R"(
+ onParentChanged: {
+ if (_oldParent && _oldParent !== parent) {
+ _oldParent.layer.enabled = false
+ _oldParent.layer.effect = null
+ %2
+ _oldParent.update()
+ _oldParent = null
+ }
+ if (parent) {
+ _oldParent = parent
+ parent.layer.enabled = true
+ parent.layer.effect = effectComponent
+ %1
+ }
+ }
+)"
+ };
+
+ parentChanged = parentChanged.arg(m_shaderFeatures.enabled(ShaderFeatures::Source)
+ ? QString("source = parent") : QString(),
+ m_shaderFeatures.enabled(ShaderFeatures::Source)
+ ? QString("source = null") : QString());
+ s += parentChanged;
+
// Custom properties
if (!m_exportedRootPropertiesString.isEmpty()) {
s += m_exportedRootPropertiesString;
@@ -595,19 +636,14 @@ QString EffectMakerModel::getQmlEffectString()
s += '\n';
}
- if (m_shaderFeatures.enabled(ShaderFeatures::BlurSources)) {
- s += " BlurHelper {\n";
- s += " id: blurHelper\n";
- s += " anchors.fill: parent\n";
- int blurMax = 32;
- if (g_propertyData.contains("BLUR_HELPER_MAX_LEVEL"))
- blurMax = g_propertyData["BLUR_HELPER_MAX_LEVEL"].toInt();
- s += QString(" property int blurMax: %1\n").arg(blurMax);
- s += " property real blurMultiplier: rootItem.blurMultiplier\n";
- s += " }\n";
- }
+ QString customImagesString = getQmlImagesString(true);
+ if (!customImagesString.isEmpty())
+ s += customImagesString;
+ s += " Component {\n";
+ s += " id: effectComponent\n";
s += getQmlComponentString(true);
+ s += " }\n";
s += "}\n";
return s;
}
@@ -651,7 +687,7 @@ void EffectMakerModel::saveComposition(const QString &name)
void EffectMakerModel::openComposition(const QString &path)
{
- clear();
+ clear(true);
const QString effectName = QFileInfo(path).baseName();
setCurrentComposition(effectName);
@@ -785,10 +821,10 @@ void EffectMakerModel::saveResources(const QString &name)
for (int i = 1; i < qmlStringList.size(); i++) {
QString line = qmlStringList.at(i).trimmed();
if (line.startsWith("vertexShader")) {
- QString vsLine = " vertexShader: '" + vsFilename + "'";
+ QString vsLine = " vertexShader: '" + vsFilename + "'";
qmlStringList[i] = vsLine;
} else if (line.startsWith("fragmentShader")) {
- QString fsLine = " fragmentShader: '" + fsFilename + "'";
+ QString fsLine = " fragmentShader: '" + fsFilename + "'";
qmlStringList[i] = fsLine;
}
}
@@ -1287,17 +1323,17 @@ void EffectMakerModel::updateCustomUniforms()
if (!uniform->description().isEmpty()) {
const QStringList descriptionLines = uniform->description().split('\n');
for (const QString &line : descriptionLines)
- exportedEffectPropertiesString += QStringLiteral(" // ") + line + '\n';
+ exportedEffectPropertiesString += QStringLiteral(" // ") + line + '\n';
}
- exportedEffectPropertiesString += QStringLiteral(" ") + readOnly
+ exportedEffectPropertiesString += QStringLiteral(" ") + readOnly
+ "property " + propertyType + " " + propertyName
+ boundValueString + '\n';
} else {
// Custom values are not added into root
exportedRootPropertiesString += " property " + propertyType + " " + propertyName
+ valueString + '\n';
- exportedEffectPropertiesString += QStringLiteral(" ")
- + readOnly + "property alias " + propertyName
+ exportedEffectPropertiesString += QStringLiteral(" ")
+ + readOnly + "property " + propertyType + " " + propertyName
+ ": rootItem." + uniform->name() + '\n';
}
}
@@ -1488,22 +1524,26 @@ QString EffectMakerModel::getQmlComponentString(bool localFiles)
{
if (localFiles) {
const QString parent = blurHelper ? QString("blurHelper.") : QString("rootItem.");
- return QString("readonly property alias %1: %2%3\n").arg(name, parent, var);
+ return QString("readonly property %1 %2: %3%4\n").arg(type, name, parent, var);
} else {
const QString parent = blurHelper ? "blurHelper." : QString();
return QString("readonly property %1 %2: %3%4\n").arg(type, name, parent, var);
}
};
- QString customImagesString = getQmlImagesString(localFiles);
QString s;
- QString l1 = localFiles ? QStringLiteral(" ") : QStringLiteral("");
- QString l2 = localFiles ? QStringLiteral(" ") : QStringLiteral(" ");
- QString l3 = localFiles ? QStringLiteral(" ") : QStringLiteral(" ");
+ QString l1 = localFiles ? QStringLiteral(" ") : QStringLiteral("");
+ QString l2 = localFiles ? QStringLiteral(" ") : QStringLiteral(" ");
+ QString l3 = localFiles ? QStringLiteral(" ") : QStringLiteral(" ");
if (!localFiles)
s += "import QtQuick\n";
s += l1 + "ShaderEffect {\n";
+
+ if (localFiles) {
+ // Explicit "source" property is required for render puppet to detect effect correctly
+ s += l2 + "property Item source: null\n";
+ }
if (m_shaderFeatures.enabled(ShaderFeatures::Source))
s += l2 + addProperty("iSource", "source", "Item");
if (m_shaderFeatures.enabled(ShaderFeatures::Time))
@@ -1529,15 +1569,18 @@ QString EffectMakerModel::getQmlComponentString(bool localFiles)
// and when in exported component, property with binding to root value.
s += localFiles ? m_exportedEffectPropertiesString : m_previewEffectPropertiesString;
- if (!customImagesString.isEmpty())
- s += '\n' + customImagesString;
+ if (!localFiles) {
+ QString customImagesString = getQmlImagesString(false);
+ if (!customImagesString.isEmpty())
+ s += '\n' + customImagesString;
+ }
s += '\n';
const QString vertFile = localFiles ? m_vertexShaderFilename : m_vertexShaderPreviewFilename;
const QString fragFile = localFiles ? m_fragmentShaderFilename : m_fragmentShaderPreviewFilename;
s += l2 + "vertexShader: 'file:///" + vertFile + "'\n";
s += l2 + "fragmentShader: 'file:///" + fragFile + "'\n";
- s += l2 + "anchors.fill: parent\n";
+ s += l2 + "anchors.fill: " + (localFiles ? "rootItem.source" : "parent") + "\n";
if (m_shaderFeatures.enabled(ShaderFeatures::GridMesh)) {
QString gridSize = QString("%1, %2").arg(m_shaderFeatures.gridMeshWidth())
.arg(m_shaderFeatures.gridMeshHeight());
@@ -1545,6 +1588,18 @@ QString EffectMakerModel::getQmlComponentString(bool localFiles)
s += l3 + QString("resolution: Qt.size(%1)\n").arg(gridSize);
s += l2 + "}\n";
}
+ if (localFiles && m_shaderFeatures.enabled(ShaderFeatures::BlurSources)) {
+ s += l2 + "BlurHelper {\n";
+ s += l3 + "id: blurHelper\n";
+ s += l3 + "source: rootItem.source\n";
+ int blurMax = 32;
+ if (g_propertyData.contains("BLUR_HELPER_MAX_LEVEL"))
+ blurMax = g_propertyData["BLUR_HELPER_MAX_LEVEL"].toInt();
+ s += l3 + QString("property int blurMax: %1\n").arg(blurMax);
+ s += l3 + "property real blurMultiplier: rootItem.blurMultiplier\n";
+ s += l2 + "}\n";
+ }
+
s += l1 + "}\n";
return s;
}
diff --git a/src/plugins/effectmakernew/effectmakermodel.h b/src/plugins/effectmakernew/effectmakermodel.h
index a25a4e4091..1bbac9cd55 100644
--- a/src/plugins/effectmakernew/effectmakermodel.h
+++ b/src/plugins/effectmakernew/effectmakermodel.h
@@ -66,7 +66,7 @@ public:
Q_INVOKABLE void moveNode(int fromIdx, int toIdx);
Q_INVOKABLE void removeNode(int idx);
- Q_INVOKABLE void clear();
+ Q_INVOKABLE void clear(bool clearName = false);
Q_INVOKABLE void assignToSelected();
Q_INVOKABLE QString getUniqueEffectName() const;
diff --git a/src/plugins/mcusupport/mcusupportimportprovider.cpp b/src/plugins/mcusupport/mcusupportimportprovider.cpp
index b78baf8bd9..f83dec6cb7 100644
--- a/src/plugins/mcusupport/mcusupportimportprovider.cpp
+++ b/src/plugins/mcusupport/mcusupportimportprovider.cpp
@@ -119,6 +119,30 @@ void McuSupportImportProvider::loadBuiltins(ImportsPerDocument *importsPerDocume
import.info = ImportInfo::moduleImport("qul", {1, 0}, QString());
getInterfacesImport(context->fileName(), importsPerDocument, import, valueOwner, snapshot);
imports->append(import);
+}
+
+FilePaths McuSupportImportProvider::prioritizeImportPaths(const Document *context,
+ const FilePaths &importPaths)
+{
+ if (!context)
+ return importPaths;
+ const std::optional<FilePath> cmakeFilesPathOpt = getTargetBuildFolder(context->fileName());
+ if (!cmakeFilesPathOpt)
+ return importPaths;
+ FilePaths ret;
+ // qmltocpp uses an incomplete QtQuick folder present in the build folder
+ // to avoid taking precedence over the correct qul_install/include/*/StyleDefault
+ // move the import path to be last
+ std::copy_if(importPaths.cbegin(),
+ importPaths.cend(),
+ std::back_inserter(ret),
+ [cmakeFilesPathOpt](const FilePath &path) { return path != *cmakeFilesPathOpt; });
+
+ // nothing was removed
+ if (ret.size() == importPaths.size())
+ return importPaths;
+ ret.push_back(*cmakeFilesPathOpt);
+ return ret;
};
void McuSupportImportProvider::getInterfacesImport(const FilePath &path,
@@ -156,6 +180,7 @@ std::optional<FilePath> McuSupportImportProvider::getFileModule(const FilePath &
const FilePath &inputFile) const
{
const auto doc = QJsonDocument::fromJson(inputFile.fileContents().value_or(""));
+
if (!doc.isObject())
return {};
diff --git a/src/plugins/mcusupport/mcusupportimportprovider.h b/src/plugins/mcusupport/mcusupportimportprovider.h
index c1a130ed3d..f7457751b0 100644
--- a/src/plugins/mcusupport/mcusupportimportprovider.h
+++ b/src/plugins/mcusupport/mcusupportimportprovider.h
@@ -29,6 +29,9 @@ public:
ValueOwner *valueOwner,
Snapshot *snapshot) override;
+ virtual Utils::FilePaths prioritizeImportPaths(const Document *context,
+ const Utils::FilePaths &importPaths) override;
+
// Add to the interfaces needed for a document
// path: opened qml document
// importsPerDocument: imports available in the document (considered imported)
diff --git a/src/plugins/projectexplorer/abi.cpp b/src/plugins/projectexplorer/abi.cpp
index 07365fc5dd..d1bd01b89b 100644
--- a/src/plugins/projectexplorer/abi.cpp
+++ b/src/plugins/projectexplorer/abi.cpp
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "abi.h"
+#include "projectexplorerconstants.h"
#include <utils/algorithm.h>
#include <utils/environment.h>
@@ -437,6 +438,18 @@ static Abis abiOf(const QByteArray &data)
return result;
}
+static QString androidAbiFromAbi(const Abi &abi)
+{
+ QString androidAbi;
+ if (abi.architecture() == Abi::Architecture::ArmArchitecture)
+ androidAbi = QLatin1String(abi.wordWidth() == 64 ? Constants::ANDROID_ABI_ARM64_V8A
+ : Constants::ANDROID_ABI_ARMEABI_V7A);
+ else
+ androidAbi = QLatin1String(abi.wordWidth() == 64 ? Constants::ANDROID_ABI_X86_64
+ : Constants::ANDROID_ABI_X86);
+ return androidAbi;
+}
+
// --------------------------------------------------------------------------
// Abi
// --------------------------------------------------------------------------
@@ -908,7 +921,11 @@ Abi Abi::fromString(const QString &abiString)
return Abi(architecture, os, flavor, format, 0);
}
- return Abi(architecture, os, flavor, format, wordWidth);
+ Abi abi(architecture, os, flavor, format, wordWidth);
+ if (abi.os() == LinuxOS && abi.osFlavor() == AndroidLinuxFlavor)
+ abi.m_param = androidAbiFromAbi(abi);
+
+ return abi;
}
Abi::Architecture Abi::architectureFromString(const QString &a)
diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt
index e167a83db3..b13841019c 100644
--- a/src/plugins/qmldesigner/CMakeLists.txt
+++ b/src/plugins/qmldesigner/CMakeLists.txt
@@ -839,7 +839,6 @@ extend_qtc_plugin(QmlDesigner
collectiondetailssortfiltermodel.cpp collectiondetailssortfiltermodel.h
collectioneditorconstants.h
collectioneditorutils.cpp collectioneditorutils.h
- collectionimporttools.cpp collectionimporttools.h
collectionlistmodel.cpp collectionlistmodel.h
collectionsourcemodel.cpp collectionsourcemodel.h
collectionview.cpp collectionview.h
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectiondetails.cpp b/src/plugins/qmldesigner/components/collectioneditor/collectiondetails.cpp
index 4cc6717d91..90f0061c87 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectiondetails.cpp
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectiondetails.cpp
@@ -28,7 +28,7 @@ const QMap<DataTypeWarning::Warning, QString> DataTypeWarning::dataTypeWarnings
class CollectionDetails::Private
{
- using SourceFormat = CollectionEditor::SourceFormat;
+ using SourceFormat = CollectionEditorConstants::SourceFormat;
public:
QList<CollectionProperty> properties;
@@ -85,6 +85,24 @@ static QVariant valueToVariant(const QJsonValue &value, CollectionDetails::DataT
}
}
+static QJsonValue variantToJsonValue(const QVariant &variant)
+{
+ using VariantType = QVariant::Type;
+
+ switch (variant.type()) {
+ case VariantType::Bool:
+ return variant.toBool();
+ case VariantType::Double:
+ case VariantType::Int:
+ return variant.toDouble();
+ case VariantType::String:
+ case VariantType::Color:
+ case VariantType::Url:
+ default:
+ return variant.toString();
+ }
+}
+
CollectionDetails::CollectionDetails()
: d(new Private())
{}
@@ -101,7 +119,7 @@ CollectionDetails::~CollectionDetails() = default;
void CollectionDetails::resetDetails(const QStringList &propertyNames,
const QList<QJsonObject> &elements,
- CollectionEditor::SourceFormat format)
+ CollectionEditorConstants::SourceFormat format)
{
if (!isValid())
return;
@@ -238,6 +256,7 @@ bool CollectionDetails::setPropertyValue(int row, int column, const QVariant &va
return false;
element.insert(d->properties.at(column).name, QJsonValue::fromVariant(value));
+ markChanged();
return true;
}
@@ -277,8 +296,10 @@ bool CollectionDetails::setPropertyType(int column, DataType type)
for (QJsonObject &element : d->elements) {
if (element.contains(property.name)) {
- QJsonValue value = element.value(property.name);
- element.insert(property.name, valueToVariant(value, type).toJsonValue());
+ const QJsonValue value = element.value(property.name);
+ const QVariant properTypedValue = valueToVariant(value, type);
+ const QJsonValue properTypedJsonValue = variantToJsonValue(properTypedValue);
+ element.insert(property.name, properTypedJsonValue);
changed = true;
}
}
@@ -294,7 +315,7 @@ CollectionReference CollectionDetails::reference() const
return d->reference;
}
-CollectionEditor::SourceFormat CollectionDetails::sourceFormat() const
+CollectionEditorConstants::SourceFormat CollectionDetails::sourceFormat() const
{
return d->sourceFormat;
}
@@ -354,8 +375,10 @@ DataTypeWarning::Warning CollectionDetails::cellWarningCheck(int row, int column
const QString &propertyName = d->properties.at(column).name;
const QJsonObject &element = d->elements.at(row);
- if (element.isEmpty())
+ if (typeAt(column) == DataType::Unknown || element.isEmpty()
+ || data(row, column) == QVariant::fromValue(nullptr)) {
return DataTypeWarning::Warning::None;
+ }
if (element.contains(propertyName) && typeAt(column) != typeAt(row, column))
return DataTypeWarning::Warning::CellDataTypeMismatch;
@@ -458,16 +481,19 @@ void CollectionDetails::resetPropertyTypes()
resetPropertyType(property);
}
-QString CollectionDetails::getCollectionAsJsonString() const
+QJsonArray CollectionDetails::getCollectionAsJsonArray() const
{
QJsonArray collectionArray;
for (const QJsonObject &element : std::as_const(d->elements))
collectionArray.push_back(element);
- QString collectionString = QString::fromUtf8(QJsonDocument(collectionArray).toJson());
+ return collectionArray;
+}
- return collectionString;
+QString CollectionDetails::getCollectionAsJsonString() const
+{
+ return QString::fromUtf8(QJsonDocument(getCollectionAsJsonArray()).toJson());
}
QString CollectionDetails::getCollectionAsCsvString() const
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectiondetails.h b/src/plugins/qmldesigner/components/collectioneditor/collectiondetails.h
index c35068ce6f..9d8eb7eca0 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectiondetails.h
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectiondetails.h
@@ -70,7 +70,7 @@ public:
void resetDetails(const QStringList &propertyNames,
const QList<QJsonObject> &elements,
- CollectionEditor::SourceFormat format);
+ CollectionEditorConstants::SourceFormat format);
void insertColumn(const QString &propertyName,
int colIdx = -1,
const QVariant &defaultValue = {},
@@ -86,7 +86,7 @@ public:
bool setPropertyType(int column, DataType type);
CollectionReference reference() const;
- CollectionEditor::SourceFormat sourceFormat() const;
+ CollectionEditorConstants::SourceFormat sourceFormat() const;
QVariant data(int row, int column) const;
QString propertyAt(int column) const;
DataType typeAt(int column) const;
@@ -106,6 +106,8 @@ public:
QString getCollectionAsJsonString() const;
QString getCollectionAsCsvString() const;
+ QJsonArray getCollectionAsJsonArray() const;
+
static void registerDeclarativeType();
CollectionDetails &operator=(const CollectionDetails &other);
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectiondetailsmodel.cpp b/src/plugins/qmldesigner/components/collectioneditor/collectiondetailsmodel.cpp
index 2279b60d13..52d5a6e2ba 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectiondetailsmodel.cpp
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectiondetailsmodel.cpp
@@ -7,11 +7,16 @@
#include "collectioneditorutils.h"
#include "modelnode.h"
+#include <coreplugin/editormanager/editormanager.h>
+
+#include <utils/fileutils.h>
#include <utils/qtcassert.h>
+#include <utils/textfileformat.h>
#include <QFile>
#include <QFileInfo>
#include <QJsonArray>
+#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonParseError>
@@ -19,17 +24,27 @@ namespace {
QStringList getJsonHeaders(const QJsonArray &collectionArray)
{
- QSet<QString> result;
+ QSet<QString> resultSet;
+ QList<QString> result;
+
for (const QJsonValue &value : collectionArray) {
if (value.isObject()) {
const QJsonObject object = value.toObject();
- const QStringList headers = object.toVariantMap().keys();
- for (const QString &header : headers)
- result.insert(header);
+ QJsonObject::ConstIterator element = object.constBegin();
+ const QJsonObject::ConstIterator stopItem = object.constEnd();
+
+ while (element != stopItem) {
+ const QString property = element.key();
+ if (!resultSet.contains(property)) {
+ result.append(property);
+ resultSet.insert(property);
+ }
+ ++element;
+ }
}
}
- return result.values();
+ return result;
}
class CollectionDataTypeHelper
@@ -339,8 +354,10 @@ bool CollectionDetailsModel::setPropertyType(int column, const QString &newValue
newValue));
if (changed) {
emit headerDataChanged(Qt::Horizontal, column, column);
- emit dataChanged(index(0, column), index(rowCount() - 1, column),
- {Qt::DisplayRole, DataTypeRole, DataTypeWarningRole});
+ emit dataChanged(
+ index(0, column),
+ index(rowCount() - 1, column),
+ {Qt::DisplayRole, Qt::EditRole, DataTypeRole, DataTypeWarningRole, ColumnDataTypeRole});
}
return changed;
@@ -353,8 +370,8 @@ bool CollectionDetailsModel::selectRow(int row)
const int rows = rowCount();
- if (m_selectedRow >= rows)
- return false;
+ if (row >= rows)
+ row = rows - 1;
selectColumn(-1);
@@ -388,7 +405,7 @@ QStringList CollectionDetailsModel::typesList()
void CollectionDetailsModel::loadCollection(const ModelNode &sourceNode, const QString &collection)
{
- QString fileName = CollectionEditor::getSourceCollectionPath(sourceNode);
+ QString fileName = CollectionEditorUtils::getSourceCollectionPath(sourceNode);
CollectionReference newReference{sourceNode, collection};
bool alreadyOpen = m_openedCollections.contains(newReference);
@@ -403,21 +420,83 @@ void CollectionDetailsModel::loadCollection(const ModelNode &sourceNode, const Q
} else {
deselectAll();
switchToCollection(newReference);
- if (sourceNode.type() == CollectionEditor::JSONCOLLECTIONMODEL_TYPENAME)
+ if (sourceNode.type() == CollectionEditorConstants::JSONCOLLECTIONMODEL_TYPENAME)
loadJsonCollection(fileName, collection);
- else if (sourceNode.type() == CollectionEditor::CSVCOLLECTIONMODEL_TYPENAME)
+ else if (sourceNode.type() == CollectionEditorConstants::CSVCOLLECTIONMODEL_TYPENAME)
loadCsvCollection(fileName, collection);
}
}
-bool CollectionDetailsModel::saveCurrentCollection()
+bool CollectionDetailsModel::saveDataStoreCollections()
{
- return saveCollection({}, &m_currentCollection);
+ const ModelNode node = m_currentCollection.reference().node;
+ const Utils::FilePath path = CollectionEditorUtils::dataStoreJsonFilePath();
+ Utils::FileReader fileData;
+ Utils::FileSaver sourceFile(path);
+
+ if (!fileData.fetch(path)) {
+ qWarning() << Q_FUNC_INFO << "Cannot read the json file:" << fileData.errorString();
+ return false;
+ }
+
+ QJsonParseError jpe;
+ QJsonDocument document = QJsonDocument::fromJson(fileData.data(), &jpe);
+
+ if (jpe.error == QJsonParseError::NoError) {
+ QJsonObject obj = document.object();
+
+ QList<CollectionDetails> collectionsToBeSaved;
+ for (CollectionDetails &openedCollection : m_openedCollections) {
+ const CollectionReference reference = openedCollection.reference();
+ if (reference.node == node) {
+ obj.insert(reference.name, openedCollection.getCollectionAsJsonArray());
+ collectionsToBeSaved << openedCollection;
+ }
+ }
+
+ document.setObject(obj);
+ bool saved = sourceFile.write(document.toJson());
+ saved &= sourceFile.finalize();
+
+ if (saved) {
+ const CollectionReference currentReference = m_currentCollection.reference();
+ for (CollectionDetails &collection : collectionsToBeSaved) {
+ collection.markSaved();
+ const CollectionReference reference = collection.reference();
+ if (reference != currentReference)
+ closeCollectionIfSaved(reference);
+ }
+ return true;
+ }
+ }
+ return false;
}
-bool CollectionDetailsModel::exportCollection(const QString &filePath)
+bool CollectionDetailsModel::exportCollection(const QUrl &url)
{
- return saveCollection(filePath, &m_currentCollection);
+ using Core::EditorManager;
+ using Utils::FilePath;
+ using Utils::TextFileFormat;
+
+ QTC_ASSERT(m_currentCollection.isValid(), return false);
+
+ bool saved = false;
+ const FilePath filePath = FilePath::fromUserInput(url.isLocalFile() ? url.toLocalFile()
+ : url.toString());
+ const QString saveFormat = filePath.toFileInfo().suffix().toLower();
+ const QString content = saveFormat == "csv" ? m_currentCollection.getCollectionAsCsvString()
+ : m_currentCollection.getCollectionAsJsonString();
+
+ TextFileFormat textFileFormat;
+ textFileFormat.codec = EditorManager::defaultTextCodec();
+ textFileFormat.lineTerminationMode = EditorManager::defaultLineEnding();
+ QString errorMessage;
+ saved = textFileFormat.writeFile(filePath, content, &errorMessage);
+
+ if (!saved)
+ qWarning() << Q_FUNC_INFO << "Unable to write file" << errorMessage;
+
+ return saved;
}
void CollectionDetailsModel::updateEmpty()
@@ -453,19 +532,19 @@ void CollectionDetailsModel::closeCollectionIfSaved(const CollectionReference &c
if (!collectionDetails.isChanged())
m_openedCollections.remove(collection);
-
- m_currentCollection = CollectionDetails{};
}
void CollectionDetailsModel::closeCurrentCollectionIfSaved()
{
- if (m_currentCollection.isValid())
+ if (m_currentCollection.isValid()) {
closeCollectionIfSaved(m_currentCollection.reference());
+ m_currentCollection = CollectionDetails{};
+ }
}
void CollectionDetailsModel::loadJsonCollection(const QString &source, const QString &collection)
{
- using CollectionEditor::SourceFormat;
+ using CollectionEditorConstants::SourceFormat;
QFile sourceFile(source);
QJsonArray collectionNodes;
@@ -510,7 +589,7 @@ void CollectionDetailsModel::loadJsonCollection(const QString &source, const QSt
void CollectionDetailsModel::loadCsvCollection(const QString &source,
[[maybe_unused]] const QString &collectionName)
{
- using CollectionEditor::SourceFormat;
+ using CollectionEditorConstants::SourceFormat;
QFile sourceFile(source);
QStringList headers;
@@ -594,49 +673,6 @@ void CollectionDetailsModel::setCollectionName(const QString &newCollectionName)
}
}
-bool CollectionDetailsModel::saveCollection(const QString &filePath, CollectionDetails *collection)
-{
- bool saved = false;
-
- auto saveSingleCollection = [&](CollectionDetails &singleCollection) {
-
- const ModelNode node = singleCollection.reference().node;
- QString path = CollectionEditor::getSourceCollectionPath(node);
- QString saveFormat = CollectionEditor::getSourceCollectionType(node);
-
- if (!filePath.isEmpty()) {
- QUrl url(filePath);
- path = url.isLocalFile() ? QFileInfo(url.toLocalFile()).absoluteFilePath() : url.toString();
- saveFormat = url.isLocalFile() ? QFileInfo(url.toLocalFile()).suffix().toLower() : saveFormat;
- }
-
- saved = saveCollectionFromString(path, (saveFormat == "json") ? singleCollection.getCollectionAsJsonString() :
- (saveFormat == "csv") ? singleCollection.getCollectionAsCsvString() : QString());
-
- if (saved && filePath.isEmpty())
- singleCollection.markSaved();
- };
-
- if (!collection) {
- for (CollectionDetails &openedCollection : m_openedCollections)
- saveSingleCollection(openedCollection);
- } else {
- saveSingleCollection(*collection);
- }
-
- return saved;
-}
-
-bool CollectionDetailsModel::saveCollectionFromString(const QString &path, const QString &content)
-{
- QFile file(path);
-
- if (file.open(QFile::WriteOnly) && file.write(content.toUtf8()))
- return true;
-
- return false;
-}
-
QString CollectionDetailsModel::warningToString(DataTypeWarning::Warning warning) const
{
return DataTypeWarning::getDataTypeWarningString(warning);
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectiondetailsmodel.h b/src/plugins/qmldesigner/components/collectioneditor/collectiondetailsmodel.h
index bf87d3838f..4fef84a3df 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectiondetailsmodel.h
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectiondetailsmodel.h
@@ -62,8 +62,8 @@ public:
void loadCollection(const ModelNode &sourceNode, const QString &collection);
- Q_INVOKABLE bool saveCurrentCollection();
- Q_INVOKABLE bool exportCollection(const QString &filePath);
+ Q_INVOKABLE bool saveDataStoreCollections();
+ Q_INVOKABLE bool exportCollection(const QUrl &url);
signals:
void collectionNameChanged(const QString &collectionName);
@@ -81,8 +81,6 @@ private:
void setCollectionName(const QString &newCollectionName);
void loadJsonCollection(const QString &source, const QString &collection);
void loadCsvCollection(const QString &source, const QString &collectionName);
- bool saveCollection(const QString &filePath = {}, CollectionDetails *collection = nullptr);
- bool saveCollectionFromString(const QString &path, const QString &content);
QVariant variantFromString(const QString &value);
QHash<CollectionReference, CollectionDetails> m_openedCollections;
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectiondetailssortfiltermodel.cpp b/src/plugins/qmldesigner/components/collectioneditor/collectiondetailssortfiltermodel.cpp
index 50fcadd494..f56bb36e88 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectiondetailssortfiltermodel.cpp
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectiondetailssortfiltermodel.cpp
@@ -80,7 +80,9 @@ bool CollectionDetailsSortFilterModel::lessThan(const QModelIndex &sourceleft,
if (sourceleft.column() == sourceRight.column()) {
int column = sourceleft.column();
CollectionDetails::DataType columnType = m_source->propertyDataType(column);
- return CollectionEditor::variantIslessThan(sourceleft.data(), sourceRight.data(), columnType);
+ return CollectionEditorUtils::variantIslessThan(sourceleft.data(),
+ sourceRight.data(),
+ columnType);
}
return false;
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectioneditorconstants.h b/src/plugins/qmldesigner/components/collectioneditor/collectioneditorconstants.h
index e914891de3..a591719d87 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectioneditorconstants.h
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectioneditorconstants.h
@@ -3,7 +3,7 @@
#pragma once
-namespace QmlDesigner::CollectionEditor {
+namespace QmlDesigner::CollectionEditorConstants {
enum class SourceFormat { Unknown, Json, Csv };
@@ -17,4 +17,4 @@ inline constexpr char CSVCOLLECTIONMODEL_TYPENAME[] = "QtQuick.Studio.Ut
inline constexpr char JSONCOLLECTIONCHILDMODEL_TYPENAME[] = "QtQuick.Studio.Utils.ChildListModel";
inline constexpr char JSONBACKEND_TYPENAME[] = "JsonData";
-} // namespace QmlDesigner::CollectionEditor
+} // namespace QmlDesigner::CollectionEditorConstants
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.cpp b/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.cpp
index f48b6547ae..33867228d5 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.cpp
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.cpp
@@ -18,7 +18,10 @@
#include <QColor>
#include <QJsonArray>
+#include <QJsonDocument>
#include <QJsonObject>
+#include <QJsonParseError>
+#include <QJsonValue>
#include <QUrl>
namespace {
@@ -104,32 +107,32 @@ inline Utils::FilePath qmlDirFilePath()
} // namespace
-namespace QmlDesigner::CollectionEditor {
+namespace QmlDesigner::CollectionEditorUtils {
bool variantIslessThan(const QVariant &a, const QVariant &b, CollectionDetails::DataType type)
{
return std::visit(LessThanVisitor{}, valueToVariant(a, type), valueToVariant(b, type));
}
-SourceFormat getSourceCollectionFormat(const ModelNode &node)
+CollectionEditorConstants::SourceFormat getSourceCollectionFormat(const ModelNode &node)
{
using namespace QmlDesigner;
- if (node.type() == CollectionEditor::JSONCOLLECTIONMODEL_TYPENAME)
- return CollectionEditor::SourceFormat::Json;
+ if (node.type() == CollectionEditorConstants::JSONCOLLECTIONMODEL_TYPENAME)
+ return CollectionEditorConstants::SourceFormat::Json;
- if (node.type() == CollectionEditor::CSVCOLLECTIONMODEL_TYPENAME)
- return CollectionEditor::SourceFormat::Csv;
+ if (node.type() == CollectionEditorConstants::CSVCOLLECTIONMODEL_TYPENAME)
+ return CollectionEditorConstants::SourceFormat::Csv;
- return CollectionEditor::SourceFormat::Unknown;
+ return CollectionEditorConstants::SourceFormat::Unknown;
}
QString getSourceCollectionType(const ModelNode &node)
{
using namespace QmlDesigner;
- if (node.type() == CollectionEditor::JSONCOLLECTIONMODEL_TYPENAME)
+ if (node.type() == CollectionEditorConstants::JSONCOLLECTIONMODEL_TYPENAME)
return "json";
- if (node.type() == CollectionEditor::CSVCOLLECTIONMODEL_TYPENAME)
+ if (node.type() == CollectionEditorConstants::CSVCOLLECTIONMODEL_TYPENAME)
return "csv";
return {};
@@ -159,6 +162,20 @@ bool canAcceptCollectionAsModel(const ModelNode &node)
&& modelProperty.propertyType().isVariant();
}
+bool hasTextRoleProperty(const ModelNode &node)
+{
+ const NodeMetaInfo nodeMetaInfo = node.metaInfo();
+ if (!nodeMetaInfo.isValid())
+ return false;
+
+ const PropertyMetaInfo textRoleProperty = nodeMetaInfo.property("textRole");
+ if (!textRoleProperty.isValid())
+ return false;
+
+ return textRoleProperty.isWritable() && !textRoleProperty.isPrivate()
+ && textRoleProperty.propertyType().isString();
+}
+
QString getSourceCollectionPath(const ModelNode &dataStoreNode)
{
using Utils::FilePath;
@@ -280,4 +297,178 @@ bool ensureDataStoreExists(bool &justCreated)
return false;
}
-} // namespace QmlDesigner::CollectionEditor
+QJsonArray loadAsSingleJsonCollection(const QUrl &url)
+{
+ QFile file(url.isLocalFile() ? url.toLocalFile() : url.toString());
+ QJsonArray collection;
+ QByteArray jsonData;
+ if (file.open(QFile::ReadOnly))
+ jsonData = file.readAll();
+
+ file.close();
+ if (jsonData.isEmpty())
+ return {};
+
+ QJsonParseError parseError;
+ QJsonDocument document = QJsonDocument::fromJson(jsonData, &parseError);
+ if (parseError.error != QJsonParseError::NoError)
+ return {};
+
+ auto refineJsonArray = [](const QJsonArray &array) -> QJsonArray {
+ QJsonArray resultArray;
+ for (const QJsonValue &collectionData : array) {
+ if (collectionData.isObject()) {
+ QJsonObject rowObject = collectionData.toObject();
+ const QStringList rowKeys = rowObject.keys();
+ for (const QString &key : rowKeys) {
+ QJsonValue cellValue = rowObject.value(key);
+ if (cellValue.isArray())
+ rowObject.remove(key);
+ }
+ resultArray.push_back(rowObject);
+ }
+ }
+ return resultArray;
+ };
+
+ if (document.isArray()) {
+ collection = refineJsonArray(document.array());
+ } else if (document.isObject()) {
+ QJsonObject documentObject = document.object();
+ const QStringList mainKeys = documentObject.keys();
+
+ bool arrayFound = false;
+ for (const QString &key : mainKeys) {
+ const QJsonValue &value = documentObject.value(key);
+ if (value.isArray()) {
+ arrayFound = true;
+ collection = refineJsonArray(value.toArray());
+ break;
+ }
+ }
+
+ if (!arrayFound) {
+ QJsonObject singleObject;
+ for (const QString &key : mainKeys) {
+ const QJsonValue value = documentObject.value(key);
+
+ if (!value.isObject())
+ singleObject.insert(key, value);
+ }
+ collection.push_back(singleObject);
+ }
+ }
+ return collection;
+}
+
+QJsonArray loadAsCsvCollection(const QUrl &url)
+{
+ QFile sourceFile(url.isLocalFile() ? url.toLocalFile() : url.toString());
+ QStringList headers;
+ QJsonArray elements;
+
+ if (sourceFile.open(QFile::ReadOnly)) {
+ QTextStream stream(&sourceFile);
+
+ if (!stream.atEnd())
+ headers = stream.readLine().split(',');
+
+ for (QString &header : headers)
+ header = header.trimmed();
+
+ if (!headers.isEmpty()) {
+ while (!stream.atEnd()) {
+ const QStringList recordDataList = stream.readLine().split(',');
+ int column = -1;
+ QJsonObject recordData;
+ for (const QString &cellData : recordDataList) {
+ if (++column == headers.size())
+ break;
+ recordData.insert(headers.at(column), cellData);
+ }
+ elements.append(recordData);
+ }
+ }
+ }
+
+ return elements;
+}
+
+QString getFirstColumnName(const QString &collectionName)
+{
+ Utils::FilePath dataStorePath = CollectionEditorUtils::dataStoreJsonFilePath();
+
+ if (!dataStorePath.exists())
+ return {};
+
+ Utils::FileReader dataStoreFile;
+ if (!dataStoreFile.fetch(dataStorePath))
+ return {};
+
+ QJsonParseError jsonError;
+ QJsonDocument dataStoreDocument = QJsonDocument::fromJson(dataStoreFile.data(), &jsonError);
+ if (jsonError.error == QJsonParseError::NoError) {
+ QJsonObject rootObject = dataStoreDocument.object();
+ if (rootObject.contains(collectionName)) {
+ QJsonArray collectionArray = rootObject.value(collectionName).toArray();
+ for (const QJsonValue &elementValue : std::as_const(collectionArray)) {
+ const QJsonObject elementObject = elementValue.toObject();
+ QJsonObject::ConstIterator element = elementObject.constBegin();
+ if (element != elementObject.constEnd())
+ return element.key();
+ }
+ } else {
+ qWarning() << Q_FUNC_INFO << __LINE__
+ << QString("Collection \"%1\" not found.").arg(collectionName);
+ }
+ } else {
+ qWarning() << Q_FUNC_INFO << __LINE__ << "Problem in reading json file."
+ << jsonError.errorString();
+ }
+
+ return {};
+}
+
+bool collectionHasColumn(const QString &collectionName, const QString &columnName)
+{
+ Utils::FilePath dataStorePath = CollectionEditorUtils::dataStoreJsonFilePath();
+
+ if (!dataStorePath.exists())
+ return false;
+
+ Utils::FileReader dataStoreFile;
+ if (!dataStoreFile.fetch(dataStorePath))
+ return false;
+
+ QJsonParseError jsonError;
+ QJsonDocument dataStoreDocument = QJsonDocument::fromJson(dataStoreFile.data(), &jsonError);
+ if (jsonError.error == QJsonParseError::NoError) {
+ QJsonObject rootObject = dataStoreDocument.object();
+ if (rootObject.contains(collectionName)) {
+ QJsonArray collectionArray = rootObject.value(collectionName).toArray();
+ for (const QJsonValue &elementValue : std::as_const(collectionArray)) {
+ const QJsonObject elementObject = elementValue.toObject();
+ QJsonObject::ConstIterator element = elementObject.constBegin();
+ const QJsonObject::ConstIterator stopItem = elementObject.constEnd();
+
+ while (element != stopItem) {
+ const QString keyName = element.key();
+ ++element;
+
+ if (columnName == keyName)
+ return true;
+ }
+ }
+ } else {
+ qWarning() << Q_FUNC_INFO << __LINE__
+ << QString("Collection \"%1\" not found.").arg(collectionName);
+ }
+ } else {
+ qWarning() << Q_FUNC_INFO << __LINE__ << "Problem in reading json file."
+ << jsonError.errorString();
+ }
+
+ return false;
+}
+
+} // namespace QmlDesigner::CollectionEditorUtils
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.h b/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.h
index 036304a381..46429f04b6 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.h
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.h
@@ -14,11 +14,11 @@ namespace Utils {
class FilePath;
}
-namespace QmlDesigner::CollectionEditor {
+namespace QmlDesigner::CollectionEditorUtils {
bool variantIslessThan(const QVariant &a, const QVariant &b, CollectionDetails::DataType type);
-SourceFormat getSourceCollectionFormat(const QmlDesigner::ModelNode &node);
+CollectionEditorConstants::SourceFormat getSourceCollectionFormat(const QmlDesigner::ModelNode &node);
QString getSourceCollectionType(const QmlDesigner::ModelNode &node);
@@ -34,6 +34,16 @@ bool ensureDataStoreExists(bool &justCreated);
bool canAcceptCollectionAsModel(const ModelNode &node);
+bool hasTextRoleProperty(const ModelNode &node);
+
QJsonArray defaultCollectionArray();
-} // namespace QmlDesigner::CollectionEditor
+QJsonArray loadAsSingleJsonCollection(const QUrl &url);
+
+QJsonArray loadAsCsvCollection(const QUrl &url);
+
+QString getFirstColumnName(const QString &collectionName);
+
+bool collectionHasColumn(const QString &collectionName, const QString &columnName);
+
+} // namespace QmlDesigner::CollectionEditorUtils
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectionimporttools.cpp b/src/plugins/qmldesigner/components/collectioneditor/collectionimporttools.cpp
deleted file mode 100644
index 183730873d..0000000000
--- a/src/plugins/qmldesigner/components/collectioneditor/collectionimporttools.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-// 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 "collectionimporttools.h"
-
-#include <QFile>
-#include <QJsonArray>
-#include <QJsonDocument>
-#include <QJsonObject>
-#include <QJsonParseError>
-#include <QJsonValue>
-#include <QUrl>
-
-namespace QmlDesigner::CollectionEditor::ImportTools {
-
-QJsonArray loadAsSingleJsonCollection(const QUrl &url)
-{
- QFile file(url.isLocalFile() ? url.toLocalFile() : url.toString());
- QJsonArray collection;
- QByteArray jsonData;
- if (file.open(QFile::ReadOnly))
- jsonData = file.readAll();
-
- file.close();
- if (jsonData.isEmpty())
- return {};
-
- QJsonParseError parseError;
- QJsonDocument document = QJsonDocument::fromJson(jsonData, &parseError);
- if (parseError.error != QJsonParseError::NoError)
- return {};
-
- auto refineJsonArray = [](const QJsonArray &array) -> QJsonArray {
- QJsonArray resultArray;
- for (const QJsonValue &collectionData : array) {
- if (collectionData.isObject()) {
- QJsonObject rowObject = collectionData.toObject();
- const QStringList rowKeys = rowObject.keys();
- for (const QString &key : rowKeys) {
- QJsonValue cellValue = rowObject.value(key);
- if (cellValue.isArray())
- rowObject.remove(key);
- }
- resultArray.push_back(rowObject);
- }
- }
- return resultArray;
- };
-
- if (document.isArray()) {
- collection = refineJsonArray(document.array());
- } else if (document.isObject()) {
- QJsonObject documentObject = document.object();
- const QStringList mainKeys = documentObject.keys();
-
- bool arrayFound = false;
- for (const QString &key : mainKeys) {
- const QJsonValue &value = documentObject.value(key);
- if (value.isArray()) {
- arrayFound = true;
- collection = refineJsonArray(value.toArray());
- break;
- }
- }
-
- if (!arrayFound) {
- QJsonObject singleObject;
- for (const QString &key : mainKeys) {
- const QJsonValue value = documentObject.value(key);
-
- if (!value.isObject())
- singleObject.insert(key, value);
- }
- collection.push_back(singleObject);
- }
- }
- return collection;
-}
-
-QJsonArray loadAsCsvCollection(const QUrl &url)
-{
- QFile sourceFile(url.isLocalFile() ? url.toLocalFile() : url.toString());
- QStringList headers;
- QJsonArray elements;
-
- if (sourceFile.open(QFile::ReadOnly)) {
- QTextStream stream(&sourceFile);
-
- if (!stream.atEnd())
- headers = stream.readLine().split(',');
-
- for (QString &header : headers)
- header = header.trimmed();
-
- if (!headers.isEmpty()) {
- while (!stream.atEnd()) {
- const QStringList recordDataList = stream.readLine().split(',');
- int column = -1;
- QJsonObject recordData;
- for (const QString &cellData : recordDataList) {
- if (++column == headers.size())
- break;
- recordData.insert(headers.at(column), cellData);
- }
- elements.append(recordData);
- }
- }
- }
-
- return elements;
-}
-
-} // namespace QmlDesigner::CollectionEditor::ImportTools
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectionimporttools.h b/src/plugins/qmldesigner/components/collectioneditor/collectionimporttools.h
deleted file mode 100644
index 6ee4f590f7..0000000000
--- a/src/plugins/qmldesigner/components/collectioneditor/collectionimporttools.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// 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 <QtCore/qtconfigmacros.h>
-
-QT_BEGIN_NAMESPACE
-class QJsonArray;
-class QUrl;
-QT_END_NAMESPACE
-
-namespace QmlDesigner::CollectionEditor::ImportTools {
-
-QJsonArray loadAsSingleJsonCollection(const QUrl &url);
-QJsonArray loadAsCsvCollection(const QUrl &url);
-
-} // namespace QmlDesigner::CollectionEditor::ImportTools
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectionlistmodel.cpp b/src/plugins/qmldesigner/components/collectioneditor/collectionlistmodel.cpp
index d910569f0d..214ece078a 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectionlistmodel.cpp
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectionlistmodel.cpp
@@ -29,7 +29,7 @@ namespace QmlDesigner {
CollectionListModel::CollectionListModel(const ModelNode &sourceModel)
: QStringListModel()
, m_sourceNode(sourceModel)
- , m_sourceType(CollectionEditor::getSourceCollectionType(sourceModel))
+ , m_sourceType(CollectionEditorUtils::getSourceCollectionType(sourceModel))
{
connect(this, &CollectionListModel::modelReset, this, &CollectionListModel::updateEmpty);
connect(this, &CollectionListModel::rowsRemoved, this, &CollectionListModel::updateEmpty);
@@ -87,8 +87,11 @@ bool CollectionListModel::removeRows(int row, int count, const QModelIndex &pare
QStringList removedCollections = stringList().mid(row, count);
bool itemsRemoved = Super::removeRows(row, count, parent);
- if (itemsRemoved)
+ if (itemsRemoved) {
emit collectionsRemoved(removedCollections);
+ if (m_selectedIndex >= row)
+ selectCollectionIndex(m_selectedIndex - count, true);
+ }
return itemsRemoved;
}
@@ -121,7 +124,7 @@ ModelNode CollectionListModel::sourceNode() const
QString CollectionListModel::sourceAddress() const
{
- return CollectionEditor::getSourceCollectionPath(m_sourceNode);
+ return CollectionEditorUtils::getSourceCollectionPath(m_sourceNode);
}
bool CollectionListModel::contains(const QString &collectionName) const
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectionsourcemodel.cpp b/src/plugins/qmldesigner/components/collectioneditor/collectionsourcemodel.cpp
index 0c57f18778..1f9c7aa5d7 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectionsourcemodel.cpp
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectionsourcemodel.cpp
@@ -25,7 +25,8 @@ QSharedPointer<QmlDesigner::CollectionListModel> loadCollection(
const QmlDesigner::ModelNode &sourceNode,
QSharedPointer<QmlDesigner::CollectionListModel> initialCollection = {})
{
- using namespace QmlDesigner::CollectionEditor;
+ using namespace QmlDesigner::CollectionEditorConstants;
+ using namespace QmlDesigner::CollectionEditorUtils;
QString sourceFileAddress = getSourceCollectionPath(sourceNode);
QSharedPointer<QmlDesigner::CollectionListModel> collectionsList;
@@ -88,9 +89,9 @@ QVariant CollectionSourceModel::data(const QModelIndex &index, int role) const
case NodeRole:
return QVariant::fromValue(*collectionSource);
case CollectionTypeRole:
- return CollectionEditor::getSourceCollectionType(*collectionSource);
+ return CollectionEditorUtils::getSourceCollectionType(*collectionSource);
case SourceRole:
- return collectionSource->variantProperty(CollectionEditor::SOURCEFILE_PROPERTY).value();
+ return collectionSource->variantProperty(CollectionEditorConstants::SOURCEFILE_PROPERTY).value();
case SelectedRole:
return index.row() == m_selectedIndex;
case CollectionsRole:
@@ -116,7 +117,8 @@ bool CollectionSourceModel::setData(const QModelIndex &index, const QVariant &va
collectionName.setValue(value.toString());
} break;
case SourceRole: {
- auto sourceAddress = collectionSource.variantProperty(CollectionEditor::SOURCEFILE_PROPERTY);
+ auto sourceAddress = collectionSource.variantProperty(
+ CollectionEditorConstants::SOURCEFILE_PROPERTY);
if (sourceAddress.value() == value)
return false;
@@ -281,13 +283,13 @@ bool CollectionSourceModel::addCollectionToSource(const ModelNode &node,
if (idx < 0)
return returnError(tr("Node is not indexed in the models."));
- if (node.type() != CollectionEditor::JSONCOLLECTIONMODEL_TYPENAME)
+ if (node.type() != CollectionEditorConstants::JSONCOLLECTIONMODEL_TYPENAME)
return returnError(tr("Node should be a JSON model."));
if (collectionExists(node, collectionName))
return returnError(tr("A model with the identical name already exists."));
- QString sourceFileAddress = CollectionEditor::getSourceCollectionPath(node);
+ QString sourceFileAddress = CollectionEditorUtils::getSourceCollectionPath(node);
QFileInfo sourceFileInfo(sourceFileAddress);
if (!sourceFileInfo.isFile())
@@ -325,6 +327,7 @@ bool CollectionSourceModel::addCollectionToSource(const ModelNode &node,
return returnError(tr("No model is available for the JSON model group."));
collections->selectCollectionName(collectionName);
+ setSelectedCollectionName(collectionName);
return true;
} else {
return returnError(tr("JSON document type should be an object containing models."));
@@ -403,9 +406,11 @@ void CollectionSourceModel::onSelectedCollectionChanged(CollectionListModel *col
m_previousSelectedList = collectionList;
- emit collectionSelected(collectionList->collectionNameAt(collectionIndex));
+ setSelectedCollectionName(collectionList->collectionNameAt(collectionIndex));
selectSourceIndex(sourceIndex(collectionList->sourceNode()));
+ } else {
+ setSelectedCollectionName({});
}
}
@@ -413,7 +418,7 @@ void CollectionSourceModel::onCollectionNameChanged(CollectionListModel *collect
const QString &oldName, const QString &newName)
{
auto emitRenameWarning = [this](const QString &msg) -> void {
- emit this->warning(tr("Rename Model"), msg);
+ emit warning(tr("Rename Model"), msg);
};
const ModelNode node = collectionList->sourceNode();
@@ -424,16 +429,16 @@ void CollectionSourceModel::onCollectionNameChanged(CollectionListModel *collect
return;
}
- if (node.type() == CollectionEditor::CSVCOLLECTIONMODEL_TYPENAME) {
+ if (node.type() == CollectionEditorConstants::CSVCOLLECTIONMODEL_TYPENAME) {
if (!setData(nodeIndex, newName, NameRole))
emitRenameWarning(tr("Can't rename the node"));
return;
- } else if (node.type() != CollectionEditor::JSONCOLLECTIONMODEL_TYPENAME) {
+ } else if (node.type() != CollectionEditorConstants::JSONCOLLECTIONMODEL_TYPENAME) {
emitRenameWarning(tr("Invalid node type"));
return;
}
- QString sourceFileAddress = CollectionEditor::getSourceCollectionPath(node);
+ QString sourceFileAddress = CollectionEditorUtils::getSourceCollectionPath(node);
QFileInfo sourceFileInfo(sourceFileAddress);
if (!sourceFileInfo.isFile()) {
@@ -513,15 +518,15 @@ void CollectionSourceModel::onCollectionsRemoved(CollectionListModel *collection
return;
}
- if (node.type() == CollectionEditor::CSVCOLLECTIONMODEL_TYPENAME) {
+ if (node.type() == CollectionEditorConstants::CSVCOLLECTIONMODEL_TYPENAME) {
removeSource(node);
return;
- } else if (node.type() != CollectionEditor::JSONCOLLECTIONMODEL_TYPENAME) {
+ } else if (node.type() != CollectionEditorConstants::JSONCOLLECTIONMODEL_TYPENAME) {
emitDeleteWarning(tr("Invalid node type"));
return;
}
- QString sourceFileAddress = CollectionEditor::getSourceCollectionPath(node);
+ QString sourceFileAddress = CollectionEditorUtils::getSourceCollectionPath(node);
QFileInfo sourceFileInfo(sourceFileAddress);
if (!sourceFileInfo.isFile()) {
@@ -575,9 +580,11 @@ void CollectionSourceModel::onCollectionsRemoved(CollectionListModel *collection
}
for (const QString &collectionName : std::as_const(collectionsRemovedFromDocument))
- emit this->collectionRemoved(collectionName);
+ emit collectionRemoved(collectionName);
updateCollectionList(nodeIndex);
+ if (m_previousSelectedList == collectionList)
+ onSelectedCollectionChanged(collectionList, collectionList->selectedIndex());
}
}
@@ -607,12 +614,20 @@ void CollectionSourceModel::setSelectedIndex(int idx)
} else if (m_previousSelectedList) {
m_previousSelectedList->selectCollectionIndex(-1);
m_previousSelectedList = {};
- emit this->collectionSelected({});
+ setSelectedCollectionName({});
}
}
}
}
+void CollectionSourceModel::setSelectedCollectionName(const QString &collectionName)
+{
+ if (m_selectedCollectionName != collectionName) {
+ m_selectedCollectionName = collectionName;
+ emit collectionSelected(m_selectedCollectionName);
+ }
+}
+
void CollectionSourceModel::updateEmpty()
{
bool isEmptyNow = m_collectionSources.isEmpty();
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectionsourcemodel.h b/src/plugins/qmldesigner/components/collectioneditor/collectionsourcemodel.h
index 487b616b97..5ab77f2a98 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectionsourcemodel.h
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectionsourcemodel.h
@@ -87,6 +87,7 @@ private slots:
private:
void setSelectedIndex(int idx);
+ void setSelectedCollectionName(const QString &collectionName);
void updateEmpty();
void updateCollectionList(QModelIndex index);
void registerCollection(const QSharedPointer<CollectionListModel> &collection);
@@ -98,6 +99,7 @@ private:
QHash<qint32, int> m_sourceIndexHash; // internalId -> index
QList<QSharedPointer<CollectionListModel>> m_collectionList;
QPointer<CollectionListModel> m_previousSelectedList;
+ QString m_selectedCollectionName;
int m_selectedIndex = -1;
bool m_isEmpty = true;
};
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectionview.cpp b/src/plugins/qmldesigner/components/collectioneditor/collectionview.cpp
index f17abf5d9f..7f3ee7192a 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectionview.cpp
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectionview.cpp
@@ -31,7 +31,7 @@ namespace {
inline bool isStudioCollectionModel(const QmlDesigner::ModelNode &node)
{
- using namespace QmlDesigner::CollectionEditor;
+ using namespace QmlDesigner::CollectionEditorConstants;
return node.metaInfo().typeName() == JSONCOLLECTIONMODEL_TYPENAME
|| node.metaInfo().typeName() == CSVCOLLECTIONMODEL_TYPENAME;
}
@@ -151,7 +151,7 @@ void CollectionView::variantPropertiesChanged(const QList<VariantProperty> &prop
if (isStudioCollectionModel(node)) {
if (property.name() == "objectName")
m_widget->sourceModel()->updateNodeName(node);
- else if (property.name() == CollectionEditor::SOURCEFILE_PROPERTY)
+ else if (property.name() == CollectionEditorConstants::SOURCEFILE_PROPERTY)
m_widget->sourceModel()->updateNodeSource(node);
}
}
@@ -169,7 +169,8 @@ void CollectionView::selectedNodesChanged(const QList<ModelNode> &selectedNodeLi
bool singleSelectedHasModelProperty = false;
if (singleNonCollectionNodeSelected) {
const ModelNode selectedNode = selectedNodeList.first();
- singleSelectedHasModelProperty = CollectionEditor::canAcceptCollectionAsModel(selectedNode);
+ singleSelectedHasModelProperty = CollectionEditorUtils::canAcceptCollectionAsModel(
+ selectedNode);
}
m_widget->setTargetNodeSelected(singleSelectedHasModelProperty);
@@ -204,7 +205,7 @@ void CollectionView::addResource(const QUrl &url, const QString &name, const QSt
resourceMetaInfo.majorVersion(),
resourceMetaInfo.minorVersion());
VariantProperty sourceProperty = resourceNode.variantProperty(
- CollectionEditor::SOURCEFILE_PROPERTY);
+ CollectionEditorConstants::SOURCEFILE_PROPERTY);
VariantProperty nameProperty = resourceNode.variantProperty("objectName");
sourceProperty.setValue(sourceAddress);
nameProperty.setValue(name);
@@ -252,18 +253,18 @@ void CollectionView::refreshModel()
NodeMetaInfo CollectionView::jsonCollectionMetaInfo() const
{
- return model()->metaInfo(CollectionEditor::JSONCOLLECTIONMODEL_TYPENAME);
+ return model()->metaInfo(CollectionEditorConstants::JSONCOLLECTIONMODEL_TYPENAME);
}
NodeMetaInfo CollectionView::csvCollectionMetaInfo() const
{
- return model()->metaInfo(CollectionEditor::CSVCOLLECTIONMODEL_TYPENAME);
+ return model()->metaInfo(CollectionEditorConstants::CSVCOLLECTIONMODEL_TYPENAME);
}
void CollectionView::ensureStudioModelImport()
{
executeInTransaction(__FUNCTION__, [&] {
- Import import = Import::createLibraryImport(CollectionEditor::COLLECTIONMODEL_IMPORT);
+ Import import = Import::createLibraryImport(CollectionEditorConstants::COLLECTIONMODEL_IMPORT);
try {
if (!model()->hasImport(import, true, true))
model()->changeImports({import}, {});
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.cpp b/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.cpp
index 9b14c2cd03..39097cbeb3 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.cpp
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.cpp
@@ -6,7 +6,6 @@
#include "collectiondetailsmodel.h"
#include "collectiondetailssortfiltermodel.h"
#include "collectioneditorutils.h"
-#include "collectionimporttools.h"
#include "collectionsourcemodel.h"
#include "collectionview.h"
#include "qmldesignerconstants.h"
@@ -216,7 +215,7 @@ bool CollectionWidget::addCollection(const QString &collectionName,
if (collectionType == "json") {
QJsonObject jsonObject;
- jsonObject.insert(collectionName, CollectionEditor::defaultCollectionArray());
+ jsonObject.insert(collectionName, CollectionEditorUtils::defaultCollectionArray());
QFile sourceFile(sourcePath);
if (!sourceFile.open(QFile::WriteOnly)) {
@@ -258,10 +257,8 @@ bool CollectionWidget::addCollection(const QString &collectionName,
}
} else if (collectionType == "json") {
QString errorMsg;
- bool added = m_sourceModel->addCollectionToSource(node,
- collectionName,
- CollectionEditor::defaultCollectionArray(),
- &errorMsg);
+ bool added = m_sourceModel->addCollectionToSource(
+ node, collectionName, CollectionEditorUtils::defaultCollectionArray(), &errorMsg);
if (!added)
warn(tr("Can not add a model to the JSON file"), errorMsg);
return added;
@@ -274,10 +271,10 @@ bool CollectionWidget::importToJson(const QVariant &sourceNode,
const QString &collectionName,
const QUrl &url)
{
- using CollectionEditor::SourceFormat;
+ using CollectionEditorConstants::SourceFormat;
using Utils::FilePath;
const ModelNode node = sourceNode.value<ModelNode>();
- const SourceFormat nodeFormat = CollectionEditor::getSourceCollectionFormat(node);
+ const SourceFormat nodeFormat = CollectionEditorUtils::getSourceCollectionFormat(node);
QTC_ASSERT(node.isValid() && nodeFormat == SourceFormat::Json, return false);
FilePath fileInfo = FilePath::fromUserInput(url.isLocalFile() ? url.toLocalFile()
@@ -287,9 +284,9 @@ bool CollectionWidget::importToJson(const QVariant &sourceNode,
QJsonArray loadedCollection;
if (fileInfo.suffix() == "json")
- loadedCollection = CollectionEditor::ImportTools::loadAsSingleJsonCollection(url);
+ loadedCollection = CollectionEditorUtils::loadAsSingleJsonCollection(url);
else if (fileInfo.suffix() == "csv")
- loadedCollection = CollectionEditor::ImportTools::loadAsCsvCollection(url);
+ loadedCollection = CollectionEditorUtils::loadAsCsvCollection(url);
if (!loadedCollection.isEmpty()) {
const QString newCollectionName = generateUniqueCollectionName(node, collectionName);
@@ -327,7 +324,7 @@ bool CollectionWidget::addCollectionToDataStore(const QString &collectionName)
bool added = m_sourceModel->addCollectionToSource(node,
generateUniqueCollectionName(node,
collectionName),
- CollectionEditor::defaultCollectionArray(),
+ CollectionEditorUtils::defaultCollectionArray(),
&errorMsg);
if (!added)
warn(tr("Failed to add a model to the default model group"), errorMsg);
@@ -343,7 +340,7 @@ void CollectionWidget::assignCollectionToSelectedNode(const QString collectionNa
void CollectionWidget::ensureDataStoreExists()
{
bool filesJustCreated = false;
- bool filesExist = CollectionEditor::ensureDataStoreExists(filesJustCreated);
+ bool filesExist = CollectionEditorUtils::ensureDataStoreExists(filesJustCreated);
if (filesExist && filesJustCreated)
m_view->resetDataStoreNode();
}
diff --git a/src/plugins/qmldesigner/components/collectioneditor/datastoremodelnode.cpp b/src/plugins/qmldesigner/components/collectioneditor/datastoremodelnode.cpp
index bebc60f1de..a1f82bbc65 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/datastoremodelnode.cpp
+++ b/src/plugins/qmldesigner/components/collectioneditor/datastoremodelnode.cpp
@@ -7,6 +7,10 @@
#include "collectioneditorconstants.h"
#include "collectioneditorutils.h"
#include "model/qmltextgenerator.h"
+#include "plaintexteditmodifier.h"
+#include "qmldesignerbase/qmldesignerbaseplugin.h"
+#include "qmldesignerexternaldependencies.h"
+#include "rewriterview.h"
#include <model.h>
#include <nodemetainfo.h>
@@ -23,20 +27,25 @@
#include <utils/fileutils.h>
#include <utils/qtcassert.h>
+#include <QPlainTextEdit>
#include <QRegularExpression>
#include <QRegularExpressionMatch>
+#include <QScopedPointer>
namespace {
+inline constexpr char CHILDLISTMODEL_TYPENAME[] = "ChildListModel";
+
QmlDesigner::PropertyNameList createNameList(const QmlDesigner::ModelNode &node)
{
using QmlDesigner::AbstractProperty;
using QmlDesigner::PropertyName;
using QmlDesigner::PropertyNameList;
- static PropertyNameList defaultsNodeProps = {"id",
- QmlDesigner::CollectionEditor::SOURCEFILE_PROPERTY,
- QmlDesigner::CollectionEditor::JSONCHILDMODELNAME_PROPERTY,
- "backend"};
+ static PropertyNameList defaultsNodeProps = {
+ "id",
+ QmlDesigner::CollectionEditorConstants::SOURCEFILE_PROPERTY,
+ QmlDesigner::CollectionEditorConstants::JSONCHILDMODELNAME_PROPERTY,
+ "backend"};
PropertyNameList dynamicPropertyNames = Utils::transform(
node.dynamicProperties(),
[](const AbstractProperty &property) -> PropertyName { return property.name(); });
@@ -49,8 +58,8 @@ QmlDesigner::PropertyNameList createNameList(const QmlDesigner::ModelNode &node)
bool isValidCollectionPropertyName(const QString &collectionId)
{
static const QmlDesigner::PropertyNameList reservedKeywords = {
- QmlDesigner::CollectionEditor::SOURCEFILE_PROPERTY,
- QmlDesigner::CollectionEditor::JSONBACKEND_TYPENAME,
+ QmlDesigner::CollectionEditorConstants::SOURCEFILE_PROPERTY,
+ QmlDesigner::CollectionEditorConstants::JSONBACKEND_TYPENAME,
"backend",
"models",
};
@@ -59,6 +68,58 @@ bool isValidCollectionPropertyName(const QString &collectionId)
&& !reservedKeywords.contains(collectionId.toLatin1());
}
+QMap<QString, QmlDesigner::PropertyName> getModelIdMap(const QmlDesigner::ModelNode &rootNode)
+{
+ using namespace QmlDesigner;
+ QMap<QString, PropertyName> modelNameForId;
+
+ const QList<AbstractProperty> propertyNames = rootNode.dynamicProperties();
+
+ for (const AbstractProperty &property : std::as_const(propertyNames)) {
+ if (!property.isNodeProperty())
+ continue;
+
+ NodeProperty nodeProperty = property.toNodeProperty();
+ if (!nodeProperty.hasDynamicTypeName(CHILDLISTMODEL_TYPENAME))
+ continue;
+
+ ModelNode childNode = nodeProperty.modelNode();
+ if (childNode.hasProperty(CollectionEditorConstants::JSONCHILDMODELNAME_PROPERTY)) {
+ QString modelName = childNode
+ .property(CollectionEditorConstants::JSONCHILDMODELNAME_PROPERTY)
+ .toVariantProperty()
+ .value()
+ .toString();
+
+ if (!modelName.isEmpty())
+ modelNameForId.insert(modelName, property.name());
+ }
+ }
+ return modelNameForId;
+}
+
+void setQmlContextToModel(QmlDesigner::Model *model, const QString &qmlContext)
+{
+ using namespace QmlDesigner;
+ Q_ASSERT(model);
+
+ QScopedPointer<QPlainTextEdit> textEdit(new QPlainTextEdit);
+ QScopedPointer<NotIndentingTextEditModifier> modifier(
+ new NotIndentingTextEditModifier(textEdit.data()));
+ textEdit->hide();
+ textEdit->setPlainText(qmlContext);
+ QmlDesigner::ExternalDependencies externalDependencies{QmlDesignerBasePlugin::settings()};
+ QScopedPointer<RewriterView> rewriter(
+ new RewriterView(externalDependencies, QmlDesigner::RewriterView::Validate));
+
+ rewriter->setParent(model);
+ rewriter->setTextModifier(modifier.get());
+ rewriter->setCheckSemanticErrors(false);
+
+ model->attachView(rewriter.get());
+ model->detachView(rewriter.get());
+}
+
} // namespace
namespace QmlDesigner {
@@ -77,15 +138,16 @@ void DataStoreModelNode::reloadModel()
}
bool forceUpdate = false;
- const FilePath dataStoreQmlPath = CollectionEditor::dataStoreQmlFilePath();
- const FilePath dataStoreJsonPath = CollectionEditor::dataStoreJsonFilePath();
+ const FilePath dataStoreQmlPath = CollectionEditorUtils::dataStoreQmlFilePath();
+ const FilePath dataStoreJsonPath = CollectionEditorUtils::dataStoreJsonFilePath();
QUrl dataStoreQmlUrl = dataStoreQmlPath.toUrl();
if (dataStoreQmlPath.exists() && dataStoreJsonPath.exists()) {
if (!m_model.get() || m_model->fileUrl() != dataStoreQmlUrl) {
- m_model = Model::create(CollectionEditor::JSONCOLLECTIONMODEL_TYPENAME, 1, 1);
+ m_model = Model::create(CollectionEditorConstants::JSONCOLLECTIONMODEL_TYPENAME, 1, 1);
forceUpdate = true;
- Import import = Import::createLibraryImport(CollectionEditor::COLLECTIONMODEL_IMPORT);
+ Import import = Import::createLibraryImport(
+ CollectionEditorConstants::COLLECTIONMODEL_IMPORT);
try {
if (!m_model->hasImport(import, true, true))
m_model->changeImports({import}, {});
@@ -102,8 +164,10 @@ void DataStoreModelNode::reloadModel()
m_dataRelativePath = dataStoreJsonPath.relativePathFrom(dataStoreQmlPath).toFSPathString();
- if (forceUpdate)
+ if (forceUpdate) {
+ preloadFile();
update();
+ }
}
QStringList DataStoreModelNode::collectionNames() const
@@ -143,6 +207,25 @@ void DataStoreModelNode::reset()
setCollectionNames({});
}
+void DataStoreModelNode::preloadFile()
+{
+ using Utils::FilePath;
+ using Utils::FileReader;
+
+ if (!m_model)
+ return;
+
+ const FilePath dataStoreQmlPath = dataStoreQmlFilePath();
+ FileReader dataStoreQmlFile;
+ QString sourceQmlContext;
+
+ if (dataStoreQmlFile.fetch(dataStoreQmlPath))
+ sourceQmlContext = QString::fromLatin1(dataStoreQmlFile.data());
+
+ setQmlContextToModel(m_model.get(), sourceQmlContext);
+ m_collectionPropertyNames = getModelIdMap(m_model->rootModelNode());
+}
+
void DataStoreModelNode::updateDataStoreProperties()
{
QTC_ASSERT(model(), return);
@@ -150,8 +233,6 @@ void DataStoreModelNode::updateDataStoreProperties()
ModelNode rootNode = modelNode();
QTC_ASSERT(rootNode.isValid(), return);
- static TypeName childNodeTypename = "ChildListModel";
-
QSet<QString> collectionNamesToBeAdded;
const QStringList allCollectionNames = m_collectionPropertyNames.keys();
for (const QString &collectionName : allCollectionNames)
@@ -165,12 +246,13 @@ void DataStoreModelNode::updateDataStoreProperties()
continue;
NodeProperty nodeProprty = property.toNodeProperty();
- if (!nodeProprty.hasDynamicTypeName(childNodeTypename))
+ if (!nodeProprty.hasDynamicTypeName(CHILDLISTMODEL_TYPENAME))
continue;
ModelNode childNode = nodeProprty.modelNode();
- if (childNode.hasProperty(CollectionEditor::JSONCHILDMODELNAME_PROPERTY)) {
- QString modelName = childNode.property(CollectionEditor::JSONCHILDMODELNAME_PROPERTY)
+ if (childNode.hasProperty(CollectionEditorConstants::JSONCHILDMODELNAME_PROPERTY)) {
+ QString modelName = childNode
+ .property(CollectionEditorConstants::JSONCHILDMODELNAME_PROPERTY)
.toVariantProperty()
.value()
.toString();
@@ -189,32 +271,17 @@ void DataStoreModelNode::updateDataStoreProperties()
QStringList collectionNamesLeft = collectionNamesToBeAdded.values();
Utils::sort(collectionNamesLeft);
- for (const QString &collectionName : std::as_const(collectionNamesLeft)) {
- PropertyName newPropertyName = getUniquePropertyName(collectionName);
- if (newPropertyName.isEmpty()) {
- qWarning() << __FUNCTION__ << __LINE__
- << QString("The property name cannot be generated from \"%1\"").arg(collectionName);
- continue;
- }
-
- ModelNode collectionNode = model()->createModelNode(childNodeTypename);
- VariantProperty modelNameProperty = collectionNode.variantProperty(
- CollectionEditor::JSONCHILDMODELNAME_PROPERTY);
- modelNameProperty.setValue(collectionName);
-
- NodeProperty nodeProp = rootNode.nodeProperty(newPropertyName);
- nodeProp.setDynamicTypeNameAndsetModelNode(childNodeTypename, collectionNode);
-
- m_collectionPropertyNames.insert(collectionName, newPropertyName);
- }
+ for (const QString &collectionName : std::as_const(collectionNamesLeft))
+ addCollectionNameToTheModel(collectionName, getUniquePropertyName(collectionName));
// Backend Property
- ModelNode backendNode = model()->createModelNode(CollectionEditor::JSONBACKEND_TYPENAME);
+ ModelNode backendNode = model()->createModelNode(CollectionEditorConstants::JSONBACKEND_TYPENAME);
NodeProperty backendProperty = rootNode.nodeProperty("backend");
- backendProperty.setDynamicTypeNameAndsetModelNode(CollectionEditor::JSONBACKEND_TYPENAME,
+ backendProperty.setDynamicTypeNameAndsetModelNode(CollectionEditorConstants::JSONBACKEND_TYPENAME,
backendNode);
// Source Property
- VariantProperty sourceProp = rootNode.variantProperty(CollectionEditor::SOURCEFILE_PROPERTY);
+ VariantProperty sourceProp = rootNode.variantProperty(
+ CollectionEditorConstants::SOURCEFILE_PROPERTY);
sourceProp.setValue(m_dataRelativePath);
}
@@ -231,19 +298,50 @@ void DataStoreModelNode::updateSingletonFile()
imports += QStringLiteral("import %1\n").arg(import.toString(true));
QString content = pragmaSingleTone + imports + getModelQmlText();
- QUrl modelUrl = m_model->fileUrl();
- FileSaver file(FilePath::fromUserInput(modelUrl.isLocalFile() ? modelUrl.toLocalFile()
- : modelUrl.toString()));
+ FileSaver file(dataStoreQmlFilePath());
file.write(content.toLatin1());
file.finalize();
}
void DataStoreModelNode::update()
{
+ if (!m_model.get())
+ return;
+
updateDataStoreProperties();
updateSingletonFile();
}
+void DataStoreModelNode::addCollectionNameToTheModel(const QString &collectionName,
+ const PropertyName &dataStorePropertyName)
+{
+ ModelNode rootNode = modelNode();
+ QTC_ASSERT(rootNode.isValid(), return);
+
+ if (dataStorePropertyName.isEmpty()) {
+ qWarning() << __FUNCTION__ << __LINE__
+ << QString("The property name cannot be generated from \"%1\"").arg(collectionName);
+ return;
+ }
+
+ ModelNode collectionNode = model()->createModelNode(CHILDLISTMODEL_TYPENAME);
+ VariantProperty modelNameProperty = collectionNode.variantProperty(
+ CollectionEditorConstants::JSONCHILDMODELNAME_PROPERTY);
+ modelNameProperty.setValue(collectionName);
+
+ NodeProperty nodeProp = rootNode.nodeProperty(dataStorePropertyName);
+ nodeProp.setDynamicTypeNameAndsetModelNode(CHILDLISTMODEL_TYPENAME, collectionNode);
+
+ m_collectionPropertyNames.insert(collectionName, dataStorePropertyName);
+}
+
+Utils::FilePath DataStoreModelNode::dataStoreQmlFilePath() const
+{
+ QUrl modelUrl = m_model->fileUrl();
+ return Utils::FilePath::fromUserInput(modelUrl.isLocalFile() ? modelUrl.toLocalFile()
+ : modelUrl.toString());
+}
+
PropertyName DataStoreModelNode::getUniquePropertyName(const QString &collectionName)
{
ModelNode dataStoreNode = modelNode();
@@ -300,7 +398,7 @@ void DataStoreModelNode::renameCollection(const QString &oldName, const QString
NodeProperty collectionNode = dataStoreNode.property(oldPropertyName).toNodeProperty();
if (collectionNode.isValid()) {
VariantProperty modelNameProperty = collectionNode.modelNode().variantProperty(
- CollectionEditor::JSONCHILDMODELNAME_PROPERTY);
+ CollectionEditorConstants::JSONCHILDMODELNAME_PROPERTY);
modelNameProperty.setValue(newName);
m_collectionPropertyNames.remove(oldName);
m_collectionPropertyNames.insert(newName, collectionNode.name());
@@ -333,7 +431,7 @@ void DataStoreModelNode::assignCollectionToNode(AbstractView *view,
{
QTC_ASSERT(targetNode.isValid(), return);
- if (!CollectionEditor::canAcceptCollectionAsModel(targetNode))
+ if (!CollectionEditorUtils::canAcceptCollectionAsModel(targetNode))
return;
if (!m_collectionPropertyNames.contains(collectionName)) {
@@ -352,12 +450,27 @@ void DataStoreModelNode::assignCollectionToNode(AbstractView *view,
return;
}
- BindingProperty modelProperty = targetNode.bindingProperty("model");
-
- QString identifier = QString("DataStore.%1").arg(QString::fromLatin1(sourceProperty.name()));
-
- view->executeInTransaction("assignCollectionToNode", [&modelProperty, &identifier]() {
+ view->executeInTransaction("assignCollectionToNode", [&]() {
+ QString identifier = QString("DataStore.%1").arg(QString::fromLatin1(sourceProperty.name()));
+ BindingProperty modelProperty = targetNode.bindingProperty("model");
modelProperty.setExpression(identifier);
+ if (CollectionEditorUtils::hasTextRoleProperty(targetNode)) {
+ VariantProperty textRoleProperty = targetNode.variantProperty("textRole");
+ const QVariant currentTextRoleValue = textRoleProperty.value();
+
+ if (currentTextRoleValue.isValid() && !currentTextRoleValue.isNull()) {
+ if (currentTextRoleValue.type() == QVariant::String) {
+ const QString currentTextRole = currentTextRoleValue.toString();
+ if (CollectionEditorUtils::collectionHasColumn(collectionName, currentTextRole))
+ return;
+ } else {
+ return;
+ }
+ }
+
+ QString textRoleValue = CollectionEditorUtils::getFirstColumnName(collectionName);
+ textRoleProperty.setValue(textRoleValue);
+ }
});
}
diff --git a/src/plugins/qmldesigner/components/collectioneditor/datastoremodelnode.h b/src/plugins/qmldesigner/components/collectioneditor/datastoremodelnode.h
index 3048fc4fc9..1c855bca7a 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/datastoremodelnode.h
+++ b/src/plugins/qmldesigner/components/collectioneditor/datastoremodelnode.h
@@ -7,6 +7,10 @@
#include <QMap>
+namespace Utils {
+class FilePath;
+}
+
namespace QmlDesigner {
class Model;
@@ -34,9 +38,14 @@ private:
QString getModelQmlText();
void reset();
+ void preloadFile();
void updateDataStoreProperties();
void updateSingletonFile();
void update();
+ void addCollectionNameToTheModel(const QString &collectionName,
+ const PropertyName &dataStorePropertyName);
+ Utils::FilePath dataStoreQmlFilePath() const;
+
PropertyName getUniquePropertyName(const QString &collectionName);
ModelPointer m_model;
diff --git a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp
index 6ad7ed994b..6e4b1a1efd 100644
--- a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp
@@ -11,6 +11,7 @@
#include "formatoperation.h"
#include "groupitemaction.h"
#include "modelnodecontextmenu_helper.h"
+#include "propertytreemodel.h"
#include "qmldesignerconstants.h"
#include "qmleditormenu.h"
#include "rewritingexception.h"
@@ -475,35 +476,20 @@ QStringList getSignalsList(const ModelNode &node)
if (!node.hasMetaInfo())
return {};
- QStringList signalsList;
- NodeMetaInfo nodeMetaInfo = node.metaInfo();
-
- for (const auto &signalName : nodeMetaInfo.signalNames()) {
- signalsList << QString::fromUtf8(signalName);
- }
-
- //on...Changed are the most regular signals, we assign them the lowest priority,
- //we don't need them right now
-// QStringList signalsWithChanged = signalsList.filter("Changed");
-
- //these are item specific, like MouseArea.clicked, they have higher priority
- QStringList signalsWithoutChanged = signalsList;
- signalsWithoutChanged.removeIf([](QString str) {
- if (str.endsWith("Changed"))
- return true;
- return false;
- });
-
- QStringList finalResult;
- finalResult.append(signalsWithoutChanged);
+ QStringList signalList;
+ std::vector<PropertyName> signalVector = PropertyTreeModel::sortedAndFilteredSignalNames(
+ node.metaInfo());
- if (finalResult.isEmpty())
- finalResult = signalsList;
+ std::vector<QString> signalVectorString = Utils::transform(signalVector,
+ [](const PropertyName &name) {
+ return QString::fromUtf8(name);
+ });
- finalResult.removeDuplicates();
+ signalList.reserve(Utils::ssize(signalVectorString));
+ std::copy(signalVectorString.begin(), signalVectorString.end(), std::back_inserter(signalList));
- return finalResult;
+ return signalList;
}
struct SlotEntry
diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
index 79ff364c40..dd00cd48d4 100644
--- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
@@ -1731,7 +1731,7 @@ bool useLayerEffect()
QtcSettings *settings = Core::ICore::settings();
const Key layerEffectEntry = "QML/Designer/UseLayerEffect";
- return settings->value(layerEffectEntry, true).toBool();
+ return settings->value(layerEffectEntry, false).toBool();
}
bool validateEffect(const QString &effectPath)
diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp b/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp
index e25f14411e..97919fa4fe 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp
+++ b/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp
@@ -309,6 +309,13 @@ ModelNode ConnectionModel::getTargetNodeForConnection(const ModelNode &connectio
static QString addOnToSignalName(const QString &signal)
{
+ if (signal.isEmpty())
+ return {};
+
+ static const QRegularExpression rx("^on[A-Z]");
+ if (rx.match(signal).hasMatch())
+ return signal;
+
QString ret = signal;
ret[0] = ret.at(0).toUpper();
ret.prepend("on");
@@ -361,11 +368,10 @@ void ConnectionModel::addConnection(const PropertyName &signalName)
ModelNode selectedNode = connectionView()->selectedModelNodes().constFirst();
PropertyName signalHandlerName = signalName;
- if (signalHandlerName.isEmpty()) {
- signalHandlerName = addOnToSignalName(QString::fromUtf8(getFirstSignalForTarget(
- selectedNode.metaInfo())))
- .toUtf8();
- }
+ if (signalHandlerName.isEmpty())
+ signalHandlerName = getFirstSignalForTarget(selectedNode.metaInfo());
+
+ signalHandlerName = addOnToSignalName(QString::fromUtf8(signalHandlerName)).toUtf8();
connectionView()
->executeInTransaction("ConnectionModel::addConnection", [=, &rootModelNode]() {
@@ -855,7 +861,7 @@ int ConnectionModelBackendDelegate::currentRow() const
return m_currentRow;
}
-QString removeOnFromSignalName(const QString &signal)
+static QString removeOnFromSignalName(const QString &signal)
{
if (signal.isEmpty())
return {};
diff --git a/src/plugins/qmldesigner/components/connectioneditor/propertytreemodel.cpp b/src/plugins/qmldesigner/components/connectioneditor/propertytreemodel.cpp
index 2b1f53243a..4189496316 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/propertytreemodel.cpp
+++ b/src/plugins/qmldesigner/components/connectioneditor/propertytreemodel.cpp
@@ -72,9 +72,7 @@ const std::vector<PropertyName> blockListSlots = {"childAt",
"inputMethodQuery",
"positionAt",
"positionToRectangle",
- "isRightToLeft"
-
-};
+ "isRightToLeft"};
const std::vector<PropertyName> priorityListSignals = {"clicked",
"doubleClicked",
@@ -99,7 +97,8 @@ const std::vector<PropertyName> priorityListSignals = {"clicked",
"enabledChanged",
"visibleChanged",
"opacityChanged",
- "rotationChanged"};
+ "rotationChanged",
+ "positionChanged"};
const std::vector<PropertyName> priorityListProperties = {"opacity",
"checked",
@@ -572,8 +571,7 @@ const std::vector<PropertyName> PropertyTreeModel::sortedAndFilteredPropertyName
const PropertyName name = metaInfo.name();
- if (!m_includeDotPropertiesOnFirstLevel
- && name.contains("."))
+ if (!m_includeDotPropertiesOnFirstLevel && name.contains("."))
return false;
return filterProperty(name, metaInfo, recursive);
@@ -606,8 +604,8 @@ const std::vector<PropertyName> PropertyTreeModel::sortedAndFilteredPropertyName
return checkedPriorityList;
}
-const std::vector<PropertyName> PropertyTreeModel::sortedAndFilteredSignalNames(
- const NodeMetaInfo &metaInfo, bool recursive) const
+std::vector<PropertyName> PropertyTreeModel::sortedAndFilteredSignalNames(const NodeMetaInfo &metaInfo,
+ bool recursive)
{
Q_UNUSED(recursive);
@@ -627,15 +625,14 @@ const std::vector<PropertyName> PropertyTreeModel::sortedAndFilteredSignalNames(
std::set<PropertyName> set(std::make_move_iterator(sorted.begin()),
std::make_move_iterator(sorted.end()));
- auto checkedPriorityList = Utils::filtered(priorityListSignals,
- [&set](const PropertyName &name) {
- auto it = set.find(name);
- const bool b = it != set.end();
- if (b)
- set.erase(it);
+ auto checkedPriorityList = Utils::filtered(priorityListSignals, [&set](const PropertyName &name) {
+ auto it = set.find(name);
+ const bool b = it != set.end();
+ if (b)
+ set.erase(it);
- return b;
- });
+ return b;
+ });
//const int priorityLength = checkedPriorityList.size(); We eventually require this to get the prioproperties
@@ -648,8 +645,8 @@ const std::vector<PropertyName> PropertyTreeModel::sortedAndFilteredSignalNames(
return checkedPriorityList;
}
-const std::vector<PropertyName> PropertyTreeModel::sortedAndFilteredSlotNames(
- const NodeMetaInfo &metaInfo, bool recursive) const
+std::vector<PropertyName> PropertyTreeModel::sortedAndFilteredSlotNames(const NodeMetaInfo &metaInfo,
+ bool recursive)
{
Q_UNUSED(recursive);
diff --git a/src/plugins/qmldesigner/components/connectioneditor/propertytreemodel.h b/src/plugins/qmldesigner/components/connectioneditor/propertytreemodel.h
index df17c112da..07e1401c4a 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/propertytreemodel.h
+++ b/src/plugins/qmldesigner/components/connectioneditor/propertytreemodel.h
@@ -84,6 +84,12 @@ public:
QHash<int, QByteArray> roleNames() const override;
+ static std::vector<PropertyName> sortedAndFilteredSignalNames(const NodeMetaInfo &metaInfo,
+ bool recursive = false);
+
+ static std::vector<PropertyName> sortedAndFilteredSlotNames(const NodeMetaInfo &metaInfo,
+ bool recursive = false);
+
private:
QModelIndex ensureModelIndex(const ModelNode &node, int row) const;
QModelIndex ensureModelIndex(const ModelNode &node, const PropertyName &name, int row) const;
@@ -94,15 +100,10 @@ private:
const std::vector<PropertyName> getDynamicProperties(const ModelNode &modelNode) const;
const std::vector<PropertyName> getDynamicSignals(const ModelNode &modelNode) const;
+
const std::vector<PropertyName> sortedAndFilteredPropertyNames(const NodeMetaInfo &metaInfo,
bool recursive = false) const;
- const std::vector<PropertyName> sortedAndFilteredSignalNames(const NodeMetaInfo &metaInfo,
- bool recursive = false) const;
-
- const std::vector<PropertyName> sortedAndFilteredSlotNames(const NodeMetaInfo &metaInfo,
- bool recursive = false) const;
-
const std::vector<PropertyName> sortedDotPropertyNames(const NodeMetaInfo &metaInfo,
const PropertyName &propertyName) const;
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp b/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp
index 404a5f5730..496f0e4b2c 100644
--- a/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp
@@ -262,6 +262,27 @@ void FormEditorItem::setFrameColor(const QColor &color)
update();
}
+void FormEditorItem::setHasEffect(bool hasEffect)
+{
+ m_hasEffect = hasEffect;
+}
+
+bool FormEditorItem::hasEffect() const
+{
+ return m_hasEffect;
+}
+
+bool FormEditorItem::parentHasEffect() const
+{
+ FormEditorItem *pi = parentItem();
+ while (pi) {
+ if (pi->hasEffect())
+ return true;
+ pi = pi->parentItem();
+ }
+ return false;
+}
+
FormEditorItem::~FormEditorItem()
{
scene()->removeItemFromHash(this);
@@ -421,7 +442,7 @@ void FormEditorItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *,
painter->setClipRegion(boundingRect().toRect());
painter->setClipping(true);
- if (!hideCompletely) {
+ if (!hideCompletely && !parentHasEffect()) {
if (showPlaceHolder) {
if (scene()->showBoundingRects() && m_boundingRect.width() > 15 && m_boundingRect.height() > 15)
paintPlaceHolderForInvisbleItem(painter);
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditoritem.h b/src/plugins/qmldesigner/components/formeditor/formeditoritem.h
index 69b67d0006..b035699772 100644
--- a/src/plugins/qmldesigner/components/formeditor/formeditoritem.h
+++ b/src/plugins/qmldesigner/components/formeditor/formeditoritem.h
@@ -98,6 +98,10 @@ public:
void setFrameColor(const QColor &color);
+ void setHasEffect(bool hasEffect);
+ bool hasEffect() const;
+ bool parentHasEffect() const;
+
protected:
AbstractFormEditorTool* tool() const;
void paintBoundingRect(QPainter *painter) const;
@@ -129,6 +133,7 @@ private: // variables
bool m_highlightBoundingRect;
bool m_blurContent;
bool m_isContentVisible;
+ bool m_hasEffect;
};
class FormEditorFlowItem : public FormEditorItem
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp
index 4b63d9ced8..fcc04ed026 100644
--- a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp
@@ -140,7 +140,7 @@ void FormEditorView::setupFormEditorItemTree(const QmlItemNode &qmlItemNode)
setupFormEditorItemTree(childNode.toQmlItemNode());
}
}
- } else {
+ } else if (!qmlItemNode.isEffectItem()) {
m_scene->addFormEditorItem(qmlItemNode, FormEditorScene::Default);
for (const QmlObjectNode &nextNode : qmlItemNode.allDirectSubNodes()) //TODO instance children
//If the node has source for components/custom parsers we ignore it.
@@ -280,6 +280,13 @@ void FormEditorView::nodeAboutToBeRemoved(const ModelNode &removedNode)
removeNodeFromScene(qmlItemNode);
}
+void FormEditorView::nodeRemoved(const ModelNode &/*removedNode*/,
+ const NodeAbstractProperty &/*parentProperty*/,
+ PropertyChangeFlags /*propertyChange*/)
+{
+ updateHasEffects();
+}
+
void FormEditorView::rootNodeTypeChanged(const QString &/*type*/, int /*majorVersion*/, int /*minorVersion*/)
{
const QList<FormEditorItem *> items = m_scene->allFormEditorItems();
@@ -343,6 +350,8 @@ static inline bool hasNodeSourceOrNonItemParent(const ModelNode &node)
void FormEditorView::nodeReparented(const ModelNode &node, const NodeAbstractProperty &/*newPropertyParent*/, const NodeAbstractProperty &/*oldPropertyParent*/, AbstractView::PropertyChangeFlags /*propertyChange*/)
{
addOrRemoveFormEditorItem(node);
+
+ updateHasEffects();
}
void FormEditorView::nodeSourceChanged(const ModelNode &node,
@@ -830,6 +839,8 @@ void FormEditorView::setupFormEditorWidget()
m_formEditorWidget->showWarningMessageBox(rewriterView()->warnings());
checkRootModelNode();
+
+ updateHasEffects();
}
QmlItemNode findRecursiveQmlItemNode(const QmlObjectNode &firstQmlObjectNode)
@@ -991,6 +1002,23 @@ void FormEditorView::setupRootItemSize()
}
}
+void FormEditorView::updateHasEffects()
+{
+ if (model()) {
+ const QList<ModelNode> nodes = allModelNodes();
+ for (const auto &node : nodes) {
+ QmlItemNode qmlNode(node);
+ FormEditorItem *item = m_scene->itemForQmlItemNode(qmlNode);
+ if (item)
+ item->setHasEffect(false);
+ if (qmlNode.isEffectItem()) {
+ FormEditorItem *parentItem = m_scene->itemForQmlItemNode(qmlNode.modelParentItem());
+ parentItem->setHasEffect(true);
+ }
+ }
+ }
+}
+
void FormEditorView::reset()
{
QTimer::singleShot(200, this, &FormEditorView::delayedReset);
diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorview.h b/src/plugins/qmldesigner/components/formeditor/formeditorview.h
index 1a9f15d016..d3c6cb21db 100644
--- a/src/plugins/qmldesigner/components/formeditor/formeditorview.h
+++ b/src/plugins/qmldesigner/components/formeditor/formeditorview.h
@@ -52,6 +52,8 @@ public:
void nodeCreated(const ModelNode &createdNode) override;
void nodeAboutToBeRemoved(const ModelNode &removedNode) override;
+ void nodeRemoved(const ModelNode &removedNode, const NodeAbstractProperty &parentProperty,
+ PropertyChangeFlags propertyChange) override;
void nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange) override;
void nodeSourceChanged(const ModelNode &node, const QString &newNodeSource) override;
void nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId) override;
@@ -138,6 +140,7 @@ private:
void checkRootModelNode();
void setupFormEditor3DView();
void setupRootItemSize();
+ void updateHasEffects();
QPointer<FormEditorWidget> m_formEditorWidget;
QPointer<FormEditorScene> m_scene;
diff --git a/src/plugins/qmldesigner/components/toolbar/toolbarbackend.cpp b/src/plugins/qmldesigner/components/toolbar/toolbarbackend.cpp
index ff0fa2ab9f..67043f02d1 100644
--- a/src/plugins/qmldesigner/components/toolbar/toolbarbackend.cpp
+++ b/src/plugins/qmldesigner/components/toolbar/toolbarbackend.cpp
@@ -149,6 +149,14 @@ WorkspaceModel::WorkspaceModel(QObject *)
};
if (!connectDockManager())
connect(designModeWidget(), &Internal::DesignModeWidget::initialized, this, connectDockManager);
+
+ connect(ProjectExplorer::ProjectManager::instance(),
+ &ProjectExplorer::ProjectManager::projectFinishedParsing,
+ this,
+ [this]() {
+ beginResetModel();
+ endResetModel();
+ });
}
int WorkspaceModel::rowCount(const QModelIndex &) const
@@ -162,7 +170,8 @@ int WorkspaceModel::rowCount(const QModelIndex &) const
QHash<int, QByteArray> WorkspaceModel::roleNames() const
{
static QHash<int, QByteArray> roleNames{{DisplayNameRole, "displayName"},
- {FileNameRole, "fileName"}};
+ {FileNameRole, "fileName"},
+ {Enabled, "enabled"}};
return roleNames;
}
@@ -176,6 +185,9 @@ QVariant WorkspaceModel::data(const QModelIndex &index, int role) const
return workspace.name();
} else if (role == FileNameRole) {
return workspace.fileName();
+ } else if (role == Enabled) {
+ if (QmlProjectManager::QmlProject::isMCUs())
+ return workspace.isMcusEnabled();
} else {
qWarning() << Q_FUNC_INFO << "invalid role";
}
diff --git a/src/plugins/qmldesigner/components/toolbar/toolbarbackend.h b/src/plugins/qmldesigner/components/toolbar/toolbarbackend.h
index 307704d63a..eb258f9ab7 100644
--- a/src/plugins/qmldesigner/components/toolbar/toolbarbackend.h
+++ b/src/plugins/qmldesigner/components/toolbar/toolbarbackend.h
@@ -29,7 +29,8 @@ public:
class WorkspaceModel : public QAbstractListModel
{
Q_OBJECT
- enum { DisplayNameRole = Qt::DisplayRole, FileNameRole = Qt::UserRole };
+
+ enum { DisplayNameRole = Qt::DisplayRole, FileNameRole = Qt::UserRole, Enabled };
public:
explicit WorkspaceModel(QObject *parent = nullptr);
diff --git a/src/plugins/qmldesigner/designercore/include/qmlitemnode.h b/src/plugins/qmldesigner/designercore/include/qmlitemnode.h
index 5816d60ce1..5948ec7ab1 100644
--- a/src/plugins/qmldesigner/designercore/include/qmlitemnode.h
+++ b/src/plugins/qmldesigner/designercore/include/qmlitemnode.h
@@ -139,6 +139,8 @@ public:
bool isFlowActionArea() const;
ModelNode rootModelNode() const;
+ bool isEffectItem() const;
+
friend auto qHash(const QmlItemNode &node) { return qHash(node.modelNode()); }
};
diff --git a/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp
index 0ce155ca6b..e01bdaaec3 100644
--- a/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp
@@ -182,14 +182,19 @@ QmlItemNode QmlItemNode::createQmlItemNodeForEffect(AbstractView *view,
const QString effectName = QFileInfo(effectPath).baseName();
Import import = Import::createLibraryImport("Effects." + effectName, "1.0");
try {
- if (!view->model()->hasImport(import, true, true))
+ if (!view->model()->hasImport(import, true, true)) {
view->model()->changeImports({import}, {});
+ // Trigger async reset puppet to ensure full transaction is done before reset
+ view->resetPuppet();
+ }
} catch (const Exception &) {
QTC_ASSERT(false, return);
}
TypeName type(effectName.toUtf8());
- newQmlItemNode = QmlItemNode(view->createModelNode(type, -1, -1));
+ ModelNode newModelNode = view->createModelNode(type, -1, -1);
+ newModelNode.setIdWithoutRefactoring(view->model()->generateNewId(effectName));
+ newQmlItemNode = QmlItemNode(newModelNode);
placeEffectNode(parentProperty, newQmlItemNode, isLayerEffect);
};
@@ -206,12 +211,8 @@ void QmlItemNode::placeEffectNode(NodeAbstractProperty &parentProperty, const Qm
parentProperty.reparentHere(effectNode);
- if (!isLayerEffect) {
- effectNode.modelNode().bindingProperty("source").setExpression("parent");
- effectNode.modelNode().bindingProperty("anchors.fill").setExpression("parent");
- } else {
+ if (isLayerEffect)
parentProperty.parentModelNode().variantProperty("layer.enabled").setValue(true);
- }
if (effectNode.modelNode().metaInfo().hasProperty("timeRunning"))
effectNode.modelNode().variantProperty("timeRunning").setValue(true);
@@ -617,6 +618,11 @@ ModelNode QmlItemNode::rootModelNode() const
return {};
}
+bool QmlItemNode::isEffectItem() const
+{
+ return modelNode().metaInfo().hasProperty("_isEffectItem");
+}
+
void QmlItemNode::setSize(const QSizeF &size)
{
if (!hasBindingProperty("width") && !(anchors().instanceHasAnchor(AnchorLineRight)
diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
index 889f847197..037259e87e 100644
--- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
+++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
@@ -388,6 +388,7 @@ bool smartVeryFuzzyCompare(const QVariant &value1, const QVariant &value2)
void removeModelNode(const QmlDesigner::ModelNode &modelNode)
{
+ QTC_ASSERT(modelNode.isValid(), return );
modelNode.model()->removeModelNodes({modelNode},
QmlDesigner::BypassModelResourceManagement::Yes);
}
@@ -400,6 +401,7 @@ bool smartColorCompare(const QVariant &value1, const QVariant &value2)
void removeProperty(const QmlDesigner::AbstractProperty &modelProperty)
{
+ QTC_ASSERT(modelProperty.isValid(), return );
modelProperty.model()->removeProperties({modelProperty},
QmlDesigner::BypassModelResourceManagement::Yes);
}
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.cpp b/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.cpp
index b7f6d2ae55..f9eb8080f7 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.cpp
+++ b/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.cpp
@@ -294,10 +294,16 @@ Storage::Synchronization::Type QmlDocumentParser::parse(const QString &sourceCon
QString filePath{m_pathCache.sourcePath(sourceId)};
environment.loadFile(
+#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
filePath,
filePath,
sourceContent,
QDateTime{},
+#else
+ QQmlJS::Dom::FileToLoad::fromMemory(environment.ownerAs<QQmlJS::Dom::DomEnvironment>(),
+ filePath,
+ sourceContent),
+#endif
[&](QmlDom::Path, const QmlDom::DomItem &, const QmlDom::DomItem &newItems) {
items = newItems;
},
diff --git a/src/plugins/qmldesigner/designmodewidget.cpp b/src/plugins/qmldesigner/designmodewidget.cpp
index a8567dec38..a26eada911 100644
--- a/src/plugins/qmldesigner/designmodewidget.cpp
+++ b/src/plugins/qmldesigner/designmodewidget.cpp
@@ -34,6 +34,7 @@
#include <coreplugin/idocument.h>
#include <coreplugin/inavigationwidgetfactory.h>
+#include <projectexplorer/projectmanager.h>
#include <qmlprojectmanager/qmlproject.h>
#include <utils/algorithm.h>
@@ -219,6 +220,13 @@ void DesignModeWidget::setup()
QString sheet = QString::fromUtf8(Utils::FileReader::fetchQrc(":/qmldesigner/dockwidgets.css"));
m_dockManager->setStyleSheet(Theme::replaceCssColors(sheet));
+ connect(ProjectExplorer::ProjectManager::instance(),
+ &ProjectExplorer::ProjectManager::projectFinishedParsing,
+ m_dockManager,
+ [this]() {
+ this->m_dockManager->setMcusProject(QmlProjectManager::QmlProject::isMCUs());
+ });
+
// Setup icons
const QString closeUnicode = Theme::getIconUnicode(Theme::Icon::close_small);
const QString maximizeUnicode = Theme::getIconUnicode(Theme::Icon::maxBar_small);
@@ -273,6 +281,7 @@ void DesignModeWidget::setup()
Core::ActionContainer *mview = Core::ActionManager::actionContainer(Core::Constants::M_VIEW);
// View > Views
Core::ActionContainer *mviews = Core::ActionManager::createMenu(Core::Constants::M_VIEW_VIEWS);
+ connect(mviews->menu(), &QMenu::aboutToShow, this, &DesignModeWidget::aboutToShowViews);
mviews->menu()->addSeparator();
// View > Workspaces
Core::ActionContainer *mworkspaces = Core::ActionManager::createMenu(QmlDesigner::Constants::M_VIEW_WORKSPACES);
@@ -482,6 +491,29 @@ void DesignModeWidget::setup()
show();
}
+static bool isMcuDisabledView(const QString viewId)
+{
+ static const QStringList mcuDisabledViews = {"Editor3D", "MaterialEditor", "MaterialBrowser", "TextureEditor"};
+ return mcuDisabledViews.contains(viewId);
+}
+
+void DesignModeWidget::aboutToShowViews()
+{
+ for (const WidgetInfo &widgetInfo : viewManager().widgetInfos()) {
+ QString id = widgetInfo.uniqueId;
+ ADS::DockWidget *dockWidget = m_dockManager->findDockWidget(id);
+ QAction *action = dockWidget->toggleViewAction();
+
+ bool isMcuProject = currentDesignDocument() && currentDesignDocument()->isQtForMCUsProject();
+ if (isMcuProject && isMcuDisabledView(id) && action->isEnabled()) {
+ action->setChecked(false);
+ action->setEnabled(false);
+ } else if (!isMcuProject && !action->isEnabled()) {
+ action->setEnabled(true);
+ }
+ }
+}
+
void DesignModeWidget::aboutToShowWorkspaces()
{
Core::ActionContainer *aci = Core::ActionManager::actionContainer(
@@ -520,6 +552,9 @@ void DesignModeWidget::aboutToShowWorkspaces()
action->setCheckable(true);
if (workspace == *m_dockManager->activeWorkspace())
action->setChecked(true);
+
+ if (currentDesignDocument() && currentDesignDocument()->isQtForMCUsProject())
+ action->setEnabled(workspace.isMcusEnabled());
}
menu->addActions(ag->actions());
}
diff --git a/src/plugins/qmldesigner/designmodewidget.h b/src/plugins/qmldesigner/designmodewidget.h
index 432549e694..464994b7e3 100644
--- a/src/plugins/qmldesigner/designmodewidget.h
+++ b/src/plugins/qmldesigner/designmodewidget.h
@@ -93,6 +93,7 @@ private:
QWidget *createCenterWidget();
QWidget *createCrumbleBarFrame();
+ void aboutToShowViews();
void aboutToShowWorkspaces();
QPointer<QWidget> m_bottomSideBar;
diff --git a/src/plugins/qmlprojectmanager/qmlproject.cpp b/src/plugins/qmlprojectmanager/qmlproject.cpp
index 0acba25ded..62a2d7bdfc 100644
--- a/src/plugins/qmlprojectmanager/qmlproject.cpp
+++ b/src/plugins/qmlprojectmanager/qmlproject.cpp
@@ -238,4 +238,17 @@ bool QmlProject::allowOnlySingleProject()
return !settings->value(key, false).toBool();
}
+bool QmlProject::isMCUs()
+{
+ if (!ProjectExplorer::ProjectManager::startupTarget())
+ return false;
+
+ const QmlProjectManager::QmlBuildSystem *buildSystem
+ = qobject_cast<QmlProjectManager::QmlBuildSystem *>(
+ ProjectExplorer::ProjectManager::startupTarget()->buildSystem());
+ QTC_ASSERT(buildSystem, return false);
+
+ return buildSystem && buildSystem->qtForMCUs();
+}
+
} // namespace QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/qmlproject.h b/src/plugins/qmlprojectmanager/qmlproject.h
index a41b05e57b..0091d77d6c 100644
--- a/src/plugins/qmlprojectmanager/qmlproject.h
+++ b/src/plugins/qmlprojectmanager/qmlproject.h
@@ -24,6 +24,8 @@ public:
ProjectExplorer::Tasks projectIssues(const ProjectExplorer::Kit *k) const final;
+ static bool isMCUs();
+
protected:
RestoreResult fromMap(const Utils::Store &map, QString *errorMessage) override;
diff --git a/src/plugins/qtsupport/baseqtversion.cpp b/src/plugins/qtsupport/baseqtversion.cpp
index fb28d16aa3..da669423e3 100644
--- a/src/plugins/qtsupport/baseqtversion.cpp
+++ b/src/plugins/qtsupport/baseqtversion.cpp
@@ -77,7 +77,7 @@ class QtVersionData
{
public:
// Update version if you add data members!
- static const int version = 2;
+ static const int version = 3;
bool installed = true;
bool hasExamples = false;
@@ -203,8 +203,11 @@ public:
hostDataPath = FilePath::fromSettings(map.value("HostDataPath"));
hostPrefixPath = FilePath::fromSettings(map.value("HostPrefixPath"));
auto it = map.find("QtAbis");
- if (it != map.end())
- qtAbis = Utils::transform(it.value().toStringList(), &Abi::fromString);
+ if (it != map.end()) {
+ const auto qtAbisList = it.value().toStringList();
+ if (!qtAbisList.isEmpty())
+ qtAbis = Utils::transform(qtAbisList, &Abi::fromString);
+ }
versionInfo = fromStore(map.value("VersionInfo").value<Store>());
}
};
diff --git a/src/plugins/studiowelcome/studiowelcomeplugin.cpp b/src/plugins/studiowelcome/studiowelcomeplugin.cpp
index b48d87121f..c80b64601b 100644
--- a/src/plugins/studiowelcome/studiowelcomeplugin.cpp
+++ b/src/plugins/studiowelcome/studiowelcomeplugin.cpp
@@ -759,7 +759,8 @@ WelcomeMode::WelcomeMode()
m_dataModelDownloader->setForceDownload(true);
connect(m_dataModelDownloader, &DataModelDownloader::progressChanged, this, [this](){
- m_quickWidget->rootObject()->setProperty("loadingProgress", m_dataModelDownloader->progress());
+ if (m_quickWidget->rootObject())
+ m_quickWidget->rootObject()->setProperty("loadingProgress", m_dataModelDownloader->progress());
});
connect(m_dataModelDownloader, &DataModelDownloader::finished, this, [this, welcomePagePath]() {