aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Jenssen <tim.jenssen@qt.io>2024-04-23 14:36:48 +0200
committerTim Jenssen <tim.jenssen@qt.io>2024-04-23 16:05:55 +0200
commitef0ee52bf92739bc5b32d70c01ff1eadd752d813 (patch)
tree0f3b2f546af088b86f21452622d77be43386cd5f
parentd9c8590c5fd10b1feceb389c142ec244909739a2 (diff)
parent7dfa7469207f899e347dc6f2bf0c3011140a9b23 (diff)
Merge remote-tracking branch 'origin/qds/dev'
Conflicts: doc/qtcreator/src/overview/creator-only/creator-keyboard-shortcuts.qdoc doc/qtcreator/src/qtquick/qtquick-live-preview-devices.qdoc doc/qtcreator/src/qtquick/qtquick-profiler.qdoc src/plugins/qmlprojectmanager/qmlprojectmanager.qbs src/plugins/remotelinux/linuxdevicetester.cpp Change-Id: I3683c1799df05209d05413383456b285a2daf96e
-rw-r--r--CMakeLists.txt4
-rw-r--r--cmake/QtCreatorAPIInternal.cmake10
-rw-r--r--doc/qtcreator/src/debugger/qtquick-debugger-example.qdoc2
-rw-r--r--doc/qtcreator/src/debugger/qtquick-debugging.qdoc2
-rw-r--r--doc/qtcreator/src/external-resources/external-resources-qds.qdoc36
-rw-r--r--doc/qtcreator/src/qtquick/qtquick-profiler.qdoc2
-rw-r--r--doc/qtcreator/src/user-interface/creator-file-system-view.qdoc21
-rw-r--r--doc/qtcreator/src/user-interface/creator-open-documents-view.qdoc19
-rw-r--r--doc/qtcreator/src/user-interface/creator-projects-view.qdoc29
-rw-r--r--doc/qtcreator/src/user-interface/creator-ui.qdoc5
-rw-r--r--doc/qtcreator/src/vcs/creator-vcs-git.qdoc4
-rw-r--r--doc/qtdesignstudio/config/qtdesignstudio.qdocconf5
-rw-r--r--doc/qtdesignstudio/examples/doc/FresnelExample.qdoc90
-rw-r--r--doc/qtdesignstudio/examples/doc/images/fresnel-angle.webpbin0 -> 7182 bytes
-rw-r--r--doc/qtdesignstudio/examples/doc/images/fresnel-example.webpbin0 -> 62494 bytes
-rw-r--r--doc/qtdesignstudio/examples/doc/rainSnowParticles.qdoc2
-rw-r--r--doc/qtdesignstudio/images/3d-view-context-menu.pngbin10442 -> 0 bytes
-rw-r--r--doc/qtdesignstudio/images/3d-view-context-menu.webpbin0 -> 5718 bytes
-rw-r--r--doc/qtdesignstudio/images/camera-look-at-node.webpbin0 -> 17124 bytes
-rw-r--r--doc/qtdesignstudio/images/edit-list-model-model-editor.webpbin0 -> 16430 bytes
-rw-r--r--doc/qtdesignstudio/images/filesystem-view-design.webpbin0 -> 5944 bytes
-rw-r--r--doc/qtdesignstudio/images/icons/add_material.pngbin0 -> 1722 bytes
-rw-r--r--doc/qtdesignstudio/images/icons/add_texture.pngbin0 -> 1716 bytes
-rw-r--r--doc/qtdesignstudio/images/icons/camera_speed.pngbin0 -> 1641 bytes
-rw-r--r--doc/qtdesignstudio/images/icons/easing-curve-spline.pngbin0 -> 1606 bytes
-rw-r--r--doc/qtdesignstudio/images/icons/easing-curve-unify.png (renamed from doc/qtdesignstudio/images/icons/easing-curve-spline-icon.png)bin360 -> 360 bytes
-rw-r--r--doc/qtdesignstudio/images/icons/export.pngbin0 -> 1617 bytes
-rw-r--r--doc/qtdesignstudio/images/icons/import.pngbin0 -> 1834 bytes
-rw-r--r--doc/qtdesignstudio/images/icons/reverse_order.pngbin0 -> 1740 bytes
-rw-r--r--doc/qtdesignstudio/images/material-editor-browser.webpbin42272 -> 36366 bytes
-rw-r--r--doc/qtdesignstudio/images/materials-remove-material.pngbin15142 -> 0 bytes
-rw-r--r--doc/qtdesignstudio/images/materials-remove-material.webpbin0 -> 5594 bytes
-rw-r--r--doc/qtdesignstudio/images/model-editor-new-model.webpbin0 -> 5832 bytes
-rw-r--r--doc/qtdesignstudio/images/navigator-material-texture.pngbin4048 -> 0 bytes
-rw-r--r--doc/qtdesignstudio/images/navigator-material-texture.webpbin0 -> 2884 bytes
-rw-r--r--doc/qtdesignstudio/images/open-documents-view.webpbin0 -> 2338 bytes
-rw-r--r--doc/qtdesignstudio/images/projects-view-design.webpbin0 -> 4660 bytes
-rw-r--r--doc/qtdesignstudio/images/qmldesigner-canvas-color.pngbin4557 -> 0 bytes
-rw-r--r--doc/qtdesignstudio/images/qmldesigner-canvas-color.webpbin0 -> 3558 bytes
-rw-r--r--doc/qtdesignstudio/images/qmldesigner-element-properties.pngbin27358 -> 0 bytes
-rw-r--r--doc/qtdesignstudio/images/qmldesigner-element-properties.webpbin0 -> 12928 bytes
-rw-r--r--doc/qtdesignstudio/images/qmldesigner-form-editor-move-cursor.pngbin9983 -> 0 bytes
-rw-r--r--doc/qtdesignstudio/images/qmldesigner-form-editor-move-cursor.webpbin0 -> 3430 bytes
-rw-r--r--doc/qtdesignstudio/images/qmldesigner-form-editor.pngbin9604 -> 0 bytes
-rw-r--r--doc/qtdesignstudio/images/qmldesigner-form-editor.webpbin0 -> 4986 bytes
-rw-r--r--doc/qtdesignstudio/images/qmldesigner-preview-size.pngbin45589 -> 0 bytes
-rw-r--r--doc/qtdesignstudio/images/qmldesigner-preview-size.webpbin0 -> 15954 bytes
-rw-r--r--doc/qtdesignstudio/images/qmldesigner-snap-margins.pngbin6617 -> 0 bytes
-rw-r--r--doc/qtdesignstudio/images/qmldesigner-snap-margins.webpbin0 -> 4052 bytes
-rw-r--r--doc/qtdesignstudio/images/qmldesigner-transition-editor-startup.pngbin3840 -> 0 bytes
-rw-r--r--doc/qtdesignstudio/images/qmldesigner-transition-editor-startup.webpbin0 -> 2316 bytes
-rw-r--r--doc/qtdesignstudio/images/qmldesigner-transitions.webpbin0 -> 20632 bytes
-rw-r--r--doc/qtdesignstudio/images/qmldesigner-zooming.gifbin93266 -> 80130 bytes
-rw-r--r--doc/qtdesignstudio/images/qtquick-assets-tab.pngbin16953 -> 0 bytes
-rw-r--r--doc/qtdesignstudio/images/qtquick-assets-tab.webpbin0 -> 8972 bytes
-rw-r--r--doc/qtdesignstudio/images/qtquick-designer-rotating-items.pngbin10790 -> 0 bytes
-rw-r--r--doc/qtdesignstudio/images/qtquick-designer-rotating-items.webpbin0 -> 6428 bytes
-rw-r--r--doc/qtdesignstudio/images/qtquick-designer-scaling-items.pngbin8340 -> 0 bytes
-rw-r--r--doc/qtdesignstudio/images/qtquick-designer-scaling-items.webpbin0 -> 3348 bytes
-rw-r--r--doc/qtdesignstudio/images/qtquick-item-properties-common.pngbin5519 -> 0 bytes
-rw-r--r--doc/qtdesignstudio/images/qtquick-item-properties-common.webpbin0 -> 5474 bytes
-rw-r--r--doc/qtdesignstudio/images/qtquick-library-context-menu.pngbin16734 -> 0 bytes
-rw-r--r--doc/qtdesignstudio/images/qtquick-library-context-menu.webpbin0 -> 12268 bytes
-rw-r--r--doc/qtdesignstudio/images/qtquick-transition-editor-settings.pngbin6812 -> 0 bytes
-rw-r--r--doc/qtdesignstudio/images/qtquick-transition-editor-settings.webpbin0 -> 4516 bytes
-rw-r--r--doc/qtdesignstudio/images/qtquick-transition-editor-view.pngbin6750 -> 0 bytes
-rw-r--r--doc/qtdesignstudio/images/qtquick-transition-editor-view.webpbin0 -> 4792 bytes
-rw-r--r--doc/qtdesignstudio/images/repeater3d-listmodel-navigator.pngbin5996 -> 4705 bytes
-rw-r--r--doc/qtdesignstudio/images/repeater3d-model-editor.webpbin0 -> 10202 bytes
-rw-r--r--doc/qtdesignstudio/images/studio-3d-editor-axis-helper.webpbin30310 -> 19966 bytes
-rw-r--r--doc/qtdesignstudio/images/studio-3d-editor-move.webpbin30488 -> 21094 bytes
-rw-r--r--doc/qtdesignstudio/images/studio-3d-editor-rotate.webpbin31534 -> 22998 bytes
-rw-r--r--doc/qtdesignstudio/images/studio-3d-editor-scale.webpbin30344 -> 21210 bytes
-rw-r--r--doc/qtdesignstudio/images/studio-3d-editor.webpbin29906 -> 19690 bytes
-rw-r--r--doc/qtdesignstudio/images/studio-3d-properties-type.pngbin6593 -> 0 bytes
-rw-r--r--doc/qtdesignstudio/images/studio-3d-properties-type.webpbin0 -> 6244 bytes
-rw-r--r--doc/qtdesignstudio/images/studio-3d-scene-environment-ambient-occlusion.webpbin0 -> 6750 bytes
-rw-r--r--doc/qtdesignstudio/images/studio-3d-scene-environment-antialiasing.webpbin0 -> 6410 bytes
-rw-r--r--doc/qtdesignstudio/images/studio-3d-scene-environment-image-based-lighting.webpbin0 -> 6382 bytes
-rw-r--r--doc/qtdesignstudio/images/studio-3d-scene-environment-light-probe.pngbin9907 -> 0 bytes
-rw-r--r--doc/qtdesignstudio/images/studio-3d-scene-environment-properties.pngbin15463 -> 0 bytes
-rw-r--r--doc/qtdesignstudio/images/studio-3d-scene-environment-properties.webpbin0 -> 6522 bytes
-rw-r--r--doc/qtdesignstudio/images/studio-3d-split-view.webpbin33988 -> 22818 bytes
-rw-r--r--doc/qtdesignstudio/images/studio-curve-editor.pngbin20623 -> 0 bytes
-rw-r--r--doc/qtdesignstudio/images/studio-curve-editor.webpbin0 -> 13526 bytes
-rw-r--r--doc/qtdesignstudio/images/studio-ext-scene-environment.webpbin0 -> 14566 bytes
-rw-r--r--doc/qtdesignstudio/images/studio-flow-item.pngbin12570 -> 0 bytes
-rw-r--r--doc/qtdesignstudio/images/studio-flow-item.webpbin0 -> 8150 bytes
-rw-r--r--doc/qtdesignstudio/images/studio-flow-view-properties.pngbin9780 -> 0 bytes
-rw-r--r--doc/qtdesignstudio/images/studio-flow-view-properties.webpbin0 -> 8724 bytes
-rw-r--r--doc/qtdesignstudio/images/studio-project-wizards.pngbin104223 -> 0 bytes
-rw-r--r--doc/qtdesignstudio/images/studio-project-wizards.webpbin0 -> 75114 bytes
-rw-r--r--doc/qtdesignstudio/images/studio-qtquick-3d-components.pngbin21566 -> 0 bytes
-rw-r--r--doc/qtdesignstudio/images/studio-qtquick-3d-components.webpbin0 -> 14204 bytes
-rw-r--r--doc/qtdesignstudio/images/studio-qtquick-3d-view.pngbin6349 -> 0 bytes
-rw-r--r--doc/qtdesignstudio/images/studio-qtquick-3d-view.webpbin0 -> 6362 bytes
-rw-r--r--doc/qtdesignstudio/images/studio-qtquick-camera-properties.webpbin0 -> 11336 bytes
-rw-r--r--doc/qtdesignstudio/images/studio-timeline-empty.pngbin3423 -> 0 bytes
-rw-r--r--doc/qtdesignstudio/images/studio-timeline-empty.webpbin0 -> 2238 bytes
-rw-r--r--doc/qtdesignstudio/images/texture-editor.pngbin56206 -> 0 bytes
-rw-r--r--doc/qtdesignstudio/images/texture-editor.webpbin0 -> 37754 bytes
-rw-r--r--doc/qtdesignstudio/src/components/qtquick-component-context-menu.qdocinc8
-rw-r--r--doc/qtdesignstudio/src/components/qtquick-data-models.qdoc14
-rw-r--r--doc/qtdesignstudio/src/components/qtquick-preset-components.qdoc4
-rw-r--r--doc/qtdesignstudio/src/developers/studio-designer-developer-workflow.qdoc8
-rw-r--r--doc/qtdesignstudio/src/mcus/qtdesignstudio-compatibility-with-mcu-sdks.qdoc12
-rw-r--r--doc/qtdesignstudio/src/overviews/qtquick-creating-ui-logic.qdoc2
-rw-r--r--doc/qtdesignstudio/src/overviews/qtquick-export.qdoc2
-rw-r--r--doc/qtdesignstudio/src/overviews/qtquick-optimizing-designs.qdoc2
-rw-r--r--doc/qtdesignstudio/src/overviews/qtquick-production-quality-animation.qdoc2
-rw-r--r--doc/qtdesignstudio/src/qtdesignstudio-app-flows.qdoc81
-rw-r--r--doc/qtdesignstudio/src/qtdesignstudio-faq.qdoc139
-rw-r--r--doc/qtdesignstudio/src/qtdesignstudio-finding-qt-runtime-version.qdoc3
-rw-r--r--doc/qtdesignstudio/src/qtdesignstudio-help-overview.qdoc6
-rw-r--r--doc/qtdesignstudio/src/qtdesignstudio-packaging.qdoc2
-rw-r--r--doc/qtdesignstudio/src/qtdesignstudio-platforms.qdoc30
-rw-r--r--doc/qtdesignstudio/src/qtdesignstudio-projects.qdoc9
-rw-r--r--doc/qtdesignstudio/src/qtdesignstudio-terms.qdoc4
-rw-r--r--doc/qtdesignstudio/src/qtdesignstudio-toc.qdoc34
-rw-r--r--doc/qtdesignstudio/src/qtdesignstudio.qdoc1
-rw-r--r--doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-camera.qdoc33
-rw-r--r--doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-custom-shaders.qdoc4
-rw-r--r--doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-editor.qdoc189
-rw-r--r--doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-effects.qdoc4
-rw-r--r--doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-lights.qdoc2
-rw-r--r--doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-model.qdoc5
-rw-r--r--doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-repeater-3d.qdoc106
-rw-r--r--doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-scene-environment.qdoc163
-rw-r--r--doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-view.qdoc76
-rw-r--r--doc/qtdesignstudio/src/reference/qtdesignstudio-keyboard-shortcuts.qdoc8
-rw-r--r--doc/qtdesignstudio/src/views/qtquick-assets.qdoc30
-rw-r--r--doc/qtdesignstudio/src/views/qtquick-components-view.qdoc32
-rw-r--r--doc/qtdesignstudio/src/views/qtquick-connection-view.qdoc33
-rw-r--r--doc/qtdesignstudio/src/views/qtquick-curve-editor.qdoc72
-rw-r--r--doc/qtdesignstudio/src/views/qtquick-designer.qdoc218
-rw-r--r--doc/qtdesignstudio/src/views/qtquick-easing-curve-editor.qdoc4
-rw-r--r--doc/qtdesignstudio/src/views/qtquick-effect-maker-view.qdoc8
-rw-r--r--doc/qtdesignstudio/src/views/qtquick-form-editor.qdoc72
-rw-r--r--doc/qtdesignstudio/src/views/qtquick-navigator.qdoc82
-rw-r--r--doc/qtdesignstudio/src/views/qtquick-properties-view.qdoc50
-rw-r--r--doc/qtdesignstudio/src/views/qtquick-properties.qdoc4
-rw-r--r--doc/qtdesignstudio/src/views/qtquick-states-view.qdoc8
-rw-r--r--doc/qtdesignstudio/src/views/qtquick-text-editor.qdoc4
-rw-r--r--doc/qtdesignstudio/src/views/qtquick-timeline-view.qdoc177
-rw-r--r--doc/qtdesignstudio/src/views/qtquick-timeline.qdoc4
-rw-r--r--doc/qtdesignstudio/src/views/qtquick-transition-editor.qdoc54
-rw-r--r--doc/qtdesignstudio/src/views/studio-content-library.qdoc5
-rw-r--r--doc/qtdesignstudio/src/views/studio-material-editor.qdoc21
-rw-r--r--doc/qtdesignstudio/src/views/studio-model-editor.qdoc62
-rw-r--r--doc/qtdesignstudio/src/views/studio-qtinsight.qdoc4
-rw-r--r--doc/qtdesignstudio/src/views/studio-texture-editor.qdoc10
-rw-r--r--doc/qtdesignstudio/src/views/studio-translations.qdoc49
-rw-r--r--doc/qtdesignstudio/src/views/studio-workspaces.qdoc2
-rw-r--r--share/qtcreator/qmldesigner/assetsLibraryQmlSources/Assets.qml6
-rw-r--r--share/qtcreator/qmldesigner/assetsLibraryQmlSources/AssetsContextMenu.qml31
-rw-r--r--share/qtcreator/qmldesigner/assetsLibraryQmlSources/AssetsView.qml8
-rw-r--r--share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionDetailsEditDelegate.qml10
-rw-r--r--share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionDetailsToolbar.qml27
-rw-r--r--share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionDetailsView.qml195
-rw-r--r--share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionItem.qml153
-rw-r--r--share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionListView.qml198
-rw-r--r--share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionView.qml16
-rw-r--r--share/qtcreator/qmldesigner/collectionEditorQmlSource/ColorViewDelegate.qml54
-rw-r--r--share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibrary.qml46
-rw-r--r--share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterial.qml13
-rw-r--r--share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterialContextMenu.qml13
-rw-r--r--share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterialsView.qml25
-rw-r--r--share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexture.qml6
-rw-r--r--share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexturesView.qml3
-rw-r--r--share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryUserView.qml162
-rw-r--r--share/qtcreator/qmldesigner/contentLibraryQmlSource/UnimportBundleMaterialDialog.qml23
-rw-r--r--share/qtcreator/qmldesigner/designericons.json2
-rw-r--r--share/qtcreator/qmldesigner/edit3dQmlSource/CameraSpeedConfigurationDialog.qml2
-rw-r--r--share/qtcreator/qmldesigner/effectComposerQmlSources/EffectComposer.qml2
-rw-r--r--share/qtcreator/qmldesigner/effectComposerQmlSources/EffectComposerPreview.qml8
-rw-r--r--share/qtcreator/qmldesigner/effectComposerQmlSources/EffectComposerTopBar.qml5
-rw-r--r--share/qtcreator/qmldesigner/effectComposerQmlSources/EffectCompositionNode.qml2
-rw-r--r--share/qtcreator/qmldesigner/effectComposerQmlSources/EffectCompositionNodeUniform.qml33
-rw-r--r--share/qtcreator/qmldesigner/effectComposerQmlSources/SaveAsDialog.qml8
-rw-r--r--share/qtcreator/qmldesigner/effectComposerQmlSources/ValueColor.qml10
-rw-r--r--share/qtcreator/qmldesigner/effectComposerQmlSources/ValueFloat.qml6
-rw-r--r--share/qtcreator/qmldesigner/effectComposerQmlSources/ValueInt.qml6
-rw-r--r--share/qtcreator/qmldesigner/effectComposerQmlSources/ValueVec2.qml12
-rw-r--r--share/qtcreator/qmldesigner/effectComposerQmlSources/ValueVec3.qml18
-rw-r--r--share/qtcreator/qmldesigner/effectComposerQmlSources/ValueVec4.qml24
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/ambient-sound-16.pngbin0 -> 315 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/ambient-sound-24.pngbin0 -> 514 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/ambient-sound-24@2x.pngbin0 -> 1846 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/animated-image-icon.pngbin0 -> 298 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/animated-image-icon16.pngbin0 -> 211 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/animated-image-icon@2x.pngbin0 -> 342 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/animatedsprite-loading.pngbin0 -> 118 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/audio-engine-16.pngbin0 -> 363 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/audio-engine-24.pngbin0 -> 472 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/audio-engine-24@2x.pngbin0 -> 803 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/audio-listener-16.pngbin0 -> 311 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/audio-listener-24.pngbin0 -> 924 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/audio-listener-24@2x.pngbin0 -> 1691 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/audio-output-16px.pngbin0 -> 359 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/audio-output-24px.pngbin0 -> 595 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/audio-output-24px@2x.pngbin0 -> 1129 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/audio-room-16.pngbin0 -> 276 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/audio-room-24.pngbin0 -> 419 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/audio-room-24@2x.pngbin0 -> 878 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/border-image-icon.pngbin0 -> 299 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/border-image-icon16.pngbin0 -> 228 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/border-image-icon@2x.pngbin0 -> 386 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/busyindicator-icon.pngbin0 -> 320 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/busyindicator-icon16.pngbin0 -> 229 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/busyindicator-icon@2x.pngbin0 -> 643 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/button-icon.pngbin0 -> 162 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/button-icon16.pngbin0 -> 145 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/button-icon@2x.pngbin0 -> 259 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/checkbox-icon.pngbin0 -> 258 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/checkbox-icon16.pngbin0 -> 230 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/checkbox-icon@2x.pngbin0 -> 336 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/column-positioner-icon-16px.pngbin0 -> 113 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/column-positioner-icon.pngbin0 -> 118 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/column-positioner-icon@2x.pngbin0 -> 121 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/combobox-icon.pngbin0 -> 156 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/combobox-icon16.pngbin0 -> 155 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/combobox-icon@2x.pngbin0 -> 185 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/component-icon.pngbin0 -> 626 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/component-icon16.pngbin0 -> 438 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/component-icon@2x.pngbin0 -> 1107 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/control-icon.pngbin0 -> 293 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/control-icon16.pngbin0 -> 229 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/control-icon@2x.pngbin0 -> 509 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/default-icon.pngbin0 -> 813 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/default3d.pngbin0 -> 375 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/default3d16.pngbin0 -> 253 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/default3d@2x.pngbin0 -> 499 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/delaybutton-icon.pngbin0 -> 189 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/delaybutton-icon16.pngbin0 -> 160 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/delaybutton-icon@2x.pngbin0 -> 286 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/dial-icon.pngbin0 -> 267 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/dial-icon16.pngbin0 -> 243 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/dial-icon@2x.pngbin0 -> 505 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/drop-area-16px.pngbin0 -> 205 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/drop-area-24px.pngbin0 -> 490 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/drop-area-24px@2x.pngbin0 -> 638 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/extended-view3d-16px.pngbin0 -> 311 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/extended-view3d-24px.pngbin0 -> 384 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/extended-view3d-24px@2x.pngbin0 -> 674 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/flickable-icon.pngbin0 -> 246 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/flickable-icon16.pngbin0 -> 209 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/flickable-icon@2x.pngbin0 -> 322 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/flipable-icon.pngbin0 -> 678 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/flipable-icon16.pngbin0 -> 466 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/flow-positioner-icon-16px.pngbin0 -> 98 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/flow-positioner-icon.pngbin0 -> 101 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/flow-positioner-icon@2x.pngbin0 -> 129 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/focusscope-icon.pngbin0 -> 143 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/focusscope-icon16.pngbin0 -> 161 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/focusscope-icon@2x.pngbin0 -> 182 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/frame-icon.pngbin0 -> 121 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/frame-icon16.pngbin0 -> 117 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/frame-icon@2x.pngbin0 -> 125 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/grid-positioner-icon-16px.pngbin0 -> 93 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/grid-positioner-icon.pngbin0 -> 97 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/grid-positioner-icon@2x.pngbin0 -> 125 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/gridview-icon.pngbin0 -> 127 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/gridview-icon16.pngbin0 -> 102 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/gridview-icon@2x.pngbin0 -> 137 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/groupbox-icon.pngbin0 -> 133 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/groupbox-icon16.pngbin0 -> 125 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/groupbox-icon@2x.pngbin0 -> 136 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/image-icon.pngbin0 -> 434 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/image-icon16.pngbin0 -> 296 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/image-icon@2x.pngbin0 -> 596 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/item-icon.pngbin0 -> 148 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/item-icon16.pngbin0 -> 135 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/item-icon@2x.pngbin0 -> 167 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/itemdelegate-icon.pngbin0 -> 127 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/itemdelegate-icon16.pngbin0 -> 124 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/itemdelegate-icon@2x.pngbin0 -> 133 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/keyframe-16px.pngbin0 -> 190 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/label-icon.pngbin0 -> 206 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/label-icon16.pngbin0 -> 182 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/label-icon@2x.pngbin0 -> 284 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/listview-icon.pngbin0 -> 148 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/listview-icon16.pngbin0 -> 136 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/listview-icon@2x.pngbin0 -> 158 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/loader-icon.pngbin0 -> 321 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/loader-icon16.pngbin0 -> 222 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/loader-icon@2x.pngbin0 -> 483 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/media-player-16px.pngbin0 -> 148 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/media-player-24px.pngbin0 -> 179 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/media-player-24px@2x.pngbin0 -> 260 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/mouse-area-icon.pngbin0 -> 358 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/mouse-area-icon16.pngbin0 -> 263 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/mouse-area-icon@2x.pngbin0 -> 755 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/page-icon.pngbin0 -> 190 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/page-icon16.pngbin0 -> 148 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/page-icon@2x.pngbin0 -> 195 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/pageindicator-icon.pngbin0 -> 179 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/pageindicator-icon16.pngbin0 -> 158 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/pageindicator-icon@2x.pngbin0 -> 207 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/pane-icon.pngbin0 -> 93 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/pane-icon16.pngbin0 -> 92 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/pane-icon@2x.pngbin0 -> 96 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/pathview-icon.pngbin0 -> 457 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/pathview-icon16.pngbin0 -> 320 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/pathview-icon@2x.pngbin0 -> 864 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/progressbar-icon.pngbin0 -> 101 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/progressbar-icon16.pngbin0 -> 92 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/progressbar-icon@2x.pngbin0 -> 127 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/radiobutton-icon.pngbin0 -> 279 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/radiobutton-icon16.pngbin0 -> 218 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/radiobutton-icon@2x.pngbin0 -> 482 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/rangeslider-icon.pngbin0 -> 269 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/rangeslider-icon16.pngbin0 -> 231 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/rangeslider-icon@2x.pngbin0 -> 282 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/rect-icon.pngbin0 -> 169 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/rect-icon16.pngbin0 -> 135 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/rect-icon@2x.pngbin0 -> 237 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/repeater-icon.pngbin0 -> 191 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/repeater-icon16.pngbin0 -> 187 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/repeater-icon@2x.pngbin0 -> 196 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/roundbutton-icon.pngbin0 -> 229 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/roundbutton-icon16.pngbin0 -> 186 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/roundbutton-icon@2x.pngbin0 -> 381 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/row-positioner-icon-16px.pngbin0 -> 115 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/row-positioner-icon.pngbin0 -> 120 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/row-positioner-icon@2x.pngbin0 -> 126 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/scrollview-icon.pngbin0 -> 110 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/scrollview-icon16.pngbin0 -> 116 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/scrollview-icon@2x.pngbin0 -> 145 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/slider-icon.pngbin0 -> 190 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/slider-icon16.pngbin0 -> 156 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/slider-icon@2x.pngbin0 -> 227 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/spatial-audio-16.pngbin0 -> 319 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/spatial-audio-24.pngbin0 -> 664 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/spatial-audio-24@2x.pngbin0 -> 1536 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/spinbox-icon.pngbin0 -> 144 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/spinbox-icon16.pngbin0 -> 151 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/spinbox-icon@2x.pngbin0 -> 178 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/stackview-icon.pngbin0 -> 162 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/stackview-icon16.pngbin0 -> 151 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/stackview-icon@2x.pngbin0 -> 167 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/swipeview-icon.pngbin0 -> 163 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/swipeview-icon16.pngbin0 -> 152 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/swipeview-icon@2x.pngbin0 -> 184 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/switch-icon.pngbin0 -> 205 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/switch-icon16.pngbin0 -> 160 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/switch-icon@2x.pngbin0 -> 314 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/text-edit-icon.pngbin0 -> 150 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/text-edit-icon16.pngbin0 -> 169 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/text-edit-icon@2x.pngbin0 -> 193 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/text-icon.pngbin0 -> 126 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/text-icon16.pngbin0 -> 141 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/text-icon@2x.pngbin0 -> 156 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/text-input-icon.pngbin0 -> 158 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/text-input-icon16.pngbin0 -> 140 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/text-input-icon@2x.pngbin0 -> 170 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/textarea-icon.pngbin0 -> 149 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/textarea-icon16.pngbin0 -> 133 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/textarea-icon@2x.pngbin0 -> 163 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/textfield-icon.pngbin0 -> 154 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/textfield-icon16.pngbin0 -> 147 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/textfield-icon@2x.pngbin0 -> 172 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/timeline-16px.pngbin0 -> 389 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/timeline-animation-16px.pngbin0 -> 296 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/timer-16px.pngbin0 -> 339 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/timer-24px.pngbin0 -> 712 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/timer-24px@2x.pngbin0 -> 1305 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/toolbar-icon.pngbin0 -> 131 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/toolbar-icon16.pngbin0 -> 114 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/toolbar-icon@2x.pngbin0 -> 140 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/toolbutton-icon.pngbin0 -> 141 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/toolbutton-icon16.pngbin0 -> 128 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/toolbutton-icon@2x.pngbin0 -> 158 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/toolseparator-icon.pngbin0 -> 111 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/toolseparator-icon16.pngbin0 -> 123 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/toolseparator-icon@2x.pngbin0 -> 131 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/tumbler-icon.pngbin0 -> 132 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/tumbler-icon16.pngbin0 -> 127 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/tumbler-icon@2x.pngbin0 -> 153 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/video-16px.pngbin0 -> 216 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/video-24px.pngbin0 -> 286 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/video-24px@2x.pngbin0 -> 399 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/video-output-16px.pngbin0 -> 289 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/video-output-24px.pngbin0 -> 387 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/video-output-24px@2x.pngbin0 -> 610 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/webview-icon.pngbin0 -> 804 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/images/webview-icon16.pngbin0 -> 519 bytes
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/multimedia.metainfo84
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/qml.metainfo53
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/qtquickcontrols2.metainfo575
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/quick.metainfo (renamed from share/qtcreator/qmldesigner/propertyEditorQmlSources/quick.metainfo)406
-rw-r--r--share/qtcreator/qmldesigner/itemLibrary/quick3d.metainfo125
-rw-r--r--share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowserContextMenu.qml9
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/EffectsSection.qml490
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ItemPane.qml4
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/ColumnLayoutSpecifics.qml6
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/GridLayoutSpecifics.qml21
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/RowLayoutSpecifics.qml6
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/StackLayoutSpecifics.qml5
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/CheckBox.qml8
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/DoubleSpinBox.qml1
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/DynamicPropertiesSection.qml93
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FlagsComboBox.qml2
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/IconButton.qml34
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml199
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SpinBox.qml3
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/UrlChooser.qml5
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/InternalConstants.qml607
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml1
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/icons.ttfbin66460 -> 66776 bytes
-rw-r--r--share/qtcreator/qmldesigner/studio_templates/files/qtquickfile/file.qml.tpl1
-rw-r--r--share/qtcreator/qmldesigner/studio_templates/files/qtuiquickfile/file.qml.tpl1
-rw-r--r--share/qtcreator/qmldesigner/studio_templates/projects/application-3d/wizard.json81
-rw-r--r--share/qtcreator/qmldesigner/studio_templates/projects/application-extended-3d/Screen01.ui.qml.tpl2
-rw-r--r--share/qtcreator/qmldesigner/studio_templates/projects/application-extended-3d/wizard.json105
-rw-r--r--share/qtcreator/qmldesigner/studio_templates/projects/application/wizard.json91
-rw-r--r--share/qtcreator/qmldesigner/studio_templates/projects/common/CMakeLists.content.txt.tpl14
-rw-r--r--share/qtcreator/qmldesigner/studio_templates/projects/common/CMakeLists.imports.txt.tpl4
-rw-r--r--share/qtcreator/qmldesigner/studio_templates/projects/common/CMakeLists.main.txt.tpl56
-rw-r--r--share/qtcreator/qmldesigner/studio_templates/projects/common/app.qmlproject.tpl35
-rw-r--r--share/qtcreator/qmldesigner/studio_templates/projects/common/app_environment.h.tpl19
-rw-r--r--share/qtcreator/qmldesigner/studio_templates/projects/common/contentmodule.main.qml.tpl17
-rw-r--r--share/qtcreator/qmldesigner/studio_templates/projects/common/import_qml_plugins.h.tpl9
-rw-r--r--share/qtcreator/qmldesigner/studio_templates/projects/common/main.cpp.tpl37
-rw-r--r--share/qtcreator/qmldesigner/studio_templates/projects/common/main.qml8
-rw-r--r--share/qtcreator/qmldesigner/studio_templates/projects/common/qmlmodules.tpl18
-rw-r--r--share/qtcreator/qmldesigner/studio_templates/projects/common/qtquickcontrols2.conf23
-rw-r--r--share/qtcreator/qmldesigner/studio_templates/projects/desktop-launcher/wizard.json70
-rw-r--r--share/qtcreator/qmldesigner/studio_templates/projects/mobile-scroll/wizard.json79
-rw-r--r--share/qtcreator/qmldesigner/studio_templates/projects/mobile-stack/wizard.json81
-rw-r--r--share/qtcreator/qmldesigner/studio_templates/projects/mobile-swipe/wizard.json81
-rw-r--r--share/qtcreator/qmldesigner/studio_templates/projects/shared-plugin/name/Constants.qml.tpl2
-rw-r--r--share/qtcreator/qmldesigner/studio_templates/projects/shared-plugin/name/DirectoryFontLoader.qml.tpl2
-rw-r--r--share/qtcreator/qmldesigner/toolbar/Main.qml20
-rw-r--r--share/qtcreator/qmldesigner/welcomepage/MainGridStack.qml12
m---------src/libs/3rdparty/googletest0
-rw-r--r--src/libs/3rdparty/sqlite/sqlite3.c484
-rw-r--r--src/libs/3rdparty/sqlite/sqlite3.h25
-rw-r--r--src/libs/languageutils/componentversion.cpp63
-rw-r--r--src/libs/languageutils/componentversion.h61
-rw-r--r--src/libs/nanotrace/CMakeLists.txt1
-rw-r--r--src/libs/nanotrace/nanotracehr.cpp56
-rw-r--r--src/libs/nanotrace/nanotracehr.h362
-rw-r--r--src/libs/nanotrace/staticstring.h116
-rw-r--r--src/libs/qmljs/CMakeLists.txt1
-rw-r--r--src/libs/qmljs/qmljs.qbs1
-rw-r--r--src/libs/qmljs/qmljsindenter.cpp603
-rw-r--r--src/libs/qmljs/qmljsindenter.h51
-rw-r--r--src/libs/qmljs/qmljsstaticanalysismessage.cpp5
-rw-r--r--src/libs/qmlpuppetcommunication/container/imagecontainer.cpp9
-rw-r--r--src/libs/sqlite/CMakeLists.txt4
-rw-r--r--src/libs/sqlite/sqlitebasestatement.cpp203
-rw-r--r--src/libs/sqlite/sqlitebasestatement.h82
-rw-r--r--src/libs/sqlite/sqliteexception.cpp30
-rw-r--r--src/libs/sqlite/sqliteexception.h9
-rw-r--r--src/libs/sqlite/sqliteids.h11
-rw-r--r--src/libs/sqlite/sqliteindex.h19
-rw-r--r--src/libs/sqlite/sqlitetracing.cpp38
-rw-r--r--src/libs/sqlite/sqlitetracing.h29
-rw-r--r--src/libs/sqlite/sqlitevalue.h62
-rw-r--r--src/libs/utils/smallstring.h113
-rw-r--r--src/plugins/android/androidmanager.cpp2
-rw-r--r--src/plugins/coreplugin/icore.cpp1
-rw-r--r--src/plugins/effectcomposer/compositionnode.cpp3
-rw-r--r--src/plugins/effectcomposer/compositionnode.h3
-rw-r--r--src/plugins/effectcomposer/effectcomposermodel.cpp221
-rw-r--r--src/plugins/effectcomposer/effectcomposermodel.h15
-rw-r--r--src/plugins/effectcomposer/effectcomposeruniformsmodel.cpp12
-rw-r--r--src/plugins/effectcomposer/effectcomposeruniformsmodel.h1
-rw-r--r--src/plugins/effectcomposer/effectcomposerview.cpp82
-rw-r--r--src/plugins/effectcomposer/effectcomposerview.h5
-rw-r--r--src/plugins/effectcomposer/uniform.cpp6
-rw-r--r--src/plugins/qmldesigner/.clang-format2
-rw-r--r--src/plugins/qmldesigner/CMakeLists.txt9
-rw-r--r--src/plugins/qmldesigner/components/assetslibrary/assetslibraryiconprovider.cpp3
-rw-r--r--src/plugins/qmldesigner/components/assetslibrary/assetslibraryiconprovider.h3
-rw-r--r--src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp36
-rw-r--r--src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h25
-rw-r--r--src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp43
-rw-r--r--src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.h2
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectiondetails.cpp65
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectiondetailsmodel.cpp24
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectiondetailsmodel.h4
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectiondetailssortfiltermodel.cpp6
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectiondetailssortfiltermodel.h1
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.cpp13
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectionview.cpp144
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectionview.h18
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectionwidget.cpp28
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectionwidget.h12
-rw-r--r--src/plugins/qmldesigner/components/componentcore/dialogutils.cpp32
-rw-r--r--src/plugins/qmldesigner/components/componentcore/dialogutils.h17
-rw-r--r--src/plugins/qmldesigner/components/componentcore/layoutingridlayout.cpp4
-rw-r--r--src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.cpp4
-rw-r--r--src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp52
-rw-r--r--src/plugins/qmldesigner/components/componentcore/resourcegenerator.cpp4
-rw-r--r--src/plugins/qmldesigner/components/componentcore/theme.h1
-rw-r--r--src/plugins/qmldesigner/components/componentcore/viewmanager.cpp23
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibrarybundleimporter.cpp38
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibrarybundleimporter.h2
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.cpp11
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterial.h7
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.cpp23
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.cpp49
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h26
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.cpp10
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.h2
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.cpp34
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.h4
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.cpp423
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.h132
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp258
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h10
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp149
-rw-r--r--src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.h19
-rw-r--r--src/plugins/qmldesigner/components/createtexture.cpp3
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/curveeditor.cpp2
-rw-r--r--src/plugins/qmldesigner/components/curveeditor/curveeditortoolbar.cpp2
-rw-r--r--src/plugins/qmldesigner/components/edit3d/bakelightsdatamodel.cpp4
-rw-r--r--src/plugins/qmldesigner/components/edit3d/cameraspeedconfiguration.cpp10
-rw-r--r--src/plugins/qmldesigner/components/edit3d/cameraspeedconfiguration.h1
-rw-r--r--src/plugins/qmldesigner/components/edit3d/edit3dview.cpp18
-rw-r--r--src/plugins/qmldesigner/components/edit3d/edit3dview.h1
-rw-r--r--src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp10
-rw-r--r--src/plugins/qmldesigner/components/edit3d/snapconfiguration.cpp10
-rw-r--r--src/plugins/qmldesigner/components/edit3d/snapconfiguration.h1
-rw-r--r--src/plugins/qmldesigner/components/integration/designdocument.cpp5
-rw-r--r--src/plugins/qmldesigner/components/integration/designdocument.h3
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp51
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp8
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp18
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.h2
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp16
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h11
-rw-r--r--src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.cpp2
-rw-r--r--src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp20
-rw-r--r--src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.h2
-rw-r--r--src/plugins/qmldesigner/components/navigator/choosefrompropertylistdialog.cpp7
-rw-r--r--src/plugins/qmldesigner/components/navigator/nameitemdelegate.cpp6
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/dynamicpropertiesproxymodel.cpp6
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp21
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.h14
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp304
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.h43
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp207
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.h10
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.cpp234
-rw-r--r--src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.h35
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.cpp9
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelineanimationform.cpp4
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelineform.cpp4
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelineview.cpp7
-rw-r--r--src/plugins/qmldesigner/components/toolbar/toolbarbackend.cpp23
-rw-r--r--src/plugins/qmldesigner/components/toolbar/toolbarbackend.h4
-rw-r--r--src/plugins/qmldesigner/components/transitioneditor/transitioneditorview.cpp7
-rw-r--r--src/plugins/qmldesigner/components/transitioneditor/transitionform.cpp4
-rw-r--r--src/plugins/qmldesigner/componentsplugin/components.metainfo6
-rw-r--r--src/plugins/qmldesigner/designercore/generatedcomponentutils.cpp139
-rw-r--r--src/plugins/qmldesigner/designercore/generatedcomponentutils.h38
-rw-r--r--src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.cpp2
-rw-r--r--src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.h2
-rw-r--r--src/plugins/qmldesigner/designercore/imagecache/taskqueue.h41
-rw-r--r--src/plugins/qmldesigner/designercore/include/model.h10
-rw-r--r--src/plugins/qmldesigner/designercore/include/modelfwd.h2
-rw-r--r--src/plugins/qmldesigner/designercore/include/nodemetainfo.h8
-rw-r--r--src/plugins/qmldesigner/designercore/include/projectstorageids.h6
-rw-r--r--src/plugins/qmldesigner/designercore/include/qmlitemnode.h1
-rw-r--r--src/plugins/qmldesigner/designercore/include/rewriterview.h5
-rw-r--r--src/plugins/qmldesigner/designercore/include/subcomponentmanager.h2
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp61
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp28
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp16
-rw-r--r--src/plugins/qmldesigner/designercore/model/abstractview.cpp6
-rw-r--r--src/plugins/qmldesigner/designercore/model/bindingproperty.cpp3
-rw-r--r--src/plugins/qmldesigner/designercore/model/model.cpp39
-rw-r--r--src/plugins/qmldesigner/designercore/model/modelresourcemanagement.cpp3
-rw-r--r--src/plugins/qmldesigner/designercore/model/modelutils.cpp18
-rw-r--r--src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp8
-rw-r--r--src/plugins/qmldesigner/designercore/model/rewriterview.cpp21
-rw-r--r--src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp271
-rw-r--r--src/plugins/qmldesigner/designercore/model/texttomodelmerger.h6
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/commontypecache.h3
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/filestatus.h12
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/filesystem.h6
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorage.cpp4538
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h3695
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.cpp114
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.h27
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstoragefwd.h1
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorageinfotypes.h176
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h12
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstoragepathwatchertypes.h43
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstoragetypes.h442
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp516
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h39
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.cpp20
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h2
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.cpp94
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h7
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/sourcepath.h6
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/sourcepathcachetypes.h2
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/typeannotationreader.cpp14
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/typeannotationreader.h4
-rw-r--r--src/plugins/qmldesigner/designercore/tracing/qmldesignertracing.cpp54
-rw-r--r--src/plugins/qmldesigner/designercore/tracing/qmldesignertracing.h18
-rw-r--r--src/plugins/qmldesigner/documentmanager.cpp18
-rw-r--r--src/plugins/qmldesigner/documentmanager.h6
-rw-r--r--src/plugins/qmldesigner/documentwarningwidget.cpp5
-rw-r--r--src/plugins/qmldesigner/puppetenvironmentbuilder.cpp2
-rw-r--r--src/plugins/qmldesigner/qmldesignerconstants.h12
-rw-r--r--src/plugins/qmldesigner/qmldesignerprojectmanager.cpp80
-rw-r--r--src/plugins/qmldesigner/qtquickplugin/quick.metainfo2
-rw-r--r--src/plugins/qmldesigner/settingspage.cpp4
-rw-r--r--src/plugins/qmldesigner/utils/asset.cpp26
-rw-r--r--src/plugins/qmldesigner/utils/asset.h6
-rw-r--r--src/plugins/qmldesigner/utils/imageutils.cpp12
-rw-r--r--src/plugins/qmldesigner/utils/imageutils.h5
-rw-r--r--src/plugins/qmldesignerbase/utils/designerpaths.cpp4
-rw-r--r--src/plugins/qmlpreview/CMakeLists.txt2
-rw-r--r--src/plugins/qmlpreview/qmlpreviewplugin.cpp12
-rw-r--r--src/plugins/qmlprojectmanager/CMakeLists.txt10
-rw-r--r--src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.cpp12
-rw-r--r--src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.h3
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/boilerplate.qrc24
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/checkablefiletreeitem.cpp45
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/checkablefiletreeitem.h31
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakegenerator.cpp591
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakegenerator.h73
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialog.cpp168
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialog.h51
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialogtreemodel.cpp174
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialogtreemodel.h51
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverter.cpp422
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverter.h77
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverterdialog.cpp180
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverterdialog.h47
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakewriter.cpp258
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakewriter.h101
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakewriterv0.cpp180
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakewriterv0.h25
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakewriterv1.cpp185
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/cmakewriterv1.h25
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.cpp668
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.h80
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/generatecmakelistsconstants.h42
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/qmlprojectappmainqml.tpl14
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/qmlprojectenvheader.tpl11
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/qmlprojectmaincppheader.tpl8
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/qmlprojectmainqml.tpl6
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/qmlprojectmodulecmakelists.tpl12
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/qmlprojectmodules.tpl16
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/templates/cmakelists_txt_shared.tpl16
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/templates/cmakemodule_v1.tpl (renamed from src/plugins/qmlprojectmanager/cmakegen/gencmakemodule.tpl)3
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/templates/cmakeroot_v0.tpl (renamed from src/plugins/qmlprojectmanager/cmakegen/gencmakeroot.tpl)0
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/templates/cmakeroot_v1.tpl (renamed from src/plugins/qmlprojectmanager/cmakegen/qmlprojectmaincmakelists.tpl)28
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/templates/environment_h.tpl (renamed from share/qtcreator/qmldesigner/studio_templates/projects/common/import_qml_components_plugins.h.tpl)5
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/templates/import_qml_components_h.tpl (renamed from src/plugins/qmlprojectmanager/cmakegen/gencmakeheadercomponents.tpl)1
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/templates/insight.tpl (renamed from share/qtcreator/qmldesigner/studio_templates/projects/common/insight.tpl)0
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/templates/main_cpp_v0.tpl (renamed from src/plugins/qmlprojectmanager/cmakegen/qmlprojectmaincpp.tpl)0
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/templates/main_cpp_v1.tpl31
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/templates/qmlcomponents.tpl (renamed from share/qtcreator/qmldesigner/studio_templates/projects/common/qmlcomponents.tpl)2
-rw-r--r--src/plugins/qmlprojectmanager/cmakegen/templates/qtquickcontrols2_conf.tpl7
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectgen/qmlprojectgenerator.cpp4
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectmanager.qbs10
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectplugin.cpp9
-rw-r--r--src/plugins/remotelinux/linuxdevicetester.cpp1
-rw-r--r--src/plugins/studiowelcome/studiowelcomeplugin.cpp31
-rw-r--r--src/plugins/texteditor/texteditor.cpp5
-rw-r--r--src/tools/qml2puppet/editor3d_qt6.qrc2
-rw-r--r--src/tools/qml2puppet/mockfiles/images/crosshair.pngbin0 -> 172 bytes
-rw-r--r--src/tools/qml2puppet/mockfiles/images/crosshair@2x.pngbin0 -> 202 bytes
-rw-r--r--src/tools/qml2puppet/mockfiles/qt6/EditCameraController.qml37
-rw-r--r--src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.cpp85
-rw-r--r--src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.h8
-rw-r--r--src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceserver.cpp12
-rw-r--r--src/tools/qml2puppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp22
-rw-r--r--src/tools/qml2puppet/qml2puppet/instances/qt5rendernodeinstanceserver.h1
-rw-r--r--src/tools/qml2puppet/qml2puppet/instances/quickitemnodeinstance.cpp20
-rw-r--r--src/tools/qml2puppet/qml2puppet/instances/servernodeinstance.cpp21
-rw-r--r--src/tools/qml2puppet/qmlprivategate/qmlprivategate.cpp503
-rw-r--r--tests/system/objects.map18
-rw-r--r--tests/system/settings/windows/QtProject/qtcreator/debuggers.xml19
-rw-r--r--tests/system/settings/windows/QtProject/qtcreator/profiles.xml3
-rw-r--r--tests/system/shared/project.py2
-rw-r--r--tests/system/shared/qtcreator.py26
-rw-r--r--tests/system/suite_debugger/tst_debug_empty_main/test.py3
-rw-r--r--tests/system/suite_tools/tst_git_first_commit/test.py2
-rw-r--r--tests/system/suite_tools/tst_git_local/test.py6
-rw-r--r--tests/unit/.clang-format2
-rw-r--r--tests/unit/tests/matchers/projectstorage-matcher.h21
-rw-r--r--tests/unit/tests/matchers/unittest-matchers.h68
-rw-r--r--tests/unit/tests/mocks/mocksqlitestatement.h2
-rw-r--r--tests/unit/tests/mocks/projectstoragemock.cpp41
-rw-r--r--tests/unit/tests/mocks/projectstoragemock.h54
-rw-r--r--tests/unit/tests/printers/gtest-creator-printing.cpp7
-rw-r--r--tests/unit/tests/stubs/qmldesigner/designercore/include/rewriterview.h2
-rw-r--r--tests/unit/tests/unittests/componentcore/propertyeditorcomponentgenerator-test.cpp2
-rw-r--r--tests/unit/tests/unittests/imagecache/taskqueue-test.cpp18
-rw-r--r--tests/unit/tests/unittests/model/model-test.cpp16
-rw-r--r--tests/unit/tests/unittests/model/modelresourcemanagement-test.cpp1
-rw-r--r--tests/unit/tests/unittests/model/modelutils-test.cpp2
-rw-r--r--tests/unit/tests/unittests/model/nodelistproperty-test.cpp4
-rw-r--r--tests/unit/tests/unittests/projectstorage/data/qml/QtQuick/Controls/designer/qtquickcontrols2.metainfo575
-rw-r--r--tests/unit/tests/unittests/projectstorage/data/qml/QtQuick3D/AssetUtils/designer/assetutils.metainfo21
-rw-r--r--tests/unit/tests/unittests/projectstorage/data/qml/QtQuick3D/Effects/designer/effectlib.metainfo401
-rw-r--r--tests/unit/tests/unittests/projectstorage/data/qml/QtQuick3D/Helpers/designer/helpers.metainfo261
-rw-r--r--tests/unit/tests/unittests/projectstorage/data/qml/QtQuick3D/ParticleEffects/designer/particleeffects.metainfo246
-rw-r--r--tests/unit/tests/unittests/projectstorage/data/qml/QtQuick3D/Particles3D/designer/particles3d.metainfo562
-rw-r--r--tests/unit/tests/unittests/projectstorage/data/qml/QtQuick3D/Physics/designer/physics.metainfo261
-rw-r--r--tests/unit/tests/unittests/projectstorage/data/qml/QtQuick3D/designer/quick3d.metainfo861
-rw-r--r--tests/unit/tests/unittests/projectstorage/projectstorage-test.cpp260
-rw-r--r--tests/unit/tests/unittests/projectstorage/projectstoragepathwatcher-test.cpp8
-rw-r--r--tests/unit/tests/unittests/projectstorage/projectstorageupdater-test.cpp291
-rw-r--r--tests/unit/tests/unittests/projectstorage/qmldocumentparser-test.cpp16
-rw-r--r--tests/unit/tests/unittests/projectstorage/qmltypesparser-test.cpp39
-rw-r--r--tests/unit/tests/unittests/projectstorage/typeannotationreader-test.cpp106
-rw-r--r--tests/unit/tests/unittests/sqlite/sqliteindex-test.cpp27
-rw-r--r--tests/unit/tests/unittests/sqlite/sqlitetable-test.cpp48
-rw-r--r--tests/unit/tests/unittests/utils/smallstring-test.cpp42
718 files changed, 20618 insertions, 11594 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9b4d1cca51..7005752acb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -166,7 +166,9 @@ endif()
add_subdirectory(src)
add_subdirectory(share)
-add_subdirectory(dist)
+if (NOT BUILD_DESIGNSTUDIO)
+ add_subdirectory(dist)
+endif()
if (WITH_TESTS)
add_subdirectory(tests)
diff --git a/cmake/QtCreatorAPIInternal.cmake b/cmake/QtCreatorAPIInternal.cmake
index 08167535e3..0cd3602d54 100644
--- a/cmake/QtCreatorAPIInternal.cmake
+++ b/cmake/QtCreatorAPIInternal.cmake
@@ -338,12 +338,18 @@ function(add_qtc_depends target_name)
foreach(obj_lib IN LISTS object_lib_depends)
target_compile_options(${target_name} PRIVATE $<TARGET_PROPERTY:${obj_lib},INTERFACE_COMPILE_OPTIONS>)
target_compile_definitions(${target_name} PRIVATE $<TARGET_PROPERTY:${obj_lib},INTERFACE_COMPILE_DEFINITIONS>)
- target_include_directories(${target_name} PRIVATE $<TARGET_PROPERTY:${obj_lib},INTERFACE_INCLUDE_DIRECTORIES>)
+ if (obj_lib MATCHES "Qt::.*|GoogleTest")
+ set(system_include "SYSTEM")
+ endif()
+ target_include_directories(${target_name} ${system_include} PRIVATE $<TARGET_PROPERTY:${obj_lib},INTERFACE_INCLUDE_DIRECTORIES>)
endforeach()
foreach(obj_lib IN LISTS object_public_depends)
target_compile_options(${target_name} PUBLIC $<TARGET_PROPERTY:${obj_lib},INTERFACE_COMPILE_OPTIONS>)
target_compile_definitions(${target_name} PUBLIC $<TARGET_PROPERTY:${obj_lib},INTERFACE_COMPILE_DEFINITIONS>)
- target_include_directories(${target_name} PUBLIC $<TARGET_PROPERTY:${obj_lib},INTERFACE_INCLUDE_DIRECTORIES>)
+ if (obj_lib MATCHES "Qt::.*|GoogleTest")
+ set(system_include "SYSTEM")
+ endif()
+ target_include_directories(${target_name} ${system_include} PUBLIC $<TARGET_PROPERTY:${obj_lib},INTERFACE_INCLUDE_DIRECTORIES>)
endforeach()
endfunction()
diff --git a/doc/qtcreator/src/debugger/qtquick-debugger-example.qdoc b/doc/qtcreator/src/debugger/qtquick-debugger-example.qdoc
index 30aa5c1358..e7141a99f2 100644
--- a/doc/qtcreator/src/debugger/qtquick-debugger-example.qdoc
+++ b/doc/qtcreator/src/debugger/qtquick-debugger-example.qdoc
@@ -33,7 +33,7 @@
\if defined(qtdesignstudio)
\note In this tutorial, you are using advanced menu items. These are not
visible by default. To toggle the visibility of advanced menu items, see
- \l{Customizing the Menu}.
+ \l{Customizing the Menu Bar}.
\endif
diff --git a/doc/qtcreator/src/debugger/qtquick-debugging.qdoc b/doc/qtcreator/src/debugger/qtquick-debugging.qdoc
index 7ed5365595..77f54e858f 100644
--- a/doc/qtcreator/src/debugger/qtquick-debugging.qdoc
+++ b/doc/qtcreator/src/debugger/qtquick-debugging.qdoc
@@ -35,7 +35,7 @@
\if defined(qtdesignstudio)
\note In this section, you are using advanced menu items. These are not
visible by default. To toggle the visibility of advanced menu items, see
- \l{Customizing the Menu}.
+ \l{Customizing the Menu Bar}.
\endif
\section1 Setting Up QML Debugging
diff --git a/doc/qtcreator/src/external-resources/external-resources-qds.qdoc b/doc/qtcreator/src/external-resources/external-resources-qds.qdoc
index d5b7fcf1bd..2a340b9ea9 100644
--- a/doc/qtcreator/src/external-resources/external-resources-qds.qdoc
+++ b/doc/qtcreator/src/external-resources/external-resources-qds.qdoc
@@ -69,3 +69,39 @@
\externalpage https://www.qt.io/download
\title Try Qt
*/
+/*!
+ \externalpage https://doc.qt.io/qt-5/custom-material-reference.html
+ \title Qt Quick 3D Custom Material Reference
+*/
+/*!
+ \externalpage https://doc.qt.io/qt-5/qml-qtquick3d-arealight.html
+ \title AreaLight
+*/
+/*!
+ \externalpage https://doc.qt.io/qt-5/qml-qtquick3d-shaderinfo.html
+ \title ShaderInfo
+*/
+/*!
+ \externalpage https://doc.qt.io/qt-5/qml-qtquick3d-bufferblit.html
+ \title BufferBlit
+*/
+/*!
+ \externalpage https://doc.qt.io/qt-5/qml-qtquick3d-cullmode.html
+ \title CullMode
+*/
+/*!
+ \externalpage https://doc.qt.io/qt-5/qml-qtquick3d-depthinput.html
+ \title DepthInput
+*/
+/*!
+ \externalpage https://doc.qt.io/qt-5/qml-qtquick3d-renderstate.html
+ \title RenderState
+*/
+/*!
+ \externalpage https://doc.qt.io/qt/i18n-source-translation.html#mark-strings-for-translation
+ \title Mark Strings for Translation
+*/
+/*!
+ \externalpage https://doc.qt.io/qt/linguist-id-based-i18n.html
+ \title Text ID based translations
+*/
diff --git a/doc/qtcreator/src/qtquick/qtquick-profiler.qdoc b/doc/qtcreator/src/qtquick/qtquick-profiler.qdoc
index b0508fe8cb..bd0985e312 100644
--- a/doc/qtcreator/src/qtquick/qtquick-profiler.qdoc
+++ b/doc/qtcreator/src/qtquick/qtquick-profiler.qdoc
@@ -27,7 +27,7 @@
\if defined(qtdesignstudio)
\note In this section, you are using advanced menu items. These are not
visible by default. To toggle the visibility of advanced menu items, see
- \l{Customizing the Menu}.
+ \l{Customizing the Menu Bar}.
\endif
diff --git a/doc/qtcreator/src/user-interface/creator-file-system-view.qdoc b/doc/qtcreator/src/user-interface/creator-file-system-view.qdoc
index ba666b35cc..a8ce9dbb5a 100644
--- a/doc/qtcreator/src/user-interface/creator-file-system-view.qdoc
+++ b/doc/qtcreator/src/user-interface/creator-file-system-view.qdoc
@@ -1,4 +1,4 @@
-// Copyright (C) 2023 The Qt Company Ltd.
+// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
@@ -15,7 +15,11 @@
\title File System
+ \if defined(qtdesignstudio)
+ \brief View all the files in the current directory.
+ \else
\brief Shows all the files in the current directory.
+ \endif
\if defined(qtcreator)
\note Usually, \l{Navigate with locator}{searching with the locator}
@@ -25,7 +29,7 @@
\image qtcreator-filesystem-view.webp {File System view in the sidebar}
\else
- \image qtcreator-filesystem-view-design.webp {File System view}
+ \image filesystem-view-design.webp {File System view}
\endif
To go to the root directory of the file system, select \uicontrol Computer
@@ -52,6 +56,7 @@
The view displays the path to the active file as bread crumbs. You can move
to any directory along the path by clicking it.
+ \if defined(qtcreator)
\section1 File System Context Menu
Use the context menu functions to:
@@ -64,34 +69,24 @@
that has the file. To specify the terminal to use on Linux and
\macos, select \preferences > \uicontrol Environment >
\uicontrol System.
- \if defined(qtcreator)
To use an \l{Terminal} {internal terminal}, select \preferences >
\uicontrol Terminal > \uicontrol {Use internal terminal}.
- \endif
\li Search in the selected directory.
\li View file properties, such as name, path, MIME type, default editor,
line endings, indentation, owner, size, last read and modified
dates, and permissions.
- \li Create new files. For more information, see
- \if defined(qtdesignstudio)
- \l{Adding Files to Projects}.
- \else
- \l{Create files}.
- \endif
+ \li Create new files. For more information, see {Create files}.
\li Rename existing files. To move the file to another directory, enter
the relative or absolute path to its new location in addition to the
new filename.
\li Remove existing files.
\li Create new folders.
- \if defined(qtcreator)
\li Compare the selected file with the currently open file in the diff
editor. For more information, see \l{Compare files}.
- \endif
\li Display the contents of a particular directory in the view.
\li Collapse all open folders.
\endlist
- \if defined(qtcreator)
\section1 File System View Toolbar
The toolbar in the \uicontrol {File System} view has additional
diff --git a/doc/qtcreator/src/user-interface/creator-open-documents-view.qdoc b/doc/qtcreator/src/user-interface/creator-open-documents-view.qdoc
index 87760c448c..67c0134c78 100644
--- a/doc/qtcreator/src/user-interface/creator-open-documents-view.qdoc
+++ b/doc/qtcreator/src/user-interface/creator-open-documents-view.qdoc
@@ -1,4 +1,4 @@
-// Copyright (C) 2023 The Qt Company Ltd.
+// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
@@ -16,13 +16,26 @@
\title Open Documents
+ \if defined(qtdesignstudio)
+ \brief View currently open files.
+ \else
\brief Shows currently open files.
+ \endif
+ \if defined(qtdesignstudio)
+ \image open-documents-view.webp {Open Documents view}
+ \else
\image qtcreator-open-documents-view.png {Open Documents view}
+ \endif
You can use the context menu to apply some of the functions also available
- in the \uicontrol File menu and in the \l {File System Context Menu}
- {File System} view to the file that you select in the view.
+ in the \uicontrol File menu and in the
+ \if defined(qtcreator)
+ \l {File System Context Menu}{File System}
+ \else
+ \uicontrol {File System}
+ \endif
+ view to the file that you select in the view.
In addition, you can:
diff --git a/doc/qtcreator/src/user-interface/creator-projects-view.qdoc b/doc/qtcreator/src/user-interface/creator-projects-view.qdoc
index b6b74f0993..d28e6f9ef0 100644
--- a/doc/qtcreator/src/user-interface/creator-projects-view.qdoc
+++ b/doc/qtcreator/src/user-interface/creator-projects-view.qdoc
@@ -1,4 +1,4 @@
-// Copyright (C) 2023 The Qt Company Ltd.
+// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
@@ -15,7 +15,11 @@
\title Projects
+ \if defined(qtdesignstudio)
+ \brief View a list of the files contained within the open project.
+ \else
\brief Shows a list of projects in a project tree.
+ \endif
\if defined(qtcreator)
The project tree has a list of all projects open in the current
@@ -29,7 +33,7 @@
is the fastest way to find a particular project, file, class, or function,
or almost anything else in your project.
\else
- \image qtcreator-projects-view-design.png {Projects view}
+ \image projects-view-design.webp {Projects view}
\endif
You can use the project tree in the following ways:
@@ -43,14 +47,19 @@
Use the \l{Switch between modes} {mode selector} to open the current
file in another editor.
\endif
- \li To bring up a \l{Projects View Context Menu}{context menu}
+ \li To open a
+ \if defined(qtcreator)
+ \l{Projects View Context Menu}{context menu}
+ \else
+ context menu
+ \endif
that has the actions most commonly needed, right-click an
item in the project tree. For example, through the menu of
the project root directory you can, among other actions, run
and close the project.
\li To see the absolute path of a file, move the mouse pointer over the
file name.
- \li To move files from one project to another, drag-and-drop them
+ \li To move files from one project to another, drag them
in the project tree. \QC makes the necessary changes to project
configuration files.
\endlist
@@ -58,6 +67,7 @@
\note If you cannot see a file in the \l Projects view, switch to the
\uicontrol {File System} view, which shows all the files in the file system.
+ \if defined(qtcreator)
\section1 Projects View Context Menu
The \uicontrol Projects view has context menus for managing projects,
@@ -65,22 +75,15 @@
projects and subprojects:
\list
- \if defined(qtcreator)
\li Set a project as the active project.
- \endif
\li Execute \uicontrol Build menu commands.
\li Create new files. For more information, see
- \if defined(qtdesignstudio)
- \l{Adding Files to Projects}.
- \else
\l{Create files}.
- \endif
\li Rename existing files. If you change the base name of a
file, \QC displays a list of other files with the same base name
and offers to rename them as well. If you rename a UI file (.ui),
\QC also changes corresponding include statements accordingly.
\li Remove existing files.
- \if defined(qtcreator)
\li Remove existing directories from \l{Import an existing project}
{generic projects}.
\li Add existing files and directories.
@@ -88,16 +91,13 @@
\l{Add libraries to qmake projects}.
\li Add and remove subprojects.
\li Find unused functions.
- \endif
\li Search in the selected directory.
\li Open a terminal window in the project directory. To specify the
terminal to use on Linux and \macos, select \preferences >
\uicontrol Environment > \uicontrol System.
- \if defined(qtcreator)
To use an \l{Terminal}{internal terminal}, select \preferences >
\uicontrol Terminal > \uicontrol {Use internal terminal}.
- \endif
\li Open a terminal window in the project directory that you configured
for building or running the project.
\li Expand or collapse the tree view to show or hide all files and
@@ -114,7 +114,6 @@
the \l {File System} view. To view a project in it, select
\uicontrol {Show in File System View}.
- \if defined(qtcreator)
\section1 Projects View Toolbar
The toolbar in the \uicontrol Projects view has additional options.
diff --git a/doc/qtcreator/src/user-interface/creator-ui.qdoc b/doc/qtcreator/src/user-interface/creator-ui.qdoc
index 9041e6432f..9794667f5b 100644
--- a/doc/qtcreator/src/user-interface/creator-ui.qdoc
+++ b/doc/qtcreator/src/user-interface/creator-ui.qdoc
@@ -95,7 +95,7 @@
\endif
\if defined(qtdesignstudio)
- \section1 Customizing the Menu
+ \section1 Customizing the Menu Bar
By default, top-level menu items \uicontrol Build, \uicontrol Debug, and
\uicontrol Analyze are not visible. These menu items have options for
@@ -113,6 +113,9 @@
You need to restart \QDS to apply changes made to these settings.
+ \note To show or hide the \uicontrol {Menu Bar}, select \uicontrol View >
+ \uicontrol {Show Menu Bar}, or use \key {Ctrl+Alt+M}.
+
\section1 Customizing the UI
The following topics describe how to customize the UI:
diff --git a/doc/qtcreator/src/vcs/creator-vcs-git.qdoc b/doc/qtcreator/src/vcs/creator-vcs-git.qdoc
index ea23e53443..e853a86812 100644
--- a/doc/qtcreator/src/vcs/creator-vcs-git.qdoc
+++ b/doc/qtcreator/src/vcs/creator-vcs-git.qdoc
@@ -30,10 +30,6 @@
You can use the \l{http://code.google.com/p/gerrit/}{Gerrit} code review
tool for projects that use Git.
- \if defined(qtdesignstudio)
- \include creator-vcs-options.qdocinc vcs options
- \endif
-
\if defined(qtcreator)
\section1 Using Git for Windows
diff --git a/doc/qtdesignstudio/config/qtdesignstudio.qdocconf b/doc/qtdesignstudio/config/qtdesignstudio.qdocconf
index 72b38940f7..95d1475cf1 100644
--- a/doc/qtdesignstudio/config/qtdesignstudio.qdocconf
+++ b/doc/qtdesignstudio/config/qtdesignstudio.qdocconf
@@ -120,4 +120,9 @@ macro.function = "\\fn"
macro.QMLD = "Qt Design Studio"
navigation.landingpage = "$IDE_DISPLAY_NAME Manual"
+
+# Auto-generate navigation linking based on "All Topics":
+navigation.toctitles = "All Topics"
+navigation.toctitles.inclusive = false
+
buildversion = "$IDE_DISPLAY_NAME Manual $QTC_VERSION"
diff --git a/doc/qtdesignstudio/examples/doc/FresnelExample.qdoc b/doc/qtdesignstudio/examples/doc/FresnelExample.qdoc
new file mode 100644
index 0000000000..8dbc8bcfbf
--- /dev/null
+++ b/doc/qtdesignstudio/examples/doc/FresnelExample.qdoc
@@ -0,0 +1,90 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \page fresnel-effect-example.html
+ \ingroup studioexamples
+
+ \title Fresnel Example
+ \brief Illustrates how to work with the fresnel effect.
+
+ \image fresnel-example.webp
+
+ The \e{Fresnel} example illustrates how to add and adjust a fresnel effect on
+ a 3D model.
+
+ The fresnel effect affects how materials reflect light at different viewing angles. Imagine the
+ water on a lake. If you look down at the water from straight above, you can see through the
+ water, but if you look from a lower angle, the reflections are stronger.
+
+ \image fresnel-angle.webp
+
+ \section1 Running the Example
+
+ To run the example in \QDS, go to the \uicontrol Welcome screen and select the example
+ from the \uicontrol Examples tab.
+
+ \section1 The 3D Scene
+
+ The example project consists of a basic 3D scene with the following components:
+
+ \list
+ \li A 3D model.
+ \li A directional light.
+ \li An HDR image used to light the scene (image-based lighting).
+ \endlist
+
+ \section1 The Material
+
+ The material on the 3D model in this example is a principled material with a
+ clearcoat.
+
+ \section2 Clearcoat
+
+ A clearcoat is an additional specular layer applied to the surface of a material. The
+ clearcoating is transparent and doesn't add any color to the material, but it affects
+ how light interacts with the material.
+
+ You adjust clearcoat properties independently from the base material.
+
+ \section2 Fresnel Properties
+
+ The following properties affect how the fresnel effect renders. These properties are
+ available both for the base material and the clearcoat layer. Adjusting the settings for the
+ clearcoat has a bigger visual effect.
+
+ \table
+ \header
+ \li Property
+ \li Description
+ \row
+ \li Fresnel power
+ \li Increasing the fresnel power decreases the head-on reflections (steep viewing angle)
+ while maintaining the reflections seen from more shallow viewing angles.
+ \row
+ \li Enable scale and bias
+ \li Takes the scale and bias properties into account.
+ \row
+ \li Scale
+ \li Determines the rate of change in reflection intensity as the viewing angle varies. A
+ large scale value results in a gentler transition between weak and strong reflections, while
+ a smaller scale creates a more abrupt shift in reflection intensity.
+ \row
+ \li Bias
+ \li Controls the offset for the fresnel power property and determines how quickly the
+ reflection transitions from weak to strong as the viewing
+ angle changes. A larger bias value shifts the transition point toward steeper angles.
+ \endtable
+
+ \section3 Adjusting the Fresnel Settings
+
+ To adjust the settings:
+
+ \list 1
+ \li In \uicontrol {Material Browser}, double-click \e {Monkey Material}.
+ \li In \uicontrol {Material Editor}, find the properties under
+ \uicontrol {Clearcoat} and \uicontrol {Fresnel} respectively.
+ \endlist
+
+ \note You see the changes live as you edit them in the \uicontrol 2D view.
+*/
diff --git a/doc/qtdesignstudio/examples/doc/images/fresnel-angle.webp b/doc/qtdesignstudio/examples/doc/images/fresnel-angle.webp
new file mode 100644
index 0000000000..2fe11380f0
--- /dev/null
+++ b/doc/qtdesignstudio/examples/doc/images/fresnel-angle.webp
Binary files differ
diff --git a/doc/qtdesignstudio/examples/doc/images/fresnel-example.webp b/doc/qtdesignstudio/examples/doc/images/fresnel-example.webp
new file mode 100644
index 0000000000..75436595aa
--- /dev/null
+++ b/doc/qtdesignstudio/examples/doc/images/fresnel-example.webp
Binary files differ
diff --git a/doc/qtdesignstudio/examples/doc/rainSnowParticles.qdoc b/doc/qtdesignstudio/examples/doc/rainSnowParticles.qdoc
index 88dbd5fbdb..5cc040d427 100644
--- a/doc/qtdesignstudio/examples/doc/rainSnowParticles.qdoc
+++ b/doc/qtdesignstudio/examples/doc/rainSnowParticles.qdoc
@@ -41,7 +41,7 @@
Now you have added a particle system to your scene.
- \image rain-snow-tutorial-particle-system
+ \image rain-snow-tutorial-particle-system.png
\section2 Adjusting the Behavior and Apperance of the Particle System
Next, you adjust the position, behavior, and apperance of the particle
diff --git a/doc/qtdesignstudio/images/3d-view-context-menu.png b/doc/qtdesignstudio/images/3d-view-context-menu.png
deleted file mode 100644
index 5b08c568cb..0000000000
--- a/doc/qtdesignstudio/images/3d-view-context-menu.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtdesignstudio/images/3d-view-context-menu.webp b/doc/qtdesignstudio/images/3d-view-context-menu.webp
new file mode 100644
index 0000000000..1b58f9bded
--- /dev/null
+++ b/doc/qtdesignstudio/images/3d-view-context-menu.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/camera-look-at-node.webp b/doc/qtdesignstudio/images/camera-look-at-node.webp
new file mode 100644
index 0000000000..e5a92308a3
--- /dev/null
+++ b/doc/qtdesignstudio/images/camera-look-at-node.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/edit-list-model-model-editor.webp b/doc/qtdesignstudio/images/edit-list-model-model-editor.webp
new file mode 100644
index 0000000000..e7f47c6402
--- /dev/null
+++ b/doc/qtdesignstudio/images/edit-list-model-model-editor.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/filesystem-view-design.webp b/doc/qtdesignstudio/images/filesystem-view-design.webp
new file mode 100644
index 0000000000..8d59b85482
--- /dev/null
+++ b/doc/qtdesignstudio/images/filesystem-view-design.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/icons/add_material.png b/doc/qtdesignstudio/images/icons/add_material.png
new file mode 100644
index 0000000000..6ecb64a180
--- /dev/null
+++ b/doc/qtdesignstudio/images/icons/add_material.png
Binary files differ
diff --git a/doc/qtdesignstudio/images/icons/add_texture.png b/doc/qtdesignstudio/images/icons/add_texture.png
new file mode 100644
index 0000000000..8b94da637d
--- /dev/null
+++ b/doc/qtdesignstudio/images/icons/add_texture.png
Binary files differ
diff --git a/doc/qtdesignstudio/images/icons/camera_speed.png b/doc/qtdesignstudio/images/icons/camera_speed.png
new file mode 100644
index 0000000000..6fcabb05c8
--- /dev/null
+++ b/doc/qtdesignstudio/images/icons/camera_speed.png
Binary files differ
diff --git a/doc/qtdesignstudio/images/icons/easing-curve-spline.png b/doc/qtdesignstudio/images/icons/easing-curve-spline.png
new file mode 100644
index 0000000000..d76bf15f21
--- /dev/null
+++ b/doc/qtdesignstudio/images/icons/easing-curve-spline.png
Binary files differ
diff --git a/doc/qtdesignstudio/images/icons/easing-curve-spline-icon.png b/doc/qtdesignstudio/images/icons/easing-curve-unify.png
index c5328bed8a..c5328bed8a 100644
--- a/doc/qtdesignstudio/images/icons/easing-curve-spline-icon.png
+++ b/doc/qtdesignstudio/images/icons/easing-curve-unify.png
Binary files differ
diff --git a/doc/qtdesignstudio/images/icons/export.png b/doc/qtdesignstudio/images/icons/export.png
new file mode 100644
index 0000000000..6d6f15bd4a
--- /dev/null
+++ b/doc/qtdesignstudio/images/icons/export.png
Binary files differ
diff --git a/doc/qtdesignstudio/images/icons/import.png b/doc/qtdesignstudio/images/icons/import.png
new file mode 100644
index 0000000000..b4ca149761
--- /dev/null
+++ b/doc/qtdesignstudio/images/icons/import.png
Binary files differ
diff --git a/doc/qtdesignstudio/images/icons/reverse_order.png b/doc/qtdesignstudio/images/icons/reverse_order.png
new file mode 100644
index 0000000000..5e661b29cc
--- /dev/null
+++ b/doc/qtdesignstudio/images/icons/reverse_order.png
Binary files differ
diff --git a/doc/qtdesignstudio/images/material-editor-browser.webp b/doc/qtdesignstudio/images/material-editor-browser.webp
index 160c96e877..1865bf8a54 100644
--- a/doc/qtdesignstudio/images/material-editor-browser.webp
+++ b/doc/qtdesignstudio/images/material-editor-browser.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/materials-remove-material.png b/doc/qtdesignstudio/images/materials-remove-material.png
deleted file mode 100644
index 9ef0a91e5b..0000000000
--- a/doc/qtdesignstudio/images/materials-remove-material.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtdesignstudio/images/materials-remove-material.webp b/doc/qtdesignstudio/images/materials-remove-material.webp
new file mode 100644
index 0000000000..64d1d19891
--- /dev/null
+++ b/doc/qtdesignstudio/images/materials-remove-material.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/model-editor-new-model.webp b/doc/qtdesignstudio/images/model-editor-new-model.webp
new file mode 100644
index 0000000000..6ea705a047
--- /dev/null
+++ b/doc/qtdesignstudio/images/model-editor-new-model.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/navigator-material-texture.png b/doc/qtdesignstudio/images/navigator-material-texture.png
deleted file mode 100644
index 849625e1eb..0000000000
--- a/doc/qtdesignstudio/images/navigator-material-texture.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtdesignstudio/images/navigator-material-texture.webp b/doc/qtdesignstudio/images/navigator-material-texture.webp
new file mode 100644
index 0000000000..5ac9152627
--- /dev/null
+++ b/doc/qtdesignstudio/images/navigator-material-texture.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/open-documents-view.webp b/doc/qtdesignstudio/images/open-documents-view.webp
new file mode 100644
index 0000000000..c3080b92b5
--- /dev/null
+++ b/doc/qtdesignstudio/images/open-documents-view.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/projects-view-design.webp b/doc/qtdesignstudio/images/projects-view-design.webp
new file mode 100644
index 0000000000..6fd1e6333c
--- /dev/null
+++ b/doc/qtdesignstudio/images/projects-view-design.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/qmldesigner-canvas-color.png b/doc/qtdesignstudio/images/qmldesigner-canvas-color.png
deleted file mode 100644
index 6baef3eb90..0000000000
--- a/doc/qtdesignstudio/images/qmldesigner-canvas-color.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtdesignstudio/images/qmldesigner-canvas-color.webp b/doc/qtdesignstudio/images/qmldesigner-canvas-color.webp
new file mode 100644
index 0000000000..3474076844
--- /dev/null
+++ b/doc/qtdesignstudio/images/qmldesigner-canvas-color.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/qmldesigner-element-properties.png b/doc/qtdesignstudio/images/qmldesigner-element-properties.png
deleted file mode 100644
index 0a8c4a1041..0000000000
--- a/doc/qtdesignstudio/images/qmldesigner-element-properties.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtdesignstudio/images/qmldesigner-element-properties.webp b/doc/qtdesignstudio/images/qmldesigner-element-properties.webp
new file mode 100644
index 0000000000..a90062d6be
--- /dev/null
+++ b/doc/qtdesignstudio/images/qmldesigner-element-properties.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/qmldesigner-form-editor-move-cursor.png b/doc/qtdesignstudio/images/qmldesigner-form-editor-move-cursor.png
deleted file mode 100644
index 018a94c88f..0000000000
--- a/doc/qtdesignstudio/images/qmldesigner-form-editor-move-cursor.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtdesignstudio/images/qmldesigner-form-editor-move-cursor.webp b/doc/qtdesignstudio/images/qmldesigner-form-editor-move-cursor.webp
new file mode 100644
index 0000000000..a1b7f83e8d
--- /dev/null
+++ b/doc/qtdesignstudio/images/qmldesigner-form-editor-move-cursor.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/qmldesigner-form-editor.png b/doc/qtdesignstudio/images/qmldesigner-form-editor.png
deleted file mode 100644
index f32f6965ba..0000000000
--- a/doc/qtdesignstudio/images/qmldesigner-form-editor.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtdesignstudio/images/qmldesigner-form-editor.webp b/doc/qtdesignstudio/images/qmldesigner-form-editor.webp
new file mode 100644
index 0000000000..b360c5c241
--- /dev/null
+++ b/doc/qtdesignstudio/images/qmldesigner-form-editor.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/qmldesigner-preview-size.png b/doc/qtdesignstudio/images/qmldesigner-preview-size.png
deleted file mode 100644
index 1a4a5e01ee..0000000000
--- a/doc/qtdesignstudio/images/qmldesigner-preview-size.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtdesignstudio/images/qmldesigner-preview-size.webp b/doc/qtdesignstudio/images/qmldesigner-preview-size.webp
new file mode 100644
index 0000000000..37f0c32ecf
--- /dev/null
+++ b/doc/qtdesignstudio/images/qmldesigner-preview-size.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/qmldesigner-snap-margins.png b/doc/qtdesignstudio/images/qmldesigner-snap-margins.png
deleted file mode 100644
index 703ed8cc9a..0000000000
--- a/doc/qtdesignstudio/images/qmldesigner-snap-margins.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtdesignstudio/images/qmldesigner-snap-margins.webp b/doc/qtdesignstudio/images/qmldesigner-snap-margins.webp
new file mode 100644
index 0000000000..c6ea462063
--- /dev/null
+++ b/doc/qtdesignstudio/images/qmldesigner-snap-margins.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/qmldesigner-transition-editor-startup.png b/doc/qtdesignstudio/images/qmldesigner-transition-editor-startup.png
deleted file mode 100644
index d269470e0d..0000000000
--- a/doc/qtdesignstudio/images/qmldesigner-transition-editor-startup.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtdesignstudio/images/qmldesigner-transition-editor-startup.webp b/doc/qtdesignstudio/images/qmldesigner-transition-editor-startup.webp
new file mode 100644
index 0000000000..a246e48411
--- /dev/null
+++ b/doc/qtdesignstudio/images/qmldesigner-transition-editor-startup.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/qmldesigner-transitions.webp b/doc/qtdesignstudio/images/qmldesigner-transitions.webp
new file mode 100644
index 0000000000..ca4aae53ff
--- /dev/null
+++ b/doc/qtdesignstudio/images/qmldesigner-transitions.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/qmldesigner-zooming.gif b/doc/qtdesignstudio/images/qmldesigner-zooming.gif
index d8d5beb6b3..82de8223be 100644
--- a/doc/qtdesignstudio/images/qmldesigner-zooming.gif
+++ b/doc/qtdesignstudio/images/qmldesigner-zooming.gif
Binary files differ
diff --git a/doc/qtdesignstudio/images/qtquick-assets-tab.png b/doc/qtdesignstudio/images/qtquick-assets-tab.png
deleted file mode 100644
index 11c4fe54b4..0000000000
--- a/doc/qtdesignstudio/images/qtquick-assets-tab.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtdesignstudio/images/qtquick-assets-tab.webp b/doc/qtdesignstudio/images/qtquick-assets-tab.webp
new file mode 100644
index 0000000000..2e65a7edd9
--- /dev/null
+++ b/doc/qtdesignstudio/images/qtquick-assets-tab.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/qtquick-designer-rotating-items.png b/doc/qtdesignstudio/images/qtquick-designer-rotating-items.png
deleted file mode 100644
index f20669be4e..0000000000
--- a/doc/qtdesignstudio/images/qtquick-designer-rotating-items.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtdesignstudio/images/qtquick-designer-rotating-items.webp b/doc/qtdesignstudio/images/qtquick-designer-rotating-items.webp
new file mode 100644
index 0000000000..17a3a664c0
--- /dev/null
+++ b/doc/qtdesignstudio/images/qtquick-designer-rotating-items.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/qtquick-designer-scaling-items.png b/doc/qtdesignstudio/images/qtquick-designer-scaling-items.png
deleted file mode 100644
index 891915dae8..0000000000
--- a/doc/qtdesignstudio/images/qtquick-designer-scaling-items.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtdesignstudio/images/qtquick-designer-scaling-items.webp b/doc/qtdesignstudio/images/qtquick-designer-scaling-items.webp
new file mode 100644
index 0000000000..cabbd7e02a
--- /dev/null
+++ b/doc/qtdesignstudio/images/qtquick-designer-scaling-items.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/qtquick-item-properties-common.png b/doc/qtdesignstudio/images/qtquick-item-properties-common.png
deleted file mode 100644
index 6311b1ce58..0000000000
--- a/doc/qtdesignstudio/images/qtquick-item-properties-common.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtdesignstudio/images/qtquick-item-properties-common.webp b/doc/qtdesignstudio/images/qtquick-item-properties-common.webp
new file mode 100644
index 0000000000..5177534146
--- /dev/null
+++ b/doc/qtdesignstudio/images/qtquick-item-properties-common.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/qtquick-library-context-menu.png b/doc/qtdesignstudio/images/qtquick-library-context-menu.png
deleted file mode 100644
index f611ea6f1c..0000000000
--- a/doc/qtdesignstudio/images/qtquick-library-context-menu.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtdesignstudio/images/qtquick-library-context-menu.webp b/doc/qtdesignstudio/images/qtquick-library-context-menu.webp
new file mode 100644
index 0000000000..32fce38c93
--- /dev/null
+++ b/doc/qtdesignstudio/images/qtquick-library-context-menu.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/qtquick-transition-editor-settings.png b/doc/qtdesignstudio/images/qtquick-transition-editor-settings.png
deleted file mode 100644
index a0fef65a51..0000000000
--- a/doc/qtdesignstudio/images/qtquick-transition-editor-settings.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtdesignstudio/images/qtquick-transition-editor-settings.webp b/doc/qtdesignstudio/images/qtquick-transition-editor-settings.webp
new file mode 100644
index 0000000000..71734e3eaa
--- /dev/null
+++ b/doc/qtdesignstudio/images/qtquick-transition-editor-settings.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/qtquick-transition-editor-view.png b/doc/qtdesignstudio/images/qtquick-transition-editor-view.png
deleted file mode 100644
index 3d747783af..0000000000
--- a/doc/qtdesignstudio/images/qtquick-transition-editor-view.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtdesignstudio/images/qtquick-transition-editor-view.webp b/doc/qtdesignstudio/images/qtquick-transition-editor-view.webp
new file mode 100644
index 0000000000..b409b5d57f
--- /dev/null
+++ b/doc/qtdesignstudio/images/qtquick-transition-editor-view.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/repeater3d-listmodel-navigator.png b/doc/qtdesignstudio/images/repeater3d-listmodel-navigator.png
index f4b3093bbb..302d7d397a 100644
--- a/doc/qtdesignstudio/images/repeater3d-listmodel-navigator.png
+++ b/doc/qtdesignstudio/images/repeater3d-listmodel-navigator.png
Binary files differ
diff --git a/doc/qtdesignstudio/images/repeater3d-model-editor.webp b/doc/qtdesignstudio/images/repeater3d-model-editor.webp
new file mode 100644
index 0000000000..e0e6087366
--- /dev/null
+++ b/doc/qtdesignstudio/images/repeater3d-model-editor.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/studio-3d-editor-axis-helper.webp b/doc/qtdesignstudio/images/studio-3d-editor-axis-helper.webp
index d0a13907e5..c1388d72ed 100644
--- a/doc/qtdesignstudio/images/studio-3d-editor-axis-helper.webp
+++ b/doc/qtdesignstudio/images/studio-3d-editor-axis-helper.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/studio-3d-editor-move.webp b/doc/qtdesignstudio/images/studio-3d-editor-move.webp
index d2ff9b9aac..ac40c5cf1a 100644
--- a/doc/qtdesignstudio/images/studio-3d-editor-move.webp
+++ b/doc/qtdesignstudio/images/studio-3d-editor-move.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/studio-3d-editor-rotate.webp b/doc/qtdesignstudio/images/studio-3d-editor-rotate.webp
index 7cd8fe1bf6..368a2d57fd 100644
--- a/doc/qtdesignstudio/images/studio-3d-editor-rotate.webp
+++ b/doc/qtdesignstudio/images/studio-3d-editor-rotate.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/studio-3d-editor-scale.webp b/doc/qtdesignstudio/images/studio-3d-editor-scale.webp
index be0270d34b..6523539449 100644
--- a/doc/qtdesignstudio/images/studio-3d-editor-scale.webp
+++ b/doc/qtdesignstudio/images/studio-3d-editor-scale.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/studio-3d-editor.webp b/doc/qtdesignstudio/images/studio-3d-editor.webp
index 903ad69b25..2218505917 100644
--- a/doc/qtdesignstudio/images/studio-3d-editor.webp
+++ b/doc/qtdesignstudio/images/studio-3d-editor.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/studio-3d-properties-type.png b/doc/qtdesignstudio/images/studio-3d-properties-type.png
deleted file mode 100644
index c0363d0233..0000000000
--- a/doc/qtdesignstudio/images/studio-3d-properties-type.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtdesignstudio/images/studio-3d-properties-type.webp b/doc/qtdesignstudio/images/studio-3d-properties-type.webp
new file mode 100644
index 0000000000..7f353ff655
--- /dev/null
+++ b/doc/qtdesignstudio/images/studio-3d-properties-type.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/studio-3d-scene-environment-ambient-occlusion.webp b/doc/qtdesignstudio/images/studio-3d-scene-environment-ambient-occlusion.webp
new file mode 100644
index 0000000000..91e01bc809
--- /dev/null
+++ b/doc/qtdesignstudio/images/studio-3d-scene-environment-ambient-occlusion.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/studio-3d-scene-environment-antialiasing.webp b/doc/qtdesignstudio/images/studio-3d-scene-environment-antialiasing.webp
new file mode 100644
index 0000000000..a8cae264d3
--- /dev/null
+++ b/doc/qtdesignstudio/images/studio-3d-scene-environment-antialiasing.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/studio-3d-scene-environment-image-based-lighting.webp b/doc/qtdesignstudio/images/studio-3d-scene-environment-image-based-lighting.webp
new file mode 100644
index 0000000000..d5a9da81fb
--- /dev/null
+++ b/doc/qtdesignstudio/images/studio-3d-scene-environment-image-based-lighting.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/studio-3d-scene-environment-light-probe.png b/doc/qtdesignstudio/images/studio-3d-scene-environment-light-probe.png
deleted file mode 100644
index 7a062a2a36..0000000000
--- a/doc/qtdesignstudio/images/studio-3d-scene-environment-light-probe.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtdesignstudio/images/studio-3d-scene-environment-properties.png b/doc/qtdesignstudio/images/studio-3d-scene-environment-properties.png
deleted file mode 100644
index 353e0c3584..0000000000
--- a/doc/qtdesignstudio/images/studio-3d-scene-environment-properties.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtdesignstudio/images/studio-3d-scene-environment-properties.webp b/doc/qtdesignstudio/images/studio-3d-scene-environment-properties.webp
new file mode 100644
index 0000000000..bb3e62d716
--- /dev/null
+++ b/doc/qtdesignstudio/images/studio-3d-scene-environment-properties.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/studio-3d-split-view.webp b/doc/qtdesignstudio/images/studio-3d-split-view.webp
index 630fdb48fe..aec301c91f 100644
--- a/doc/qtdesignstudio/images/studio-3d-split-view.webp
+++ b/doc/qtdesignstudio/images/studio-3d-split-view.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/studio-curve-editor.png b/doc/qtdesignstudio/images/studio-curve-editor.png
deleted file mode 100644
index 01cd7f5ab4..0000000000
--- a/doc/qtdesignstudio/images/studio-curve-editor.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtdesignstudio/images/studio-curve-editor.webp b/doc/qtdesignstudio/images/studio-curve-editor.webp
new file mode 100644
index 0000000000..79624624d1
--- /dev/null
+++ b/doc/qtdesignstudio/images/studio-curve-editor.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/studio-ext-scene-environment.webp b/doc/qtdesignstudio/images/studio-ext-scene-environment.webp
new file mode 100644
index 0000000000..cc26498c95
--- /dev/null
+++ b/doc/qtdesignstudio/images/studio-ext-scene-environment.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/studio-flow-item.png b/doc/qtdesignstudio/images/studio-flow-item.png
deleted file mode 100644
index 905174d600..0000000000
--- a/doc/qtdesignstudio/images/studio-flow-item.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtdesignstudio/images/studio-flow-item.webp b/doc/qtdesignstudio/images/studio-flow-item.webp
new file mode 100644
index 0000000000..1b3c54d818
--- /dev/null
+++ b/doc/qtdesignstudio/images/studio-flow-item.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/studio-flow-view-properties.png b/doc/qtdesignstudio/images/studio-flow-view-properties.png
deleted file mode 100644
index 95fe403b76..0000000000
--- a/doc/qtdesignstudio/images/studio-flow-view-properties.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtdesignstudio/images/studio-flow-view-properties.webp b/doc/qtdesignstudio/images/studio-flow-view-properties.webp
new file mode 100644
index 0000000000..7592e57954
--- /dev/null
+++ b/doc/qtdesignstudio/images/studio-flow-view-properties.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/studio-project-wizards.png b/doc/qtdesignstudio/images/studio-project-wizards.png
deleted file mode 100644
index 3a329bd16e..0000000000
--- a/doc/qtdesignstudio/images/studio-project-wizards.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtdesignstudio/images/studio-project-wizards.webp b/doc/qtdesignstudio/images/studio-project-wizards.webp
new file mode 100644
index 0000000000..fcb7c22ff0
--- /dev/null
+++ b/doc/qtdesignstudio/images/studio-project-wizards.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/studio-qtquick-3d-components.png b/doc/qtdesignstudio/images/studio-qtquick-3d-components.png
deleted file mode 100644
index 25974ab326..0000000000
--- a/doc/qtdesignstudio/images/studio-qtquick-3d-components.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtdesignstudio/images/studio-qtquick-3d-components.webp b/doc/qtdesignstudio/images/studio-qtquick-3d-components.webp
new file mode 100644
index 0000000000..54be760fd2
--- /dev/null
+++ b/doc/qtdesignstudio/images/studio-qtquick-3d-components.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/studio-qtquick-3d-view.png b/doc/qtdesignstudio/images/studio-qtquick-3d-view.png
deleted file mode 100644
index 9c0e8fc82b..0000000000
--- a/doc/qtdesignstudio/images/studio-qtquick-3d-view.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtdesignstudio/images/studio-qtquick-3d-view.webp b/doc/qtdesignstudio/images/studio-qtquick-3d-view.webp
new file mode 100644
index 0000000000..7351317e10
--- /dev/null
+++ b/doc/qtdesignstudio/images/studio-qtquick-3d-view.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/studio-qtquick-camera-properties.webp b/doc/qtdesignstudio/images/studio-qtquick-camera-properties.webp
new file mode 100644
index 0000000000..e54afe807e
--- /dev/null
+++ b/doc/qtdesignstudio/images/studio-qtquick-camera-properties.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/studio-timeline-empty.png b/doc/qtdesignstudio/images/studio-timeline-empty.png
deleted file mode 100644
index 861a1021bb..0000000000
--- a/doc/qtdesignstudio/images/studio-timeline-empty.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtdesignstudio/images/studio-timeline-empty.webp b/doc/qtdesignstudio/images/studio-timeline-empty.webp
new file mode 100644
index 0000000000..16aa728a52
--- /dev/null
+++ b/doc/qtdesignstudio/images/studio-timeline-empty.webp
Binary files differ
diff --git a/doc/qtdesignstudio/images/texture-editor.png b/doc/qtdesignstudio/images/texture-editor.png
deleted file mode 100644
index e8eecbd13b..0000000000
--- a/doc/qtdesignstudio/images/texture-editor.png
+++ /dev/null
Binary files differ
diff --git a/doc/qtdesignstudio/images/texture-editor.webp b/doc/qtdesignstudio/images/texture-editor.webp
new file mode 100644
index 0000000000..092a6f0dab
--- /dev/null
+++ b/doc/qtdesignstudio/images/texture-editor.webp
Binary files differ
diff --git a/doc/qtdesignstudio/src/components/qtquick-component-context-menu.qdocinc b/doc/qtdesignstudio/src/components/qtquick-component-context-menu.qdocinc
index 34140b8894..7fb95a9880 100644
--- a/doc/qtdesignstudio/src/components/qtquick-component-context-menu.qdocinc
+++ b/doc/qtdesignstudio/src/components/qtquick-component-context-menu.qdocinc
@@ -1,4 +1,4 @@
-// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
@@ -26,7 +26,7 @@
\li Group
\li \l{Organizing Components}
\row
- \li Position
+ \li Positioner
\li \l{Using Positioners}
\row
\li Layout
@@ -53,8 +53,8 @@
\li Move Component Instances into Separate Files
\li \l{Turning Component Instances into Custom Components}
\row
- \li Add New Signal Handler
- \li \l{Adding Signal Handlers}
+ \li Connecting Components to Signals
+ \li \l{Connecting Components to Signals in the Connection View}
\row
\li Go to Implementation
\li \l{Using UI Files}
diff --git a/doc/qtdesignstudio/src/components/qtquick-data-models.qdoc b/doc/qtdesignstudio/src/components/qtquick-data-models.qdoc
index 400e264d02..b93b745bc2 100644
--- a/doc/qtdesignstudio/src/components/qtquick-data-models.qdoc
+++ b/doc/qtdesignstudio/src/components/qtquick-data-models.qdoc
@@ -142,17 +142,17 @@
To edit list models:
\list 1
- \li Drag-and-drop a \uicontrol {Grid View} or \uicontrol {List View}
+ \li Drag a \uicontrol {Grid View} or \uicontrol {List View}
from \uicontrol Components >
\uicontrol {Default Components} > \uicontrol Views to the
\uicontrol Navigator or \uicontrol {2D} view.
\li Right-click the view in \uicontrol Navigator, and select
- \uicontrol {Edit List Model} in the context-menu to open
- the list model editor:
- \image qtquick-designer-edit-list-model.png "List view in model editor"
- \li Double-click the column headings and cells to change their values.
- \li Use the toolbar buttons to add, remove, or move rows and columns.
- In a list, each column represents a property and each row adds a
+ \uicontrol {Edit Model} in the context-menu to open the
+ \uicontrol {Model Editor} view.
+ \image edit-list-model-model-editor.webp "List view in Model Editor"
+ \li Double-click a cell to edit its value.
+ \li Use the toolbar buttons to add or remove rows and columns.
+ In a list, each column represents a property, and each row adds a
list item.
\endlist
diff --git a/doc/qtdesignstudio/src/components/qtquick-preset-components.qdoc b/doc/qtdesignstudio/src/components/qtquick-preset-components.qdoc
index 19ee8e60dd..4920cf582d 100644
--- a/doc/qtdesignstudio/src/components/qtquick-preset-components.qdoc
+++ b/doc/qtdesignstudio/src/components/qtquick-preset-components.qdoc
@@ -1,4 +1,4 @@
-// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
@@ -58,7 +58,7 @@
\li \l {Custom Effects and Materials}
\li \l {Lights}
\li \l {Cameras}
- \li \l {Scene Environment}
+ \li \l {Scene Environments}
\li \l {Morph Target}
\li \l {Repeater3D}
\li \l {Loader3D}
diff --git a/doc/qtdesignstudio/src/developers/studio-designer-developer-workflow.qdoc b/doc/qtdesignstudio/src/developers/studio-designer-developer-workflow.qdoc
index 0a6531fe12..e8c6c8e329 100644
--- a/doc/qtdesignstudio/src/developers/studio-designer-developer-workflow.qdoc
+++ b/doc/qtdesignstudio/src/developers/studio-designer-developer-workflow.qdoc
@@ -10,7 +10,7 @@
\note In this section, you are using advanced menu items. These are not
visible by default. To toggle the visibility of advanced menu items, see
- \l{Customizing the Menu}.
+ \l{Customizing the Menu Bar}.
\QDS enables designers and developers to work together on common
projects to develop applications. Designers use the \l{Design Views}{views}
@@ -46,7 +46,7 @@
\li Select \uicontrol {File} > \uicontrol {Export Project} > \uicontrol {Generate CMake Build Files}.
\image studio-project-export.webp "Export the \QDS project for Qt Creator"
- \li Select \uicontrol {Details} to access the \l {Advanced Options}.
+ \li Select \uicontrol {Details} to access the \uicontrol {Advanced Options}.
\image studio-project-export-advanced.webp "Access Advanced Options in the project exporter"
\note The project exporter has default settings selected. This works better if the project
@@ -68,7 +68,7 @@
After exporting the project from the \QDS, you have to open it from Qt Creator.
If you have used any version before \QDS 4.0 to create the project, manually include this code
- in the \l {CMakeLists.txt} file so the exported project works in Qt Creator.
+ in the \e {CMakeLists.txt} file so the exported project works in Qt Creator.
\code
set(BUILD_QDS_COMPONENTS ON CACHE BOOL "Build design studio components")
@@ -83,6 +83,6 @@
\endcode
\note If you have created the project with the \QDS version 4.0 or above, you already have this code in
- \l {CMakeLists.txt} by default.
+ \e {CMakeLists.txt} by default.
*/
diff --git a/doc/qtdesignstudio/src/mcus/qtdesignstudio-compatibility-with-mcu-sdks.qdoc b/doc/qtdesignstudio/src/mcus/qtdesignstudio-compatibility-with-mcu-sdks.qdoc
index de94f59d80..0e833cead1 100644
--- a/doc/qtdesignstudio/src/mcus/qtdesignstudio-compatibility-with-mcu-sdks.qdoc
+++ b/doc/qtdesignstudio/src/mcus/qtdesignstudio-compatibility-with-mcu-sdks.qdoc
@@ -16,10 +16,16 @@
\li \QDS Version
\li \QMCU SDK Version
\row
- \li 4.3 or later
- \li 2.6 or later
+ \li 4.5 or later
+ \li 2.8 or later
\row
- \li 4.2 or later
+ \li 4.4
+ \li 2.7
+ \row
+ \li 4.3
+ \li 2.6
+ \row
+ \li 4.2
\li 2.5
\row
\li 4.0 up to 4.1
diff --git a/doc/qtdesignstudio/src/overviews/qtquick-creating-ui-logic.qdoc b/doc/qtdesignstudio/src/overviews/qtquick-creating-ui-logic.qdoc
index a5e05f8beb..1ea19bac4b 100644
--- a/doc/qtdesignstudio/src/overviews/qtquick-creating-ui-logic.qdoc
+++ b/doc/qtdesignstudio/src/overviews/qtquick-creating-ui-logic.qdoc
@@ -84,7 +84,7 @@
\li \l{Connecting Components to Signals}
\row
\li Formatting connections
- \li \l{Adding Actions and Assignments}
+ \li \l{Actions and Conditions}
\row
\li Dynamically changing the behavior of a component
\li \l{Adding Bindings Between Properties}
diff --git a/doc/qtdesignstudio/src/overviews/qtquick-export.qdoc b/doc/qtdesignstudio/src/overviews/qtquick-export.qdoc
index f9ae3b8d7b..f083f85f8e 100644
--- a/doc/qtdesignstudio/src/overviews/qtquick-export.qdoc
+++ b/doc/qtdesignstudio/src/overviews/qtquick-export.qdoc
@@ -10,7 +10,7 @@
\note In this section, you are using advanced menu items. These are not
visible by default. To toggle the visibility of advanced menu items, see
- \l{Customizing the Menu}.
+ \l{Customizing the Menu Bar}.
\l{glossary-component}{Components} contained in \l{UI Files}
{UI files} (.ui.qml) can be exported to JSON metadata format and PNG assets.
diff --git a/doc/qtdesignstudio/src/overviews/qtquick-optimizing-designs.qdoc b/doc/qtdesignstudio/src/overviews/qtquick-optimizing-designs.qdoc
index 3cf0c1336b..937362450b 100644
--- a/doc/qtdesignstudio/src/overviews/qtquick-optimizing-designs.qdoc
+++ b/doc/qtdesignstudio/src/overviews/qtquick-optimizing-designs.qdoc
@@ -21,7 +21,7 @@
\endlist
For more useful information for application developers, see
- \l {Performance Considerations And Suggestions}.
+ \l {QML Performance Considerations And Suggestions}.
For more information about optimizing 3D scenes, see
\l{Creating Optimized 3D Scenes}.
diff --git a/doc/qtdesignstudio/src/overviews/qtquick-production-quality-animation.qdoc b/doc/qtdesignstudio/src/overviews/qtquick-production-quality-animation.qdoc
index fcf1a4c455..068a7c140b 100644
--- a/doc/qtdesignstudio/src/overviews/qtquick-production-quality-animation.qdoc
+++ b/doc/qtdesignstudio/src/overviews/qtquick-production-quality-animation.qdoc
@@ -28,7 +28,7 @@
to upload the draw primitives to the graphics hardware.
The frames-per-second (FPS) refresh rate of animations is displayed in the
- \uicontrol FPS field on the \l{Summary of Main Toolbar Actions}{toolbar}
+ \uicontrol FPS field on the toolbar
in the \uicontrol Design mode.
To improve the FPS rate, application developers should:
diff --git a/doc/qtdesignstudio/src/qtdesignstudio-app-flows.qdoc b/doc/qtdesignstudio/src/qtdesignstudio-app-flows.qdoc
index 05906cba86..2c7564fe86 100644
--- a/doc/qtdesignstudio/src/qtdesignstudio-app-flows.qdoc
+++ b/doc/qtdesignstudio/src/qtdesignstudio-app-flows.qdoc
@@ -66,8 +66,11 @@
\title Adding Flow Views
- You can add a flow view to an existing project or create a new project
- for it, as described in \l {Creating Projects}.
+ A flow view is the base component of the flow diagram that you can use to wireframe
+ the UI of your application. For more information, see \l{Designing Application Flows}.
+
+ Add a flow view to an existing project or create a new project for it, as described in
+ \l {Creating Projects}.
To create the flow view, select \uicontrol File >
\uicontrol {New File} >
@@ -76,24 +79,18 @@
\image studio-flow-view-create.png "Create Flow View wizard template"
- You only need to select the \uicontrol {Use Event Simulator} check box if
- you want to add an event simulator to the flow view. The event simulator
- needs the project to be imported to the flow view, so you also need
- to select the \uicontrol {Use Application Import} check box. You need the
+ If you want to add an event simulator to the flow view, select the
+ \uicontrol {Use Event Simulator} checkbox. In this case, select also the
+ \uicontrol {Use Application Import} checkbox to import the project to the flow view
+ as the event simulator requires it to work correctly. You need the
import also for access to the project \c Constants.qml file that contains
- global settings for the project.
-
- The flow view properties enable you to adjust the appearance of all
- the items in the flow: action areas, transition lines, decisions, and
- wildcards. You can change the global settings for all items by editing
- flow view properties, or you can select an individual action area or
- transition line and change the appearance of just that component, including
- the color, line thickness, dotted or solid lines, and even the curve of
- the line. This enables you to add extra semantics to the design
- of the flow diagram itself.
+ global settings for the project. For more information, see \l {Simulating Events}.
- You can \l{Adding Flow Items}{add flow items} to the flow view to design
- the UI.
+ You can adjust the appearance of all the items in the flow: action areas,
+ transition lines, decisions, and wildcards. Change the global settings for all items
+ by editing the flow view properties. To add additional semantics to the flow diagram
+ design, select an individual action area or transition line and change the appearance
+ of just that component.
\section1 Flow View Properties
@@ -102,12 +99,12 @@
\l Visibility sections in the \l Properties view. Specify flow view
properties in the \uicontrol {Flow View} section.
- \image studio-flow-view-properties.png "Flow View component properties"
+ \image studio-flow-view-properties.webp "Flow View component properties"
To specify the \uicontrol {Flow Item} that is currently visible in the
flow view, set its index in the \uicontrol {Current index} field.
- You can use the \l{Picking Colors}{color picker} to set colors for:
+ Use the \l{Picking Colors}{color picker} to set colors for:
\list
\li Transition lines
@@ -133,9 +130,6 @@
area or transition line, see \l{Flow Action Area Properties} and
\l{Flow Transition Properties}.
- In the \uicontrol Layout tab, you can use \l{Setting Anchors and Margins}
- {anchors} to position the component.
-
In the \uicontrol Advanced section, you can manage the more
\l{Specifying Developer Properties}{advanced properties}
of components.
@@ -148,29 +142,26 @@
\title Adding Flow Items
- After you create a \l{Adding Flow Views}{Flow View} component, you can
- use a project wizard template to add a \uicontrol {Flow Item} component
- for each screen in the UI.
+ After you create a \l{Adding Flow Views}{Flow View} component, use a project wizard
+ template to add a \uicontrol {Flow Item} component for each screen in the UI.
If you \l{Importing 2D Assets}{imported} your screen designs from a
design tool as individual \l{glossary-component}{components}
- (\e {.ui.qml} files), you can use them as content for flow items.
+ (\e {.ui.qml} files), you can use them as content for flow items like any other components.
The imported components are listed in \uicontrol Components
> \uicontrol {My Components}.
- If you are building your UI from scratch in \QDS, you must first add
- components to the flow items to create the screens as you would any
- components. For more information, see \l {Using Components}. The
- flow items that you attach the components to are listed under
+ If you are building your UI from scratch in \QDS, add components to the flow items
+ first to create the screens as you would any components. For more information, see
+ \l {Using Components}. The flow items that you attach the components to are listed under
\uicontrol {My Components}.
- \image studio-flow-item.png "Custom Flow Item in Components"
+ \image studio-flow-item.webp "Custom Flow Item in Components"
\note You must use the wizard to create the flow items. After you create
a flow view, the \uicontrol {Flow View} module is added to
- \uicontrol Components. It contains a \uicontrol {Flow Item} component that
- you can use to \l{Applying States in Flows}{apply states to flow items}, and
- that you should use solely for that purpose.
+ \uicontrol Components. It contains the \uicontrol {Flow Item} component for
+ \l{Applying States in Flows}{applying states to flow items}, and solely for that purpose.
To add flow items:
@@ -181,7 +172,7 @@
to create flow items for each screen in the UI.
\li Add content to the flow item in one of the following ways:
\list
- \li Drag-and-drop components from \uicontrol Components to a
+ \li Drag components from \uicontrol Components to a
flow item in the \l {2D} view or \l Navigator.
\li Drag a screen from \uicontrol Components
> \uicontrol {My Components} to a flow item in
@@ -190,10 +181,9 @@
\li In \l Properties, edit the properties of each flow item.
\endlist
- You can now drag the flow items from \uicontrol Components
- > \uicontrol {My Components} to the flow view in the \uicontrol {2D}
- or \uicontrol Navigator view. When you have all the flow items in place, you can
- \l{Adding Action Areas and Transitions}{add action areas} to them to create
+ Now, drag the flow items from \uicontrol Components > \uicontrol {My Components} to the
+ flow view in the \uicontrol {2D} or \uicontrol Navigator view. When you have all the flow
+ items in place, \l{Adding Action Areas and Transitions}{add action areas} to them to create
transitions between them.
\section1 Flow Item Properties
@@ -209,23 +199,20 @@
properties are used to \l{Applying States in Flows}{apply states}
in flows.
- To include another flow view into a flow view, select the UI file (.ui.qml)
+ To include another flow view as a flow item into a flow view, select the UI file (.ui.qml)
that specifies the flow view in the \uicontrol {Loader source} field.
Usually, a flow item is inactive and invisible when it is not currently
selected in the flow. Especially, all events from the flow item are ignored.
To make a flow item always active, so that another flow item within it
can respond to events and trigger the opening of a dialog, for example,
- select the \uicontrol {Force active} check box.
+ select the \uicontrol {Force active} checkbox.
- By default, transitions are drawn from action areas to the target flow item.
+ In the flow view, transitions are drawn from action areas to the target flow item by default.
To draw the transitions from the edges of flow items instead, select the
- \uicontrol {Join lines} check box in the \uicontrol {Transition Lines}
+ \uicontrol {Join lines} checkbox in the \uicontrol {Transition Lines}
section.
- In the \uicontrol Layout tab, you can use \l{Setting Anchors and Margins}
- {anchors} to position the component.
-
In the \uicontrol Advanced section, you can manage the more
\l{Specifying Developer Properties}{advanced properties} of components.
*/
diff --git a/doc/qtdesignstudio/src/qtdesignstudio-faq.qdoc b/doc/qtdesignstudio/src/qtdesignstudio-faq.qdoc
deleted file mode 100644
index 8f7267e0d3..0000000000
--- a/doc/qtdesignstudio/src/qtdesignstudio-faq.qdoc
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
-
-/*!
- \previouspage creator-how-to-get-help.html
- \page studio-faq.html
- \nextpage studio-platforms.html
-
- \title Frequently Asked Questions
-
- This section contains answers to some frequently asked questions about \QDS
- grouped by categories. You might also find answers to your questions in the
- product documentation by searching or browsing the index in the
- \l{Get help}{Help mode}. Many questions are also answered by the
- \l{Examples}{examples} and \l{Tutorials}{video tutorials}.
-
- \list
- \li \l {FAQ - \QB}{\QB}
- \li \l {FAQ - Assets}{Assets}
- \li \l {FAQ - Components}{Components}
- \li \l {FAQ - Views}{Views}
- \li \l {FAQ - Integration Between \QDS and Qt Creator}{Integration Between \QDS and Qt Creator}
- \li \l {FAQ - Performance}{Performance}
- \li \l {FAQ - Data Simulation}{Data Simulation}
- \endlist
-
- \section1 FAQ - \QB
-
- \section2 How does \QBPS differ from \QBSK and \QBF?
-
- \QBPS, \QBSK, and \QBF are functionally similar. The biggest difference
- between the tools is that \QBSK and \QBF can export .svg (vector), .png, and
- .jpeg files, while \QBPS only supports .png and .jpeg. Adobe Illustrator
- users can port their designs into Photoshop, but they must be rasterized
- into \e {smart objects}.
-
- For more information, see \l {Exporting from Design Tools}.
-
- \section2 Do I need to copy the .qml files in the resource folder after each design modification?
-
- No you don't. When you add new or modified .metadata files to your project
- from Photoshop, \QBPS, \QBSK, or \QBF, select the \uicontrol {Merge QML}
- check box in the \uicontrol {Asset Import} dialog to merge the changes into
- existing QML files instead of overwriting them.
-
- For more information, see \l {Importing 2D Assets}.
-
- \section2 Where can I find log files generated by \QB while exporting metadata?
-
- On Windows, the logs are stored inside the temp folder in
- \c {C:\Users\<USERNAME>\AppData\Local\Temp}. The log files are named as
- \e csxs<versionNumber>-<HostID>.log. Please note that you might have to set
- the log level to generate logs. Also note the CEP version while setting the
- log level. The CEP version depends on the Photoshop version you are using.
- Currently the latest version is version 10.
-
- \section1 FAQ - Assets
-
- \section2 Can I import my organization's preferred font in \QDS?
-
- Yes, you can import your custom fonts, for example, in .ttf or .otf formats.
- Fonts installed on your system will be available to use in your imported
- designs. If you need to deploy the device, you will have to import the font
- into the project.
-
- For more information, see \l {Using Custom Fonts}.
-
- \section1 FAQ - Components
-
- \section2 Can I use custom components?
-
- Yes, you can create custom components and controls by using wizard templates
- or move component instances into separate files to turn them into new
- components that you can create instances of. For more information, see
- \l {Using Components}.
-
- \section2 What are the 3D import formats for \QDS?
-
- You can import files stored in several widely-used formats, such as .fbx,
- .obj, .gltf, .glb, .blend, .dae, .uia, and .uip.
-
- For more information, see \l {Importing 3D Assets}.
-
- \section2 How can I integrate custom C++ components into QDS?
-
- You must create your own QML module that contains the components and
- provides additional information about your components. For more information,
- see \l {Using QML Modules with Plugins}.
-
- \section1 FAQ - Views
-
- \section2 What are the keyboard shortcuts for moving around in the \uicontrol{3D} view?
-
- \list
- \li To pan: \key Alt + middle mouse button
- \li To orbit (rotate): \key Alt (or \key Option on \macos) + left mouse button
- \li To zoom: \key Alt + right mouse button
- \endlist
-
- For more information, see the \l {3D} view.
-
- \section1 FAQ - Integration Between \QDS and Qt Creator
-
- \section2 Can I automatically propagate name changes between \QDS and Qt Creator?
-
- Unfortunately we do not automate renaming files between tools at the moment.
- If you decide to change the name of a property, alias, or signal in \QDS,
- you need to manually change the name in Qt Creator to maintain the connection.
- However, you can rename symbols in all files within a project. To rename a
- QML type in a project, select \uicontrol Tools > \uicontrol QML/JS >
- \uicontrol {Rename Symbol Under Cursor} or press \key Ctrl+Shift+R. For more
- information, see \l {Rename symbols}.
-
- \section2 How can I add .qml files to my project in Qt Creator?
-
- Use the project wizard templates to create an application in \QDS and copy
- your .qml files to the project folder. Then make some changes to the project
- configuration and source files, as instructed in
- \l {Converting UI Projects to Applications}.
-
- \section1 FAQ - Performance
-
- \section2 Will my application with 3D components run at 60 FPS?
-
- With the ability to test the full (2D/3D) UI in \QDS on target hardware,
- you will quickly be able to determine if a 3D object is causing performance
- issues using the \uicontrol FPS field in the \uicontrol Design mode.
- \uicontrol FPS displays the frames-per-second (FPS) refresh rate of
- previewed animations.
-
- See \l {Optimizing Your 3D Scene} to learn how you can enhance the
- performance by optimizing your scene.
-
- \section1 FAQ - Data Simulation
-
- \section2 Can I automatically generate dummy data?
- No, this is not supported at the moment. For more information about creating
- the data manually, see \l {Loading Placeholder Data}.
- */
diff --git a/doc/qtdesignstudio/src/qtdesignstudio-finding-qt-runtime-version.qdoc b/doc/qtdesignstudio/src/qtdesignstudio-finding-qt-runtime-version.qdoc
index cb9c7e86e9..5f2bc9bdad 100644
--- a/doc/qtdesignstudio/src/qtdesignstudio-finding-qt-runtime-version.qdoc
+++ b/doc/qtdesignstudio/src/qtdesignstudio-finding-qt-runtime-version.qdoc
@@ -34,5 +34,8 @@
\row
\li 4.4
\li 6.6.2
+ \row
+ \li 4.5
+ \li 6.7.0 (with additional Quick3D features)
\endtable
*/
diff --git a/doc/qtdesignstudio/src/qtdesignstudio-help-overview.qdoc b/doc/qtdesignstudio/src/qtdesignstudio-help-overview.qdoc
index be9e6b4ed5..36fbc8c015 100644
--- a/doc/qtdesignstudio/src/qtdesignstudio-help-overview.qdoc
+++ b/doc/qtdesignstudio/src/qtdesignstudio-help-overview.qdoc
@@ -11,8 +11,7 @@
\table
\row
\li \image qds-front-help.png
- \li Learn more about using the \uicontrol Help mode, frequently
- asked questions, and supported platforms.
+ \li Learn more about using the \uicontrol Help mode and supported platforms.
\endtable
\list
@@ -23,9 +22,6 @@
and index functions to find particular topics in the helps, or
request context-sensitive help by pressing \key F1 in the Design
mode.
- \li \l{Frequently Asked Questions}
-
- Contains answers to some frequently asked questions about \QDS.
\li \l{Supported Platforms}
You can install and run \QDS on several operating systems to design
diff --git a/doc/qtdesignstudio/src/qtdesignstudio-packaging.qdoc b/doc/qtdesignstudio/src/qtdesignstudio-packaging.qdoc
index 1e426f011e..4158a7b545 100644
--- a/doc/qtdesignstudio/src/qtdesignstudio-packaging.qdoc
+++ b/doc/qtdesignstudio/src/qtdesignstudio-packaging.qdoc
@@ -10,7 +10,7 @@
\note In this section, you are using advanced menu items. These are not
visible by default. To toggle the visibility of advanced menu items, see
- \l{Customizing the Menu}.
+ \l{Customizing the Menu Bar}.
When you are ready to deliver your application to users or upload it to
app stores, you can use \QDS to create suitable packages that contain all
diff --git a/doc/qtdesignstudio/src/qtdesignstudio-platforms.qdoc b/doc/qtdesignstudio/src/qtdesignstudio-platforms.qdoc
index 5a50eb2bf4..501e30adc7 100644
--- a/doc/qtdesignstudio/src/qtdesignstudio-platforms.qdoc
+++ b/doc/qtdesignstudio/src/qtdesignstudio-platforms.qdoc
@@ -1,4 +1,4 @@
-// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
@@ -11,20 +11,20 @@
You can install and run \QDS on several operating systems to create
applications for multiple desktop, embedded, and mobile device platforms.
- \section1 Development Platforms
+ \section1 Host Platforms
\QDS is available in binary packages for the following operating systems:
\list
- \li \macOS 11.0
- \li Linux:
- \list
- \li CentOS 8.1
- \li openSUSE Leap 15.1
- \li SUSE Linux Enterprise Server 15 (SLES 15)
- \li Ubuntu 20.04
- \endlist
- \li Windows 10, version 2004
+ \li Windows 11
+ \li Windows 10 64-bit
+ \li \macOS 12, 13
+ \list
+ \li ARM-based Mac
+ \li Intel Mac
+ \endlist
+ \li Linux Ubuntu 22.04 (latest LTS)
+ \li Linux Ubuntu 20.04
\endlist
\note For a good user experience on Windows 10, we recommend the following
@@ -36,9 +36,9 @@
\QB is available for the following design tools:
\list
- \li Adobe Photoshop version 24.0
- \li Adobe XD version 55.0.12
- \li Figma version 116.4
- \li Sketch version 90.0
+ \li Adobe Photoshop 25.0
+ \li Adobe XD 57.1.12.2
+ \li Figma 116.15.15
+ \li Sketch 99.1
\endlist
*/
diff --git a/doc/qtdesignstudio/src/qtdesignstudio-projects.qdoc b/doc/qtdesignstudio/src/qtdesignstudio-projects.qdoc
index 3daf6e7089..46b2ac8fbb 100644
--- a/doc/qtdesignstudio/src/qtdesignstudio-projects.qdoc
+++ b/doc/qtdesignstudio/src/qtdesignstudio-projects.qdoc
@@ -37,7 +37,7 @@
\li
\li Lists your most recently used presets.
\row
- \li {1,2} General
+ \li {1,3} General
\li Empty
\li Creates a project that uses default components such as rectangles,
images, and text. You can run the application on all target
@@ -47,6 +47,11 @@
\li Creates a project that uses default and 3D components such as
cameras, lights, 3D models, and materials.
\row
+ \li 3D Extended
+ \li Creates a project that uses default and 3D components, such as
+ camera, light, model and materials. Extended scene environment is
+ also included to enable various built-in effects.
+ \row
\li \QMCU
\li MCU
\li Creates an application that uses a subset of default components
@@ -77,7 +82,7 @@
\note This tab is not visible if there are no saved custom presets.
\endtable
- \image studio-project-wizards.png "The Create Project wizard"
+ \image studio-project-wizards.webp "The Create Project wizard"
To test how well your designs work, you can preview the
UIs on the desktop, embedded Linux devices, or Android devices. For more
diff --git a/doc/qtdesignstudio/src/qtdesignstudio-terms.qdoc b/doc/qtdesignstudio/src/qtdesignstudio-terms.qdoc
index 9c517f9846..70ff56517c 100644
--- a/doc/qtdesignstudio/src/qtdesignstudio-terms.qdoc
+++ b/doc/qtdesignstudio/src/qtdesignstudio-terms.qdoc
@@ -30,7 +30,7 @@
An \e asset is an image, font file, 3D model, or other supported file that
you add to your \l{glossary-project}{project}.
- \image qtquick-assets-tab.png "Assets"
+ \image qtquick-assets-tab.webp "Assets"
Assets are packaged with \l{glossary-component}{components} for delivery
to users.
@@ -187,7 +187,7 @@
also be modified by another component, unless a particular component
type has explicitly disallowed this for a specific property.
- \image qtquick-item-properties-common.png "Properties view"
+ \image qtquick-item-properties-common.webp "Properties view"
Read more about properties:
diff --git a/doc/qtdesignstudio/src/qtdesignstudio-toc.qdoc b/doc/qtdesignstudio/src/qtdesignstudio-toc.qdoc
index 636cbfeb19..659e446bb3 100644
--- a/doc/qtdesignstudio/src/qtdesignstudio-toc.qdoc
+++ b/doc/qtdesignstudio/src/qtdesignstudio-toc.qdoc
@@ -1,4 +1,4 @@
-// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
@@ -16,29 +16,30 @@
\list
\li \l{2D}
\li \l{3D}
- \li \l{Material Editor and Browser}
- \li \l{Components}
\li \l{Assets}
- \li \l{Navigator}
- \li \l{Properties}
- \li \l{Connections}
- \li \l{States}
- \li \l{Translations}
- \li \l{Transitions}
- \li \l{Timeline}
- \li \l{Curves}
\li \l{Code}
\generatelist studio-how-to-code
\generatelist studio-how-to-refactor-code
\generatelist studio-how-to-search
\generatelist studio-preferences-code
- \li \l{Projects}
+ \li \l{Components}
+ \li \l{Connections}
+ \li \l{Content Library}
+ \li \l{Curves}
+ \li \l{Effect Composer}
\li \l{File System}
+ \li \l{Material Editor and Browser}
+ \li \l{Model Editor}
+ \li \l{Navigator}
\li \l{Open Documents}
- \li \l{Content Library}
- \li \l{Texture Editor}
+ \li \l{Projects}
+ \li \l{Properties}
\li \l{Qt Insight}
- \li \l{Effect Composer}
+ \li \l{States}
+ \li \l{Texture Editor}
+ \li \l{Timeline}
+ \li \l{Transitions}
+ \li \l{Translations}
\endlist
\li \l{Managing Workspaces}
\li \l{Manage sessions}
@@ -89,7 +90,7 @@
\li \l{Custom Effects and Materials}
\li \l{Lights}
\li \l{Cameras}
- \li \l{Scene Environment}
+ \li \l{Scene Environments}
\li \l{Morph Target}
\li \l{Repeater3D}
\li \l{Loader3D}
@@ -264,7 +265,6 @@
\li \l {Search from documentation}
\li \l {Select the help start page}
\endlist
- \li \l{Frequently Asked Questions}
\li \l{Supported Platforms}
\endlist
\li \l{Technical Support}
diff --git a/doc/qtdesignstudio/src/qtdesignstudio.qdoc b/doc/qtdesignstudio/src/qtdesignstudio.qdoc
index 6d84474605..6aab55a1ad 100644
--- a/doc/qtdesignstudio/src/qtdesignstudio.qdoc
+++ b/doc/qtdesignstudio/src/qtdesignstudio.qdoc
@@ -86,7 +86,6 @@
\li \b {\l Help}
\list
\li \l{Get help}{Getting Help}
- \li \l{Frequently Asked Questions}
\li \l{Supported Platforms}
\endlist
\row
diff --git a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-camera.qdoc b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-camera.qdoc
index 202249188d..89da3cbb34 100644
--- a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-camera.qdoc
+++ b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-camera.qdoc
@@ -8,13 +8,13 @@
\title Cameras
- A camera is always necessary to view the content of a 3D scene. A camera
+ A camera is necessary to view the content of a 3D scene. A camera
defines how to project the content of a 3D scene into a 2D coordinate space,
which can then be used on a 2D surface. When a camera is present in the
scene, it can be used to direct what is displayed in a \l {3D Views}
{3D view}.
- \image studio-qtquick-3d-components.png "Qt Quick 3D components in Components"
+ \image studio-qtquick-3d-components.webp "Qt Quick 3D components in Components"
To add a camera component to your UI, do one of the following:
\list
@@ -31,7 +31,7 @@
\uicontrol QtQuick3D module to your project, as described in
\l {Adding and Removing Modules}.
- You can use the following components in your scenes to determine camera
+ The following components in your scenes determine the camera
projection:
\list
@@ -65,7 +65,7 @@
You can edit the camera properties in the \uicontrol Properties view.
- \image studio-qtquick-camera-properties "Properties view for Perspective Camera"
+ \image studio-qtquick-camera-properties.webp "Properties view for Perspective Camera"
\section1 Setting Camera Field of View
@@ -73,6 +73,8 @@
when \l {Creating Projects}{creating your project}, the camera properties
will be slightly different.
+ \note Orthographic cameras don't have the FOV property.
+
The camera frustum can be obtained by taking a frustum (that is, a
truncation with parallel planes) of the cone of vision that a camera or eye
would have to the rectangular viewports typically used in computer graphics.
@@ -112,10 +114,10 @@
\note The \uicontrol {Horizontal magnification} and
\uicontrol {Vertical magnification} properties are not available in Qt 5.
- The \uicontrol {Frustum culling enabled} property determines whether the
+ The \uicontrol {Frustum culling} property determines whether the
objects outside the camera frustum will be culled, which means they will not
be passed to the renderer.
- \note The \uicontrol {Frustum culling enabled} property is not available in
+ \note The \uicontrol {Frustum culling} property is not available in
Qt 5.
The default values are intended to cause anything within the view
@@ -124,5 +126,22 @@
better results with ambient occlusion or with effects that use the depth
buffer of the camera, such as the \e {depth of field} effect.
- \note Orthographic cameras don't have the FOV property.
+ \section1 Setting a Camera to Look at an Object
+
+ Setting the camera to look at a specific object can be useful, for example,
+ if you want to create a cinematic effect or have the camera follow a user-controlled object.
+
+ To set a camera to look at an object:
+
+ \list 1
+ \li In \uicontrol Navigator, select the camera.
+ \li In \uicontrol Properties > \uicontrol {Look-at-Node}, select the object that
+ the camera should look at.
+ \image camera-look-at-node.webp
+ \endlist
+
+ When you set a camera to look at an object, the camera automatically rotates to
+ point toward the assigned object, even if the object or the camera moves. The rotation only
+ happens around the x and y axes.
+
*/
diff --git a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-custom-shaders.qdoc b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-custom-shaders.qdoc
index b559fd2230..f053834f0d 100644
--- a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-custom-shaders.qdoc
+++ b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-custom-shaders.qdoc
@@ -29,7 +29,7 @@
\uicontrol {Custom Material} components, in
\uicontrol Components > \uicontrol {Qt Quick3D} > \uicontrol {Qt Quick 3D}.
- \image studio-qtquick-3d-components.png "Effect and Custom Material Components in Components"
+ \image studio-qtquick-3d-components.webp "Effect and Custom Material Components in Components"
\note In Qt 5 the \uicontrol Effect component is located in
\uicontrol {Qt Quick 3D Effects} >
@@ -218,7 +218,7 @@
\row
\li \l Blending
- \li \inlineimage ok.png
+ \li
\li A pass command that specifies the source blending function.
The \uicontrol Source property specifies the source blending
diff --git a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-editor.qdoc b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-editor.qdoc
index 7111d2db90..ebe842a555 100644
--- a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-editor.qdoc
+++ b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-editor.qdoc
@@ -1,4 +1,4 @@
-// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
@@ -6,8 +6,12 @@
\page studio-3d-editor.html
\nextpage studio-material-editor.html
+ \ingroup studio-views
+
\title 3D
+ \brief Edit a 3D scene.
+
When editing a 3D scene, you view the scene in the \uicontrol{3D}
view. You can change the projection of the view by switching between
\e {perspective camera} and \e {orthographic camera} modes. When using the
@@ -25,7 +29,7 @@
components from \uicontrol Components > \inlineimage icons/plus.png
> \uicontrol {Qt Quick 3D} > \uicontrol {Qt Quick 3D}.
- You can use the \l{Summary of the 3D View Toolbar Buttons}{toolbar buttons}
+ You can use the toolbar buttons
to \e transform 3D components and manipulate the 3D scene. Transformation
refers to moving, rotating, or scaling of a component. The \e pivot of the
component is used as the origin for transformations. You can set a
@@ -56,7 +60,7 @@
\li Delete components
\endlist
- \image 3d-view-context-menu.png
+ \image 3d-view-context-menu.webp "The context menu in the 3D view"
To refresh the contents of the \uicontrol{3D} view, press \key P or
select the \inlineimage icons/reset.png
@@ -71,6 +75,8 @@
\section1 Controlling the 3D View Camera
+ \section2 Toggling Camera Mode
+
To switch to perspective camera mode, select
\inlineimage perspective_camera.png
(\uicontrol {Toggle Perspective/Orthographic Edit Camera}).
@@ -78,14 +84,16 @@
\inlineimage orthographic_camera.png
. You can also Toggle the camera mode by using the keyboard shortcut \key T.
+ \section2 Navigating in the 3D Scene
+
You can navigate the scene by panning, rotating, and zooming the 3D view
camera:
\list
\li To pan, press \key Alt (or \key Option on \macos) and use the
middle mouse button to click and drag anywhere in the rendered
- view to slide the view around.
- \note It is not possible to pan using Magic Mouse.
+ view to slide the view around. Alternatively, press and hold \key {right mouse
+ button} and \key {left mouse button} and drag anywhere in the view to pan.
\li To orbit, press \key Alt and click and drag anywhere in the rendered
view to rotate the view.
\li To zoom, use the mouse wheel or press \key Alt and right-click
@@ -104,6 +112,17 @@
selected, the camera is pointed at the world origin. This does not affect
the camera zoom level.
+ \image studio-3d-editor-axis-helper.webp "Axis helper in the 3D view"
+
+ You can use scene cameras (2) to view the \uicontrol View3D component from a
+ specific angle in the \l {2D} view while editing scenes. Different types of
+ cameras are available in \uicontrol Components
+ > \uicontrol {Qt Quick 3D} > \uicontrol {Qt Quick 3D}. For more information
+ about using cameras in the scene, the available camera types, and their
+ properties, see \l{Cameras}.
+
+ \section2 Using Split View
+
To view the scene in a split view of four different point of views, select
\inlineimage icons/split-view.png.
@@ -114,14 +133,44 @@
independently. Navigate each split by panning, rotating, and zooming, as
described above.
- \image studio-3d-editor-axis-helper.webp "Axis helper in the 3D view"
+ \section2 Using Fly Mode
- You can use scene cameras (2) to view the \uicontrol View3D component from a
- specific angle in the \l {2D} view while editing scenes. Different types of
- cameras are available in \uicontrol Components
- > \uicontrol {Qt Quick 3D} > \uicontrol {Qt Quick 3D}. For more information
- about using cameras in the scene, the available camera types, and their
- properties, see \l{Cameras}.
+ You can move around freely in the 3D scene with fly mode. To navigate the scene with
+ fly mode, keep the \key {right mouse button} pressed and use the listed keys to move
+ around the scene.
+
+ \table
+ \header
+ \li Key
+ \li Action
+ \row
+ \li \key W or \key {Up arrow}
+ \li Move forward.
+ \row
+ \li \key S or \key {Down arrow}
+ \li Move backward.
+ \row
+ \li \key A or \key {Left arrow}
+ \li Move left.
+ \row
+ \li \key D or \key {Right arrow}
+ \li Move right.
+ \row
+ \li \key E or \key {Page up}
+ \li Move up.
+ \row
+ \li \key Q or \key {Page down}
+ \li Move down.
+ \endtable
+
+ To adjust the movement speed, select \inlineimage icons/camera_speed.png in the
+ \uicontrol 3D view toolbar to open the configuration dialog.
+
+ In the configuration dialog, you can:
+ \list
+ \li Adjust the movement speed of the camera with a slider.
+ \li Set a value multiplier for the speed slider.
+ \endlist
\section1 Using Global and Local Orientation
@@ -423,120 +472,4 @@
Select \uicontrol{Reset All Viewports} to reset the shading of the scene in all of the
splits.
- \section1 Summary of the 3D View Toolbar Buttons
-
- The \uicontrol{3D} view toolbar contains the following buttons:
-
- \table
- \header
- \li Button
- \li Tooltip
- \li Keyboard Shortcut
- \li Read More
- \row
- \li \inlineimage icons/select_group.png
- \inlineimage icons/select_item.png
- \li Toggle Group/Single Selection Mode
- \li \key Q
- \li \l{Selecting Components}
- \row
- \li \inlineimage icons/move_off.png
- \li Activate the Move Tool
- \li \key W
- \li \l{moving components 3d view}{Moving Components}
- \row
- \li \inlineimage icons/rotate_off.png
- \li Activate Rotate Tool
- \li \key E
- \li \l{Rotating Components}
- \row
- \li \inlineimage icons/scale_off.png
- \li Activate Scale Tool
- \li \key R
- \li \l{Scaling Components}
- \row
- \li \inlineimage icons/fit_selected.png
- \li Fit Selected Object to View
- \li \key F
- \li \l{Controlling the 3D View Camera}
- \row
- \li \inlineimage icons/perspective_camera.png
- \inlineimage icons/orthographic_camera.png
- \li Toggle Perspective/Orthographic Edit Camera
- \li \key T
- \li \l{Controlling the 3D View Camera}
- \row
- \li \inlineimage icons/global.png
- \li Toggle Global/Local Orientation
- \li \key Y
- \li \l{Using Global and Local Orientation}
- \row
- \li \inlineimage icons/edit_light_off.png
- \inlineimage icons/edit_light_on.png
- \li Toggle Edit Light On/Off
- \li \key U
- \li \l{Using Edit Light}
- \row
- \li \inlineimage icons/snapping-3d.png
- \li Toggle Snapping During Node Drag
- \li \key Shift + \key Tab
- \li \l{Snapping}
- \row
- \li \inlineimage icons/snapping-3d-conf.png
- \li Open Snap Configuration Dialog
- \li
- \li \l{Configuring Snapping}
- \row
- \li \inlineimage icons/align-camera-on.png
- \li Align Selected Cameras to View
- \li
- \li\l{Aligning Views and Cameras}
- \row
- \li \inlineimage icons/align-view-on.png
- \li Align View to Selected Camera
- \li
- \li \l{Aligning Views and Cameras}
- \row
- \li \inlineimage icons/visibilityon.png
- \li Visibility Toggles
- \li
- \li \l{Toggling Visibility}
- \row
- \li \inlineimage icons/3d-background-color.png
- \li Background Color Actions
- \li
- \li \l{Changing Colors}
- \row
- \li \inlineimage icons/split-view.png
- \li Toggle Split View On/Off
- \li \key Ctrl + \key Alt + \key Q
- \li \l{Using Split View}
- \row
- \li \inlineimage icons/particles-seek.png
- \li Seek Particle System Time
- \li
- \li \l{Particle Editor}
- \row
- \li \inlineimage icons/particle-animation-on.png
- \li Toggle Particle Animation
- \li \key V
- \li \l{Particle Editor}
- \row
- \li \inlineimage icons/particle-play.png
- \inlineimage icons/particle-pause.png
- \li Play/Pause Particles
- \li \key ,
- \li \l{Particle Editor}
- \row
- \li \inlineimage icons/particle-restart.png
- \li Restart Particles
- \li \key /
- \li \l{Particle Editor}
- \row
- \li \inlineimage icons/reset.png
- \li Reset View
- \li \key P
- \li
- \endtable
-
*/
diff --git a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-effects.qdoc b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-effects.qdoc
index 158932dff8..95eb3232d7 100644
--- a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-effects.qdoc
+++ b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-effects.qdoc
@@ -1,4 +1,4 @@
-// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
@@ -263,7 +263,7 @@
be transparent in the \uicontrol {Background Mode} field of the
\uicontrol {Scene Environment} component. Otherwise, the clear color of
the background hides the blur. For more information, see
- \l {Scene Environment}.
+ \l {Scene Environments}.
The \uicontrol {Fade Amount} property defines the fade speed of the
trail.
diff --git a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-lights.qdoc b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-lights.qdoc
index af994d5877..c7ae1e955e 100644
--- a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-lights.qdoc
+++ b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-lights.qdoc
@@ -9,7 +9,7 @@
\title Lights
Light components are the primary source of lighting in a \QDS scene.
- As a secondary light source, you can use \l{Setting the Light Probe}
+ As a secondary light source, you can use \l{Setting Image Based Lighting}
{image-based lighting}.
To add a light component to your UI, do one of the following:
diff --git a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-model.qdoc b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-model.qdoc
index 4159269bc7..e1f6edd8de 100644
--- a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-model.qdoc
+++ b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-model.qdoc
@@ -27,11 +27,14 @@
\note You can not create \uicontrol Empty models this way.
\endlist
+ Double-clicking a 3D model in \uicontrol 2D view opens the \uicontrol 3D view with
+ the 3D model selected.
+
If you cannot find the model components in \uicontrol {Components}, add the
\uicontrol QtQuick3D module to your project, as described in
\l {Adding and Removing Modules}.
- \image studio-qtquick-3d-components.png "The Qt Quick 3D section in Components"
+ \image studio-qtquick-3d-components.webp "The Qt Quick 3D section in Components"
\section1 Model Properties
diff --git a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-repeater-3d.qdoc b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-repeater-3d.qdoc
index 9e181a8aae..0f0d0634ca 100644
--- a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-repeater-3d.qdoc
+++ b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-repeater-3d.qdoc
@@ -1,4 +1,4 @@
-// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
@@ -8,10 +8,6 @@
\title Repeater3D
- \note The \uicontrol Repeater3D component is released as a tech preview
- feature in \QDS 2.2, and its functionality will be improved in future
- releases.
-
The \uicontrol Repeater3D component is used to create multiple
similar items. Like other view types, \uicontrol Repeater3D needs a model
and a delegate. The delegate sets the item to use and the model sets the
@@ -100,90 +96,58 @@
\endlist
\image repeater3d-numeric-model.webp
- \section1 Adding a Repeater3D Component with a List Model
+ \section1 Adding a Repeater3D Component with a Model
This section explains how to add a \uicontrol Repeater3D component with
- a ListModel to your \QDS project:
+ a model to your \QDS project:
To add a \uicontrol Repeater3D component:
\list 1
\li Drag a \uicontrol Repeater3D component from \uicontrol Components to
\e scene in \uicontrol Navigator.
- \li You need to enter the QML code for the \uicontrol ListModel manually.
- Go to the \uicontrol {Code} view and enter the following code somewhere
- inside the root object:
- \code qml
- ListModel {
- id: planetModel
- ListElement {
- name: "Mars"
- radius: 3.39
- }
- ListElement {
- name: "Earth"
- radius: 6.37
- }
- ListElement {
- name: "Venus"
- radius: 6.05
- }
- }
- \endcode
- The default root object for a \QDS project is \uicontrol Rectangle, so
- you can paste the \uicontrol ListModel code, for example, like this:
- \code qml
- Rectangle {
- width: Constants.width
- height: Constants.height
- color: Constants.backgroundColor
-
- ListModel {
- id: planetModel
- ListElement {
- name: "Mars"
- radius: 3.39
- }
- ListElement {
- name: "Earth"
- radius: 6.37
- }
- ListElement {
- name: "Venus"
- radius: 6.05
- }
- }
-
- View3D {
- id: view3D
- anchors.fill: parent
- ...
- \endcode
- \li In the \uicontrol {Code} view, add \c {model: planetModel} to the
- \uicontrol Repeater3D object to tell that you want to use your
- \uicontrol ListModel as the model for the \uicontrol Repeater3D object.
- \code qml
- Repeater3D {
- id: repeater3D
- model: planetModel
- }
- \endcode
+ \li Go to \uicontrol {Model Editor} and create a new model with the name
+ \e planetModel.
+ \li Add the following columns and data to the model.
+ \raw HTML
+ <table>
+ <tr>
+ <th>name (<i>String</i>)</th>
+ <th>radius (<i>Real</i>)</th>
+ </tr>
+ <tr>
+ <td>Mars</td>
+ <td>3.39</td>
+ </tr>
+ <tr>
+ <td>Earth</td>
+ <td>6.37</td>
+ </tr>
+ <tr>
+ <td>Venus</td>
+ <td>6.05</td>
+ </tr>
+ </table>
+ \endraw
+ \note You can also import a model in JSON or CSV format. See \l {Importing a Data Model}.
+ \image repeater3d-model-editor.webp
+ \li In \uicontrol Navigator, select \e{_3DRepeater}.
+ \li In \uicontrol Properties, set \uicontrol Model to \e {DataStore.planetModel}.
\endlist
-
Now, you have set up the \uicontrol Repeater3D component to use a
\uicontrol ListModel to draw the items. Next, you need to add the
- item to draw. In this example we are using a \uicontrol Sphere.
+ item to draw. In this example, you are using a \uicontrol Sphere.
\list 1
- \li From \uicontrol Components, drag a \uicontrol Sphere to \e repeater3D
+ \li From \uicontrol Components, drag a \uicontrol Sphere to \e _3DRepeater
in \uicontrol Navigator.
\image repeater3d-listmodel-navigator.png
- \li Select \e sphere in \uicontrol Navigator and select
+ \li Select \e sphere in \uicontrol Navigator and in the \Properties view, select
\inlineimage icons/action-icon.png
next to \uicontrol Scale > \uicontrol X.
\li Select \uicontrol {Set binding} to open \uicontrol {Binding Editor}.
\li In the binding editor, enter \c{radius}. This sets the X
- scale to the radius value defined in the ListModel for each of the sphere
+ scale to the radius value defined in the model for each of the sphere
instances.
\image repeater3d-radius-binding.png
\li Select \uicontrol OK.
@@ -195,7 +159,7 @@
position so you need to change the position to see all spheres.
\list 1
- \li Select \e sphere in \uicontrol Navigator and select
+ \li Select \e sphere in \uicontrol Navigator and in the \uicontrol Properties view, select
\inlineimage icons/action-icon.png
next to \uicontrol Translation > \uicontrol X.
\li Select \uicontrol {Set binding} to open \uicontrol {Binding Editor}.
diff --git a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-scene-environment.qdoc b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-scene-environment.qdoc
index 6e9db7012c..5d18f39a83 100644
--- a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-scene-environment.qdoc
+++ b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-scene-environment.qdoc
@@ -1,4 +1,4 @@
-// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
@@ -6,31 +6,43 @@
\previouspage studio-3d-camera.html
\nextpage studio-3d-morph-target.html
- \title Scene Environment
+ \title Scene Environments
- You can use the \uicontrol {Scene Environment} component to specify
- how a scene is rendered globally. You can specify settings for antialiasing,
- scene background, ambient occlusion, and image-based lighting in the
- \l Properties view. The \uicontrol {Scene Environment} component is available
- in \uicontrol Components > \uicontrol {Qt Quick 3D}. It is
- automatically included under the 3D view component in \l{Creating Projects}
- {projects created} using the \uicontrol {Qt Quick 3D Application} wizard
- template.
+ The \uicontrol {Scene Environment} and the \uicontrol {Extended Scene Environment}
+ components define how a scene is rendered globally.
- \note If you select \uicontrol {Qt 5} as the \uicontrol {Target Qt Version}
- when \l {Creating Projects}{creating your project}, the available properties
- for this component will be slightly different. The properties may also be
- situated differently in the \uicontrol Properties view.
+ \note The available properties for the scene environments and their location in the
+ \uicontrol Properties view vary according to \uicontrol {Target Qt Version} that
+ you select when \l {Creating Projects}{creating your project}.
+
+ \note \uicontrol {Extended Scene Environment} is available in projects created with
+ Qt 6.5 or higher as the \uicontrol {Target Qt Version}.
+
+ \section1 Adding Scene Environments to Projects
+
+ Add the scene environment components to projects by selecting a suitable preset when
+ \l{Creating Projects}{creating your project}.
+
+ Use the \uicontrol {3D} preset to create a project with a \uicontrol View3D
+ component that includes a scene environment. If you need to add it manually, it is
+ available in \uicontrol Components > \uicontrol {Qt Quick 3D}.
+
+ Use the \uicontrol {Extended 3D} preset to create a project with a 3D view
+ component that includes an extended scene environment. It is also
+ available in \uicontrol Components > \uicontrol {Qt Quick 3D Helpers}.
\section1 Setting the Scene Environment
- In the \uicontrol {Scene Environment} section of the \uicontrol Properties
- view, you can specify whether and how the background of the scene should be
- cleared, specify whether you wish to perform depth-tests on the scene,
- apply post-processing effects to the scene, and define how colors are
- tonemapped before the scene is rendered.
+ To define properties for the scene environment, select \uicontrol {Scene Environment}
+ in \uicontrol Navigator and specify its properties in the \uicontrol Properties view.
- \image studio-3d-scene-environment-properties.png "The Scene Environment properties"
+ Set the properties in the \uicontrol {Scene Environment} section of the
+ \uicontrol Properties view to specify whether and how the background
+ of the scene should be cleared, to apply post-processing effects to the scene,
+ to define how colors are tonemapped before the scene is rendered, and to
+ specify fog settings.
+
+ \image studio-3d-scene-environment-properties.webp "The Scene Environment properties"
The \uicontrol {Clear color} property specifies which color will be used to
clear the background of the scene if \uicontrol {Background mode} is defined
@@ -64,23 +76,22 @@
image as a \uicontrol SkyBox using the
\uicontrol Image property in the \uicontrol {Light probe}
section (In Qt 5, the \uicontrol {Light Probe} property in
- the \uicontrol {Image-Based Lighting} group.
+ the \uicontrol {Image-Based Lighting} group).
+ \row
+ \li SkyBoxCubeMap
+ \li The scene will not be cleared, but instead a
+ \uicontrol SkyBox or Skydome that uses a \uicontrol CubeMapTexture
+ will be rendered. A cube map texture has six faces
+ (X+, X-, Y+, Y-, Z+, and Z-), where each face is an individual
+ 2D image. Selecting this mode allows custom materials and post-processing
+ effects to work with cube map textures in their shaders.
\endtable
To leave the scene uncleared, select \uicontrol {Unspecified} as the
\uicontrol {Background mode}.
- You can perform depth tests to optimize the scene environment. To skip the
- depth tests, deselect the \uicontrol {Enable depth test} checkbox. Note that
- skipping the tests can cause rendering errors.
-
- To have the renderer write to the depth buffer as part of the color pass,
- deselect the \uicontrol {Enable depth prepass} checkbox. Deselecting the
- checkbox disables the depth prepass on any GPU that uses tiled rendering
- architecture.
-
- The \uicontrol Effect property defines a post-processing effect to the
- scene. Use the dropdown menu to select one of the effects that will be
+ The \uicontrol Effects property defines post-processing effects applied
+ to the scene. Use the dropdown menu to select one of the effects that will be
applied to the entire scene. The order of the effects is significant since
the result of each effect is fed to the next.
@@ -92,14 +103,21 @@
tonemapping, or \uicontrol ToneMapModeFilmic to apply filmic tonemapping.
\note The \uicontrol {Tonemap mode} property is not available in Qt 5.
+ The \uicontrol Fog property defines settings for fog applied to the
+ scene. When the \uicontrol Fog property of a scene environment is set to a
+ valid \uicontrol Fog object, the properties are used to configure the
+ rendering of fog. The simple fog provided by this type is implemented by
+ the materials. Use the dropdown menu to select a \uicontrol Fog object for
+ your scene.
+
\section1 Applying Antialiasing
- Antialiasing is used to make curved lines smoother on the screen. In the
+ Use antialiasing to make curved lines smoother on the screen. In the
\uicontrol Antialiasing section of the \uicontrol Properties view, you can
specify the mode and quality of antialiasing and also enable temporal
antialiasing and define its strength.
- \image studio-3d-scene-environment-antialiasing.png "The Antialiasing properties"
+ \image studio-3d-scene-environment-antialiasing.webp "The antialiasing properties"
The \uicontrol {Antialiasing mode} property specifies the mode of
antialiasing applied when the scene is rendered. Select one of the following
@@ -174,11 +192,12 @@
animations stop.
The \uicontrol {Temporal AA strength} property modifies the amount of
- temporal movement in antialiasing. This property only has an effect when
+ temporal movement in antialiasing. This property is only available when
the \uicontrol {Temporal AA} property is set to true.
- \note In Qt 5, the antialiasing properties are located in
- \uicontrol Properties > \uicontrol {Scene Environment}.
+ The \uicontrol {Specular AA} property enables specular antialiasing. Specular
+ aliasing is often visible in form of bright dots and flickering when moving the
+ camera around.
\section1 Applying Ambient Occlusion
@@ -188,14 +207,17 @@
\uicontrol {Sample rate}, and \uicontrol Bias properties in the
\uicontrol {Ambient Occlusion} section of the \uicontrol Properties view.
- \image studio-3d-scene-environment-ambient-occlusion.png "The Ambient Occlusion properties"
+ \image studio-3d-scene-environment-ambient-occlusion.webp "The ambient occlusion properties"
+
+ In \uicontrol Properties > \uicontrol {Ambient Occlusion}, select the
+ \uicontrol Enabled checkbox to define settings for ambient occlusion.
- You can set the strength of the shadows using the \uicontrol Strength
- property, which defines the amount of ambient occlusion applied. A value of
- 100 causes full darkness shadows, while lower values cause the shadowing to
- appear lighter. A value of 0 disables ambient occlusion entirely, thus
- improving performance at a cost to the visual realism of 3D objects rendered
- in the scene. All values other than 0 have the same impact on performance.
+ Set the strength of the shadows using the \uicontrol Strength property,
+ which defines the amount of ambient occlusion applied. A value of 100 causes
+ full darkness shadows, while lower values cause the shadowing to appear lighter.
+ A value of 0 disables ambient occlusion entirely, thus improving performance at
+ a cost to the visual realism of 3D objects rendered in the scene. All values other
+ than 0 have the same impact on performance.
The \uicontrol Distance property defines roughly how far the ambient occlusion
shadows spread away from objects. Greater distances cause increasing impact
@@ -213,7 +235,7 @@
occlusion, try adjusting the value in the \uicontrol {Clip far} field in
the \l{Cameras}{scene camera} properties.
- The \uicontrol {Sample rate} property specifies the number of shades of gray,
+ The \uicontrol {Sample Rate} property specifies the number of shades of gray,
thus defining the quality of ambient occlusion at the expense of performance.
The \uicontrol Bias property defines a cutoff distance preventing objects
@@ -227,15 +249,15 @@
differently: \uicontrol {AO strength}, \uicontrol {AO distance},
\uicontrol {AO softness}, \uicontrol {AO dither}, and \uicontrol {AO bias}.
- \section1 Setting the Light Probe
+ \section1 Setting Image Based Lighting
- In the \uicontrol {Light Probe} section of the \uicontrol Properties view,
- you can set the \uicontrol Image, \uicontrol Exposure, \uicontrol Horizon,
+ In the \uicontrol {Image Based Lighting} section of the \uicontrol Properties view,
+ you can set the \uicontrol {HDR Image}, \uicontrol Exposure, \uicontrol Horizon,
and \uicontrol Orientation properties for image-based lighting.
- \image studio-3d-scene-environment-light-probe.png "The Light Probe properties"
+ \image studio-3d-scene-environment-image-based-lighting.webp "Image based lighting properties"
- The \uicontrol Image property defines an image used to light the scene
+ The \uicontrol {HDR Image} property defines an image used to light the scene
instead of or in addition to standard lights. The image is preferably a
high-dynamic range image or a pre-generated cubemap. Pre-baking provides
significant performance improvements at run time because no time is spent on
@@ -286,4 +308,45 @@
The value of the \uicontrol {Probe FOV} property sets the angle of the
image source field of view when using a camera source as the IBL probe.
+
+ \section2 Advanced Scene Environment settings
+
+ You can perform depth tests to optimize the scene environment. To skip the
+ depth tests, clear the \uicontrol {Enable depth test} checkbox. Note that
+ skipping the tests can cause rendering errors.
+
+ To have the renderer write to the depth buffer as part of the color pass,
+ clear the \uicontrol {Enable depth prepass} checkbox. Clearing the
+ checkbox disables the depth prepass on any GPU that uses tiled rendering
+ architecture.
+
+ To specify additional render settings for debugging scenes, define
+ \uicontrol {Debug Settings}.
+
+ To define lightmap baking settings for direct and indirect lighting, use
+ the \uicontrol {Light Mapper} property to specify a lightmapper object.
+ These settings are not relevant at other times, such as when using already
+ generated lightmaps to render a scene.
+
+ \section1 Setting the Extended Scene Environment
+
+ In addition to properties described above, in the extended scene environment
+ you can apply effects to your scene by defining them as properties. When enabling
+ one or more of these effects, the result is similar to manually adding
+ \l {3D Effects}{effects} to \uicontrol {Scene Environment}.
+
+ Use \uicontrol {Extended Scene Environment} instead of \uicontrol {Scene Environment}
+ to add multiple and complex effects to your scene. Because the \uicontrol
+ {Extended Scene Environment} combines the effects that are enabled, the number of
+ render passes is reduced, which results in significantly better performance
+ than applying individual post-processing effects to the scene.
+
+ For the extended scene environment, you can also define \uicontrol {Local Custom Properties}.
+
+ \image studio-ext-scene-environment.webp "Properties of Extended Scene Environment"
+
+ \note If additional post-processing effects are manually added to
+ \uicontrol {Scene Environment}, those effects will be applied before the effects
+ defined in the properties of \uicontrol {Extended Scene Environment}.
+
*/
diff --git a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-view.qdoc b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-view.qdoc
index 5f2f53ca96..1ada3625ff 100644
--- a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-view.qdoc
+++ b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-view.qdoc
@@ -1,4 +1,4 @@
-// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
@@ -8,42 +8,61 @@
\title 3D Views
- To create a Qt Quick 3D UI project, we recommend using a \uicontrol
- {Qt Quick 3D Application} wizard template that adds the
+ To create a Qt Quick 3D UI project, use the \uicontrol {3D} preset that adds the
\l {3D Components}{Qt Quick 3D} components to \uicontrol Components
- and contains a 3D view. A 3D view component includes a
- \l {Scene Environment}{scene environment} as well as a scene
- \l {Lights}{light}, \l {Cameras}{camera}, and
- \l {3D Models}{model}. A default \l {Materials and Shaders}{material}
- is attached to the model. You can attach \l {Textures}{textures}
- to materials. For more information about creating projects, see \l{Creating Projects}.
-
- To add a 3D view to some other kind of a project, you first need to add the
+ and contains a 3D view component. The \uicontrol {View3D} component
+ includes a \l {Scene Environments}{scene environment} as well as a scene \l {Lights}{light},
+ \l {Cameras}{camera}, and \l {3D Models}{model}. A default \l {Materials and Shaders}{material}
+ is attached to the model. You can attach \l {Textures}{textures} to materials.
+
+ To create a project with many complex effects, use the \uicontrol {Extended 3D} preset
+ that creates a project with an \uicontrol {Extended View3D} component.
+ The extended 3D view includes an {Extended Scene Environment}
+ component that enables using various effects by defining them as properties.
+
+ \note The extended 3D view is available in projects created with Qt 6.5
+ or higher set as the target version.
+
+ For more information about creating projects, see \l{Creating Projects}.
+
+ To manually add a 3D view to your project, you first need to add the
\uicontrol {Qt Quick 3D} module to \uicontrol {Components}, as described in
\l {Adding and Removing Modules}.
- \image studio-qtquick-3d-components.png "Qt Quick 3D components in Components"
+ \note \uicontrol {The Qt Quick 3D} module is not available in projects created
+ with Qt 5 set as the target version.
- You can now drag-and-drop a \uicontrol View3D component to the \l Navigator
- or \l {2D} view.
+ \image studio-qtquick-3d-components.webp "QtQuick3D components"
- \image studio-navigator-view3d.png "A View 3D component in the Navigator"
+ You can now drag a \uicontrol View3D or an \uicontrol {Extended View3D} component from
+ \l Components > \uicontrol QtQuick3D > \uicontrol Items to \l Navigator or to the
+ \l {2D} view.
- By default, a directional light and a perspective camera are used in a 3D
- scene created by using the wizard template mentioned above. To use other
- light and camera types, select the component in the \uicontrol{3D} or
- \uicontrol Navigator view and change the type of the component in the \uicontrol
- Type field in \l Properties. For example, to use a point light, enter
- \e {PointLight}.
+ To switch to the \uicontrol 3D view while maintaining the camera orientation of the
+ \uicontrol View3D, right-click a \uicontrol View3D or an \uicontrol {Extended View3D}
+ component in the \uicontrol Navigator or \uicontrol 2D view and select
+ \uicontrol {Edit in 3D View}. Alternatively, you can double-click a \uicontrol View3D
+ or an \uicontrol {Extended View3D} component in the \uicontrol 2D view to open the
+ \uicontrol 3D view. Double-clicking a 3D model in the \uicontrol 2D view opens the
+ \uicontrol 3D view with the 3D model selected.
- \image studio-3d-properties-type.png "Type field in Properties view"
+ \image studio-navigator-view3d.png "A View 3D component in Navigator"
- Similarly to other components, you can select a 3D view in \uicontrol
- Navigator or the \uicontrol{3D} view and modify its property values in the
- \uicontrol Properties view. Use the properties in the \uicontrol View3D
- tab to set properties specific to a 3D view component.
+ By default, a directional light and a perspective camera are used in 3D
+ scenes created by using the \uicontrol 3D and \uicontrol {Extended 3D}
+ presets. To use other light and camera types, select the component in
+ the \uicontrol {3D} or \uicontrol Navigator view and change the type of
+ the component in the \uicontrol Type field in \l Properties. For example,
+ to use a point light, enter \c {PointLight}.
- \image studio-qtquick-3d-view.png "View 3D component properties"
+ \image studio-3d-properties-type.webp "Type field in the Properties view"
+
+ Select a 3D view in \uicontrol Navigator or in \uicontrol{3D} to modify
+ its property values in the \uicontrol Properties view. Use the properties
+ in the \uicontrol View3D tab to set properties specific to a 3D view
+ component.
+
+ \image studio-qtquick-3d-view.webp "View 3D component properties"
The \uicontrol Camera property defines which camera is used to render the
scene to the \uicontrol {2D} view. If this property is not defined, the
@@ -63,4 +82,7 @@
\note The \uicontrol {Import Scene} property can only be set once.
Subsequent changes will have no effect.
+
+ The \uicontrol {Render Format} property defines the format of the backing
+ texture.
*/
diff --git a/doc/qtdesignstudio/src/reference/qtdesignstudio-keyboard-shortcuts.qdoc b/doc/qtdesignstudio/src/reference/qtdesignstudio-keyboard-shortcuts.qdoc
index ac6354ca90..21b195b522 100644
--- a/doc/qtdesignstudio/src/reference/qtdesignstudio-keyboard-shortcuts.qdoc
+++ b/doc/qtdesignstudio/src/reference/qtdesignstudio-keyboard-shortcuts.qdoc
@@ -112,6 +112,9 @@
\li Previous open document in history
\li \key{Ctrl+Tab}
\row
+ \li Toggle \uicontrol {Menu Bar} visibility
+ \li \key{Ctrl+Alt+M}
+ \row
\li Switch to \uicontrol Welcome mode
\li \key{Ctrl+1}
\row
@@ -201,7 +204,10 @@
\li Action
\li Keyboard shortcut
\row
- \li Open the QML file that defines the selected component
+ \li Open the project with \uicontrol {Live Preview}.
+ \li \key{Alt+P} (\key{Opt+P} on \macos)
+ \row
+ \li Open the QML file that defines the selected component.
\li \key{F2}
\row
\li Jump to the \uicontrol {Code} view.
diff --git a/doc/qtdesignstudio/src/views/qtquick-assets.qdoc b/doc/qtdesignstudio/src/views/qtquick-assets.qdoc
index b95bf1e889..fad871debd 100644
--- a/doc/qtdesignstudio/src/views/qtquick-assets.qdoc
+++ b/doc/qtdesignstudio/src/views/qtquick-assets.qdoc
@@ -1,4 +1,4 @@
-// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
@@ -6,43 +6,31 @@
\previouspage quick-components-view.html
\nextpage qtquick-navigator.html
+ \ingroup studio-views
+
\title Assets
+ \brief Select assets such as images and fonts to use in your application.
+
The \uicontrol Assets view lists available assets.
\uicontrol {Assets} displays the images and other files
- that you add to the project folder by dragging-and-dropping external asset
+ that you add to the project folder by dragging external asset
files to \QDS or by selecting \inlineimage icons/plus.png
. For more information about importing assets to \QDS, see
\l {Importing 2D Assets} and \l {Importing 3D Assets}.
- To add assets to your UI, drag-and-drop them from
+ To add assets to your UI, drag them from
\uicontrol Assets to the \l Navigator, \l {2D}, or \l {3D} view.
To add multiple assets to your UI simultaneously, multiselect them first by
holding \key Ctrl and clicking the asset files you wish to select.
- \image qtquick-assets-tab.png "Assets view"
+ \image qtquick-assets-tab.webp "Assets view"
- When you drag-and-drop assets from \uicontrol Assets to the \l Navigator
+ When you drag assets from \uicontrol Assets to the \l Navigator
or \l {2D} view, component instances with a suitable type are
automatically created for you. For example, instances of the
\l{Images}{Image} component will be created for graphics files.
- \section1 Context Menu Commands
-
- \image qtquick-library-context-menu.png "Context menu commands in Assets"
-
- To use the context menu commands in \uicontrol Assets, right-click the
- name of a folder and select one of the following commands:
-
- \list
- \li \uicontrol {Expand All}: expands all folders.
- \li \uicontrol {Collapse All}: collapses all folders.
- \li \uicontrol {Rename Folder}: prompts you to enter a new name
- for the folder.
- \li \uicontrol {New Folder}: creates a new folder.
- \li \uicontrol {Delete Folder}: deletes the folder.
- \endlist
-
*/
diff --git a/doc/qtdesignstudio/src/views/qtquick-components-view.qdoc b/doc/qtdesignstudio/src/views/qtquick-components-view.qdoc
index 1e2786bfbc..5933e4be70 100644
--- a/doc/qtdesignstudio/src/views/qtquick-components-view.qdoc
+++ b/doc/qtdesignstudio/src/views/qtquick-components-view.qdoc
@@ -1,13 +1,18 @@
-// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page quick-components-view.html
\previouspage studio-material-editor.html
\nextpage quick-assets.html
+ \sa {Using Components}
+
+ \ingroup studio-views
\title Components
+ \brief Select preset components and your own components to use in your application.
+
The \uicontrol Component view lists the available components.
\image qtquick-components-tab.png "Components view"
@@ -52,7 +57,7 @@
\li \l{Custom Shaders}
\li \l{Lights}
\li \l{Cameras}
- \li \l{Scene Environment}
+ \li \l{Scene Environments}
\li \l{Morph Target}
\li \l{Repeater3D}
\li \l{Particles}
@@ -86,27 +91,4 @@
final application package, it is recommended that you select
\uicontrol {Remove Module} to remove the ones you don't use in the project.
- \section1 Context Menu Commands
-
- \image qtquick-components-context-menu.png "Context menu commands in Components"
- \image qtquick-components-context-menu-hide.png "Context menu command Hide Category"
-
- To use the context menu commands in \uicontrol Components, right-click the
- name of a module or category and select one of the following commands:
-
- \list
- \li \uicontrol {Remove Module}: removes the module and all of its
- components from \uicontrol Components.
- \li \uicontrol {Expand All}: expands all the modules.
- \li \uicontrol {Collapse All}: collapses all the modules.
- \li \uicontrol {Hide Category}: hides the category from the module.
- \li \uicontrol {Show Module Hidden Categories}: shows the hidden
- categories of the module.
- \li \uicontrol {Show All Hidden Categories}: shows the hidden
- categories in all of the modules.
- \endlist
-
- \note The context menu commands for the \uicontrol Components categories do
- not function if you have entered something into the \uicontrol Search field.
- Clear the \uicontrol Search field to resume using the context menu commands.
*/
diff --git a/doc/qtdesignstudio/src/views/qtquick-connection-view.qdoc b/doc/qtdesignstudio/src/views/qtquick-connection-view.qdoc
index 5cc2c4a667..066ff1c9dc 100644
--- a/doc/qtdesignstudio/src/views/qtquick-connection-view.qdoc
+++ b/doc/qtdesignstudio/src/views/qtquick-connection-view.qdoc
@@ -1,13 +1,19 @@
-// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page qtquick-connection-view.html
\previouspage qtquick-properties-view.html
\nextpage qtquick-states-view.html
+ \sa {Working with Connections}
+
+ \ingroup studio-views
\title Connections
+ \brief Add functionality to the UI by creating connections between components,
+ signals, and component properties.
+
The \uicontrol {Connections} view is a collection of views that enable you
to create connections between components and the application, to bind
component properties together, and to add custom properties for components.
@@ -36,29 +42,4 @@
{preset properties} that you can specify values for. You can add
custom properties that would not otherwise exist for a particular
\l{Component Types}{component type}.
-
- \section1 Summary of the Connections View Tabs
-
- \table
- \header
- \li Tab
- \li Purpose
- \li Read More
- \row
- \li \uicontrol Connections
- \li Create connections between components and the application logic
- by accessing signals outside of the components that emit them.
- \li \l{Connecting Components to Signals}
- \row
- \li \uicontrol Bindings
- \li Dynamically change the behavior of a component by creating a
- binding between the properties of two components.
- \li \l{Adding Bindings Between Properties}
- \row
- \li \uicontrol Properties
- \li Add custom properties that would not otherwise exist for a
- particular preset component or your own custom component.
- \li \l{Specifying Custom Properties}
-
- \endtable
*/
diff --git a/doc/qtdesignstudio/src/views/qtquick-curve-editor.qdoc b/doc/qtdesignstudio/src/views/qtquick-curve-editor.qdoc
index 88ba762f53..52e1ba5963 100644
--- a/doc/qtdesignstudio/src/views/qtquick-curve-editor.qdoc
+++ b/doc/qtdesignstudio/src/views/qtquick-curve-editor.qdoc
@@ -1,4 +1,4 @@
-// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
@@ -6,12 +6,16 @@
\previouspage qtquick-timeline-view.html
\nextpage qtquick-text-editor.html
+ \ingroup studio-views
+
\title Curves
+ \brief View and modify the animation curve.
+
The \uicontrol {Curves} view shows the interpolated values of an animated
property over the animation range.
- \image studio-curve-editor.png "Curves"
+ \image studio-curve-editor.webp "Curves"
When you edit an animation curve, you implicitly edit the
\l{Editing Easing Curves}{easing curves} that the underlying system uses
@@ -20,11 +24,22 @@
simultaneously.
You can use the toolbar buttons to add \uicontrol Linear, \uicontrol Step,
- or \uicontrol Spline interpolation between two keyframes.
+ or \uicontrol Spline interpolation between keyframes.
+
+ To apply interpolation between keyframes:
+ \list 1
+ \li Select the keyframes. To select multiple keyframes, press and hold
+ \key Ctrl, and then select them.
+ \li Select \inlineimage icons/easing-curve-linear-icon.png (\uicontrol Linear),
+ \inlineimage icons/easing-curve-step-icon.png (\uicontrol Step) or
+ \inlineimage icons/easing-curve-spline.png (\uicontrol Spline) depending on
+ which interpolation method you want to use.
+ \endlist
When you set interpolation to \uicontrol Spline, handles appear in
\uicontrol {Curves} that you can use to modify the curve. Select
- \uicontrol Unify to lock the handle on the left of a keyframe to the one
+ \inlineimage icons/easing-curve-unify.png (\uicontrol Unify) to lock the handle on the
+ left of a keyframe to the one
on the right of it so that moving the left handle also moves the right
handle.
@@ -32,53 +47,14 @@
in \l Navigator, you can select \inlineimage icons/lockon.png
to unlock it. You can also lock individual easing curves for editing.
- To lock an animation curve, hover the mouse over the keyframe in the list,
+ To lock an animation curve, hover the mouse over the property in the list,
and then select \inlineimage icons/lockoff.png
.
- To pin an animation curve, hover the mouse over the keyframe in the list,
+ To pin an animation curve, hover the mouse over the property in the list,
and then select \inlineimage icons/pin.png
.
- \section1 Curves Toolbar
-
- The \uicontrol {Curves} toolbar contains the following buttons and
- fields.
-
- \table
- \header
- \li Button/Field
- \li Action
- \row
- \li \inlineimage icons/easing-curve-linear-icon.png
- \li \uicontrol Linear specifies that the interpolation between
- keyframes is linear.
- \row
- \li \inlineimage icons/easing-curve-step-icon.png
- \li \uicontrol Step uses steps for interpolation between keyframes.
- \row
- \li \inlineimage icons/easing-curve-spline-icon.png
- \li \uicontrol Spline uses bezier spline curves for interpolation
- between keyframes and displays handles for managing them.
- \row
- \li \uicontrol {Set Default}
- \li Currently not used.
- \row
- \li \uicontrol Unify
- \li For \uicontrol Spline curves, locks the handle on the left of a
- keyframe to the one on the right.
- \row
- \li Start Frame
- \li Specifies the first frame of the curve.
- \row
- \li End Frame
- \li Specifies the last frame of the curve.
- \row
- \li Current Frame
- \li Displays the frame that the playhead is currently on. Enter a
- number in the field to move the playhead to the respective frame.
- \endtable
-
\section1 Editing Animation Curves
To edit animation curves:
@@ -90,14 +66,14 @@
\uicontrol {Curves} to open the animation curve editor.
\li Right-click in \uicontrol {Curves}, and select
\uicontrol {Insert Keyframe} to add a keyframe.
- \li Select keyframes to display the easing curves attached to them.
- To select multiple keyframes, press and hold \key Ctrl.
+ \li Select properties in the list to display the easing curves attached to them.
+ To select multiple properties, press and hold \key Ctrl, and then select them.
\endlist
Your changes are automatically saved when you close the view.
\section1 Deleting Keyframes in Curves
- To delete the selected keyframe, select \uicontrol {Delete All Keyframes}
+ To delete the selected keyframe, select \uicontrol {Delete Selected Keyframes}
in the context menu.
*/
diff --git a/doc/qtdesignstudio/src/views/qtquick-designer.qdoc b/doc/qtdesignstudio/src/views/qtquick-designer.qdoc
index 3ca0149437..d4fb09efc6 100644
--- a/doc/qtdesignstudio/src/views/qtquick-designer.qdoc
+++ b/doc/qtdesignstudio/src/views/qtquick-designer.qdoc
@@ -1,4 +1,4 @@
-// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
// **********************************************************************
@@ -27,218 +27,8 @@
\section1 Summary of Design Views
- In addition to the summary of design views, the table below includes an MCU
- column that indicates the views which are fully supported on MCU projects.
- For more information, see \l {\QDS Features on MCU Projects}.
+ The following table provides a summary of the design views. For information on
+ MCU support, see \l {\QDS Features on MCU Projects}.
- \table
- \header
- \li View
- \li Purpose
- \li MCU
- \li Read More
- \row
- \li \l {2D}
- \li Provides a working area for designing 2D UIs.
- When you are editing 3D scenes, the \uicontrol {2D} view is
- used as a canvas for the 3D scene projected by the camera.
- \li \image ok.png
- \li \l {2D}
- \row
- \li \l {3D}
- \li Provides an editor for files you created using 3D graphics
- applications and stored in one of the supported formats.
- \li
- \li \l {3D}
- \row
- \li \l {Material Editor and Browser}
- \li In the \uicontrol {Material Editor} and
- \uicontrol {Material Browser} views, you create and manage materials and
- textures.
- \li
- \li \l {Material Editor and Browser}
- \row
- \li \l Components
- \li Contains preset components and your own components, that you can use
- to design you application.
- \li \image ok.png
- \li \l{Using Components}
- \row
- \li \l Assets
- \li Contains assets such as images and fonts that you can use in your
- application.
- \li \image ok.png
- \li \l Assets
- \row
- \li \l Navigator
- \li Displays the composition of the current component file as
- a tree structure. A component file can contain references
- to other components and assets.
- \li \image ok.png
- \li \l Navigator
- \row
- \li \l Properties
- \li Enables you to modify the properties of the selected component.
- \li \image ok.png
- \li \l {Specifying Component Properties}
- \row
- \li \l{Connections}
- \li Enables you to add functionality to the UI by creating
- connections between components, signals, and component properties.
- \li \image ok.png
- \li \l{Working with Connections}
- \row
- \li \l States
- \li Displays the different states that can be applied to a component.
- Typically, states describe UI configurations, such as the
- visibility and behavior of components and the available user
- actions.
- \li \image ok.png
- \li \l{Working with States}
- \row
- \li \l{Transitions}
- \li Enables you to make movement between states smooth by animating
- the changes between states.
- \li \image ok.png
- \li \l{Animating Transitions Between States}
- \row
- \li \l Translations
- \li Provides functionality to add multi-language support to your
- project.
- \li
- \li \l{Translations}
- \row
- \li \l Timeline
- \li Provides a timeline and keyframe based editor for animating
- the properties of components.
- \li \image ok.png
- \li \l{Creating Timeline Animations}
- \row
- \li \l{Curves}
- \li Enables you to view and modify the whole animation curve by
- inserting keyframes to the curve and dragging them and the point
- handlers to modify the curve.
- \li
- \li \l {Editing Animation Curves}
- \row
- \li \l{Code}
- \li Provides a code editor for viewing and modifying the code
- generated by the visual editors.
- \li \image ok.png
- \li \l {Code}
- \row
- \li \l Projects
- \li Shows a list of open projects and the files they contain.
- \li \image ok.png
- \li \l Projects
- \row
- \li \l{File System}
- \li Shows all files in the currently selected directory.
- \li \image ok.png
- \li \l{File System}
- \row
- \li \l{Open Documents}
- \li Shows currently open files.
- \li \image ok.png
- \li \l{Open Documents}
- \row
- \li \l{Content Library}
- \li The \uicontrol {Content Library} view contains material, texture,
- and environment bundles with assets that you can use in your project.
- \li
- \li \l{Content Library}
- \row
- \li \l{Texture Editor}
- \li In the \uicontrol {Texture Editor} view, you create and manage
- textures.
- \li
- \li \l{Texture Editor}
- \row
- \li \l{Effect Composer}
- \li Use \uicontrol {Effect Composer} to compose custom effects.
- \li
- \li \l{Effect Composer}
- \endtable
-
- \section1 Summary of Main Toolbar Actions
-
- The top level toolbar in the \uicontrol Design mode contains shortcuts to
- widely used actions.
-
- \table
- \header
- \li Button/Field
- \li Action
- \li Keyboard Shortcut
- \li Read More
-
- \row
- \li \inlineimage icons/home.png
- \li \uicontrol {Home}: opens the welcome page.
- \li
- \li
- \row
- \li \inlineimage icons/start_playback.png
- \li \uicontrol {Play}: runs the application.
- \li
- \li
- \row
- \li \uicontrol {Live Preview}
- \li Shows a preview of the current file or the entire UI. The changes you
- make to the UI are instantly visible to you in the preview.
- \li \key Alt+P (\key Opt+P on \macos)
- \li \l{Validating with Target Hardware}
-
- \row
- \li Currently open file
- \li Displays the location and filename of the currently open file. You
- can select another file in the list of open files to view it in
- the \uicontrol {2D} and \uicontrol Navigator views.
- \li
- \li \l{Open Documents}
- \row
- \li \inlineimage icons/prev.png
- \li \uicontrol {Go Back}: moves a step backwards in your location history.
- That is, returns the focus to the last location in the last file it
- was on.
- \li \key Alt+< (\key Opt+Cmd+< on \macos)
- \li
- \row
- \li \inlineimage icons/next.png
- \li \uicontrol {Go Forward}: moves a step forward in your location history.
- \li \key Alt+> (\key Opt+Cmd+> on \macos)
- \li
- \row
- \li \inlineimage icons/close.png
- \li \uicontrol {Close Document}: closes the current file.
- \li \key Ctrl+W (\key Cmd+W on \macos)
- \li
- \row
- \li \inlineimage icons/create_component.png
- \li Creates a custom component from the selected item.
- \li
- \li \l{Creating Custom Components}
- \row
- \li \inlineimage icons/edit_component.png
- \li Edits the selected custom component.
- \li
- \li \l{Creating Custom Components}
- \row
- \li Workspace
- \li Displays the currently selected workspace. To switch to another
- workspace, select it in the list.
- \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
- \li \l{Sharing Applications Online}
- \endtable
+ \annotatedlist studio-views
*/
diff --git a/doc/qtdesignstudio/src/views/qtquick-easing-curve-editor.qdoc b/doc/qtdesignstudio/src/views/qtquick-easing-curve-editor.qdoc
index ef518989ce..66b54c0d55 100644
--- a/doc/qtdesignstudio/src/views/qtquick-easing-curve-editor.qdoc
+++ b/doc/qtdesignstudio/src/views/qtquick-easing-curve-editor.qdoc
@@ -1,4 +1,4 @@
-// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
@@ -79,7 +79,7 @@
\endlist
When you attach easing curves to keyframes, the shape of the
- \l{keyframe_marker}{keyframe marker} on a keyframe track in
+ keyframe marker on a keyframe track in
\l Timeline changes from \inlineimage icons/keyframe_linear_active.png
to a marker that describes the type of the selected easing curve.
diff --git a/doc/qtdesignstudio/src/views/qtquick-effect-maker-view.qdoc b/doc/qtdesignstudio/src/views/qtquick-effect-maker-view.qdoc
index 3d7e046d85..f0de1a3522 100644
--- a/doc/qtdesignstudio/src/views/qtquick-effect-maker-view.qdoc
+++ b/doc/qtdesignstudio/src/views/qtquick-effect-maker-view.qdoc
@@ -4,10 +4,14 @@
/*!
\page qtquick-effect-composer-view.html
\previouspage studio-qt-insight.html
- \nextpage creator-project-managing-workspaces.html
+ \nextpage studio-model-editor.html
+
+ \ingroup studio-views
\title Effect Composer
+ \brief Compose custom effects.
+
Use \uicontrol {Effect Composer} to create post-processing effects that
can be applied to 2D or 3D components. The effects created with \uicontrol {Effect Composer}
are shader effects, which can be used in any \QDS projects.
@@ -86,4 +90,4 @@
\uicontrol Navigator, and in \uicontrol Properties >
\uicontrol {Exposed Custom Properties}, select or clear the
\uicontrol timeRunning checkbox.
-
+*/
diff --git a/doc/qtdesignstudio/src/views/qtquick-form-editor.qdoc b/doc/qtdesignstudio/src/views/qtquick-form-editor.qdoc
index 3ac3027392..7ecd0a77db 100644
--- a/doc/qtdesignstudio/src/views/qtquick-form-editor.qdoc
+++ b/doc/qtdesignstudio/src/views/qtquick-form-editor.qdoc
@@ -1,4 +1,4 @@
-// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
@@ -6,13 +6,17 @@
\previouspage creator-using-qt-quick-designer.html
\nextpage studio-3d-editor.html
+ \ingroup studio-views
+
\title 2D
+ \brief Design 2D UIs.
+
You design applications in the \uicontrol {2D} view by opening
component files and placing instances of \l{Component Types}{2D components}
and \l{Assets}{assets} into them.
- \image qmldesigner-form-editor.png "The 2D view"
+ \image qmldesigner-form-editor.webp "The 2D view"
When you select component instances in the \uicontrol {2D} view, markers
appear around their edges and in their corners. Depending on the shape of
@@ -25,60 +29,12 @@
\li \l{Rotating 2D Components}{Rotate}
\endlist
- \section1 Summary of 2D View Buttons
-
- The \uicontrol {2D} view toolbar contains the following buttons and
- fields.
-
- \table
- \header
- \li Button/Field
- \li Tooltip
- \li Read More
- \row
- \li \uicontrol {Override Width}
- \li Shows a preview of the component using the specified width.
- \li \l{Previewing Component Size}
- \row
- \li \uicontrol {Override Height}
- \li Shows a preview of the component using the specified height.
- \li \l{Previewing Component Size}
- \row
- \li \inlineimage icons/canvas-color.png
- \li Sets the color of the \uicontrol {2D} view working area.
- \li \l{Setting Canvas Color}
- \row
- \li \inlineimage icons/zoomIn.png
- \li Zooms in.
- \li \l{Zooming}
- \row
- \li \inlineimage icons/zoomOut.png
- \li Zooms out.
- \li \l{Zooming}
- \row
- \li Zoom level
- \li Sets the zoom level that you select from the list.
- \li \l{Zooming}
- \row
- \li \inlineimage icons/zoomAll.png
- \li Zooms to fit all content.
- \li \l{Zooming}
- \row
- \li \inlineimage icons/zoomSelection.png
- \li Zooms to fit the current selection.
- \li \l{Zooming}
- \row
- \li \inlineimage icons/reset.png
- \li Refreshes the contents of the \uicontrol {2D} view.
- \li \l{Refreshing 2D View Contents}
- \endtable
-
\section1 Moving Components
When the move cursor is displayed, you can move the selected component
instance to any position in the \uicontrol {2D} view.
- \image qmldesigner-form-editor-move-cursor.png "Move cursor in the 2D view"
+ \image qmldesigner-form-editor-move-cursor.webp "Move cursor in the 2D view"
For more information about alternative ways of positioning component
instances in UIs, see \l{Scalable Layouts}.
@@ -88,7 +44,7 @@
When the resize cursor is displayed, you can drag the markers to resize
component instances.
- \image qtquick-designer-scaling-items.png "The 2D view"
+ \image qtquick-designer-scaling-items.webp "The 2D view"
To have the resizing done from the center of the selected component instance
rather than from its edges, press \key Alt (or \key Opt on \macos).
@@ -110,7 +66,7 @@
clockwise or counter-clockwise to freely rotate the component instance
around its origin.
- \image qtquick-designer-rotating-items.png "2D rotation tool"
+ \image qtquick-designer-rotating-items.webp "2D rotation tool"
Additionally, press \key Shift or \key Alt (or \key Opt on \macos)
to rotate component instances in steps of 5 or 45 degrees, respectively.
@@ -152,9 +108,9 @@
\image qtquick-designer-options.png "Qt Quick Designer preferences"
The following image shows the snapping lines (1) when
- \uicontrol {Parent component padding} is set to 5 pixels.
+ \uicontrol {Parent component padding} is set to 10 pixels.
- \image qmldesigner-snap-margins.png "Snapping lines on canvas"
+ \image qmldesigner-snap-margins.webp "Snapping lines on canvas"
For alternative ways of aligning and distributing component instances by
using the \l Properties view, see \l{Aligning and Distributing Components}.
@@ -181,7 +137,7 @@
values are not changed permanently in the UI file. You can permanently
change the property values in the \uicontrol Properties view (4).
- \image qmldesigner-preview-size.png "Component width and height"
+ \image qmldesigner-preview-size.webp "Component width and height"
To set the initial size of the root component, select \uicontrol Edit >
\uicontrol Preferences > \uicontrol {Qt Quick} > \uicontrol {Qt Quick Designer}
@@ -204,7 +160,7 @@
not affect the background color of your root component or component
instances in any way.
- \image qmldesigner-canvas-color.png "Transparent canvas color for a transparent component instance"
+ \image qmldesigner-canvas-color.webp "Transparent canvas color for a transparent component instance"
\section1 Refreshing 2D View Contents
@@ -219,6 +175,4 @@
To refresh the contents of the \uicontrol {2D} view, press \key R or
select the \inlineimage icons/reset.png
(\uicontrol {Reset View}) button.
-
- \include qtquick-component-context-menu.qdocinc context-menu
*/
diff --git a/doc/qtdesignstudio/src/views/qtquick-navigator.qdoc b/doc/qtdesignstudio/src/views/qtquick-navigator.qdoc
index f0cd1fe235..cfba22dc60 100644
--- a/doc/qtdesignstudio/src/views/qtquick-navigator.qdoc
+++ b/doc/qtdesignstudio/src/views/qtquick-navigator.qdoc
@@ -1,4 +1,4 @@
-// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
@@ -6,8 +6,12 @@
\previouspage quick-assets.html
\nextpage qtquick-properties-view.html
+ \ingroup studio-views
+
\title Navigator
+ \brief View the composition of the current component file as a tree structure.
+
The \uicontrol Navigator view displays the components in the current
component file and their relationships. \l{glossary-component}{Components}
(1) are listed in a tree structure, below their parent (2). You can preview
@@ -36,57 +40,11 @@
you can change the source of an Image component by selecting
\uicontrol {Change Source URL} in the context menu.
- \section1 Summary of Navigator Buttons
-
- The following table lists the \uicontrol Navigator buttons:
-
- \table
- \header
- \li Icon
- \li Tooltip
- \li Read More
- \row
- \li \inlineimage icons/arrowleft.png
- \li Moves the component one level up in the component tree, so that
- it becomes the last sibling of its current parent.
- \li \l{Arranging Components}
- \row
- \li \inlineimage icons/arrowright.png
- \li Moves the component one level down in the component tree, so that it
- becomes the child of its last sibling.
- \li \l{Arranging Components}
- \row
- \li \inlineimage icons/navigator-arrowdown.png
- \li Moves the component down within its parent.
- \li \l{Arranging Components}
- \row
- \li \inlineimage icons/navigator-arrowup.png
- \li Moves the component up within its parent.
- \li \l{Arranging Components}
- \row
- \li \inlineimage icons/filtericon.png
- \li Shows and hides invisible components in \uicontrol Navigator.
- \li \l{Showing and Hiding Components}
- \row
- \li \inlineimage icons/alias.png
- \li Adds a property alias that you can use from outside of the
- component.
- \li \l{Adding Property Aliases}
- \row
- \li \inlineimage icons/visibilityon.png
- \li Shows and hides components in the \uicontrol {2D} view.
- \li \l{Showing and Hiding Components}
- \row
- \li \inlineimage icons/lockon.png
- \li Locks components in all views.
- \li \l{Locking Components}
- \endtable
-
\section1 Showing and Hiding Components
To show and hide components in the \uicontrol {2D} view when focusing on
- specific parts of the application, click \inlineimage icons/visibilityon.png
- in \uicontrol Navigator.
+ specific parts of the application, select \inlineimage icons/eye_open.png and
+ \inlineimage icons/visibility-off.png in \uicontrol Navigator.
To change the visibility of a component in the application code, select the
\uicontrol Visibility check box in the \uicontrol Properties view or select
@@ -99,10 +57,8 @@
component. To hide or show child components, edit the properties of the
parent component.
- To hide invisible components in \uicontrol Navigator, click
- \inlineimage icons/filtericon.png
- (\uicontrol {Filter Tree}) and select
- \uicontrol {Show Only Visible Components}.
+ To show and hide invisible components in \uicontrol Navigator, select
+ \inlineimage {icons/visibilityon.png}.
\section1 Locking Components
@@ -141,9 +97,8 @@
By default, components that are located at the top of the file are listed at
the bottom of the \uicontrol Navigator tree and behind overlapping
components in the \uicontrol {2D} view. To list the components in the order
- in which they appear in the file, as some other tools do, click
- \inlineimage icons/filtericon.png
- (\uicontrol {Filter Tree}), and select \uicontrol {Reverse Component Order}.
+ in which they appear in the file, as some other tools do, select
+ \inlineimage {icons/reverse_order.png}.
To move a component to the top or bottom of the tree within its parent,
right-click it in the \uicontrol Navigator or \uicontrol {2D} view
@@ -156,20 +111,18 @@
\image qtquick-designer-navigator-arrange.gif "Reversing component order"
- You can also drag-and-drop the component to another position in the tree or
- use the arrow buttons to move the component in the tree. You can use the
- left and right arrow buttons to change the parent of the component.
+ You can also drag the component to another position in the tree or use the
+ \inlineimage {icons/navigator-arrowup.png} and \inlineimage {icons/navigator-arrowdown.png}
+ buttons to move the component in the tree. You can use the \inlineimage {icons/arrowleft.png}
+ and \inlineimage {icons/arrowright.png} buttons to change the parent of the component.
\image qmldesigner-navigator-arrows.png "Navigator buttons"
- When you drag-and-drop instances of components to the \uicontrol {2D} view,
+ When you drag instances of components to the \uicontrol {2D} view,
the new component is added as a child of the component
beneath it. When you move the components, it is not possible to determine
whether you want to adjust their position or attach them to a new parent component.
- Therefore, the parent component is not automatically changed. To change the
- parent of the component, press down the \key Shift key before you drag-and-drop
- the component into a new position. The topmost component under the cursor becomes the
- new parent of the component.
+ Therefore, the parent component is not automatically changed.
\section1 Adding Property Aliases
@@ -236,5 +189,4 @@
\image qmldesigner-breadcrumbs.png "Component hierarchy"
- \include qtquick-component-context-menu.qdocinc context-menu
*/
diff --git a/doc/qtdesignstudio/src/views/qtquick-properties-view.qdoc b/doc/qtdesignstudio/src/views/qtquick-properties-view.qdoc
index acde01a951..2d660c9951 100644
--- a/doc/qtdesignstudio/src/views/qtquick-properties-view.qdoc
+++ b/doc/qtdesignstudio/src/views/qtquick-properties-view.qdoc
@@ -1,4 +1,4 @@
-// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
@@ -6,21 +6,25 @@
\previouspage qtquick-navigator.html
\nextpage qtquick-connection-view.html
+ \ingroup studio-views
+
\title Properties
+ \brief Modify the properties of the selected component.
+
The \uicontrol Properties view displays all the properties of the selected
\l{glossary-component}{component}. The properties are grouped by type. The
top part of the view displays properties that are common to all components,
such as component type, ID, name, geometry, and visibility.
- \image qtquick-item-properties-common.png "Basic component properties"
+ \image qtquick-item-properties-common.webp "Basic component properties"
The bottom part of the view displays properties that have been defined for
the component type. For example, the following image displays the predefined
properties you can set for \l{basic-rectangle}{Rectangle} and \l Text
components.
- \image qmldesigner-element-properties.png "Rectangle and Text properties"
+ \image qmldesigner-element-properties.webp "Rectangle and Text properties"
\section1 Custom Properties
@@ -42,46 +46,6 @@
\image custom-properties.png
- \section1 Summary of Properties View Buttons
-
- The following table lists the \uicontrol Properties view buttons:
-
- \table
- \header
- \li Icon
- \li Tooltip
- \li Read More
- \row
- \li \inlineimage icons/alias.png
- \li Adds a property alias that you can use from outside of the
- component for the root component. You can use a menu item
- in the actions menu to add property aliases for property
- values of child components.
- \li \l{Adding Property Aliases}
- \row
- \li \inlineimage icons/action-icon.png
- \li Opens a menu with actions for:
- \list
- \li Resetting property values to their default values
- \li Setting property bindings
- \li Creating property aliases
- \li Inserting keyframes for timeline animations
- \endlist
- \li
- \list
- \li \l{Viewing Changes in Properties}
- \li \l{Adding Bindings Between Properties}
- \li \l{Adding Property Aliases}
- \li \l{Setting Keyframe Values}
- \endlist
- \row
- \li \inlineimage icons/action-icon-binding.png
- \li Indicates that the value of the property is bound to the value
- of another property. Opens the same menu as the action icon.
- \li \l{Adding Bindings Between Properties}
-
- \endtable
-
\section1 Viewing Changes in Properties
The default values of properties are displayed in white color, while the
diff --git a/doc/qtdesignstudio/src/views/qtquick-properties.qdoc b/doc/qtdesignstudio/src/views/qtquick-properties.qdoc
index fc8ba92e93..87dfd7a341 100644
--- a/doc/qtdesignstudio/src/views/qtquick-properties.qdoc
+++ b/doc/qtdesignstudio/src/views/qtquick-properties.qdoc
@@ -1,4 +1,4 @@
-// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
@@ -17,7 +17,7 @@
All components share a set of properties that you can specify in the
\uicontrol Properties view.
- \image qtquick-item-properties-common.png "Basic component properties"
+ \image qtquick-item-properties-common.webp "Basic component properties"
\section2 Type
diff --git a/doc/qtdesignstudio/src/views/qtquick-states-view.qdoc b/doc/qtdesignstudio/src/views/qtquick-states-view.qdoc
index 407e2f5769..5270df5b06 100644
--- a/doc/qtdesignstudio/src/views/qtquick-states-view.qdoc
+++ b/doc/qtdesignstudio/src/views/qtquick-states-view.qdoc
@@ -1,4 +1,4 @@
-// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
@@ -7,12 +7,16 @@
\nextpage studio-translations.html
\sa {Working with States}
+ \ingroup studio-views
+
\title States
+ \brief Apply states to a component.
+
The \uicontrol States view displays the different
\l{Working with States}{states} of a UI.
- \image qmldesigner-transitions.png "States view"
+ \image qmldesigner-transitions.webp "States view"
To open the \uicontrol States view, select \uicontrol View >
\uicontrol Views > \uicontrol States.
diff --git a/doc/qtdesignstudio/src/views/qtquick-text-editor.qdoc b/doc/qtdesignstudio/src/views/qtquick-text-editor.qdoc
index f202df3c37..6941a1c2ec 100644
--- a/doc/qtdesignstudio/src/views/qtquick-text-editor.qdoc
+++ b/doc/qtdesignstudio/src/views/qtquick-text-editor.qdoc
@@ -6,8 +6,12 @@
\previouspage qtquick-curve-editor.html
\nextpage creator-projects-view.html
+ \ingroup studio-views
+
\title Code
+ \brief View and modify the code generated by the visual editors.
+
To view and modify the code in a \l{UI Files}{UI file} (.ui.qml) or
component file (.qml), go to \uicontrol View and select \uicontrol Views >
\uicontrol Code. \QDS generates the code when you create components in the
diff --git a/doc/qtdesignstudio/src/views/qtquick-timeline-view.qdoc b/doc/qtdesignstudio/src/views/qtquick-timeline-view.qdoc
index 8194726184..2e34d70dc4 100644
--- a/doc/qtdesignstudio/src/views/qtquick-timeline-view.qdoc
+++ b/doc/qtdesignstudio/src/views/qtquick-timeline-view.qdoc
@@ -1,4 +1,4 @@
-// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
@@ -6,14 +6,18 @@
\previouspage qtquick-transition-editor.html
\nextpage qtquick-curve-editor.html
+ \ingroup studio-views
+
\title Timeline
+ \brief Animate the properties of components.
+
You can use the timeline and keyframe based editor in the
\uicontrol Timeline view to animate the properties of
\l{glossary_component}{components}. The view is empty until
you create a timeline.
- \image studio-timeline-empty.png "Empty Timeline view"
+ \image studio-timeline-empty.webp "Empty Timeline view"
Select the \inlineimage icons/plus.png
(\uicontrol {Add Timeline}) button to
@@ -23,7 +27,7 @@
\image studio-timeline-settings.png "Timeline Settings dialog"
When you select \uicontrol Close, the \uicontrol Timeline view appears.
- It now displays a \l{Timeline Toolbar}{toolbar} and a ruler but no
+ It now displays a toolbar and a ruler but no
keyframe tracks.
\image studio-timeline-no-tracks.webp "Timeline view without keyframe tracks"
@@ -86,171 +90,4 @@
\image studio-timeline-keyframe-track-colors.webp "Keyframe track colors in Timeline"
- \section1 Timeline Toolbar
-
- The \uicontrol Timeline toolbar contains the following buttons and fields.
-
- \table
- \header
- \li Button/Field
- \li Action
- \li Read More
- \row
- \li \inlineimage icons/settings.png
- \li Opens the \uicontrol {Timeline Settings} dialog for editing
- timeline settings.
- \li \l{Creating a Timeline}
- \row
- \li Timeline ID
- \li Displays the ID of the current timeline.
- \li \l{Creating a Timeline}
- \row
- \li \inlineimage icons/to_first_frame.png
- \li \uicontrol {To Start (Home)} moves to the first frame on the
- timeline.
- \li \l{Navigating in Timeline}
- \row
- \li \inlineimage icons/back_one_frame.png
- \li \uicontrol {Previous (,)} moves to the previous frame on the
- timeline.
- \li \l{Navigating in Timeline}
- \row
- \li \inlineimage icons/start_playback.png
- \li \uicontrol {Play (Space)} previews the animation.
- \li \l{Viewing the Animation}
- \row
- \li \inlineimage icons/forward_one_frame.png
- \li \uicontrol {Next (.)} moves to the next frame on the timeline.
- \li \l{Navigating in Timeline}
- \row
- \li \inlineimage icons/to_last_frame.png
- \li \uicontrol {To End (End)} moves to the last frame on the timeline.
- \li \l{Navigating in Timeline}
- \row
- \li Current Keyframe
- \li Displays the frame that the playhead is currently on. Enter a
- number in the field to move the playhead to the respective frame.
- \li \l{Navigating in Timeline}
- \row
- \li \inlineimage icons/global_record_keyframes.png
- \li Records changes in keyframe values.
- \li \l {Setting Keyframe Values}
- \row
- \li \inlineimage icons/curve_editor.png
- \li Opens \uicontrol {Easing Curve Editor} for attaching an easing
- curve to the selected transition.
- \li \l{Editing Easing Curves}
- \row
- \li Start Frame
- \li Specifies the first frame of the timeline. Negative values are
- allowed. The difference between the start frame and the end frame
- determines the duration of the animation.
- \li \l{Creating a Timeline}
- \row
- \li \inlineimage icons/zoomOut.png
- \li \uicontrol {Zoom Out} (\key Ctrl+-) zooms out of the view.
- \li \l{Zooming in Timeline}
- \row
- \li Slider
- \li Sets the zooming level.
- \li \l{Zooming in Timeline}
- \row
- \li \inlineimage icons/zoomIn.png
- \li \uicontrol {Zoom In} (\key Ctrl++) zooms into the view.
- \li \l{Zooming in Timeline}
- \row
- \li End Frame
- \li Specifies the last frame of the timeline. The difference between
- the start frame and the end frame determines the duration of the
- animation, so if the start frame is 0, the end frame equals the
- duration.
- \li \l{Creating a Timeline}
- \row
- \li State Name
- \li Displays the name of the current state.
- \li \l{Binding Animations to States}
- \endtable
-
- \section1 Keyframe Track Icons
-
- Each keyframe track can contain the following buttons and markers.
-
- \table
- \header
- \li Button/Icon
- \li Action
- \li Read More
- \row
- \li \inlineimage icons/previous_keyframe.png
- \li Jumps to the previous frame on the timeline.
- \li \l{Setting Keyframe Values}
- \row
- \li \inlineimage icons/next_keyframe.png
- \li Jumps to the next frame on the timeline.
- \li \l{Setting Keyframe Values}
- \row
- \li \inlineimage icons/local_record_keyframes.png
- \li Records changes in keyframe values for a particular property.
- \li \l {Setting Keyframe Values}
- \target keyframe_marker
- \row
- \li \inlineimage icons/keyframe.png
- \li Indicates the type of easing curve attached to the keyframe.
- When a keyframe track is selected, the keyframe markers on it turn
- gray, and when a keyframe itself is selected, its marker turns
- brown:
- \list
- \li \inlineimage icons/keyframe_linear_active.png
- - linear easing curve
- \li \inlineimage icons/keyframe_manualbezier_active.png
- - manually set Bezier curve
- \li \inlineimage icons/keyframe_autobezier_active.png
- - automatically set Bezier curve
- \li \inlineimage icons/keyframe_lineartobezier_active.png
- - linear-to-Bezier curve
- \endlist
- \li \l {Editing Easing Curves}
- \endtable
-
- \section1 Timeline Context Menu
-
- The following table summarizes the context menu items available for each
- keyframe track for a component, property, or keyframe marker and provides
- links to more information about them.
-
- \table
- \header
- \li To Learn About
- \li Go To
- \row
- \li Delete All Keyframes
- \li \l{Deleting Keyframes}
- \row
- \li Add Keyframes at Current Frame
- \li \l{Setting Keyframe Values}
- \row
- \li Copy All Keyframes
- \li \l{Copying Keyframes}
- \row
- \li Paste Keyframes
- \li \l{Copying Keyframes}
- \row
- \li Remove Property
- \li \l{Setting Keyframe Values}
- \row
- \li Delete Keyframe
- \li \l{Deleting Keyframes}
- \row
- \li Edit Easing Curve
- \li \l{Editing Easing Curves}
- \row
- \li Edit Keyframe
- \li \l{Editing Keyframe Values}
- \row
- \li Override Color
- \li \l{Setting Keyframe Track Color}
- \row
- \li Reset Color
- \li \l{Setting Keyframe Track Color}
- \endtable
*/
diff --git a/doc/qtdesignstudio/src/views/qtquick-timeline.qdoc b/doc/qtdesignstudio/src/views/qtquick-timeline.qdoc
index c6a33f62c7..b599932ed0 100644
--- a/doc/qtdesignstudio/src/views/qtquick-timeline.qdoc
+++ b/doc/qtdesignstudio/src/views/qtquick-timeline.qdoc
@@ -1,4 +1,4 @@
-// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
@@ -191,7 +191,7 @@
position of the playhead, right-click the component name on the timeline and
select \uicontrol {Add Keyframes at Current Frame}.
- Keyframes are marked on the timeline by using \l{keyframe_marker}{markers}
+ Keyframes are marked on the timeline by using markers
of different colors and shapes, depending on whether they are active or
inactive or whether you have applied \l{Editing Easing Curves}
{easing curves} to them.
diff --git a/doc/qtdesignstudio/src/views/qtquick-transition-editor.qdoc b/doc/qtdesignstudio/src/views/qtquick-transition-editor.qdoc
index b21207259e..7f73e0ceca 100644
--- a/doc/qtdesignstudio/src/views/qtquick-transition-editor.qdoc
+++ b/doc/qtdesignstudio/src/views/qtquick-transition-editor.qdoc
@@ -1,4 +1,4 @@
-// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
@@ -6,8 +6,12 @@
\previouspage studio-translations.html
\nextpage qtquick-timeline-view.html
+ \ingroup studio-views
+
\title Transitions
+ \brief Make movement between states smooth.
+
To make movement between states smooth, you can use
\uicontrol {Transitions} to animate the changes between
states.
@@ -17,7 +21,7 @@
animated, such as colors or numbers, in the \l Properties view. For example,
you can animate the changes in the position of a component.
- \image qtquick-transition-editor-view.png "Transitions view"
+ \image qtquick-transition-editor-view.webp "Transitions view"
In \uicontrol {Transitions}, you can set the start frame, end
frame, and duration for the transition of each property. You can also
@@ -31,46 +35,6 @@
and \inlineimage icons/zoom_big.png
buttons to zoom out of or into the view.
- \section1 Summary of Transitions Toolbar Actions
-
- \table
- \header
- \li Button/Field
- \li Action
- \li Read More
- \row
- \li \inlineimage icons/settings.png
- \li Opens \uicontrol {Transition Settings} dialog for editing
- transition settings.
- \li \l{Specifying Transition Settings}
- \row
- \li Transition ID
- \li Displays a list of transitions that you can open in
- \uicontrol {Transitions}.
- \li \l{Animating Transitions Between States}
- \row
- \li \inlineimage icons/curve_editor.png
- \li Opens \uicontrol {Easing Curve Editor} for attaching an easing
- curve to the selected transition.
- \li \l{Editing Easing Curves}
- \row
- \li \inlineimage icons/zoomOut.png
- \li \uicontrol {Zoom Out} (\key Ctrl+-): zooms out of the view.
- \li \l{Zooming in Transitions}
- \row
- \li Slider
- \li Sets the zooming level.
- \li \l{Zooming in Transitions}
- \row
- \li \inlineimage icons/zoomIn.png
- \li \uicontrol {Zoom In} (\key Ctrl++): zooms into the view.
- \li \l{Zooming in Transitions}
- \row
- \li Maximum Duration
- \li Specifies the maximum duration of the transition.
- \li
- \endtable
-
\section1 Animating Transitions Between States
To animate transitions:
@@ -78,12 +42,12 @@
\list 1
\li Select \uicontrol View > \uicontrol Views >
\uicontrol {Transition Editor}.
- \image qmldesigner-transition-editor-startup.png "Empty Transitions view"
+ \image qmldesigner-transition-editor-startup.webp "Empty Transitions view"
\li Select the \inlineimage icons/plus.png
(\uicontrol {Add Transition}) button to add a transition. This
works only if you have added at least one state and modified at
least one property in it.
- \image qtquick-transition-editor-view.png "Transitions view"
+ \image qtquick-transition-editor-view.webp "Transitions view"
\li Move the blue bar next to the component or property name to set
the start and end frame of the animation of the property. Pull its
left and right edges to set the duration of the animation.
@@ -98,7 +62,7 @@
(\uicontrol {Transition Settings (S)}) button in
\uicontrol {Transition Editor}.
- \image qtquick-transition-editor-settings.png "Transitions settings"
+ \image qtquick-transition-editor-settings.webp "Transitions settings"
To add transitions:
diff --git a/doc/qtdesignstudio/src/views/studio-content-library.qdoc b/doc/qtdesignstudio/src/views/studio-content-library.qdoc
index e2785149e1..b3dbb28065 100644
--- a/doc/qtdesignstudio/src/views/studio-content-library.qdoc
+++ b/doc/qtdesignstudio/src/views/studio-content-library.qdoc
@@ -6,8 +6,13 @@
\previouspage creator-open-documents-view.html
\nextpage studio-texture-editor.html
+ \ingroup studio-views
+
\title Content Library
+ \brief Select material, texture, and environment bundles with assets to
+ use in your application.
+
\note The \uicontrol {Content Library} view is included in the
\l{https://www.qt.io/pricing}{Qt Design Studio Enterprise license}.
diff --git a/doc/qtdesignstudio/src/views/studio-material-editor.qdoc b/doc/qtdesignstudio/src/views/studio-material-editor.qdoc
index bb2923a7ab..44cea9504a 100644
--- a/doc/qtdesignstudio/src/views/studio-material-editor.qdoc
+++ b/doc/qtdesignstudio/src/views/studio-material-editor.qdoc
@@ -1,4 +1,4 @@
-// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
@@ -6,9 +6,12 @@
\previouspage studio-3d-editor.html
\nextpage quick-components-view.html
+ \ingroup studio-views
\title Material Editor and Browser
+ \brief Create and manage materials and textures.
+
In the \uicontrol {Material Editor} and \uicontrol {Material Browser} views,
you create and manage materials and textures.
@@ -21,7 +24,8 @@
To create a new material, do one of the following:
\list
- \li In \uicontrol {Material Browser}, select \inlineimage icons/plus.png
+ \li In \uicontrol {Material Browser}, select \inlineimage icons/add_material.png
+ \inlineimage icons/plus.png
.
\li In \uicontrol {Material Editor}, select \inlineimage icons/plus.png
.
@@ -67,7 +71,7 @@
\li In \uicontrol{Properties}, select
\inlineimage icons/close.png
next to the material.
- \image materials-remove-material.png
+ \image materials-remove-material.webp "Remove a material in model properties"
\endlist
\section2 Copying and Pasting Material Properties
@@ -82,7 +86,7 @@
want to copy properties from.
\li Select \uicontrol {Copy properties} and then
\uicontrol All or a property group.
- \image material-copy-properties.png
+ \image material-copy-properties.png "Copy material properties in Material Browser"
\li Right-click the material that you want to copy the properties to.
\li Select \uicontrol {Paste properties}.
\endlist
@@ -114,11 +118,10 @@
\li From \uicontrol{Assets}, drag an image to
\uicontrol{Reflection Map}.
\li In \uicontrol {Navigator}, select
- \inlineimage icons/filtericon.png
- and then clear \uicontrol {Show Only Visible Components}. Now the
+ \inlineimage {icons/visibilityon.png}. Now the
texture you just added to the material is visible in
\uicontrol {Navigator}.
- \image navigator-material-texture.png
+ \image navigator-material-texture.webp "Materials visible in Navigator"
\li In \uicontrol {Navigator}, select the texture.
\li In \uicontrol {Properties}, set \uicontrol {Texture Mapping} to
\uicontrol {Environment}.
@@ -276,8 +279,8 @@
To create a new texture, do one of the following in
\uicontrol {Material Browser}:
\list
- \li Select \inlineimage icons/plus.png
- in the \uicontrol Textures section.
+ \li Select \inlineimage icons/add_texture.png \inlineimage icons/plus.png
+ .
\li Right-click anywhere in the \uicontrol Textures section and select
\uicontrol {Create new texture}.
\endlist
diff --git a/doc/qtdesignstudio/src/views/studio-model-editor.qdoc b/doc/qtdesignstudio/src/views/studio-model-editor.qdoc
new file mode 100644
index 0000000000..4d10f87552
--- /dev/null
+++ b/doc/qtdesignstudio/src/views/studio-model-editor.qdoc
@@ -0,0 +1,62 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \page studio-model-editor.html
+ \previouspage qtquick-effect-composer-view.html
+ \nextpage creator-project-managing-workspaces.html
+
+ \ingroup studio-views
+
+ \title Model Editor
+
+ \brief Create, manage, import, and export data models.
+
+ In the \uicontrol {Model Editor} view, you can create, manage, import, and export
+ data models. With data models, you can, for example, populate views with data.
+
+ \image edit-list-model-model-editor.webp
+
+ For examples of how to use data models, see
+ \l {Adding a Repeater3D Component with a List Model}.
+
+ \section1 Creating a Data Model
+
+ To create a data model:
+ \list 1
+ \li In \uicontrol {Model Editor}, select \inlineimage {icons/zoomIn.png}.
+ \li Enter a name and select \uicontrol {Create}.
+ \endlist
+
+ This creates a single-cell table.
+
+ \image model-editor-new-model.webp
+
+ Next, add columns, rows, and data to the model.
+
+ \note You must manually save the table after you have made changes. To do this,
+ select \inlineimage {icons/save-effect-composer.png}.
+
+ \section1 Editing a Data Model
+
+ Edit a data model in one of the following ways:
+ \list
+ \li Right-click a column name to edit its name and type, delete, or sort it.
+ \li Double-click a cell to edit its content.
+ \li Use the toolbar to add and remove columns and rows.
+ \endlist
+
+ \note You must manually save the table after you have made changes. To do this,
+ select \inlineimage {icons/save-effect-composer.png}.
+
+ \section1 Importing a Data Model
+
+ Import data models from JSON or CSV files. To do this, select \inlineimage {icons/import.png}
+ in \uicontrol {Model Editor}.
+
+ \section1 Exporting a Data Model
+
+ Export data models to JSON or CSV files. To do this, select \inlineimage {icons/export.png}
+ in \uicontrol {Model Editor}.
+
+*/
diff --git a/doc/qtdesignstudio/src/views/studio-qtinsight.qdoc b/doc/qtdesignstudio/src/views/studio-qtinsight.qdoc
index 6af9b071e1..6f420e1cb7 100644
--- a/doc/qtdesignstudio/src/views/studio-qtinsight.qdoc
+++ b/doc/qtdesignstudio/src/views/studio-qtinsight.qdoc
@@ -6,8 +6,12 @@
\previouspage studio-texture-editor.html
\nextpage qtquick-effect-composer-view.html
+ \ingroup studio-views
+
\title Qt Insight
+ \brief Manage your Qt Insight.
+
In the \uicontrol {Qt Insight} view, you manage your Qt Insight.
Qt Insight is an analytics solution that provides real user insights on the usage of Qt
diff --git a/doc/qtdesignstudio/src/views/studio-texture-editor.qdoc b/doc/qtdesignstudio/src/views/studio-texture-editor.qdoc
index ef45d8efdf..62b0eb147c 100644
--- a/doc/qtdesignstudio/src/views/studio-texture-editor.qdoc
+++ b/doc/qtdesignstudio/src/views/studio-texture-editor.qdoc
@@ -1,4 +1,4 @@
-// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
@@ -6,11 +6,15 @@
\previouspage studio-content-library.html
\nextpage studio-qt-insight.html
+ \ingroup studio-views
+
\title Texture Editor
+ \brief Create and manage textures.
+
In the \uicontrol {Texture Editor} view, you create and manage textures.
- \image texture-editor.png
+ \image texture-editor.webp "Texture Editor"
\section1 Creating a Texture
@@ -38,7 +42,7 @@
\li Select \inlineimage icons/apply.png
.
\li Select the material and property that you want to add the texture to.
- \image select-material-property.png
+ \image select-material-property.png "Select a material property"
\endlist
\note You can also apply textures to materials in the
diff --git a/doc/qtdesignstudio/src/views/studio-translations.qdoc b/doc/qtdesignstudio/src/views/studio-translations.qdoc
index a2a610b313..ecf43369a4 100644
--- a/doc/qtdesignstudio/src/views/studio-translations.qdoc
+++ b/doc/qtdesignstudio/src/views/studio-translations.qdoc
@@ -1,4 +1,4 @@
-// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
@@ -6,8 +6,12 @@
\previouspage qtquick-states-view.html
\nextpage qtquick-timeline-view.html
+ \ingroup studio-views
+
\title Translations
+ \brief Handle translations and multi-language support.
+
The \uicontrol Translations view is included in the
\l{https://www.qt.io/pricing}{Qt Design Studio Enterprise license}.
@@ -16,49 +20,6 @@
\image studio-translations-view.png "Translations view"
- \section1 Summary of Translations View Buttons
-
- The \uicontrol {Translations} view contains the following buttons.
-
- \table
- \header
- \li Button
- \li Function
- \li Read More
- \row
- \li \inlineimage icons/select-languages.png
- \li Select which languages you want your project to support.
- \li
- \row
- \li \inlineimage icons/export-json-translations.png
- \li Export all your translations to a JSON file.
- \li \l{Importing and Exporting Translations}
- \row
- \li \inlineimage icons/import-json-translations.png
- \li Import translations from a JSON file.
- \li \l{Importing and Exporting Translations}
- \row
- \li \inlineimage icons/generate-translation-files.png
- \li Generate Qt compiled translation source files (\e{.qm})
- and Qt translation source files (\e{.ts}).
- \li \l{Generating Qt Translation Source Files}
- \row
- \li \inlineimage icons/project-translation-test.png
- \li Run translation test for several documents and create a test report.
- \li \l{Running Translation Test for Several Documents}
- \row
- \li \inlineimage icons/qml-translation-test.png
- \li Run translation test for the currently open document. This test
- shows translation warnings in the \uicontrol{2D} view and creates a
- test report.
- \li \l{Running Translation Test for a Single Document}
- \row
- \li \inlineimage icons/export-translations.png
- \li Export all translations used in your project or all translations
- currently visible in your UI.
- \li \l{Exporting Translations in Other Ways}
- \endtable
-
\section1 Importing and Exporting Translations
You can import and export translations using JSON files.
diff --git a/doc/qtdesignstudio/src/views/studio-workspaces.qdoc b/doc/qtdesignstudio/src/views/studio-workspaces.qdoc
index 407513c40f..ed79be99d1 100644
--- a/doc/qtdesignstudio/src/views/studio-workspaces.qdoc
+++ b/doc/qtdesignstudio/src/views/studio-workspaces.qdoc
@@ -3,7 +3,7 @@
/*!
\page creator-project-managing-workspaces.html
- \previouspage qtquick-effect-composer-view.html
+ \previouspage studio-model-editor.html
\nextpage creator-project-managing-sessions.html
\title Managing Workspaces
diff --git a/share/qtcreator/qmldesigner/assetsLibraryQmlSources/Assets.qml b/share/qtcreator/qmldesigner/assetsLibraryQmlSources/Assets.qml
index cfa4020995..26bef6f8e9 100644
--- a/share/qtcreator/qmldesigner/assetsLibraryQmlSources/Assets.qml
+++ b/share/qtcreator/qmldesigner/assetsLibraryQmlSources/Assets.qml
@@ -94,7 +94,7 @@ Item {
anchors.fill: parent
acceptedButtons: Qt.RightButton
onClicked: {
- if (assetsModel.haveFiles) {
+ if (assetsModel.hasFiles) {
function onFolderCreated(path) {
assetsView.addCreatedFolder(path)
}
@@ -182,13 +182,13 @@ Item {
leftPadding: 10
color: StudioTheme.Values.themeTextColor
font.pixelSize: StudioTheme.Values.baseFont
- visible: !assetsModel.haveFiles && !root.__searchBoxEmpty
+ visible: !assetsModel.hasFiles && !root.__searchBoxEmpty
}
Item { // placeholder when the assets library is empty
width: parent.width
height: parent.height - toolbar.height - column.spacing
- visible: !assetsModel.haveFiles && root.__searchBoxEmpty
+ visible: !assetsModel.hasFiles && root.__searchBoxEmpty
clip: true
MouseArea { // right clicking the empty area of the view
diff --git a/share/qtcreator/qmldesigner/assetsLibraryQmlSources/AssetsContextMenu.qml b/share/qtcreator/qmldesigner/assetsLibraryQmlSources/AssetsContextMenu.qml
index 391c622048..a8eb5285f5 100644
--- a/share/qtcreator/qmldesigner/assetsLibraryQmlSources/AssetsContextMenu.qml
+++ b/share/qtcreator/qmldesigner/assetsLibraryQmlSources/AssetsContextMenu.qml
@@ -83,7 +83,7 @@ StudioControls.Menu {
root.__selectedAssetPathsList = selectedAssetPathsList
root.__fileIndex = fileIndex
root.__dirIndex = dirModelIndex
- root.__dirPath = AssetsLibraryBackend.assetsModel.filePath(dirModelIndex)
+ root.__dirPath = root.assetsModel.filePath(dirModelIndex)
root.__isDirectory = false
root.popup()
}
@@ -124,9 +124,9 @@ StudioControls.Menu {
id: addTexturesItem
text: qsTr("Add Texture")
enabled: rootView.hasMaterialLibrary
- visible: root.__fileIndex && AssetsLibraryBackend.assetsModel.allFilePathsAreTextures(root.__selectedAssetPathsList)
+ visible: root.__fileIndex && root.assetsModel.allFilePathsAreTextures(root.__selectedAssetPathsList)
height: addTexturesItem.visible ? addTexturesItem.implicitHeight : 0
- onTriggered: AssetsLibraryBackend.rootView.addTextures(root.__selectedAssetPathsList)
+ onTriggered: root.rootView.addTextures(root.__selectedAssetPathsList)
}
StudioControls.MenuItem {
@@ -134,7 +134,7 @@ StudioControls.Menu {
text: qsTr("Add Light Probe")
enabled: rootView.hasMaterialLibrary && rootView.hasSceneEnv
visible: root.__fileIndex && root.__selectedAssetPathsList.length === 1
- && AssetsLibraryBackend.assetsModel.allFilePathsAreTextures(root.__selectedAssetPathsList)
+ && root.assetsModel.allFilePathsAreTextures(root.__selectedAssetPathsList)
height: addLightProbes.visible ? addLightProbes.implicitHeight : 0
onTriggered: rootView.addLightProbe(root.__selectedAssetPathsList[0])
}
@@ -145,7 +145,7 @@ StudioControls.Menu {
visible: root.__fileIndex
height: deleteFileItem.visible ? deleteFileItem.implicitHeight : 0
onTriggered: {
- let deleted = AssetsLibraryBackend.assetsModel.requestDeleteFiles(root.__selectedAssetPathsList)
+ let deleted = root.assetsModel.requestDeleteFiles(root.__selectedAssetPathsList)
if (!deleted)
confirmDeleteFiles.open()
}
@@ -182,7 +182,7 @@ StudioControls.Menu {
StudioControls.MenuItem {
text: qsTr("New Folder")
- visible: AssetsLibraryBackend.assetsModel.haveFiles
+ visible: root.assetsModel.hasFiles
height: visible ? implicitHeight : 0
NewFolderDialog {
@@ -209,11 +209,11 @@ StudioControls.Menu {
}
onTriggered: {
- if (!AssetsLibraryBackend.assetsModel.hasChildren(root.__dirIndex)) {
+ if (!root.assetsModel.hasChildren(root.__dirIndex)) {
// NOTE: the folder may still not be empty -- it doesn't have files visible to the
// user, but that doesn't mean that there are no other files (e.g. files of unknown
// types) on disk in this directory.
- AssetsLibraryBackend.assetsModel.deleteFolderRecursively(root.__dirIndex)
+ root.assetsModel.deleteFolderRecursively(root.__dirIndex)
} else {
confirmDeleteFolderDialog.open()
}
@@ -222,7 +222,7 @@ StudioControls.Menu {
StudioControls.MenuItem {
text: qsTr("New Effect")
- visible: rootView.canCreateEffects()
+ visible: root.rootView.canCreateEffects()
height: visible ? implicitHeight : 0
NewEffectDialog {
@@ -235,15 +235,22 @@ StudioControls.Menu {
}
StudioControls.MenuItem {
- text: rootView.showInGraphicalShellMsg()
+ text: root.rootView.showInGraphicalShellMsg()
enabled: root.__showInGraphicalShellEnabled
onTriggered: {
if (!root.__fileIndex || root.__selectedAssetPathsList.length > 1)
- rootView.showInGraphicalShell(root.__dirPath)
+ root.rootView.showInGraphicalShell(root.__dirPath)
else
- rootView.showInGraphicalShell(root.__selectedAssetPathsList[0])
+ root.rootView.showInGraphicalShell(root.__selectedAssetPathsList[0])
}
}
+
+ StudioControls.MenuItem {
+ text: qsTr("Add to Content Library")
+ visible: root.rootView.userBundleEnabled() && root.__fileIndex && root.assetsModel.allFilePathsAreTextures(root.__selectedAssetPathsList)
+ height: visible ? implicitHeight : 0
+ onTriggered: root.rootView.addAssetsToContentLibrary(root.__selectedAssetPathsList)
+ }
}
diff --git a/share/qtcreator/qmldesigner/assetsLibraryQmlSources/AssetsView.qml b/share/qtcreator/qmldesigner/assetsLibraryQmlSources/AssetsView.qml
index 9326e6a5e3..aeabc92c6d 100644
--- a/share/qtcreator/qmldesigner/assetsLibraryQmlSources/AssetsView.qml
+++ b/share/qtcreator/qmldesigner/assetsLibraryQmlSources/AssetsView.qml
@@ -70,9 +70,9 @@ TreeView {
model: assetsModel
onRowsChanged: {
- if (root.rows > root.rootPathRow + 1 && !assetsModel.haveFiles ||
- root.rows <= root.rootPathRow + 1 && assetsModel.haveFiles) {
- assetsModel.syncHaveFiles()
+ if (root.rows > root.rootPathRow + 1 && !assetsModel.hasFiles ||
+ root.rows <= root.rootPathRow + 1 && assetsModel.hasFiles) {
+ assetsModel.syncHasFiles()
}
root.updateRows()
@@ -366,7 +366,7 @@ TreeView {
function moveSelection(amount)
{
- if (!assetsModel.haveFiles || !amount)
+ if (!assetsModel.hasFiles || !amount)
return
let index = root.currentFilePath ? assetsModel.indexForPath(root.currentFilePath)
diff --git a/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionDetailsEditDelegate.qml b/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionDetailsEditDelegate.qml
index 90b3021c96..fd969382e6 100644
--- a/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionDetailsEditDelegate.qml
+++ b/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionDetailsEditDelegate.qml
@@ -96,6 +96,16 @@ Item {
if (realField.activeFocus)
realField.contentItem.focus = true
}
+
+ textFromValue: function (value, locale) {
+ locale.numberOptions = Locale.OmitGroupSeparator
+ var decimals = realField.trailingZeroes ? realField.decimals : decimalCounter(realField.realValue)
+ if (decimals > 0) {
+ var text = Number(realField.realValue).toLocaleString(locale, 'f', decimals + 1)
+ return text.substring(0, text.length - 1)
+ }
+ return Number(realField.realValue).toLocaleString(locale, 'f', decimals)
+ }
}
}
}
diff --git a/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionDetailsToolbar.qml b/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionDetailsToolbar.qml
index 8b4c08f845..e7997f7eae 100644
--- a/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionDetailsToolbar.qml
+++ b/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionDetailsToolbar.qml
@@ -29,6 +29,11 @@ Rectangle {
root.model.insertRow(root.model.rowCount())
}
+ function closeDialogs() {
+ addColumnDialog.reject()
+ fileDialog.reject()
+ }
+
RowLayout {
id: container
@@ -49,7 +54,7 @@ Rectangle {
id: addColumnLeftButton
buttonIcon: StudioTheme.Constants.addcolumnleft_medium
- tooltip: qsTr("Add property left")
+ tooltip: qsTr("Add column left")
enabled: root.model.selectedColumn > -1
onClicked: addColumnDialog.popUp(root.model.selectedColumn)
}
@@ -58,7 +63,7 @@ Rectangle {
id: addColumnRightButton
buttonIcon: StudioTheme.Constants.addcolumnright_medium
- tooltip: qsTr("Add property right")
+ tooltip: qsTr("Add column right")
enabled: root.model.selectedColumn > -1
onClicked: addColumnDialog.popUp(root.model.selectedColumn + 1)
}
@@ -67,7 +72,7 @@ Rectangle {
id: deleteColumnButton
buttonIcon: StudioTheme.Constants.deletecolumn_medium
- tooltip: qsTr("Delete selected property")
+ tooltip: qsTr("Delete selected column")
enabled: root.model.selectedColumn > -1
onClicked: root.model.removeColumn(root.model.selectedColumn)
}
@@ -81,7 +86,7 @@ Rectangle {
id: addRowBelowButton
buttonIcon: StudioTheme.Constants.addrowbelow_medium
- tooltip: qsTr("Insert row below")
+ tooltip: qsTr("Add row below")
enabled: root.model.selectedRow > -1
onClicked: root.model.insertRow(root.model.selectedRow + 1)
}
@@ -90,7 +95,7 @@ Rectangle {
id: addRowAboveButton
buttonIcon: StudioTheme.Constants.addrowabove_medium
- tooltip: qsTr("Insert row above")
+ tooltip: qsTr("Add row above")
enabled: root.model.selectedRow > -1
onClicked: root.model.insertRow(root.model.selectedRow)
}
@@ -117,8 +122,18 @@ Rectangle {
buttonIcon: StudioTheme.Constants.save_medium
tooltip: qsTr("Save changes")
- enabled: root.model.collectionName !== ""
+ enabled: root.model.collectionName !== "" && root.model.hasUnsavedChanges
onClicked: root.model.saveDataStoreCollections()
+
+ Rectangle {
+ width: StudioTheme.Values.smallStatusIndicatorDiameter
+ height: StudioTheme.Values.smallStatusIndicatorDiameter
+ radius: StudioTheme.Values.smallStatusIndicatorDiameter / 2
+ anchors.right: parent.right
+ anchors.top: parent.top
+ visible: root.model.hasUnsavedChanges
+ color: StudioTheme.Values.themeIconColorSelected
+ }
}
IconButton {
diff --git a/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionDetailsView.qml b/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionDetailsView.qml
index c9a6d2dbcb..2193bd1763 100644
--- a/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionDetailsView.qml
+++ b/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionDetailsView.qml
@@ -21,11 +21,19 @@ Rectangle {
color: StudioTheme.Values.themeControlBackground
function closeDialogs() {
- editPropertyDialog.close()
+ editPropertyDialog.reject()
+ deleteColumnDialog.reject()
+ toolbar.closeDialogs()
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: tableView.model.deselectAll()
}
Column {
id: topRow
+ readonly property real maxAvailableHeight: root.height
visible: root.model.collectionName !== ""
width: parent.width
@@ -39,6 +47,11 @@ Rectangle {
}
GridLayout {
+ id: gridLayout
+ readonly property real maxAvailableHeight: topRow.maxAvailableHeight
+ - topRow.spacing
+ - toolbar.height
+
columns: 3
rowSpacing: 1
columnSpacing: 1
@@ -92,7 +105,8 @@ Rectangle {
id: topHeaderMouseArea
anchors.fill: parent
- anchors.margins: 5
+ anchors.leftMargin: StudioTheme.Values.borderHover
+ anchors.rightMargin: StudioTheme.Values.borderHover
acceptedButtons: Qt.LeftButton | Qt.RightButton
hoverEnabled: true
onClicked: (mouse) => {
@@ -147,12 +161,18 @@ Rectangle {
StudioControls.MenuItem {
text: qsTr("Sort Ascending")
- onTriggered: sortedModel.sort(headerMenu.clickedHeaderIndex, Qt.AscendingOrder)
+ onTriggered: {
+ tableView.closeEditor()
+ tableView.model.sort(headerMenu.clickedHeaderIndex, Qt.AscendingOrder)
+ }
}
StudioControls.MenuItem {
text: qsTr("Sort Descending")
- onTriggered: sortedModel.sort(headerMenu.clickedHeaderIndex, Qt.DescendingOrder)
+ onTriggered: {
+ tableView.closeEditor()
+ tableView.model.sort(headerMenu.clickedHeaderIndex, Qt.DescendingOrder)
+ }
}
}
}
@@ -174,7 +194,8 @@ Rectangle {
MouseArea {
anchors.fill: parent
- anchors.margins: 5
+ anchors.topMargin: StudioTheme.Values.borderHover
+ anchors.bottomMargin: StudioTheme.Values.borderHover
acceptedButtons: Qt.LeftButton
onClicked: tableView.model.selectRow(index)
}
@@ -187,15 +208,29 @@ Rectangle {
model: root.sortedModel
clip: true
- property point tableStart: tableTopLeftCorner.mapToItem(root, Qt.point(x, y));
+ readonly property real maxAvailableHeight: gridLayout.maxAvailableHeight
+ - addRowButton.height
+ - headerView.height
+ - (2 * gridLayout.rowSpacing)
+ readonly property real maxAvailableWidth: gridLayout.width
+ - StudioTheme.Values.collectionTableHorizontalMargin
+ - rowIdView.width
+ - addColumnButton.width
+ - gridLayout.columnSpacing
+
+ property real childrenWidth: tableView.contentItem.childrenRect.width
+ property real childrenHeight: tableView.contentItem.childrenRect.height
+
+ property int targetRow
+ property int targetColumn
Layout.alignment: Qt.AlignTop + Qt.AlignLeft
Layout.preferredWidth: tableView.contentWidth
Layout.preferredHeight: tableView.contentHeight
Layout.minimumWidth: 100
Layout.minimumHeight: 20
- Layout.maximumWidth: root.width - (tableStart.x + addColumnContainer.width)
- Layout.maximumHeight: root.height - (tableStart.y + addRowContainer.height)
+ Layout.maximumWidth: maxAvailableWidth
+ Layout.maximumHeight: maxAvailableHeight
columnWidthProvider: function(column) {
if (!isColumnLoaded(column))
@@ -215,6 +250,45 @@ Rectangle {
return Math.max(h, StudioTheme.Values.collectionCellMinimumHeight)
}
+ function ensureRowIsVisible(row) {
+ let rows = tableView.model.rowCount()
+ let rowIsLoaded = tableView.isRowLoaded(row)
+
+ if (row < 0 || row >= rows || rowIsLoaded) {
+ if (rowIsLoaded)
+ tableView.positionViewAtRow(row, Qt.AlignLeft | Qt.AlignTop)
+
+ tableView.targetRow = -1
+ return
+ }
+
+ tableView.targetRow = row
+ tableView.positionViewAtRow(row, Qt.AlignLeft | Qt.AlignTop)
+ ensureTimer.start()
+ }
+
+ function ensureColumnIsVisible(column) {
+ let columns = tableView.model.columnCount()
+ let columnIsLoaded = tableView.isColumnLoaded(column)
+
+ if (column < 0 || column >= columns || columnIsLoaded) {
+ if (columnIsLoaded)
+ tableView.positionViewAtColumn(column, Qt.AlignLeft | Qt.AlignTop)
+
+ tableView.targetColumn = -1
+ return
+ }
+
+ tableView.targetColumn = column
+ tableView.positionViewAtColumn(column, Qt.AlignLeft | Qt.AlignTop)
+ ensureTimer.start()
+ }
+
+ onMaxAvailableHeightChanged: resetSizeTimer.start()
+ onMaxAvailableWidthChanged: resetSizeTimer.start()
+ onChildrenWidthChanged: resetSizeTimer.start()
+ onChildrenHeightChanged: resetSizeTimer.start()
+
delegate: Rectangle {
id: itemCell
@@ -264,7 +338,7 @@ Rectangle {
Text {
text: display ?? ""
color: itemSelected ? StudioTheme.Values.themeInteraction
- : StudioTheme.Values.themePlaceholderTextColorInteraction
+ : StudioTheme.Values.themeTextColor
leftPadding: 5
topPadding: 3
bottomPadding: 3
@@ -297,15 +371,70 @@ Rectangle {
top: itemCell.top
left: itemCell.left
}
+ Component.onCompleted: tableView.model.deselectAll()
}
+ }
- Connections {
- target: tableView.model
+ Timer {
+ id: resetSizeTimer
- function onModelReset() {
- tableView.clearColumnWidths()
- tableView.clearRowHeights()
- }
+ interval: 100
+ repeat: false
+ onTriggered: {
+ let cWidth = Math.min(tableView.maxAvailableWidth, tableView.childrenWidth)
+ let cHeight = Math.min(tableView.maxAvailableHeight, tableView.childrenHeight)
+
+ if (tableView.contentWidth !== cWidth || tableView.contentHeight !== cHeight)
+ tableView.returnToBounds()
+ }
+ }
+
+ Timer {
+ id: ensureTimer
+
+ interval: 100
+ repeat: false
+ onTriggered: {
+ tableView.ensureRowIsVisible(tableView.targetRow)
+ tableView.ensureColumnIsVisible(tableView.targetColumn)
+ }
+ }
+
+ Connections {
+ target: tableView.model
+
+ function onModelReset() {
+ root.closeDialogs()
+ tableView.clearColumnWidths()
+ tableView.clearRowHeights()
+ }
+
+ function onRowsInserted(parent, first, last) {
+ tableView.closeEditor()
+ tableView.model.selectRow(first)
+ tableView.ensureRowIsVisible(first)
+ }
+
+ function onColumnsInserted(parent, first, last) {
+ tableView.closeEditor()
+ tableView.model.selectColumn(first)
+ tableView.ensureColumnIsVisible(first)
+ }
+
+ function onRowsRemoved(parent, first, last) {
+ let nextRow = first - 1
+ if (nextRow < 0 && tableView.model.rowCount(parent) > 0)
+ nextRow = 0
+
+ tableView.model.selectRow(nextRow)
+ }
+
+ function onColumnsRemoved(parent, first, last) {
+ let nextColumn = first - 1
+ if (nextColumn < 0 && tableView.model.columnCount(parent) > 0)
+ nextColumn = 0
+
+ tableView.model.selectColumn(nextColumn)
}
}
@@ -331,7 +460,7 @@ Rectangle {
}
HelperWidgets.IconButton {
- id: addColumnContainer
+ id: addColumnButton
iconSize:16
Layout.preferredWidth: 24
@@ -346,7 +475,7 @@ Rectangle {
}
HelperWidgets.IconButton {
- id: addRowContainer
+ id: addRowButton
iconSize:16
Layout.preferredWidth: tableView.width
@@ -367,10 +496,38 @@ Rectangle {
}
}
+ ColumnLayout {
+ id: importsProblem
+
+ visible: !topRow.visible && rootView.dataStoreExists && !rootView.projectImportExists
+ width: parent.width
+ anchors.verticalCenter: parent.verticalCenter
+ clip: true
+
+ Text {
+ text: qsTr("Import the project to your design document to make the Model Editor enabled.")
+ Layout.alignment: Qt.AlignCenter
+ Layout.maximumWidth: parent.width
+ leftPadding: StudioTheme.Values.collectionItemTextPadding
+ rightPadding: StudioTheme.Values.collectionItemTextPadding
+ color: StudioTheme.Values.themeTextColor
+ font.pixelSize: StudioTheme.Values.mediumFontSize
+ wrapMode: Text.Wrap
+ }
+
+ HelperWidgets.Button {
+ text: qsTr("Enable DataStore (This will add the required import)")
+ Layout.alignment: Qt.AlignCenter
+ onClicked: rootView.addProjectImport()
+ leftPadding: StudioTheme.Values.collectionItemTextPadding
+ rightPadding: StudioTheme.Values.collectionItemTextPadding
+ }
+ }
+
Text {
anchors.centerIn: parent
- text: qsTr("Select a model to continue")
- visible: !topRow.visible
+ text: qsTr("There are no models in this project.\nAdd or import a model.")
+ visible: !topRow.visible && !importsProblem.visible
color: StudioTheme.Values.themeTextColor
font.pixelSize: StudioTheme.Values.mediumFontSize
}
diff --git a/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionItem.qml b/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionItem.qml
index 31ced43c1d..d963070536 100644
--- a/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionItem.qml
+++ b/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionItem.qml
@@ -16,9 +16,17 @@ Item {
implicitHeight: boundingRect.height + 3
property color textColor
+ readonly property string name: collectionName ?? ""
+ readonly property bool isSelected: collectionIsSelected
+ readonly property int id: index
+
+ function rename(newName) {
+ collectionName = newName
+ }
signal selectItem(int itemIndex)
signal deleteItem()
+ signal contextMenuRequested()
Item {
id: boundingRect
@@ -90,155 +98,12 @@ Item {
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.RightButton | Qt.LeftButton
- onClicked: collectionMenu.popup()
- }
- }
- }
- }
-
- StudioControls.Menu {
- id: collectionMenu
-
- closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
-
- StudioControls.MenuItem {
- text: qsTr("Delete")
- shortcut: StandardKey.Delete
- onTriggered: deleteDialog.open()
- }
-
- StudioControls.MenuItem {
- text: qsTr("Rename")
- shortcut: StandardKey.Replace
- onTriggered: renameDialog.open()
- }
-
- StudioControls.MenuItem {
- text: qsTr("Assign to the selected node")
- enabled: CollectionEditorBackend.rootView.targetNodeSelected
- onTriggered: rootView.assignCollectionToSelectedNode(collectionName)
- }
- }
-
- component Spacer: Item {
- implicitWidth: 1
- implicitHeight: StudioTheme.Values.columnGap
- }
-
- StudioControls.Dialog {
- id: deleteDialog
-
- title: qsTr("Deleting the model")
- clip: true
- implicitWidth: 300
-
- contentItem: ColumnLayout {
- spacing: 2
-
- Text {
- Layout.fillWidth: true
-
- wrapMode: Text.WordWrap
- color: StudioTheme.Values.themeTextColor
- text: qsTr("Are you sure that you want to delete model \"%1\"?"
- + "\nThe model will be deleted permanently.").arg(collectionName)
-
- }
-
- Spacer {}
-
- RowLayout {
- spacing: StudioTheme.Values.sectionRowSpacing
- Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
-
- HelperWidgets.Button {
- text: qsTr("Delete")
- onClicked: root.deleteItem()
- }
-
- HelperWidgets.Button {
- text: qsTr("Cancel")
- onClicked: deleteDialog.reject()
- }
- }
- }
- }
-
- StudioControls.Dialog {
- id: renameDialog
-
- title: qsTr("Rename model")
-
- onAccepted: {
- if (newNameField.text !== "")
- collectionName = newNameField.text
- }
-
- onOpened: {
- newNameField.text = collectionName
- }
-
- contentItem: ColumnLayout {
- spacing: 2
-
- Text {
- text: qsTr("Previous name: " + collectionName)
- color: StudioTheme.Values.themeTextColor
- }
-
- Spacer {}
-
- Text {
- Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
- text: qsTr("New name:")
- color: StudioTheme.Values.themeTextColor
- }
-
- StudioControls.TextField {
- id: newNameField
-
- Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
- Layout.fillWidth: true
-
- actionIndicator.visible: false
- translationIndicator.visible: false
- validator: newNameValidator
-
- Keys.onEnterPressed: renameDialog.accept()
- Keys.onReturnPressed: renameDialog.accept()
- Keys.onEscapePressed: renameDialog.reject()
-
- onTextChanged: {
- btnRename.enabled = newNameField.text !== ""
- }
- }
-
- Spacer {}
-
- RowLayout {
- Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
- spacing: StudioTheme.Values.sectionRowSpacing
-
- HelperWidgets.Button {
- id: btnRename
-
- text: qsTr("Rename")
- onClicked: renameDialog.accept()
- }
-
- HelperWidgets.Button {
- text: qsTr("Cancel")
- onClicked: renameDialog.reject()
+ onClicked: contextMenuRequested()
}
}
}
}
- RegularExpressionValidator {
- id: newNameValidator
- regularExpression: /^\w+$/
- }
-
states: [
State {
name: "default"
diff --git a/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionListView.qml b/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionListView.qml
index ef06a2e7a0..2b95abfc4f 100644
--- a/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionListView.qml
+++ b/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionListView.qml
@@ -2,6 +2,11 @@
// 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 HelperWidgets 2.0 as HelperWidgets
+import StudioControls 1.0 as StudioControls
+import StudioTheme as StudioTheme
import CollectionEditorBackend
ListView {
@@ -10,8 +15,201 @@ ListView {
model: CollectionEditorBackend.model
clip: true
+ function closeDialogs() {
+ currentCollection.dereference()
+ collectionMenu.close()
+ deleteDialog.reject()
+ renameDialog.reject()
+ }
+
delegate: CollectionItem {
implicitWidth: root.width
onDeleteItem: root.model.removeRow(index)
+ onContextMenuRequested: collectionMenu.openMenu(this)
+ }
+
+ QtObject {
+ id: currentCollection
+
+ property CollectionItem item
+ readonly property string name: item ? item.name : ""
+ readonly property bool selected: item ? item.isSelected : false
+ readonly property int index: item ? item.id : -1
+
+ function rename(newName) {
+ if (item)
+ item.rename(newName)
+ }
+
+ function deleteItem() {
+ if (item)
+ item.deleteItem()
+ }
+
+ function dereference() {
+ item = null
+ }
+ }
+
+ StudioControls.Menu {
+ id: collectionMenu
+
+ closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
+
+ function openMenu(item) {
+ currentCollection.item = item
+ popup()
+ }
+
+ StudioControls.MenuItem {
+ text: qsTr("Delete")
+ shortcut: StandardKey.Delete
+ onTriggered: deleteDialog.open()
+ }
+
+ StudioControls.MenuItem {
+ text: qsTr("Rename")
+ shortcut: StandardKey.Replace
+ onTriggered: renameDialog.open()
+ }
+
+ StudioControls.MenuItem {
+ text: qsTr("Assign to the selected node")
+ enabled: CollectionEditorBackend.rootView.targetNodeSelected
+ onTriggered: rootView.assignCollectionToSelectedNode(currentCollection.name)
+ }
+ }
+
+ StudioControls.Dialog {
+ id: deleteDialog
+
+ title: qsTr("Deleting the model")
+ clip: true
+
+ onAccepted: currentCollection.deleteItem()
+
+ contentItem: ColumnLayout {
+ id: deleteDialogContent // Keep the id here even if it's not used, because the dialog might lose implicitSize
+
+ width: 300
+ spacing: 2
+
+ Text {
+ Layout.fillWidth: true
+
+ wrapMode: Text.WordWrap
+ color: StudioTheme.Values.themeTextColor
+ text: qsTr("Are you sure that you want to delete model \"%1\"?"
+ + "\nThe model will be deleted permanently.").arg(currentCollection.name)
+
+ }
+
+ Spacer {}
+
+ RowLayout {
+ spacing: StudioTheme.Values.sectionRowSpacing
+ Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
+ Layout.fillWidth: true
+ Layout.preferredHeight: 40
+
+ HelperWidgets.Button {
+ text: qsTr("Delete")
+ onClicked: deleteDialog.accept()
+ }
+
+ HelperWidgets.Button {
+ text: qsTr("Cancel")
+ onClicked: deleteDialog.reject()
+ }
+ }
+ }
+ }
+
+ StudioControls.Dialog {
+ id: renameDialog
+
+ title: qsTr("Rename model")
+
+ onAccepted: {
+ if (newNameField.text !== "")
+ currentCollection.rename(newNameField.text)
+ }
+
+ onOpened: {
+ newNameField.text = currentCollection.name
+ }
+
+ contentItem: ColumnLayout {
+ spacing: 2
+
+ Text {
+ text: qsTr("Previous name: " + currentCollection.name)
+ color: StudioTheme.Values.themeTextColor
+ }
+
+ Spacer {}
+
+ Text {
+ Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
+ text: qsTr("New name:")
+ color: StudioTheme.Values.themeTextColor
+ }
+
+ StudioControls.TextField {
+ id: newNameField
+
+ Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
+ Layout.fillWidth: true
+
+ actionIndicator.visible: false
+ translationIndicator.visible: false
+ validator: newNameValidator
+
+ Keys.onEnterPressed: renameDialog.accept()
+ Keys.onReturnPressed: renameDialog.accept()
+ Keys.onEscapePressed: renameDialog.reject()
+
+ onTextChanged: {
+ btnRename.enabled = newNameField.text !== ""
+ }
+ }
+
+ Spacer {}
+
+ RowLayout {
+ Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
+ spacing: StudioTheme.Values.sectionRowSpacing
+
+ HelperWidgets.Button {
+ id: btnRename
+
+ text: qsTr("Rename")
+ onClicked: renameDialog.accept()
+ }
+
+ HelperWidgets.Button {
+ text: qsTr("Cancel")
+ onClicked: renameDialog.reject()
+ }
+ }
+ }
+ }
+
+ Connections {
+ target: root.model
+
+ function onModelReset() {
+ root.closeDialogs()
+ }
+ }
+
+ RegularExpressionValidator {
+ id: newNameValidator
+ regularExpression: /^\w+$/
+ }
+
+ component Spacer: Item {
+ implicitWidth: 1
+ implicitHeight: StudioTheme.Values.columnGap
}
}
diff --git a/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionView.qml b/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionView.qml
index acf82fe452..9d483037ac 100644
--- a/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionView.qml
+++ b/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionView.qml
@@ -28,6 +28,12 @@ Item {
print("TODO: deleteSelectedCollection")
}
+ function closeDialogs() {
+ importDialog.reject()
+ newCollection.reject()
+ warningDialog.reject()
+ }
+
ImportDialog {
id: importDialog
@@ -147,6 +153,8 @@ Item {
}
CollectionListView { // Model Groups
+ id: collectionListView
+
Layout.fillWidth: true
Layout.minimumHeight: bottomSpacer.isExpanded ? 150 : 0
Layout.fillHeight: !bottomSpacer.isExpanded
@@ -187,4 +195,12 @@ Item {
SplitView.fillWidth: true
}
}
+
+ Connections {
+ target: root.model
+
+ function onModelReset() {
+ root.closeDialogs()
+ }
+ }
}
diff --git a/share/qtcreator/qmldesigner/collectionEditorQmlSource/ColorViewDelegate.qml b/share/qtcreator/qmldesigner/collectionEditorQmlSource/ColorViewDelegate.qml
index 6bb1b60159..16e55acfb4 100644
--- a/share/qtcreator/qmldesigner/collectionEditorQmlSource/ColorViewDelegate.qml
+++ b/share/qtcreator/qmldesigner/collectionEditorQmlSource/ColorViewDelegate.qml
@@ -16,19 +16,33 @@ Row {
property color color
property bool supportGradient: false
- readonly property color __editColor: edit
+
+ property QtObject backendValue: QtObject {
+ property color value: edit
+ readonly property color editColor: edit
+
+ function resetValue() {
+ if (value)
+ value = ""
+ }
+
+ onValueChanged: {
+ if (editColor !== value)
+ edit = value
+ }
+ }
property variant value: {
- if (!edit)
+ if (!colorEditor.backendValue || !colorEditor.backendValue.value)
return "white" // default color for Rectangle
if (colorEditor.isVector3D) {
- return Qt.rgba(__editColor.x,
- __editColor.y,
- __editColor.z, 1)
+ return Qt.rgba(colorEditor.backendValue.value.x,
+ colorEditor.backendValue.value.y,
+ colorEditor.backendValue.value.z, 1)
}
- return __editColor
+ return colorEditor.backendValue.value
}
property alias gradientPropertyName: popupDialog.gradientPropertyName
@@ -42,31 +56,17 @@ Row {
property bool __block: false
- function getColorFromEditValue() {
- if (!edit)
- return "white" // default color for Rectangle
-
- if (colorEditor.isVector3D) {
- return Qt.rgba(__editColor.x,
- __editColor.y,
- __editColor.z, 1)
- }
-
- return __editColor
- }
-
function resetShapeColor() {
- if (edit)
- edit = ""
+ colorEditor.backendValue.resetValue()
}
function writeColor() {
if (colorEditor.isVector3D) {
- edit = Qt.vector3d(colorEditor.color.r,
+ colorEditor.backendValue.value = Qt.vector3d(colorEditor.color.r,
colorEditor.color.g,
colorEditor.color.b)
} else {
- edit = colorEditor.color
+ colorEditor.backendValue.value = colorEditor.color
}
}
@@ -77,7 +77,7 @@ Row {
// Syncing color from backend to frontend and block reflection
function syncColor() {
colorEditor.__block = true
- colorEditor.color = colorEditor.getColorFromEditValue()
+ colorEditor.color = colorEditor.value
hexTextField.syncColor()
colorEditor.__block = false
}
@@ -92,7 +92,7 @@ Row {
colorEditor.syncColor()
}
- function on__EditColorChanged() {
+ function onBackendValueChanged() {
if (popupDialog.isSolid())
colorEditor.syncColor()
}
@@ -208,7 +208,7 @@ Row {
if (colorEditor.supportGradient && popupDialog.loaderItem.gradientModel.hasGradient) {
var hexColor = convertColorToString(colorEditor.color)
hexTextField.text = hexColor
- edit = hexColor
+ colorEditor.backendValue.value = hexColor
popupDialog.loaderItem.commitGradientColor()
}
}
@@ -292,5 +292,5 @@ Row {
Component.onCompleted: popupDialog.determineActiveColorMode()
- on__EditColorChanged: popupDialog.determineActiveColorMode()
+ onBackendValueChanged: popupDialog.determineActiveColorMode()
}
diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibrary.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibrary.qml
index c6db8425ff..2c98b58adc 100644
--- a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibrary.qml
+++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibrary.qml
@@ -23,6 +23,7 @@ Item {
texturesView.closeContextMenu()
environmentsView.closeContextMenu()
effectsView.closeContextMenu()
+ userView.closeContextMenu()
HelperWidgets.Controller.closeContextMenu()
}
@@ -113,10 +114,18 @@ Item {
id: tabBar
width: parent.width
height: StudioTheme.Values.toolbarHeight
- tabsModel: [{name: qsTr("Materials"), icon: StudioTheme.Constants.material_medium},
- {name: qsTr("Textures"), icon: StudioTheme.Constants.textures_medium},
- {name: qsTr("Environments"), icon: StudioTheme.Constants.languageList_medium},
- {name: qsTr("Effects"), icon: StudioTheme.Constants.effects}]
+
+ Component.onCompleted: {
+ var tabs = [
+ { name: qsTr("Materials"), icon: StudioTheme.Constants.material_medium },
+ { name: qsTr("Textures"), icon: StudioTheme.Constants.textures_medium },
+ { name: qsTr("Environments"), icon: StudioTheme.Constants.languageList_medium },
+ { name: qsTr("Effects"), icon: StudioTheme.Constants.effects }
+ ];
+ if (ContentLibraryBackend.rootView.userBundleEnabled())
+ tabs.push({ name: qsTr("User Assets"), icon: StudioTheme.Constants.effects });
+ tabBar.tabsModel = tabs;
+ }
}
}
}
@@ -148,7 +157,8 @@ Item {
onUnimport: (bundleMat) => {
confirmUnimportDialog.targetBundleItem = bundleMat
- confirmUnimportDialog.targetBundleType = "material"
+ confirmUnimportDialog.targetBundleLabel = "material"
+ confirmUnimportDialog.targetBundleModel = ContentLibraryBackend.materialsModel
confirmUnimportDialog.open()
}
@@ -208,7 +218,31 @@ Item {
onUnimport: (bundleItem) => {
confirmUnimportDialog.targetBundleItem = bundleItem
- confirmUnimportDialog.targetBundleType = "effect"
+ confirmUnimportDialog.targetBundleLabel = "effect"
+ confirmUnimportDialog.targetBundleModel = ContentLibraryBackend.effectsModel
+ confirmUnimportDialog.open()
+ }
+
+ onCountChanged: root.responsiveResize(stackLayout.width, stackLayout.height)
+ }
+
+ ContentLibraryUserView {
+ id: userView
+
+ adsFocus: root.adsFocus
+ width: root.width
+
+ cellWidth: root.thumbnailSize
+ cellHeight: root.thumbnailSize + 20
+ numColumns: root.numColumns
+ hideHorizontalScrollBar: true
+
+ searchBox: searchBox
+
+ onUnimport: (bundleItem) => {
+ confirmUnimportDialog.targetBundleItem = bundleItem
+ confirmUnimportDialog.targetBundleLabel = "material"
+ confirmUnimportDialog.targetBundleModel = ContentLibraryBackend.userModel
confirmUnimportDialog.open()
}
diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterial.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterial.qml
index 93b226d6ca..0e9fc4903e 100644
--- a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterial.qml
+++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterial.qml
@@ -12,12 +12,15 @@ import WebFetcher
Item {
id: root
- signal showContextMenu()
-
// Download states: "" (ie default, not downloaded), "unavailable", "downloading", "downloaded",
// "failed"
property string downloadState: modelData.isDownloaded() ? "downloaded" : ""
+ property bool importerRunning: false
+
+ signal showContextMenu()
+ signal addToProject()
+
visible: modelData.bundleMaterialVisible
MouseArea {
@@ -29,7 +32,7 @@ Item {
acceptedButtons: Qt.LeftButton | Qt.RightButton
onPressed: (mouse) => {
- if (mouse.button === Qt.LeftButton && !materialsModel.importerRunning) {
+ if (mouse.button === Qt.LeftButton && !root.importerRunning) {
if (root.downloadState === "downloaded")
ContentLibraryBackend.rootView.startDragMaterial(modelData, mapToGlobal(mouse.x, mouse.y))
} else if (mouse.button === Qt.RightButton && root.downloadState === "downloaded") {
@@ -96,12 +99,12 @@ Item {
pressColor: Qt.hsla(c.hslHue, c.hslSaturation, c.hslLightness, .4)
anchors.right: img.right
anchors.bottom: img.bottom
- enabled: !ContentLibraryBackend.materialsModel.importerRunning
+ enabled: !root.importerRunning
visible: root.downloadState === "downloaded"
&& (containsMouse || mouseArea.containsMouse)
onClicked: {
- ContentLibraryBackend.materialsModel.addToProject(modelData)
+ root.addToProject()
}
}
diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterialContextMenu.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterialContextMenu.qml
index ca3a05bdd1..b67ec311ef 100644
--- a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterialContextMenu.qml
+++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterialContextMenu.qml
@@ -15,8 +15,9 @@ StudioControls.Menu {
readonly property bool targetAvailable: targetMaterial && !importerRunning
- signal unimport(var bundleMat);
- signal addToProject(var bundleMat)
+ signal unimport();
+ signal addToProject()
+ signal applyToSelected(bool add)
function popupMenu(targetMaterial = null)
{
@@ -29,13 +30,13 @@ StudioControls.Menu {
StudioControls.MenuItem {
text: qsTr("Apply to selected (replace)")
enabled: root.targetAvailable && root.hasModelSelection
- onTriggered: materialsModel.applyToSelected(root.targetMaterial, false)
+ onTriggered: root.applyToSelected(false)
}
StudioControls.MenuItem {
text: qsTr("Apply to selected (add)")
enabled: root.targetAvailable && root.hasModelSelection
- onTriggered: materialsModel.applyToSelected(root.targetMaterial, true)
+ onTriggered: root.applyToSelected(true)
}
StudioControls.MenuSeparator {}
@@ -45,7 +46,7 @@ StudioControls.Menu {
text: qsTr("Add an instance to project")
onTriggered: {
- root.addToProject(root.targetMaterial)
+ root.addToProject()
}
}
@@ -53,6 +54,6 @@ StudioControls.Menu {
enabled: root.targetAvailable && root.targetMaterial.bundleMaterialImported
text: qsTr("Remove from project")
- onTriggered: root.unimport(root.targetMaterial)
+ onTriggered: root.unimport()
}
}
diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterialsView.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterialsView.qml
index c21baf4c58..9a0e33b8e5 100644
--- a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterialsView.qml
+++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterialsView.qml
@@ -27,8 +27,6 @@ HelperWidgets.ScrollView {
root.count = c
}
- property var currMaterialItem: null
- property var rootItem: null
property var materialsModel: ContentLibraryBackend.materialsModel
required property var searchBox
@@ -51,17 +49,19 @@ HelperWidgets.ScrollView {
ContentLibraryMaterialContextMenu {
id: ctxMenu
- hasModelSelection: materialsModel.hasModelSelection
- importerRunning: materialsModel.importerRunning
+ hasModelSelection: root.materialsModel.hasModelSelection
+ importerRunning: root.materialsModel.importerRunning
- onUnimport: (bundleMat) => root.unimport(bundleMat)
- onAddToProject: (bundleMat) => materialsModel.addToProject(bundleMat)
+ onApplyToSelected: (add) => root.materialsModel.applyToSelected(ctxMenu.targetMaterial, add)
+
+ onUnimport: root.unimport(ctxMenu.targetMaterial)
+ onAddToProject: root.materialsModel.addToProject(ctxMenu.targetMaterial)
}
Repeater {
id: categoryRepeater
- model: materialsModel
+ model: root.materialsModel
delegate: HelperWidgets.Section {
id: section
@@ -73,7 +73,7 @@ HelperWidgets.ScrollView {
bottomPadding: StudioTheme.Values.sectionPadding
caption: bundleCategoryName
- visible: bundleCategoryVisible && !materialsModel.isEmpty
+ visible: bundleCategoryVisible && !root.materialsModel.isEmpty
expanded: bundleCategoryExpanded
expandOnClick: false
category: "ContentLib_Mat"
@@ -103,7 +103,10 @@ HelperWidgets.ScrollView {
width: root.cellWidth
height: root.cellHeight
+ importerRunning: root.materialsModel.importerRunning
+
onShowContextMenu: ctxMenu.popupMenu(modelData)
+ onAddToProject: root.materialsModel.addToProject(modelData)
}
onCountChanged: root.assignMaxCount()
@@ -115,13 +118,13 @@ HelperWidgets.ScrollView {
Text {
id: infoText
text: {
- if (!materialsModel.matBundleExists)
+ if (!root.materialsModel.matBundleExists)
qsTr("No materials available. Make sure you have internet connection.")
else if (!ContentLibraryBackend.rootView.isQt6Project)
qsTr("<b>Content Library</b> materials are not supported in Qt5 projects.")
else if (!ContentLibraryBackend.rootView.hasQuick3DImport)
qsTr("To use <b>Content Library</b>, first add the QtQuick3D module in the <b>Components</b> view.")
- else if (!materialsModel.hasRequiredQuick3DImport)
+ else if (!root.materialsModel.hasRequiredQuick3DImport)
qsTr("To use <b>Content Library</b>, version 6.3 or later of the QtQuick3D module is required.")
else if (!ContentLibraryBackend.rootView.hasMaterialLibrary)
qsTr("<b>Content Library</b> is disabled inside a non-visual component.")
@@ -134,7 +137,7 @@ HelperWidgets.ScrollView {
font.pixelSize: StudioTheme.Values.baseFontSize
topPadding: 10
leftPadding: 10
- visible: materialsModel.isEmpty
+ visible: root.materialsModel.isEmpty
}
}
}
diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexture.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexture.qml
index f74f190040..4fbeb1b8b5 100644
--- a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexture.qml
+++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexture.qml
@@ -148,7 +148,7 @@ Item {
visible: root.delegateVisible && root.downloadState != "downloading"
cache: false
- property string webUrl: modelData.textureWebUrl
+ property string textureUrl: modelData.textureUrl
IconButton {
id: downloadIcon
@@ -279,7 +279,7 @@ Item {
FileDownloader {
id: textureDownloader
- url: image.webUrl
+ url: image.textureUrl
probeUrl: false
downloadEnabled: true
onDownloadStarting: {
@@ -333,7 +333,7 @@ Item {
FileDownloader {
id: iconDownloader
- url: modelData.textureWebIconUrl
+ url: modelData.textureIconUrl
probeUrl: false
downloadEnabled: true
targetFilePath: modelData.textureIconPath
diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexturesView.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexturesView.qml
index 1fac9f2234..617b724e66 100644
--- a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexturesView.qml
+++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexturesView.qml
@@ -27,9 +27,6 @@ HelperWidgets.ScrollView {
root.count = c
}
- property var currMaterialItem: null
- property var rootItem: null
-
required property var searchBox
required property var model
required property string sectionCategory
diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryUserView.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryUserView.qml
new file mode 100644
index 0000000000..85123af374
--- /dev/null
+++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryUserView.qml
@@ -0,0 +1,162 @@
+// 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 Qt.labs.qmlmodels
+import HelperWidgets as HelperWidgets
+import StudioControls as StudioControls
+import StudioTheme as StudioTheme
+import ContentLibraryBackend
+
+HelperWidgets.ScrollView {
+ id: root
+
+ clip: true
+ interactive: !ctxMenu.opened && !ContentLibraryBackend.rootView.isDragging
+ && !HelperWidgets.Controller.contextMenuOpened
+
+ property real cellWidth: 100
+ property real cellHeight: 120
+ property int numColumns: 4
+
+ property int count: 0
+ function assignMaxCount() {
+ let c = 0
+ for (let i = 0; i < categoryRepeater.count; ++i)
+ c = Math.max(c, categoryRepeater.itemAt(i)?.count ?? 0)
+
+ root.count = c
+ }
+
+ required property var searchBox
+
+ signal unimport(var bundleItem);
+
+ function closeContextMenu() {
+ ctxMenu.close()
+ }
+
+ function expandVisibleSections() {
+ for (let i = 0; i < categoryRepeater.count; ++i) {
+ let cat = categoryRepeater.itemAt(i)
+ if (cat.visible && !cat.expanded)
+ cat.expandSection()
+ }
+ }
+
+ Column {
+ ContentLibraryMaterialContextMenu {
+ id: ctxMenu
+
+ hasModelSelection: ContentLibraryBackend.userModel.hasModelSelection
+ importerRunning: ContentLibraryBackend.userModel.importerRunning
+
+ onApplyToSelected: (add) => ContentLibraryBackend.userModel.applyToSelected(ctxMenu.targetMaterial, add)
+
+ onUnimport: root.unimport(ctxMenu.targetMaterial)
+ onAddToProject: ContentLibraryBackend.userModel.addToProject(ctxMenu.targetMaterial)
+ }
+
+ Repeater {
+ id: categoryRepeater
+
+ model: ContentLibraryBackend.userModel
+
+ delegate: HelperWidgets.Section {
+ id: section
+
+ width: root.width
+ leftPadding: StudioTheme.Values.sectionPadding
+ rightPadding: StudioTheme.Values.sectionPadding
+ topPadding: StudioTheme.Values.sectionPadding
+ bottomPadding: StudioTheme.Values.sectionPadding
+
+ caption: categoryName
+ visible: categoryVisible
+ category: "ContentLib_User"
+
+ function expandSection() {
+ section.expanded = true
+ }
+
+ property alias count: repeater.count
+
+ onCountChanged: root.assignMaxCount()
+
+ property int numVisibleItem: 1 // initially, the tab is invisible so this will be 0
+
+ Grid {
+ width: section.width - section.leftPadding - section.rightPadding
+ spacing: StudioTheme.Values.sectionGridSpacing
+ columns: root.numColumns
+
+ Repeater {
+ id: repeater
+ model: categoryItems
+
+ delegate: DelegateChooser {
+ role: "itemType"
+
+ DelegateChoice {
+ roleValue: "material"
+ ContentLibraryMaterial {
+ width: root.cellWidth
+ height: root.cellHeight
+
+ importerRunning: ContentLibraryBackend.userModel.importerRunning
+
+ onShowContextMenu: ctxMenu.popupMenu(modelData)
+ onAddToProject: ContentLibraryBackend.userModel.addToProject(modelData)
+
+ onVisibleChanged: {
+ section.numVisibleItem += visible ? 1 : -1
+ }
+ }
+ }
+ DelegateChoice {
+ roleValue: "texture"
+ delegate: ContentLibraryTexture {
+ width: root.cellWidth
+ height: root.cellWidth // for textures use a square size since there is no name row
+
+ // onShowContextMenu: ctxMenu.popupMenu(modelData) // TODO
+ }
+ }
+ }
+
+ onCountChanged: root.assignMaxCount()
+ }
+ }
+
+ Text {
+ text: qsTr("No match found.");
+ color: StudioTheme.Values.themeTextColor
+ font.pixelSize: StudioTheme.Values.baseFontSize
+ leftPadding: 10
+ visible: !searchBox.isEmpty() && section.numVisibleItem === 0
+ }
+ }
+ }
+
+ Text {
+ id: infoText
+ text: {
+ if (!ContentLibraryBackend.effectsModel.bundleExists)
+ qsTr("User bundle couldn't be found.")
+ else if (!ContentLibraryBackend.rootView.isQt6Project)
+ qsTr("<b>Content Library</b> is not supported in Qt5 projects.")
+ else if (!ContentLibraryBackend.rootView.hasQuick3DImport)
+ qsTr("To use <b>Content Library</b>, first add the QtQuick3D module in the <b>Components</b> view.")
+ else if (!ContentLibraryBackend.rootView.hasMaterialLibrary)
+ qsTr("<b>Content Library</b> is disabled inside a non-visual component.")
+ else
+ ""
+ }
+ color: StudioTheme.Values.themeTextColor
+ font.pixelSize: StudioTheme.Values.baseFontSize
+ topPadding: 10
+ leftPadding: 10
+ visible: ContentLibraryBackend.effectsModel.isEmpty
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/UnimportBundleMaterialDialog.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/UnimportBundleMaterialDialog.qml
index 48be045d8b..4385e3bf82 100644
--- a/share/qtcreator/qmldesigner/contentLibraryQmlSource/UnimportBundleMaterialDialog.qml
+++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/UnimportBundleMaterialDialog.qml
@@ -12,24 +12,27 @@ import ContentLibraryBackend
StudioControls.Dialog {
id: root
- title: qsTr("Bundle material might be in use")
+ property var targetBundleItem
+ property var targetBundleLabel // "effect" or "material"
+ property var targetBundleModel
+
+ title: qsTr("Bundle %1 might be in use").arg(root.targetBundleLabel)
anchors.centerIn: parent
closePolicy: Popup.CloseOnEscape
implicitWidth: 300
modal: true
- property var targetBundleType // "effect" or "material"
- property var targetBundleItem
+ onOpened: warningText.forceActiveFocus()
contentItem: Column {
spacing: 20
width: parent.width
Text {
- id: folderNotEmpty
+ id: warningText
- text: qsTr("If the %1 you are removing is in use, it might cause the project to malfunction.\n\nAre you sure you want to remove the %1?")
- .arg(root.targetBundleType)
+ text: qsTr("If the %1 you are removing is in use, it might cause the project to malfunction.\n\nAre you sure you want to remove it?")
+ .arg(root.targetBundleLabel)
color: StudioTheme.Values.themeTextColor
wrapMode: Text.WordWrap
anchors.right: parent.right
@@ -49,11 +52,7 @@ StudioControls.Dialog {
text: qsTr("Remove")
onClicked: {
- if (root.targetBundleType === "material")
- ContentLibraryBackend.materialsModel.removeFromProject(root.targetBundleItem)
- else if (root.targetBundleType === "effect")
- ContentLibraryBackend.effectsModel.removeFromProject(root.targetBundleItem)
-
+ root.targetBundleModel.removeFromProject(root.targetBundleItem)
root.accept()
}
}
@@ -64,6 +63,4 @@ StudioControls.Dialog {
}
}
}
-
- onOpened: folderNotEmpty.forceActiveFocus()
}
diff --git a/share/qtcreator/qmldesigner/designericons.json b/share/qtcreator/qmldesigner/designericons.json
index 157012b312..005494b471 100644
--- a/share/qtcreator/qmldesigner/designericons.json
+++ b/share/qtcreator/qmldesigner/designericons.json
@@ -219,7 +219,7 @@
}
},
"CameraSpeedConfigIcon": {
- "iconName": "camera_medium"
+ "iconName": "cameraSpeed_medium"
},
"EditColorIcon": {
"iconName": "colorSelection_medium"
diff --git a/share/qtcreator/qmldesigner/edit3dQmlSource/CameraSpeedConfigurationDialog.qml b/share/qtcreator/qmldesigner/edit3dQmlSource/CameraSpeedConfigurationDialog.qml
index 2e2ff54700..b51369ffa3 100644
--- a/share/qtcreator/qmldesigner/edit3dQmlSource/CameraSpeedConfigurationDialog.qml
+++ b/share/qtcreator/qmldesigner/edit3dQmlSource/CameraSpeedConfigurationDialog.qml
@@ -57,7 +57,7 @@ Rectangle {
HelperWidgets.IconIndicator {
anchors.fill: parent
- icon: StudioTheme.Constants.camera_medium
+ icon: StudioTheme.Constants.cameraSpeed_medium
pixelSize: StudioTheme.Values.myIconFontSize * 1.4
iconColor: StudioTheme.Values.themeLinkIndicatorColorHover
enabled: false
diff --git a/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectComposer.qml b/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectComposer.qml
index dda1d93ff9..305bbc7925 100644
--- a/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectComposer.qml
+++ b/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectComposer.qml
@@ -365,7 +365,7 @@ ColumnLayout {
Connections {
id: dragConnection
target: root.draggedSec
- onYChanged: root.handleDragMove()
+ function onYChanged() { root.handleDragMove() }
}
Timer {
diff --git a/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectComposerPreview.qml b/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectComposerPreview.qml
index c832b2f370..c0c47f7366 100644
--- a/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectComposerPreview.qml
+++ b/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectComposerPreview.qml
@@ -21,6 +21,7 @@ Column {
readonly property int updateDelay: 100
readonly property int previewMargin: 5
+ readonly property int extraMargin: 200
property real previewScale: 1
@@ -246,6 +247,8 @@ Column {
layer.enabled: true
layer.mipmap: true
layer.smooth: true
+ layer.sourceRect: Qt.rect(-root.extraMargin, -root.extraMargin,
+ width + root.extraMargin * 2, height + root.extraMargin * 2)
visible: false
Image {
@@ -347,10 +350,6 @@ Column {
width: source.width
height: source.height
anchors.centerIn: parent
- // Cache the layer. This way heavy shaders rendering doesn't
- // slow down code editing & rest of the UI.
- layer.enabled: true
- layer.smooth: true
}
}
@@ -383,7 +382,6 @@ Column {
Connections {
target: effectComposerModel
function onShadersBaked() {
- console.log("Shaders Baked!")
updateTimer.restart()
}
}
diff --git a/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectComposerTopBar.qml b/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectComposerTopBar.qml
index d5ac4461c4..8f98ae25b2 100644
--- a/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectComposerTopBar.qml
+++ b/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectComposerTopBar.qml
@@ -48,7 +48,7 @@ Rectangle {
style: StudioTheme.Values.viewBarButtonStyle
buttonIcon: StudioTheme.Constants.saveAs_medium
tooltip: qsTr("Save current composition with a new name")
- enabled: root.backendModel ? root.backendModel.isEnabled && !root.backendModel.isEmpty
+ enabled: root.backendModel ? root.backendModel.isEnabled && root.backendModel.currentComposition !== ""
: false
onClicked: root.saveAsClicked()
@@ -58,7 +58,8 @@ Rectangle {
style: StudioTheme.Values.viewBarButtonStyle
buttonIcon: StudioTheme.Constants.assignTo_medium
tooltip: qsTr("Assign current composition to selected item")
- enabled: root.backendModel ? root.backendModel.isEnabled
+ enabled: root.backendModel ? root.backendModel.hasValidTarget
+ && root.backendModel.isEnabled
&& root.backendModel.currentComposition !== ""
: false
diff --git a/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectCompositionNode.qml b/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectCompositionNode.qml
index 6defa3b092..a606461b5c 100644
--- a/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectCompositionNode.qml
+++ b/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectCompositionNode.qml
@@ -43,6 +43,8 @@ HelperWidgets.Section {
EffectCompositionNodeUniform {
width: root.width
+
+ onReset: nodeUniformsModel.resetData(index)
}
}
}
diff --git a/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectCompositionNodeUniform.qml b/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectCompositionNodeUniform.qml
index 71cbf94f8b..7c3214c5fa 100644
--- a/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectCompositionNodeUniform.qml
+++ b/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectCompositionNodeUniform.qml
@@ -13,9 +13,10 @@ Item {
id: root
height: layout.implicitHeight
-
visible: !uniformUseCustomValue
+ signal reset()
+
Component.onCompleted: {
if (uniformType === "int") {
if (uniformControlType === "channel")
@@ -49,10 +50,11 @@ Item {
RowLayout {
id: layout
- spacing: 20
anchors.fill: parent
Text {
+ id: textName
+
text: uniformDisplayName
color: StudioTheme.Values.themeTextColor
font.pixelSize: StudioTheme.Values.baseFontSize
@@ -63,11 +65,38 @@ Item {
elide: Text.ElideRight
HelperWidgets.ToolTipArea {
+ id: tooltipArea
+
anchors.fill: parent
tooltip: uniformDescription
}
}
+ Item {
+ Layout.preferredHeight: 30
+ Layout.preferredWidth: 30
+
+ MouseArea {
+ id: mouseArea
+
+ anchors.fill: parent
+ hoverEnabled: true
+ }
+
+ HelperWidgets.IconButton {
+ id: iconButton
+
+ buttonSize: 24
+ icon: StudioTheme.Constants.reload_medium
+ iconSize: 16
+ anchors.centerIn: parent
+ visible: mouseArea.containsMouse || iconButton.containsMouse
+ tooltip: qsTr("Reset value")
+ onClicked: root.reset()
+ }
+
+ }
+
Loader {
id: valueLoader
Layout.fillWidth: true
diff --git a/share/qtcreator/qmldesigner/effectComposerQmlSources/SaveAsDialog.qml b/share/qtcreator/qmldesigner/effectComposerQmlSources/SaveAsDialog.qml
index d139ba9205..65b01be457 100644
--- a/share/qtcreator/qmldesigner/effectComposerQmlSources/SaveAsDialog.qml
+++ b/share/qtcreator/qmldesigner/effectComposerQmlSources/SaveAsDialog.qml
@@ -50,11 +50,13 @@ StudioControls.Dialog {
if (/[^A-Za-z0-9_]+/.test(text))
errMsg = qsTr("Name contains invalid characters.")
else if (!/^[A-Z]/.test(text))
- errMsg = qsTr("Name must start with a capital letter")
+ errMsg = qsTr("Name must start with a capital letter.")
else if (text.length < 3)
- errMsg = qsTr("Name must have at least 3 characters")
+ errMsg = qsTr("Name must have at least 3 characters.")
else if (/\s/.test(text))
- errMsg = qsTr("Name cannot contain white space")
+ errMsg = qsTr("Name cannot contain white space.")
+ else if (EffectComposerBackend.effectComposerModel.nameExists(text))
+ errMsg = qsTr("Name is already taken.")
emptyText.text = errMsg
btnSave.enabled = errMsg.length === 0
diff --git a/share/qtcreator/qmldesigner/effectComposerQmlSources/ValueColor.qml b/share/qtcreator/qmldesigner/effectComposerQmlSources/ValueColor.qml
index 4b00bd7613..f7482260b5 100644
--- a/share/qtcreator/qmldesigner/effectComposerQmlSources/ValueColor.qml
+++ b/share/qtcreator/qmldesigner/effectComposerQmlSources/ValueColor.qml
@@ -15,8 +15,14 @@ Row {
StudioControls.ColorEditor {
actionIndicatorVisible: false
- Component.onCompleted: color = uniformValue
+ // color: uniformValue binding can get overwritten by normal operation of the control
+ property color resetValue: uniformValue
- onColorChanged: uniformValue = color
+ onResetValueChanged: color = uniformValue
+ Component.onCompleted: color = uniformValue
+ onColorChanged: {
+ if (uniformValue !== color)
+ uniformValue = color
+ }
}
}
diff --git a/share/qtcreator/qmldesigner/effectComposerQmlSources/ValueFloat.qml b/share/qtcreator/qmldesigner/effectComposerQmlSources/ValueFloat.qml
index 7348d6668b..969d7e2949 100644
--- a/share/qtcreator/qmldesigner/effectComposerQmlSources/ValueFloat.qml
+++ b/share/qtcreator/qmldesigner/effectComposerQmlSources/ValueFloat.qml
@@ -14,6 +14,10 @@ Row {
HelperWidgets.DoubleSpinBox {
id: spinBox
+ // value: uniformValue binding can get overwritten by normal operation of the control
+ property double resetValue: uniformValue
+ onResetValueChanged: value = resetValue
+
width: 60
spinBoxIndicatorVisible: false
inputHAlignment: Qt.AlignHCenter
@@ -22,7 +26,7 @@ Row {
value: uniformValue
stepSize: .01
decimals: 2
- onValueChanged: uniformValue = value
+ onValueModified: uniformValue = value
}
StudioControls.Slider {
diff --git a/share/qtcreator/qmldesigner/effectComposerQmlSources/ValueInt.qml b/share/qtcreator/qmldesigner/effectComposerQmlSources/ValueInt.qml
index 89f571c8cb..d67929168a 100644
--- a/share/qtcreator/qmldesigner/effectComposerQmlSources/ValueInt.qml
+++ b/share/qtcreator/qmldesigner/effectComposerQmlSources/ValueInt.qml
@@ -14,6 +14,10 @@ Row {
HelperWidgets.DoubleSpinBox {
id: spinBox
+ // value: uniformValue binding can get overwritten by normal operation of the control
+ property double resetValue: uniformValue
+ onResetValueChanged: value = resetValue
+
width: 60
spinBoxIndicatorVisible: false
inputHAlignment: Qt.AlignHCenter
@@ -22,7 +26,7 @@ Row {
value: uniformValue
stepSize: 1
decimals: 0
- onValueChanged: uniformValue = Math.round(value)
+ onValueModified: uniformValue = Math.round(value)
}
StudioControls.Slider {
diff --git a/share/qtcreator/qmldesigner/effectComposerQmlSources/ValueVec2.qml b/share/qtcreator/qmldesigner/effectComposerQmlSources/ValueVec2.qml
index b703d5f184..adb4fe9905 100644
--- a/share/qtcreator/qmldesigner/effectComposerQmlSources/ValueVec2.qml
+++ b/share/qtcreator/qmldesigner/effectComposerQmlSources/ValueVec2.qml
@@ -15,6 +15,10 @@ RowLayout {
HelperWidgets.DoubleSpinBox {
id: vX
+ // value: uniformValue binding can get overwritten by normal operation of the control
+ property double resetValue: uniformValue.x
+ onResetValueChanged: value = resetValue
+
Layout.fillWidth: true
Layout.minimumWidth: 30
Layout.maximumWidth: 60
@@ -26,7 +30,7 @@ RowLayout {
value: uniformValue.x
stepSize: .01
decimals: 2
- onValueChanged: uniformValue.x = value
+ onValueModified: uniformValue.x = value
}
Item { // spacer
@@ -51,6 +55,10 @@ RowLayout {
HelperWidgets.DoubleSpinBox {
id: vY
+ // value: uniformValue binding can get overwritten by normal operation of the control
+ property double resetValue: uniformValue.y
+ onResetValueChanged: value = resetValue
+
Layout.fillWidth: true
Layout.minimumWidth: 30
Layout.maximumWidth: 60
@@ -62,7 +70,7 @@ RowLayout {
value: uniformValue.y
stepSize: .01
decimals: 2
- onValueChanged: uniformValue.y = value
+ onValueModified: uniformValue.y = value
}
Item { // spacer
diff --git a/share/qtcreator/qmldesigner/effectComposerQmlSources/ValueVec3.qml b/share/qtcreator/qmldesigner/effectComposerQmlSources/ValueVec3.qml
index d59b63a514..78573c48f6 100644
--- a/share/qtcreator/qmldesigner/effectComposerQmlSources/ValueVec3.qml
+++ b/share/qtcreator/qmldesigner/effectComposerQmlSources/ValueVec3.qml
@@ -15,6 +15,10 @@ RowLayout {
HelperWidgets.DoubleSpinBox {
id: vX
+ // value: uniformValue binding can get overwritten by normal operation of the control
+ property double resetValue: uniformValue.x
+ onResetValueChanged: value = resetValue
+
Layout.fillWidth: true
Layout.minimumWidth: 30
Layout.maximumWidth: 60
@@ -26,7 +30,7 @@ RowLayout {
value: uniformValue.x
stepSize: .01
decimals: 2
- onValueChanged: uniformValue.x = value
+ onValueModified: uniformValue.x = value
}
Item { // spacer
@@ -51,6 +55,10 @@ RowLayout {
HelperWidgets.DoubleSpinBox {
id: vY
+ // value: uniformValue binding can get overwritten by normal operation of the control
+ property double resetValue: uniformValue.y
+ onResetValueChanged: value = resetValue
+
Layout.fillWidth: true
Layout.minimumWidth: 30
Layout.maximumWidth: 60
@@ -62,7 +70,7 @@ RowLayout {
value: uniformValue.y
stepSize: .01
decimals: 2
- onValueChanged: uniformValue.y = value
+ onValueModified: uniformValue.y = value
}
Item { // spacer
@@ -87,6 +95,10 @@ RowLayout {
HelperWidgets.DoubleSpinBox {
id: vZ
+ // value: uniformValue binding can get overwritten by normal operation of the control
+ property double resetValue: uniformValue.z
+ onResetValueChanged: value = resetValue
+
Layout.fillWidth: true
Layout.minimumWidth: 30
Layout.maximumWidth: 60
@@ -98,7 +110,7 @@ RowLayout {
value: uniformValue.z
stepSize: .01
decimals: 2
- onValueChanged: uniformValue.z = value
+ onValueModified: uniformValue.z = value
}
Item { // spacer
diff --git a/share/qtcreator/qmldesigner/effectComposerQmlSources/ValueVec4.qml b/share/qtcreator/qmldesigner/effectComposerQmlSources/ValueVec4.qml
index 7e930abf81..61ce8e6389 100644
--- a/share/qtcreator/qmldesigner/effectComposerQmlSources/ValueVec4.qml
+++ b/share/qtcreator/qmldesigner/effectComposerQmlSources/ValueVec4.qml
@@ -15,6 +15,10 @@ RowLayout {
HelperWidgets.DoubleSpinBox {
id: vX
+ // value: uniformValue binding can get overwritten by normal operation of the control
+ property double resetValue: uniformValue.x
+ onResetValueChanged: value = resetValue
+
Layout.fillWidth: true
Layout.minimumWidth: 30
Layout.maximumWidth: 60
@@ -26,7 +30,7 @@ RowLayout {
value: uniformValue.x
stepSize: .01
decimals: 2
- onValueChanged: uniformValue.x = value
+ onValueModified: uniformValue.x = value
}
Item { // spacer
@@ -51,6 +55,10 @@ RowLayout {
HelperWidgets.DoubleSpinBox {
id: vY
+ // value: uniformValue binding can get overwritten by normal operation of the control
+ property double resetValue: uniformValue.y
+ onResetValueChanged: value = resetValue
+
Layout.fillWidth: true
Layout.minimumWidth: 30
Layout.maximumWidth: 60
@@ -62,7 +70,7 @@ RowLayout {
value: uniformValue.y
stepSize: .01
decimals: 2
- onValueChanged: uniformValue.y = value
+ onValueModified: uniformValue.y = value
}
Item { // spacer
@@ -87,6 +95,10 @@ RowLayout {
HelperWidgets.DoubleSpinBox {
id: vZ
+ // value: uniformValue binding can get overwritten by normal operation of the control
+ property double resetValue: uniformValue.z
+ onResetValueChanged: value = resetValue
+
Layout.fillWidth: true
Layout.minimumWidth: 30
Layout.maximumWidth: 60
@@ -98,7 +110,7 @@ RowLayout {
value: uniformValue.z
stepSize: .01
decimals: 2
- onValueChanged: uniformValue.z = value
+ onValueModified: uniformValue.z = value
}
Item { // spacer
@@ -123,6 +135,10 @@ RowLayout {
HelperWidgets.DoubleSpinBox {
id: vW
+ // value: uniformValue binding can get overwritten by normal operation of the control
+ property double resetValue: uniformValue.w
+ onResetValueChanged: value = resetValue
+
Layout.fillWidth: true
Layout.minimumWidth: 30
Layout.maximumWidth: 60
@@ -134,7 +150,7 @@ RowLayout {
value: uniformValue.w
stepSize: .01
decimals: 2
- onValueChanged: uniformValue.w = value
+ onValueModified: uniformValue.w = value
}
Item { // spacer
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/ambient-sound-16.png b/share/qtcreator/qmldesigner/itemLibrary/images/ambient-sound-16.png
new file mode 100644
index 0000000000..6b16d81397
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/ambient-sound-16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/ambient-sound-24.png b/share/qtcreator/qmldesigner/itemLibrary/images/ambient-sound-24.png
new file mode 100644
index 0000000000..0549a84758
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/ambient-sound-24.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/ambient-sound-24@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/ambient-sound-24@2x.png
new file mode 100644
index 0000000000..8876f95ae6
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/ambient-sound-24@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/animated-image-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/animated-image-icon.png
new file mode 100644
index 0000000000..71371f97a3
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/animated-image-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/animated-image-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/animated-image-icon16.png
new file mode 100644
index 0000000000..86b80e95ab
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/animated-image-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/animated-image-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/animated-image-icon@2x.png
new file mode 100644
index 0000000000..4ad2a9011b
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/animated-image-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/animatedsprite-loading.png b/share/qtcreator/qmldesigner/itemLibrary/images/animatedsprite-loading.png
new file mode 100644
index 0000000000..ff2bbbd140
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/animatedsprite-loading.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/audio-engine-16.png b/share/qtcreator/qmldesigner/itemLibrary/images/audio-engine-16.png
new file mode 100644
index 0000000000..da40bc69a2
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/audio-engine-16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/audio-engine-24.png b/share/qtcreator/qmldesigner/itemLibrary/images/audio-engine-24.png
new file mode 100644
index 0000000000..b3ebdf745b
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/audio-engine-24.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/audio-engine-24@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/audio-engine-24@2x.png
new file mode 100644
index 0000000000..476df8640f
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/audio-engine-24@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/audio-listener-16.png b/share/qtcreator/qmldesigner/itemLibrary/images/audio-listener-16.png
new file mode 100644
index 0000000000..ecc583b859
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/audio-listener-16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/audio-listener-24.png b/share/qtcreator/qmldesigner/itemLibrary/images/audio-listener-24.png
new file mode 100644
index 0000000000..ee181f57cc
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/audio-listener-24.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/audio-listener-24@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/audio-listener-24@2x.png
new file mode 100644
index 0000000000..2588277e53
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/audio-listener-24@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/audio-output-16px.png b/share/qtcreator/qmldesigner/itemLibrary/images/audio-output-16px.png
new file mode 100644
index 0000000000..6ae703de64
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/audio-output-16px.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/audio-output-24px.png b/share/qtcreator/qmldesigner/itemLibrary/images/audio-output-24px.png
new file mode 100644
index 0000000000..f2133ca716
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/audio-output-24px.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/audio-output-24px@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/audio-output-24px@2x.png
new file mode 100644
index 0000000000..9336b81b6e
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/audio-output-24px@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/audio-room-16.png b/share/qtcreator/qmldesigner/itemLibrary/images/audio-room-16.png
new file mode 100644
index 0000000000..98f245d624
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/audio-room-16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/audio-room-24.png b/share/qtcreator/qmldesigner/itemLibrary/images/audio-room-24.png
new file mode 100644
index 0000000000..294d1574ae
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/audio-room-24.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/audio-room-24@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/audio-room-24@2x.png
new file mode 100644
index 0000000000..bef7f80e3e
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/audio-room-24@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/border-image-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/border-image-icon.png
new file mode 100644
index 0000000000..5418a0f55a
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/border-image-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/border-image-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/border-image-icon16.png
new file mode 100644
index 0000000000..17f7ed0688
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/border-image-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/border-image-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/border-image-icon@2x.png
new file mode 100644
index 0000000000..fb4fb33910
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/border-image-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/busyindicator-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/busyindicator-icon.png
new file mode 100644
index 0000000000..666d1ed93f
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/busyindicator-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/busyindicator-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/busyindicator-icon16.png
new file mode 100644
index 0000000000..5aa57d7f48
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/busyindicator-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/busyindicator-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/busyindicator-icon@2x.png
new file mode 100644
index 0000000000..bb2278ff89
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/busyindicator-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/button-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/button-icon.png
new file mode 100644
index 0000000000..c44909f6dd
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/button-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/button-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/button-icon16.png
new file mode 100644
index 0000000000..5c921deb13
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/button-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/button-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/button-icon@2x.png
new file mode 100644
index 0000000000..f90a1ba7dc
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/button-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/checkbox-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/checkbox-icon.png
new file mode 100644
index 0000000000..ee669b3a88
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/checkbox-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/checkbox-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/checkbox-icon16.png
new file mode 100644
index 0000000000..8d89eab841
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/checkbox-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/checkbox-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/checkbox-icon@2x.png
new file mode 100644
index 0000000000..51c5601de0
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/checkbox-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/column-positioner-icon-16px.png b/share/qtcreator/qmldesigner/itemLibrary/images/column-positioner-icon-16px.png
new file mode 100644
index 0000000000..8d963e2bab
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/column-positioner-icon-16px.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/column-positioner-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/column-positioner-icon.png
new file mode 100644
index 0000000000..0cd116d13c
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/column-positioner-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/column-positioner-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/column-positioner-icon@2x.png
new file mode 100644
index 0000000000..3247384285
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/column-positioner-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/combobox-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/combobox-icon.png
new file mode 100644
index 0000000000..2d31b17c65
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/combobox-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/combobox-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/combobox-icon16.png
new file mode 100644
index 0000000000..15fc3505ba
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/combobox-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/combobox-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/combobox-icon@2x.png
new file mode 100644
index 0000000000..5f82390596
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/combobox-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/component-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/component-icon.png
new file mode 100644
index 0000000000..9c7df42bc7
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/component-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/component-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/component-icon16.png
new file mode 100644
index 0000000000..99941541c6
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/component-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/component-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/component-icon@2x.png
new file mode 100644
index 0000000000..f66349a63b
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/component-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/control-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/control-icon.png
new file mode 100644
index 0000000000..fd9e4e8ff3
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/control-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/control-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/control-icon16.png
new file mode 100644
index 0000000000..31c765483e
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/control-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/control-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/control-icon@2x.png
new file mode 100644
index 0000000000..22604d2492
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/control-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/default-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/default-icon.png
new file mode 100644
index 0000000000..564226e949
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/default-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/default3d.png b/share/qtcreator/qmldesigner/itemLibrary/images/default3d.png
new file mode 100644
index 0000000000..a3b6c7f6f2
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/default3d.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/default3d16.png b/share/qtcreator/qmldesigner/itemLibrary/images/default3d16.png
new file mode 100644
index 0000000000..de8906a724
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/default3d16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/default3d@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/default3d@2x.png
new file mode 100644
index 0000000000..7ca04a01ea
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/default3d@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/delaybutton-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/delaybutton-icon.png
new file mode 100644
index 0000000000..5a55bd9f77
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/delaybutton-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/delaybutton-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/delaybutton-icon16.png
new file mode 100644
index 0000000000..cd21394e46
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/delaybutton-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/delaybutton-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/delaybutton-icon@2x.png
new file mode 100644
index 0000000000..7beee2fab0
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/delaybutton-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/dial-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/dial-icon.png
new file mode 100644
index 0000000000..b3b63e3523
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/dial-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/dial-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/dial-icon16.png
new file mode 100644
index 0000000000..8d8c7c09b0
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/dial-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/dial-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/dial-icon@2x.png
new file mode 100644
index 0000000000..22547a16b8
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/dial-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/drop-area-16px.png b/share/qtcreator/qmldesigner/itemLibrary/images/drop-area-16px.png
new file mode 100644
index 0000000000..278690f07f
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/drop-area-16px.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/drop-area-24px.png b/share/qtcreator/qmldesigner/itemLibrary/images/drop-area-24px.png
new file mode 100644
index 0000000000..a286efb032
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/drop-area-24px.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/drop-area-24px@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/drop-area-24px@2x.png
new file mode 100644
index 0000000000..47abb7f9e3
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/drop-area-24px@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/extended-view3d-16px.png b/share/qtcreator/qmldesigner/itemLibrary/images/extended-view3d-16px.png
new file mode 100644
index 0000000000..d9027813d0
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/extended-view3d-16px.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/extended-view3d-24px.png b/share/qtcreator/qmldesigner/itemLibrary/images/extended-view3d-24px.png
new file mode 100644
index 0000000000..a8a0bf65a4
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/extended-view3d-24px.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/extended-view3d-24px@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/extended-view3d-24px@2x.png
new file mode 100644
index 0000000000..a2f7bf93d3
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/extended-view3d-24px@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/flickable-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/flickable-icon.png
new file mode 100644
index 0000000000..bdc2253959
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/flickable-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/flickable-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/flickable-icon16.png
new file mode 100644
index 0000000000..d7ab9de8a7
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/flickable-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/flickable-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/flickable-icon@2x.png
new file mode 100644
index 0000000000..b28b0fa4d9
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/flickable-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/flipable-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/flipable-icon.png
new file mode 100644
index 0000000000..1f5f6966c0
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/flipable-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/flipable-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/flipable-icon16.png
new file mode 100644
index 0000000000..cf252f08b8
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/flipable-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/flow-positioner-icon-16px.png b/share/qtcreator/qmldesigner/itemLibrary/images/flow-positioner-icon-16px.png
new file mode 100644
index 0000000000..67be7b474d
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/flow-positioner-icon-16px.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/flow-positioner-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/flow-positioner-icon.png
new file mode 100644
index 0000000000..f8fa80970e
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/flow-positioner-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/flow-positioner-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/flow-positioner-icon@2x.png
new file mode 100644
index 0000000000..fc3deff849
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/flow-positioner-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/focusscope-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/focusscope-icon.png
new file mode 100644
index 0000000000..0dff9a075d
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/focusscope-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/focusscope-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/focusscope-icon16.png
new file mode 100644
index 0000000000..50c6f75cd8
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/focusscope-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/focusscope-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/focusscope-icon@2x.png
new file mode 100644
index 0000000000..b3ffdea6eb
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/focusscope-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/frame-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/frame-icon.png
new file mode 100644
index 0000000000..32abc8bf1e
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/frame-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/frame-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/frame-icon16.png
new file mode 100644
index 0000000000..e5b65ad53b
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/frame-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/frame-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/frame-icon@2x.png
new file mode 100644
index 0000000000..8b876f38ec
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/frame-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/grid-positioner-icon-16px.png b/share/qtcreator/qmldesigner/itemLibrary/images/grid-positioner-icon-16px.png
new file mode 100644
index 0000000000..47b34f9d14
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/grid-positioner-icon-16px.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/grid-positioner-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/grid-positioner-icon.png
new file mode 100644
index 0000000000..10d0b69a7b
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/grid-positioner-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/grid-positioner-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/grid-positioner-icon@2x.png
new file mode 100644
index 0000000000..4374b60e7a
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/grid-positioner-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/gridview-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/gridview-icon.png
new file mode 100644
index 0000000000..7457fbd7e1
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/gridview-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/gridview-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/gridview-icon16.png
new file mode 100644
index 0000000000..038a02ed86
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/gridview-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/gridview-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/gridview-icon@2x.png
new file mode 100644
index 0000000000..af233a0df3
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/gridview-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/groupbox-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/groupbox-icon.png
new file mode 100644
index 0000000000..5542ecf8bf
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/groupbox-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/groupbox-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/groupbox-icon16.png
new file mode 100644
index 0000000000..9cf4324819
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/groupbox-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/groupbox-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/groupbox-icon@2x.png
new file mode 100644
index 0000000000..80dab3c716
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/groupbox-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/image-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/image-icon.png
new file mode 100644
index 0000000000..318ce0874a
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/image-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/image-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/image-icon16.png
new file mode 100644
index 0000000000..3aa46b6106
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/image-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/image-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/image-icon@2x.png
new file mode 100644
index 0000000000..cc84918975
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/image-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/item-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/item-icon.png
new file mode 100644
index 0000000000..af81cdfdb1
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/item-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/item-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/item-icon16.png
new file mode 100644
index 0000000000..46d3ec1dbc
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/item-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/item-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/item-icon@2x.png
new file mode 100644
index 0000000000..f05aa57c2f
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/item-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/itemdelegate-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/itemdelegate-icon.png
new file mode 100644
index 0000000000..822cf3e7b8
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/itemdelegate-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/itemdelegate-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/itemdelegate-icon16.png
new file mode 100644
index 0000000000..b3ed007a0e
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/itemdelegate-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/itemdelegate-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/itemdelegate-icon@2x.png
new file mode 100644
index 0000000000..cb81308ff8
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/itemdelegate-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/keyframe-16px.png b/share/qtcreator/qmldesigner/itemLibrary/images/keyframe-16px.png
new file mode 100644
index 0000000000..6e1c9f912a
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/keyframe-16px.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/label-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/label-icon.png
new file mode 100644
index 0000000000..788bef078c
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/label-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/label-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/label-icon16.png
new file mode 100644
index 0000000000..b68d384568
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/label-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/label-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/label-icon@2x.png
new file mode 100644
index 0000000000..7001413d3b
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/label-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/listview-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/listview-icon.png
new file mode 100644
index 0000000000..5a2f3c203b
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/listview-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/listview-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/listview-icon16.png
new file mode 100644
index 0000000000..2657bf2181
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/listview-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/listview-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/listview-icon@2x.png
new file mode 100644
index 0000000000..b1d3fb67d2
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/listview-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/loader-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/loader-icon.png
new file mode 100644
index 0000000000..29082eacf1
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/loader-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/loader-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/loader-icon16.png
new file mode 100644
index 0000000000..4a2b093259
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/loader-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/loader-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/loader-icon@2x.png
new file mode 100644
index 0000000000..750b13bd02
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/loader-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/media-player-16px.png b/share/qtcreator/qmldesigner/itemLibrary/images/media-player-16px.png
new file mode 100644
index 0000000000..515287a846
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/media-player-16px.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/media-player-24px.png b/share/qtcreator/qmldesigner/itemLibrary/images/media-player-24px.png
new file mode 100644
index 0000000000..1b31ddc826
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/media-player-24px.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/media-player-24px@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/media-player-24px@2x.png
new file mode 100644
index 0000000000..86ae5914ac
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/media-player-24px@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/mouse-area-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/mouse-area-icon.png
new file mode 100644
index 0000000000..fe316caf8d
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/mouse-area-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/mouse-area-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/mouse-area-icon16.png
new file mode 100644
index 0000000000..bc8725fb5f
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/mouse-area-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/mouse-area-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/mouse-area-icon@2x.png
new file mode 100644
index 0000000000..04a25e13db
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/mouse-area-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/page-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/page-icon.png
new file mode 100644
index 0000000000..b5ac87e899
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/page-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/page-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/page-icon16.png
new file mode 100644
index 0000000000..bc6810b605
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/page-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/page-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/page-icon@2x.png
new file mode 100644
index 0000000000..23db032f4a
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/page-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/pageindicator-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/pageindicator-icon.png
new file mode 100644
index 0000000000..edb6b377bb
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/pageindicator-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/pageindicator-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/pageindicator-icon16.png
new file mode 100644
index 0000000000..0fb8967564
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/pageindicator-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/pageindicator-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/pageindicator-icon@2x.png
new file mode 100644
index 0000000000..7be0ee813b
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/pageindicator-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/pane-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/pane-icon.png
new file mode 100644
index 0000000000..62ebe487ff
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/pane-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/pane-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/pane-icon16.png
new file mode 100644
index 0000000000..2b8048441c
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/pane-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/pane-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/pane-icon@2x.png
new file mode 100644
index 0000000000..55bb116a69
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/pane-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/pathview-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/pathview-icon.png
new file mode 100644
index 0000000000..8dc82b8196
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/pathview-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/pathview-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/pathview-icon16.png
new file mode 100644
index 0000000000..a6a61f61b2
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/pathview-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/pathview-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/pathview-icon@2x.png
new file mode 100644
index 0000000000..d654a8e7e6
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/pathview-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/progressbar-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/progressbar-icon.png
new file mode 100644
index 0000000000..a023f73c30
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/progressbar-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/progressbar-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/progressbar-icon16.png
new file mode 100644
index 0000000000..6fede21d8c
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/progressbar-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/progressbar-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/progressbar-icon@2x.png
new file mode 100644
index 0000000000..0069400335
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/progressbar-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/radiobutton-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/radiobutton-icon.png
new file mode 100644
index 0000000000..d38170e22f
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/radiobutton-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/radiobutton-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/radiobutton-icon16.png
new file mode 100644
index 0000000000..07b46a8ab0
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/radiobutton-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/radiobutton-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/radiobutton-icon@2x.png
new file mode 100644
index 0000000000..4bbddda4b2
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/radiobutton-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/rangeslider-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/rangeslider-icon.png
new file mode 100644
index 0000000000..1c4c7b2948
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/rangeslider-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/rangeslider-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/rangeslider-icon16.png
new file mode 100644
index 0000000000..3be4624ddd
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/rangeslider-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/rangeslider-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/rangeslider-icon@2x.png
new file mode 100644
index 0000000000..aee69b3302
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/rangeslider-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/rect-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/rect-icon.png
new file mode 100644
index 0000000000..3997195f72
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/rect-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/rect-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/rect-icon16.png
new file mode 100644
index 0000000000..72893106ae
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/rect-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/rect-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/rect-icon@2x.png
new file mode 100644
index 0000000000..150fa50ea2
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/rect-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/repeater-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/repeater-icon.png
new file mode 100644
index 0000000000..efe3ca80b4
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/repeater-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/repeater-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/repeater-icon16.png
new file mode 100644
index 0000000000..775a57a38c
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/repeater-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/repeater-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/repeater-icon@2x.png
new file mode 100644
index 0000000000..bb541b6711
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/repeater-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/roundbutton-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/roundbutton-icon.png
new file mode 100644
index 0000000000..d4b470dc25
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/roundbutton-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/roundbutton-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/roundbutton-icon16.png
new file mode 100644
index 0000000000..f6f3666639
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/roundbutton-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/roundbutton-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/roundbutton-icon@2x.png
new file mode 100644
index 0000000000..4553e165e7
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/roundbutton-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/row-positioner-icon-16px.png b/share/qtcreator/qmldesigner/itemLibrary/images/row-positioner-icon-16px.png
new file mode 100644
index 0000000000..1c5be82245
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/row-positioner-icon-16px.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/row-positioner-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/row-positioner-icon.png
new file mode 100644
index 0000000000..a7e654c918
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/row-positioner-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/row-positioner-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/row-positioner-icon@2x.png
new file mode 100644
index 0000000000..48c99f8c0e
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/row-positioner-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/scrollview-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/scrollview-icon.png
new file mode 100644
index 0000000000..5ef73ff19f
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/scrollview-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/scrollview-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/scrollview-icon16.png
new file mode 100644
index 0000000000..f8ca7a3685
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/scrollview-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/scrollview-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/scrollview-icon@2x.png
new file mode 100644
index 0000000000..0eb7f9665e
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/scrollview-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/slider-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/slider-icon.png
new file mode 100644
index 0000000000..bd0a9729be
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/slider-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/slider-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/slider-icon16.png
new file mode 100644
index 0000000000..a08622df89
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/slider-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/slider-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/slider-icon@2x.png
new file mode 100644
index 0000000000..93842e4cdd
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/slider-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/spatial-audio-16.png b/share/qtcreator/qmldesigner/itemLibrary/images/spatial-audio-16.png
new file mode 100644
index 0000000000..676fe13404
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/spatial-audio-16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/spatial-audio-24.png b/share/qtcreator/qmldesigner/itemLibrary/images/spatial-audio-24.png
new file mode 100644
index 0000000000..29f7f14db3
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/spatial-audio-24.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/spatial-audio-24@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/spatial-audio-24@2x.png
new file mode 100644
index 0000000000..a518cada63
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/spatial-audio-24@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/spinbox-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/spinbox-icon.png
new file mode 100644
index 0000000000..37277c5e43
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/spinbox-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/spinbox-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/spinbox-icon16.png
new file mode 100644
index 0000000000..f88711dd25
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/spinbox-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/spinbox-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/spinbox-icon@2x.png
new file mode 100644
index 0000000000..b62a3bad51
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/spinbox-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/stackview-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/stackview-icon.png
new file mode 100644
index 0000000000..a6ced34925
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/stackview-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/stackview-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/stackview-icon16.png
new file mode 100644
index 0000000000..0f19d0efa3
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/stackview-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/stackview-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/stackview-icon@2x.png
new file mode 100644
index 0000000000..9b5ef9517b
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/stackview-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/swipeview-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/swipeview-icon.png
new file mode 100644
index 0000000000..031cb27c36
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/swipeview-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/swipeview-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/swipeview-icon16.png
new file mode 100644
index 0000000000..446c469690
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/swipeview-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/swipeview-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/swipeview-icon@2x.png
new file mode 100644
index 0000000000..0ccb978c46
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/swipeview-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/switch-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/switch-icon.png
new file mode 100644
index 0000000000..e018159286
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/switch-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/switch-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/switch-icon16.png
new file mode 100644
index 0000000000..9abd275659
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/switch-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/switch-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/switch-icon@2x.png
new file mode 100644
index 0000000000..787f54ca41
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/switch-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/text-edit-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/text-edit-icon.png
new file mode 100644
index 0000000000..068ebeef0f
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/text-edit-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/text-edit-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/text-edit-icon16.png
new file mode 100644
index 0000000000..b96ed468cb
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/text-edit-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/text-edit-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/text-edit-icon@2x.png
new file mode 100644
index 0000000000..3b7cb6d5da
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/text-edit-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/text-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/text-icon.png
new file mode 100644
index 0000000000..29a81f5d6c
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/text-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/text-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/text-icon16.png
new file mode 100644
index 0000000000..ee7cc512cb
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/text-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/text-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/text-icon@2x.png
new file mode 100644
index 0000000000..1df8f765de
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/text-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/text-input-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/text-input-icon.png
new file mode 100644
index 0000000000..c743c22074
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/text-input-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/text-input-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/text-input-icon16.png
new file mode 100644
index 0000000000..3ceef6d037
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/text-input-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/text-input-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/text-input-icon@2x.png
new file mode 100644
index 0000000000..666644d2d3
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/text-input-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/textarea-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/textarea-icon.png
new file mode 100644
index 0000000000..f1b2dc0f84
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/textarea-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/textarea-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/textarea-icon16.png
new file mode 100644
index 0000000000..4afc1fbab5
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/textarea-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/textarea-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/textarea-icon@2x.png
new file mode 100644
index 0000000000..c32ecc71a9
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/textarea-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/textfield-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/textfield-icon.png
new file mode 100644
index 0000000000..ba5537acef
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/textfield-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/textfield-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/textfield-icon16.png
new file mode 100644
index 0000000000..c4a62a6582
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/textfield-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/textfield-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/textfield-icon@2x.png
new file mode 100644
index 0000000000..e05fd41b9a
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/textfield-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/timeline-16px.png b/share/qtcreator/qmldesigner/itemLibrary/images/timeline-16px.png
new file mode 100644
index 0000000000..d4ecf00031
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/timeline-16px.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/timeline-animation-16px.png b/share/qtcreator/qmldesigner/itemLibrary/images/timeline-animation-16px.png
new file mode 100644
index 0000000000..31b8fed666
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/timeline-animation-16px.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/timer-16px.png b/share/qtcreator/qmldesigner/itemLibrary/images/timer-16px.png
new file mode 100644
index 0000000000..c675d5a707
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/timer-16px.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/timer-24px.png b/share/qtcreator/qmldesigner/itemLibrary/images/timer-24px.png
new file mode 100644
index 0000000000..bd9419aaa0
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/timer-24px.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/timer-24px@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/timer-24px@2x.png
new file mode 100644
index 0000000000..ff2d487cc9
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/timer-24px@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/toolbar-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/toolbar-icon.png
new file mode 100644
index 0000000000..5cb5b2e1af
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/toolbar-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/toolbar-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/toolbar-icon16.png
new file mode 100644
index 0000000000..569373afa1
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/toolbar-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/toolbar-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/toolbar-icon@2x.png
new file mode 100644
index 0000000000..fd9e6ceebc
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/toolbar-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/toolbutton-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/toolbutton-icon.png
new file mode 100644
index 0000000000..3298f69519
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/toolbutton-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/toolbutton-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/toolbutton-icon16.png
new file mode 100644
index 0000000000..9ab7861c25
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/toolbutton-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/toolbutton-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/toolbutton-icon@2x.png
new file mode 100644
index 0000000000..e5958cded3
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/toolbutton-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/toolseparator-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/toolseparator-icon.png
new file mode 100644
index 0000000000..5e99f06f2e
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/toolseparator-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/toolseparator-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/toolseparator-icon16.png
new file mode 100644
index 0000000000..68f22c5df1
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/toolseparator-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/toolseparator-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/toolseparator-icon@2x.png
new file mode 100644
index 0000000000..549c11c67c
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/toolseparator-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/tumbler-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/tumbler-icon.png
new file mode 100644
index 0000000000..98eb8232a2
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/tumbler-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/tumbler-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/tumbler-icon16.png
new file mode 100644
index 0000000000..ff5f95cf32
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/tumbler-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/tumbler-icon@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/tumbler-icon@2x.png
new file mode 100644
index 0000000000..236abf0cfe
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/tumbler-icon@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/video-16px.png b/share/qtcreator/qmldesigner/itemLibrary/images/video-16px.png
new file mode 100644
index 0000000000..caf9c16a61
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/video-16px.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/video-24px.png b/share/qtcreator/qmldesigner/itemLibrary/images/video-24px.png
new file mode 100644
index 0000000000..df1b84e5c9
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/video-24px.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/video-24px@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/video-24px@2x.png
new file mode 100644
index 0000000000..4b9f31faf3
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/video-24px@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/video-output-16px.png b/share/qtcreator/qmldesigner/itemLibrary/images/video-output-16px.png
new file mode 100644
index 0000000000..f00afc52e9
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/video-output-16px.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/video-output-24px.png b/share/qtcreator/qmldesigner/itemLibrary/images/video-output-24px.png
new file mode 100644
index 0000000000..fd3c89c081
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/video-output-24px.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/video-output-24px@2x.png b/share/qtcreator/qmldesigner/itemLibrary/images/video-output-24px@2x.png
new file mode 100644
index 0000000000..0f651a1013
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/video-output-24px@2x.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/webview-icon.png b/share/qtcreator/qmldesigner/itemLibrary/images/webview-icon.png
new file mode 100644
index 0000000000..22904f2f8b
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/webview-icon.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/images/webview-icon16.png b/share/qtcreator/qmldesigner/itemLibrary/images/webview-icon16.png
new file mode 100644
index 0000000000..ac7be01bb7
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/images/webview-icon16.png
Binary files differ
diff --git a/share/qtcreator/qmldesigner/itemLibrary/multimedia.metainfo b/share/qtcreator/qmldesigner/itemLibrary/multimedia.metainfo
new file mode 100644
index 0000000000..2e3616aa4b
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/multimedia.metainfo
@@ -0,0 +1,84 @@
+MetaInfo {
+ Type {
+ name: "QtMultimedia.MediaPlayer"
+ icon: "images/media-player-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeContainer: false
+ }
+
+ ItemLibraryEntry {
+ name: "Media Player"
+ category: "f.Qt Quick - Multimedia"
+ libraryIcon: "images/media-player-24px.png"
+ version: "6.0"
+ requiredImport: "QtMultimedia"
+ }
+ }
+
+ Type {
+ name: "QtMultimedia.AudioOutput"
+ icon: "images/audio-output-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeContainer: false
+ }
+
+ ItemLibraryEntry {
+ name: "Audio Output"
+ category: "f.Qt Quick - Multimedia"
+ libraryIcon: "images/audio-output-24px.png"
+ version: "6.0"
+ requiredImport: "QtMultimedia"
+ }
+ }
+
+ Type {
+ name: "QtMultimedia.VideoOutput"
+ icon: "images/video-output-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeContainer: false
+ }
+
+ ItemLibraryEntry {
+ name: "Video Output"
+ category: "f.Qt Quick - Multimedia"
+ libraryIcon: "images/video-output-24px.png"
+ version: "6.0"
+ requiredImport: "QtMultimedia"
+ }
+ }
+
+ Type {
+ name: "QtMultimedia.Video"
+ icon: "images/video-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: true
+ canBeContainer: false
+ }
+
+ ItemLibraryEntry {
+ name: "Video"
+ category: "f.Qt Quick - Multimedia"
+ libraryIcon: "images/video-24px.png"
+ version: "6.0"
+ requiredImport: "QtMultimedia"
+
+ Property { name: "width"; type: "int"; value: 200; }
+ Property { name: "height"; type: "int"; value: 200; }
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/itemLibrary/qml.metainfo b/share/qtcreator/qmldesigner/itemLibrary/qml.metainfo
new file mode 100644
index 0000000000..4bef02ddd3
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/qml.metainfo
@@ -0,0 +1,53 @@
+MetaInfo {
+
+ Type {
+ name: "QML.Component"
+ icon: "images/component-icon16.png"
+
+ Hints {
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ }
+
+ ItemLibraryEntry {
+ name: "Component"
+ category: "e.Qt Quick - Instancers"
+ libraryIcon: "images/component-icon.png"
+ version: "1.0"
+
+ QmlSource { source: "source/component.qml" }
+ toolTip: qsTr("Allows you to define components inline, within a QML document.")
+ }
+
+ ItemLibraryEntry {
+ name: "Component 3D"
+ category: "Instancers"
+ libraryIcon: "images/component-icon.png"
+ version: "1.0"
+ requiredImport: "QtQuick3D"
+
+ QmlSource { source: "source/component3d.qml" }
+ toolTip: qsTr("Allows you to define 3D components inline, within a QML document.")
+ }
+ }
+
+Type {
+ name: "QtQml.Base.Timer"
+ icon: "images/timer-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeContainer: false
+ }
+
+ ItemLibraryEntry {
+ name: "Timer"
+ category: "d.Qt Quick - Animation"
+ libraryIcon: "images/timer-24px.png"
+ version: "2.0"
+ toolTip: qsTr(" Triggers an action at a given time.")
+ }
+}
+}
diff --git a/share/qtcreator/qmldesigner/itemLibrary/qtquickcontrols2.metainfo b/share/qtcreator/qmldesigner/itemLibrary/qtquickcontrols2.metainfo
new file mode 100644
index 0000000000..cd4165957d
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/qtquickcontrols2.metainfo
@@ -0,0 +1,575 @@
+MetaInfo {
+ Type {
+ name: "QtQuick.Controls.Basic.BusyIndicator"
+ icon: "images/busyindicator-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Busy Indicator"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/busyindicator-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("Indicates activity while, for example, content is being loaded.")
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.Button"
+ icon: "images/button-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Button"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/button-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A button with text.")
+
+ Property { name: "text"; type: "binding"; value: "qsTr(\"Button\")" }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.CheckBox"
+ icon: "images/checkbox-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Check Box"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/checkbox-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A checkbox with a text label.")
+
+ Property { name: "text"; type: "binding"; value: "qsTr(\"Check Box\")" }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.CheckDelegate"
+ icon: "images/checkbox-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Check Delegate"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/checkbox-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("Presents items from a model as checkboxes.")
+
+ Property { name: "text"; type: "binding"; value: "qsTr(\"Check Delegate\")" }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.ComboBox"
+ icon: "images/combobox-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Combo Box"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/combobox-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("An editable drop-down list.")
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.Control"
+ icon: "images/control-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Control"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/control-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("An abstract base type for UI controls.")
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.DelayButton"
+ icon: "images/button-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Delay Button"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/delaybutton-icon.png"
+ version: "2.2"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A button with a delay preventing accidental presses.")
+
+ Property { name: "text"; type: "binding"; value: "qsTr(\"Delay Button\")" }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.Dial"
+ icon: "images/dial-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Dial"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/dial-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+
+ toolTip: qsTr("A circular dial that is rotated to set a value.")
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.Frame"
+ icon: "images/frame-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Frame"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/frame-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("An untitled container for a group of controls.")
+
+ Property { name: "width"; type: "int"; value: 200 }
+ Property { name: "height"; type: "int"; value: 200 }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.GroupBox"
+ icon: "images/groupbox-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Group Box"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/groupbox-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A titled container for a group of controls.")
+
+ Property { name: "width"; type: "int"; value: 200 }
+ Property { name: "height"; type: "int"; value: 200 }
+ Property { name: "title"; type: "binding"; value: "qsTr(\"Group Box\")" }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.ItemDelegate"
+ icon: "images/itemdelegate-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Item Delegate"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/itemdelegate-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("Presents a standard view item. It can be used as a delegate in various views and controls, such as ListView and ComboBox.")
+
+ Property { name: "text"; type: "binding"; value: "qsTr(\"Item Delegate\")" }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.Label"
+ icon: "images/label-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Label"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/label-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A text label.")
+
+ Property { name: "text"; type: "binding"; value: "qsTr(\"Label\")" }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.Page"
+ icon: "images/page-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Page"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/page-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A page with header and footer.")
+
+ Property { name: "width"; type: "int"; value: 200 }
+ Property { name: "height"; type: "int"; value: 200 }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.PageIndicator"
+ icon: "images/pageindicator-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Page Indicator"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/pageindicator-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("Indicates the currently active page.")
+
+ Property { name: "count"; type: "int"; value: 3 }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.Pane"
+ icon: "images/pane-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Pane"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/pane-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("Provides a background matching the application style and theme.")
+
+ Property { name: "width"; type: "int"; value: 200 }
+ Property { name: "height"; type: "int"; value: 200 }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.ProgressBar"
+ icon: "images/progressbar-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Progress Bar"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/progressbar-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A bar indicating the progress of an operation.")
+
+ Property { name: "value"; type: "real"; value: 0.5 }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.RadioButton"
+ icon: "images/radiobutton-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Radio Button"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/radiobutton-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("An option button that you can toggle on or off.")
+
+ Property { name: "text"; type: "binding"; value: "qsTr(\"Radio Button\")" }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.RadioDelegate"
+ icon: "images/radiobutton-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Radio Delegate"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/radiobutton-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("Presents items from a model as radio buttons.")
+
+ Property { name: "text"; type: "binding"; value: "qsTr(\"Radio Delegate\")" }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.RangeSlider"
+ icon: "images/rangeslider-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Range Slider"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/rangeslider-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A bar with adjustable start and end points.")
+
+ Property { name: "first.value"; type: "real"; value: 0.25 }
+ Property { name: "second.value"; type: "real"; value: 0.75 }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.RoundButton"
+ icon: "images/roundbutton-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Round Button"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/roundbutton-icon.png"
+ version: "2.1"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A round button with text.")
+
+ Property { name: "text"; type: "string"; value: "+" }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.Slider"
+ icon: "images/slider-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Slider"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/slider-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("An adjustable slider.")
+
+ Property { name: "value"; type: "real"; value: 0.5 }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.SpinBox"
+ icon: "images/spinbox-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Spin Box"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/spinbox-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A box with an adjustable number.")
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.ScrollView"
+ icon: "images/scrollview-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Scroll View"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/scrollview-icon.png"
+ version: "2.2"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A scrollable area.")
+
+ Property { name: "width"; type: "int"; value: 200 }
+ Property { name: "height"; type: "int"; value: 200 }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.StackView"
+ icon: "images/stackview-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Stack View"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/stackview-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("Provides a stack-based navigation for a set of pages.")
+
+ Property { name: "width"; type: "int"; value: 200 }
+ Property { name: "height"; type: "int"; value: 200 }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.SwipeDelegate"
+ icon: "images/itemdelegate-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Swipe Delegate"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/itemdelegate-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("Presents items from a model as items that you can swipe to expose more options.")
+
+ Property { name: "text"; type: "binding"; value: "qsTr(\"Swipe Delegate\")" }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.SwipeView"
+ icon: "images/swipeview-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Swipe View"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/swipeview-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("Provides a view where you can navigate pages by swiping.")
+
+ Property { name: "width"; type: "int"; value: 200 }
+ Property { name: "height"; type: "int"; value: 200 }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.Switch"
+ icon: "images/switch-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Switch"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/switch-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A button that you can toggle on and off.")
+
+ Property { name: "text"; type: "binding"; value: "qsTr(\"Switch\")" }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.SwitchDelegate"
+ icon: "images/switch-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Switch Delegate"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/switch-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("Presents items from a model as toggle switches.")
+
+ Property { name: "text"; type: "binding"; value: "qsTr(\"Switch Delegate\")" }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.TabBar"
+ icon: "images/toolbar-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Tab Bar"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/toolbar-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A tab-based navigation model.")
+
+ Property { name: "width"; type: "int"; value: 240 }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.TabButton"
+ icon: "images/toolbutton-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Tab Button"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/toolbutton-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A button suitable for a tab bar.")
+
+ Property { name: "text"; type: "binding"; value: "qsTr(\"Tab Button\")" }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.TextArea"
+ icon: "images/textarea-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Text Area"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/textarea-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A multi-line text box.")
+
+ Property { name: "placeholderText"; type: "binding"; value: "qsTr(\"Text Area\")" }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.TextField"
+ icon: "images/textfield-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Text Field"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/textfield-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A single-line text box.")
+
+ Property { name: "placeholderText"; type: "binding"; value: "qsTr(\"Text Field\")" }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.ToolBar"
+ icon: "images/toolbar-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Tool Bar"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/toolbar-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A row that can hold actions and buttons.")
+
+ Property { name: "width"; type: "int"; value: 360 }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.ToolButton"
+ icon: "images/toolbutton-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Tool Button"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/toolbutton-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A button suitable for a tool bar.")
+
+ Property { name: "text"; type: "binding"; value: "qsTr(\"Tool Button\")" }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.ToolSeparator"
+ icon: "images/toolseparator-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Tool Separator"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/toolseparator-icon.png"
+ version: "2.1"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A line to separate sections in a tool bar.")
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Basic.Tumbler"
+ icon: "images/tumbler-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Tumbler"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/tumbler-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A spinnable wheel of selectable items.")
+
+ Property { name: "model"; type: "int"; value: "10" }
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/quick.metainfo b/share/qtcreator/qmldesigner/itemLibrary/quick.metainfo
index f390f72260..98e5684bdc 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/quick.metainfo
+++ b/share/qtcreator/qmldesigner/itemLibrary/quick.metainfo
@@ -2,7 +2,7 @@ MetaInfo {
Type {
name: "QtQuick.Item"
- icon: ":/qtquickplugin/images/item-icon16.png"
+ icon: "images/item-icon16.png"
Hints {
visibleNonDefaultProperties: "layer.effect"
@@ -11,7 +11,7 @@ MetaInfo {
ItemLibraryEntry {
name: "Item"
category: "a.Qt Quick - Basic"
- libraryIcon: ":/qtquickplugin/images/item-icon.png"
+ libraryIcon: "images/item-icon.png"
version: "2.0"
Property { name: "width"; type: "int"; value: 200; }
@@ -22,12 +22,12 @@ MetaInfo {
Type {
name: "QtQuick.Rectangle"
- icon: ":/qtquickplugin/images/rect-icon16.png"
+ icon: "images/rect-icon16.png"
ItemLibraryEntry {
name: "Rectangle"
category: "a.Qt Quick - Basic"
- libraryIcon: ":/qtquickplugin/images/rect-icon.png"
+ libraryIcon: "images/rect-icon.png"
version: "2.0"
Property { name: "width"; type: "int"; value: 200; }
@@ -39,12 +39,12 @@ MetaInfo {
Type {
name: "QtQuick.Text"
- icon: ":/qtquickplugin/images/text-icon16.png"
+ icon: "images/text-icon16.png"
ItemLibraryEntry {
name: "Text"
category: "a.Qt Quick - Basic"
- libraryIcon: ":/qtquickplugin/images/text-icon.png"
+ libraryIcon: "images/text-icon.png"
version: "2.0"
Property { name: "font.pixelSize"; type: "int"; value: 12; }
@@ -55,12 +55,12 @@ MetaInfo {
Type {
name: "QtQuick.TextEdit"
- icon: ":/qtquickplugin/images/text-edit-icon16.png"
+ icon: "images/text-edit-icon16.png"
ItemLibraryEntry {
name: "Text Edit"
category: "a.Qt Quick - Basic"
- libraryIcon: ":/qtquickplugin/images/text-edit-icon.png"
+ libraryIcon: "images/text-edit-icon.png"
version: "2.0"
Property { name: "width"; type: "int"; value: 80; }
@@ -73,12 +73,12 @@ MetaInfo {
Type {
name: "QtQuick.TextInput"
- icon: ":/qtquickplugin/images/text-input-icon16.png"
+ icon: "images/text-input-icon16.png"
ItemLibraryEntry {
name: "Text Input"
category: "a.Qt Quick - Basic"
- libraryIcon: ":/qtquickplugin/images/text-input-icon.png"
+ libraryIcon: "images/text-input-icon.png"
version: "2.0"
Property { name: "width"; type: "int"; value: 80; }
@@ -91,12 +91,12 @@ MetaInfo {
Type {
name: "QtQuick.MouseArea"
- icon: ":/qtquickplugin/images/mouse-area-icon16.png"
+ icon: "images/mouse-area-icon16.png"
ItemLibraryEntry {
name: "Mouse Area"
category: "a.Qt Quick - Basic"
- libraryIcon: ":/qtquickplugin/images/mouse-area-icon.png"
+ libraryIcon: "images/mouse-area-icon.png"
version: "2.0"
Property { name: "width"; type: "int"; value: 100; }
@@ -107,17 +107,17 @@ MetaInfo {
Type {
name: "QtQuick.Image"
- icon: ":/qtquickplugin/images/image-icon16.png"
+ icon: "images/image-icon16.png"
ItemLibraryEntry {
name: "Image"
category: "a.Qt Quick - Basic"
- libraryIcon: ":/qtquickplugin/images/image-icon.png"
+ libraryIcon: "images/image-icon.png"
version: "2.0"
Property { name: "width"; type: "int"; value: 100; }
Property { name: "height"; type: "int"; value: 100; }
- Property { name: "source"; type: "QUrl"; value:"qrc:/qtquickplugin/images/template_image.png"; }
+ Property { name: "source"; type: "QUrl"; value:"qrcimages/template_image.png"; }
Property { name: "fillMode"; type: "enum"; value: "Image.PreserveAspectFit"; }
toolTip: qsTr("Displays an image.")
}
@@ -125,29 +125,29 @@ MetaInfo {
Type {
name: "QtQuick.AnimatedImage"
- icon: ":/qtquickplugin/images/animated-image-icon16.png"
+ icon: "images/animated-image-icon16.png"
ItemLibraryEntry {
name: "Animated Image"
category: "a.Qt Quick - Basic"
- libraryIcon: ":/qtquickplugin/images/animated-image-icon.png"
+ libraryIcon: "images/animated-image-icon.png"
version: "2.0"
Property { name: "width"; type: "int"; value: 100; }
Property { name: "height"; type: "int"; value: 100; }
- Property { name: "source"; type: "QUrl"; value:"qrc:/qtquickplugin/images/template_image.png"; }
+ Property { name: "source"; type: "QUrl"; value:"qrcimages/template_image.png"; }
toolTip: qsTr("Animates a series of images.")
}
}
Type {
name: "QtQuick.AnimatedSprite"
- icon: ":/qtquickplugin/images/animated-image-icon16.png"
+ icon: "images/animated-image-icon16.png"
ItemLibraryEntry {
name: "Animated Sprite"
category: "a.Qt Quick - Basic"
- libraryIcon: ":/qtquickplugin/images/animated-image-icon.png"
+ libraryIcon: "images/animated-image-icon.png"
version: "2.0"
Property { name: "frameWidth"; type: "int"; value: 64; }
@@ -155,36 +155,36 @@ MetaInfo {
Property { name: "frameCount"; type: "int"; value: 4; }
Property { name: "frameDuration"; type: "int"; value: 500; }
Property { name: "source"; type: "QUrl"; value:"animatedsprite-loading.png"; }
- ExtraFile { source: ":/qtquickplugin/images/animatedsprite-loading.png" }
+ ExtraFile { source: "images/animatedsprite-loading.png" }
toolTip: qsTr("Draws a sprite animation.")
}
}
Type {
name: "QtQuick.BorderImage"
- icon: ":/qtquickplugin/images/border-image-icon16.png"
+ icon: "images/border-image-icon16.png"
ItemLibraryEntry {
name: "Border Image"
category: "a.Qt Quick - Basic"
- libraryIcon: ":/qtquickplugin/images/border-image-icon.png"
+ libraryIcon: "images/border-image-icon.png"
version: "2.0"
Property { name: "width"; type: "int"; value: 100; }
Property { name: "height"; type: "int"; value: 100; }
- Property { name: "source"; type: "QUrl"; value:"qrc:/qtquickplugin/images/template_image.png"; }
+ Property { name: "source"; type: "QUrl"; value:"qrcimages/template_image.png"; }
toolTip: qsTr("A responsive border based on an image.")
}
}
Type {
name: "QtQuick.Flickable"
- icon: ":/qtquickplugin/images/flickable-icon16.png"
+ icon: "images/flickable-icon16.png"
ItemLibraryEntry {
name: "Flickable"
category: "a.Qt Quick - Basic"
- libraryIcon: ":/qtquickplugin/images/flickable-icon.png"
+ libraryIcon: "images/flickable-icon.png"
version: "2.0"
Property { name: "width"; type: "int"; value: 300; }
@@ -195,57 +195,57 @@ MetaInfo {
Type {
name: "QtQuick.GridView"
- icon: ":/qtquickplugin/images/gridview-icon16.png"
+ icon: "images/gridview-icon16.png"
ItemLibraryEntry {
name: "Grid View"
category: "b.Qt Quick - Views"
- libraryIcon: ":/qtquickplugin/images/gridview-icon.png"
+ libraryIcon: "images/gridview-icon.png"
version: "2.0"
- QmlSource { source: ":/qtquickplugin/source/gridviewv2.qml" }
+ QmlSource { source: "source/gridviewv2.qml" }
toolTip: qsTr("Organizes dynamic data sets in a grid.")
}
}
Type {
name: "QtQuick.ListView"
- icon: ":/qtquickplugin/images/listview-icon16.png"
+ icon: "images/listview-icon16.png"
ItemLibraryEntry {
name: "List View"
category: "b.Qt Quick - Views"
- libraryIcon: ":/qtquickplugin/images/listview-icon.png"
+ libraryIcon: "images/listview-icon.png"
version: "2.0"
- QmlSource { source: ":/qtquickplugin/source/listviewv2.qml" }
+ QmlSource { source: "source/listviewv2.qml" }
toolTip: qsTr("Organizes dynamic data sets in a list.")
}
}
Type {
name: "QtQuick.PathView"
- icon: ":/qtquickplugin/images/pathview-icon16.png"
+ icon: "images/pathview-icon16.png"
ItemLibraryEntry {
name: "Path View"
category: "b.Qt Quick - Views"
- libraryIcon: ":/qtquickplugin/images/pathview-icon.png"
+ libraryIcon: "images/pathview-icon.png"
version: "2.0"
- QmlSource { source: ":/qtquickplugin/source/pathviewv2.qml" }
+ QmlSource { source: "source/pathviewv2.qml" }
toolTip: qsTr("Organizes dynamic data sets along a path.")
}
}
Type {
name: "QtQuick.FocusScope"
- icon: ":/qtquickplugin/images/focusscope-icon16.png"
+ icon: "images/focusscope-icon16.png"
ItemLibraryEntry {
name: "Focus Scope"
category: "a.Qt Quick - Basic"
- libraryIcon: ":/qtquickplugin/images/focusscope-icon.png"
+ libraryIcon: "images/focusscope-icon.png"
version: "2.0"
Property { name: "width"; type: "int"; value: 100; }
@@ -256,12 +256,12 @@ MetaInfo {
Type {
name: "QtQuick.Column"
- icon: ":/qtquickplugin/images/column-positioner-icon-16px.png"
+ icon: "images/column-positioner-icon-16px.png"
ItemLibraryEntry {
name: "Column"
category: "c.Qt Quick - Positioner"
- libraryIcon: ":/qtquickplugin/images/column-positioner-icon.png"
+ libraryIcon: "images/column-positioner-icon.png"
version: "2.0"
Property { name: "width"; type: "int"; value: 200; }
@@ -273,12 +273,12 @@ MetaInfo {
Type {
name: "QtQuick.Row"
- icon: ":/qtquickplugin/images/row-positioner-icon-16px.png"
+ icon: "images/row-positioner-icon-16px.png"
ItemLibraryEntry {
name: "Row"
category: "c.Qt Quick - Positioner"
- libraryIcon: ":/qtquickplugin/images/row-positioner-icon.png"
+ libraryIcon: "images/row-positioner-icon.png"
version: "2.0"
toolTip: qsTr("Organizes items in a row.")
@@ -289,12 +289,12 @@ MetaInfo {
Type {
name: "QtQuick.Grid"
- icon: ":/qtquickplugin/images/grid-positioner-icon-16px.png"
+ icon: "images/grid-positioner-icon-16px.png"
ItemLibraryEntry {
name: "Grid"
category: "c.Qt Quick - Positioner"
- libraryIcon: ":/qtquickplugin/images/grid-positioner-icon.png"
+ libraryIcon: "images/grid-positioner-icon.png"
version: "2.0"
Property { name: "width"; type: "int"; value: 400; }
@@ -305,12 +305,12 @@ MetaInfo {
Type {
name: "QtQuick.Flow"
- icon: ":/qtquickplugin/images/flow-positioner-icon-16px.png"
+ icon: "images/flow-positioner-icon-16px.png"
ItemLibraryEntry {
name: "Flow"
category: "c.Qt Quick - Positioner"
- libraryIcon: ":/qtquickplugin/images/flow-positioner-icon.png"
+ libraryIcon: "images/flow-positioner-icon.png"
version: "2.0"
Property { name: "width"; type: "int"; value: 400; }
@@ -321,7 +321,7 @@ MetaInfo {
Type {
name: "QtQuick.Timeline.Timeline"
- icon: ":/qtquickplugin/images/timeline-16px.png"
+ icon: "images/timeline-16px.png"
Hints {
visibleNonDefaultProperties: "animations"
@@ -337,7 +337,7 @@ MetaInfo {
Type {
name: "QtQuick.Timeline.TimelineAnimation"
- icon: ":/qtquickplugin/images/timeline-animation-16px.png"
+ icon: "images/timeline-animation-16px.png"
Hints {
visibleInLibrary: false
@@ -352,7 +352,7 @@ MetaInfo {
Type {
name: "QtQuick.Timeline.Keyframe"
- icon: ":/qtquickplugin/images/keyframe-16px.png"
+ icon: "images/keyframe-16px.png"
ItemLibraryEntry {
name: "Keyframe"
@@ -364,7 +364,7 @@ MetaInfo {
Type {
name: "QtQuick.Timeline.KeyframeGroup"
- icon: ":/qtquickplugin/images/keyframe-16px.png"
+ icon: "images/keyframe-16px.png"
ItemLibraryEntry {
name: "KeyframeGroup"
@@ -376,7 +376,7 @@ MetaInfo {
Type {
name: "QtQuick.PropertyAnimation"
- icon: ":/qtquickplugin/images/item-icon16.png"
+ icon: "images/item-icon16.png"
Hints {
visibleInNavigator: true
@@ -388,7 +388,7 @@ MetaInfo {
ItemLibraryEntry {
name: "Property Animation"
category: "d.Qt Quick - Animation"
- libraryIcon: ":/qtquickplugin/images/item-icon.png"
+ libraryIcon: "images/item-icon.png"
version: "2.0"
toolTip: qsTr("Animates changes in property values.")
}
@@ -396,7 +396,7 @@ MetaInfo {
Type {
name: "QtQuick.PauseAnimation"
- icon: ":/qtquickplugin/images/item-icon16.png"
+ icon: "images/item-icon16.png"
Hints {
visibleInNavigator: true
@@ -408,7 +408,7 @@ MetaInfo {
ItemLibraryEntry {
name: "Pause Animation"
category: "d.Qt Quick - Animation"
- libraryIcon: ":/qtquickplugin/images/item-icon.png"
+ libraryIcon: "images/item-icon.png"
version: "2.0"
toolTip: qsTr("Provides a pause between animations.")
}
@@ -416,7 +416,7 @@ MetaInfo {
Type {
name: "QtQuick.SequentialAnimation"
- icon: ":/qtquickplugin/images/item-icon16.png"
+ icon: "images/item-icon16.png"
Hints {
visibleInNavigator: true
@@ -427,7 +427,7 @@ MetaInfo {
ItemLibraryEntry {
name: "Sequential Animation"
category: "d.Qt Quick - Animation"
- libraryIcon: ":/qtquickplugin/images/item-icon.png"
+ libraryIcon: "images/item-icon.png"
version: "2.0"
toolTip: qsTr("Runs animations one after the other.")
}
@@ -435,7 +435,7 @@ MetaInfo {
Type {
name: "QtQuick.ParallelAnimation"
- icon: ":/qtquickplugin/images/item-icon16.png"
+ icon: "images/item-icon16.png"
Hints {
visibleInNavigator: true
@@ -446,7 +446,7 @@ MetaInfo {
ItemLibraryEntry {
name: "Parallel Animation"
category: "d.Qt Quick - Animation"
- libraryIcon: ":/qtquickplugin/images/item-icon.png"
+ libraryIcon: "images/item-icon.png"
version: "2.0"
toolTip: qsTr("Runs animations together at the same time.")
}
@@ -454,7 +454,7 @@ MetaInfo {
Type {
name: "QtQuick.PropertyAction"
- icon: ":/qtquickplugin/images/item-icon16.png"
+ icon: "images/item-icon16.png"
Hints {
visibleInNavigator: true
@@ -466,7 +466,7 @@ MetaInfo {
ItemLibraryEntry {
name: "Property Action"
category: "d.Qt Quick - Animation"
- libraryIcon: ":/qtquickplugin/images/item-icon.png"
+ libraryIcon: "images/item-icon.png"
version: "2.0"
toolTip: qsTr("Provides an immediate property change during animations.")
}
@@ -474,7 +474,7 @@ MetaInfo {
Type {
name: "QtQuick.ScriptAction"
- icon: ":/qtquickplugin/images/item-icon16.png"
+ icon: "images/item-icon16.png"
Hints {
visibleInNavigator: true
@@ -486,7 +486,7 @@ MetaInfo {
ItemLibraryEntry {
name: "Script Action"
category: "d.Qt Quick - Animation"
- libraryIcon: ":/qtquickplugin/images/item-icon.png"
+ libraryIcon: "images/item-icon.png"
version: "2.0"
toolTip: qsTr("Runs a script during animation.")
}
@@ -494,7 +494,7 @@ MetaInfo {
Type {
name: "QtQuick.ColorAnimation"
- icon: ":/qtquickplugin/images/item-icon16.png"
+ icon: "images/item-icon16.png"
Hints {
visibleInNavigator: true
@@ -506,7 +506,7 @@ MetaInfo {
ItemLibraryEntry {
name: "Color Animation"
category: "d.Qt Quick - Animation"
- libraryIcon: ":/qtquickplugin/images/item-icon.png"
+ libraryIcon: "images/item-icon.png"
version: "2.0"
toolTip: qsTr("Animates the color of an item.")
}
@@ -514,7 +514,7 @@ MetaInfo {
Type {
name: "QtQuick.NumberAnimation"
- icon: ":/qtquickplugin/images/item-icon16.png"
+ icon: "images/item-icon16.png"
Hints {
visibleInNavigator: true
@@ -526,7 +526,7 @@ MetaInfo {
ItemLibraryEntry {
name: "Number Animation"
category: "d.Qt Quick - Animation"
- libraryIcon: ":/qtquickplugin/images/item-icon.png"
+ libraryIcon: "images/item-icon.png"
version: "2.0"
Property { name: "to"; type: "int"; value: 0; }
Property { name: "from"; type: "int"; value: 0; }
@@ -535,74 +535,13 @@ MetaInfo {
}
Type {
- name: "QtQml.Timer"
- icon: ":/qtquickplugin/images/timer-16px.png"
-
- Hints {
- visibleInNavigator: true
- canBeDroppedInNavigator: true
- canBeDroppedInFormEditor: false
- canBeContainer: false
- }
-
- ItemLibraryEntry {
- name: "Timer"
- category: "d.Qt Quick - Animation"
- libraryIcon: ":/qtquickplugin/images/timer-24px.png"
- version: "2.0"
- toolTip: qsTr(" Triggers an action at a given time.")
- }
- }
-
- Type {
- name: "QML.Component"
- icon: ":/qtquickplugin/images/component-icon16.png"
-
- Hints {
- canBeDroppedInNavigator: true
- canBeDroppedInFormEditor: false
- }
-
- ItemLibraryEntry {
- name: "Component"
- category: "e.Qt Quick - Instancers"
- libraryIcon: ":/qtquickplugin/images/component-icon.png"
- version: "1.0"
-
- QmlSource { source: ":/qtquickplugin/source/component.qml" }
- toolTip: qsTr("Allows you to define components inline, within a QML document.")
- }
- }
-
- Type {
- name: "QML.Component"
- icon: ":/qtquickplugin/images/component-icon16.png"
-
- Hints {
- canBeDroppedInNavigator: true
- canBeDroppedInFormEditor: false
- }
-
- ItemLibraryEntry {
- name: "Component 3D"
- category: "Instancers"
- libraryIcon: ":/qtquickplugin/images/component-icon.png"
- version: "1.0"
- requiredImport: "QtQuick3D"
-
- QmlSource { source: ":/qtquickplugin/source/component3d.qml" }
- toolTip: qsTr("Allows you to define 3D components inline, within a QML document.")
- }
- }
-
- Type {
name: "QtQuick.Loader"
- icon: ":/qtquickplugin/images/loader-icon16.png"
+ icon: "images/loader-icon16.png"
ItemLibraryEntry {
name: "Loader"
category: "e.Qt Quick - Instancers"
- libraryIcon: ":/qtquickplugin/images/loader-icon.png"
+ libraryIcon: "images/loader-icon.png"
version: "2.0"
Property { name: "width"; type: "int"; value: 200; }
Property { name: "height"; type: "int"; value: 200; }
@@ -612,7 +551,7 @@ MetaInfo {
Type {
name: "QtQuick.Repeater"
- icon: ":/qtquickplugin/images/repeater-icon16.png"
+ icon: "images/repeater-icon16.png"
Hints {
canBeDroppedInFormEditor: false
@@ -622,216 +561,9 @@ MetaInfo {
ItemLibraryEntry {
name: "Repeater"
category: "e.Qt Quick - Instancers"
- libraryIcon: ":/qtquickplugin/images/repeater-icon.png"
+ libraryIcon: "images/repeater-icon.png"
version: "2.0"
toolTip: qsTr("Creates a number of copies of the same item.")
}
}
-
- Type {
- name: "QtMultimedia.MediaPlayer"
- icon: ":/qtquickplugin/images/media-player-16px.png"
-
- Hints {
- visibleInNavigator: true
- canBeDroppedInNavigator: true
- canBeDroppedInFormEditor: false
- canBeContainer: false
- }
-
- ItemLibraryEntry {
- name: "Media Player"
- category: "f.Qt Quick - Multimedia"
- libraryIcon: ":/qtquickplugin/images/media-player-24px.png"
- version: "6.0"
- requiredImport: "QtMultimedia"
- }
- }
-
- Type {
- name: "QtMultimedia.AudioOutput"
- icon: ":/qtquickplugin/images/audio-output-16px.png"
-
- Hints {
- visibleInNavigator: true
- canBeDroppedInNavigator: true
- canBeDroppedInFormEditor: false
- canBeContainer: false
- }
-
- ItemLibraryEntry {
- name: "Audio Output"
- category: "f.Qt Quick - Multimedia"
- libraryIcon: ":/qtquickplugin/images/audio-output-24px.png"
- version: "6.0"
- requiredImport: "QtMultimedia"
- }
- }
-
- Type {
- name: "QtMultimedia.VideoOutput"
- icon: ":/qtquickplugin/images/video-output-16px.png"
-
- Hints {
- visibleInNavigator: true
- canBeDroppedInNavigator: true
- canBeDroppedInFormEditor: false
- canBeContainer: false
- }
-
- ItemLibraryEntry {
- name: "Video Output"
- category: "f.Qt Quick - Multimedia"
- libraryIcon: ":/qtquickplugin/images/video-output-24px.png"
- version: "6.0"
- requiredImport: "QtMultimedia"
- }
- }
-
- Type {
- name: "QtMultimedia.Video"
- icon: ":/qtquickplugin/images/video-16px.png"
-
- Hints {
- visibleInNavigator: true
- canBeDroppedInNavigator: true
- canBeDroppedInFormEditor: true
- canBeContainer: false
- }
-
- ItemLibraryEntry {
- name: "Video"
- category: "f.Qt Quick - Multimedia"
- libraryIcon: ":/qtquickplugin/images/video-24px.png"
- version: "6.0"
- requiredImport: "QtMultimedia"
-
- Property { name: "width"; type: "int"; value: 200; }
- Property { name: "height"; type: "int"; value: 200; }
- }
- }
-
- Type {
- name: "QtQuick3D.SpatialAudio.AmbientSound"
- icon: ":/qtquickplugin/images/ambient-sound-16.png"
-
- Hints {
- canBeDroppedInNavigator: true
- canBeDroppedInFormEditor: false
- canBeDroppedInView3D: false
- canBeContainer: false
- }
-
- ItemLibraryEntry {
- name: "Ambient Sound"
- category: "Spatial Audio"
- libraryIcon: ":/qtquickplugin/images/ambient-sound-24.png"
- version: "6.0"
- requiredImport: "QtQuick3D.SpatialAudio"
- toolTip: qsTr("An ambient background sound.")
- }
- }
-
- Type {
- name: "QtQuick3D.SpatialAudio.AudioEngine"
- icon: ":/qtquickplugin/images/audio-engine-16.png"
-
- Hints {
- canBeDroppedInNavigator: true
- canBeDroppedInFormEditor: false
- canBeDroppedInView3D: false
- canBeContainer: false
- }
-
- ItemLibraryEntry {
- name: "Audio Engine"
- category: "Spatial Audio"
- libraryIcon: ":/qtquickplugin/images/audio-engine-24.png"
- version: "6.0"
- requiredImport: "QtQuick3D.SpatialAudio"
- toolTip: qsTr("Manages sound objects inside a 3D scene.")
- }
- }
-
- Type {
- name: "QtQuick3D.SpatialAudio.AudioListener"
- icon: ":/qtquickplugin/images/audio-listener-16.png"
-
- Hints {
- canBeDroppedInNavigator: true
- canBeDroppedInFormEditor: false
- canBeDroppedInView3D: true
- }
-
- ItemLibraryEntry {
- name: "Audio Listener"
- category: "Spatial Audio"
- libraryIcon: ":/qtquickplugin/images/audio-listener-24.png"
- version: "6.0"
- requiredImport: "QtQuick3D.SpatialAudio"
- toolTip: qsTr("Sets the position and orientation of listening.")
- }
- }
-
- Type {
- name: "QtQuick3D.SpatialAudio.AudioRoom"
- icon: ":/qtquickplugin/images/audio-room-16.png"
-
- Hints {
- canBeDroppedInNavigator: true
- canBeDroppedInFormEditor: false
- canBeDroppedInView3D: true
- }
-
- ItemLibraryEntry {
- name: "Audio Room"
- category: "Spatial Audio"
- libraryIcon: ":/qtquickplugin/images/audio-room-24.png"
- version: "6.0"
- requiredImport: "QtQuick3D.SpatialAudio"
- toolTip: qsTr("Sets up a room for the spatial audio engine.")
- }
- }
-
- Type {
- name: "QtQuick3D.SpatialAudio.SpatialSound"
- icon: ":/qtquickplugin/images/spatial-audio-16.png"
-
- Hints {
- canBeDroppedInNavigator: true
- canBeDroppedInFormEditor: false
- canBeDroppedInView3D: true
- }
-
- ItemLibraryEntry {
- name: "Spatial Sound"
- category: "Spatial Audio"
- libraryIcon: ":/qtquickplugin/images/spatial-audio-24.png"
- version: "6.0"
- requiredImport: "QtQuick3D.SpatialAudio"
- toolTip: qsTr("A sound object in 3D space.")
- }
- }
-
- Type {
- name: "QtQuick3D.BakedLightmap"
- icon: ":/ItemLibrary/images/item-default-icon.png"
-
- Hints {
- canBeDroppedInNavigator: true
- canBeDroppedInFormEditor: false
- canBeDroppedInView3D: false
- }
-
- ItemLibraryEntry {
- name: "Baked Lightmap"
- category: "Components"
- libraryIcon: ":/ItemLibrary/images/item-default-icon.png"
- version: "6.5"
- requiredImport: "QtQuick3D"
- toolTip: qsTr("An object to specify details about baked lightmap of a model.")
-
- Property { name: "loadPrefix"; type: "string"; value: "lightmaps"; }
- }
- }
}
diff --git a/share/qtcreator/qmldesigner/itemLibrary/quick3d.metainfo b/share/qtcreator/qmldesigner/itemLibrary/quick3d.metainfo
new file mode 100644
index 0000000000..8f00613966
--- /dev/null
+++ b/share/qtcreator/qmldesigner/itemLibrary/quick3d.metainfo
@@ -0,0 +1,125 @@
+MetaInfo {
+ Type {
+ name: "QtQuick3D.SpatialAudio.AmbientSound"
+ icon: "images/ambient-sound-16.png"
+
+ Hints {
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ canBeContainer: false
+ }
+
+ ItemLibraryEntry {
+ name: "Ambient Sound"
+ category: "Spatial Audio"
+ libraryIcon: "images/ambient-sound-24.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D.SpatialAudio"
+ toolTip: qsTr("An ambient background sound.")
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.SpatialAudio.AudioEngine"
+ icon: "images/audio-engine-16.png"
+
+ Hints {
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ canBeContainer: false
+ }
+
+ ItemLibraryEntry {
+ name: "Audio Engine"
+ category: "Spatial Audio"
+ libraryIcon: "images/audio-engine-24.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D.SpatialAudio"
+ toolTip: qsTr("Manages sound objects inside a 3D scene.")
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.SpatialAudio.AudioListener"
+ icon: "images/audio-listener-16.png"
+
+ Hints {
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Audio Listener"
+ category: "Spatial Audio"
+ libraryIcon: "images/audio-listener-24.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D.SpatialAudio"
+ toolTip: qsTr("Sets the position and orientation of listening.")
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.SpatialAudio.AudioRoom"
+ icon: "images/audio-room-16.png"
+
+ Hints {
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Audio Room"
+ category: "Spatial Audio"
+ libraryIcon: "images/audio-room-24.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D.SpatialAudio"
+ toolTip: qsTr("Sets up a room for the spatial audio engine.")
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.SpatialAudio.SpatialSound"
+ icon: "images/spatial-audio-16.png"
+
+ Hints {
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Spatial Sound"
+ category: "Spatial Audio"
+ libraryIcon: "images/spatial-audio-24.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D.SpatialAudio"
+ toolTip: qsTr("A sound object in 3D space.")
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.BakedLightmap"
+ icon: ":/ItemLibrary/images/item-default-icon.png"
+
+ Hints {
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "Baked Lightmap"
+ category: "Components"
+ libraryIcon: ":/ItemLibrary/images/item-default-icon.png"
+ version: "6.5"
+ requiredImport: "QtQuick3D"
+ toolTip: qsTr("An object to specify details about baked lightmap of a model.")
+
+ Property { name: "loadPrefix"; type: "string"; value: "lightmaps"; }
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowserContextMenu.qml b/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowserContextMenu.qml
index f72d21b35b..b01aa7d2a3 100644
--- a/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowserContextMenu.qml
+++ b/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowserContextMenu.qml
@@ -127,4 +127,13 @@ StudioControls.Menu {
onTriggered: materialBrowserModel.addNewMaterial()
}
+
+ Component.onCompleted: {
+ if (MaterialBrowserBackend.rootView.userBundleEnabled()) {
+ var menuItem = Qt.createQmlObject("import StudioControls as StudioControls; StudioControls.MenuItem {}", root)
+ menuItem.text = qsTr("Add to Content Library")
+ menuItem.onTriggered.connect(MaterialBrowserBackend.rootView.addMaterialToContentLibrary)
+ root.addItem(menuItem)
+ }
+ }
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/EffectsSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/EffectsSection.qml
new file mode 100644
index 0000000000..056bd5fd60
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/EffectsSection.qml
@@ -0,0 +1,490 @@
+// 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 HelperWidgets
+import StudioTheme as StudioTheme
+import StudioControls as StudioControls
+
+Section {
+ id: root
+
+ property bool hasDesignerEffect: false
+ property var model
+ property var effectNode
+ property var effectNodeWrapper
+
+ // Draggging
+ property Item draggedSec: null
+ property var secsY: []
+ property int moveFromIdx: 0
+ property int moveToIdx: 0
+
+ function invalidate() {
+ root.effectNode = null
+ root.model = null
+
+ var effect = modelNodeBackend.allChildrenOfType("DesignEffect")
+ root.effectNode = effect
+ root.effectNodeWrapper = modelNodeBackend.registerSubSelectionWrapper(effect)
+ root.hasDesignerEffect = effect.length === 1
+
+ if (!root.hasDesignerEffect)
+ return
+
+ root.model = modelNodeBackend.allChildren(effect[0]) //ids for all effects
+ }
+
+ leftPadding: 0
+ anchors.left: parent.left
+ anchors.right: parent.right
+ caption: qsTr('Effects <a style="color:%1;">[beta]</a>').arg(StudioTheme.Values.themeInteraction)
+ visible: backendValues.layer_effect.isAvailable
+
+ property Connections connection: Connections {
+ target: modelNodeBackend
+
+ function onSelectionChanged() { root.invalidate() }
+ function onSelectionToBeChanged() { root.model = [] }
+ }
+
+ SectionLayout {
+ PropertyLabel {}
+
+ SecondColumnLayout {
+ Spacer { implicitWidth: StudioTheme.Values.actionIndicatorWidth }
+
+ AbstractButton {
+ id: effectButton
+ implicitWidth: StudioTheme.Values.singleControlColumnWidth
+ width: StudioTheme.Values.singleControlColumnWidth
+ buttonIcon: root.hasDesignerEffect ? qsTr("Remove Effects") : qsTr("Add Effects")
+ iconFont: StudioTheme.Constants.font
+ tooltip: qsTr("Adds a note with a title to explain the component.")
+ onClicked: {
+ if (root.hasDesignerEffect) {
+ root.effectNodeWrapper.deleteModelNode()
+ } else {
+ modelNodeBackend.createModelNode(-1, "data", "DesignEffect", "QtQuick.Studio.DesignEffects")
+ var effectNode = modelNodeBackend.allChildrenOfType("DesignEffect")
+ modelNodeBackend.createModelNode(effectNode, "effects", "DesignDropShadow")
+ }
+ root.invalidate()
+ }
+ }
+ }
+
+ PropertyLabel {
+ text: qsTr("Visibility")
+ visible: root.hasDesignerEffect
+ }
+
+ SecondColumnLayout {
+ visible: root.hasDesignerEffect
+
+ CheckBox {
+ text: qsTr("Visible")
+ implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ + StudioTheme.Values.actionIndicatorWidth
+ backendValue: root.effectNodeWrapper.properties.visible
+ }
+
+ ExpandingSpacer {}
+ }
+ }
+
+ Item {
+ visible: root.hasDesignerEffect
+ width: 1
+ height: StudioTheme.Values.sectionHeadSpacerHeight
+ }
+
+ function handleDragMove() {
+ root.dragTimer.stop()
+ if (root.secsY.length === 0) {
+ for (let i = 0; i < repeater.count; ++i)
+ root.secsY[i] = repeater.itemAt(i).y
+ }
+
+ let scrollView = Controller.mainScrollView
+
+ let oldContentY = scrollView.contentY
+ if (root.draggedSec.y < scrollView.dragScrollMargin + scrollView.contentY
+ && scrollView.contentY > 0) {
+ scrollView.contentY -= scrollView.dragScrollMargin / 2
+ } else if (root.draggedSec.y > scrollView.contentY + scrollView.height - scrollView.dragScrollMargin
+ && scrollView.contentY < scrollView.contentHeight - scrollView.height) {
+ scrollView.contentY += scrollView.dragScrollMargin / 2
+ if (scrollView.contentY > scrollView.contentHeight - scrollView.height)
+ scrollView.contentY = scrollView.contentHeight - scrollView.height
+ }
+
+ if (scrollView.contentY < 0)
+ scrollView.contentY = 0
+
+ if (oldContentY !== scrollView.contentY) {
+ // Changing dragged section position in drag handler doesn't seem to stick
+ // when triggered by mouse move, so do it again async
+ root.dragTimer.targetY = root.draggedSec.y - oldContentY + scrollView.contentY
+ root.dragTimer.restart()
+ root.dragConnection.enabled = false
+ root.draggedSec.y = root.dragTimer.targetY
+ root.dragConnection.enabled = true
+ }
+
+ root.moveToIdx = root.moveFromIdx
+ for (let i = 0; i < repeater.count; ++i) {
+ let currItem = repeater.itemAt(i)
+ if (i > root.moveFromIdx) {
+ if (root.draggedSec.y > currItem.y) {
+ currItem.y = root.secsY[i] - root.draggedSec.height - nodesCol.spacing
+ root.moveToIdx = i
+ } else {
+ currItem.y = root.secsY[i]
+ }
+ } else if (i < root.moveFromIdx) {
+ if (root.draggedSec.y < currItem.y) {
+ currItem.y = root.secsY[i] + root.draggedSec.height + nodesCol.spacing
+ root.moveToIdx = Math.min(root.moveToIdx, i)
+ } else {
+ currItem.y = root.secsY[i]
+ }
+ }
+ }
+ }
+
+ property Connections dragConnection: Connections {
+ target: root.draggedSec
+
+ function onYChanged() { root.handleDragMove() }
+ }
+
+ property Timer dragTimer: Timer {
+ running: false
+ interval: 16
+ repeat: false
+
+ property real targetY: -1
+
+ onTriggered: {
+ // Ensure we get position change triggers even if user holds mouse still to
+ // make scrolling smooth
+ root.draggedSec.y = targetY
+ root.handleDragMove()
+ }
+ }
+
+ Column {
+ id: nodesCol
+ anchors.left: parent.left
+ anchors.right: parent.right
+ spacing: 1
+
+ Section {
+ sectionHeight: 37
+ anchors.left: parent.left
+ anchors.right: parent.right
+ caption: qsTr("Layer Blur")
+ labelCapitalization: Font.MixedCase
+ visible: root.hasDesignerEffect
+ category: "DesignEffects"
+ expanded: false
+
+ SectionLayout {
+
+ PropertyLabel { text: qsTr("Visibility") }
+
+ SecondColumnLayout {
+ CheckBox {
+ text: qsTr("Visible")
+ implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ + StudioTheme.Values.actionIndicatorWidth
+ backendValue: root.effectNodeWrapper.properties.layerBlurVisible
+ }
+
+ ExpandingSpacer {}
+ }
+
+ PropertyLabel { text: qsTr("Blur") }
+
+ SecondColumnLayout {
+ SpinBox {
+ implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ + StudioTheme.Values.actionIndicatorWidth
+ backendValue: root.effectNodeWrapper.properties.layerBlurRadius
+ minimumValue: 0
+ maximumValue: 250
+ }
+
+ ExpandingSpacer {}
+ }
+ }
+ }
+
+ Section {
+ sectionHeight: 37
+ anchors.left: parent.left
+ anchors.right: parent.right
+ caption: qsTr("Background Blur")
+ labelCapitalization: Font.MixedCase
+ visible: root.hasDesignerEffect
+ category: "DesignEffects"
+ expanded: false
+
+ SectionLayout {
+
+ PropertyLabel { text: qsTr("Visibility") }
+
+ SecondColumnLayout {
+ CheckBox {
+ text: qsTr("Visible")
+ implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ + StudioTheme.Values.actionIndicatorWidth
+ backendValue: root.effectNodeWrapper.properties.backgroundBlurVisible
+ }
+
+ ExpandingSpacer {}
+ }
+
+ PropertyLabel { text: qsTr("Blur") }
+
+ SecondColumnLayout {
+ SpinBox {
+ implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ + StudioTheme.Values.actionIndicatorWidth
+ backendValue: root.effectNodeWrapper.properties.backgroundBlurRadius
+ minimumValue: 0
+ maximumValue: 250
+ }
+
+ ExpandingSpacer {}
+ }
+
+ PropertyLabel { text: qsTr("Background") }
+
+ SecondColumnLayout {
+ ItemFilterComboBox {
+ implicitWidth: StudioTheme.Values.singleControlColumnWidth
+ + StudioTheme.Values.actionIndicatorWidth
+ width: implicitWidth
+ typeFilter: "QtQuick.Item"
+ backendValue: root.effectNodeWrapper.properties.backgroundLayer
+ }
+
+ ExpandingSpacer {}
+ }
+ }
+ }
+
+ Repeater {
+ id: repeater
+ model: root.model
+
+ Section {
+ id: delegate
+
+ property QtObject wrapper: modelNodeBackend.registerSubSelectionWrapper(modelData)
+ property bool wasExpanded: false
+
+ Behavior on y {
+ id: dragAnimation
+
+ PropertyAnimation {
+ duration: 300
+ easing.type: Easing.InOutQuad
+ }
+ }
+
+ onStartDrag: function(section) {
+ root.draggedSec = section
+ root.moveFromIdx = index
+ // We only need to animate non-dragged sections
+ dragAnimation.enabled = false
+ delegate.wasExpanded = delegate.expanded
+ delegate.expanded = false
+ delegate.highlightBorder = true
+ root.secsY = []
+ }
+
+ onStopDrag: {
+ if (root.secsY.length !== 0) {
+ if (root.moveFromIdx === root.moveToIdx)
+ root.draggedSec.y = root.secsY[root.moveFromIdx]
+ else
+ modelNodeBackend.moveNode(root.effectNode, "effects", root.moveFromIdx, root.moveToIdx)
+ }
+
+ delegate.highlightBorder = false
+ root.draggedSec = null
+ delegate.expanded = delegate.wasExpanded
+ dragAnimation.enabled = true
+
+ Qt.callLater(root.invalidate)
+ }
+
+ sectionHeight: 37
+ anchors.left: parent.left
+ anchors.right: parent.right
+ category: "DesignEffects"
+ fillBackground: true
+ expanded: false
+
+ draggable: true
+ showCloseButton: true
+
+ content: StudioControls.ComboBox {
+ id: shadowComboBox
+ actionIndicatorVisible: false
+ width: 200
+ textRole: "text"
+ valueRole: "value"
+ model: [
+ { value: "DesignDropShadow", text: qsTr("Drop Shadow") },
+ { value: "DesignInnerShadow", text: qsTr("Inner Shadow") }
+ ]
+ anchors.verticalCenter: parent.verticalCenter
+
+ // When an item is selected, update the backend.
+ onActivated: modelNodeBackend.changeType(modelData, shadowComboBox.currentValue)
+ // Set the initial currentIndex to the value stored in the backend.
+ Component.onCompleted: {
+ shadowComboBox.currentIndex = shadowComboBox.indexOfValue(modelNodeBackend.simplifiedTypeName(modelData))
+ }
+ }
+
+ onCloseButtonClicked: {
+ delegate.wrapper.deleteModelNode()
+ Qt.callLater(root.invalidate)
+ }
+
+ SectionLayout {
+
+ PropertyLabel { text: qsTr("Visibility") }
+
+ SecondColumnLayout {
+ CheckBox {
+ text: qsTr("Visible")
+ implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ + StudioTheme.Values.actionIndicatorWidth
+ backendValue: delegate.wrapper.properties.visible
+ }
+
+ ExpandingSpacer {}
+ }
+
+ PropertyLabel { text: qsTr("Blur") }
+
+ SecondColumnLayout {
+ SpinBox {
+ implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ + StudioTheme.Values.actionIndicatorWidth
+ backendValue: delegate.wrapper.properties.blur
+ minimumValue: 0
+ maximumValue: 250
+ }
+
+ ExpandingSpacer {}
+ }
+
+ PropertyLabel {
+ text: qsTr("Spread")
+ enabled: modelNodeBackend.isInstanceOf("Rectangle")
+ }
+
+ SecondColumnLayout {
+ SpinBox {
+ implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ + StudioTheme.Values.actionIndicatorWidth
+ backendValue: delegate.wrapper.properties.spread
+ enabled: modelNodeBackend.isInstanceOf("Rectangle")
+ minimumValue: -2048
+ maximumValue: 2048
+ }
+
+ ExpandingSpacer {}
+ }
+
+ PropertyLabel {
+ text: qsTr("Color")
+ tooltip: qsTr("Sets the color.")
+ }
+
+ ColorEditor {
+ backendValue: delegate.wrapper.properties.color
+ supportGradient: false
+ }
+
+ PropertyLabel { text: qsTr("Offset") }
+
+ SecondColumnLayout {
+ SpinBox {
+ implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ + StudioTheme.Values.actionIndicatorWidth
+ backendValue: delegate.wrapper.properties.offsetX
+ minimumValue: -0xffff
+ maximumValue: 0xffff
+ }
+
+ Spacer { implicitWidth: StudioTheme.Values.controlLabelGap }
+
+ ControlLabel {
+ text: "X"
+ tooltip: qsTr("X-coordinate")
+ }
+
+ Spacer { implicitWidth: StudioTheme.Values.controlGap }
+
+ SpinBox {
+ implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ + StudioTheme.Values.actionIndicatorWidth
+ backendValue: delegate.wrapper.properties.offsetY
+ minimumValue: -0xffff
+ maximumValue: 0xffff
+ }
+
+ Spacer { implicitWidth: StudioTheme.Values.controlLabelGap }
+
+ ControlLabel {
+ text: "Y"
+ tooltip: qsTr("Y-coordinate")
+ }
+
+ ExpandingSpacer {}
+ }
+ }
+ }
+ }
+ }
+
+ Item {
+ visible: root.hasDesignerEffect
+ width: 1
+ height: StudioTheme.Values.sectionHeadSpacerHeight
+ }
+
+ SectionLayout {
+ visible: root.hasDesignerEffect
+
+ PropertyLabel {}
+
+ SecondColumnLayout {
+ Spacer { implicitWidth: StudioTheme.Values.actionIndicatorWidth }
+
+ AbstractButton {
+ id: addShadowEffectButton
+ implicitWidth: StudioTheme.Values.singleControlColumnWidth
+ width: StudioTheme.Values.singleControlColumnWidth
+ buttonIcon: qsTr("Add Shadow Effect")
+ iconFont: StudioTheme.Constants.font
+ tooltip: qsTr("Adds a Design Drop Shadow.")
+ onClicked: {
+ modelNodeBackend.createModelNode(root.effectNode,
+ "effects",
+ "DesignDropShadow")
+ root.invalidate()
+ }
+ }
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ItemPane.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ItemPane.qml
index 60bd415a6a..aeef8a9598 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ItemPane.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ItemPane.qml
@@ -133,6 +133,10 @@ PropertyEditorPane {
visible: specificsOne.source.toString() !== ""
}
+ EffectsSection {
+ expanded: false
+ }
+
AdvancedSection {
expanded: false
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/ColumnLayoutSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/ColumnLayoutSpecifics.qml
index 2072f13a8e..aeaeacbd4e 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/ColumnLayoutSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/ColumnLayoutSpecifics.qml
@@ -12,7 +12,10 @@ Section {
caption: qsTr("Column Layout")
SectionLayout {
- PropertyLabel { text: qsTr("Column spacing") }
+ PropertyLabel {
+ text: qsTr("Column spacing")
+ tooltip: qsTr("Sets the space between the items in pixels in the <b>Column Layout</b>.")
+ }
SecondColumnLayout {
SpinBox {
@@ -30,6 +33,7 @@ Section {
PropertyLabel {
text: qsTr("Layout direction")
blockedByTemplate: !backendValues.layoutDirection.isAvailable
+ tooltip: qsTr("Sets the direction of the item flow in the <b>Column Layout</b>.")
}
SecondColumnLayout {
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/GridLayoutSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/GridLayoutSpecifics.qml
index 8eea143542..e6606ffe00 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/GridLayoutSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/GridLayoutSpecifics.qml
@@ -12,7 +12,10 @@ Section {
caption: qsTr("Grid Layout")
SectionLayout {
- PropertyLabel { text: qsTr("Columns & Rows") }
+ PropertyLabel {
+ text: qsTr("Columns & Rows")
+ tooltip: qsTr("Sets the number of columns and rows in the <b>Grid Layout</b>.")
+ }
SecondColumnLayout {
SpinBox {
@@ -49,7 +52,10 @@ Section {
ExpandingSpacer {}
}
- PropertyLabel { text: qsTr("Spacing") }
+ PropertyLabel {
+ text: qsTr("Spacing")
+ tooltip: qsTr("Sets the space between the items in pixels in the rows and columns in the <b>Grid Layout</b>.")
+ }
SecondColumnLayout {
SpinBox {
@@ -86,7 +92,10 @@ Section {
ExpandingSpacer {}
}
- PropertyLabel { text: qsTr("Flow") }
+ PropertyLabel {
+ text: qsTr("Flow")
+ tooltip: qsTr("Set the direction of dynamic items to flow in rows or columns in the <b>Grid Layout</b>.")
+ }
SecondColumnLayout {
ComboBox {
@@ -100,7 +109,11 @@ Section {
ExpandingSpacer {}
}
- PropertyLabel { text: qsTr("Layout direction") }
+ PropertyLabel {
+ text: qsTr("Layout direction")
+ tooltip: qsTr("Sets the direction of the dynamic items left to right or right to left in the <b>Grid Layout</b>.")
+
+ }
SecondColumnLayout {
ComboBox {
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/RowLayoutSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/RowLayoutSpecifics.qml
index b4a2ced1cd..726b3783fb 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/RowLayoutSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/RowLayoutSpecifics.qml
@@ -12,7 +12,10 @@ Section {
caption: qsTr("Row Layout")
SectionLayout {
- PropertyLabel { text: qsTr("Row spacing") }
+ PropertyLabel {
+ text: qsTr("Row spacing")
+ tooltip: qsTr("Sets the space between the items in pixels in the <b>Row Layout</b>.")
+ }
SecondColumnLayout {
SpinBox {
@@ -30,6 +33,7 @@ Section {
PropertyLabel {
text: qsTr("Layout direction")
blockedByTemplate: !backendValues.layoutDirection.isAvailable
+ tooltip: qsTr("Sets the direction of the item flow in the <b>Row Layout</b>.")
}
SecondColumnLayout {
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/StackLayoutSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/StackLayoutSpecifics.qml
index 110a8cbf1a..dc865bf128 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/StackLayoutSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/StackLayoutSpecifics.qml
@@ -12,7 +12,10 @@ Section {
caption: qsTr("Stack Layout")
SectionLayout {
- PropertyLabel { text: qsTr("Current index") }
+ PropertyLabel {
+ text: qsTr("Current index")
+ tooltip: qsTr("Sets the index of the child item currently visible in the <b>Stack Layout</b>.")
+ }
SecondColumnLayout {
SpinBox {
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/CheckBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/CheckBox.qml
index 95788a9ec6..7f1e6f5d46 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/CheckBox.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/CheckBox.qml
@@ -22,17 +22,25 @@ StudioControls.CheckBox {
labelColor: colorLogic.textColor
+ property bool __block: false
+
ColorLogic {
id: colorLogic
backendValue: checkBox.backendValue
onValueFromBackendChanged: {
+ checkBox.__block = true
if (colorLogic.valueFromBackend !== undefined
&& checkBox.checked !== colorLogic.valueFromBackend)
checkBox.checked = colorLogic.valueFromBackend
+ checkBox.__block = false
}
+
}
onCheckedChanged: {
+ if (checkBox.__block)
+ return
+
if (backendValue.value !== checkBox.checked)
backendValue.value = checkBox.checked
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/DoubleSpinBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/DoubleSpinBox.qml
index a44e8c690b..11ce0e1e75 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/DoubleSpinBox.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/DoubleSpinBox.qml
@@ -53,5 +53,6 @@ Item {
decimals: 2
onRealValueModified: wrapper.valueModified()
+ onCompressedRealValueModified: wrapper.valueModified()
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/DynamicPropertiesSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/DynamicPropertiesSection.qml
index 39176ca82a..88a0debae8 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/DynamicPropertiesSection.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/DynamicPropertiesSection.qml
@@ -291,53 +291,64 @@ Section {
property int vecSize: 0
property var proxyValues: []
property var spinBoxes: [boxX, boxY, boxZ, boxW]
+ property bool block: false
signal remove
- onVecSizeChanged: updateProxyValues()
+ onVecSizeChanged: layoutVector.updateProxyValues()
- spacing: StudioTheme.Values.sectionRowSpacing / 2
+ spacing: StudioTheme.Values.sectionRowSpacing
function isValidValue(v) {
return !(v === undefined || isNaN(v))
}
- function updateExpression() {
+ function updateExpressionFromExpression() {
+ if (layoutVector.block)
+ return
+
+ layoutVector.backendValue.expression = layoutVector.proxyValues[0].expression
+ // Only the first proxy value has an expression editor enabled
+ }
+
+ function updateExpressionFromValue() {
+ if (layoutVector.block)
+ return
+
for (let i = 0; i < vecSize; ++i) {
- if (!isValidValue(proxyValues[i].value))
+ if (!layoutVector.isValidValue(layoutVector.proxyValues[i].value))
return
}
- let expStr = "Qt.vector" + vecSize + "d("+proxyValues[0].value
- for (let j=1; j < vecSize; ++j)
- expStr += ", " + proxyValues[j].value
+ let expStr = "Qt.vector" + layoutVector.vecSize + "d(" + layoutVector.proxyValues[0].value
+ for (let j=1; j < layoutVector.vecSize; ++j)
+ expStr += ", " + layoutVector.proxyValues[j].value
expStr += ")"
layoutVector.backendValue.expression = expStr
}
function updateProxyValues() {
- if (!backendValue)
+ if (!layoutVector.backendValue)
return;
- const startIndex = backendValue.expression.indexOf('(')
- const endIndex = backendValue.expression.indexOf(')')
- if (startIndex === -1 || endIndex === -1 || endIndex < startIndex)
- return
- const numberStr = backendValue.expression.slice(startIndex + 1, endIndex)
- const numbers = numberStr.split(",")
- if (!Array.isArray(numbers) || numbers.length !== vecSize)
- return
+ let vals = layoutVector.backendValue.getExpressionAsVector()
- let vals = []
- for (let i = 0; i < vecSize; ++i) {
- vals[i] = parseFloat(numbers[i])
- if (!isValidValue(vals[i]))
- return
+ layoutVector.block = true
+
+ if (layoutVector.vecSize === vals.length) {
+ for (let j = 0; j < layoutVector.vecSize; ++j) {
+ layoutVector.proxyValues[j].setForceBound(false)
+ layoutVector.proxyValues[j].value = vals[j]
+ }
+ } else {
+ for (let j = 0; j < layoutVector.vecSize; ++j) {
+ layoutVector.proxyValues[j].setForceBound(true) // Required since the backendValue is just proxied
+ layoutVector.proxyValues[j].expression = layoutVector.backendValue.expression
+ }
}
- for (let j = 0; j < vecSize; ++j)
- proxyValues[j].value = vals[j]
+ layoutVector.block = false
}
SecondColumnLayout {
@@ -357,15 +368,18 @@ Section {
tooltip: "X"
}
- Spacer { implicitWidth: StudioTheme.Values.controlGap }
+ Spacer {
+ implicitWidth: StudioTheme.Values.controlGap
+ + StudioTheme.Values.actionIndicatorWidth
+ }
SpinBox {
id: boxY
+ actionIndicatorVisible: false
minimumValue: -9999999
maximumValue: 9999999
decimals: 2
implicitWidth: StudioTheme.Values.twoControlColumnWidth
- + StudioTheme.Values.actionIndicatorWidth
}
Spacer { implicitWidth: StudioTheme.Values.controlLabelGap }
@@ -386,14 +400,16 @@ Section {
}
SecondColumnLayout {
- visible: vecSize > 2
+ visible: layoutVector.vecSize > 2
+ Spacer { implicitWidth: StudioTheme.Values.actionIndicatorWidth }
+
SpinBox {
id: boxZ
+ actionIndicatorVisible: false
minimumValue: -9999999
maximumValue: 9999999
decimals: 2
implicitWidth: StudioTheme.Values.twoControlColumnWidth
- + StudioTheme.Values.actionIndicatorWidth
}
Spacer { implicitWidth: StudioTheme.Values.controlLabelGap }
@@ -401,19 +417,22 @@ Section {
ControlLabel {
text: "Z"
tooltip: "Z"
- visible: vecSize > 2
+ visible: layoutVector.vecSize > 2
}
- Spacer { implicitWidth: StudioTheme.Values.controlGap }
+ Spacer {
+ implicitWidth: StudioTheme.Values.controlGap
+ + StudioTheme.Values.actionIndicatorWidth
+ }
SpinBox {
id: boxW
+ actionIndicatorVisible: false
minimumValue: -9999999
maximumValue: 9999999
decimals: 2
implicitWidth: StudioTheme.Values.twoControlColumnWidth
- + StudioTheme.Values.actionIndicatorWidth
- visible: vecSize > 3
+ visible: layoutVector.vecSize > 3
}
Spacer { implicitWidth: StudioTheme.Values.controlLabelGap }
@@ -421,7 +440,7 @@ Section {
ControlLabel {
text: "W"
tooltip: "W"
- visible: vecSize > 3
+ visible: layoutVector.vecSize > 3
}
Spacer { implicitWidth: StudioTheme.Values.controlGap }
@@ -430,7 +449,7 @@ Section {
height: 10
implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ StudioTheme.Values.actionIndicatorWidth
- visible: vecSize === 2 // Placeholder for last spinbox
+ visible: layoutVector.vecSize === 2 // Placeholder for last spinbox
}
Spacer { implicitWidth: StudioTheme.Values.twoControlColumnGap }
@@ -486,9 +505,12 @@ Section {
model: root.propertiesModel
row: index
}
+
PropertyLabel {
text: propertyName
tooltip: propertyType
+ Layout.alignment: Qt.AlignTop
+ Layout.topMargin: 6
}
Loader {
@@ -540,7 +562,8 @@ Section {
for (let i = 0; i < vecSize; ++i) {
var newProxyValue = propertyRow.createProxyBackendValue()
loader.item.proxyValues.push(newProxyValue)
- newProxyValue.valueChangedQml.connect(loader.item.updateExpression)
+ newProxyValue.valueChangedQml.connect(loader.item.updateExpressionFromValue)
+ newProxyValue.expressionChangedQml.connect(loader.item.updateExpressionFromExpression)
loader.item.spinBoxes[i].backendValue = newProxyValue
}
propertyRow.backendValue.expressionChanged.connect(loader.item.updateProxyValues)
@@ -685,7 +708,7 @@ Section {
StudioControls.ComboBox {
id: comboBox
actionIndicator.visible: false
- model: ["int", "real", "color", "string", "bool", "url", "alias",
+ model: ["int", "real", "color", "string", "bool", "url", "alias", "signal",
"TextureInput", "vector2d", "vector3d", "vector4d"]
width: cePopup.itemWidth
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FlagsComboBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FlagsComboBox.qml
index 46c98f25c5..edf17374e2 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FlagsComboBox.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FlagsComboBox.qml
@@ -132,6 +132,8 @@ StudioControls.CustomComboBox {
ExtendedFunctionLogic {
id: extFuncLogic
backendValue: root.backendValue
+
+ onMenuVisibleChanged: root.popup.visible = false
}
actionIndicator.icon.color: extFuncLogic.color
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/IconButton.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/IconButton.qml
index 008320cb92..4534d3fe7d 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/IconButton.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/IconButton.qml
@@ -8,9 +8,9 @@ import StudioTheme as StudioTheme
Rectangle {
id: root
- signal clicked()
- signal pressed()
- signal released()
+ signal clicked(mouse: var)
+ signal pressed(mouse: var)
+ signal released(mouse: var)
property alias icon: icon.text
property alias tooltip: toolTip.text
@@ -30,18 +30,17 @@ Rectangle {
property color hoverColor: root.transparentBg ? "transparent" : StudioTheme.Values.themeControlBackgroundHover
property color pressColor: root.transparentBg ? "transparent" : StudioTheme.Values.themeControlBackgroundInteraction
- width: buttonSize
- height: buttonSize
+ width: root.buttonSize
+ height: root.buttonSize
- color: !enabled ? normalColor
- : mouseArea.pressed ? pressColor
- : mouseArea.containsMouse ? hoverColor
- : normalColor
+ color: !root.enabled ? root.normalColor
+ : mouseArea.pressed ? root.pressColor
+ : mouseArea.containsMouse ? root.hoverColor
+ : root.normalColor
Text {
id: icon
anchors.centerIn: root
-
color: root.enabled ? StudioTheme.Values.themeTextColor : StudioTheme.Values.themeTextColorDisabled
font.family: StudioTheme.Constants.iconFont.family
font.pixelSize: StudioTheme.Values.baseIconFontSize
@@ -49,30 +48,29 @@ Rectangle {
MouseArea {
id: mouseArea
-
anchors.fill: parent
hoverEnabled: root.visible
- onClicked: {
+ onClicked: function(mouse) {
// We need to keep mouse area enabled even when button is disabled to make tooltip work
if (root.enabled)
- root.clicked()
+ root.clicked(mouse)
}
- onPressed: {
+ onPressed: function(mouse) {
if (root.enabled)
- root.pressed()
+ root.pressed(mouse)
}
- onReleased: {
+ onReleased: function(mouse) {
if (root.enabled)
- root.released()
+ root.released(mouse)
}
}
ToolTip {
id: toolTip
- visible: mouseArea.containsMouse && text !== ""
+ visible: mouseArea.containsMouse && toolTip.text !== ""
delay: 1000
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml
index dbbb200f73..245b8506a2 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml
@@ -9,11 +9,13 @@ import StudioTheme as StudioTheme
Item {
id: section
- property alias caption: label.text
- property alias labelColor: label.color
+
+ property string caption: "Title"
+ property color labelColor: StudioTheme.Values.themeTextColor
+ property int labelCapitalization: Font.AllUppercase
property alias sectionHeight: header.height
property alias sectionBackgroundColor: header.color
- property alias sectionFontSize: label.font.pixelSize
+ property int sectionFontSize: StudioTheme.Values.myFontSize
property alias showTopSeparator: topSeparator.visible
property alias showArrow: arrow.visible
property alias showLeftBorder: leftBorder.visible
@@ -26,6 +28,17 @@ Item {
property alias fillBackground: sectionBackground.visible
property alias highlightBorder: sectionBorder.visible
+ property Item content: Controls.Label {
+ id: label
+ text: section.caption
+ color: section.labelColor
+ elide: Text.ElideRight
+ font.pixelSize: section.sectionFontSize
+ font.capitalization: section.labelCapitalization
+ anchors.verticalCenter: parent?.verticalCenter
+ textFormat: Text.RichText
+ }
+
property int leftPadding: StudioTheme.Values.sectionLeftPadding
property int rightPadding: 0
property int topPadding: StudioTheme.Values.sectionHeadSpacerHeight
@@ -59,7 +72,7 @@ Item {
Connections {
target: Controller
function onCollapseAll(cat) {
- if (collapsible && cat === section.category) {
+ if (section.collapsible && cat === section.category) {
if (section.expandOnClick)
section.expanded = false
else
@@ -106,6 +119,22 @@ Item {
onExited: section.dropExit()
}
+ StudioControls.Menu {
+ id: contextMenu
+
+ StudioControls.MenuItem {
+ text: qsTr("Expand All")
+ onTriggered: Controller.expandAll(section.category)
+ }
+
+ StudioControls.MenuItem {
+ text: qsTr("Collapse All")
+ onTriggered: Controller.collapseAll(section.category)
+ }
+
+ onOpenedChanged: Controller.contextMenuOpened = contextMenu.opened
+ }
+
Rectangle {
id: header
height: section.hideHeader ? 0 : StudioTheme.Values.sectionHeadHeight
@@ -116,43 +145,6 @@ Item {
: Qt.lighter(StudioTheme.Values.themeSectionHeadBackground, 1.0
+ (0.2 * section.level))
- Item {
- StudioControls.Menu {
- id: contextMenu
-
- StudioControls.MenuItem {
- text: qsTr("Expand All")
- onTriggered: Controller.expandAll(section.category)
- }
-
- StudioControls.MenuItem {
- text: qsTr("Collapse All")
- onTriggered: Controller.collapseAll(section.category)
- }
-
- onOpenedChanged: Controller.contextMenuOpened = contextMenu.opened
- }
- }
-
- Image {
- id: arrow
- width: 8
- height: 4
- source: "image://icons/down-arrow"
- anchors.left: parent.left
- anchors.leftMargin: 4 + (section.level * section.levelShift) + (section.draggable ? 20 : 0) + (section.showEyeButton ? 25 : 0)
- anchors.verticalCenter: parent.verticalCenter
- }
-
- Controls.Label {
- id: label
- anchors.verticalCenter: parent.verticalCenter
- color: StudioTheme.Values.themeTextColor
- x: arrow.x + 18
- font.pixelSize: StudioTheme.Values.myFontSize
- font.capitalization: Font.AllUppercase
- }
-
MouseArea {
id: mouseArea
anchors.fill: parent
@@ -173,58 +165,102 @@ Item {
}
}
- IconButton {
- id: closeButton
+ RowLayout {
+ spacing: 1
+ anchors.fill: parent
- icon: StudioTheme.Constants.closeCross
- buttonSize: 22
- iconScale: containsMouse ? 1.2 : 1
- transparentBg: true
- anchors.right: parent.right
- anchors.rightMargin: 10
- visible: false
+ IconButton {
+ id: dragButton
+ visible: false
+ icon: StudioTheme.Constants.dragmarks
+ buttonSize: 21
+ iconScale: dragButton.enabled && dragButton.containsMouse ? 1.2 : 1
+ transparentBg: true
- onClicked: root.closeButtonClicked()
- }
+ Layout.alignment: Qt.AlignVCenter
+ Layout.preferredWidth: dragButton.width
+ Layout.maximumWidth: dragButton.width
+
+ drag.target: dragButton.enabled ? section : null
+ drag.axis: Drag.YAxis
+
+ onPressed: {
+ section.startDrag(section)
+ section.z = ++section.parent.z // put the dragged section on top
+ }
- IconButton {
- id: dragButton
+ onReleased: {
+ section.stopDrag()
+ }
+ }
- icon: StudioTheme.Constants.dragmarks
- buttonSize: 22
- iconScale: dragButton.enabled && dragButton.containsMouse ? 1.2 : 1
- transparentBg: true
+ IconButton {
+ id: eyeButton
- visible: false
- drag.target: dragButton.enabled ? section : null
- drag.axis: Drag.YAxis
+ visible: false
+ icon: section.eyeEnabled ? StudioTheme.Constants.visible_small
+ : StudioTheme.Constants.invisible_small
+ buttonSize: 21
+ iconScale: eyeButton.containsMouse ? 1.2 : 1
+ transparentBg: true
- onPressed: {
- section.startDrag(section)
+ Layout.alignment: Qt.AlignVCenter
+ Layout.preferredWidth: eyeButton.width
+ Layout.maximumWidth: eyeButton.width
- section.z = ++section.parent.z // put the dragged section on top
+ onClicked: {
+ section.eyeEnabled = !section.eyeEnabled
+ section.eyeButtonClicked()
+ }
}
- onReleased: {
- section.stopDrag()
+ IconButton {
+ id: arrow
+ icon: StudioTheme.Constants.sectionToggle
+ transparentBg: true
+
+ buttonSize: 21
+ iconSize: StudioTheme.Values.smallIconFontSize
+ iconColor: StudioTheme.Values.themeTextColor
+
+ Layout.alignment: Qt.AlignVCenter
+ Layout.preferredWidth: arrow.width
+ Layout.maximumWidth: arrow.width
+
+ onClicked: function(mouse) {
+ if (!section.collapsible && section.expanded)
+ return
+
+ transition.enabled = true
+ if (section.expandOnClick)
+ section.expanded = !section.expanded
+ else
+ section.toggleExpand()
+ }
}
- }
- IconButton {
- id: eyeButton
+ Item {
+ id: headerContent
+ height: header.height
+ Layout.fillWidth: true
+ children: [ section.content ]
+ }
- anchors.left: dragButton.right
+ IconButton {
+ id: closeButton
- icon: section.eyeEnabled ? StudioTheme.Constants.visible_small : StudioTheme.Constants.invisible_small
- buttonSize: 22
- iconScale: eyeButton.containsMouse ? 1.2 : 1
- transparentBg: true
+ visible: false
+ icon: StudioTheme.Constants.closeCross
+ buttonSize: 21
+ iconScale: closeButton.containsMouse ? 1.2 : 1
+ transparentBg: true
- visible: false
+ Layout.alignment: Qt.AlignVCenter
+ Layout.preferredWidth: closeButton.width
+ Layout.maximumWidth: closeButton.width
+ Layout.rightMargin: 10
- onClicked: {
- section.eyeEnabled = !section.eyeEnabled
- root.eyeButtonClicked()
+ onClicked: section.closeButtonClicked()
}
}
}
@@ -266,6 +302,7 @@ Item {
border.width: 1
visible: false
}
+
Item {
id: topSpacer
height: section.addTopPadding && column.height > 0 ? section.topPadding : 0
@@ -285,7 +322,7 @@ Item {
id: leftBorder
visible: false
width: 1
- height: parent.height - bottomPadding
+ height: parent.height - section.bottomPadding
color: header.color
}
@@ -320,8 +357,8 @@ Item {
}
onRunningChanged: {
- if (!running)
- enabled = false
+ if (!transition.running)
+ transition.enabled = false
}
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SpinBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SpinBox.qml
index f125c459c5..04cbb78f35 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SpinBox.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SpinBox.qml
@@ -22,6 +22,9 @@ Item {
property alias realDragRange: spinBox.realDragRange
property alias pixelsPerUnit: spinBox.pixelsPerUnit
+ property alias actionIndicatorEnabled: spinBox.actionIndicator.enabled
+ property alias actionIndicatorVisible: spinBox.actionIndicatorVisible
+
width: 96
implicitHeight: spinBox.height
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/UrlChooser.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/UrlChooser.qml
index c73e736ef4..0e42515c76 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/UrlChooser.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/UrlChooser.qml
@@ -448,9 +448,10 @@ Row {
for (var j = 0; j < myModel.length; ++j) {
let item = myModel[j]
if (root.hideDuplicates && nameMap.has(item.fileName)) {
- // Prefer hiding imported asset files rather than other project files
+ // Prefer hiding generated component files rather than other project files
let listIndex = nameMap.get(item.fileName)
- if (comboBox.listModel.get(listIndex).absoluteFilePath.includes("/asset_imports/")) {
+ let absPath = comboBox.listModel.get(listIndex).absoluteFilePath
+ if (absPath.includes("/GeneratedComponents/") || absPath.includes("/asset_imports/")) {
comboBox.listModel.set(listIndex, {
absoluteFilePath: item.absoluteFilePath,
relativeFilePath: item.relativeFilePath,
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/InternalConstants.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/InternalConstants.qml
index ee2df02e04..3c74243f68 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/InternalConstants.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/InternalConstants.qml
@@ -75,309 +75,310 @@ QtObject {
readonly property string binding_medium: "\u005C"
readonly property string bounds_small: "\u005D"
readonly property string branch_medium: "\u005E"
- readonly property string camera_medium: "\u005F"
- readonly property string camera_small: "\u0060"
- readonly property string centerHorizontal: "\u0061"
- readonly property string centerVertical: "\u0062"
- readonly property string cleanLogs_medium: "\u0063"
- readonly property string clearList_large: "\u0064"
- readonly property string clearList_medium: "\u0065"
- readonly property string closeCross: "\u0066"
- readonly property string closeFile_large: "\u0067"
- readonly property string closeLink: "\u0068"
- readonly property string close_small: "\u0069"
- readonly property string code: "\u006A"
- readonly property string codeEditor_medium: "\u006B"
- readonly property string codeview_medium: "\u006C"
- readonly property string colorPopupClose: "\u006D"
- readonly property string colorSelection_medium: "\u006E"
- readonly property string columnsAndRows: "\u006F"
- readonly property string comboBox_medium: "\u0070"
- readonly property string cone_medium: "\u0071"
- readonly property string cone_small: "\u0072"
- readonly property string connection_small: "\u0073"
- readonly property string connections_medium: "\u0074"
- readonly property string copyLink: "\u0075"
- readonly property string copyStyle: "\u0076"
- readonly property string copy_small: "\u0077"
- readonly property string cornerA: "\u0078"
- readonly property string cornerB: "\u0079"
- readonly property string cornersAll: "\u007A"
- readonly property string createComponent_large: "\u007B"
- readonly property string createComponent_small: "\u007C"
- readonly property string createObject_medium: "\u007D"
- readonly property string create_medium: "\u007E"
- readonly property string create_small: "\u007F"
- readonly property string cube_medium: "\u0080"
- readonly property string cube_small: "\u0081"
- readonly property string curveDesigner: "\u0082"
- readonly property string curveDesigner_medium: "\u0083"
- readonly property string curveEditor: "\u0084"
- readonly property string customMaterialEditor: "\u0085"
- readonly property string cylinder_medium: "\u0086"
- readonly property string cylinder_small: "\u0087"
- readonly property string decisionNode: "\u0088"
- readonly property string deleteColumn: "\u0089"
- readonly property string deleteMaterial: "\u008A"
- readonly property string deleteRow: "\u008B"
- readonly property string deleteTable: "\u008C"
- readonly property string delete_medium: "\u008D"
- readonly property string delete_small: "\u008E"
- readonly property string deletecolumn_medium: "\u008F"
- readonly property string deletepermanently_medium: "\u0090"
- readonly property string deleterow_medium: "\u0091"
- readonly property string designMode_large: "\u0092"
- readonly property string detach: "\u0093"
- readonly property string directionalLight_small: "\u0094"
- readonly property string distributeBottom: "\u0095"
- readonly property string distributeCenterHorizontal: "\u0096"
- readonly property string distributeCenterVertical: "\u0097"
- readonly property string distributeLeft: "\u0098"
- readonly property string distributeOriginBottomRight: "\u0099"
- readonly property string distributeOriginCenter: "\u009A"
- readonly property string distributeOriginNone: "\u009B"
- readonly property string distributeOriginTopLeft: "\u009D"
- readonly property string distributeRight: "\u009E"
- readonly property string distributeSpacingHorizontal: "\u009F"
- readonly property string distributeSpacingVertical: "\u00A0"
- readonly property string distributeTop: "\u00A1"
- readonly property string download: "\u00A2"
- readonly property string downloadUnavailable: "\u00A3"
- readonly property string downloadUpdate: "\u00A4"
- readonly property string downloaded: "\u00A5"
- readonly property string dragmarks: "\u00A6"
- readonly property string duplicate_small: "\u00A7"
- readonly property string edit: "\u00A8"
- readonly property string editComponent_large: "\u00A9"
- readonly property string editComponent_small: "\u00AA"
- readonly property string editLightOff_medium: "\u00AB"
- readonly property string editLightOn_medium: "\u00AC"
- readonly property string edit_medium: "\u00AE"
- readonly property string edit_small: "\u00AF"
- readonly property string effects: "\u00B0"
- readonly property string events_small: "\u00B1"
- readonly property string export_medium: "\u00B2"
- readonly property string eyeDropper: "\u00B3"
- readonly property string favorite: "\u00B4"
- readonly property string fitAll_medium: "\u00B5"
- readonly property string fitSelected_small: "\u00B6"
- readonly property string fitSelection_medium: "\u00B7"
- readonly property string fitToView_medium: "\u00B8"
- readonly property string flowAction: "\u00B9"
- readonly property string flowTransition: "\u00BA"
- readonly property string fontStyleBold: "\u00BB"
- readonly property string fontStyleItalic: "\u00BC"
- readonly property string fontStyleStrikethrough: "\u00BD"
- readonly property string fontStyleUnderline: "\u00BE"
- readonly property string forward_medium: "\u00BF"
- readonly property string globalOrient_medium: "\u00C0"
- readonly property string gradient: "\u00C1"
- readonly property string gridView: "\u00C2"
- readonly property string grid_medium: "\u00C3"
- readonly property string group_small: "\u00C4"
- readonly property string help: "\u00C5"
- readonly property string home_large: "\u00C6"
- readonly property string idAliasOff: "\u00C7"
- readonly property string idAliasOn: "\u00C8"
- readonly property string import_medium: "\u00C9"
- readonly property string imported: "\u00CA"
- readonly property string importedModels_small: "\u00CB"
- readonly property string infinity: "\u00CC"
- readonly property string invisible_medium: "\u00CD"
- readonly property string invisible_small: "\u00CE"
- readonly property string jumpToCode_medium: "\u00CF"
- readonly property string jumpToCode_small: "\u00D0"
- readonly property string keyframe: "\u00D1"
- readonly property string languageList_medium: "\u00D2"
- readonly property string layouts_small: "\u00D3"
- readonly property string lights_small: "\u00D4"
- readonly property string linear_medium: "\u00D5"
- readonly property string linkTriangle: "\u00D6"
- readonly property string linked: "\u00D7"
- readonly property string listView: "\u00D8"
- readonly property string listView_medium: "\u00D9"
- readonly property string list_medium: "\u00DA"
- readonly property string localOrient_medium: "\u00DB"
- readonly property string lockOff: "\u00DC"
- readonly property string lockOn: "\u00DD"
- readonly property string loopPlayback_medium: "\u00DE"
- readonly property string materialBrowser_medium: "\u00DF"
- readonly property string materialPreviewEnvironment: "\u00E0"
- readonly property string materialPreviewModel: "\u00E1"
- readonly property string material_medium: "\u00E2"
- readonly property string maxBar_small: "\u00E3"
- readonly property string mergeCells: "\u00E4"
- readonly property string merge_small: "\u00E5"
- readonly property string minus: "\u00E6"
- readonly property string mirror: "\u00E7"
- readonly property string more_medium: "\u00E8"
- readonly property string mouseArea_small: "\u00E9"
- readonly property string moveDown_medium: "\u00EA"
- readonly property string moveInwards_medium: "\u00EB"
- readonly property string moveUp_medium: "\u00EC"
- readonly property string moveUpwards_medium: "\u00ED"
- readonly property string move_medium: "\u00EE"
- readonly property string newMaterial: "\u00EF"
- readonly property string nextFile_large: "\u00F0"
- readonly property string normalBar_small: "\u00F1"
- readonly property string openLink: "\u00F2"
- readonly property string openMaterialBrowser: "\u00F3"
- readonly property string orientation: "\u00F4"
- readonly property string orthCam_medium: "\u00F5"
- readonly property string orthCam_small: "\u00F6"
- readonly property string paddingEdge: "\u00F7"
- readonly property string paddingFrame: "\u00F8"
- readonly property string particleAnimation_medium: "\u00F9"
- readonly property string pasteStyle: "\u00FA"
- readonly property string paste_small: "\u00FB"
- readonly property string pause: "\u00FC"
- readonly property string pause_medium: "\u00FD"
- readonly property string perspectiveCam_medium: "\u00FE"
- readonly property string perspectiveCam_small: "\u00FF"
- readonly property string pin: "\u0100"
- readonly property string plane_medium: "\u0101"
- readonly property string plane_small: "\u0102"
- readonly property string play: "\u0103"
- readonly property string playFill_medium: "\u0104"
- readonly property string playOutline_medium: "\u0105"
- readonly property string plus: "\u0106"
- readonly property string pointLight_small: "\u0107"
- readonly property string positioners_small: "\u0108"
- readonly property string previewEnv_medium: "\u0109"
- readonly property string previousFile_large: "\u010A"
- readonly property string promote: "\u010B"
- readonly property string properties_medium: "\u010C"
- readonly property string readOnly: "\u010D"
- readonly property string recent_medium: "\u010E"
- readonly property string recordFill_medium: "\u010F"
- readonly property string recordOutline_medium: "\u0110"
- readonly property string redo: "\u0111"
- readonly property string reload_medium: "\u0112"
- readonly property string remove_medium: "\u0113"
- readonly property string remove_small: "\u0114"
- readonly property string rename_small: "\u0115"
- readonly property string replace_small: "\u0116"
- readonly property string resetView_small: "\u0117"
- readonly property string restartParticles_medium: "\u0118"
- readonly property string reverseOrder_medium: "\u0119"
- readonly property string roatate_medium: "\u011A"
- readonly property string rotationFill: "\u011B"
- readonly property string rotationOutline: "\u011C"
- readonly property string runProjFill_large: "\u011D"
- readonly property string runProjOutline_large: "\u011E"
- readonly property string s_anchors: "\u011F"
- readonly property string s_annotations: "\u0120"
- readonly property string s_arrange: "\u0121"
- readonly property string s_boundingBox: "\u0122"
- readonly property string s_component: "\u0123"
- readonly property string s_connections: "\u0124"
- readonly property string s_edit: "\u0125"
- readonly property string s_enterComponent: "\u0126"
- readonly property string s_eventList: "\u0127"
- readonly property string s_group: "\u0128"
- readonly property string s_layouts: "\u0129"
- readonly property string s_merging: "\u012A"
- readonly property string s_mouseArea: "\u012B"
- readonly property string s_positioners: "\u012C"
- readonly property string s_selection: "\u012D"
- readonly property string s_snapping: "\u012E"
- readonly property string s_timeline: "\u012F"
- readonly property string s_visibility: "\u0130"
- readonly property string saveAs_medium: "\u0131"
- readonly property string saveLogs_medium: "\u0132"
- readonly property string save_medium: "\u0133"
- readonly property string scale_medium: "\u0134"
- readonly property string search: "\u0135"
- readonly property string search_small: "\u0136"
- readonly property string sectionToggle: "\u0137"
- readonly property string selectFill_medium: "\u0138"
- readonly property string selectOutline_medium: "\u0139"
- readonly property string selectParent_small: "\u013A"
- readonly property string selection_small: "\u013B"
- readonly property string settings_medium: "\u013C"
- readonly property string signal_small: "\u013D"
- readonly property string snapping_conf_medium: "\u013E"
- readonly property string snapping_medium: "\u013F"
- readonly property string snapping_small: "\u0140"
- readonly property string sortascending_medium: "\u0141"
- readonly property string sortdescending_medium: "\u0142"
- readonly property string sphere_medium: "\u0143"
- readonly property string sphere_small: "\u0144"
- readonly property string splitColumns: "\u0145"
- readonly property string splitRows: "\u0146"
- readonly property string splitScreen_medium: "\u0147"
- readonly property string spotLight_small: "\u0148"
- readonly property string stackedContainer_small: "\u0149"
- readonly property string startNode: "\u014A"
- readonly property string step_medium: "\u014B"
- readonly property string stop_medium: "\u014C"
- readonly property string tableView_medium: "\u014D"
- readonly property string testIcon: "\u014E"
- readonly property string textAlignBottom: "\u014F"
- readonly property string textAlignCenter: "\u0150"
- readonly property string textAlignJustified: "\u0151"
- readonly property string textAlignLeft: "\u0152"
- readonly property string textAlignMiddle: "\u0153"
- readonly property string textAlignRight: "\u0154"
- readonly property string textAlignTop: "\u0155"
- readonly property string textBulletList: "\u0156"
- readonly property string textFullJustification: "\u0157"
- readonly property string textNumberedList: "\u0158"
- readonly property string textures_medium: "\u0159"
- readonly property string tickIcon: "\u015A"
- readonly property string tickMark_small: "\u015B"
- readonly property string timeline_small: "\u015C"
- readonly property string toEndFrame_medium: "\u015D"
- readonly property string toNextFrame_medium: "\u015E"
- readonly property string toPrevFrame_medium: "\u015F"
- readonly property string toStartFrame_medium: "\u0160"
- readonly property string topToolbar_annotations: "\u0161"
- readonly property string topToolbar_closeFile: "\u0162"
- readonly property string topToolbar_designMode: "\u0163"
- readonly property string topToolbar_enterComponent: "\u0164"
- readonly property string topToolbar_home: "\u0165"
- readonly property string topToolbar_makeComponent: "\u0166"
- readonly property string topToolbar_navFile: "\u0167"
- readonly property string topToolbar_runProject: "\u0168"
- readonly property string translationCreateFiles: "\u0169"
- readonly property string translationCreateReport: "\u016A"
- readonly property string translationExport: "\u016B"
- readonly property string translationImport: "\u016C"
- readonly property string translationSelectLanguages: "\u016D"
- readonly property string translationTest: "\u016E"
- readonly property string transparent: "\u016F"
- readonly property string triState: "\u0170"
- readonly property string triangleArcA: "\u0171"
- readonly property string triangleArcB: "\u0172"
- readonly property string triangleCornerA: "\u0173"
- readonly property string triangleCornerB: "\u0174"
- readonly property string unLinked: "\u0175"
- readonly property string undo: "\u0176"
- readonly property string unify_medium: "\u0177"
- readonly property string unpin: "\u0178"
- readonly property string upDownIcon: "\u0179"
- readonly property string upDownSquare2: "\u017A"
- readonly property string updateAvailable_medium: "\u017B"
- readonly property string updateContent_medium: "\u017C"
- readonly property string visibilityOff: "\u017D"
- readonly property string visibilityOn: "\u017E"
- readonly property string visible_medium: "\u017F"
- readonly property string visible_small: "\u0180"
- readonly property string warning_medium: "\u0181"
- readonly property string wildcard: "\u0182"
- readonly property string wizardsAutomotive: "\u0183"
- readonly property string wizardsDesktop: "\u0184"
- readonly property string wizardsGeneric: "\u0185"
- readonly property string wizardsMcuEmpty: "\u0186"
- readonly property string wizardsMcuGraph: "\u0187"
- readonly property string wizardsMobile: "\u0188"
- readonly property string wizardsUnknown: "\u0189"
- readonly property string zoomAll: "\u018A"
- readonly property string zoomIn: "\u018B"
- readonly property string zoomIn_medium: "\u018C"
- readonly property string zoomOut: "\u018D"
- readonly property string zoomOut_medium: "\u018E"
- readonly property string zoomSelection: "\u018F"
+ readonly property string cameraSpeed_medium: "\u005F"
+ readonly property string camera_medium: "\u0060"
+ readonly property string camera_small: "\u0061"
+ readonly property string centerHorizontal: "\u0062"
+ readonly property string centerVertical: "\u0063"
+ readonly property string cleanLogs_medium: "\u0064"
+ readonly property string clearList_large: "\u0065"
+ readonly property string clearList_medium: "\u0066"
+ readonly property string closeCross: "\u0067"
+ readonly property string closeFile_large: "\u0068"
+ readonly property string closeLink: "\u0069"
+ readonly property string close_small: "\u006A"
+ readonly property string code: "\u006B"
+ readonly property string codeEditor_medium: "\u006C"
+ readonly property string codeview_medium: "\u006D"
+ readonly property string colorPopupClose: "\u006E"
+ readonly property string colorSelection_medium: "\u006F"
+ readonly property string columnsAndRows: "\u0070"
+ readonly property string comboBox_medium: "\u0071"
+ readonly property string cone_medium: "\u0072"
+ readonly property string cone_small: "\u0073"
+ readonly property string connection_small: "\u0074"
+ readonly property string connections_medium: "\u0075"
+ readonly property string copyLink: "\u0076"
+ readonly property string copyStyle: "\u0077"
+ readonly property string copy_small: "\u0078"
+ readonly property string cornerA: "\u0079"
+ readonly property string cornerB: "\u007A"
+ readonly property string cornersAll: "\u007B"
+ readonly property string createComponent_large: "\u007C"
+ readonly property string createComponent_small: "\u007D"
+ readonly property string createObject_medium: "\u007E"
+ readonly property string create_medium: "\u007F"
+ readonly property string create_small: "\u0080"
+ readonly property string cube_medium: "\u0081"
+ readonly property string cube_small: "\u0082"
+ readonly property string curveDesigner: "\u0083"
+ readonly property string curveDesigner_medium: "\u0084"
+ readonly property string curveEditor: "\u0085"
+ readonly property string customMaterialEditor: "\u0086"
+ readonly property string cylinder_medium: "\u0087"
+ readonly property string cylinder_small: "\u0088"
+ readonly property string decisionNode: "\u0089"
+ readonly property string deleteColumn: "\u008A"
+ readonly property string deleteMaterial: "\u008B"
+ readonly property string deleteRow: "\u008C"
+ readonly property string deleteTable: "\u008D"
+ readonly property string delete_medium: "\u008E"
+ readonly property string delete_small: "\u008F"
+ readonly property string deletecolumn_medium: "\u0090"
+ readonly property string deletepermanently_medium: "\u0091"
+ readonly property string deleterow_medium: "\u0092"
+ readonly property string designMode_large: "\u0093"
+ readonly property string detach: "\u0094"
+ readonly property string directionalLight_small: "\u0095"
+ readonly property string distributeBottom: "\u0096"
+ readonly property string distributeCenterHorizontal: "\u0097"
+ readonly property string distributeCenterVertical: "\u0098"
+ readonly property string distributeLeft: "\u0099"
+ readonly property string distributeOriginBottomRight: "\u009A"
+ readonly property string distributeOriginCenter: "\u009B"
+ readonly property string distributeOriginNone: "\u009D"
+ readonly property string distributeOriginTopLeft: "\u009E"
+ readonly property string distributeRight: "\u009F"
+ readonly property string distributeSpacingHorizontal: "\u00A0"
+ readonly property string distributeSpacingVertical: "\u00A1"
+ readonly property string distributeTop: "\u00A2"
+ readonly property string download: "\u00A3"
+ readonly property string downloadUnavailable: "\u00A4"
+ readonly property string downloadUpdate: "\u00A5"
+ readonly property string downloaded: "\u00A6"
+ readonly property string dragmarks: "\u00A7"
+ readonly property string duplicate_small: "\u00A8"
+ readonly property string edit: "\u00A9"
+ readonly property string editComponent_large: "\u00AA"
+ readonly property string editComponent_small: "\u00AB"
+ readonly property string editLightOff_medium: "\u00AC"
+ readonly property string editLightOn_medium: "\u00AE"
+ readonly property string edit_medium: "\u00AF"
+ readonly property string edit_small: "\u00B0"
+ readonly property string effects: "\u00B1"
+ readonly property string events_small: "\u00B2"
+ readonly property string export_medium: "\u00B3"
+ readonly property string eyeDropper: "\u00B4"
+ readonly property string favorite: "\u00B5"
+ readonly property string fitAll_medium: "\u00B6"
+ readonly property string fitSelected_small: "\u00B7"
+ readonly property string fitSelection_medium: "\u00B8"
+ readonly property string fitToView_medium: "\u00B9"
+ readonly property string flowAction: "\u00BA"
+ readonly property string flowTransition: "\u00BB"
+ readonly property string fontStyleBold: "\u00BC"
+ readonly property string fontStyleItalic: "\u00BD"
+ readonly property string fontStyleStrikethrough: "\u00BE"
+ readonly property string fontStyleUnderline: "\u00BF"
+ readonly property string forward_medium: "\u00C0"
+ readonly property string globalOrient_medium: "\u00C1"
+ readonly property string gradient: "\u00C2"
+ readonly property string gridView: "\u00C3"
+ readonly property string grid_medium: "\u00C4"
+ readonly property string group_small: "\u00C5"
+ readonly property string help: "\u00C6"
+ readonly property string home_large: "\u00C7"
+ readonly property string idAliasOff: "\u00C8"
+ readonly property string idAliasOn: "\u00C9"
+ readonly property string import_medium: "\u00CA"
+ readonly property string imported: "\u00CB"
+ readonly property string importedModels_small: "\u00CC"
+ readonly property string infinity: "\u00CD"
+ readonly property string invisible_medium: "\u00CE"
+ readonly property string invisible_small: "\u00CF"
+ readonly property string jumpToCode_medium: "\u00D0"
+ readonly property string jumpToCode_small: "\u00D1"
+ readonly property string keyframe: "\u00D2"
+ readonly property string languageList_medium: "\u00D3"
+ readonly property string layouts_small: "\u00D4"
+ readonly property string lights_small: "\u00D5"
+ readonly property string linear_medium: "\u00D6"
+ readonly property string linkTriangle: "\u00D7"
+ readonly property string linked: "\u00D8"
+ readonly property string listView: "\u00D9"
+ readonly property string listView_medium: "\u00DA"
+ readonly property string list_medium: "\u00DB"
+ readonly property string localOrient_medium: "\u00DC"
+ readonly property string lockOff: "\u00DD"
+ readonly property string lockOn: "\u00DE"
+ readonly property string loopPlayback_medium: "\u00DF"
+ readonly property string materialBrowser_medium: "\u00E0"
+ readonly property string materialPreviewEnvironment: "\u00E1"
+ readonly property string materialPreviewModel: "\u00E2"
+ readonly property string material_medium: "\u00E3"
+ readonly property string maxBar_small: "\u00E4"
+ readonly property string mergeCells: "\u00E5"
+ readonly property string merge_small: "\u00E6"
+ readonly property string minus: "\u00E7"
+ readonly property string mirror: "\u00E8"
+ readonly property string more_medium: "\u00E9"
+ readonly property string mouseArea_small: "\u00EA"
+ readonly property string moveDown_medium: "\u00EB"
+ readonly property string moveInwards_medium: "\u00EC"
+ readonly property string moveUp_medium: "\u00ED"
+ readonly property string moveUpwards_medium: "\u00EE"
+ readonly property string move_medium: "\u00EF"
+ readonly property string newMaterial: "\u00F0"
+ readonly property string nextFile_large: "\u00F1"
+ readonly property string normalBar_small: "\u00F2"
+ readonly property string openLink: "\u00F3"
+ readonly property string openMaterialBrowser: "\u00F4"
+ readonly property string orientation: "\u00F5"
+ readonly property string orthCam_medium: "\u00F6"
+ readonly property string orthCam_small: "\u00F7"
+ readonly property string paddingEdge: "\u00F8"
+ readonly property string paddingFrame: "\u00F9"
+ readonly property string particleAnimation_medium: "\u00FA"
+ readonly property string pasteStyle: "\u00FB"
+ readonly property string paste_small: "\u00FC"
+ readonly property string pause: "\u00FD"
+ readonly property string pause_medium: "\u00FE"
+ readonly property string perspectiveCam_medium: "\u00FF"
+ readonly property string perspectiveCam_small: "\u0100"
+ readonly property string pin: "\u0101"
+ readonly property string plane_medium: "\u0102"
+ readonly property string plane_small: "\u0103"
+ readonly property string play: "\u0104"
+ readonly property string playFill_medium: "\u0105"
+ readonly property string playOutline_medium: "\u0106"
+ readonly property string plus: "\u0107"
+ readonly property string pointLight_small: "\u0108"
+ readonly property string positioners_small: "\u0109"
+ readonly property string previewEnv_medium: "\u010A"
+ readonly property string previousFile_large: "\u010B"
+ readonly property string promote: "\u010C"
+ readonly property string properties_medium: "\u010D"
+ readonly property string readOnly: "\u010E"
+ readonly property string recent_medium: "\u010F"
+ readonly property string recordFill_medium: "\u0110"
+ readonly property string recordOutline_medium: "\u0111"
+ readonly property string redo: "\u0112"
+ readonly property string reload_medium: "\u0113"
+ readonly property string remove_medium: "\u0114"
+ readonly property string remove_small: "\u0115"
+ readonly property string rename_small: "\u0116"
+ readonly property string replace_small: "\u0117"
+ readonly property string resetView_small: "\u0118"
+ readonly property string restartParticles_medium: "\u0119"
+ readonly property string reverseOrder_medium: "\u011A"
+ readonly property string roatate_medium: "\u011B"
+ readonly property string rotationFill: "\u011C"
+ readonly property string rotationOutline: "\u011D"
+ readonly property string runProjFill_large: "\u011E"
+ readonly property string runProjOutline_large: "\u011F"
+ readonly property string s_anchors: "\u0120"
+ readonly property string s_annotations: "\u0121"
+ readonly property string s_arrange: "\u0122"
+ readonly property string s_boundingBox: "\u0123"
+ readonly property string s_component: "\u0124"
+ readonly property string s_connections: "\u0125"
+ readonly property string s_edit: "\u0126"
+ readonly property string s_enterComponent: "\u0127"
+ readonly property string s_eventList: "\u0128"
+ readonly property string s_group: "\u0129"
+ readonly property string s_layouts: "\u012A"
+ readonly property string s_merging: "\u012B"
+ readonly property string s_mouseArea: "\u012C"
+ readonly property string s_positioners: "\u012D"
+ readonly property string s_selection: "\u012E"
+ readonly property string s_snapping: "\u012F"
+ readonly property string s_timeline: "\u0130"
+ readonly property string s_visibility: "\u0131"
+ readonly property string saveAs_medium: "\u0132"
+ readonly property string saveLogs_medium: "\u0133"
+ readonly property string save_medium: "\u0134"
+ readonly property string scale_medium: "\u0135"
+ readonly property string search: "\u0136"
+ readonly property string search_small: "\u0137"
+ readonly property string sectionToggle: "\u0138"
+ readonly property string selectFill_medium: "\u0139"
+ readonly property string selectOutline_medium: "\u013A"
+ readonly property string selectParent_small: "\u013B"
+ readonly property string selection_small: "\u013C"
+ readonly property string settings_medium: "\u013D"
+ readonly property string signal_small: "\u013E"
+ readonly property string snapping_conf_medium: "\u013F"
+ readonly property string snapping_medium: "\u0140"
+ readonly property string snapping_small: "\u0141"
+ readonly property string sortascending_medium: "\u0142"
+ readonly property string sortdescending_medium: "\u0143"
+ readonly property string sphere_medium: "\u0144"
+ readonly property string sphere_small: "\u0145"
+ readonly property string splitColumns: "\u0146"
+ readonly property string splitRows: "\u0147"
+ readonly property string splitScreen_medium: "\u0148"
+ readonly property string spotLight_small: "\u0149"
+ readonly property string stackedContainer_small: "\u014A"
+ readonly property string startNode: "\u014B"
+ readonly property string step_medium: "\u014C"
+ readonly property string stop_medium: "\u014D"
+ readonly property string tableView_medium: "\u014E"
+ readonly property string testIcon: "\u014F"
+ readonly property string textAlignBottom: "\u0150"
+ readonly property string textAlignCenter: "\u0151"
+ readonly property string textAlignJustified: "\u0152"
+ readonly property string textAlignLeft: "\u0153"
+ readonly property string textAlignMiddle: "\u0154"
+ readonly property string textAlignRight: "\u0155"
+ readonly property string textAlignTop: "\u0156"
+ readonly property string textBulletList: "\u0157"
+ readonly property string textFullJustification: "\u0158"
+ readonly property string textNumberedList: "\u0159"
+ readonly property string textures_medium: "\u015A"
+ readonly property string tickIcon: "\u015B"
+ readonly property string tickMark_small: "\u015C"
+ readonly property string timeline_small: "\u015D"
+ readonly property string toEndFrame_medium: "\u015E"
+ readonly property string toNextFrame_medium: "\u015F"
+ readonly property string toPrevFrame_medium: "\u0160"
+ readonly property string toStartFrame_medium: "\u0161"
+ readonly property string topToolbar_annotations: "\u0162"
+ readonly property string topToolbar_closeFile: "\u0163"
+ readonly property string topToolbar_designMode: "\u0164"
+ readonly property string topToolbar_enterComponent: "\u0165"
+ readonly property string topToolbar_home: "\u0166"
+ readonly property string topToolbar_makeComponent: "\u0167"
+ readonly property string topToolbar_navFile: "\u0168"
+ readonly property string topToolbar_runProject: "\u0169"
+ readonly property string translationCreateFiles: "\u016A"
+ readonly property string translationCreateReport: "\u016B"
+ readonly property string translationExport: "\u016C"
+ readonly property string translationImport: "\u016D"
+ readonly property string translationSelectLanguages: "\u016E"
+ readonly property string translationTest: "\u016F"
+ readonly property string transparent: "\u0170"
+ readonly property string triState: "\u0171"
+ readonly property string triangleArcA: "\u0172"
+ readonly property string triangleArcB: "\u0173"
+ readonly property string triangleCornerA: "\u0174"
+ readonly property string triangleCornerB: "\u0175"
+ readonly property string unLinked: "\u0176"
+ readonly property string undo: "\u0177"
+ readonly property string unify_medium: "\u0178"
+ readonly property string unpin: "\u0179"
+ readonly property string upDownIcon: "\u017A"
+ readonly property string upDownSquare2: "\u017B"
+ readonly property string updateAvailable_medium: "\u017C"
+ readonly property string updateContent_medium: "\u017D"
+ readonly property string visibilityOff: "\u017E"
+ readonly property string visibilityOn: "\u017F"
+ readonly property string visible_medium: "\u0180"
+ readonly property string visible_small: "\u0181"
+ readonly property string warning_medium: "\u0182"
+ readonly property string wildcard: "\u0183"
+ readonly property string wizardsAutomotive: "\u0184"
+ readonly property string wizardsDesktop: "\u0185"
+ readonly property string wizardsGeneric: "\u0186"
+ readonly property string wizardsMcuEmpty: "\u0187"
+ readonly property string wizardsMcuGraph: "\u0188"
+ readonly property string wizardsMobile: "\u0189"
+ readonly property string wizardsUnknown: "\u018A"
+ readonly property string zoomAll: "\u018B"
+ readonly property string zoomIn: "\u018C"
+ readonly property string zoomIn_medium: "\u018D"
+ readonly property string zoomOut: "\u018E"
+ readonly property string zoomOut_medium: "\u018F"
+ readonly property string zoomSelection: "\u0190"
readonly property font iconFont: Qt.font({
"family": controlIcons.name,
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml
index 59030cd126..1a04c8ebc3 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml
@@ -251,6 +251,7 @@ QtObject {
property real collectionTableVerticalMargin: 10
property real collectionCellMinimumWidth: 60
property real collectionCellMinimumHeight: 20
+ property real smallStatusIndicatorDiameter: 6
// NEW NEW NEW
readonly property int flowMargin: 7
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/icons.ttf b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/icons.ttf
index 714cd4b753..cdce3eeefd 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/icons.ttf
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/icons.ttf
Binary files differ
diff --git a/share/qtcreator/qmldesigner/studio_templates/files/qtquickfile/file.qml.tpl b/share/qtcreator/qmldesigner/studio_templates/files/qtquickfile/file.qml.tpl
index f77f7d99c9..996d474208 100644
--- a/share/qtcreator/qmldesigner/studio_templates/files/qtquickfile/file.qml.tpl
+++ b/share/qtcreator/qmldesigner/studio_templates/files/qtquickfile/file.qml.tpl
@@ -7,6 +7,7 @@ import %{ApplicationImport}
@endif
%{RootItem} {
+ id: root
@if %{UseImport}
width: Constants.width
height: Constants.height
diff --git a/share/qtcreator/qmldesigner/studio_templates/files/qtuiquickfile/file.qml.tpl b/share/qtcreator/qmldesigner/studio_templates/files/qtuiquickfile/file.qml.tpl
index 47ca3af299..e7e86e9ffa 100644
--- a/share/qtcreator/qmldesigner/studio_templates/files/qtuiquickfile/file.qml.tpl
+++ b/share/qtcreator/qmldesigner/studio_templates/files/qtuiquickfile/file.qml.tpl
@@ -14,6 +14,7 @@ import %{ApplicationImport}
@endif
%{RootItem} {
+ id: root
@if %{UseImport}
width: Constants.width
height: Constants.height
diff --git a/share/qtcreator/qmldesigner/studio_templates/projects/application-3d/wizard.json b/share/qtcreator/qmldesigner/studio_templates/projects/application-3d/wizard.json
index 42d0bf748c..a5d0d7539c 100644
--- a/share/qtcreator/qmldesigner/studio_templates/projects/application-3d/wizard.json
+++ b/share/qtcreator/qmldesigner/studio_templates/projects/application-3d/wizard.json
@@ -18,6 +18,8 @@
{ "key": "ProjectPluginClassName", "value": "%{ProjectName}Plugin" },
{ "key": "QmlProjectFileName", "value": "%{JS: Util.fileName('%{ProjectName}', 'qmlproject')}" },
{ "key": "IsQt6Project", "value": "%{JS: value('QtQuickVersion') !== '2.15' }" },
+ { "key": "AssetDir", "value": "GeneratedComponents" },
+ { "key": "ContentDir", "value": "%{ProjectName}Content" },
{ "key": "ImportModuleName", "value": "%{ProjectName}" },
{ "key": "UIClassName", "value": "Screen01" },
{ "key": "UIClassFileName", "value": "%{JS: Util.fileName('%{UIClassName}', 'ui.qml')}" },
@@ -236,7 +238,7 @@
"type": "ComboBox",
"data":
{
- "index": 3,
+ "index": 5,
"items":
[
{
@@ -278,6 +280,14 @@
'TargetQuickVersion': '6.6',
'TargetQuick3DVersion': '6.6'
})"
+ },
+ {
+ "trKey": "Qt 6.7",
+ "value":
+ "({
+ 'TargetQuickVersion': '6.7',
+ 'TargetQuick3DVersion': '6.7'
+ })"
}
]
}
@@ -298,98 +308,49 @@
"openAsProject": true
},
{
- "source": "../common/CMakeLists.main.txt.tpl",
- "target": "%{ProjectDirectory}/CMakeLists.txt"
- },
- {
- "source": "../common/qmlmodules.tpl",
- "target": "%{ProjectDirectory}/qmlmodules"
- },
- {
- "source": "../common/qmlcomponents.tpl",
- "target": "%{ProjectDirectory}/qmlcomponents"
- },
- {
- "source": "../common/insight.tpl",
- "target": "%{ProjectDirectory}/insight"
- },
- {
- "source": "../common/main.qml",
- "target": "%{ProjectDirectory}/main.qml"
- },
- {
"source": "../common/qtquickcontrols2.conf.tpl",
"target": "%{ProjectDirectory}/qtquickcontrols2.conf"
},
{
- "source": "../common/main.cpp.tpl",
- "target": "%{ProjectDirectory}/src/main.cpp"
- },
- {
- "source": "../common/app_environment.h.tpl",
- "target": "%{ProjectDirectory}/src/app_environment.h"
- },
- {
- "source": "../common/import_qml_plugins.h.tpl",
- "target": "%{ProjectDirectory}/src/import_qml_plugins.h"
- },
- {
- "source": "../common/import_qml_components_plugins.h.tpl",
- "target": "%{ProjectDirectory}/src/import_qml_components_plugins.h"
- },
-
- {
- "source": "../common/CMakeLists.content.txt.tpl",
- "target": "%{ProjectDirectory}/content/CMakeLists.txt"
- },
- {
"source": "../common/App.qml.tpl",
- "target": "%{ProjectDirectory}/content/App.qml"
+ "target": "%{ProjectDirectory}/%{ContentDir}/App.qml"
},
{
"source": "Screen01.ui.qml.tpl",
- "target": "%{ProjectDirectory}/content/Screen01.ui.qml",
+ "target": "%{ProjectDirectory}/%{ContentDir}/Screen01.ui.qml",
"openInEditor": true
},
{
"source": "../common/fonts.txt",
- "target": "%{ProjectDirectory}/content/fonts/fonts.txt"
+ "target": "%{ProjectDirectory}/%{ContentDir}/fonts/fonts.txt"
},
{
"source": "../common/asset_imports.txt",
- "target": "%{ProjectDirectory}/asset_imports/asset_imports.txt"
- },
- {
- "source": "../common/CMakeLists.imports.txt.tpl",
- "target": "%{ProjectDirectory}/imports/CMakeLists.txt"
- },
- {
- "source": "../shared-plugin/name/CMakeLists.importmodule.txt.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/CMakeLists.txt"
+ "target": "%{ProjectDirectory}/%{AssetDir}/%{AssetDir}.txt"
},
{
"source": "../shared-plugin/name/importmodule.qmldir.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/qmldir"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/qmldir"
},
{
"source": "../shared-plugin/name/Constants.qml.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/Constants.qml"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/Constants.qml"
},
{
"source": "../shared-plugin/name/DirectoryFontLoader.qml.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/DirectoryFontLoader.qml"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/DirectoryFontLoader.qml"
},
{
"source": "../shared-plugin/name/EventListModel.qml.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/EventListModel.qml"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/EventListModel.qml"
},
{
"source": "../shared-plugin/name/EventListSimulator.qml.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/EventListSimulator.qml"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/EventListSimulator.qml"
},
{
"source": "../shared-plugin/name/designer/plugin.metainfo",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/designer/plugin.metainfo"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/designer/plugin.metainfo"
}
]
}
diff --git a/share/qtcreator/qmldesigner/studio_templates/projects/application-extended-3d/Screen01.ui.qml.tpl b/share/qtcreator/qmldesigner/studio_templates/projects/application-extended-3d/Screen01.ui.qml.tpl
index 2b26fe3f0c..41d562fb53 100644
--- a/share/qtcreator/qmldesigner/studio_templates/projects/application-extended-3d/Screen01.ui.qml.tpl
+++ b/share/qtcreator/qmldesigner/studio_templates/projects/application-extended-3d/Screen01.ui.qml.tpl
@@ -19,7 +19,7 @@ Rectangle {
color: Constants.backgroundColor
View3D {
- id: view3D
+ id: extendedView3D
anchors.fill: parent
environment: sceneEnvironment
diff --git a/share/qtcreator/qmldesigner/studio_templates/projects/application-extended-3d/wizard.json b/share/qtcreator/qmldesigner/studio_templates/projects/application-extended-3d/wizard.json
index 101d5c6903..5f2e5bfcaf 100644
--- a/share/qtcreator/qmldesigner/studio_templates/projects/application-extended-3d/wizard.json
+++ b/share/qtcreator/qmldesigner/studio_templates/projects/application-extended-3d/wizard.json
@@ -18,6 +18,8 @@
{ "key": "ProjectPluginClassName", "value": "%{ProjectName}Plugin" },
{ "key": "QmlProjectFileName", "value": "%{JS: Util.fileName('%{ProjectName}', 'qmlproject')}" },
{ "key": "IsQt6Project", "value": "%{JS: value('QtQuickVersion') !== '2.15' }" },
+ { "key": "AssetDir", "value": "GeneratedComponents" },
+ { "key": "ContentDir", "value": "%{ProjectName}Content" },
{ "key": "ImportModuleName", "value": "%{ProjectName}" },
{ "key": "UIClassName", "value": "Screen01" },
{ "key": "UIClassFileName", "value": "%{JS: Util.fileName('%{UIClassName}', 'ui.qml')}" },
@@ -236,34 +238,10 @@
"type": "ComboBox",
"data":
{
- "index": 3,
+ "index": 2,
"items":
[
{
- "trKey": "Qt 6.2",
- "value":
- "({
- 'TargetQuickVersion': '6.2',
- 'TargetQuick3DVersion': '6.2'
- })"
- },
- {
- "trKey": "Qt 6.3",
- "value":
- "({
- 'TargetQuickVersion': '6.3',
- 'TargetQuick3DVersion': '6.3'
- })"
- },
- {
- "trKey": "Qt 6.4",
- "value":
- "({
- 'TargetQuickVersion': '6.4',
- 'TargetQuick3DVersion': '6.4'
- })"
- },
- {
"trKey": "Qt 6.5",
"value":
"({
@@ -278,6 +256,14 @@
'TargetQuickVersion': '6.6',
'TargetQuick3DVersion': '6.6'
})"
+ },
+ {
+ "trKey": "Qt 6.7",
+ "value":
+ "({
+ 'TargetQuickVersion': '6.7',
+ 'TargetQuick3DVersion': '6.7'
+ })"
}
]
}
@@ -298,98 +284,49 @@
"openAsProject": true
},
{
- "source": "../common/CMakeLists.main.txt.tpl",
- "target": "%{ProjectDirectory}/CMakeLists.txt"
- },
- {
- "source": "../common/qmlmodules.tpl",
- "target": "%{ProjectDirectory}/qmlmodules"
- },
- {
- "source": "../common/qmlcomponents.tpl",
- "target": "%{ProjectDirectory}/qmlcomponents"
- },
- {
- "source": "../common/insight.tpl",
- "target": "%{ProjectDirectory}/insight"
- },
- {
- "source": "../common/main.qml",
- "target": "%{ProjectDirectory}/main.qml"
- },
- {
"source": "../common/qtquickcontrols2.conf.tpl",
"target": "%{ProjectDirectory}/qtquickcontrols2.conf"
},
{
- "source": "../common/main.cpp.tpl",
- "target": "%{ProjectDirectory}/src/main.cpp"
- },
- {
- "source": "../common/app_environment.h.tpl",
- "target": "%{ProjectDirectory}/src/app_environment.h"
- },
- {
- "source": "../common/import_qml_plugins.h.tpl",
- "target": "%{ProjectDirectory}/src/import_qml_plugins.h"
- },
- {
- "source": "../common/import_qml_components_plugins.h.tpl",
- "target": "%{ProjectDirectory}/src/import_qml_components_plugins.h"
- },
-
- {
- "source": "../common/CMakeLists.content.txt.tpl",
- "target": "%{ProjectDirectory}/content/CMakeLists.txt"
- },
- {
"source": "../common/App.qml.tpl",
- "target": "%{ProjectDirectory}/content/App.qml"
+ "target": "%{ProjectDirectory}/%{ContentDir}/App.qml"
},
{
"source": "Screen01.ui.qml.tpl",
- "target": "%{ProjectDirectory}/content/Screen01.ui.qml",
+ "target": "%{ProjectDirectory}/%{ContentDir}/Screen01.ui.qml",
"openInEditor": true
},
{
"source": "../common/fonts.txt",
- "target": "%{ProjectDirectory}/content/fonts/fonts.txt"
+ "target": "%{ProjectDirectory}/%{ContentDir}/fonts/fonts.txt"
},
{
"source": "../common/asset_imports.txt",
- "target": "%{ProjectDirectory}/asset_imports/asset_imports.txt"
- },
- {
- "source": "../common/CMakeLists.imports.txt.tpl",
- "target": "%{ProjectDirectory}/imports/CMakeLists.txt"
- },
- {
- "source": "../shared-plugin/name/CMakeLists.importmodule.txt.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/CMakeLists.txt"
+ "target": "%{ProjectDirectory}/%{AssetDir}/%{AssetDir}.txt"
},
{
"source": "../shared-plugin/name/importmodule.qmldir.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/qmldir"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/qmldir"
},
{
"source": "../shared-plugin/name/Constants.qml.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/Constants.qml"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/Constants.qml"
},
{
"source": "../shared-plugin/name/DirectoryFontLoader.qml.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/DirectoryFontLoader.qml"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/DirectoryFontLoader.qml"
},
{
"source": "../shared-plugin/name/EventListModel.qml.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/EventListModel.qml"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/EventListModel.qml"
},
{
"source": "../shared-plugin/name/EventListSimulator.qml.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/EventListSimulator.qml"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/EventListSimulator.qml"
},
{
"source": "../shared-plugin/name/designer/plugin.metainfo",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/designer/plugin.metainfo"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/designer/plugin.metainfo"
}
]
}
diff --git a/share/qtcreator/qmldesigner/studio_templates/projects/application/wizard.json b/share/qtcreator/qmldesigner/studio_templates/projects/application/wizard.json
index c8b74dec49..41fe2df289 100644
--- a/share/qtcreator/qmldesigner/studio_templates/projects/application/wizard.json
+++ b/share/qtcreator/qmldesigner/studio_templates/projects/application/wizard.json
@@ -17,6 +17,8 @@
{ "key": "ProjectPluginName", "value": "%{ProjectName}plugin" },
{ "key": "ProjectPluginClassName", "value": "%{ProjectName}Plugin" },
{ "key": "QmlProjectFileName", "value": "%{JS: Util.fileName('%{ProjectName}', 'qmlproject')}" },
+ { "key": "AssetDir", "value": "GeneratedComponents" },
+ { "key": "ContentDir", "value": "%{ProjectName}Content" },
{ "key": "ImportModuleName", "value": "%{ProjectName}" },
{ "key": "UIClassName", "value": "Screen01" },
{ "key": "UIClassFileName", "value": "%{JS: Util.fileName('%{UIClassName}', 'ui.qml')}" },
@@ -236,7 +238,7 @@
"type": "ComboBox",
"data":
{
- "index": 4,
+ "index": 6,
"items":
[
{
@@ -280,6 +282,13 @@
"({
'TargetQuickVersion': '6.6'
})"
+ },
+ {
+ "trKey": "Qt 6.7",
+ "value":
+ "({
+ 'TargetQuickVersion': '6.7'
+ })"
}
]
}
@@ -300,108 +309,48 @@
"openAsProject": true
},
{
- "source": "../common/CMakeLists.main.txt.tpl",
- "target": "%{ProjectDirectory}/CMakeLists.txt",
- "condition": "%{IsQt6Project}"
- },
- {
- "source": "../common/qmlmodules.tpl",
- "target": "%{ProjectDirectory}/qmlmodules",
- "condition": "%{IsQt6Project}"
- },
- {
- "source": "../common/qmlcomponents.tpl",
- "target": "%{ProjectDirectory}/qmlcomponents",
- "condition": "%{IsQt6Project}"
- },
- {
- "source": "../common/insight.tpl",
- "target": "%{ProjectDirectory}/insight",
- "condition": "%{IsQt6Project}"
- },
- {
- "source": "../common/main.qml",
- "target": "%{ProjectDirectory}/main.qml",
- "condition": "%{IsQt6Project}"
- },
- {
"source": "../common/qtquickcontrols2.conf.tpl",
"target": "%{ProjectDirectory}/qtquickcontrols2.conf"
},
{
- "source": "../common/main.cpp.tpl",
- "target": "%{ProjectDirectory}/src/main.cpp",
- "condition": "%{IsQt6Project}"
- },
- {
- "source": "../common/app_environment.h.tpl",
- "target": "%{ProjectDirectory}/src/app_environment.h",
- "condition": "%{IsQt6Project}"
- },
- {
- "source": "../common/import_qml_plugins.h.tpl",
- "target": "%{ProjectDirectory}/src/import_qml_plugins.h",
- "condition": "%{IsQt6Project}"
- },
- {
- "source": "../common/import_qml_components_plugins.h.tpl",
- "target": "%{ProjectDirectory}/src/import_qml_components_plugins.h",
- "condition": "%{IsQt6Project}"
- },
- {
- "source": "../common/CMakeLists.content.txt.tpl",
- "target": "%{ProjectDirectory}/content/CMakeLists.txt",
- "condition": "%{IsQt6Project}"
- },
- {
"source": "../common/App.qml.tpl",
- "target": "%{ProjectDirectory}/content/App.qml"
+ "target": "%{ProjectDirectory}/%{ContentDir}/App.qml"
},
{
"source": "Screen01.ui.qml.tpl",
- "target": "%{ProjectDirectory}/content/Screen01.ui.qml"
+ "target": "%{ProjectDirectory}/%{ContentDir}/Screen01.ui.qml"
},
{
"source": "../common/fonts.txt",
- "target": "%{ProjectDirectory}/content/fonts/fonts.txt"
+ "target": "%{ProjectDirectory}/%{ContentDir}/fonts/fonts.txt"
},
{
"source": "../common/asset_imports.txt",
- "target": "%{ProjectDirectory}/asset_imports/asset_imports.txt"
- },
- {
- "source": "../common/CMakeLists.imports.txt.tpl",
- "target": "%{ProjectDirectory}/imports/CMakeLists.txt",
- "condition": "%{IsQt6Project}"
- },
- {
- "source": "../shared-plugin/name/CMakeLists.importmodule.txt.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/CMakeLists.txt",
- "condition": "%{IsQt6Project}"
+ "target": "%{ProjectDirectory}/%{AssetDir}/Quick3DAssets.txt"
},
{
"source": "../shared-plugin/name/importmodule.qmldir.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/qmldir"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/qmldir"
},
{
"source": "../shared-plugin/name/Constants.qml.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/Constants.qml"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/Constants.qml"
},
{
"source": "../shared-plugin/name/DirectoryFontLoader.qml.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/DirectoryFontLoader.qml"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/DirectoryFontLoader.qml"
},
{
"source": "../shared-plugin/name/EventListModel.qml.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/EventListModel.qml"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/EventListModel.qml"
},
{
"source": "../shared-plugin/name/EventListSimulator.qml.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/EventListSimulator.qml"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/EventListSimulator.qml"
},
{
"source": "../shared-plugin/name/designer/plugin.metainfo",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/designer/plugin.metainfo"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/designer/plugin.metainfo"
}
]
}
diff --git a/share/qtcreator/qmldesigner/studio_templates/projects/common/CMakeLists.content.txt.tpl b/share/qtcreator/qmldesigner/studio_templates/projects/common/CMakeLists.content.txt.tpl
deleted file mode 100644
index a5a4360e3f..0000000000
--- a/share/qtcreator/qmldesigner/studio_templates/projects/common/CMakeLists.content.txt.tpl
+++ /dev/null
@@ -1,14 +0,0 @@
-### This file is automatically generated by Qt Design Studio.
-### Do not change
-
-qt_add_library(content STATIC)
-qt6_add_qml_module(content
- URI "content"
- VERSION 1.0
- RESOURCE_PREFIX "/qt/qml"
- QML_FILES
- App.qml
- %{UIClassFileName}
- RESOURCES
- fonts/fonts.txt
-)
diff --git a/share/qtcreator/qmldesigner/studio_templates/projects/common/CMakeLists.imports.txt.tpl b/share/qtcreator/qmldesigner/studio_templates/projects/common/CMakeLists.imports.txt.tpl
deleted file mode 100644
index 418f6d7719..0000000000
--- a/share/qtcreator/qmldesigner/studio_templates/projects/common/CMakeLists.imports.txt.tpl
+++ /dev/null
@@ -1,4 +0,0 @@
-### This file is automatically generated by Qt Design Studio.
-### Do not change
-
-add_subdirectory(%{ImportModuleName})
diff --git a/share/qtcreator/qmldesigner/studio_templates/projects/common/CMakeLists.main.txt.tpl b/share/qtcreator/qmldesigner/studio_templates/projects/common/CMakeLists.main.txt.tpl
deleted file mode 100644
index eb621ef219..0000000000
--- a/share/qtcreator/qmldesigner/studio_templates/projects/common/CMakeLists.main.txt.tpl
+++ /dev/null
@@ -1,56 +0,0 @@
-cmake_minimum_required(VERSION 3.21.1)
-
-option(LINK_INSIGHT "Link Qt Insight Tracker library" ON)
-option(BUILD_QDS_COMPONENTS "Build design studio components" ON)
-
-project(%{ProjectName}App LANGUAGES CXX)
-
-set(CMAKE_AUTOMOC ON)
-
-find_package(Qt6 6.2 REQUIRED COMPONENTS Core Gui Qml Quick)
-
-if (Qt6_VERSION VERSION_GREATER_EQUAL 6.3)
- qt_standard_project_setup()
-endif()
-
-qt_add_executable(%{ProjectName}App src/main.cpp)
-
-qt_add_resources(%{ProjectName}App "configuration"
- PREFIX "/"
- FILES
- qtquickcontrols2.conf
-)
-
-target_link_libraries(%{ProjectName}App PRIVATE
- Qt6::Core
- Qt6::Gui
- Qt6::Qml
- Qt6::Quick
-)
-
-set(QT_QML_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/qml)
-set(QML_IMPORT_PATH ${QT_QML_OUTPUT_DIRECTORY}
- CACHE STRING "Import paths for Qt Creator's code model"
- FORCE
-)
-
-if (BUILD_QDS_COMPONENTS)
- include(${CMAKE_CURRENT_SOURCE_DIR}/qmlcomponents)
-endif()
-
-include(${CMAKE_CURRENT_SOURCE_DIR}/qmlmodules)
-
-if (LINK_INSIGHT)
- include(${CMAKE_CURRENT_SOURCE_DIR}/insight)
-endif ()
-
-include(GNUInstallDirs)
-install(TARGETS %{ProjectName}App
- BUNDLE DESTINATION .
- LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
-)
-
-# make IDEs aware of the QML import path
-set(QML_IMPORT_PATH ${PROJECT_BINARY_DIR}/qml CACHE PATH
- "Path to the custom QML components defined by the project")
diff --git a/share/qtcreator/qmldesigner/studio_templates/projects/common/app.qmlproject.tpl b/share/qtcreator/qmldesigner/studio_templates/projects/common/app.qmlproject.tpl
index 75aeae6714..6d346818e4 100644
--- a/share/qtcreator/qmldesigner/studio_templates/projects/common/app.qmlproject.tpl
+++ b/share/qtcreator/qmldesigner/studio_templates/projects/common/app.qmlproject.tpl
@@ -5,32 +5,36 @@ import QmlProject 1.1
@endif
Project {
- mainFile: "content/App.qml"
- mainUiFile: "content/Screen01.ui.qml"
+ mainFile: "%{ContentDir}/App.qml"
+ mainUiFile: "%{ContentDir}/Screen01.ui.qml"
/* Include .qml, .js, and image files from current directory and subdirectories */
QmlFiles {
- directory: "content"
+ directory: "%{ProjectName}"
}
QmlFiles {
- directory: "imports"
+ directory: "%{ContentDir}"
+ }
+
+ QmlFiles {
+ directory: "%{AssetDir}"
}
JavaScriptFiles {
- directory: "content"
+ directory: "%{ProjectName}"
}
JavaScriptFiles {
- directory: "imports"
+ directory: "%{ProjectName}"
}
ImageFiles {
- directory: "content"
+ directory: "%{ContentDir}"
}
ImageFiles {
- directory: "asset_imports"
+ directory: "%{AssetDir}"
}
Files {
@@ -69,17 +73,12 @@ Project {
Files {
filter: "*.mesh"
- directory: "asset_imports"
+ directory: "%{AssetDir}"
}
Files {
filter: "*.qad"
- directory: "asset_imports"
- }
-
- Files {
- filter: "*.qml"
- directory: "asset_imports"
+ directory: "%{AssetDir}"
}
Environment {
@@ -109,7 +108,7 @@ Project {
@endif
/* List of plugin directories passed to QML runtime */
- importPaths: [ "imports", "asset_imports" ]
+ importPaths: [ "." ]
/* Required for deployment */
targetDirectory: "/opt/%{ProjectName}"
@@ -125,10 +124,10 @@ Project {
/* args: Specifies command line arguments for qsb tool to generate shaders.
files: Specifies target files for qsb tool. If path is included, it must be relative to this file.
Wildcard '*' can be used in the file name part of the path.
- e.g. files: [ "content/shaders/*.vert", "*.frag" ] */
+ e.g. files: [ "%{ContentDir}/shaders/*.vert", "*.frag" ] */
ShaderTool {
args: "-s --glsl \\\"100 es,120,150\\\" --hlsl 50 --msl 12"
- files: [ "content/shaders/*" ]
+ files: [ "%{ContentDir}/shaders/*" ]
}
@endif
diff --git a/share/qtcreator/qmldesigner/studio_templates/projects/common/app_environment.h.tpl b/share/qtcreator/qmldesigner/studio_templates/projects/common/app_environment.h.tpl
deleted file mode 100644
index e1f7ec2e23..0000000000
--- a/share/qtcreator/qmldesigner/studio_templates/projects/common/app_environment.h.tpl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * This file is automatically generated by Qt Design Studio.
- * Do not change.
-*/
-
-#include <QGuiApplication>
-
-void set_qt_environment()
-{
-@if %{UseVirtualKeyboard}
- qputenv("QT_IM_MODULE", "qtvirtualkeyboard");
- qputenv("QT_VIRTUALKEYBOARD_DESKTOP_DISABLE", "1");
-@endif
- qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", "1");
- qputenv("QT_ENABLE_HIGHDPI_SCALING", "0");
- qputenv("QT_LOGGING_RULES", "qt.qml.connections=false");
- qputenv("QT_QUICK_CONTROLS_CONF", ":/qtquickcontrols2.conf");
- qputenv("QML_COMPAT_RESOLVE_URLS_ON_ASSIGNMENT", "1");
-}
diff --git a/share/qtcreator/qmldesigner/studio_templates/projects/common/contentmodule.main.qml.tpl b/share/qtcreator/qmldesigner/studio_templates/projects/common/contentmodule.main.qml.tpl
deleted file mode 100644
index ac0b0b28c0..0000000000
--- a/share/qtcreator/qmldesigner/studio_templates/projects/common/contentmodule.main.qml.tpl
+++ /dev/null
@@ -1,17 +0,0 @@
-import QtQuick %{QtQuickVersion}
-@if !%{IsQt6Project}
-import QtQuick.Window %{QtQuickVersion}
-@endif
-import %{ApplicationImport}
-
-Window {
- width: Constants.width
- height: Constants.height
-
- visible: true
-
- Screen01 {
- width: parent.width
- height: parent.height
- }
-}
diff --git a/share/qtcreator/qmldesigner/studio_templates/projects/common/import_qml_plugins.h.tpl b/share/qtcreator/qmldesigner/studio_templates/projects/common/import_qml_plugins.h.tpl
deleted file mode 100644
index f9700ff452..0000000000
--- a/share/qtcreator/qmldesigner/studio_templates/projects/common/import_qml_plugins.h.tpl
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * This file is automatically generated by Qt Design Studio.
- * Do not change.
-*/
-
-#include <QtQml/qqmlextensionplugin.h>
-
-Q_IMPORT_QML_PLUGIN(contentPlugin)
-Q_IMPORT_QML_PLUGIN(%{ProjectPluginClassName})
diff --git a/share/qtcreator/qmldesigner/studio_templates/projects/common/main.cpp.tpl b/share/qtcreator/qmldesigner/studio_templates/projects/common/main.cpp.tpl
deleted file mode 100644
index 915d08462e..0000000000
--- a/share/qtcreator/qmldesigner/studio_templates/projects/common/main.cpp.tpl
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
-
-#include <QGuiApplication>
-#include <QQmlApplicationEngine>
-
-#include "app_environment.h"
-#include "import_qml_components_plugins.h"
-#include "import_qml_plugins.h"
-
-int main(int argc, char *argv[])
-{
- set_qt_environment();
-
- QGuiApplication app(argc, argv);
-
- QQmlApplicationEngine engine;
- const QUrl url(u"qrc:/qt/qml/Main/main.qml"_qs);
- QObject::connect(
- &engine, &QQmlApplicationEngine::objectCreated, &app,
- [url](QObject *obj, const QUrl &objUrl) {
- if (!obj && url == objUrl)
- QCoreApplication::exit(-1);
- },
- Qt::QueuedConnection);
-
- engine.addImportPath(QCoreApplication::applicationDirPath() + "/qml");
- engine.addImportPath(":/");
-
- engine.load(url);
-
- if (engine.rootObjects().isEmpty()) {
- return -1;
- }
-
- return app.exec();
-}
diff --git a/share/qtcreator/qmldesigner/studio_templates/projects/common/main.qml b/share/qtcreator/qmldesigner/studio_templates/projects/common/main.qml
deleted file mode 100644
index 2c4f857df3..0000000000
--- a/share/qtcreator/qmldesigner/studio_templates/projects/common/main.qml
+++ /dev/null
@@ -1,8 +0,0 @@
-/* This file is generated and only relevant for integrating the project into a Qt 6 and cmake based
-C++ project. */
-
-import QtQuick
-import content
-
-App {
-}
diff --git a/share/qtcreator/qmldesigner/studio_templates/projects/common/qmlmodules.tpl b/share/qtcreator/qmldesigner/studio_templates/projects/common/qmlmodules.tpl
deleted file mode 100644
index 5a22661b5a..0000000000
--- a/share/qtcreator/qmldesigner/studio_templates/projects/common/qmlmodules.tpl
+++ /dev/null
@@ -1,18 +0,0 @@
-### This file is automatically generated by Qt Design Studio.
-### Do not change
-
-qt6_add_qml_module(${CMAKE_PROJECT_NAME}
- URI "Main"
- VERSION 1.0
- RESOURCE_PREFIX "/qt/qml"
- NO_PLUGIN
- QML_FILES main.qml
-)
-
-add_subdirectory(content)
-add_subdirectory(imports)
-
-target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE
- contentplugin
- %{ProjectPluginName}
-)
diff --git a/share/qtcreator/qmldesigner/studio_templates/projects/common/qtquickcontrols2.conf b/share/qtcreator/qmldesigner/studio_templates/projects/common/qtquickcontrols2.conf
deleted file mode 100644
index 9c7633fb0a..0000000000
--- a/share/qtcreator/qmldesigner/studio_templates/projects/common/qtquickcontrols2.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-; This file can be edited to change the style of the application
-; Read "Qt Quick Controls 2 Configuration File" for details:
-; http://doc.qt.io/qt-5/qtquickcontrols2-configuration.html
-
-[Controls]
-Style=%{QtQuickControlsStyle}
-@if '%{QtQuickControlsStyle}' == 'Universal'
-
-[Universal]
-Theme=%{QtQuickControlsStyleTheme}
-;Accent=Steel
-;Foreground=Brown
-;Background=Steel
-@endif
-@if '%{QtQuickControlsStyle}' == 'Material'
-
-[Material]
-Theme=%{QtQuickControlsStyleTheme}
-;Accent=BlueGrey
-;Primary=BlueGray
-;Foreground=Brown
-;Background=Grey
-@endif
diff --git a/share/qtcreator/qmldesigner/studio_templates/projects/desktop-launcher/wizard.json b/share/qtcreator/qmldesigner/studio_templates/projects/desktop-launcher/wizard.json
index 01a603eb9d..ddaf502154 100644
--- a/share/qtcreator/qmldesigner/studio_templates/projects/desktop-launcher/wizard.json
+++ b/share/qtcreator/qmldesigner/studio_templates/projects/desktop-launcher/wizard.json
@@ -17,6 +17,8 @@
{ "key": "ProjectPluginName", "value": "%{ProjectName}plugin" },
{ "key": "ProjectPluginClassName", "value": "%{ProjectName}Plugin" },
{ "key": "QmlProjectFileName", "value": "%{JS: Util.fileName('%{ProjectName}', 'qmlproject')}" },
+ { "key": "AssetDir", "value": "GeneratedComponents" },
+ { "key": "ContentDir", "value": "%{ProjectName}Content" },
{ "key": "ImportModuleName", "value": "%{ProjectName}" },
{ "key": "UIClassName", "value": "Screen01" },
{ "key": "UIClassFileName", "value": "%{JS: Util.fileName('%{UIClassName}', 'ui.qml')}" },
@@ -298,97 +300,49 @@
"openAsProject": true
},
{
- "source": "../common/CMakeLists.main.txt.tpl",
- "target": "%{ProjectDirectory}/CMakeLists.txt"
- },
- {
- "source": "../common/qmlmodules.tpl",
- "target": "%{ProjectDirectory}/qmlmodules"
- },
- {
- "source": "../common/qmlcomponents.tpl",
- "target": "%{ProjectDirectory}/qmlcomponents"
- },
- {
- "source": "../common/insight.tpl",
- "target": "%{ProjectDirectory}/insight"
- },
- {
- "source": "../common/main.qml",
- "target": "%{ProjectDirectory}/main.qml"
- },
- {
"source": "../common/qtquickcontrols2.conf.tpl",
"target": "%{ProjectDirectory}/qtquickcontrols2.conf"
},
{
- "source": "../common/main.cpp.tpl",
- "target": "%{ProjectDirectory}/src/main.cpp"
- },
- {
- "source": "../common/app_environment.h.tpl",
- "target": "%{ProjectDirectory}/src/app_environment.h"
- },
- {
- "source": "../common/import_qml_plugins.h.tpl",
- "target": "%{ProjectDirectory}/src/import_qml_plugins.h"
- },
- {
- "source": "../common/import_qml_components_plugins.h.tpl",
- "target": "%{ProjectDirectory}/src/import_qml_components_plugins.h"
- },
- {
- "source": "../common/CMakeLists.content.txt.tpl",
- "target": "%{ProjectDirectory}/content/CMakeLists.txt"
- },
- {
"source": "../common/App.qml.tpl",
- "target": "%{ProjectDirectory}/content/App.qml"
+ "target": "%{ProjectDirectory}/%{ContentDir}/App.qml"
},
{
"source": "Screen01.ui.qml.tpl",
- "target": "%{ProjectDirectory}/content/Screen01.ui.qml",
+ "target": "%{ProjectDirectory}/%{ContentDir}/Screen01.ui.qml",
"openInEditor": true
},
{
"source": "../common/fonts.txt",
- "target": "%{ProjectDirectory}/content/fonts/fonts.txt"
+ "target": "%{ProjectDirectory}/%{ContentDir}/fonts/fonts.txt"
},
{
"source": "../common/asset_imports.txt",
- "target": "%{ProjectDirectory}/asset_imports/asset_imports.txt"
- },
- {
- "source": "../common/CMakeLists.imports.txt.tpl",
- "target": "%{ProjectDirectory}/imports/CMakeLists.txt"
- },
- {
- "source": "../shared-plugin/name/CMakeLists.importmodule.txt.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/CMakeLists.txt"
+ "target": "%{ProjectDirectory}/%{AssetDir}/%{AssetDir}.txt"
},
{
"source": "../shared-plugin/name/importmodule.qmldir.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/qmldir"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/qmldir"
},
{
"source": "../shared-plugin/name/Constants.qml.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/Constants.qml"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/Constants.qml"
},
{
"source": "../shared-plugin/name/DirectoryFontLoader.qml.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/DirectoryFontLoader.qml"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/DirectoryFontLoader.qml"
},
{
"source": "../shared-plugin/name/EventListModel.qml.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/EventListModel.qml"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/EventListModel.qml"
},
{
"source": "../shared-plugin/name/EventListSimulator.qml.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/EventListSimulator.qml"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/EventListSimulator.qml"
},
{
"source": "../shared-plugin/name/designer/plugin.metainfo",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/designer/plugin.metainfo"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/designer/plugin.metainfo"
}
]
}
diff --git a/share/qtcreator/qmldesigner/studio_templates/projects/mobile-scroll/wizard.json b/share/qtcreator/qmldesigner/studio_templates/projects/mobile-scroll/wizard.json
index d521cc201e..585a73aa90 100644
--- a/share/qtcreator/qmldesigner/studio_templates/projects/mobile-scroll/wizard.json
+++ b/share/qtcreator/qmldesigner/studio_templates/projects/mobile-scroll/wizard.json
@@ -17,6 +17,8 @@
{ "key": "ProjectPluginName", "value": "%{ProjectName}plugin" },
{ "key": "ProjectPluginClassName", "value": "%{ProjectName}Plugin" },
{ "key": "QmlProjectFileName", "value": "%{JS: Util.fileName('%{ProjectName}', 'qmlproject')}" },
+ { "key": "AssetDir", "value": "GeneratedComponents" },
+ { "key": "ContentDir", "value": "%{ProjectName}Content" },
{ "key": "ImportModuleName", "value": "%{ProjectName}" },
{ "key": "UIClassName", "value": "Screen01" },
{ "key": "UIClassFileName", "value": "%{JS: Util.fileName('%{UIClassName}', 'ui.qml')}" },
@@ -193,7 +195,7 @@
"type": "ComboBox",
"data":
{
- "index": 4,
+ "index": 6,
"items":
[
{
@@ -237,6 +239,13 @@
"({
'TargetQuickVersion': '6.6'
})"
+ },
+ {
+ "trKey": "Qt 6.7",
+ "value":
+ "({
+ 'TargetQuickVersion': '6.7'
+ })"
}
]
}
@@ -257,97 +266,49 @@
"openAsProject": true
},
{
- "source": "../common/CMakeLists.main.txt.tpl",
- "target": "%{ProjectDirectory}/CMakeLists.txt"
- },
- {
- "source": "../common/qmlmodules.tpl",
- "target": "%{ProjectDirectory}/qmlmodules"
- },
- {
- "source": "../common/qmlcomponents.tpl",
- "target": "%{ProjectDirectory}/qmlcomponents"
- },
- {
- "source": "../common/insight.tpl",
- "target": "%{ProjectDirectory}/insight"
- },
- {
- "source": "../common/main.qml",
- "target": "%{ProjectDirectory}/main.qml"
- },
- {
"source": "../common/qtquickcontrols2.conf.tpl",
"target": "%{ProjectDirectory}/qtquickcontrols2.conf"
},
{
- "source": "../common/main.cpp.tpl",
- "target": "%{ProjectDirectory}/src/main.cpp"
- },
- {
- "source": "../common/app_environment.h.tpl",
- "target": "%{ProjectDirectory}/src/app_environment.h"
- },
- {
- "source": "../common/import_qml_plugins.h.tpl",
- "target": "%{ProjectDirectory}/src/import_qml_plugins.h"
- },
- {
- "source": "../common/import_qml_components_plugins.h.tpl",
- "target": "%{ProjectDirectory}/src/import_qml_components_plugins.h"
- },
- {
- "source": "../common/CMakeLists.content.txt.tpl",
- "target": "%{ProjectDirectory}/content/CMakeLists.txt"
- },
- {
"source": "../common/App.qml.tpl",
- "target": "%{ProjectDirectory}/content/App.qml"
+ "target": "%{ProjectDirectory}/%{ContentDir}/App.qml"
},
{
"source": "Screen01.ui.qml.tpl",
- "target": "%{ProjectDirectory}/content/Screen01.ui.qml",
+ "target": "%{ProjectDirectory}/%{ContentDir}/Screen01.ui.qml",
"openInEditor": true
},
{
"source": "../common/fonts.txt",
- "target": "%{ProjectDirectory}/content/fonts/fonts.txt"
+ "target": "%{ProjectDirectory}/%{ContentDir}/fonts/fonts.txt"
},
{
"source": "../common/asset_imports.txt",
- "target": "%{ProjectDirectory}/asset_imports/asset_imports.txt"
- },
- {
- "source": "../common/CMakeLists.imports.txt.tpl",
- "target": "%{ProjectDirectory}/imports/CMakeLists.txt"
- },
- {
- "source": "../shared-plugin/name/CMakeLists.importmodule.txt.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/CMakeLists.txt"
+ "target": "%{ProjectDirectory}/%{AssetDir}/%{AssetDir}.txt"
},
{
"source": "../shared-plugin/name/importmodule.qmldir.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/qmldir"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/qmldir"
},
{
"source": "../shared-plugin/name/Constants.qml.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/Constants.qml"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/Constants.qml"
},
{
"source": "../shared-plugin/name/DirectoryFontLoader.qml.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/DirectoryFontLoader.qml"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/DirectoryFontLoader.qml"
},
{
"source": "../shared-plugin/name/EventListModel.qml.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/EventListModel.qml"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/EventListModel.qml"
},
{
"source": "../shared-plugin/name/EventListSimulator.qml.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/EventListSimulator.qml"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/EventListSimulator.qml"
},
{
"source": "../shared-plugin/name/designer/plugin.metainfo",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/designer/plugin.metainfo"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/designer/plugin.metainfo"
}
]
}
diff --git a/share/qtcreator/qmldesigner/studio_templates/projects/mobile-stack/wizard.json b/share/qtcreator/qmldesigner/studio_templates/projects/mobile-stack/wizard.json
index 17cd30d507..a44a1429be 100644
--- a/share/qtcreator/qmldesigner/studio_templates/projects/mobile-stack/wizard.json
+++ b/share/qtcreator/qmldesigner/studio_templates/projects/mobile-stack/wizard.json
@@ -17,6 +17,8 @@
{ "key": "ProjectPluginName", "value": "%{ProjectName}plugin" },
{ "key": "ProjectPluginClassName", "value": "%{ProjectName}Plugin" },
{ "key": "QmlProjectFileName", "value": "%{JS: Util.fileName('%{ProjectName}', 'qmlproject')}" },
+ { "key": "AssetDir", "value": "GeneratedComponents" },
+ { "key": "ContentDir", "value": "%{ProjectName}Content" },
{ "key": "ImportModuleName", "value": "%{ProjectName}" },
{ "key": "IsQt6Project", "value": "%{JS: value('QtQuickVersion') !== '2.15' }" },
{ "key": "QtQuickVersion", "value": "%{JS: %{TargetQtVersion}.TargetQuickVersion}" },
@@ -191,7 +193,7 @@
"type": "ComboBox",
"data":
{
- "index": 4,
+ "index": 6,
"items":
[
{
@@ -235,6 +237,13 @@
"({
'TargetQuickVersion': '6.6'
})"
+ },
+ {
+ "trKey": "Qt 6.7",
+ "value":
+ "({
+ 'TargetQuickVersion': '6.7'
+ })"
}
]
}
@@ -254,102 +263,54 @@
"openAsProject": true
},
{
- "source": "../common/CMakeLists.main.txt.tpl",
- "target": "%{ProjectDirectory}/CMakeLists.txt"
- },
- {
- "source": "../common/qmlmodules.tpl",
- "target": "%{ProjectDirectory}/qmlmodules"
- },
- {
- "source": "../common/qmlcomponents.tpl",
- "target": "%{ProjectDirectory}/qmlcomponents"
- },
- {
- "source": "../common/insight.tpl",
- "target": "%{ProjectDirectory}/insight"
- },
- {
- "source": "../common/main.qml",
- "target": "%{ProjectDirectory}/main.qml"
- },
- {
"source": "../common/qtquickcontrols2.conf.tpl",
"target": "%{ProjectDirectory}/qtquickcontrols2.conf"
},
{
- "source": "../common/main.cpp.tpl",
- "target": "%{ProjectDirectory}/src/main.cpp"
- },
- {
- "source": "../common/app_environment.h.tpl",
- "target": "%{ProjectDirectory}/src/app_environment.h"
- },
- {
- "source": "../common/import_qml_plugins.h.tpl",
- "target": "%{ProjectDirectory}/src/import_qml_plugins.h"
- },
- {
- "source": "../common/import_qml_components_plugins.h.tpl",
- "target": "%{ProjectDirectory}/src/import_qml_components_plugins.h"
- },
- {
- "source": "CMakeLists.content.txt.tpl",
- "target": "%{ProjectDirectory}/content/CMakeLists.txt"
- },
- {
"source": "App.qml.tpl",
- "target": "%{ProjectDirectory}/content/App.qml"
+ "target": "%{ProjectDirectory}/%{ContentDir}/App.qml"
},
{
"source": "Screen01.ui.qml.tpl",
- "target": "%{ProjectDirectory}/content/Screen01.ui.qml",
+ "target": "%{ProjectDirectory}/%{ContentDir}/Screen01.ui.qml",
"openInEditor": true
},
{
"source": "Screen02.ui.qml.tpl",
- "target": "%{ProjectDirectory}/content/Screen02.ui.qml",
+ "target": "%{ProjectDirectory}/%{ContentDir}/Screen02.ui.qml",
"openInEditor": true
},
{
"source": "../common/fonts.txt",
- "target": "%{ProjectDirectory}/content/fonts/fonts.txt"
+ "target": "%{ProjectDirectory}/%{ContentDir}/fonts/fonts.txt"
},
{
"source": "../common/asset_imports.txt",
- "target": "%{ProjectDirectory}/asset_imports/asset_imports.txt"
- },
- {
- "source": "../common/CMakeLists.imports.txt.tpl",
- "target": "%{ProjectDirectory}/imports/CMakeLists.txt"
- },
- {
- "source": "../shared-plugin/name/CMakeLists.importmodule.txt.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/CMakeLists.txt"
+ "target": "%{ProjectDirectory}/%{AssetDir}/%{AssetDir}.txt"
},
{
"source": "../shared-plugin/name/importmodule.qmldir.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/qmldir"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/qmldir"
},
{
"source": "../shared-plugin/name/Constants.qml.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/Constants.qml"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/Constants.qml"
},
{
"source": "../shared-plugin/name/DirectoryFontLoader.qml.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/DirectoryFontLoader.qml"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/DirectoryFontLoader.qml"
},
{
"source": "../shared-plugin/name/EventListModel.qml.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/EventListModel.qml"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/EventListModel.qml"
},
{
"source": "../shared-plugin/name/EventListSimulator.qml.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/EventListSimulator.qml"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/EventListSimulator.qml"
},
{
"source": "../shared-plugin/name/designer/plugin.metainfo",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/designer/plugin.metainfo"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/designer/plugin.metainfo"
}
]
}
diff --git a/share/qtcreator/qmldesigner/studio_templates/projects/mobile-swipe/wizard.json b/share/qtcreator/qmldesigner/studio_templates/projects/mobile-swipe/wizard.json
index 37710ae91d..b3f70a8b79 100644
--- a/share/qtcreator/qmldesigner/studio_templates/projects/mobile-swipe/wizard.json
+++ b/share/qtcreator/qmldesigner/studio_templates/projects/mobile-swipe/wizard.json
@@ -17,6 +17,8 @@
{ "key": "ProjectPluginName", "value": "%{ProjectName}plugin" },
{ "key": "ProjectPluginClassName", "value": "%{ProjectName}Plugin" },
{ "key": "QmlProjectFileName", "value": "%{JS: Util.fileName('%{ProjectName}', 'qmlproject')}" },
+ { "key": "AssetDir", "value": "GeneratedComponents" },
+ { "key": "ContentDir", "value": "%{ProjectName}Content" },
{ "key": "ImportModuleName", "value": "%{ProjectName}" },
{ "key": "IsQt6Project", "value": "%{JS: value('QtQuickVersion') !== '2.15' }" },
{ "key": "QtQuickVersion", "value": "%{JS: %{TargetQtVersion}.TargetQuickVersion}" },
@@ -191,7 +193,7 @@
"type": "ComboBox",
"data":
{
- "index": 4,
+ "index": 6,
"items":
[
{
@@ -235,6 +237,13 @@
"({
'TargetQuickVersion': '6.6'
})"
+ },
+ {
+ "trKey": "Qt 6.7",
+ "value":
+ "({
+ 'TargetQuickVersion': '6.7'
+ })"
}
]
}
@@ -254,102 +263,54 @@
"openAsProject": true
},
{
- "source": "../common/CMakeLists.main.txt.tpl",
- "target": "%{ProjectDirectory}/CMakeLists.txt"
- },
- {
- "source": "../common/qmlmodules.tpl",
- "target": "%{ProjectDirectory}/qmlmodules"
- },
- {
- "source": "../common/qmlcomponents.tpl",
- "target": "%{ProjectDirectory}/qmlcomponents"
- },
- {
- "source": "../common/insight.tpl",
- "target": "%{ProjectDirectory}/insight"
- },
- {
- "source": "../common/main.qml",
- "target": "%{ProjectDirectory}/main.qml"
- },
- {
"source": "../common/qtquickcontrols2.conf.tpl",
"target": "%{ProjectDirectory}/qtquickcontrols2.conf"
},
{
- "source": "../common/main.cpp.tpl",
- "target": "%{ProjectDirectory}/src/main.cpp"
- },
- {
- "source": "../common/app_environment.h.tpl",
- "target": "%{ProjectDirectory}/src/app_environment.h"
- },
- {
- "source": "../common/import_qml_plugins.h.tpl",
- "target": "%{ProjectDirectory}/src/import_qml_plugins.h"
- },
- {
- "source": "../common/import_qml_components_plugins.h.tpl",
- "target": "%{ProjectDirectory}/src/import_qml_components_plugins.h"
- },
- {
- "source": "CMakeLists.content.txt.tpl",
- "target": "%{ProjectDirectory}/content/CMakeLists.txt"
- },
- {
"source": "App.qml.tpl",
- "target": "%{ProjectDirectory}/content/App.qml"
+ "target": "%{ProjectDirectory}/%{ContentDir}/App.qml"
},
{
"source": "Screen01.ui.qml.tpl",
- "target": "%{ProjectDirectory}/content/Screen01.ui.qml",
+ "target": "%{ProjectDirectory}/%{ContentDir}/Screen01.ui.qml",
"openInEditor": true
},
{
"source": "Screen02.ui.qml.tpl",
- "target": "%{ProjectDirectory}/content/Screen02.ui.qml",
+ "target": "%{ProjectDirectory}/%{ContentDir}/Screen02.ui.qml",
"openInEditor": true
},
{
"source": "../common/fonts.txt",
- "target": "%{ProjectDirectory}/content/fonts/fonts.txt"
+ "target": "%{ProjectDirectory}/%{ContentDir}/fonts/fonts.txt"
},
{
"source": "../common/asset_imports.txt",
- "target": "%{ProjectDirectory}/asset_imports/asset_imports.txt"
- },
- {
- "source": "../common/CMakeLists.imports.txt.tpl",
- "target": "%{ProjectDirectory}/imports/CMakeLists.txt"
- },
- {
- "source": "../shared-plugin/name/CMakeLists.importmodule.txt.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/CMakeLists.txt"
+ "target": "%{ProjectDirectory}/%{AssetDir}/%{AssetDir}.txt"
},
{
"source": "../shared-plugin/name/importmodule.qmldir.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/qmldir"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/qmldir"
},
{
"source": "../shared-plugin/name/Constants.qml.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/Constants.qml"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/Constants.qml"
},
{
"source": "../shared-plugin/name/DirectoryFontLoader.qml.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/DirectoryFontLoader.qml"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/DirectoryFontLoader.qml"
},
{
"source": "../shared-plugin/name/EventListModel.qml.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/EventListModel.qml"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/EventListModel.qml"
},
{
"source": "../shared-plugin/name/EventListSimulator.qml.tpl",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/EventListSimulator.qml"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/EventListSimulator.qml"
},
{
"source": "../shared-plugin/name/designer/plugin.metainfo",
- "target": "%{ProjectDirectory}/imports/%{ImportModuleName}/designer/plugin.metainfo"
+ "target": "%{ProjectDirectory}/%{ImportModuleName}/designer/plugin.metainfo"
}
]
}
diff --git a/share/qtcreator/qmldesigner/studio_templates/projects/shared-plugin/name/Constants.qml.tpl b/share/qtcreator/qmldesigner/studio_templates/projects/shared-plugin/name/Constants.qml.tpl
index cc5da7be55..35aa48896b 100644
--- a/share/qtcreator/qmldesigner/studio_templates/projects/shared-plugin/name/Constants.qml.tpl
+++ b/share/qtcreator/qmldesigner/studio_templates/projects/shared-plugin/name/Constants.qml.tpl
@@ -26,7 +26,7 @@ QtObject {
@if %{IsQt6Project}
property StudioApplication application: StudioApplication {
- fontPath: Qt.resolvedUrl("../../content/" + relativeFontDirectory)
+ fontPath: Qt.resolvedUrl("../../%{ContentDir}/" + relativeFontDirectory)
}
@else
property DirectoryFontLoader directoryFontLoader: DirectoryFontLoader {
diff --git a/share/qtcreator/qmldesigner/studio_templates/projects/shared-plugin/name/DirectoryFontLoader.qml.tpl b/share/qtcreator/qmldesigner/studio_templates/projects/shared-plugin/name/DirectoryFontLoader.qml.tpl
index 677fe05428..56ecc9f2f8 100644
--- a/share/qtcreator/qmldesigner/studio_templates/projects/shared-plugin/name/DirectoryFontLoader.qml.tpl
+++ b/share/qtcreator/qmldesigner/studio_templates/projects/shared-plugin/name/DirectoryFontLoader.qml.tpl
@@ -7,7 +7,7 @@ import Qt.labs.folderlistmodel %{QtQuickVersion}
QtObject {
id: loader
- property url fontDirectory: Qt.resolvedUrl("../../content/" + relativeFontDirectory)
+ property url fontDirectory: Qt.resolvedUrl("../../%{ContentDir}/" + relativeFontDirectory)
property string relativeFontDirectory: "fonts"
function loadFont(url) {
diff --git a/share/qtcreator/qmldesigner/toolbar/Main.qml b/share/qtcreator/qmldesigner/toolbar/Main.qml
index 7235028df6..88a9bd744a 100644
--- a/share/qtcreator/qmldesigner/toolbar/Main.qml
+++ b/share/qtcreator/qmldesigner/toolbar/Main.qml
@@ -190,6 +190,26 @@ Rectangle {
onActivated: backend.openFileByIndex(index)
}
+ Text {
+ parent:currentFile.contentItem
+ visible: backend.isDocumentDirty
+
+ anchors.right: parent.right
+ anchors.rightMargin: parent.width - metric.textWidth - 18
+ color: StudioTheme.Values.themeTextColor
+ text: StudioTheme.Constants.wildcard
+ font.family: StudioTheme.Constants.iconFont.family
+ font.pixelSize: StudioTheme.Values.smallIconFont
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.verticalCenterOffset: -4
+
+ FontMetrics {
+ id: metric
+ font: currentFile.font
+ property int textWidth: metric.boundingRect(currentFile.currentText).width
+ }
+ }
+
ToolbarButton {
id: backButton
anchors.verticalCenter: parent.verticalCenter
diff --git a/share/qtcreator/qmldesigner/welcomepage/MainGridStack.qml b/share/qtcreator/qmldesigner/welcomepage/MainGridStack.qml
index 73b023bddc..555596223b 100644
--- a/share/qtcreator/qmldesigner/welcomepage/MainGridStack.qml
+++ b/share/qtcreator/qmldesigner/welcomepage/MainGridStack.qml
@@ -88,7 +88,17 @@ Item {
Layout.fillWidth: true
Layout.fillHeight: true
hover: hoverHandler.hovered
- model: ExamplesModel { id: examplesModel}
+
+ Component.onCompleted: {
+ // remove items with old versions from the examples model
+ for (let i = examplesModel.count - 1; i >= 0; --i) {
+ if (!projectModel.exampleVersionOk(examplesModel.get(i).minQDSVersion))
+ examplesModel.remove(i)
+ }
+ }
+
+ model: ExamplesModelV2 { id: examplesModel }
+
delegate: ThumbnailDelegate {
type: ThumbnailDelegate.Type.Example
downloadable: showDownload
diff --git a/src/libs/3rdparty/googletest b/src/libs/3rdparty/googletest
-Subproject b796f7d44681514f58a683a3a71ff17c94edb0c
+Subproject f8d7d77c06936315286eb55f8de22cd23c18857
diff --git a/src/libs/3rdparty/sqlite/sqlite3.c b/src/libs/3rdparty/sqlite/sqlite3.c
index 139ee46a6a..08c593e55c 100644
--- a/src/libs/3rdparty/sqlite/sqlite3.c
+++ b/src/libs/3rdparty/sqlite/sqlite3.c
@@ -1,6 +1,6 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-** version 3.45.1. By combining all the individual C code files into this
+** version 3.45.3. By combining all the individual C code files into this
** single large file, the entire code can be compiled as a single translation
** unit. This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately. Performance improvements
@@ -18,7 +18,7 @@
** separate file. This file contains only code for the core SQLite library.
**
** The content in this amalgamation comes from Fossil check-in
-** e876e51a0ed5c5b3126f52e532044363a014.
+** 8653b758870e6ef0c98d46b3ace27849054a.
*/
#define SQLITE_CORE 1
#define SQLITE_AMALGAMATION 1
@@ -459,9 +459,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.45.1"
-#define SQLITE_VERSION_NUMBER 3045001
-#define SQLITE_SOURCE_ID "2024-01-30 16:01:20 e876e51a0ed5c5b3126f52e532044363a014bc594cfefa87ffb5b82257cc467a"
+#define SQLITE_VERSION "3.45.3"
+#define SQLITE_VERSION_NUMBER 3045003
+#define SQLITE_SOURCE_ID "2024-04-15 13:34:05 8653b758870e6ef0c98d46b3ace27849054af85da891eb121e9aaa537f1e8355"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -733,6 +733,8 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
** the 1st parameter to sqlite3_exec() while sqlite3_exec() is running.
** <li> The application must not modify the SQL statement text passed into
** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running.
+** <li> The application must not dereference the arrays or string pointers
+** passed as the 3rd and 4th callback parameters after it returns.
** </ul>
*/
SQLITE_API int sqlite3_exec(
@@ -2454,6 +2456,22 @@ struct sqlite3_mem_methods {
** configuration setting is never used, then the default maximum is determined
** by the [SQLITE_MEMDB_DEFAULT_MAXSIZE] compile-time option. If that
** compile-time option is not set, then the default maximum is 1073741824.
+**
+** [[SQLITE_CONFIG_ROWID_IN_VIEW]]
+** <dt>SQLITE_CONFIG_ROWID_IN_VIEW
+** <dd>The SQLITE_CONFIG_ROWID_IN_VIEW option enables or disables the ability
+** for VIEWs to have a ROWID. The capability can only be enabled if SQLite is
+** compiled with -DSQLITE_ALLOW_ROWID_IN_VIEW, in which case the capability
+** defaults to on. This configuration option queries the current setting or
+** changes the setting to off or on. The argument is a pointer to an integer.
+** If that integer initially holds a value of 1, then the ability for VIEWs to
+** have ROWIDs is activated. If the integer initially holds zero, then the
+** ability is deactivated. Any other initial value for the integer leaves the
+** setting unchanged. After changes, if any, the integer is written with
+** a 1 or 0, if the ability for VIEWs to have ROWIDs is on or off. If SQLite
+** is compiled without -DSQLITE_ALLOW_ROWID_IN_VIEW (which is the usual and
+** recommended case) then the integer is always filled with zero, regardless
+** if its initial value.
** </dl>
*/
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
@@ -2485,6 +2503,7 @@ struct sqlite3_mem_methods {
#define SQLITE_CONFIG_SMALL_MALLOC 27 /* boolean */
#define SQLITE_CONFIG_SORTERREF_SIZE 28 /* int nByte */
#define SQLITE_CONFIG_MEMDB_MAXSIZE 29 /* sqlite3_int64 */
+#define SQLITE_CONFIG_ROWID_IN_VIEW 30 /* int* */
/*
** CAPI3REF: Database Connection Configuration Options
@@ -15097,6 +15116,7 @@ SQLITE_PRIVATE u32 sqlite3TreeTrace;
** 0x00010000 Beginning of DELETE/INSERT/UPDATE processing
** 0x00020000 Transform DISTINCT into GROUP BY
** 0x00040000 SELECT tree dump after all code has been generated
+** 0x00080000 NOT NULL strength reduction
*/
/*
@@ -18427,6 +18447,15 @@ struct Table {
#define HasRowid(X) (((X)->tabFlags & TF_WithoutRowid)==0)
#define VisibleRowid(X) (((X)->tabFlags & TF_NoVisibleRowid)==0)
+/* Macro is true if the SQLITE_ALLOW_ROWID_IN_VIEW (mis-)feature is
+** available. By default, this macro is false
+*/
+#ifndef SQLITE_ALLOW_ROWID_IN_VIEW
+# define ViewCanHaveRowid 0
+#else
+# define ViewCanHaveRowid (sqlite3Config.mNoVisibleRowid==0)
+#endif
+
/*
** Each foreign key constraint is an instance of the following structure.
**
@@ -19346,6 +19375,7 @@ struct NameContext {
#define NC_InAggFunc 0x020000 /* True if analyzing arguments to an agg func */
#define NC_FromDDL 0x040000 /* SQL text comes from sqlite_schema */
#define NC_NoSelect 0x080000 /* Do not descend into sub-selects */
+#define NC_Where 0x100000 /* Processing WHERE clause of a SELECT */
#define NC_OrderAgg 0x8000000 /* Has an aggregate other than count/min/max */
/*
@@ -19369,6 +19399,7 @@ struct Upsert {
Expr *pUpsertWhere; /* WHERE clause for the ON CONFLICT UPDATE */
Upsert *pNextUpsert; /* Next ON CONFLICT clause in the list */
u8 isDoUpdate; /* True for DO UPDATE. False for DO NOTHING */
+ u8 isDup; /* True if 2nd or later with same pUpsertIdx */
/* Above this point is the parse tree for the ON CONFLICT clauses.
** The next group of fields stores intermediate data. */
void *pToFree; /* Free memory when deleting the Upsert object */
@@ -20140,6 +20171,11 @@ struct Sqlite3Config {
#ifndef SQLITE_UNTESTABLE
int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */
#endif
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
+ u32 mNoVisibleRowid; /* TF_NoVisibleRowid if the ROWID_IN_VIEW
+ ** feature is disabled. 0 if rowids can
+ ** occur in views. */
+#endif
int bLocaltimeFault; /* True to fail localtime() calls */
int (*xAltLocaltime)(const void*,void*); /* Alternative localtime() routine */
int iOnceResetThreshold; /* When to reset OP_Once counters */
@@ -20595,10 +20631,13 @@ SQLITE_PRIVATE void sqlite3MutexWarnOnContention(sqlite3_mutex*);
# define EXP754 (((u64)0x7ff)<<52)
# define MAN754 ((((u64)1)<<52)-1)
# define IsNaN(X) (((X)&EXP754)==EXP754 && ((X)&MAN754)!=0)
+# define IsOvfl(X) (((X)&EXP754)==EXP754)
SQLITE_PRIVATE int sqlite3IsNaN(double);
+SQLITE_PRIVATE int sqlite3IsOverflow(double);
#else
-# define IsNaN(X) 0
-# define sqlite3IsNaN(X) 0
+# define IsNaN(X) 0
+# define sqlite3IsNaN(X) 0
+# define sqlite3IsOVerflow(X) 0
#endif
/*
@@ -21444,7 +21483,7 @@ SQLITE_PRIVATE With *sqlite3WithPush(Parse*, With*, u8);
SQLITE_PRIVATE Upsert *sqlite3UpsertNew(sqlite3*,ExprList*,Expr*,ExprList*,Expr*,Upsert*);
SQLITE_PRIVATE void sqlite3UpsertDelete(sqlite3*,Upsert*);
SQLITE_PRIVATE Upsert *sqlite3UpsertDup(sqlite3*,Upsert*);
-SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*);
+SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*,Upsert*);
SQLITE_PRIVATE void sqlite3UpsertDoUpdate(Parse*,Upsert*,Table*,Index*,int);
SQLITE_PRIVATE Upsert *sqlite3UpsertOfIndex(Upsert*,Index*);
SQLITE_PRIVATE int sqlite3UpsertNextIsIPK(Upsert*);
@@ -21834,6 +21873,9 @@ static const char * const sqlite3azCompileOpt[] = {
"ALLOW_COVERING_INDEX_SCAN=" CTIMEOPT_VAL(SQLITE_ALLOW_COVERING_INDEX_SCAN),
# endif
#endif
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
+ "ALLOW_ROWID_IN_VIEW",
+#endif
#ifdef SQLITE_ALLOW_URI_AUTHORITY
"ALLOW_URI_AUTHORITY",
#endif
@@ -22854,6 +22896,9 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
#ifndef SQLITE_UNTESTABLE
0, /* xTestCallback */
#endif
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
+ 0, /* mNoVisibleRowid. 0 == allow rowid-in-view */
+#endif
0, /* bLocaltimeFault */
0, /* xAltLocaltime */
0x7ffffffe, /* iOnceResetThreshold */
@@ -31309,6 +31354,7 @@ SQLITE_API void sqlite3_str_vappendf(
if( xtype==etFLOAT ){
iRound = -precision;
}else if( xtype==etGENERIC ){
+ if( precision==0 ) precision = 1;
iRound = precision;
}else{
iRound = precision+1;
@@ -34640,6 +34686,19 @@ SQLITE_PRIVATE int sqlite3IsNaN(double x){
}
#endif /* SQLITE_OMIT_FLOATING_POINT */
+#ifndef SQLITE_OMIT_FLOATING_POINT
+/*
+** Return true if the floating point value is NaN or +Inf or -Inf.
+*/
+SQLITE_PRIVATE int sqlite3IsOverflow(double x){
+ int rc; /* The value return */
+ u64 y;
+ memcpy(&y,&x,sizeof(y));
+ rc = IsOvfl(y);
+ return rc;
+}
+#endif /* SQLITE_OMIT_FLOATING_POINT */
+
/*
** Compute a string length that is limited to what can be stored in
** lower 30 bits of a 32-bit signed integer.
@@ -35199,6 +35258,9 @@ do_atof_calc:
u64 s2;
rr[0] = (double)s;
s2 = (u64)rr[0];
+#if defined(_MSC_VER) && _MSC_VER<1700
+ if( s2==0x8000000000000000LL ){ s2 = 2*(u64)(0.5*rr[0]); }
+#endif
rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s);
if( e>0 ){
while( e>=100 ){
@@ -35641,7 +35703,7 @@ SQLITE_PRIVATE void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRou
assert( p->n>0 );
assert( p->n<sizeof(p->zBuf) );
p->iDP = p->n + exp;
- if( iRound<0 ){
+ if( iRound<=0 ){
iRound = p->iDP - iRound;
if( iRound==0 && p->zBuf[i+1]>='5' ){
iRound = 1;
@@ -53262,6 +53324,14 @@ SQLITE_API unsigned char *sqlite3_serialize(
pOut = 0;
}else{
sz = sqlite3_column_int64(pStmt, 0)*szPage;
+ if( sz==0 ){
+ sqlite3_reset(pStmt);
+ sqlite3_exec(db, "BEGIN IMMEDIATE; COMMIT;", 0, 0, 0);
+ rc = sqlite3_step(pStmt);
+ if( rc==SQLITE_ROW ){
+ sz = sqlite3_column_int64(pStmt, 0)*szPage;
+ }
+ }
if( piSize ) *piSize = sz;
if( mFlags & SQLITE_SERIALIZE_NOCOPY ){
pOut = 0;
@@ -63785,7 +63855,7 @@ SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager *pPager){
** This will be either the rollback journal or the WAL file.
*/
SQLITE_PRIVATE sqlite3_file *sqlite3PagerJrnlFile(Pager *pPager){
-#if SQLITE_OMIT_WAL
+#ifdef SQLITE_OMIT_WAL
return pPager->jfd;
#else
return pPager->pWal ? sqlite3WalFile(pPager->pWal) : pPager->jfd;
@@ -77088,7 +77158,10 @@ static int fillInCell(
n = nHeader + nPayload;
testcase( n==3 );
testcase( n==4 );
- if( n<4 ) n = 4;
+ if( n<4 ){
+ n = 4;
+ pPayload[nPayload] = 0;
+ }
*pnSize = n;
assert( nSrc<=nPayload );
testcase( nSrc<nPayload );
@@ -79534,7 +79607,10 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
if( flags & BTREE_PREFORMAT ){
rc = SQLITE_OK;
szNew = p->pBt->nPreformatSize;
- if( szNew<4 ) szNew = 4;
+ if( szNew<4 ){
+ szNew = 4;
+ newCell[3] = 0;
+ }
if( ISAUTOVACUUM(p->pBt) && szNew>pPage->maxLocal ){
CellInfo info;
pPage->xParseCell(pPage, newCell, &info);
@@ -79596,7 +79672,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
}else if( loc<0 && pPage->nCell>0 ){
assert( pPage->leaf );
idx = ++pCur->ix;
- pCur->curFlags &= ~BTCF_ValidNKey;
+ pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
}else{
assert( pPage->leaf );
}
@@ -79626,7 +79702,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
*/
if( pPage->nOverflow ){
assert( rc==SQLITE_OK );
- pCur->curFlags &= ~(BTCF_ValidNKey);
+ pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
rc = balance(pCur);
/* Must make sure nOverflow is reset to zero even if the balance()
@@ -88379,6 +88455,23 @@ static void serialGet(
pMem->flags = IsNaN(x) ? MEM_Null : MEM_Real;
}
}
+static int serialGet7(
+ const unsigned char *buf, /* Buffer to deserialize from */
+ Mem *pMem /* Memory cell to write value into */
+){
+ u64 x = FOUR_BYTE_UINT(buf);
+ u32 y = FOUR_BYTE_UINT(buf+4);
+ x = (x<<32) + y;
+ assert( sizeof(x)==8 && sizeof(pMem->u.r)==8 );
+ swapMixedEndianFloat(x);
+ memcpy(&pMem->u.r, &x, sizeof(x));
+ if( IsNaN(x) ){
+ pMem->flags = MEM_Null;
+ return 1;
+ }
+ pMem->flags = MEM_Real;
+ return 0;
+}
SQLITE_PRIVATE void sqlite3VdbeSerialGet(
const unsigned char *buf, /* Buffer to deserialize from */
u32 serial_type, /* Serial type to deserialize */
@@ -89058,7 +89151,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
}else if( serial_type==0 ){
rc = -1;
}else if( serial_type==7 ){
- sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
+ serialGet7(&aKey1[d1], &mem1);
rc = -sqlite3IntFloatCompare(pRhs->u.i, mem1.u.r);
}else{
i64 lhs = vdbeRecordDecodeInt(serial_type, &aKey1[d1]);
@@ -89083,14 +89176,18 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
}else if( serial_type==0 ){
rc = -1;
}else{
- sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
if( serial_type==7 ){
- if( mem1.u.r<pRhs->u.r ){
+ if( serialGet7(&aKey1[d1], &mem1) ){
+ rc = -1; /* mem1 is a NaN */
+ }else if( mem1.u.r<pRhs->u.r ){
rc = -1;
}else if( mem1.u.r>pRhs->u.r ){
rc = +1;
+ }else{
+ assert( rc==0 );
}
}else{
+ sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
rc = sqlite3IntFloatCompare(mem1.u.i, pRhs->u.r);
}
}
@@ -89160,7 +89257,14 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
/* RHS is null */
else{
serial_type = aKey1[idx1];
- rc = (serial_type!=0 && serial_type!=10);
+ if( serial_type==0
+ || serial_type==10
+ || (serial_type==7 && serialGet7(&aKey1[d1], &mem1)!=0)
+ ){
+ assert( rc==0 );
+ }else{
+ rc = 1;
+ }
}
if( rc!=0 ){
@@ -94858,7 +94962,9 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
}
}
}else if( affinity==SQLITE_AFF_TEXT && ((flags1 | flags3) & MEM_Str)!=0 ){
- if( (flags1 & MEM_Str)==0 && (flags1&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){
+ if( (flags1 & MEM_Str)!=0 ){
+ pIn1->flags &= ~(MEM_Int|MEM_Real|MEM_IntReal);
+ }else if( (flags1&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){
testcase( pIn1->flags & MEM_Int );
testcase( pIn1->flags & MEM_Real );
testcase( pIn1->flags & MEM_IntReal );
@@ -94867,7 +94973,9 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask);
if( NEVER(pIn1==pIn3) ) flags3 = flags1 | MEM_Str;
}
- if( (flags3 & MEM_Str)==0 && (flags3&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){
+ if( (flags3 & MEM_Str)!=0 ){
+ pIn3->flags &= ~(MEM_Int|MEM_Real|MEM_IntReal);
+ }else if( (flags3&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){
testcase( pIn3->flags & MEM_Int );
testcase( pIn3->flags & MEM_Real );
testcase( pIn3->flags & MEM_IntReal );
@@ -106212,6 +106320,8 @@ static void resolveAlias(
assert( iCol>=0 && iCol<pEList->nExpr );
pOrig = pEList->a[iCol].pExpr;
assert( pOrig!=0 );
+ assert( !ExprHasProperty(pExpr, EP_Reduced|EP_TokenOnly) );
+ if( pExpr->pAggInfo ) return;
db = pParse->db;
pDup = sqlite3ExprDup(db, pOrig, 0);
if( db->mallocFailed ){
@@ -106599,8 +106709,37 @@ static int lookupName(
}
}
if( 0==cnt && VisibleRowid(pTab) ){
+ /* pTab is a potential ROWID match. Keep track of it and match
+ ** the ROWID later if that seems appropriate. (Search for "cntTab"
+ ** to find related code.) Only allow a ROWID match if there is
+ ** a single ROWID match candidate.
+ */
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
+ /* In SQLITE_ALLOW_ROWID_IN_VIEW mode, allow a ROWID match
+ ** if there is a single VIEW candidate or if there is a single
+ ** non-VIEW candidate plus multiple VIEW candidates. In other
+ ** words non-VIEW candidate terms take precedence over VIEWs.
+ */
+ if( cntTab==0
+ || (cntTab==1
+ && ALWAYS(pMatch!=0)
+ && ALWAYS(pMatch->pTab!=0)
+ && (pMatch->pTab->tabFlags & TF_Ephemeral)!=0
+ && (pTab->tabFlags & TF_Ephemeral)==0)
+ ){
+ cntTab = 1;
+ pMatch = pItem;
+ }else{
+ cntTab++;
+ }
+#else
+ /* The (much more common) non-SQLITE_ALLOW_ROWID_IN_VIEW case is
+ ** simpler since we require exactly one candidate, which will
+ ** always be a non-VIEW
+ */
cntTab++;
pMatch = pItem;
+#endif
}
}
if( pMatch ){
@@ -106726,13 +106865,13 @@ static int lookupName(
** Perhaps the name is a reference to the ROWID
*/
if( cnt==0
- && cntTab==1
+ && cntTab>=1
&& pMatch
&& (pNC->ncFlags & (NC_IdxExpr|NC_GenCol))==0
&& sqlite3IsRowid(zCol)
&& ALWAYS(VisibleRowid(pMatch->pTab) || pMatch->fg.isNestedFrom)
){
- cnt = 1;
+ cnt = cntTab;
if( pMatch->fg.isNestedFrom==0 ) pExpr->iColumn = -1;
pExpr->affExpr = SQLITE_AFF_INTEGER;
}
@@ -107097,6 +107236,19 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
** resolved. This prevents "column" from being counted as having been
** referenced, which might prevent a SELECT from being erroneously
** marked as correlated.
+ **
+ ** 2024-03-28: Beware of aggregates. A bare column of aggregated table
+ ** can still evaluate to NULL even though it is marked as NOT NULL.
+ ** Example:
+ **
+ ** CREATE TABLE t1(a INT NOT NULL);
+ ** SELECT a, a IS NULL, a IS NOT NULL, count(*) FROM t1;
+ **
+ ** The "a IS NULL" and "a IS NOT NULL" expressions cannot be optimized
+ ** here because at the time this case is hit, we do not yet know whether
+ ** or not t1 is being aggregated. We have to assume the worst and omit
+ ** the optimization. The only time it is safe to apply this optimization
+ ** is within the WHERE clause.
*/
case TK_NOTNULL:
case TK_ISNULL: {
@@ -107107,19 +107259,36 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
anRef[i] = p->nRef;
}
sqlite3WalkExpr(pWalker, pExpr->pLeft);
- if( 0==sqlite3ExprCanBeNull(pExpr->pLeft) && !IN_RENAME_OBJECT ){
- testcase( ExprHasProperty(pExpr, EP_OuterON) );
- assert( !ExprHasProperty(pExpr, EP_IntValue) );
- pExpr->u.iValue = (pExpr->op==TK_NOTNULL);
- pExpr->flags |= EP_IntValue;
- pExpr->op = TK_INTEGER;
+ if( IN_RENAME_OBJECT ) return WRC_Prune;
+ if( sqlite3ExprCanBeNull(pExpr->pLeft) ){
+ /* The expression can be NULL. So the optimization does not apply */
+ return WRC_Prune;
+ }
- for(i=0, p=pNC; p && i<ArraySize(anRef); p=p->pNext, i++){
- p->nRef = anRef[i];
+ for(i=0, p=pNC; p; p=p->pNext, i++){
+ if( (p->ncFlags & NC_Where)==0 ){
+ return WRC_Prune; /* Not in a WHERE clause. Unsafe to optimize. */
}
- sqlite3ExprDelete(pParse->db, pExpr->pLeft);
- pExpr->pLeft = 0;
}
+ testcase( ExprHasProperty(pExpr, EP_OuterON) );
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
+#if TREETRACE_ENABLED
+ if( sqlite3TreeTrace & 0x80000 ){
+ sqlite3DebugPrintf(
+ "NOT NULL strength reduction converts the following to %d:\n",
+ pExpr->op==TK_NOTNULL
+ );
+ sqlite3ShowExpr(pExpr);
+ }
+#endif /* TREETRACE_ENABLED */
+ pExpr->u.iValue = (pExpr->op==TK_NOTNULL);
+ pExpr->flags |= EP_IntValue;
+ pExpr->op = TK_INTEGER;
+ for(i=0, p=pNC; p && i<ArraySize(anRef); p=p->pNext, i++){
+ p->nRef = anRef[i];
+ }
+ sqlite3ExprDelete(pParse->db, pExpr->pLeft);
+ pExpr->pLeft = 0;
return WRC_Prune;
}
@@ -108019,7 +108188,9 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
}
if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort;
}
+ sNC.ncFlags |= NC_Where;
if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort;
+ sNC.ncFlags &= ~NC_Where;
/* Resolve names in table-valued-function arguments */
for(i=0; i<p->pSrc->nSrc; i++){
@@ -108558,9 +108729,10 @@ SQLITE_PRIVATE Expr *sqlite3ExprSkipCollateAndLikely(Expr *pExpr){
assert( pExpr->x.pList->nExpr>0 );
assert( pExpr->op==TK_FUNCTION );
pExpr = pExpr->x.pList->a[0].pExpr;
- }else{
- assert( pExpr->op==TK_COLLATE );
+ }else if( pExpr->op==TK_COLLATE ){
pExpr = pExpr->pLeft;
+ }else{
+ break;
}
}
return pExpr;
@@ -111079,9 +111251,12 @@ SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr *p){
return 0;
case TK_COLUMN:
assert( ExprUseYTab(p) );
- return ExprHasProperty(p, EP_CanBeNull) ||
- NEVER(p->y.pTab==0) || /* Reference to column of index on expr */
- (p->iColumn>=0
+ return ExprHasProperty(p, EP_CanBeNull)
+ || NEVER(p->y.pTab==0) /* Reference to column of index on expr */
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
+ || (p->iColumn==XN_ROWID && IsView(p->y.pTab))
+#endif
+ || (p->iColumn>=0
&& p->y.pTab->aCol!=0 /* Possible due to prior error */
&& ALWAYS(p->iColumn<p->y.pTab->nCol)
&& p->y.pTab->aCol[p->iColumn].notNull==0);
@@ -123572,9 +123747,12 @@ SQLITE_PRIVATE void sqlite3CreateView(
** on a view, even though views do not have rowids. The following flag
** setting fixes this problem. But the fix can be disabled by compiling
** with -DSQLITE_ALLOW_ROWID_IN_VIEW in case there are legacy apps that
- ** depend upon the old buggy behavior. */
-#ifndef SQLITE_ALLOW_ROWID_IN_VIEW
- p->tabFlags |= TF_NoVisibleRowid;
+ ** depend upon the old buggy behavior. The ability can also be toggled
+ ** using sqlite3_config(SQLITE_CONFIG_ROWID_IN_VIEW,...) */
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
+ p->tabFlags |= sqlite3Config.mNoVisibleRowid; /* Optional. Allow by default */
+#else
+ p->tabFlags |= TF_NoVisibleRowid; /* Never allow rowid in view */
#endif
sqlite3TwoPartName(pParse, pName1, pName2, &pName);
@@ -128947,13 +129125,13 @@ SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue){
double r1, r2;
const char *zVal;
r1 = sqlite3_value_double(pValue);
- sqlite3_str_appendf(pStr, "%!.15g", r1);
+ sqlite3_str_appendf(pStr, "%!0.15g", r1);
zVal = sqlite3_str_value(pStr);
if( zVal ){
sqlite3AtoF(zVal, &r2, pStr->nChar, SQLITE_UTF8);
if( r1!=r2 ){
sqlite3_str_reset(pStr);
- sqlite3_str_appendf(pStr, "%!.20e", r1);
+ sqlite3_str_appendf(pStr, "%!0.20e", r1);
}
}
break;
@@ -129255,7 +129433,7 @@ static void replaceFunc(
}
if( zPattern[0]==0 ){
assert( sqlite3_value_type(argv[1])!=SQLITE_NULL );
- sqlite3_result_value(context, argv[0]);
+ sqlite3_result_text(context, (const char*)zStr, nStr, SQLITE_TRANSIENT);
return;
}
nPattern = sqlite3_value_bytes(argv[1]);
@@ -129738,7 +129916,7 @@ static void sumFinalize(sqlite3_context *context){
if( p->approx ){
if( p->ovrfl ){
sqlite3_result_error(context,"integer overflow",-1);
- }else if( !sqlite3IsNaN(p->rErr) ){
+ }else if( !sqlite3IsOverflow(p->rErr) ){
sqlite3_result_double(context, p->rSum+p->rErr);
}else{
sqlite3_result_double(context, p->rSum);
@@ -129755,7 +129933,7 @@ static void avgFinalize(sqlite3_context *context){
double r;
if( p->approx ){
r = p->rSum;
- if( !sqlite3IsNaN(p->rErr) ) r += p->rErr;
+ if( !sqlite3IsOverflow(p->rErr) ) r += p->rErr;
}else{
r = (double)(p->iSum);
}
@@ -129769,7 +129947,7 @@ static void totalFinalize(sqlite3_context *context){
if( p ){
if( p->approx ){
r = p->rSum;
- if( !sqlite3IsNaN(p->rErr) ) r += p->rErr;
+ if( !sqlite3IsOverflow(p->rErr) ) r += p->rErr;
}else{
r = (double)(p->iSum);
}
@@ -133175,7 +133353,7 @@ SQLITE_PRIVATE void sqlite3Insert(
pNx->iDataCur = iDataCur;
pNx->iIdxCur = iIdxCur;
if( pNx->pUpsertTarget ){
- if( sqlite3UpsertAnalyzeTarget(pParse, pTabList, pNx) ){
+ if( sqlite3UpsertAnalyzeTarget(pParse, pTabList, pNx, pUpsert) ){
goto insert_cleanup;
}
}
@@ -135067,7 +135245,10 @@ static int xferOptimization(
}
}
#ifndef SQLITE_OMIT_CHECK
- if( pDest->pCheck && sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1) ){
+ if( pDest->pCheck
+ && (db->mDbFlags & DBFLAG_Vacuum)==0
+ && sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1)
+ ){
return 0; /* Tables have different CHECK constraints. Ticket #2252 */
}
#endif
@@ -139474,31 +139655,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
int mxCol; /* Maximum non-virtual column number */
if( pObjTab && pObjTab!=pTab ) continue;
- if( !IsOrdinaryTable(pTab) ){
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- sqlite3_vtab *pVTab;
- int a1;
- if( !IsVirtual(pTab) ) continue;
- if( pTab->nCol<=0 ){
- const char *zMod = pTab->u.vtab.azArg[0];
- if( sqlite3HashFind(&db->aModule, zMod)==0 ) continue;
- }
- sqlite3ViewGetColumnNames(pParse, pTab);
- if( pTab->u.vtab.p==0 ) continue;
- pVTab = pTab->u.vtab.p->pVtab;
- if( NEVER(pVTab==0) ) continue;
- if( NEVER(pVTab->pModule==0) ) continue;
- if( pVTab->pModule->iVersion<4 ) continue;
- if( pVTab->pModule->xIntegrity==0 ) continue;
- sqlite3VdbeAddOp3(v, OP_VCheck, i, 3, isQuick);
- pTab->nTabRef++;
- sqlite3VdbeAppendP4(v, pTab, P4_TABLEREF);
- a1 = sqlite3VdbeAddOp1(v, OP_IsNull, 3); VdbeCoverage(v);
- integrityCheckResultRow(v);
- sqlite3VdbeJumpHere(v, a1);
-#endif
- continue;
- }
+ if( !IsOrdinaryTable(pTab) ) continue;
if( isQuick || HasRowid(pTab) ){
pPk = 0;
r2 = 0;
@@ -139633,6 +139790,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
** is REAL, we have to load the actual data using OP_Column
** to reliably determine if the value is a NULL. */
sqlite3VdbeAddOp3(v, OP_Column, p1, p3, 3);
+ sqlite3ColumnDefault(v, pTab, j, 3);
jmp3 = sqlite3VdbeAddOp2(v, OP_NotNull, 3, labelOk);
VdbeCoverage(v);
}
@@ -139823,6 +139981,38 @@ SQLITE_PRIVATE void sqlite3Pragma(
}
}
}
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ /* Second pass to invoke the xIntegrity method on all virtual
+ ** tables.
+ */
+ for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
+ Table *pTab = sqliteHashData(x);
+ sqlite3_vtab *pVTab;
+ int a1;
+ if( pObjTab && pObjTab!=pTab ) continue;
+ if( IsOrdinaryTable(pTab) ) continue;
+ if( !IsVirtual(pTab) ) continue;
+ if( pTab->nCol<=0 ){
+ const char *zMod = pTab->u.vtab.azArg[0];
+ if( sqlite3HashFind(&db->aModule, zMod)==0 ) continue;
+ }
+ sqlite3ViewGetColumnNames(pParse, pTab);
+ if( pTab->u.vtab.p==0 ) continue;
+ pVTab = pTab->u.vtab.p->pVtab;
+ if( NEVER(pVTab==0) ) continue;
+ if( NEVER(pVTab->pModule==0) ) continue;
+ if( pVTab->pModule->iVersion<4 ) continue;
+ if( pVTab->pModule->xIntegrity==0 ) continue;
+ sqlite3VdbeAddOp3(v, OP_VCheck, i, 3, isQuick);
+ pTab->nTabRef++;
+ sqlite3VdbeAppendP4(v, pTab, P4_TABLEREF);
+ a1 = sqlite3VdbeAddOp1(v, OP_IsNull, 3); VdbeCoverage(v);
+ integrityCheckResultRow(v);
+ sqlite3VdbeJumpHere(v, a1);
+ continue;
+ }
+#endif
}
{
static const int iLn = VDBE_OFFSET_LINENO(2);
@@ -140459,7 +140649,11 @@ static int pragmaVtabBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
j = seen[0]-1;
pIdxInfo->aConstraintUsage[j].argvIndex = 1;
pIdxInfo->aConstraintUsage[j].omit = 1;
- if( seen[1]==0 ) return SQLITE_OK;
+ if( seen[1]==0 ){
+ pIdxInfo->estimatedCost = (double)1000;
+ pIdxInfo->estimatedRows = 1000;
+ return SQLITE_OK;
+ }
pIdxInfo->estimatedCost = (double)20;
pIdxInfo->estimatedRows = 20;
j = seen[1]-1;
@@ -143686,11 +143880,7 @@ static const char *columnTypeImpl(
** data for the result-set column of the sub-select.
*/
if( iCol<pS->pEList->nExpr
-#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
- && iCol>=0
-#else
- && ALWAYS(iCol>=0)
-#endif
+ && (!ViewCanHaveRowid || iCol>=0)
){
/* If iCol is less than zero, then the expression requests the
** rowid of the sub-select or view. This expression is legal (see
@@ -146865,6 +147055,10 @@ static int pushDownWindowCheck(Parse *pParse, Select *pSubq, Expr *pExpr){
**
** (11) The subquery is not a VALUES clause
**
+** (12) The WHERE clause is not "rowid ISNULL" or the equivalent. This
+** case only comes up if SQLite is compiled using
+** SQLITE_ALLOW_ROWID_IN_VIEW.
+**
** Return 0 if no changes are made and non-zero if one or more WHERE clause
** terms are duplicated into the subquery.
*/
@@ -146975,6 +147169,18 @@ static int pushDownWhereTerms(
}
#endif
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
+ if( ViewCanHaveRowid && (pWhere->op==TK_ISNULL || pWhere->op==TK_NOTNULL) ){
+ Expr *pLeft = pWhere->pLeft;
+ if( ALWAYS(pLeft)
+ && pLeft->op==TK_COLUMN
+ && pLeft->iColumn < 0
+ ){
+ return 0; /* Restriction (12) */
+ }
+ }
+#endif
+
if( sqlite3ExprIsSingleTableConstraint(pWhere, pSrcList, iSrc) ){
nChng++;
pSubq->selFlags |= SF_PushDown;
@@ -147602,12 +147808,14 @@ SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse *pParse, SrcItem *pFrom){
while( pSel->pPrior ){ pSel = pSel->pPrior; }
sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol);
pTab->iPKey = -1;
+ pTab->eTabType = TABTYP_VIEW;
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
#ifndef SQLITE_ALLOW_ROWID_IN_VIEW
/* The usual case - do not allow ROWID on a subquery */
pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid;
#else
- pTab->tabFlags |= TF_Ephemeral; /* Legacy compatibility mode */
+ /* Legacy compatibility mode */
+ pTab->tabFlags |= TF_Ephemeral | sqlite3Config.mNoVisibleRowid;
#endif
return pParse->nErr ? SQLITE_ERROR : SQLITE_OK;
}
@@ -147875,7 +148083,7 @@ static int selectExpander(Walker *pWalker, Select *p){
pNestedFrom = pFrom->pSelect->pEList;
assert( pNestedFrom!=0 );
assert( pNestedFrom->nExpr==pTab->nCol );
- assert( VisibleRowid(pTab)==0 );
+ assert( VisibleRowid(pTab)==0 || ViewCanHaveRowid );
}else{
if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
continue;
@@ -147907,7 +148115,8 @@ static int selectExpander(Walker *pWalker, Select *p){
pUsing = 0;
}
- nAdd = pTab->nCol + (VisibleRowid(pTab) && (selFlags&SF_NestedFrom));
+ nAdd = pTab->nCol;
+ if( VisibleRowid(pTab) && (selFlags & SF_NestedFrom)!=0 ) nAdd++;
for(j=0; j<nAdd; j++){
const char *zName;
struct ExprList_item *pX; /* Newly added ExprList term */
@@ -147989,7 +148198,8 @@ static int selectExpander(Walker *pWalker, Select *p){
pX = &pNew->a[pNew->nExpr-1];
assert( pX->zEName==0 );
if( (selFlags & SF_NestedFrom)!=0 && !IN_RENAME_OBJECT ){
- if( pNestedFrom ){
+ if( pNestedFrom && (!ViewCanHaveRowid || j<pNestedFrom->nExpr) ){
+ assert( j<pNestedFrom->nExpr );
pX->zEName = sqlite3DbStrDup(db, pNestedFrom->a[j].zEName);
testcase( pX->zEName==0 );
}else{
@@ -152923,6 +153133,9 @@ SQLITE_PRIVATE void sqlite3Update(
}
}
if( chngRowid==0 && pPk==0 ){
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
+ if( isView ) sqlite3VdbeAddOp2(v, OP_Null, 0, regOldRowid);
+#endif
sqlite3VdbeAddOp2(v, OP_Copy, regOldRowid, regNewRowid);
}
}
@@ -153460,7 +153673,8 @@ SQLITE_PRIVATE Upsert *sqlite3UpsertNew(
SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget(
Parse *pParse, /* The parsing context */
SrcList *pTabList, /* Table into which we are inserting */
- Upsert *pUpsert /* The ON CONFLICT clauses */
+ Upsert *pUpsert, /* The ON CONFLICT clauses */
+ Upsert *pAll /* Complete list of all ON CONFLICT clauses */
){
Table *pTab; /* That table into which we are inserting */
int rc; /* Result code */
@@ -153563,6 +153777,14 @@ SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget(
continue;
}
pUpsert->pUpsertIdx = pIdx;
+ if( sqlite3UpsertOfIndex(pAll,pIdx)!=pUpsert ){
+ /* Really this should be an error. The isDup ON CONFLICT clause will
+ ** never fire. But this problem was not discovered until three years
+ ** after multi-CONFLICT upsert was added, and so we silently ignore
+ ** the problem to prevent breaking applications that might actually
+ ** have redundant ON CONFLICT clauses. */
+ pUpsert->isDup = 1;
+ }
break;
}
if( pUpsert->pUpsertIdx==0 ){
@@ -153589,9 +153811,13 @@ SQLITE_PRIVATE int sqlite3UpsertNextIsIPK(Upsert *pUpsert){
Upsert *pNext;
if( NEVER(pUpsert==0) ) return 0;
pNext = pUpsert->pNextUpsert;
- if( pNext==0 ) return 1;
- if( pNext->pUpsertTarget==0 ) return 1;
- if( pNext->pUpsertIdx==0 ) return 1;
+ while( 1 /*exit-by-return*/ ){
+ if( pNext==0 ) return 1;
+ if( pNext->pUpsertTarget==0 ) return 1;
+ if( pNext->pUpsertIdx==0 ) return 1;
+ if( !pNext->isDup ) return 0;
+ pNext = pNext->pNextUpsert;
+ }
return 0;
}
@@ -166619,16 +166845,10 @@ static SQLITE_NOINLINE void whereAddIndexedExpr(
for(i=0; i<pIdx->nColumn; i++){
Expr *pExpr;
int j = pIdx->aiColumn[i];
- int bMaybeNullRow;
if( j==XN_EXPR ){
pExpr = pIdx->aColExpr->a[i].pExpr;
- testcase( pTabItem->fg.jointype & JT_LEFT );
- testcase( pTabItem->fg.jointype & JT_RIGHT );
- testcase( pTabItem->fg.jointype & JT_LTORJ );
- bMaybeNullRow = (pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0;
}else if( j>=0 && (pTab->aCol[j].colFlags & COLFLAG_VIRTUAL)!=0 ){
pExpr = sqlite3ColumnExpr(pTab, &pTab->aCol[j]);
- bMaybeNullRow = 0;
}else{
continue;
}
@@ -166660,7 +166880,7 @@ static SQLITE_NOINLINE void whereAddIndexedExpr(
p->iDataCur = pTabItem->iCursor;
p->iIdxCur = iIdxCur;
p->iIdxCol = i;
- p->bMaybeNullRow = bMaybeNullRow;
+ p->bMaybeNullRow = (pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0;
if( sqlite3IndexAffinityStr(pParse->db, pIdx) ){
p->aff = pIdx->zColAff[i];
}
@@ -178865,6 +179085,18 @@ SQLITE_API int sqlite3_config(int op, ...){
}
#endif /* SQLITE_OMIT_DESERIALIZE */
+ case SQLITE_CONFIG_ROWID_IN_VIEW: {
+ int *pVal = va_arg(ap,int*);
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
+ if( 0==*pVal ) sqlite3GlobalConfig.mNoVisibleRowid = TF_NoVisibleRowid;
+ if( 1==*pVal ) sqlite3GlobalConfig.mNoVisibleRowid = 0;
+ *pVal = (sqlite3GlobalConfig.mNoVisibleRowid==0);
+#else
+ *pVal = 0;
+#endif
+ break;
+ }
+
default: {
rc = SQLITE_ERROR;
break;
@@ -204785,6 +205017,7 @@ json_parse_restart:
case '[': {
/* Parse array */
iThis = pParse->nBlob;
+ assert( i<=(u32)pParse->nJson );
jsonBlobAppendNode(pParse, JSONB_ARRAY, pParse->nJson - i, 0);
iStart = pParse->nBlob;
if( pParse->oom ) return -1;
@@ -205183,6 +205416,10 @@ static void jsonReturnStringAsBlob(JsonString *pStr){
JsonParse px;
memset(&px, 0, sizeof(px));
jsonStringTerminate(pStr);
+ if( pStr->eErr ){
+ sqlite3_result_error_nomem(pStr->pCtx);
+ return;
+ }
px.zJson = pStr->zBuf;
px.nJson = pStr->nUsed;
px.db = sqlite3_context_db_handle(pStr->pCtx);
@@ -206508,8 +206745,9 @@ rebuild_from_cache:
}
p->zJson = (char*)sqlite3_value_text(pArg);
p->nJson = sqlite3_value_bytes(pArg);
+ if( db->mallocFailed ) goto json_pfa_oom;
if( p->nJson==0 ) goto json_pfa_malformed;
- if( NEVER(p->zJson==0) ) goto json_pfa_oom;
+ assert( p->zJson!=0 );
if( jsonConvertTextToBlob(p, (flgs & JSON_KEEPERROR) ? 0 : ctx) ){
if( flgs & JSON_KEEPERROR ){
p->nErr = 1;
@@ -206675,10 +206913,10 @@ static void jsonDebugPrintBlob(
if( sz==0 && x<=JSONB_FALSE ){
sqlite3_str_append(pOut, "\n", 1);
}else{
- u32 i;
+ u32 j;
sqlite3_str_appendall(pOut, ": \"");
- for(i=iStart+n; i<iStart+n+sz; i++){
- u8 c = pParse->aBlob[i];
+ for(j=iStart+n; j<iStart+n+sz; j++){
+ u8 c = pParse->aBlob[j];
if( c<0x20 || c>=0x7f ) c = '.';
sqlite3_str_append(pOut, (char*)&c, 1);
}
@@ -208086,6 +208324,9 @@ static int jsonEachColumn(
case JEACH_VALUE: {
u32 i = jsonSkipLabel(p);
jsonReturnFromBlob(&p->sParse, i, ctx, 1);
+ if( (p->sParse.aBlob[i] & 0x0f)>=JSONB_ARRAY ){
+ sqlite3_result_subtype(ctx, JSON_SUBTYPE);
+ }
break;
}
case JEACH_TYPE: {
@@ -208132,9 +208373,9 @@ static int jsonEachColumn(
case JEACH_JSON: {
if( p->sParse.zJson==0 ){
sqlite3_result_blob(ctx, p->sParse.aBlob, p->sParse.nBlob,
- SQLITE_STATIC);
+ SQLITE_TRANSIENT);
}else{
- sqlite3_result_text(ctx, p->sParse.zJson, -1, SQLITE_STATIC);
+ sqlite3_result_text(ctx, p->sParse.zJson, -1, SQLITE_TRANSIENT);
}
break;
}
@@ -209160,11 +209401,9 @@ static RtreeNode *nodeNew(Rtree *pRtree, RtreeNode *pParent){
** Clear the Rtree.pNodeBlob object
*/
static void nodeBlobReset(Rtree *pRtree){
- if( pRtree->pNodeBlob && pRtree->inWrTrans==0 && pRtree->nCursor==0 ){
- sqlite3_blob *pBlob = pRtree->pNodeBlob;
- pRtree->pNodeBlob = 0;
- sqlite3_blob_close(pBlob);
- }
+ sqlite3_blob *pBlob = pRtree->pNodeBlob;
+ pRtree->pNodeBlob = 0;
+ sqlite3_blob_close(pBlob);
}
/*
@@ -209208,7 +209447,6 @@ static int nodeAcquire(
&pRtree->pNodeBlob);
}
if( rc ){
- nodeBlobReset(pRtree);
*ppNode = 0;
/* If unable to open an sqlite3_blob on the desired row, that can only
** be because the shadow tables hold erroneous data. */
@@ -209268,6 +209506,7 @@ static int nodeAcquire(
}
*ppNode = pNode;
}else{
+ nodeBlobReset(pRtree);
if( pNode ){
pRtree->nNodeRef--;
sqlite3_free(pNode);
@@ -209412,6 +209651,7 @@ static void nodeGetCoord(
int iCoord, /* Which coordinate to extract */
RtreeCoord *pCoord /* OUT: Space to write result to */
){
+ assert( iCell<NCELL(pNode) );
readCoord(&pNode->zData[12 + pRtree->nBytesPerCell*iCell + 4*iCoord], pCoord);
}
@@ -209601,7 +209841,9 @@ static int rtreeClose(sqlite3_vtab_cursor *cur){
sqlite3_finalize(pCsr->pReadAux);
sqlite3_free(pCsr);
pRtree->nCursor--;
- nodeBlobReset(pRtree);
+ if( pRtree->nCursor==0 && pRtree->inWrTrans==0 ){
+ nodeBlobReset(pRtree);
+ }
return SQLITE_OK;
}
@@ -210186,7 +210428,11 @@ static int rtreeRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *pRowid){
int rc = SQLITE_OK;
RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc);
if( rc==SQLITE_OK && ALWAYS(p) ){
- *pRowid = nodeGetRowid(RTREE_OF_CURSOR(pCsr), pNode, p->iCell);
+ if( p->iCell>=NCELL(pNode) ){
+ rc = SQLITE_ABORT;
+ }else{
+ *pRowid = nodeGetRowid(RTREE_OF_CURSOR(pCsr), pNode, p->iCell);
+ }
}
return rc;
}
@@ -210204,6 +210450,7 @@ static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
if( rc ) return rc;
if( NEVER(p==0) ) return SQLITE_OK;
+ if( p->iCell>=NCELL(pNode) ) return SQLITE_ABORT;
if( i==0 ){
sqlite3_result_int64(ctx, nodeGetRowid(pRtree, pNode, p->iCell));
}else if( i<=pRtree->nDim2 ){
@@ -211685,8 +211932,7 @@ constraint:
*/
static int rtreeBeginTransaction(sqlite3_vtab *pVtab){
Rtree *pRtree = (Rtree *)pVtab;
- assert( pRtree->inWrTrans==0 );
- pRtree->inWrTrans++;
+ pRtree->inWrTrans = 1;
return SQLITE_OK;
}
@@ -211700,6 +211946,9 @@ static int rtreeEndTransaction(sqlite3_vtab *pVtab){
nodeBlobReset(pRtree);
return SQLITE_OK;
}
+static int rtreeRollback(sqlite3_vtab *pVtab){
+ return rtreeEndTransaction(pVtab);
+}
/*
** The xRename method for rtree module virtual tables.
@@ -211818,7 +212067,7 @@ static sqlite3_module rtreeModule = {
rtreeBeginTransaction, /* xBegin - begin transaction */
rtreeEndTransaction, /* xSync - sync transaction */
rtreeEndTransaction, /* xCommit - commit transaction */
- rtreeEndTransaction, /* xRollback - rollback transaction */
+ rtreeRollback, /* xRollback - rollback transaction */
0, /* xFindFunction - function overloading */
rtreeRename, /* xRename - rename the table */
rtreeSavepoint, /* xSavepoint */
@@ -245377,23 +245626,26 @@ static void fts5IterSetOutputsTokendata(Fts5Iter *pIter){
static void fts5TokendataIterNext(Fts5Iter *pIter, int bFrom, i64 iFrom){
int ii;
Fts5TokenDataIter *pT = pIter->pTokenDataIter;
+ Fts5Index *pIndex = pIter->pIndex;
for(ii=0; ii<pT->nIter; ii++){
Fts5Iter *p = pT->apIter[ii];
if( p->base.bEof==0
&& (p->base.iRowid==pIter->base.iRowid || (bFrom && p->base.iRowid<iFrom))
){
- fts5MultiIterNext(p->pIndex, p, bFrom, iFrom);
+ fts5MultiIterNext(pIndex, p, bFrom, iFrom);
while( bFrom && p->base.bEof==0
&& p->base.iRowid<iFrom
- && p->pIndex->rc==SQLITE_OK
+ && pIndex->rc==SQLITE_OK
){
- fts5MultiIterNext(p->pIndex, p, 0, 0);
+ fts5MultiIterNext(pIndex, p, 0, 0);
}
}
}
- fts5IterSetOutputsTokendata(pIter);
+ if( pIndex->rc==SQLITE_OK ){
+ fts5IterSetOutputsTokendata(pIter);
+ }
}
/*
@@ -250547,7 +250799,7 @@ static void fts5SourceIdFunc(
){
assert( nArg==0 );
UNUSED_PARAM2(nArg, apUnused);
- sqlite3_result_text(pCtx, "fts5: 2024-01-30 16:01:20 e876e51a0ed5c5b3126f52e532044363a014bc594cfefa87ffb5b82257cc467a", -1, SQLITE_TRANSIENT);
+ sqlite3_result_text(pCtx, "fts5: 2024-04-15 13:34:05 8653b758870e6ef0c98d46b3ace27849054af85da891eb121e9aaa537f1e8355", -1, SQLITE_TRANSIENT);
}
/*
diff --git a/src/libs/3rdparty/sqlite/sqlite3.h b/src/libs/3rdparty/sqlite/sqlite3.h
index 4fdfde004e..2618b37a7b 100644
--- a/src/libs/3rdparty/sqlite/sqlite3.h
+++ b/src/libs/3rdparty/sqlite/sqlite3.h
@@ -146,9 +146,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.45.1"
-#define SQLITE_VERSION_NUMBER 3045001
-#define SQLITE_SOURCE_ID "2024-01-30 16:01:20 e876e51a0ed5c5b3126f52e532044363a014bc594cfefa87ffb5b82257cc467a"
+#define SQLITE_VERSION "3.45.3"
+#define SQLITE_VERSION_NUMBER 3045003
+#define SQLITE_SOURCE_ID "2024-04-15 13:34:05 8653b758870e6ef0c98d46b3ace27849054af85da891eb121e9aaa537f1e8355"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -420,6 +420,8 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
** the 1st parameter to sqlite3_exec() while sqlite3_exec() is running.
** <li> The application must not modify the SQL statement text passed into
** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running.
+** <li> The application must not dereference the arrays or string pointers
+** passed as the 3rd and 4th callback parameters after it returns.
** </ul>
*/
SQLITE_API int sqlite3_exec(
@@ -2141,6 +2143,22 @@ struct sqlite3_mem_methods {
** configuration setting is never used, then the default maximum is determined
** by the [SQLITE_MEMDB_DEFAULT_MAXSIZE] compile-time option. If that
** compile-time option is not set, then the default maximum is 1073741824.
+**
+** [[SQLITE_CONFIG_ROWID_IN_VIEW]]
+** <dt>SQLITE_CONFIG_ROWID_IN_VIEW
+** <dd>The SQLITE_CONFIG_ROWID_IN_VIEW option enables or disables the ability
+** for VIEWs to have a ROWID. The capability can only be enabled if SQLite is
+** compiled with -DSQLITE_ALLOW_ROWID_IN_VIEW, in which case the capability
+** defaults to on. This configuration option queries the current setting or
+** changes the setting to off or on. The argument is a pointer to an integer.
+** If that integer initially holds a value of 1, then the ability for VIEWs to
+** have ROWIDs is activated. If the integer initially holds zero, then the
+** ability is deactivated. Any other initial value for the integer leaves the
+** setting unchanged. After changes, if any, the integer is written with
+** a 1 or 0, if the ability for VIEWs to have ROWIDs is on or off. If SQLite
+** is compiled without -DSQLITE_ALLOW_ROWID_IN_VIEW (which is the usual and
+** recommended case) then the integer is always filled with zero, regardless
+** if its initial value.
** </dl>
*/
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
@@ -2172,6 +2190,7 @@ struct sqlite3_mem_methods {
#define SQLITE_CONFIG_SMALL_MALLOC 27 /* boolean */
#define SQLITE_CONFIG_SORTERREF_SIZE 28 /* int nByte */
#define SQLITE_CONFIG_MEMDB_MAXSIZE 29 /* sqlite3_int64 */
+#define SQLITE_CONFIG_ROWID_IN_VIEW 30 /* int* */
/*
** CAPI3REF: Database Connection Configuration Options
diff --git a/src/libs/languageutils/componentversion.cpp b/src/libs/languageutils/componentversion.cpp
index 6c599e300b..f041740d3b 100644
--- a/src/libs/languageutils/componentversion.cpp
+++ b/src/libs/languageutils/componentversion.cpp
@@ -10,27 +10,17 @@
namespace LanguageUtils {
-const int ComponentVersion::NoVersion = -1;
-const int ComponentVersion::MaxVersion = std::numeric_limits<int>::max();
+// QTC_TEMP
-ComponentVersion::ComponentVersion()
- : _major(NoVersion), _minor(NoVersion)
+ComponentVersion::ComponentVersion(QStringView versionString)
+ : _major(NoVersion)
+ , _minor(NoVersion)
{
-}
-
-ComponentVersion::ComponentVersion(int major, int minor)
- : _major(major), _minor(minor)
-{
-}
-
-ComponentVersion::ComponentVersion(const QString &versionString)
- : _major(NoVersion), _minor(NoVersion)
-{
- int dotIdx = versionString.indexOf(QLatin1Char('.'));
+ auto dotIdx = versionString.indexOf(QLatin1Char('.'));
if (dotIdx == -1)
return;
bool ok = false;
- int maybeMajor = versionString.left(dotIdx).toInt(&ok);
+ auto maybeMajor = versionString.left(dotIdx).toInt(&ok);
if (!ok)
return;
int maybeMinor = versionString.mid(dotIdx + 1).toInt(&ok);
@@ -40,15 +30,6 @@ ComponentVersion::ComponentVersion(const QString &versionString)
_minor = maybeMinor;
}
-ComponentVersion::~ComponentVersion()
-{
-}
-
-bool ComponentVersion::isValid() const
-{
- return _major >= 0 && _minor >= 0;
-}
-
QString ComponentVersion::toString() const
{
QByteArray temp;
@@ -65,36 +46,4 @@ void ComponentVersion::addToHash(QCryptographicHash &hash) const
hash.addData(reinterpret_cast<const char *>(&_minor), sizeof(_minor));
}
-bool operator<(const ComponentVersion &lhs, const ComponentVersion &rhs)
-{
- return lhs.majorVersion() < rhs.majorVersion()
- || (lhs.majorVersion() == rhs.majorVersion() && lhs.minorVersion() < rhs.minorVersion());
-}
-
-bool operator<=(const ComponentVersion &lhs, const ComponentVersion &rhs)
-{
- return lhs.majorVersion() < rhs.majorVersion()
- || (lhs.majorVersion() == rhs.majorVersion() && lhs.minorVersion() <= rhs.minorVersion());
-}
-
-bool operator>(const ComponentVersion &lhs, const ComponentVersion &rhs)
-{
- return rhs < lhs;
-}
-
-bool operator>=(const ComponentVersion &lhs, const ComponentVersion &rhs)
-{
- return rhs <= lhs;
-}
-
-bool operator==(const ComponentVersion &lhs, const ComponentVersion &rhs)
-{
- return lhs.majorVersion() == rhs.majorVersion() && lhs.minorVersion() == rhs.minorVersion();
-}
-
-bool operator!=(const ComponentVersion &lhs, const ComponentVersion &rhs)
-{
- return !(lhs == rhs);
-}
-
} // namespace LanguageUtils
diff --git a/src/libs/languageutils/componentversion.h b/src/libs/languageutils/componentversion.h
index 4b39e8402a..2b8311a6cb 100644
--- a/src/libs/languageutils/componentversion.h
+++ b/src/libs/languageutils/componentversion.h
@@ -9,6 +9,10 @@ QT_BEGIN_NAMESPACE
class QCryptographicHash;
QT_END_NAMESPACE
+#include <QStringView>
+
+#include <limits>
+
namespace LanguageUtils {
class LANGUAGEUTILS_EXPORT ComponentVersion
@@ -17,25 +21,56 @@ class LANGUAGEUTILS_EXPORT ComponentVersion
int _minor;
public:
- static const int NoVersion;
- static const int MaxVersion;
+ static constexpr int NoVersion = -1;
+ static constexpr int MaxVersion = std::numeric_limits<int>::max();
+
+ ComponentVersion()
+ : _major(NoVersion)
+ , _minor(NoVersion)
+ {}
- ComponentVersion();
- ComponentVersion(int major, int minor);
- explicit ComponentVersion(const QString &versionString);
- ~ComponentVersion();
+ ComponentVersion(int major, int minor)
+ : _major(major)
+ , _minor(minor)
+ {}
+
+ explicit ComponentVersion(QStringView versionString);
+ ~ComponentVersion() = default;
int majorVersion() const { return _major; }
int minorVersion() const { return _minor; }
- friend bool LANGUAGEUTILS_EXPORT operator<(const ComponentVersion &lhs, const ComponentVersion &rhs);
- friend bool LANGUAGEUTILS_EXPORT operator<=(const ComponentVersion &lhs, const ComponentVersion &rhs);
- friend bool LANGUAGEUTILS_EXPORT operator>(const ComponentVersion &lhs, const ComponentVersion &rhs);
- friend bool LANGUAGEUTILS_EXPORT operator>=(const ComponentVersion &lhs, const ComponentVersion &rhs);
- friend bool LANGUAGEUTILS_EXPORT operator==(const ComponentVersion &lhs, const ComponentVersion &rhs);
- friend bool LANGUAGEUTILS_EXPORT operator!=(const ComponentVersion &lhs, const ComponentVersion &rhs);
+ friend bool operator<(const ComponentVersion &lhs, const ComponentVersion &rhs)
+ {
+ return std::tie(lhs._major, lhs._minor) < std::tie(rhs._major, rhs._minor);
+ }
+
+ friend bool operator<=(const ComponentVersion &lhs, const ComponentVersion &rhs)
+ {
+ return std::tie(lhs._major, lhs._minor) <= std::tie(rhs._major, rhs._minor);
+ }
+
+ friend bool operator>(const ComponentVersion &lhs, const ComponentVersion &rhs)
+ {
+ return rhs < lhs;
+ }
+
+ friend bool operator>=(const ComponentVersion &lhs, const ComponentVersion &rhs)
+ {
+ return rhs <= lhs;
+ }
+
+ friend bool operator==(const ComponentVersion &lhs, const ComponentVersion &rhs)
+ {
+ return lhs.majorVersion() == rhs.majorVersion() && lhs.minorVersion() == rhs.minorVersion();
+ }
+
+ friend bool operator!=(const ComponentVersion &lhs, const ComponentVersion &rhs)
+ {
+ return !(lhs == rhs);
+ }
- bool isValid() const;
+ bool isValid() const { return _major >= 0 && _minor >= 0; }
QString toString() const;
void addToHash(QCryptographicHash &hash) const;
};
diff --git a/src/libs/nanotrace/CMakeLists.txt b/src/libs/nanotrace/CMakeLists.txt
index 011c26f049..50693644ea 100644
--- a/src/libs/nanotrace/CMakeLists.txt
+++ b/src/libs/nanotrace/CMakeLists.txt
@@ -4,6 +4,7 @@ add_qtc_library(Nanotrace
nanotraceglobals.h
nanotrace.cpp nanotrace.h
nanotracehr.cpp nanotracehr.h
+ staticstring.h
PUBLIC_DEPENDS Qt::Core Qt::Gui
PROPERTIES
CXX_VISIBILITY_PRESET default
diff --git a/src/libs/nanotrace/nanotracehr.cpp b/src/libs/nanotrace/nanotracehr.cpp
index 07d2ff95ac..0006227434 100644
--- a/src/libs/nanotrace/nanotracehr.cpp
+++ b/src/libs/nanotrace/nanotracehr.cpp
@@ -45,6 +45,18 @@ unsigned int getUnsignedIntegerHash(std::thread::id id)
return static_cast<unsigned int>(std::hash<std::thread::id>{}(id) & 0xFFFFFFFF);
}
+template<std::size_t capacity>
+constexpr bool isArgumentValid(const StaticString<capacity> &string)
+{
+ return string.isValid() && string.size();
+}
+
+template<typename String>
+constexpr bool isArgumentValid(const String &string)
+{
+ return string.size();
+}
+
template<typename TraceEvent>
void printEvent(std::ostream &out, const TraceEvent &event, qint64 processId, std::thread::id threadId)
{
@@ -67,23 +79,24 @@ void printEvent(std::ostream &out, const TraceEvent &event, qint64 processId, st
out << R"(,"flow_in":true)";
}
- if (event.arguments.size())
+ if (isArgumentValid(event.arguments)) {
out << R"(,"args":)" << event.arguments;
+ }
out << "}";
}
-void writeMetaEvent(TraceFile<Tracing::IsEnabled> *file, std::string_view key, std::string_view value)
+void writeMetaEvent(TraceFile<Tracing::IsEnabled> &file, std::string_view key, std::string_view value)
{
- std::lock_guard lock{file->fileMutex};
- auto &out = file->out;
+ std::lock_guard lock{file.fileMutex};
+ auto &out = file.out;
if (out.is_open()) {
- file->out << R"({"name":")" << key << R"(","ph":"M", "pid":)"
- << getUnsignedIntegerHash(QCoreApplication::applicationPid()) << R"(,"tid":)"
- << getUnsignedIntegerHash(std::this_thread::get_id()) << R"(,"args":{"name":")"
- << value << R"("}})"
- << ",\n";
+ file.out << R"({"name":")" << key << R"(","ph":"M", "pid":)"
+ << getUnsignedIntegerHash(QCoreApplication::applicationPid()) << R"(,"tid":)"
+ << getUnsignedIntegerHash(std::this_thread::get_id()) << R"(,"args":{"name":")"
+ << value << R"("}})"
+ << ",\n";
}
}
@@ -103,7 +116,6 @@ std::string getThreadName()
} // namespace
-namespace Internal {
template<typename String>
void convertToString(String &string, const QImage &image)
{
@@ -132,14 +144,11 @@ void convertToString(String &string, const QImage &image)
return "alpha premultiplied"sv;
}))));
- Internal::convertToString(string, dict);
+ convertToString(string, dict);
}
-template NANOTRACE_EXPORT void convertToString(std::string &string, const QImage &image);
template NANOTRACE_EXPORT void convertToString(ArgumentsString &string, const QImage &image);
-} // namespace Internal
-
template<typename TraceEvent>
void flushEvents(const Utils::span<TraceEvent> events,
std::thread::id threadId,
@@ -148,8 +157,8 @@ void flushEvents(const Utils::span<TraceEvent> events,
if (events.empty())
return;
- std::lock_guard lock{eventQueue.file->fileMutex};
- auto &out = eventQueue.file->out;
+ std::lock_guard lock{eventQueue.file.fileMutex};
+ auto &out = eventQueue.file.out;
if (out.is_open()) {
auto processId = QCoreApplication::applicationPid();
@@ -200,17 +209,17 @@ void finalizeFile(EnabledTraceFile &file)
template<typename TraceEvent>
void flushInThread(EnabledEventQueue<TraceEvent> &eventQueue)
{
- if (eventQueue.file->processing.valid())
- eventQueue.file->processing.wait();
+ if (eventQueue.file.processing.valid())
+ eventQueue.file.processing.wait();
auto flush = [&](const Utils::span<TraceEvent> &events, std::thread::id threadId) {
flushEvents(events, threadId, eventQueue);
};
- eventQueue.file->processing = std::async(std::launch::async,
- flush,
- eventQueue.currentEvents.subspan(0, eventQueue.eventsIndex),
- eventQueue.threadId);
+ eventQueue.file.processing = std::async(std::launch::async,
+ flush,
+ eventQueue.currentEvents.subspan(0, eventQueue.eventsIndex),
+ eventQueue.threadId);
eventQueue.currentEvents = eventQueue.currentEvents.data() == eventQueue.eventsOne.data()
? eventQueue.eventsTwo
: eventQueue.eventsOne;
@@ -223,10 +232,11 @@ template NANOTRACE_EXPORT void flushInThread(
EnabledEventQueue<StringViewWithStringArgumentsTraceEvent> &eventQueue);
template<typename TraceEvent>
-EventQueue<TraceEvent, Tracing::IsEnabled>::EventQueue(EnabledTraceFile *file)
+EventQueue<TraceEvent, Tracing::IsEnabled>::EventQueue(EnabledTraceFile &file)
: file{file}
, threadId{std::this_thread::get_id()}
{
+ setEventsSpans(*eventArrayOne.get(), *eventArrayTwo.get());
Internal::EventQueueTracker<TraceEvent>::get().addQueue(this);
if (auto thread = QThread::currentThread()) {
auto name = getThreadName();
diff --git a/src/libs/nanotrace/nanotracehr.h b/src/libs/nanotrace/nanotracehr.h
index 7856ea3582..810e4e3c5d 100644
--- a/src/libs/nanotrace/nanotracehr.h
+++ b/src/libs/nanotrace/nanotracehr.h
@@ -5,16 +5,22 @@
#include "nanotraceglobals.h"
+#include "staticstring.h"
+
#include <utils/smallstring.h>
#include <utils/span.h>
#include <QByteArrayView>
+#include <QList>
+#include <QMap>
#include <QStringView>
+#include <QVarLengthArray>
#include <QVariant>
#include <array>
#include <atomic>
#include <chrono>
+#include <exception>
#include <fstream>
#include <future>
#include <mutex>
@@ -41,7 +47,7 @@ enum class Tracing { IsDisabled, IsEnabled };
# define NO_UNIQUE_ADDRESS
#endif
-using ArgumentsString = Utils::BasicSmallString<510>;
+using ArgumentsString = StaticString<3700>;
namespace Literals {
struct TracerLiteral
@@ -80,44 +86,41 @@ struct IsDictonary
inline constexpr IsDictonary isDictonary;
-namespace Internal {
-
template<typename String>
void convertToString(String &string, std::string_view text)
{
- string.append(R"(")");
+ string.append('\"');
string.append(text);
- string.append(R"(")");
+ string.append('\"');
}
template<typename String>
void convertToString(String &string, const QImage &image);
-extern template NANOTRACE_EXPORT void convertToString(std::string &string, const QImage &image);
extern template NANOTRACE_EXPORT void convertToString(ArgumentsString &string, const QImage &image);
template<typename String, std::size_t size>
void convertToString(String &string, const char (&text)[size])
{
- string.append(R"(")");
- string.append(text);
- string.append(R"(")");
+ string.append('\"');
+ string.append(std::string_view{text, size - 1});
+ string.append('\"');
}
template<typename String>
void convertToString(String &string, QStringView text)
{
- string.append(R"(")");
+ string.append('\"');
string.append(Utils::PathString{text});
- string.append(R"(")");
+ string.append('\"');
}
template<typename String>
void convertToString(String &string, const QByteArray &text)
{
- string.append(R"(")");
+ string.append('\"');
string.append(std::string_view(text.data(), Utils::usize(text)));
- string.append(R"(")");
+ string.append('\"');
}
template<typename String>
@@ -129,28 +132,29 @@ void convertToString(String &string, bool isTrue)
string.append("false");
}
-template<typename String, typename Callable, typename = std::enable_if_t<std::is_invocable_v<Callable>>>
+template<typename String, typename Callable, typename std::enable_if_t<std::is_invocable_v<Callable>, bool> = true>
void convertToString(String &string, Callable &&callable)
{
convertToString(string, callable());
}
-template<typename String>
-void convertToString(String &string, int number)
+template<typename String, typename Number, typename std::enable_if_t<std::is_arithmetic_v<Number>, bool> = true>
+void convertToString(String &string, Number number)
{
- string.append(Utils::SmallString::number(number));
+ string.append(number);
}
-template<typename String>
-void convertToString(String &string, long long number)
+template<typename Enumeration>
+constexpr std::underlying_type_t<Enumeration> to_underlying(Enumeration enumeration) noexcept
{
- string.append(Utils::SmallString::number(number));
+ static_assert(std::is_enum_v<Enumeration>, "to_underlying expect an enumeration");
+ return static_cast<std::underlying_type_t<Enumeration>>(enumeration);
}
-template<typename String>
-void convertToString(String &string, double number)
+template<typename String, typename Enumeration, typename std::enable_if_t<std::is_enum_v<Enumeration>, bool> = true>
+void convertToString(String &string, Enumeration enumeration)
{
- string.append(Utils::SmallString::number(number));
+ string.append(to_underlying(enumeration));
}
template<typename String>
@@ -165,14 +169,14 @@ void convertToString(String &string, const QVariant &value)
convertToString(string, value.toString());
}
-template<typename String, typename... Arguments>
-void convertToString(String &string, const std::tuple<const IsDictonary &, Arguments...> &dictonary);
-
-template<typename String, typename... Arguments>
-void convertToString(String &string, const std::tuple<const IsArray &, Arguments...> &list);
-
-template<typename String, template<typename...> typename Container, typename... Arguments>
-void convertToString(String &string, const Container<Arguments...> &container);
+template<typename String, typename Type>
+void convertToString(String &string, const std::optional<Type> &value)
+{
+ if (value)
+ convertToString(string, *value);
+ else
+ convertToString(string, "empty optional");
+}
template<typename String, typename Value>
void convertArrayEntryToString(String &string, const Value &value)
@@ -184,15 +188,15 @@ void convertArrayEntryToString(String &string, const Value &value)
template<typename String, typename... Entries>
void convertArrayToString(String &string, const IsArray &, Entries &...entries)
{
- string.append(R"([)");
+ string.append('[');
(convertArrayEntryToString(string, entries), ...);
if (sizeof...(entries))
string.pop_back();
- string.append("]");
+ string.append(']');
}
template<typename String, typename... Arguments>
-void convertToString(String &string, const std::tuple<const IsArray &, Arguments...> &list)
+void convertToString(String &string, const std::tuple<IsArray, Arguments...> &list)
{
std::apply([&](auto &&...entries) { convertArrayToString(string, entries...); }, list);
}
@@ -202,55 +206,107 @@ void convertDictonaryEntryToString(String &string, const std::tuple<Key, Value>
{
const auto &[key, value] = argument;
convertToString(string, key);
- string.append(":");
+ string.append(':');
convertToString(string, value);
- string.append(",");
+ string.append(',');
}
template<typename String, typename... Entries>
void convertDictonaryToString(String &string, const IsDictonary &, Entries &...entries)
{
- string.append(R"({)");
+ string.append('{');
(convertDictonaryEntryToString(string, entries), ...);
if (sizeof...(entries))
string.pop_back();
- string.append("}");
+ string.append('}');
}
template<typename String, typename... Arguments>
-void convertToString(String &string, const std::tuple<const IsDictonary &, Arguments...> &dictonary)
+void convertToString(String &string, const std::tuple<IsDictonary, Arguments...> &dictonary)
{
std::apply([&](auto &&...entries) { convertDictonaryToString(string, entries...); }, dictonary);
}
-template<typename String, template<typename...> typename Container, typename... Arguments>
-void convertToString(String &string, const Container<Arguments...> &container)
+template<typename T>
+struct is_container : std::false_type
+{};
+
+template<typename... Arguments>
+struct is_container<std::vector<Arguments...>> : std::true_type
+{};
+
+template<typename... Arguments>
+struct is_container<QList<Arguments...>> : std::true_type
+{};
+
+template<typename T, qsizetype Prealloc>
+struct is_container<QVarLengthArray<T, Prealloc>> : std::true_type
+{};
+
+template<typename String, typename Container, typename std::enable_if_t<is_container<Container>::value, bool> = true>
+void convertToString(String &string, const Container &values)
+{
+ string.append('[');
+
+ for (const auto &value : values) {
+ convertToString(string, value);
+ string.append(',');
+ }
+
+ if (values.size())
+ string.pop_back();
+
+ string.append(']');
+}
+
+template<typename T>
+struct is_map : std::false_type
+{};
+
+template<typename... Arguments>
+struct is_map<QtPrivate::QKeyValueRange<Arguments...>> : std::true_type
+{};
+
+template<typename... Arguments>
+struct is_map<std::map<Arguments...>> : std::true_type
+{};
+
+template<typename String, typename Map, typename std::enable_if_t<is_map<Map>::value, bool> = true>
+void convertToString(String &string, const Map &map)
{
- string.append("[");
- for (const auto &entry : container) {
- convertToString(string, entry);
- string.append(",");
+ string.append('{');
+
+ for (const auto &[key, value] : map) {
+ convertToString(string, key);
+ string.append(':');
+ convertToString(string, value);
+ string.append(',');
}
- if (container.size())
+ if (map.begin() != map.end())
string.pop_back();
- string.append("]");
+ string.append('}');
+}
+
+template<typename String, typename Key, typename Value>
+void convertToString(String &string, const QMap<Key, Value> &dictonary)
+{
+ convertToString(string, dictonary.asKeyValueRange());
}
+namespace Internal {
+
template<typename String, typename... Arguments>
-String toArguments(Arguments &&...arguments)
+void toArguments(String &text, Arguments &&...arguments)
{
- String text;
constexpr auto argumentCount = sizeof...(Arguments);
- text.append("{");
+ text.append('{');
(convertDictonaryEntryToString(text, arguments), ...);
if (argumentCount)
text.pop_back();
- text.append("}");
-
- return text;
+ text.append('}');
}
inline std::string_view toArguments(std::string_view arguments)
@@ -259,48 +315,58 @@ inline std::string_view toArguments(std::string_view arguments)
}
template<typename String>
-void appendArguments(String &eventArguments)
+void setArguments(String &eventArguments)
{
- eventArguments = {};
+ if constexpr (std::is_same_v<String, std::string_view>)
+ eventArguments = {};
+ else
+ eventArguments.clear();
}
template<typename String>
-void appendArguments(String &eventArguments, TracerLiteral arguments)
+void setArguments(String &eventArguments, TracerLiteral arguments)
{
eventArguments = arguments;
}
template<typename String, typename... Arguments>
-[[maybe_unused]] void appendArguments(String &eventArguments, Arguments &&...arguments)
+[[maybe_unused]] void setArguments(String &eventArguments, Arguments &&...arguments)
{
static_assert(
!std::is_same_v<String, std::string_view>,
R"(The arguments type of the tracing event queue is a string view. You can only provide trace token arguments as TracerLiteral (""_t).)");
- eventArguments = Internal::toArguments<String>(std::forward<Arguments>(arguments)...);
+ if constexpr (std::is_same_v<String, std::string_view>)
+ eventArguments = {};
+ else
+ eventArguments.clear();
+ Internal::toArguments(eventArguments, std::forward<Arguments>(arguments)...);
}
} // namespace Internal
template<typename Key, typename Value>
-auto keyValue(Key &&key, Value &&value)
+auto keyValue(const Key &key, Value &&value)
{
- return std::forward_as_tuple(std::forward<Key>(key), std::forward<Value>(value));
+ if constexpr (std::is_lvalue_reference_v<Value>)
+ return std::tuple<const Key &, const Value &>(key, value);
+ else
+ return std::tuple<const Key &, std::decay_t<Value>>(key, value);
}
template<typename... Entries>
auto dictonary(Entries &&...entries)
{
- return std::forward_as_tuple(isDictonary, std::forward<Entries>(entries)...);
+ return std::make_tuple(isDictonary, std::forward<Entries>(entries)...);
}
template<typename... Entries>
auto array(Entries &&...entries)
{
- return std::forward_as_tuple(isArray, std::forward<Entries>(entries)...);
+ return std::make_tuple(isArray, std::forward<Entries>(entries)...);
}
-enum class IsFlow : std::size_t { No = 0, Out = 1 << 0, In = 1 << 1, InOut = In | Out };
+enum class IsFlow : char { No = 0, Out = 1 << 0, In = 1 << 1, InOut = In | Out };
inline bool operator&(IsFlow first, IsFlow second)
{
@@ -309,7 +375,7 @@ inline bool operator&(IsFlow first, IsFlow second)
}
template<typename String, typename ArgumentsString>
-struct TraceEvent
+struct alignas(4096) TraceEvent
{
using StringType = String;
using ArgumentType = std::conditional_t<std::is_same_v<String, std::string_view>, TracerLiteral, String>;
@@ -324,13 +390,13 @@ struct TraceEvent
String name;
String category;
- ArgumentsString arguments;
TimePoint time;
Duration duration;
std::size_t id = 0;
- std::size_t bindId : 62;
- IsFlow flow : 2;
+ std::size_t bindId = 0;
+ IsFlow flow = IsFlow::No;
char type = ' ';
+ ArgumentsString arguments;
};
using StringViewTraceEvent = TraceEvent<std::string_view, std::string_view>;
@@ -413,6 +479,8 @@ class EventQueue
{
public:
using IsActive = std::false_type;
+
+ template<typename TraceFile> EventQueue(TraceFile &) {}
};
namespace Internal {
@@ -423,7 +491,13 @@ class EventQueueTracker
using Queue = EventQueue<TraceEvent, Tracing::IsEnabled>;
public:
- EventQueueTracker() = default;
+ EventQueueTracker()
+ {
+ terminateHandler = std::get_terminate();
+
+ std::set_terminate([]() { EventQueueTracker::get().terminate(); });
+ }
+
EventQueueTracker(const EventQueueTracker &) = delete;
EventQueueTracker(EventQueueTracker &&) = delete;
EventQueueTracker &operator=(const EventQueueTracker &) = delete;
@@ -457,8 +531,25 @@ public:
}
private:
+ void terminate()
+ {
+ flushAll();
+ if (terminateHandler)
+ terminateHandler();
+ }
+
+ void flushAll()
+ {
+ std::lock_guard lock{mutex};
+
+ for (auto queue : queues)
+ queue->flush();
+ }
+
+private:
std::mutex mutex;
std::vector<Queue *> queues;
+ std::terminate_handler terminateHandler = nullptr;
};
} // namespace Internal
@@ -466,11 +557,12 @@ template<typename TraceEvent>
class EventQueue<TraceEvent, Tracing::IsEnabled>
{
using TraceEventsSpan = Utils::span<TraceEvent>;
+ using TraceEvents = std::array<TraceEvent, 1000>;
public:
using IsActive = std::true_type;
- EventQueue(EnabledTraceFile *file);
+ EventQueue(EnabledTraceFile &file);
~EventQueue();
@@ -483,7 +575,9 @@ public:
EventQueue &operator=(const EventQueue &) = delete;
EventQueue &operator=(EventQueue &&) = delete;
- EnabledTraceFile *file = nullptr;
+ EnabledTraceFile &file;
+ std::unique_ptr<TraceEvents> eventArrayOne = std::make_unique<TraceEvents>();
+ std::unique_ptr<TraceEvents> eventArrayTwo = std::make_unique<TraceEvents>();
TraceEventsSpan eventsOne;
TraceEventsSpan eventsTwo;
TraceEventsSpan currentEvents;
@@ -505,35 +599,6 @@ extern template class NANOTRACE_EXPORT_EXTERN_TEMPLATE EventQueue<StringTraceEve
extern template class NANOTRACE_EXPORT_EXTERN_TEMPLATE
EventQueue<StringViewWithStringArgumentsTraceEvent, Tracing::IsEnabled>;
-template<typename TraceEvent, std::size_t eventCount, Tracing isEnabled>
-class EventQueueData : public EventQueue<TraceEvent, isEnabled>
-{
-public:
- using IsActive = std::true_type;
-
- EventQueueData(TraceFile<Tracing::IsDisabled> &) {}
-};
-
-template<typename TraceEvent, std::size_t eventCount>
-class EventQueueData<TraceEvent, eventCount, Tracing::IsEnabled>
- : public EventQueue<TraceEvent, Tracing::IsEnabled>
-{
- using TraceEvents = std::array<TraceEvent, eventCount>;
- using Base = EventQueue<TraceEvent, Tracing::IsEnabled>;
-
-public:
- using IsActive = std::true_type;
-
- EventQueueData(EnabledTraceFile &file)
- : Base{&file}
- {
- Base::setEventsSpans(*eventsOne.get(), *eventsTwo.get());
- }
-
- std::unique_ptr<TraceEvents> eventsOne = std::make_unique<TraceEvents>();
- std::unique_ptr<TraceEvents> eventsTwo = std::make_unique<TraceEvents>();
-};
-
template<typename TraceEvent>
TraceEvent &getTraceEvent(EnabledEventQueue<TraceEvent> &eventQueue)
{
@@ -1150,6 +1215,10 @@ public:
return std::pair<TracerType, FlowTokenType>();
}
+ template<typename... Arguments>
+ void threadEvent(ArgumentType, Arguments &&...)
+ {}
+
static constexpr bool isActive() { return false; }
};
@@ -1237,6 +1306,24 @@ public:
std::forward_as_tuple(PrivateTag{}, traceName, bindId, m_self)};
}
+ template<typename... Arguments>
+ void threadEvent(ArgumentType traceName, Arguments &&...arguments)
+ {
+ if (isEnabled == IsEnabled::No)
+ return;
+
+ auto &traceEvent = getTraceEvent(m_eventQueue);
+
+ traceEvent.time = Clock::now();
+ traceEvent.name = std::move(traceName);
+ traceEvent.category = traceName;
+ traceEvent.type = 'i';
+ traceEvent.id = 0;
+ traceEvent.bindId = 0;
+ traceEvent.flow = IsFlow::No;
+ Internal::setArguments(traceEvent.arguments, std::forward<Arguments>(arguments)...);
+ }
+
EnabledEventQueue<TraceEvent> &eventQueue() const { return m_eventQueue; }
std::string_view name() const { return m_name; }
@@ -1270,7 +1357,7 @@ private:
traceEvent.id = id;
traceEvent.bindId = bindId;
traceEvent.flow = flow;
- Internal::appendArguments(traceEvent.arguments, std::forward<Arguments>(arguments)...);
+ Internal::setArguments(traceEvent.arguments, std::forward<Arguments>(arguments)...);
traceEvent.time = Clock::now();
}
@@ -1296,7 +1383,7 @@ private:
traceEvent.id = id;
traceEvent.bindId = bindId;
traceEvent.flow = flow;
- Internal::appendArguments(traceEvent.arguments, std::forward<Arguments>(arguments)...);
+ Internal::setArguments(traceEvent.arguments, std::forward<Arguments>(arguments)...);
}
template<typename... Arguments>
@@ -1316,9 +1403,11 @@ private:
traceEvent.id = id;
traceEvent.bindId = 0;
traceEvent.flow = IsFlow::No;
- Internal::appendArguments(traceEvent.arguments, std::forward<Arguments>(arguments)...);
+ Internal::setArguments(traceEvent.arguments, std::forward<Arguments>(arguments)...);
}
+ CategoryFunctionPointer self() { return m_self; }
+
private:
StringType m_name;
EnabledEventQueue<TraceEvent> &m_eventQueue;
@@ -1403,11 +1492,8 @@ class Tracer<Category, std::true_type>
, flow{flow}
, m_category{category}
{
- if (category().isEnabled == IsEnabled::Yes) {
- Internal::appendArguments<ArgumentsStringType>(m_arguments,
- std::forward<Arguments>(arguments)...);
- m_start = Clock::now();
- }
+ if (category().isEnabled == IsEnabled::Yes)
+ sendBeginTrace(std::forward<Arguments>(arguments)...);
}
public:
@@ -1426,13 +1512,15 @@ public:
: m_name{name}
, m_category{category}
{
- if (category().isEnabled == IsEnabled::Yes) {
- Internal::appendArguments<ArgumentsStringType>(m_arguments,
- std::forward<Arguments>(arguments)...);
- m_start = Clock::now();
- }
+ if (category().isEnabled == IsEnabled::Yes)
+ sendBeginTrace(std::forward<Arguments>(arguments)...);
}
+ template<typename... Arguments>
+ [[nodiscard]] Tracer(ArgumentType name, Category &category, Arguments &&...arguments)
+ : Tracer(std::move(name), category.self(), std::forward<Arguments>(arguments)...)
+ {}
+
Tracer(const Tracer &) = delete;
Tracer &operator=(const Tracer &) = delete;
Tracer(Tracer &&other) noexcept = delete;
@@ -1440,7 +1528,7 @@ public:
TokenType createToken() { return {0, m_category}; }
- ~Tracer() { sendTrace(); }
+ ~Tracer() { sendEndTrace(); }
template<typename... Arguments>
Tracer beginDuration(ArgumentType name, Arguments &&...arguments)
@@ -1457,44 +1545,52 @@ public:
template<typename... Arguments>
void end(Arguments &&...arguments)
{
- sendTrace(std::forward<Arguments>(arguments)...);
+ sendEndTrace(std::forward<Arguments>(arguments)...);
m_name = {};
}
private:
template<typename... Arguments>
- void sendTrace(Arguments &&...arguments)
+ void sendBeginTrace(Arguments &&...arguments)
+ {
+ auto &category = m_category();
+ if (category.isEnabled == IsEnabled::Yes) {
+ auto &traceEvent = getTraceEvent(category.eventQueue());
+ traceEvent.name = m_name;
+ traceEvent.category = category.name();
+ traceEvent.bindId = m_bindId;
+ traceEvent.flow = flow;
+ traceEvent.type = 'B';
+ Internal::setArguments<ArgumentsStringType>(traceEvent.arguments,
+ std::forward<Arguments>(arguments)...);
+ traceEvent.time = Clock::now();
+ }
+ }
+
+ template<typename... Arguments>
+ void sendEndTrace(Arguments &&...arguments)
{
if (m_name.size()) {
- auto category = m_category();
+ auto &category = m_category();
if (category.isEnabled == IsEnabled::Yes) {
- auto duration = Clock::now() - m_start;
+ auto end = Clock::now();
auto &traceEvent = getTraceEvent(category.eventQueue());
- traceEvent.name = m_name;
+ traceEvent.name = std::move(m_name);
traceEvent.category = category.name();
- traceEvent.time = m_start;
- traceEvent.duration = duration;
+ traceEvent.time = end;
traceEvent.bindId = m_bindId;
traceEvent.flow = flow;
- traceEvent.type = 'X';
- if (sizeof...(arguments)) {
- m_arguments.clear();
- Internal::appendArguments<ArgumentsStringType>(traceEvent.arguments,
- std::forward<Arguments>(
- arguments)...);
- } else {
- traceEvent.arguments = m_arguments;
- }
+ traceEvent.type = 'E';
+ Internal::setArguments<ArgumentsStringType>(traceEvent.arguments,
+ std::forward<Arguments>(arguments)...);
}
}
}
private:
- TimePoint m_start;
StringType m_name;
- ArgumentsStringType m_arguments;
- std::size_t m_bindId;
- IsFlow flow;
+ std::size_t m_bindId = 0;
+ IsFlow flow = IsFlow::No;
CategoryFunctionPointer m_category;
};
diff --git a/src/libs/nanotrace/staticstring.h b/src/libs/nanotrace/staticstring.h
new file mode 100644
index 0000000000..d787bd2fe3
--- /dev/null
+++ b/src/libs/nanotrace/staticstring.h
@@ -0,0 +1,116 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#pragma once
+
+#include <utils/smallstringview.h>
+
+#if !(defined(__cpp_lib_to_chars) && (__cpp_lib_to_chars >= 201611L))
+# include <QLocale>
+#endif
+
+#include <array>
+#include <charconv>
+#include <limits>
+
+namespace NanotraceHR {
+
+template<std::size_t Capacity>
+class StaticString
+{
+public:
+ StaticString() = default;
+ StaticString(const StaticString &) = delete;
+ StaticString &operator=(const StaticString &) = delete;
+
+ char *data() { return m_data.data(); }
+
+ const char *data() const { return m_data.data(); }
+
+ void append(Utils::SmallStringView string) noexcept
+ {
+ auto newSize = m_size + string.size();
+
+ if (newSize <= Capacity) {
+ std::char_traits<char>::copy(std::next(data(), static_cast<std::ptrdiff_t>(m_size)),
+ string.data(),
+ string.size());
+ m_size = newSize;
+ } else {
+ m_size = Capacity + 1;
+ }
+ }
+
+ void append(char character) noexcept
+ {
+ auto newSize = m_size + 1;
+
+ if (newSize <= Capacity) {
+ auto current = std::next(data(), static_cast<std::ptrdiff_t>(m_size));
+ *current = character;
+
+ m_size = newSize;
+ } else {
+ m_size = Capacity + 1;
+ }
+ }
+
+ template<typename Type, typename std::enable_if_t<std::is_arithmetic_v<Type>, bool> = true>
+ void append(Type number)
+ {
+#if !(defined(__cpp_lib_to_chars) && (__cpp_lib_to_chars >= 201611L))
+ if constexpr (std::is_floating_point_v<Type>) {
+ QLocale locale{QLocale::Language::C};
+ append(locale.toString(number).toStdString());
+ return;
+ }
+#endif
+ // 2 bytes for the sign and because digits10 returns the floor
+ char buffer[std::numeric_limits<Type>::digits10 + 2];
+ auto result = std::to_chars(buffer, buffer + sizeof(buffer), number);
+ auto endOfConversionString = result.ptr;
+
+ append({buffer, endOfConversionString});
+ }
+
+ void pop_back() { --m_size; }
+
+ StaticString &operator+=(Utils::SmallStringView string) noexcept
+ {
+ append(string);
+
+ return *this;
+ }
+
+ StaticString &operator+=(char character) noexcept
+ {
+ append(character);
+
+ return *this;
+ }
+
+ template<typename Type, typename = std::enable_if_t<std::is_arithmetic_v<Type>>>
+ StaticString &operator+=(Type number) noexcept
+ {
+ append(number);
+
+ return *this;
+ }
+
+ bool isValid() const { return m_size <= Capacity; }
+
+ std::size_t size() const { return m_size; }
+
+ friend std::ostream &operator<<(std::ostream &out, const StaticString &text)
+ {
+ return out << std::string_view{text.data(), text.size()};
+ }
+
+ void clear() { m_size = 0; }
+
+private:
+ std::array<char, Capacity> m_data;
+ std::size_t m_size = 0;
+};
+
+} // namespace NanotraceHR
diff --git a/src/libs/qmljs/CMakeLists.txt b/src/libs/qmljs/CMakeLists.txt
index 4ca15cf7cc..a4966a8b4a 100644
--- a/src/libs/qmljs/CMakeLists.txt
+++ b/src/libs/qmljs/CMakeLists.txt
@@ -33,7 +33,6 @@ add_qtc_library(QmlJS
qmljsfindexportedcpptypes.cpp qmljsfindexportedcpptypes.h
qmljsicons.cpp qmljsicons.h
qmljsimportdependencies.cpp qmljsimportdependencies.h
- qmljsindenter.cpp qmljsindenter.h
qmljsinterpreter.cpp qmljsinterpreter.h
qmljslineinfo.cpp qmljslineinfo.h
qmljslink.cpp qmljslink.h
diff --git a/src/libs/qmljs/qmljs.qbs b/src/libs/qmljs/qmljs.qbs
index 18434c83ba..d5cc21faf1 100644
--- a/src/libs/qmljs/qmljs.qbs
+++ b/src/libs/qmljs/qmljs.qbs
@@ -28,7 +28,6 @@ QtcLibrary {
"qmljsfindexportedcpptypes.cpp", "qmljsfindexportedcpptypes.h",
"qmljsicons.cpp", "qmljsicons.h",
"qmljsimportdependencies.cpp", "qmljsimportdependencies.h",
- "qmljsindenter.cpp", "qmljsindenter.h",
"qmljsinterpreter.cpp", "qmljsinterpreter.h",
"qmljsdialect.cpp", "qmljsdialect.h",
"qmljslineinfo.cpp", "qmljslineinfo.h",
diff --git a/src/libs/qmljs/qmljsindenter.cpp b/src/libs/qmljs/qmljsindenter.cpp
deleted file mode 100644
index 8055847d90..0000000000
--- a/src/libs/qmljs/qmljsindenter.cpp
+++ /dev/null
@@ -1,603 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-/*
- This file is a self-contained interactive indenter for Qt Script.
-
- The general problem of indenting a program is ill posed. On
- the one hand, an indenter has to analyze programs written in a
- free-form formal language that is best described in terms of
- tokens, not characters, not lines. On the other hand, indentation
- applies to lines and white space characters matter, and otherwise
- the programs to indent are formally invalid in general, as they
- are begin edited.
-
- The approach taken here works line by line. We receive a program
- consisting of N lines or more, and we want to compute the
- indentation appropriate for the Nth line. Lines beyond the Nth
- lines are of no concern to us, so for simplicity we pretend the
- program has exactly N lines and we call the Nth line the "bottom
- line". Typically, we have to indent the bottom line when it's
- still empty, so we concentrate our analysis on the N - 1 lines
- that precede.
-
- By inspecting the (N - 1)-th line, the (N - 2)-th line, ...
- backwards, we determine the kind of the bottom line and indent it
- accordingly.
-
- * The bottom line is a comment line. See
- bottomLineStartsInCComment() and
- indentWhenBottomLineStartsInCComment().
- * The bottom line is a continuation line. See isContinuationLine()
- and indentForContinuationLine().
- * The bottom line is a standalone line. See
- indentForStandaloneLine().
-
- Certain tokens that influence the indentation, notably braces,
- are looked for in the lines. This is done by simple string
- comparison, without a real tokenizer. Confusing constructs such
- as comments and string literals are removed beforehand.
-*/
-
-#include <qmljs/qmljsindenter.h>
-#include <qmljs/qmljsscanner.h>
-
-#include <QTextBlock>
-
-using namespace QmlJS;
-
-/*
- Saves and restores the state of the global linizer. This enables
- backtracking.
-
- Identical to the defines in qmljslineinfo.cpp
-*/
-#define YY_SAVE() LinizerState savedState = yyLinizerState
-#define YY_RESTORE() yyLinizerState = savedState
-
-
-QmlJSIndenter::QmlJSIndenter()
- : caseOrDefault(QRegularExpression(QLatin1String(
- "^\\s*(?:"
- "case\\b[^:]+|"
- "default)"
- "\\s*:.*$")))
-
-{
-
- /*
- The indenter supports a few parameters:
-
- * ppHardwareTabSize is the size of a '\t' in your favorite editor.
- * ppIndentSize is the size of an indentation, or software tab
- size.
- * ppContinuationIndentSize is the extra indent for a continuation
- line, when there is nothing to align against on the previous
- line.
- * ppCommentOffset is the indentation within a C-style comment,
- when it cannot be picked up.
- */
-
- ppHardwareTabSize = 8;
- ppIndentSize = 4;
- ppContinuationIndentSize = 8;
- ppCommentOffset = 2;
-}
-
-QmlJSIndenter::~QmlJSIndenter()
-{
-}
-
-void QmlJSIndenter::setTabSize(int size)
-{
- ppHardwareTabSize = size;
-}
-
-void QmlJSIndenter::setIndentSize(int size)
-{
- ppIndentSize = size;
- ppContinuationIndentSize = 2 * size;
-}
-
-/*
- Returns true if string t is made only of white space; otherwise
- returns false.
-*/
-bool QmlJSIndenter::isOnlyWhiteSpace(const QString &t) const
-{
- return firstNonWhiteSpace(t).isNull();
-}
-
-/*
- Assuming string t is a line, returns the column number of a given
- index. Column numbers and index are identical for strings that don't
- contain '\t's.
-*/
-int QmlJSIndenter::columnForIndex(const QString &t, int index) const
-{
- int col = 0;
- if (index > t.length())
- index = t.length();
-
- for (int i = 0; i < index; i++) {
- if (t.at(i) == QLatin1Char('\t'))
- col = ((col / ppHardwareTabSize) + 1) * ppHardwareTabSize;
- else
- col++;
- }
- return col;
-}
-
-/*
- Returns the indentation size of string t.
-*/
-int QmlJSIndenter::indentOfLine(const QString &t) const
-{
- return columnForIndex(t, t.indexOf(firstNonWhiteSpace(t)));
-}
-
-/*
- Replaces t[k] by ch, unless t[k] is '\t'. Tab characters are better
- left alone since they break the "index equals column" rule. No
- provisions are taken against '\n' or '\r', which shouldn't occur in
- t anyway.
-*/
-void QmlJSIndenter::eraseChar(QString &t, int k, QChar ch) const
-{
- if (t.at(k) != QLatin1Char('\t'))
- t[k] = ch;
-}
-
-/*
- Returns '(' if the last parenthesis is opening, ')' if it is
- closing, and QChar() if there are no parentheses in t.
-*/
-QChar QmlJSIndenter::lastParen() const
-{
- for (int index = yyLinizerState.tokens.size() - 1; index != -1; --index) {
- const Token &token = yyLinizerState.tokens.at(index);
-
- if (token.is(Token::LeftParenthesis))
- return QLatin1Char('(');
-
- else if (token.is(Token::RightParenthesis))
- return QLatin1Char(')');
- }
-
- return QChar();
-}
-
-/*
- Returns true if typedIn the same as okayCh or is null; otherwise
- returns false.
-*/
-bool QmlJSIndenter::okay(QChar typedIn, QChar okayCh) const
-{
- return typedIn == QChar() || typedIn == okayCh;
-}
-
-/*
- Returns the recommended indent for the bottom line of yyProgram
- assuming that it starts in a C-style comment, a condition that is
- tested elsewhere.
-
- Essentially, we're trying to align against some text on the
- previous line.
-*/
-int QmlJSIndenter::indentWhenBottomLineStartsInMultiLineComment()
-{
- QTextBlock block = yyProgram.lastBlock().previous();
- QString blockText;
-
- for (; block.isValid(); block = block.previous()) {
- blockText = block.text();
-
- if (! isOnlyWhiteSpace(blockText))
- break;
- }
-
- return indentOfLine(blockText);
-}
-
-/*
- Returns the recommended indent for the bottom line of yyProgram,
- assuming it's a continuation line.
-
- We're trying to align the continuation line against some parenthesis
- or other bracked left opened on a previous line, or some interesting
- operator such as '='.
-*/
-int QmlJSIndenter::indentForContinuationLine()
-{
- int braceDepth = 0;
- int delimDepth = 0;
-
- bool leftBraceFollowed = *yyLeftBraceFollows;
-
- for (int i = 0; i < SmallRoof; i++) {
- int hook = -1;
-
- int j = yyLine->length();
- while (j > 0 && hook < 0) {
- j--;
- QChar ch = yyLine->at(j);
-
- switch (ch.unicode()) {
- case ')':
- delimDepth++;
- break;
- case ']':
- braceDepth++;
- break;
- case '}':
- braceDepth++;
- break;
- case '(':
- delimDepth--;
- /*
- An unclosed delimiter is a good place to align at,
- at least for some styles (including Qt's).
- */
- if (delimDepth == -1)
- hook = j;
- break;
-
- case '[':
- braceDepth--;
- /*
- An unclosed delimiter is a good place to align at,
- at least for some styles (including Qt's).
- */
- if (braceDepth == -1)
- hook = j;
- break;
- case '{':
- braceDepth--;
- /*
- A left brace followed by other stuff on the same
- line is typically for an enum or an initializer.
- Such a brace must be treated just like the other
- delimiters.
- */
- if (braceDepth == -1) {
- if (j < yyLine->length() - 1)
- hook = j;
- else
- return 0; // shouldn't happen
- }
- break;
- case '=':
- /*
- An equal sign is a very natural alignment hook
- because it's usually the operator with the lowest
- precedence in statements it appears in. Case in
- point:
-
- int x = 1 +
- 2;
-
- However, we have to beware of constructs such as
- default arguments and explicit enum constant
- values:
-
- void foo(int x = 0,
- int y = 0);
-
- And not
-
- void foo(int x = 0,
- int y = 0);
-
- These constructs are caracterized by a ',' at the
- end of the unfinished lines or by unbalanced
- parentheses.
- */
- Q_ASSERT(j - 1 >= 0);
-
- if (QString::fromLatin1("!=<>").indexOf(yyLine->at(j - 1)) == -1 &&
- j + 1 < yyLine->length() && yyLine->at(j + 1) != QLatin1Char('=')) {
- if (braceDepth == 0 && delimDepth == 0 &&
- j < yyLine->length() - 1 &&
- !yyLine->endsWith(QLatin1Char(',')) &&
- (yyLine->contains(QLatin1Char('(')) == yyLine->contains(QLatin1Char(')'))))
- hook = j;
- }
- }
- }
-
- if (hook >= 0) {
- /*
- Yes, we have a delimiter or an operator to align
- against! We don't really align against it, but rather
- against the following token, if any. In this example,
- the following token is "11":
-
- int x = (11 +
- 2);
-
- If there is no such token, we use a continuation indent:
-
- static QRegExp foo(QString(
- "foo foo foo foo foo foo foo foo foo"));
- */
- hook++;
- while (hook < yyLine->length()) {
- if (!yyLine->at(hook).isSpace())
- return columnForIndex(*yyLine, hook);
- hook++;
- }
- return indentOfLine(*yyLine) + ppContinuationIndentSize;
- }
-
- if (braceDepth != 0)
- break;
-
- /*
- The line's delimiters are balanced. It looks like a
- continuation line or something.
- */
- if (delimDepth == 0) {
- if (leftBraceFollowed) {
- /*
- We have
-
- int main()
- {
-
- or
-
- Bar::Bar()
- : Foo(x)
- {
-
- The "{" should be flush left.
- */
- if (!isContinuationLine())
- return indentOfLine(*yyLine);
- } else if (isContinuationLine() || yyLine->endsWith(QLatin1Char(','))) {
- /*
- We have
-
- x = a +
- b +
- c;
-
- or
-
- int t[] = {
- 1, 2, 3,
- 4, 5, 6
-
- The "c;" should fall right under the "b +", and the
- "4, 5, 6" right under the "1, 2, 3,".
- */
- return indentOfLine(*yyLine);
- } else {
- /*
- We have
-
- stream << 1 +
- 2;
-
- We could, but we don't, try to analyze which
- operator has precedence over which and so on, to
- obtain the excellent result
-
- stream << 1 +
- 2;
-
- We do have a special trick above for the assignment
- operator above, though.
- */
- return indentOfLine(*yyLine) + ppContinuationIndentSize;
- }
- }
-
- if (!readLine())
- break;
- }
- return 0;
-}
-
-/*
- Returns the recommended indent for the bottom line of yyProgram if
- that line is standalone (or should be indented likewise).
-
- Indenting a standalone line is tricky, mostly because of braceless
- control statements. Grossly, we are looking backwards for a special
- line, a "hook line", that we can use as a starting point to indent,
- and then modify the indentation level according to the braces met
- along the way to that hook.
-
- Let's consider a few examples. In all cases, we want to indent the
- bottom line.
-
- Example 1:
-
- x = 1;
- y = 2;
-
- The hook line is "x = 1;". We met 0 opening braces and 0 closing
- braces. Therefore, "y = 2;" inherits the indent of "x = 1;".
-
- Example 2:
-
- if (x) {
- y;
-
- The hook line is "if (x) {". No matter what precedes it, "y;" has
- to be indented one level deeper than the hook line, since we met one
- opening brace along the way.
-
- Example 3:
-
- if (a)
- while (b) {
- c;
- }
- d;
-
- To indent "d;" correctly, we have to go as far as the "if (a)".
- Compare with
-
- if (a) {
- while (b) {
- c;
- }
- d;
-
- Still, we're striving to go back as little as possible to
- accommodate people with irregular indentation schemes. A hook line
- near at hand is much more reliable than a remote one.
-*/
-int QmlJSIndenter::indentForStandaloneLine()
-{
- for (int i = 0; i < SmallRoof; i++) {
- if (!*yyLeftBraceFollows) {
- YY_SAVE();
-
- if (matchBracelessControlStatement()) {
- /*
- The situation is this, and we want to indent "z;":
-
- if (x &&
- y)
- z;
-
- yyLine is "if (x &&".
- */
- return indentOfLine(*yyLine) + ppIndentSize;
- }
- YY_RESTORE();
- }
-
- if (yyLine->endsWith(QLatin1Char(';')) || yyLine->contains(QLatin1Char('{'))) {
- /*
- The situation is possibly this, and we want to indent
- "z;":
-
- while (x)
- y;
- z;
-
- We return the indent of "while (x)". In place of "y;",
- any arbitrarily complex compound statement can appear.
- */
-
- if (*yyBraceDepth > 0) {
- do {
- if (!readLine())
- break;
- } while (*yyBraceDepth > 0);
- }
-
- LinizerState hookState;
-
- while (isContinuationLine())
- readLine();
- hookState = yyLinizerState;
-
- readLine();
- if (*yyBraceDepth <= 0) {
- do {
- if (!matchBracelessControlStatement())
- break;
- hookState = yyLinizerState;
- } while (readLine());
- }
-
- yyLinizerState = hookState;
-
- while (isContinuationLine())
- readLine();
-
- int indentChange = - *yyBraceDepth;
- if (caseOrDefault.match(*yyLine).hasMatch())
- ++indentChange;
-
- /*
- Never trust lines containing only '{' or '}', as some
- people (Richard M. Stallman) format them weirdly.
- */
- if (yyLine->trimmed().length() > 1)
- return indentOfLine(*yyLine) + indentChange * ppIndentSize;
- }
-
- if (!readLine())
- return -*yyBraceDepth * ppIndentSize;
- }
- return 0;
-}
-
-/*
- Returns the recommended indent for the bottom line of program.
- Unless null, typedIn stores the character of yyProgram that
- triggered reindentation.
-
- This function works better if typedIn is set properly; it is
- slightly more conservative if typedIn is completely wild, and
- slighly more liberal if typedIn is always null. The user might be
- annoyed by the liberal behavior.
-*/
-int QmlJSIndenter::indentForBottomLine(QTextBlock begin, QTextBlock end, QChar typedIn)
-{
- if (begin == end)
- return 0;
-
- const QTextBlock last = end.previous();
-
- initialize(begin, last);
-
- QString bottomLine = last.text();
- QChar firstCh = firstNonWhiteSpace(bottomLine);
- int indent = 0;
-
- if (bottomLineStartsInMultilineComment()) {
- /*
- The bottom line starts in a C-style comment. Indent it
- smartly, unless the user has already played around with it,
- in which case it's better to leave her stuff alone.
- */
- if (isOnlyWhiteSpace(bottomLine))
- indent = indentWhenBottomLineStartsInMultiLineComment();
- else
- indent = indentOfLine(bottomLine);
- } else {
- if (isUnfinishedLine())
- indent = indentForContinuationLine();
- else
- indent = indentForStandaloneLine();
-
- if ((okay(typedIn, QLatin1Char('}')) && firstCh == QLatin1Char('}'))
- || (okay(typedIn, QLatin1Char(']')) && firstCh == QLatin1Char(']'))) {
- /*
- A closing brace is one level more to the left than the
- code it follows.
- */
- indent -= ppIndentSize;
- } else if (okay(typedIn, QLatin1Char(':'))) {
- if (caseOrDefault.match(bottomLine).hasMatch()) {
- /*
- Move a case label (or the ':' in front of a
- constructor initialization list) one level to the
- left, but only if the user did not play around with
- it yet. Some users have exotic tastes in the
- matter, and most users probably are not patient
- enough to wait for the final ':' to format their
- code properly.
-
- We don't attempt the same for goto labels, as the
- user is probably the middle of "foo::bar". (Who
- uses goto, anyway?)
- */
- if (indentOfLine(bottomLine) <= indent)
- indent -= ppIndentSize;
- else
- indent = indentOfLine(bottomLine);
- }
- }
- }
-
- return qMax(0, indent);
-}
-
diff --git a/src/libs/qmljs/qmljsindenter.h b/src/libs/qmljs/qmljsindenter.h
deleted file mode 100644
index 55141c1b3b..0000000000
--- a/src/libs/qmljs/qmljsindenter.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#pragma once
-
-#include <qmljs/qmljs_global.h>
-#include <qmljs/qmljslineinfo.h>
-
-#include <QRegularExpression>
-
-QT_FORWARD_DECLARE_CLASS(QTextBlock)
-
-namespace QmlJS {
-
-class QMLJS_EXPORT QmlJSIndenter : public LineInfo
-{
- Q_DISABLE_COPY(QmlJSIndenter)
-
-public:
- QmlJSIndenter();
- ~QmlJSIndenter();
-
- void setTabSize(int size);
- void setIndentSize(int size);
-
- int indentForBottomLine(QTextBlock firstBlock, QTextBlock lastBlock, QChar typedIn);
-
-private:
- bool isOnlyWhiteSpace(const QString &t) const;
- int columnForIndex(const QString &t, int index) const;
- int indentOfLine(const QString &t) const;
-
- void eraseChar(QString &t, int k, QChar ch) const;
- QChar lastParen() const;
- bool okay(QChar typedIn, QChar okayCh) const;
-
- int indentWhenBottomLineStartsInMultiLineComment();
- int indentForContinuationLine();
- int indentForStandaloneLine();
-
-private:
- int ppHardwareTabSize;
- int ppIndentSize;
- int ppContinuationIndentSize;
- int ppCommentOffset;
-
-private:
- QRegularExpression caseOrDefault;
-};
-
-} // namespace QmlJS
diff --git a/src/libs/qmljs/qmljsstaticanalysismessage.cpp b/src/libs/qmljs/qmljsstaticanalysismessage.cpp
index 5b15e69428..432b97aba7 100644
--- a/src/libs/qmljs/qmljsstaticanalysismessage.cpp
+++ b/src/libs/qmljs/qmljsstaticanalysismessage.cpp
@@ -189,8 +189,9 @@ StaticAnalysisMessages::StaticAnalysisMessages()
Tr::tr("Maximum string value length is %1."), 1);
newMsg(ErrInvalidArrayValueLength, Error,
Tr::tr("%1 elements expected in array value."), 1);
- newMsg(WarnImperativeCodeNotEditableInVisualDesigner, Warning,
- Tr::tr("Imperative code is not supported in Qt Design Studio."));
+ newMsg(WarnImperativeCodeNotEditableInVisualDesigner,
+ Warning,
+ Tr::tr("JavaScript can break the visual tooling in Qt Design Studio."));
newMsg(WarnUnsupportedTypeInVisualDesigner, Warning,
Tr::tr("This type (%1) is not supported in Qt Design Studio."), 1);
newMsg(WarnReferenceToParentItemNotSupportedByVisualDesigner, Warning,
diff --git a/src/libs/qmlpuppetcommunication/container/imagecontainer.cpp b/src/libs/qmlpuppetcommunication/container/imagecontainer.cpp
index 545d4d927d..7747a9d118 100644
--- a/src/libs/qmlpuppetcommunication/container/imagecontainer.cpp
+++ b/src/libs/qmlpuppetcommunication/container/imagecontainer.cpp
@@ -15,7 +15,7 @@
#define QTC_ASSERT_STRING(cond) qDebug("SOFT ASSERT: \"" cond"\" in file " __FILE__ ", line " QTC_ASSERT_STRINGIFY(__LINE__))
#define QTC_ASSERT(cond, action) if (cond) {} else { QTC_ASSERT_STRING(#cond); action; } do {} while (0)
-static Q_LOGGING_CATEGORY(imageContainerDebug, "qtc.imagecontainer.debug", QtDebugMsg)
+static Q_LOGGING_CATEGORY(imageContainerDebug, "qtc.imagecontainer")
namespace QmlDesigner {
@@ -194,9 +194,10 @@ static void readSharedMemory(qint32 key, ImageContainer &container)
QImage image = QImage(imageWidth, imageHeight, QImage::Format(imageFormat));
image.setDevicePixelRatio(pixelRatio);
- if (image.isNull())
- qCInfo(imageContainerDebug()) << Q_FUNC_INFO << "Not able to create image:" << imageWidth << imageHeight << imageFormat;
- else
+ if (image.isNull()) {
+ if (imageWidth || imageHeight || imageFormat)
+ qCWarning(imageContainerDebug) << Q_FUNC_INFO << "Not able to create image:" << imageWidth << imageHeight << imageFormat;
+ } else
std::memcpy(image.bits(), reinterpret_cast<const qint32*>(sharedMemory.constData()) + 6, byteCount);
container.setImage(image);
diff --git a/src/libs/sqlite/CMakeLists.txt b/src/libs/sqlite/CMakeLists.txt
index 2c7e1ebbf3..f86f31871a 100644
--- a/src/libs/sqlite/CMakeLists.txt
+++ b/src/libs/sqlite/CMakeLists.txt
@@ -31,7 +31,7 @@ endif()
add_qtc_library(Sqlite
PROPERTIES AUTOMOC OFF AUTOUIC OFF
- DEPENDS Qt::Core Threads::Threads ${CMAKE_DL_LIBS} SqliteInternal
+ DEPENDS Qt::Core Threads::Threads ${CMAKE_DL_LIBS} SqliteInternal Nanotrace
INCLUDES
../3rdparty/sqlite
PUBLIC_INCLUDES
@@ -58,7 +58,7 @@ add_qtc_library(Sqlite
sqlitesessionchangeset.cpp sqlitesessionchangeset.h
sqlitesessions.cpp sqlitesessions.h
sqlitetable.h
- sqlitetransaction.h
+ sqlitetracing.cpp sqlitetracing.h
sqlitetransaction.h
sqlitevalue.h
sqlitewritestatement.h
diff --git a/src/libs/sqlite/sqlitebasestatement.cpp b/src/libs/sqlite/sqlitebasestatement.cpp
index 23466c0cea..8557bf6ad2 100644
--- a/src/libs/sqlite/sqlitebasestatement.cpp
+++ b/src/libs/sqlite/sqlitebasestatement.cpp
@@ -26,32 +26,7 @@ extern "C" int sqlite3_carray_bind(
namespace Sqlite {
-namespace {
-using TraceFile = NanotraceHR::TraceFile<sqliteTracingStatus()>;
-
-TraceFile traceFile{"sqlite.json"};
-
-thread_local NanotraceHR::EventQueueData<NanotraceHR::StringViewTraceEvent, 10000, sqliteTracingStatus()>
- eventQueueData(traceFile);
-
-NanotraceHR::StringViewCategory<sqliteTracingStatus()> &sqliteLowLevelCategory();
-
-thread_local NanotraceHR::StringViewCategory<sqliteTracingStatus()> sqliteLowLevelCategory_{
- "sqlite low level"_t, eventQueueData, sqliteLowLevelCategory};
-
-NanotraceHR::StringViewCategory<sqliteTracingStatus()> &sqliteLowLevelCategory()
-{
- return sqliteLowLevelCategory_;
-}
-
-thread_local NanotraceHR::StringViewCategory<sqliteTracingStatus()> sqliteHighLevelCategory_{
- "sqlite high level"_t, eventQueueData, sqliteHighLevelCategory};
-} // namespace
-
-NanotraceHR::StringViewCategory<sqliteTracingStatus()> &sqliteHighLevelCategory()
-{
- return sqliteHighLevelCategory_;
-}
+using NanotraceHR::keyValue;
BaseStatement::BaseStatement(Utils::SmallStringView sqlStatement, Database &database)
: m_database(database)
@@ -107,14 +82,18 @@ void BaseStatement::waitForUnlockNotify() const
void BaseStatement::reset() const noexcept
{
- NanotraceHR::Tracer tracer{"reset"_t, sqliteLowLevelCategory()};
+ NanotraceHR::Tracer tracer{"reset"_t,
+ sqliteLowLevelCategory(),
+ keyValue("sqlite statement", handle())};
sqlite3_reset(m_compiledStatement.get());
}
bool BaseStatement::next() const
{
- NanotraceHR::Tracer tracer{"next"_t, sqliteLowLevelCategory()};
+ NanotraceHR::Tracer tracer{"next"_t,
+ sqliteLowLevelCategory(),
+ keyValue("sqlite statement", handle())};
int resultCode;
do {
@@ -141,7 +120,10 @@ void BaseStatement::step() const
void BaseStatement::bindNull(int index)
{
- NanotraceHR::Tracer tracer{"bind null"_t, sqliteLowLevelCategory()};
+ NanotraceHR::Tracer tracer{"bind null"_t,
+ sqliteLowLevelCategory(),
+ keyValue("sqlite statement", handle()),
+ keyValue("index", index)};
int resultCode = sqlite3_bind_null(m_compiledStatement.get(), index);
if (resultCode != SQLITE_OK)
@@ -155,7 +137,11 @@ void BaseStatement::bind(int index, NullValue)
void BaseStatement::bind(int index, int value)
{
- NanotraceHR::Tracer tracer{"bind int"_t, sqliteLowLevelCategory()};
+ NanotraceHR::Tracer tracer{"bind int"_t,
+ sqliteLowLevelCategory(),
+ keyValue("sqlite statement", handle()),
+ keyValue("index", index),
+ keyValue("value", value)};
int resultCode = sqlite3_bind_int(m_compiledStatement.get(), index, value);
if (resultCode != SQLITE_OK)
@@ -164,7 +150,11 @@ void BaseStatement::bind(int index, int value)
void BaseStatement::bind(int index, long long value)
{
- NanotraceHR::Tracer tracer{"bind long long"_t, sqliteLowLevelCategory()};
+ NanotraceHR::Tracer tracer{"bind long long"_t,
+ sqliteLowLevelCategory(),
+ keyValue("sqlite statement", handle()),
+ keyValue("index", index),
+ keyValue("value", value)};
int resultCode = sqlite3_bind_int64(m_compiledStatement.get(), index, value);
if (resultCode != SQLITE_OK)
@@ -173,7 +163,11 @@ void BaseStatement::bind(int index, long long value)
void BaseStatement::bind(int index, double value)
{
- NanotraceHR::Tracer tracer{"bind double"_t, sqliteLowLevelCategory()};
+ NanotraceHR::Tracer tracer{"bind double"_t,
+ sqliteLowLevelCategory(),
+ keyValue("sqlite statement", handle()),
+ keyValue("index", index),
+ keyValue("value", value)};
int resultCode = sqlite3_bind_double(m_compiledStatement.get(), index, value);
if (resultCode != SQLITE_OK)
@@ -182,7 +176,11 @@ void BaseStatement::bind(int index, double value)
void BaseStatement::bind(int index, void *pointer)
{
- NanotraceHR::Tracer tracer{"bind pointer"_t, sqliteLowLevelCategory()};
+ NanotraceHR::Tracer tracer{"bind pointer"_t,
+ sqliteLowLevelCategory(),
+ keyValue("sqlite statement", handle()),
+ keyValue("index", index),
+ keyValue("pointer", reinterpret_cast<std::uintptr_t>(pointer))};
int resultCode = sqlite3_bind_pointer(m_compiledStatement.get(), index, pointer, "carray", nullptr);
if (resultCode != SQLITE_OK)
@@ -191,7 +189,12 @@ void BaseStatement::bind(int index, void *pointer)
void BaseStatement::bind(int index, Utils::span<const int> values)
{
- NanotraceHR::Tracer tracer{"bind int span"_t, sqliteLowLevelCategory()};
+ NanotraceHR::Tracer tracer{"bind int span"_t,
+ sqliteLowLevelCategory(),
+ keyValue("sqlite statement", handle()),
+ keyValue("index", index),
+ keyValue("pointer", reinterpret_cast<std::uintptr_t>(values.data())),
+ keyValue("size", values.size())};
int resultCode = sqlite3_carray_bind(m_compiledStatement.get(),
index,
@@ -205,7 +208,12 @@ void BaseStatement::bind(int index, Utils::span<const int> values)
void BaseStatement::bind(int index, Utils::span<const long long> values)
{
- NanotraceHR::Tracer tracer{"bind long long span"_t, sqliteLowLevelCategory()};
+ NanotraceHR::Tracer tracer{"bind long long span"_t,
+ sqliteLowLevelCategory(),
+ keyValue("sqlite statement", handle()),
+ keyValue("index", index),
+ keyValue("pointer", reinterpret_cast<std::uintptr_t>(values.data())),
+ keyValue("size", values.size())};
int resultCode = sqlite3_carray_bind(m_compiledStatement.get(),
index,
@@ -219,7 +227,12 @@ void BaseStatement::bind(int index, Utils::span<const long long> values)
void BaseStatement::bind(int index, Utils::span<const double> values)
{
- NanotraceHR::Tracer tracer{"bind double span"_t, sqliteLowLevelCategory()};
+ NanotraceHR::Tracer tracer{"bind double span"_t,
+ sqliteLowLevelCategory(),
+ keyValue("sqlite statement", handle()),
+ keyValue("index", index),
+ keyValue("pointer", reinterpret_cast<std::uintptr_t>(values.data())),
+ keyValue("size", values.size())};
int resultCode = sqlite3_carray_bind(m_compiledStatement.get(),
index,
@@ -233,7 +246,12 @@ void BaseStatement::bind(int index, Utils::span<const double> values)
void BaseStatement::bind(int index, Utils::span<const char *> values)
{
- NanotraceHR::Tracer tracer{"bind const char* span"_t, sqliteLowLevelCategory()};
+ NanotraceHR::Tracer tracer{"bind const char* span"_t,
+ sqliteLowLevelCategory(),
+ keyValue("sqlite statement", handle()),
+ keyValue("index", index),
+ keyValue("pointer", reinterpret_cast<std::uintptr_t>(values.data())),
+ keyValue("size", values.size())};
int resultCode = sqlite3_carray_bind(m_compiledStatement.get(),
index,
@@ -247,7 +265,11 @@ void BaseStatement::bind(int index, Utils::span<const char *> values)
void BaseStatement::bind(int index, Utils::SmallStringView text)
{
- NanotraceHR::Tracer tracer{"bind string"_t, sqliteLowLevelCategory()};
+ NanotraceHR::Tracer tracer{"bind string"_t,
+ sqliteLowLevelCategory(),
+ keyValue("sqlite statement", handle()),
+ keyValue("index", index),
+ keyValue("text", text)};
int resultCode = sqlite3_bind_text(m_compiledStatement.get(),
index,
@@ -260,7 +282,12 @@ void BaseStatement::bind(int index, Utils::SmallStringView text)
void BaseStatement::bind(int index, BlobView blobView)
{
- NanotraceHR::Tracer tracer{"bind blob"_t, sqliteLowLevelCategory()};
+ NanotraceHR::Tracer tracer{"bind blob"_t,
+ sqliteLowLevelCategory(),
+ keyValue("sqlite statement", handle()),
+ keyValue("index", index),
+ keyValue("pointer", reinterpret_cast<std::uintptr_t>(blobView.data())),
+ keyValue("size", blobView.size())};
int resultCode = SQLITE_OK;
@@ -280,7 +307,11 @@ void BaseStatement::bind(int index, BlobView blobView)
void BaseStatement::bind(int index, const Value &value)
{
- NanotraceHR::Tracer tracer{"bind value"_t, sqliteLowLevelCategory()};
+ NanotraceHR::Tracer tracer{
+ "bind value"_t,
+ sqliteLowLevelCategory(),
+ keyValue("sqlite statement", handle()),
+ };
switch (value.type()) {
case ValueType::Integer:
@@ -303,7 +334,11 @@ void BaseStatement::bind(int index, const Value &value)
void BaseStatement::bind(int index, ValueView value)
{
- NanotraceHR::Tracer tracer{"bind value"_t, sqliteLowLevelCategory()};
+ NanotraceHR::Tracer tracer{
+ "bind value"_t,
+ sqliteLowLevelCategory(),
+ keyValue("sqlite statement", handle()),
+ };
switch (value.type()) {
case ValueType::Integer:
@@ -326,7 +361,9 @@ void BaseStatement::bind(int index, ValueView value)
void BaseStatement::prepare(Utils::SmallStringView sqlStatement)
{
- NanotraceHR::Tracer tracer{"prepare"_t, sqliteLowLevelCategory()};
+ NanotraceHR::Tracer tracer{"prepare"_t,
+ sqliteLowLevelCategory(),
+ keyValue("sql statement", sqlStatement)};
if (!m_database.isLocked())
throw DatabaseIsNotLocked{};
@@ -342,14 +379,18 @@ void BaseStatement::prepare(Utils::SmallStringView sqlStatement)
nullptr);
m_compiledStatement.reset(sqliteStatement);
- if (resultCode == SQLITE_LOCKED)
+ if (resultCode == SQLITE_LOCKED) {
+ tracer.tick("wait for unlock"_t);
waitForUnlockNotify();
+ }
} while (resultCode == SQLITE_LOCKED);
if (resultCode != SQLITE_OK)
Sqlite::throwError(resultCode, sqliteDatabaseHandle());
+
+ tracer.end(keyValue("sqlite statement", handle()));
}
sqlite3 *BaseStatement::sqliteDatabaseHandle() const
@@ -427,7 +468,10 @@ StringType convertToTextForColumn(sqlite3_stmt *sqlStatment, int column)
Type BaseStatement::fetchType(int column) const
{
- NanotraceHR::Tracer tracer{"fetch type"_t, sqliteLowLevelCategory()};
+ NanotraceHR::Tracer tracer{"fetch type"_t,
+ sqliteLowLevelCategory(),
+ keyValue("sqlite statement", handle()),
+ keyValue("column", column)};
auto dataType = sqlite3_column_type(m_compiledStatement.get(), column);
@@ -449,9 +493,16 @@ Type BaseStatement::fetchType(int column) const
int BaseStatement::fetchIntValue(int column) const
{
- NanotraceHR::Tracer tracer{"fetch int"_t, sqliteLowLevelCategory()};
+ NanotraceHR::Tracer tracer{"fetch int"_t,
+ sqliteLowLevelCategory(),
+ keyValue("sqlite statement", handle()),
+ keyValue("column", column)};
+
+ auto value = sqlite3_column_int(m_compiledStatement.get(), column);
- return sqlite3_column_int(m_compiledStatement.get(), column);
+ tracer.end(keyValue("value", value));
+
+ return value;
}
template<>
@@ -473,9 +524,16 @@ long BaseStatement::fetchValue<long>(int column) const
long long BaseStatement::fetchLongLongValue(int column) const
{
- NanotraceHR::Tracer tracer{"fetch long long"_t, sqliteLowLevelCategory()};
+ NanotraceHR::Tracer tracer{"fetch long long"_t,
+ sqliteLowLevelCategory(),
+ keyValue("sqlite statement", handle()),
+ keyValue("column", column)};
+
+ auto value = sqlite3_column_int64(m_compiledStatement.get(), column);
- return sqlite3_column_int64(m_compiledStatement.get(), column);
+ tracer.end(keyValue("value", value));
+
+ return value;
}
template<>
@@ -486,14 +544,24 @@ long long BaseStatement::fetchValue<long long>(int column) const
double BaseStatement::fetchDoubleValue(int column) const
{
- NanotraceHR::Tracer tracer{"fetch double"_t, sqliteLowLevelCategory()};
+ NanotraceHR::Tracer tracer{"fetch double"_t,
+ sqliteLowLevelCategory(),
+ keyValue("sqlite statement", handle()),
+ keyValue("column", column)};
+
+ auto value = sqlite3_column_double(m_compiledStatement.get(), column);
+
+ tracer.end(keyValue("value", value));
- return sqlite3_column_double(m_compiledStatement.get(), column);
+ return value;
}
BlobView BaseStatement::fetchBlobValue(int column) const
{
- NanotraceHR::Tracer tracer{"fetch blob"_t, sqliteLowLevelCategory()};
+ NanotraceHR::Tracer tracer{"fetch blob"_t,
+ sqliteLowLevelCategory(),
+ keyValue("sqlite statement", handle()),
+ keyValue("column", column)};
return convertToBlobForColumn(m_compiledStatement.get(), column);
}
@@ -507,7 +575,16 @@ double BaseStatement::fetchValue<double>(int column) const
template<typename StringType>
StringType BaseStatement::fetchValue(int column) const
{
- return convertToTextForColumn<StringType>(m_compiledStatement.get(), column);
+ NanotraceHR::Tracer tracer{"fetch string value"_t,
+ sqliteLowLevelCategory(),
+ keyValue("sqlite statement", handle()),
+ keyValue("column", column)};
+
+ auto text = convertToTextForColumn<StringType>(m_compiledStatement.get(), column);
+
+ tracer.end(keyValue("text", text));
+
+ return text;
}
template SQLITE_EXPORT Utils::SmallStringView BaseStatement::fetchValue<Utils::SmallStringView>(
@@ -519,11 +596,25 @@ template SQLITE_EXPORT Utils::PathString BaseStatement::fetchValue<Utils::PathSt
Utils::SmallStringView BaseStatement::fetchSmallStringViewValue(int column) const
{
- return fetchValue<Utils::SmallStringView>(column);
+ NanotraceHR::Tracer tracer{"fetch string view"_t,
+ sqliteLowLevelCategory(),
+ keyValue("sqlite statement", handle()),
+ keyValue("column", column)};
+
+ auto text = fetchValue<Utils::SmallStringView>(column);
+
+ tracer.end(keyValue("text", text));
+
+ return text;
}
ValueView BaseStatement::fetchValueView(int column) const
{
+ NanotraceHR::Tracer tracer{"fetch value view"_t,
+ sqliteLowLevelCategory(),
+ keyValue("sqlite statement", handle()),
+ keyValue("column", column)};
+
int dataType = sqlite3_column_type(m_compiledStatement.get(), column);
switch (dataType) {
case SQLITE_NULL:
@@ -543,7 +634,11 @@ ValueView BaseStatement::fetchValueView(int column) const
void BaseStatement::Deleter::operator()(sqlite3_stmt *statement)
{
- NanotraceHR::Tracer tracer{"finalize"_t, sqliteLowLevelCategory()};
+ NanotraceHR::Tracer tracer{
+ "finalize"_t,
+ sqliteLowLevelCategory(),
+ keyValue("sqlite statement", reinterpret_cast<std::uintptr_t>(statement)),
+ };
sqlite3_finalize(statement);
}
diff --git a/src/libs/sqlite/sqlitebasestatement.h b/src/libs/sqlite/sqlitebasestatement.h
index d2306c67a5..3710021ff5 100644
--- a/src/libs/sqlite/sqlitebasestatement.h
+++ b/src/libs/sqlite/sqlitebasestatement.h
@@ -9,6 +9,7 @@
#include "sqliteblob.h"
#include "sqliteexception.h"
#include "sqliteids.h"
+#include "sqlitetracing.h"
#include "sqlitetransaction.h"
#include "sqlitevalue.h"
@@ -30,8 +31,6 @@ using std::int64_t;
namespace Sqlite {
-using namespace NanotraceHR::Literals;
-
class Database;
class DatabaseBackend;
@@ -44,17 +43,6 @@ constexpr static std::underlying_type_t<Enumeration> to_underlying(Enumeration e
return static_cast<std::underlying_type_t<Enumeration>>(enumeration);
}
-constexpr NanotraceHR::Tracing sqliteTracingStatus()
-{
-#ifdef ENABLE_SQLITE_TRACING
- return NanotraceHR::tracingStatus();
-#else
- return NanotraceHR::Tracing::IsDisabled;
-#endif
-}
-
-SQLITE_EXPORT NanotraceHR::StringViewCategory<sqliteTracingStatus()> &sqliteHighLevelCategory();
-
class SQLITE_EXPORT BaseStatement
{
public:
@@ -136,6 +124,11 @@ public:
protected:
~BaseStatement() = default;
+ std::uintptr_t handle() const
+ {
+ return reinterpret_cast<std::uintptr_t>(m_compiledStatement.get());
+ }
+
private:
struct Deleter
{
@@ -166,7 +159,12 @@ public:
void execute()
{
- NanotraceHR::Tracer tracer{"execute"_t, sqliteHighLevelCategory()};
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{
+ "execute"_t,
+ sqliteHighLevelCategory(),
+ keyValue("sqlite statement", BaseStatement::handle()),
+ };
Resetter resetter{this};
BaseStatement::next();
@@ -175,7 +173,10 @@ public:
template<typename... ValueType>
void bindValues(const ValueType &...values)
{
- NanotraceHR::Tracer tracer{"bind"_t, sqliteHighLevelCategory()};
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"bind"_t,
+ sqliteHighLevelCategory(),
+ keyValue("sqlite statement", BaseStatement::handle())};
static_assert(BindParameterCount == sizeof...(values), "Wrong binding parameter count!");
@@ -186,7 +187,10 @@ public:
template<typename... ValueType>
void write(const ValueType&... values)
{
- NanotraceHR::Tracer tracer{"write"_t, sqliteHighLevelCategory()};
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"write"_t,
+ sqliteHighLevelCategory(),
+ keyValue("sqlite statement", BaseStatement::handle())};
Resetter resetter{this};
bindValues(values...);
@@ -206,24 +210,37 @@ public:
struct is_container<QVarLengthArray<T, Prealloc>> : std::true_type
{};
+ template<typename T>
+ struct is_small_container : std::false_type
+ {};
+
+ template<typename T, qsizetype Prealloc>
+ struct is_small_container<QVarLengthArray<T, Prealloc>> : std::true_type
+ {};
+
template<typename Container,
std::size_t capacity = 32,
typename = std::enable_if_t<is_container<Container>::value>,
typename... QueryTypes>
auto values(const QueryTypes &...queryValues)
{
- NanotraceHR::Tracer tracer{"values"_t, sqliteHighLevelCategory()};
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"values"_t,
+ sqliteHighLevelCategory(),
+ keyValue("sqlite statement", BaseStatement::handle())};
Resetter resetter{this};
Container resultValues;
- resultValues.reserve(std::max(capacity, m_maximumResultCount));
+ using size_tupe = typename Container::size_type;
+ if constexpr (!is_small_container<Container>::value)
+ resultValues.reserve(static_cast<size_tupe>(std::max(capacity, m_maximumResultCount)));
bindValues(queryValues...);
while (BaseStatement::next())
emplaceBackValues(resultValues);
- setMaximumResultCount(resultValues.size());
+ setMaximumResultCount(static_cast<std::size_t>(resultValues.size()));
return resultValues;
}
@@ -241,7 +258,10 @@ public:
template<typename ResultType, typename... QueryTypes>
auto value(const QueryTypes &...queryValues)
{
- NanotraceHR::Tracer tracer{"value"_t, sqliteHighLevelCategory()};
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"value"_t,
+ sqliteHighLevelCategory(),
+ keyValue("sqlite statement", BaseStatement::handle())};
Resetter resetter{this};
ResultType resultValue{};
@@ -257,7 +277,10 @@ public:
template<typename ResultType, typename... QueryTypes>
auto optionalValue(const QueryTypes &...queryValues)
{
- NanotraceHR::Tracer tracer{"optionalValue"_t, sqliteHighLevelCategory()};
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"optionalValue"_t,
+ sqliteHighLevelCategory(),
+ keyValue("sqlite statement", BaseStatement::handle())};
Resetter resetter{this};
std::optional<ResultType> resultValue;
@@ -273,6 +296,7 @@ public:
template<typename Type>
static auto toValue(Utils::SmallStringView sqlStatement, Database &database)
{
+ using NanotraceHR::keyValue;
NanotraceHR::Tracer tracer{"toValue"_t, sqliteHighLevelCategory()};
StatementImplementation statement(sqlStatement, database);
@@ -287,7 +311,10 @@ public:
template<typename Callable, typename... QueryTypes>
void readCallback(Callable &&callable, const QueryTypes &...queryValues)
{
- NanotraceHR::Tracer tracer{"readCallback"_t, sqliteHighLevelCategory()};
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"readCallback"_t,
+ sqliteHighLevelCategory(),
+ keyValue("sqlite statement", BaseStatement::handle())};
Resetter resetter{this};
@@ -304,7 +331,10 @@ public:
template<typename Container, typename... QueryTypes>
void readTo(Container &container, const QueryTypes &...queryValues)
{
- NanotraceHR::Tracer tracer{"readTo"_t, sqliteHighLevelCategory()};
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"readTo"_t,
+ sqliteHighLevelCategory(),
+ keyValue("sqlite statement", BaseStatement::handle())};
Resetter resetter{this};
@@ -402,9 +432,11 @@ public:
private:
using TracerCategory = std::decay_t<decltype(sqliteHighLevelCategory())>;
- NanotraceHR::Tracer<TracerCategory, typename TracerCategory::IsActive> tracer{
- "range"_t, sqliteHighLevelCategory()};
StatementImplementation &m_statement;
+ NanotraceHR::Tracer<TracerCategory, typename TracerCategory::IsActive> tracer{
+ "range"_t,
+ sqliteHighLevelCategory(),
+ NanotraceHR::keyValue("sqlite statement", m_statement.handle())};
};
template<typename ResultType>
diff --git a/src/libs/sqlite/sqliteexception.cpp b/src/libs/sqlite/sqliteexception.cpp
index b5f581ad68..bb4a474adb 100644
--- a/src/libs/sqlite/sqliteexception.cpp
+++ b/src/libs/sqlite/sqliteexception.cpp
@@ -3,14 +3,20 @@
#include "sqliteexception.h"
+#include "sqlitetracing.h"
+
#include <utils/smallstringio.h>
+#include <nanotrace/nanotracehr.h>
+
#include <sqlite.h>
#include <QDebug>
namespace Sqlite {
+using NanotraceHR::keyValue;
+
const char *Exception::what() const noexcept
{
return "Sqlite::Exception";
@@ -18,7 +24,10 @@ const char *Exception::what() const noexcept
const char *ExceptionWithMessage::what() const noexcept
{
- return "Sqlite::ExceptionWithMessage";
+ static Utils::SmallString text = Utils::SmallString::join(
+ {"Sqlite::ExceptionWithMessage", m_sqliteErrorMessage});
+
+ return text.data();
}
void ExceptionWithMessage::printWarning() const
@@ -26,6 +35,13 @@ void ExceptionWithMessage::printWarning() const
qWarning() << what() << m_sqliteErrorMessage;
}
+StatementIsBusy::StatementIsBusy(Utils::SmallString &&sqliteErrorMessage)
+ : ExceptionWithMessage{std::move(sqliteErrorMessage)}
+{
+ sqliteHighLevelCategory().threadEvent("StatementIsBusy"_t,
+ keyValue("error message", std::string_view{what()}));
+}
+
const char *StatementIsBusy::what() const noexcept
{
return "Sqlite::StatementIsBusy";
@@ -36,9 +52,19 @@ const char *DatabaseIsBusy::what() const noexcept
return "Sqlite::DatabaseIsBusy";
}
+StatementHasError::StatementHasError(Utils::SmallString &&sqliteErrorMessage)
+ : ExceptionWithMessage{std::move(sqliteErrorMessage)}
+{
+ sqliteHighLevelCategory().threadEvent("StatementHasError"_t,
+ keyValue("error message", std::string_view{what()}));
+}
+
const char *StatementHasError::what() const noexcept
{
- return "Sqlite::StatementHasError";
+ static Utils::SmallString text = Utils::SmallString::join(
+ {"Sqlite::StatementHasError: ", message()});
+
+ return text.data();
}
const char *StatementIsMisused::what() const noexcept
diff --git a/src/libs/sqlite/sqliteexception.h b/src/libs/sqlite/sqliteexception.h
index f0cadfc748..17a0639e19 100644
--- a/src/libs/sqlite/sqliteexception.h
+++ b/src/libs/sqlite/sqliteexception.h
@@ -23,13 +23,15 @@ public:
class SQLITE_EXPORT ExceptionWithMessage : public Exception
{
public:
- ExceptionWithMessage(Utils::SmallString &&sqliteErrorMessage = Utils::SmallString{})
+ ExceptionWithMessage(Utils::SmallString &&sqliteErrorMessage = {})
: m_sqliteErrorMessage(std::move(sqliteErrorMessage))
{}
const char *what() const noexcept override;
void printWarning() const;
+ std::string_view message() const noexcept { return m_sqliteErrorMessage; }
+
private:
Utils::SmallString m_sqliteErrorMessage;
};
@@ -37,7 +39,7 @@ private:
class SQLITE_EXPORT StatementIsBusy : public ExceptionWithMessage
{
public:
- using ExceptionWithMessage::ExceptionWithMessage;
+ StatementIsBusy(Utils::SmallString &&sqliteErrorMessage);
const char *what() const noexcept override;
};
@@ -90,7 +92,8 @@ public:
class SQLITE_EXPORT StatementHasError : public ExceptionWithMessage
{
public:
- using ExceptionWithMessage::ExceptionWithMessage;
+ StatementHasError(Utils::SmallString &&sqliteErrorMessage);
+
const char *what() const noexcept override;
};
diff --git a/src/libs/sqlite/sqliteids.h b/src/libs/sqlite/sqliteids.h
index d64e4d9645..1ffd546d9f 100644
--- a/src/libs/sqlite/sqliteids.h
+++ b/src/libs/sqlite/sqliteids.h
@@ -5,6 +5,7 @@
#include <utils/span.h>
+#include <nanotrace/nanotracehr.h>
#include <type_traits>
#include <vector>
@@ -64,6 +65,15 @@ public:
[[noreturn, deprecated]] InternalIntegerType operator&() const { throw std::exception{}; }
+ template<typename String>
+ friend void convertToString(String &string, BasicId id)
+ {
+ if (id.isValid())
+ NanotraceHR::convertToString(string, id.internalId());
+ else
+ NanotraceHR::convertToString(string, "invalid");
+ }
+
private:
InternalIntegerType id = 0;
};
@@ -88,4 +98,5 @@ struct hash<Sqlite::BasicId<Type, InternalIntegerType>>
return std::hash<InternalIntegerType>{}(id.internalId());
}
};
+
} // namespace std
diff --git a/src/libs/sqlite/sqliteindex.h b/src/libs/sqlite/sqliteindex.h
index f320fcd599..7c7a8dbb2b 100644
--- a/src/libs/sqlite/sqliteindex.h
+++ b/src/libs/sqlite/sqliteindex.h
@@ -40,6 +40,8 @@ public:
return Utils::SmallString::join({"CREATE ",
m_indexType == IndexType::Unique ? "UNIQUE " : "",
"INDEX IF NOT EXISTS index_",
+ kindName(),
+ "_",
m_tableName,
"_",
m_columnNames.join("_"),
@@ -65,6 +67,23 @@ public:
}
private:
+ std::string_view kindName() const
+ {
+ using namespace std::string_view_literals;
+
+ if (m_indexType == IndexType::Unique && m_condition.hasContent())
+ return "unique_partial"sv;
+
+ if (m_indexType == IndexType::Unique)
+ return "unique"sv;
+
+ if (m_condition.hasContent())
+ return "partial"sv;
+
+ return "normal"sv;
+ }
+
+private:
Utils::SmallString m_tableName;
Utils::SmallStringVector m_columnNames;
IndexType m_indexType;
diff --git a/src/libs/sqlite/sqlitetracing.cpp b/src/libs/sqlite/sqlitetracing.cpp
new file mode 100644
index 0000000000..700546f146
--- /dev/null
+++ b/src/libs/sqlite/sqlitetracing.cpp
@@ -0,0 +1,38 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "sqlitetracing.h"
+
+namespace Sqlite {
+
+TraceFile &traceFile()
+{
+ static TraceFile traceFile{"tracing.json"};
+
+ return traceFile;
+}
+
+namespace {
+
+thread_local NanotraceHR::EventQueue<NanotraceHR::StringViewWithStringArgumentsTraceEvent,
+ sqliteTracingStatus()>
+ eventQueue(traceFile());
+
+} // namespace
+
+NanotraceHR::StringViewWithStringArgumentsCategory<sqliteTracingStatus()> &sqliteLowLevelCategory()
+{
+ thread_local NanotraceHR::StringViewWithStringArgumentsCategory<sqliteTracingStatus()>
+ sqliteLowLevelCategory_{"sqlite low level"_t, eventQueue, sqliteLowLevelCategory};
+ return sqliteLowLevelCategory_;
+}
+
+NanotraceHR::StringViewWithStringArgumentsCategory<sqliteTracingStatus()> &sqliteHighLevelCategory()
+{
+ thread_local NanotraceHR::StringViewWithStringArgumentsCategory<sqliteTracingStatus()>
+ sqliteHighLevelCategory_{"sqlite high level"_t, eventQueue, sqliteHighLevelCategory};
+
+ return sqliteHighLevelCategory_;
+}
+
+} // namespace Sqlite
diff --git a/src/libs/sqlite/sqlitetracing.h b/src/libs/sqlite/sqlitetracing.h
new file mode 100644
index 0000000000..8dadc6de0d
--- /dev/null
+++ b/src/libs/sqlite/sqlitetracing.h
@@ -0,0 +1,29 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "sqliteglobal.h"
+
+#include <nanotrace/nanotracehr.h>
+
+namespace Sqlite {
+using namespace NanotraceHR::Literals;
+
+constexpr NanotraceHR::Tracing sqliteTracingStatus()
+{
+#ifdef ENABLE_SQLITE_TRACING
+ return NanotraceHR::Tracing::IsEnabled;
+#else
+ return NanotraceHR::Tracing::IsDisabled;
+#endif
+}
+
+using TraceFile = NanotraceHR::TraceFile<sqliteTracingStatus()>;
+
+SQLITE_EXPORT TraceFile &traceFile();
+
+NanotraceHR::StringViewWithStringArgumentsCategory<sqliteTracingStatus()> &sqliteLowLevelCategory();
+
+SQLITE_EXPORT NanotraceHR::StringViewWithStringArgumentsCategory<sqliteTracingStatus()> &
+sqliteHighLevelCategory();
+
+} // namespace Sqlite
diff --git a/src/libs/sqlite/sqlitevalue.h b/src/libs/sqlite/sqlitevalue.h
index fe576f3fec..725682494b 100644
--- a/src/libs/sqlite/sqlitevalue.h
+++ b/src/libs/sqlite/sqlitevalue.h
@@ -6,6 +6,7 @@
#include "sqliteblob.h"
#include "sqliteexception.h"
+#include <nanotrace/nanotracehr.h>
#include <utils/smallstring.h>
#include <QVariant>
@@ -33,7 +34,7 @@ public:
explicit ValueBase(NullValue) {}
explicit ValueBase(VariantType &&value)
- : value(value)
+ : value(std::move(value))
{}
explicit ValueBase(const char *value)
@@ -43,6 +44,7 @@ public:
explicit ValueBase(long long value)
: value(value)
{}
+
explicit ValueBase(int value)
: value(static_cast<long long>(value))
{}
@@ -60,11 +62,6 @@ public:
{}
- explicit ValueBase(StringType &&value)
- : value(std::move(value))
-
- {}
-
explicit ValueBase(BlobView value)
: value(value)
@@ -229,14 +226,42 @@ public:
class ValueView : public ValueBase<Utils::SmallStringView, BlobView>
{
public:
+ ValueView() = default;
+
+ explicit ValueView(NullValue) {}
+
explicit ValueView(ValueBase &&base)
: ValueBase(std::move(base))
{}
+ explicit ValueView(Utils::SmallStringView value)
+ : ValueBase(value)
+ {}
+
+ explicit ValueView(BlobView value)
+ : ValueBase(value)
+ {}
+
+ explicit ValueView(long long value)
+ : ValueBase(value)
+ {}
+
+ explicit ValueView(int value)
+ : ValueBase(static_cast<long long>(value))
+ {}
+
+ explicit ValueView(uint value)
+ : ValueBase(static_cast<long long>(value))
+ {}
+
+ explicit ValueView(double value)
+ : ValueBase(value)
+ {}
+
template<typename Type>
static ValueView create(Type &&value_)
{
- return ValueView{ValueBase{value_}};
+ return ValueView(std::forward<Type>(value_));
}
};
@@ -386,4 +411,27 @@ private:
};
using Values = std::vector<Value>;
+
+template<typename String>
+void convertToString(String &string, const Value &value)
+{
+ switch (value.type()) {
+ case ValueType::Null:
+ convertToString(string, "null");
+ break;
+ case ValueType::Integer:
+ convertToString(string, value.toInteger());
+ break;
+ case ValueType::Float:
+ convertToString(string, value.toFloat());
+ break;
+ case ValueType::String:
+ convertToString(string, value.toStringView());
+ break;
+ case ValueType::Blob:
+ convertToString(string, "blob");
+ break;
+ }
+}
+
} // namespace Sqlite
diff --git a/src/libs/utils/smallstring.h b/src/libs/utils/smallstring.h
index c522a6cae9..e8c3d74b92 100644
--- a/src/libs/utils/smallstring.h
+++ b/src/libs/utils/smallstring.h
@@ -93,7 +93,7 @@ public:
static_cast<std::size_t>(std::distance(begin, end))}
{}
- template<typename Type, typename = std::enable_if_t<std::is_pointer<Type>::value>>
+ template<typename Type, typename std::enable_if_t<std::is_pointer<Type>::value, bool> = true>
BasicSmallString(Type characterPointer) noexcept
: BasicSmallString(characterPointer, std::char_traits<char>::length(characterPointer))
{
@@ -118,7 +118,7 @@ public:
template<typename BeginIterator,
typename EndIterator,
- typename = std::enable_if_t<std::is_same<BeginIterator, EndIterator>::value>>
+ typename std::enable_if_t<std::is_same<BeginIterator, EndIterator>::value, bool> = true>
BasicSmallString(BeginIterator begin, EndIterator end) noexcept
: BasicSmallString(&(*begin), size_type(end - begin))
{}
@@ -354,6 +354,14 @@ public:
return false;
}
+ bool startsWith(QStringView subStringToSearch) const noexcept
+ {
+ if (size() >= Utils::usize(subStringToSearch))
+ return subStringToSearch == QLatin1StringView{data(), subStringToSearch.size()};
+
+ return false;
+ }
+
bool startsWith(char characterToSearch) const noexcept
{
return data()[0] == characterToSearch;
@@ -423,13 +431,55 @@ public:
size_type oldSize = size();
size_type newSize = oldSize + string.size();
- reserve(optimalCapacity(newSize));
+ if (fitsNotInCapacity(newSize))
+ reserve(optimalCapacity(newSize));
+
std::char_traits<char>::copy(std::next(data(), static_cast<std::ptrdiff_t>(oldSize)),
string.data(),
string.size());
setSize(newSize);
}
+ void append(char character) noexcept
+ {
+ size_type oldSize = size();
+ size_type newSize = oldSize + 1;
+
+ if (fitsNotInCapacity(newSize))
+ reserve(optimalCapacity(newSize));
+
+ auto current = std::next(data(), static_cast<std::ptrdiff_t>(oldSize));
+ *current = character;
+ setSize(newSize);
+ }
+
+ template<typename Type, typename std::enable_if_t<std::is_arithmetic_v<Type>, bool> = true>
+ void append(Type number)
+ {
+#if defined(__cpp_lib_to_chars) && (__cpp_lib_to_chars >= 201611L)
+ // 2 bytes for the sign and because digits10 returns the floor
+ char buffer[std::numeric_limits<Type>::digits10 + 2];
+ auto result = std::to_chars(buffer, buffer + sizeof(buffer), number);
+ auto endOfConversionString = result.ptr;
+
+ append({buffer, endOfConversionString});
+#else
+ if constexpr (std::is_floating_point_v<Type>) {
+ QLocale locale{QLocale::Language::C};
+ append(locale.toString(number));
+ return;
+ } else {
+ // 2 bytes for the sign and because digits10 returns the floor
+ char buffer[std::numeric_limits<Type>::digits10 + 2];
+ auto result = std::to_chars(buffer, buffer + sizeof(buffer), number);
+ auto endOfConversionString = result.ptr;
+
+ append({buffer, endOfConversionString});
+ }
+
+#endif
+ }
+
void append(QStringView string) noexcept
{
QStringEncoder encoder{QStringEncoder::Utf8};
@@ -469,6 +519,13 @@ public:
return *this;
}
+ BasicSmallString &operator+=(char character) noexcept
+ {
+ append(character);
+
+ return *this;
+ }
+
BasicSmallString &operator+=(QStringView string) noexcept
{
append(string);
@@ -476,6 +533,14 @@ public:
return *this;
}
+ template<typename Type, typename std::enable_if_t<std::is_arithmetic_v<Type>, bool> = true>
+ BasicSmallString &operator+=(Type number) noexcept
+ {
+ append(number);
+
+ return *this;
+ }
+
BasicSmallString &operator+=(std::initializer_list<SmallStringView> list) noexcept
{
appendInitializerList(list, size());
@@ -580,37 +645,12 @@ public:
return joinedString;
}
- static
- BasicSmallString number(int number)
+ template<typename Type, typename std::enable_if_t<std::is_arithmetic_v<Type>, bool> = true>
+ static BasicSmallString number(Type number)
{
- // 2 bytes for the sign and because digits10 returns the floor
- char buffer[std::numeric_limits<int>::digits10 + 2];
- auto result = std::to_chars(buffer, buffer + sizeof(buffer), number);
- auto endOfConversionString = result.ptr;
- return BasicSmallString(buffer, endOfConversionString);
- }
-
- static BasicSmallString number(long long int number) noexcept
- {
- // 2 bytes for the sign and because digits10 returns the floor
- char buffer[std::numeric_limits<long long int>::digits10 + 2];
- auto result = std::to_chars(buffer, buffer + sizeof(buffer), number);
- auto endOfConversionString = result.ptr;
- return BasicSmallString(buffer, endOfConversionString);
- }
-
- static BasicSmallString number(double number) noexcept
- {
-#if defined(__cpp_lib_to_chars) && (__cpp_lib_to_chars >= 201611L)
- // 2 bytes for the sign and because digits10 returns the floor
- char buffer[std::numeric_limits<double>::digits10 + 2];
- auto result = std::to_chars(buffer, buffer + sizeof(buffer), number);
- auto endOfConversionString = result.ptr;
- return BasicSmallString(buffer, endOfConversionString);
-#else
- QLocale locale{QLocale::Language::C};
- return BasicSmallString{locale.toString(number)};
-#endif
+ BasicSmallString string;
+ string.append(number);
+ return string;
}
char &operator[](std::size_t index) noexcept { return *(data() + index); }
@@ -655,7 +695,6 @@ public:
friend BasicSmallString operator+(const BasicSmallString &first,
const char (&second)[ArraySize]) noexcept
{
-
return operator+(first, SmallStringView(second));
}
@@ -687,8 +726,10 @@ unittest_public:
bool fitsNotInCapacity(size_type capacity) const noexcept
{
- return (isShortString() && capacity > shortStringCapacity())
- || (!isShortString() && capacity > m_data.reference.capacity);
+ if (isShortString())
+ return capacity > shortStringCapacity();
+
+ return capacity > m_data.reference.capacity;
}
static size_type optimalHeapCapacity(const size_type size) noexcept
diff --git a/src/plugins/android/androidmanager.cpp b/src/plugins/android/androidmanager.cpp
index 3666762be6..5128f761a0 100644
--- a/src/plugins/android/androidmanager.cpp
+++ b/src/plugins/android/androidmanager.cpp
@@ -532,7 +532,7 @@ QString androidNameForApiLevel(int x)
case 33:
return QLatin1String("Android 13.0 (\"Tiramisu\")");
case 34:
- return QLatin1String("Android API 34");
+ return QLatin1String("Android 14.0 (\"UpsideDownCake\")");
default:
return Tr::tr("Unknown Android version. API Level: %1").arg(x);
}
diff --git a/src/plugins/coreplugin/icore.cpp b/src/plugins/coreplugin/icore.cpp
index 85401aa8bc..a625895b68 100644
--- a/src/plugins/coreplugin/icore.cpp
+++ b/src/plugins/coreplugin/icore.cpp
@@ -2575,6 +2575,7 @@ void ICorePrivate::changeLog()
});
auto versionCombo = new QComboBox;
+ versionCombo->setMinimumWidth(80);
for (const VersionFilePair &f : versionedFiles)
versionCombo->addItem(f.first.toString());
dialog = new LogDialog(ICore::dialogParent());
diff --git a/src/plugins/effectcomposer/compositionnode.cpp b/src/plugins/effectcomposer/compositionnode.cpp
index 108eb5801d..d939e2283a 100644
--- a/src/plugins/effectcomposer/compositionnode.cpp
+++ b/src/plugins/effectcomposer/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("extraMargin"))
+ m_extraMargin = json.value("extraMargin").toInt();
+
if (json.contains("enabled"))
m_isEnabled = json["enabled"].toBool();
diff --git a/src/plugins/effectcomposer/compositionnode.h b/src/plugins/effectcomposer/compositionnode.h
index b3348bb38f..433468688a 100644
--- a/src/plugins/effectcomposer/compositionnode.h
+++ b/src/plugins/effectcomposer/compositionnode.h
@@ -52,6 +52,8 @@ public:
int decRefCount();
void setRefCount(int count);
+ int extraMargin() const { return m_extraMargin; }
+
signals:
void uniformsModelChanged();
void isEnabledChanged();
@@ -70,6 +72,7 @@ private:
QString m_id;
bool m_isEnabled = true;
int m_refCount = 0;
+ int m_extraMargin = 0;
QList<Uniform *> m_uniforms;
diff --git a/src/plugins/effectcomposer/effectcomposermodel.cpp b/src/plugins/effectcomposer/effectcomposermodel.cpp
index 5a5ad5718c..a983072334 100644
--- a/src/plugins/effectcomposer/effectcomposermodel.cpp
+++ b/src/plugins/effectcomposer/effectcomposermodel.cpp
@@ -94,6 +94,11 @@ bool EffectComposerModel::setData(const QModelIndex &index, const QVariant &valu
return true;
}
+void EffectComposerModel::setEffectsTypePrefix(const QString &prefix)
+{
+ m_effectTypePrefix = prefix;
+}
+
void EffectComposerModel::setIsEmpty(bool val)
{
if (m_isEmpty != val) {
@@ -207,14 +212,14 @@ void EffectComposerModel::clear(bool clearName)
void EffectComposerModel::assignToSelected()
{
const QString effectsAssetsDir = QmlDesigner::ModelNodeOperations::getEffectsDefaultDirectory();
- const QString path = effectsAssetsDir + QDir::separator() + m_currentComposition + ".qep";
+ const QString path = effectsAssetsDir + '/' + m_currentComposition + ".qep";
emit assignToSelectedTriggered(path);
}
QString EffectComposerModel::getUniqueEffectName() const
{
const QString effectsDir = QmlDesigner::ModelNodeOperations::getEffectsDefaultDirectory();
- const QString path = effectsDir + QDir::separator() + "Effect%1.qep";
+ const QString path = effectsDir + '/' + "Effect%1.qep";
int num = 0;
@@ -224,6 +229,14 @@ QString EffectComposerModel::getUniqueEffectName() const
return QString("Effect%1").arg(num, 2, 10, QChar('0'));
}
+bool EffectComposerModel::nameExists(const QString &name) const
+{
+ const QString effectsDir = QmlDesigner::ModelNodeOperations::getEffectsDefaultDirectory();
+ const QString path = effectsDir + '/' + "%1" + ".qep";
+
+ return QFile::exists(path.arg(name));
+}
+
QString EffectComposerModel::fragmentShader() const
{
return m_fragmentShader;
@@ -490,6 +503,8 @@ QJsonObject nodeToJson(const CompositionNode &node)
nodeObject.insert("enabled", node.isEnabled());
nodeObject.insert("version", 1);
nodeObject.insert("id", node.id());
+ if (node.extraMargin())
+ nodeObject.insert("extraMargin", node.extraMargin());
// Add properties
QJsonArray propertiesArray;
@@ -676,10 +691,44 @@ R"(
)";
s += frameProp.arg(tr("Frame"), tr("This property allows explicit control of current animation frame."));
}
+
s += " }\n";
s += " }\n";
}
+ if (m_shaderFeatures.enabled(ShaderFeatures::Source) && m_extraMargin) {
+ QString generalSection =
+ R"(
+ Section {
+ caption: "%1"
+ width: parent.width
+
+ SectionLayout {
+ PropertyLabel {
+ text: "%2"
+ tooltip: "%3"
+ }
+
+ SecondColumnLayout {
+ SpinBox {
+ minimumValue: 0
+ maximumValue: 1000
+ decimals: 0
+ stepSize: 1
+ sliderIndicatorVisible: true
+ backendValue: backendValues.extraMargin
+ implicitWidth: StudioTheme.Values.singleControlColumnWidth
+ + StudioTheme.Values.actionIndicatorWidth
+ }
+ ExpandingSpacer {}
+ }
+ }
+ }
+)";
+ s += generalSection.arg(tr("General"), tr("Extra Margin"),
+ tr("This property specifies how much of extra space is reserved for the effect outside the parent geometry."));
+ }
+
for (const auto &node : std::as_const(m_nodes)) {
const QList<Uniform *> uniforms = static_cast<EffectComposerUniformsModel *>(
node->uniformsModel())->uniforms();
@@ -739,8 +788,46 @@ Item {
s += header;
if (m_shaderFeatures.enabled(ShaderFeatures::Source)) {
- s += " // This is the main source for the effect. Set internally to the current parent item. Do not modify.\n";
- s += " property Item source: null\n";
+ QString sourceStr{
+R"(
+ // This is the main source for the effect. Set internally to the current parent item. Do not modify.
+ property Item source: null
+)"
+ };
+
+ QString extraMarginStr{
+R"(
+ // This property specifies how much of extra space is reserved for the effect outside the parent geometry.
+ // It should be sufficient for most use cases but if the application uses extreme values it may be necessary to
+ // increase this value.
+ property int extraMargin: %1
+
+ onExtraMarginChanged: setupSourceRect()
+
+ function setupSourceRect() {
+ if (source) {
+ var w = source.width + extraMargin * 2
+ var h = source.height + extraMargin * 2
+ source.layer.sourceRect = Qt.rect(-extraMargin, -extraMargin, w, h)
+ }
+ }
+
+ function connectSource(enable) {
+ if (source) {
+ if (enable) {
+ source.widthChanged.connect(setupSourceRect)
+ source.heightChanged.connect(setupSourceRect)
+ } else {
+ source.widthChanged.disconnect(setupSourceRect)
+ source.heightChanged.disconnect(setupSourceRect)
+ }
+ }
+ }
+)"
+ };
+ s += sourceStr;
+ if (m_extraMargin)
+ s += extraMarginStr.arg(m_extraMargin);
}
if (m_shaderFeatures.enabled(ShaderFeatures::Time)
|| m_shaderFeatures.enabled(ShaderFeatures::Frame)) {
@@ -762,7 +849,8 @@ R"(
if (_oldParent && _oldParent !== parent) {
_oldParent.layer.enabled = false
_oldParent.layer.effect = null
- %2
+ %7
+ %4%2
_oldParent.update()
_oldParent = null
}
@@ -772,7 +860,8 @@ R"(
parent.layer.enabled = true
parent.layer.effect = effectComponent
}
- %1
+ %6
+ %4%1%5%3
}
}
@@ -780,35 +869,50 @@ R"(
if (visible) {
parent.layer.enabled = true
parent.layer.effect = effectComponent
- source = parent
+ %6
+ %4%1%5%3
} else {
parent.layer.enabled = false
parent.layer.effect = null
- source = null
+ %8
+ %4%2
}
parent.update()
}
+
)"
};
+ QString mipmap1;
+ QString mipmap2;
+ QString mipmap3;
if (m_shaderFeatures.enabled(ShaderFeatures::Mipmap)) {
- QString mipmap1{
+ mipmap1 = QString {
R"(parent.layer.smooth = true
- parent.layer.mipmap = true
- %1)"
+ parent.layer.mipmap = true)"
};
- QString mipmap2{
+ mipmap2 = QString {
R"(_oldParent.layer.smooth = false
- _oldParent.layer.mipmap = false
- %2)"
+ _oldParent.layer.mipmap = false)"
+ };
+ mipmap3 = QString {
+ R"(parent.layer.smooth = false
+ parent.layer.mipmap = false)"
};
- parentChanged = parentChanged.arg(mipmap1, mipmap2);
}
- parentChanged = parentChanged.arg(m_shaderFeatures.enabled(ShaderFeatures::Source)
- ? QString("source = parent") : QString(),
- m_shaderFeatures.enabled(ShaderFeatures::Source)
- ? QString("source = null") : QString());
+ if (m_shaderFeatures.enabled(ShaderFeatures::Source)) {
+ parentChanged = parentChanged.arg(QString("source = parent"),
+ QString("source = null"),
+ m_extraMargin ? QString(" setupSourceRect()") : QString(),
+ m_extraMargin ? QString("connectSource(false)\n ") : QString(),
+ m_extraMargin ? QString("\n connectSource(true)\n") : QString(),
+ mipmap1,
+ mipmap2,
+ mipmap3);
+ } else {
+ parentChanged = parentChanged.arg(QString(), QString(), QString());
+ }
s += parentChanged;
// Custom properties
@@ -846,7 +950,7 @@ void EffectComposerModel::saveComposition(const QString &name)
}
const QString effectsAssetsDir = QmlDesigner::ModelNodeOperations::getEffectsDefaultDirectory();
- const QString path = effectsAssetsDir + QDir::separator() + name + ".qep";
+ const QString path = effectsAssetsDir + '/' + name + ".qep";
auto saveFile = QFile(path);
if (!saveFile.open(QIODevice::WriteOnly)) {
QString error = QString("Error: Couldn't save composition file: '%1'").arg(path);
@@ -854,6 +958,8 @@ void EffectComposerModel::saveComposition(const QString &name)
return;
}
+ updateExtraMargin();
+
QJsonObject json;
// File format version
json.insert("version", 1);
@@ -974,7 +1080,7 @@ void EffectComposerModel::saveResources(const QString &name)
// Get effects dir
const Utils::FilePath effectsResDir = QmlDesigner::ModelNodeOperations::getEffectsImportDirectory();
- const QString effectsResPath = effectsResDir.pathAppended(name).toString() + QDir::separator();
+ const QString effectsResPath = effectsResDir.pathAppended(name).toString() + '/';
Utils::FilePath effectPath = Utils::FilePath::fromString(effectsResPath);
// Create the qmldir for effects
@@ -982,7 +1088,7 @@ void EffectComposerModel::saveResources(const QString &name)
Utils::FilePath qmldirPath = effectsResDir.resolvePath(qmldirFileName);
QString qmldirContent = QString::fromUtf8(qmldirPath.fileContents().value_or(QByteArray()));
if (qmldirContent.isEmpty()) {
- qmldirContent.append("module Effects\n");
+ qmldirContent.append(QString("module %1\n").arg(m_effectTypePrefix));
qmldirPath.writeFileContents(qmldirContent.toUtf8());
}
@@ -1000,7 +1106,7 @@ void EffectComposerModel::saveResources(const QString &name)
qmldirPath = effectPath.resolvePath(qmldirFileName);
qmldirContent = QString::fromUtf8(qmldirPath.fileContents().value_or(QByteArray()));
if (qmldirContent.isEmpty()) {
- qmldirContent.append("module Effects.");
+ qmldirContent.append(QString("module %1.").arg(m_effectTypePrefix));
qmldirContent.append(name);
qmldirContent.append('\n');
qmldirContent.append(name);
@@ -1041,7 +1147,27 @@ void EffectComposerModel::saveResources(const QString &name)
const QString qmlString = qmlStringList.join('\n');
QString qmlFilePath = effectsResPath + qmlFilename;
- writeToFile(qmlString.toUtf8(), qmlFilePath, FileType::Text);
+
+ // Get exposed properties from the old qml file if it exists
+ QSet<QByteArray> oldExposedProps;
+ Utils::FilePath oldQmlFile = Utils::FilePath::fromString(qmlFilePath);
+ if (oldQmlFile.exists()) {
+ const QByteArray oldQmlContent = oldQmlFile.fileContents().value();
+ oldExposedProps = getExposedProperties(oldQmlContent);
+ }
+
+ const QByteArray qmlUtf8 = qmlString.toUtf8();
+ if (!oldExposedProps.isEmpty()) {
+ const QSet<QByteArray> newExposedProps = getExposedProperties(qmlUtf8);
+ oldExposedProps.subtract(newExposedProps);
+ if (!oldExposedProps.isEmpty()) {
+ // If there were exposed properties that are no longer exposed, those
+ // need to be removed from any instances of the effect in the scene
+ emit removePropertiesFromScene(oldExposedProps, name);
+ }
+ }
+
+ writeToFile(qmlUtf8, qmlFilePath, FileType::Text);
newFileNames.append(qmlFilename);
// Save shaders and images
@@ -1110,7 +1236,7 @@ void EffectComposerModel::saveResources(const QString &name)
endResetModel();
}
- emit resourcesSaved(QString("Effects.%1.%1").arg(name).toUtf8(), effectPath);
+ emit resourcesSaved(QString("%1.%2.%2").arg(m_effectTypePrefix, name).toUtf8(), effectPath);
}
void EffectComposerModel::resetEffectError(int type)
@@ -1729,6 +1855,19 @@ void EffectComposerModel::setIsEnabled(bool enabled)
emit isEnabledChanged();
}
+bool EffectComposerModel::hasValidTarget() const
+{
+ return m_hasValidTarget;
+}
+
+void EffectComposerModel::setHasValidTarget(bool validTarget)
+{
+ if (m_hasValidTarget == validTarget)
+ return;
+ m_hasValidTarget = validTarget;
+ emit hasValidTargetChanged();
+}
+
QString EffectComposerModel::getQmlImagesString(bool localFiles)
{
QString imagesString;
@@ -1831,6 +1970,12 @@ QString EffectComposerModel::getQmlComponentString(bool localFiles)
s += l2 + "vertexShader: 'file:///" + vertFile + "'\n";
s += l2 + "fragmentShader: 'file:///" + fragFile + "'\n";
s += l2 + "anchors.fill: " + (localFiles ? "rootItem.source" : "parent") + "\n";
+ if (localFiles) {
+ if (m_extraMargin)
+ s += l2 + "anchors.margins: -rootItem.extraMargin\n";
+ } else {
+ s += l2 + "anchors.margins: -root.extraMargin\n";
+ }
if (m_shaderFeatures.enabled(ShaderFeatures::GridMesh)) {
QString gridSize = QString("%1, %2").arg(m_shaderFeatures.gridMeshWidth())
.arg(m_shaderFeatures.gridMeshHeight());
@@ -1866,6 +2011,32 @@ void EffectComposerModel::connectCompositionNode(CompositionNode *node)
});
}
+void EffectComposerModel::updateExtraMargin()
+{
+ m_extraMargin = 0;
+ for (CompositionNode *node : std::as_const(m_nodes))
+ m_extraMargin = qMax(node->extraMargin(), m_extraMargin);
+}
+
+QSet<QByteArray> EffectComposerModel::getExposedProperties(const QByteArray &qmlContent)
+{
+ QSet<QByteArray> returnSet;
+ const QByteArrayList lines = qmlContent.split('\n');
+ const QByteArray propertyTag {" property"}; // Match only toplevel exposed properties
+ for (const QByteArray &line : lines) {
+ if (line.startsWith(propertyTag)) {
+ QByteArrayList words = line.trimmed().split(' ');
+ if (words.size() >= 3) {
+ QByteArray propName = words[2];
+ if (propName.endsWith(':'))
+ propName.chop(1);
+ returnSet.insert(propName);
+ }
+ }
+ }
+ return returnSet;
+}
+
QString EffectComposerModel::currentComposition() const
{
return m_currentComposition;
diff --git a/src/plugins/effectcomposer/effectcomposermodel.h b/src/plugins/effectcomposer/effectcomposermodel.h
index bd4040efc2..14ef09e8a9 100644
--- a/src/plugins/effectcomposer/effectcomposermodel.h
+++ b/src/plugins/effectcomposer/effectcomposermodel.h
@@ -11,6 +11,7 @@
#include <QFileSystemWatcher>
#include <QMap>
#include <QRegularExpression>
+#include <QSet>
#include <QTemporaryFile>
#include <QTimer>
@@ -48,6 +49,7 @@ class EffectComposerModel : public QAbstractListModel
Q_PROPERTY(bool hasUnsavedChanges MEMBER m_hasUnsavedChanges WRITE setHasUnsavedChanges NOTIFY hasUnsavedChangesChanged)
Q_PROPERTY(bool shadersUpToDate READ shadersUpToDate WRITE setShadersUpToDate NOTIFY shadersUpToDateChanged)
Q_PROPERTY(bool isEnabled READ isEnabled WRITE setIsEnabled NOTIFY isEnabledChanged)
+ Q_PROPERTY(bool hasValidTarget READ hasValidTarget WRITE setHasValidTarget NOTIFY hasValidTargetChanged)
Q_PROPERTY(QString currentComposition READ currentComposition WRITE setCurrentComposition NOTIFY currentCompositionChanged)
public:
@@ -58,6 +60,8 @@ public:
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
+ void setEffectsTypePrefix(const QString &prefix);
+
bool isEmpty() const { return m_isEmpty; }
void setIsEmpty(bool val);
@@ -70,6 +74,7 @@ public:
Q_INVOKABLE void clear(bool clearName = false);
Q_INVOKABLE void assignToSelected();
Q_INVOKABLE QString getUniqueEffectName() const;
+ Q_INVOKABLE bool nameExists(const QString &name) const;
bool shadersUpToDate() const;
void setShadersUpToDate(bool newShadersUpToDate);
@@ -77,6 +82,9 @@ public:
bool isEnabled() const;
void setIsEnabled(bool enabled);
+ bool hasValidTarget() const;
+ void setHasValidTarget(bool validTarget);
+
QString fragmentShader() const;
void setFragmentShader(const QString &newFragmentShader);
@@ -110,12 +118,14 @@ signals:
void effectErrorChanged();
void shadersUpToDateChanged();
void isEnabledChanged();
+ void hasValidTargetChanged();
void shadersBaked();
void currentCompositionChanged();
void nodesChanged();
void resourcesSaved(const QByteArray &type, const Utils::FilePath &path);
void hasUnsavedChangesChanged();
void assignToSelectedTriggered(const QString &effectPath);
+ void removePropertiesFromScene(QSet<QByteArray> props, const QString &typeName);
private:
enum Roles {
@@ -176,6 +186,8 @@ private:
QString getDesignerSpecifics() const;
void connectCompositionNode(CompositionNode *node);
+ void updateExtraMargin();
+ QSet<QByteArray> getExposedProperties(const QByteArray &qmlContent);
QList<CompositionNode *> m_nodes;
@@ -210,8 +222,11 @@ private:
QString m_qmlComponentString;
bool m_loadComponentImages = true;
bool m_isEnabled = true;
+ bool m_hasValidTarget = false;
QString m_currentComposition;
QTimer m_rebakeTimer;
+ int m_extraMargin = 0;
+ QString m_effectTypePrefix;
const QRegularExpression m_spaceReg = QRegularExpression("\\s+");
};
diff --git a/src/plugins/effectcomposer/effectcomposeruniformsmodel.cpp b/src/plugins/effectcomposer/effectcomposeruniformsmodel.cpp
index 492d5a9e80..c2c162a87e 100644
--- a/src/plugins/effectcomposer/effectcomposeruniformsmodel.cpp
+++ b/src/plugins/effectcomposer/effectcomposeruniformsmodel.cpp
@@ -59,7 +59,9 @@ bool EffectComposerUniformsModel::setData(const QModelIndex &index, const QVaria
int idx = value.toString().indexOf("file:");
QString path = idx > 0 ? updatedValue.right(updatedValue.size() - idx - 5) : updatedValue;
- updatedValue = QUrl::fromLocalFile(path).toString();
+
+ if (idx == -1)
+ updatedValue = QUrl::fromLocalFile(path).toString();
uniform->setValue(updatedValue);
g_propertyData.insert(uniform->name(), updatedValue);
@@ -73,6 +75,14 @@ bool EffectComposerUniformsModel::setData(const QModelIndex &index, const QVaria
return true;
}
+bool EffectComposerUniformsModel::resetData(int row)
+{
+ QModelIndex idx = index(row, 0);
+ QTC_ASSERT(idx.isValid(), return false);
+
+ return setData(idx, idx.data(DefaultValueRole), ValueRole);
+}
+
void EffectComposerUniformsModel::resetModel()
{
beginResetModel();
diff --git a/src/plugins/effectcomposer/effectcomposeruniformsmodel.h b/src/plugins/effectcomposer/effectcomposeruniformsmodel.h
index 65b2d7b2f0..fc82194fdf 100644
--- a/src/plugins/effectcomposer/effectcomposeruniformsmodel.h
+++ b/src/plugins/effectcomposer/effectcomposeruniformsmodel.h
@@ -20,6 +20,7 @@ public:
int rowCount(const QModelIndex & parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
+ Q_INVOKABLE bool resetData(int row);
void resetModel();
diff --git a/src/plugins/effectcomposer/effectcomposerview.cpp b/src/plugins/effectcomposer/effectcomposerview.cpp
index e7a879bd8b..48c6a33c4b 100644
--- a/src/plugins/effectcomposer/effectcomposerview.cpp
+++ b/src/plugins/effectcomposer/effectcomposerview.cpp
@@ -10,7 +10,9 @@
#include <designermcumanager.h>
#include <documentmanager.h>
#include <modelnodeoperations.h>
+#include <qmlchangeset.h>
#include <qmldesignerconstants.h>
+#include <qmldesignerplugin.h>
#include <coreplugin/icore.h>
@@ -31,6 +33,7 @@ void EffectComposerContext::contextHelp(const HelpCallback &callback) const
EffectComposerView::EffectComposerView(QmlDesigner::ExternalDependenciesInterface &externalDependencies)
: AbstractView{externalDependencies}
+ , m_componentUtils(externalDependencies)
{
}
@@ -48,14 +51,73 @@ QmlDesigner::WidgetInfo EffectComposerView::widgetInfo()
m_widget = new EffectComposerWidget{this};
connect(m_widget->effectComposerModel(), &EffectComposerModel::assignToSelectedTriggered, this,
- [&] (const QString &effectPath) {
- executeInTransaction("EffectComposerView::widgetInfo", [&] {
+ [this] (const QString &effectPath) {
+ executeInTransaction("EffectComposerView assignToSelectedTriggered", [&] {
const QList<QmlDesigner::ModelNode> selectedNodes = selectedModelNodes();
for (const QmlDesigner::ModelNode &node : selectedNodes)
QmlDesigner::ModelNodeOperations::handleItemLibraryEffectDrop(effectPath, node);
});
});
+ connect(m_widget->effectComposerModel(), &EffectComposerModel::removePropertiesFromScene, this,
+ [this] (QSet<QByteArray> props, const QString &typeName) {
+ // Remove specified properties from all instances of specified type
+
+ QmlDesigner::DesignDocument *document
+ = QmlDesigner::QmlDesignerPlugin::instance()->currentDesignDocument();
+ if (!document)
+ return;
+
+ const QByteArray fullType = QString("%1.%2.%2").arg(m_componentUtils.composedEffectsTypePrefix(),
+ typeName).toUtf8();
+ const QList<QmlDesigner::ModelNode> allNodes = allModelNodes();
+ QList<QmlDesigner::ModelNode> typeNodes;
+ QList<QmlDesigner::ModelNode> propertyChangeNodes;
+ for (const QmlDesigner::ModelNode &node : allNodes) {
+ if (QmlDesigner::QmlPropertyChanges::isValidQmlPropertyChanges(node))
+ propertyChangeNodes.append(node);
+#ifdef QDS_USE_PROJECTSTORAGE
+// TODO: typeName() shouldn't be used with projectstorage. Needs alternative solution (using modules?)
+#else
+ else if (node.metaInfo().typeName() == fullType)
+ typeNodes.append(node);
+#endif
+ }
+ if (!typeNodes.isEmpty()) {
+ bool clearStacks = false;
+
+ executeInTransaction("EffectComposerView removePropertiesFromScene", [&] {
+ for (QmlDesigner::ModelNode node : std::as_const(propertyChangeNodes)) {
+ QmlDesigner::ModelNode targetNode = QmlDesigner::QmlPropertyChanges(node).target();
+ if (typeNodes.contains(targetNode)) {
+ for (const QByteArray &prop : props) {
+ if (node.hasProperty(prop)) {
+ node.removeProperty(prop);
+ clearStacks = true;
+ }
+ }
+ QList<QmlDesigner::AbstractProperty> remainingProps = node.properties();
+ if (remainingProps.size() == 1 && remainingProps[0].name() == "target")
+ node.destroy(); // Remove empty changes node
+ }
+ }
+ for (const QmlDesigner::ModelNode &node : std::as_const(typeNodes)) {
+ for (const QByteArray &prop : props) {
+ if (node.hasProperty(prop)) {
+ node.removeProperty(prop);
+ clearStacks = true;
+ }
+ }
+ }
+ });
+
+ // Reset undo stack as changing of the actual effect cannot be undone, and thus the
+ // stack will contain only unworkable states
+ if (clearStacks)
+ document->clearUndoRedoStacks();
+ }
+ });
+
auto context = new EffectComposerContext(m_widget.data());
Core::ICore::addContextObject(context);
}
@@ -91,6 +153,7 @@ void EffectComposerView::modelAttached(QmlDesigner::Model *model)
if (m_currProjectPath != currProjectPath) { // starting a new project
m_widget->effectComposerNodesModel()->loadModel();
m_widget->effectComposerModel()->clear(true);
+ m_widget->effectComposerModel()->setEffectsTypePrefix(m_componentUtils.composedEffectsTypePrefix());
m_widget->effectComposerModel()->setIsEnabled(
!QmlDesigner::DesignerMcuManager::instance().isMCUProject());
m_widget->initView();
@@ -105,4 +168,19 @@ void EffectComposerView::modelAboutToBeDetached(QmlDesigner::Model *model)
AbstractView::modelAboutToBeDetached(model);
}
+void EffectComposerView::selectedNodesChanged(const QList<QmlDesigner::ModelNode> & selectedNodeList,
+ const QList<QmlDesigner::ModelNode> & /*lastSelectedNodeList*/)
+{
+ bool hasValidTarget = false;
+
+ for (const QmlDesigner::ModelNode &node : selectedNodeList) {
+ if (node.metaInfo().isQtQuickItem()) {
+ hasValidTarget = true;
+ break;
+ }
+ }
+
+ m_widget->effectComposerModel()->setHasValidTarget(hasValidTarget);
+}
+
} // namespace EffectComposer
diff --git a/src/plugins/effectcomposer/effectcomposerview.h b/src/plugins/effectcomposer/effectcomposerview.h
index c7a381cb7d..b264fe0fd9 100644
--- a/src/plugins/effectcomposer/effectcomposerview.h
+++ b/src/plugins/effectcomposer/effectcomposerview.h
@@ -4,7 +4,9 @@
#pragma once
#include "abstractview.h"
+#include "modelnode.h"
+#include <generatedcomponentutils.h>
#include <coreplugin/icontext.h>
#include <QPointer>
@@ -35,6 +37,8 @@ public:
// AbstractView
void modelAttached(QmlDesigner::Model *model) override;
void modelAboutToBeDetached(QmlDesigner::Model *model) override;
+ void selectedNodesChanged(const QList<QmlDesigner::ModelNode> &selectedNodeList,
+ const QList<QmlDesigner::ModelNode> &lastSelectedNodeList) override;
private:
void customNotification(const AbstractView *view, const QString &identifier,
@@ -42,6 +46,7 @@ private:
QPointer<EffectComposerWidget> m_widget;
QString m_currProjectPath;
+ QmlDesigner::GeneratedComponentUtils m_componentUtils;
};
} // namespace EffectComposer
diff --git a/src/plugins/effectcomposer/uniform.cpp b/src/plugins/effectcomposer/uniform.cpp
index 98d5ffd336..590b38b423 100644
--- a/src/plugins/effectcomposer/uniform.cpp
+++ b/src/plugins/effectcomposer/uniform.cpp
@@ -94,7 +94,13 @@ void Uniform::setValue(const QVariant &newValue)
{
if (m_value != newValue) {
m_value = newValue;
+
emit uniformValueChanged();
+
+ if (m_type == Type::Sampler) {
+ m_backendValue->setValue(newValue);
+ emit uniformBackendValueChanged();
+ }
}
}
diff --git a/src/plugins/qmldesigner/.clang-format b/src/plugins/qmldesigner/.clang-format
index d3695ac298..366f82f76f 100644
--- a/src/plugins/qmldesigner/.clang-format
+++ b/src/plugins/qmldesigner/.clang-format
@@ -2,6 +2,7 @@ Language: Cpp
AccessModifierOffset: -4
AlignEscapedNewlines: DontAlign
AllowShortFunctionsOnASingleLine: Inline
+AlwaysBreakTemplateDeclarations: true # use with clang 19
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
@@ -15,6 +16,7 @@ BreakBeforeBinaryOperators: All
BreakBeforeBraces: Custom
BreakConstructorInitializers: BeforeComma
BreakInheritanceList: AfterComma
+# BreakTemplateDeclarations: Yes # use with clang 19
ColumnLimit: 100
IncludeCategories:
- Regex: 'Q.*'
diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt
index b5b64bebbc..520c4ebc79 100644
--- a/src/plugins/qmldesigner/CMakeLists.txt
+++ b/src/plugins/qmldesigner/CMakeLists.txt
@@ -8,7 +8,6 @@ if (APPLE)
set(QmlDesignerPluginInstallPrefix "${IDE_PLUGIN_PATH}/QmlDesigner")
endif()
-add_compile_options("$<$<COMPILE_LANG_AND_ID:CXX,Clang,GNU>:-Wno-error=maybe-uninitialized>")
set(BUILD_NOT_DESIGNSTUDIO NOT ${BUILD_NOT_DESIGNSTUDIO})
option(QTC_USE_QML_DESIGNER_LITE "Use Qml Designer Lite" ${BUILD_NOT_DESIGNSTUDIO})
@@ -46,6 +45,10 @@ add_qtc_library(QmlDesignerUtils STATIC
qmldesignerutils_global.h
)
+
+target_compile_options(QmlDesignerUtils PUBLIC $<$<COMPILE_LANG_AND_ID:CXX,Clang,GNU>:-Wno-error=maybe-uninitialized>)
+target_compile_options(QmlDesignerUtils PUBLIC $<$<COMPILE_LANG_AND_ID:CXX,Clang>:-Wno-unneeded-internal-declaration>)
+
extend_qtc_library(QmlDesignerUtils
CONDITION ENABLE_COMPILE_WARNING_AS_ERROR
PROPERTIES COMPILE_WARNING_AS_ERROR ON
@@ -91,6 +94,8 @@ add_qtc_library(QmlDesignerCore STATIC
SOURCES
rewritertransaction.cpp
rewritertransaction.h
+ generatedcomponentutils.cpp
+ generatedcomponentutils.h
)
extend_qtc_library(QmlDesignerCore
@@ -631,6 +636,7 @@ extend_qtc_plugin(QmlDesigner
svgpasteaction.cpp svgpasteaction.h
viewmanager.cpp viewmanager.h
utils3d.cpp utils3d.h
+ dialogutils.cpp dialogutils.h
)
extend_qtc_plugin(QmlDesigner
@@ -822,6 +828,7 @@ extend_qtc_plugin(QmlDesigner
contentlibraryeffect.cpp contentlibraryeffect.h
contentlibraryeffectscategory.cpp contentlibraryeffectscategory.h
contentlibraryeffectsmodel.cpp contentlibraryeffectsmodel.h
+ contentlibraryusermodel.cpp contentlibraryusermodel.h
)
extend_qtc_plugin(QmlDesigner
diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibraryiconprovider.cpp b/src/plugins/qmldesigner/components/assetslibrary/assetslibraryiconprovider.cpp
index dc5a1c9741..b821cc6595 100644
--- a/src/plugins/qmldesigner/components/assetslibrary/assetslibraryiconprovider.cpp
+++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibraryiconprovider.cpp
@@ -2,9 +2,8 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "assetslibraryiconprovider.h"
-#include "asset.h"
-#include "modelnodeoperations.h"
+#include <modelnodeoperations.h>
#include <theme.h>
#include <utils/hdrimage.h>
#include <utils/ktximage.h>
diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibraryiconprovider.h b/src/plugins/qmldesigner/components/assetslibrary/assetslibraryiconprovider.h
index fb38605ea6..d52779232f 100644
--- a/src/plugins/qmldesigner/components/assetslibrary/assetslibraryiconprovider.h
+++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibraryiconprovider.h
@@ -3,12 +3,11 @@
#pragma once
+#include <asset.h>
#include <synchronousimagecache.h>
#include <QQuickImageProvider>
-#include "asset.h"
-
namespace QmlDesigner {
struct Thumbnail
diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp
index c2359409eb..9d09f52d8f 100644
--- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp
+++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp
@@ -1,21 +1,19 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-#include <QCheckBox>
-#include <QFileInfo>
-#include <QFileSystemModel>
-#include <QMessageBox>
-#include <QSortFilterProxyModel>
-
-#include "asset.h"
#include "assetslibrarymodel.h"
+#include <asset.h>
#include <modelnodeoperations.h>
#include <qmldesignerplugin.h>
#include <coreplugin/icore.h>
#include <utils/algorithm.h>
-#include <utils/qtcassert.h>
+#include <utils/filesystemwatcher.h>
+
+#include <QFileInfo>
+#include <QFileSystemModel>
+#include <QMessageBox>
namespace QmlDesigner {
@@ -38,7 +36,7 @@ void AssetsLibraryModel::createBackendModel()
QObject::connect(m_sourceFsModel, &QFileSystemModel::directoryLoaded, this,
[this]([[maybe_unused]] const QString &dir) {
- syncHaveFiles();
+ syncHasFiles();
});
m_fileWatcher = new Utils::FileSystemWatcher(parent());
@@ -207,7 +205,7 @@ bool AssetsLibraryModel::filterAcceptsRow(int sourceRow, const QModelIndex &sour
}
}
-bool AssetsLibraryModel::checkHaveFiles(const QModelIndex &parentIdx) const
+bool AssetsLibraryModel::checkHasFiles(const QModelIndex &parentIdx) const
{
if (!parentIdx.isValid())
return false;
@@ -218,30 +216,30 @@ bool AssetsLibraryModel::checkHaveFiles(const QModelIndex &parentIdx) const
if (!isDirectory(newIdx))
return true;
- if (checkHaveFiles(newIdx))
+ if (checkHasFiles(newIdx))
return true;
}
return false;
}
-void AssetsLibraryModel::setHaveFiles(bool value)
+void AssetsLibraryModel::setHasFiles(bool value)
{
- if (m_haveFiles != value) {
- m_haveFiles = value;
- emit haveFilesChanged();
+ if (m_hasFiles != value) {
+ m_hasFiles = value;
+ emit hasFilesChanged();
}
}
-bool AssetsLibraryModel::checkHaveFiles() const
+bool AssetsLibraryModel::checkHasFiles() const
{
auto rootIdx = indexForPath(m_rootPath);
- return checkHaveFiles(rootIdx);
+ return checkHasFiles(rootIdx);
}
-void AssetsLibraryModel::syncHaveFiles()
+void AssetsLibraryModel::syncHasFiles()
{
- setHaveFiles(checkHaveFiles());
+ setHasFiles(checkHasFiles());
}
QString AssetsLibraryModel::getUniqueName(const QString &oldName) {
diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h
index 9334e86e9b..2516be787f 100644
--- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h
+++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h
@@ -3,12 +3,13 @@
#pragma once
-#include <QFileInfo>
-#include <QFileSystemModel>
#include <QSortFilterProxyModel>
-#include <utils/filesystemwatcher.h>
-#include <utils/qtcassert.h>
+namespace Utils {
+class FileSystemWatcher;
+}
+
+QT_FORWARD_DECLARE_CLASS(QFileSystemModel)
namespace QmlDesigner {
@@ -22,7 +23,7 @@ public:
void setRootPath(const QString &newPath);
void setSearchText(const QString &searchText);
- Q_PROPERTY(bool haveFiles READ haveFiles NOTIFY haveFilesChanged);
+ Q_PROPERTY(bool hasFiles READ hasFiles NOTIFY hasFilesChanged)
Q_INVOKABLE QString rootPath() const;
Q_INVOKABLE QString filePath(const QModelIndex &index) const;
@@ -35,7 +36,7 @@ public:
Q_INVOKABLE QModelIndex parentDirIndex(const QString &path) const;
Q_INVOKABLE QModelIndex parentDirIndex(const QModelIndex &index) const;
Q_INVOKABLE QString parentDirPath(const QString &path) const;
- Q_INVOKABLE void syncHaveFiles();
+ Q_INVOKABLE void syncHasFiles();
Q_INVOKABLE QList<QModelIndex> parentIndices(const QModelIndex &index) const;
Q_INVOKABLE bool indexIsValid(const QModelIndex &index) const;
@@ -55,30 +56,30 @@ public:
return std::min(result, 1);
}
- bool haveFiles() const { return m_haveFiles; }
+ bool hasFiles() const { return m_hasFiles; }
QString getUniqueName(const QString &oldName);
signals:
void directoryLoaded(const QString &path);
void rootPathChanged();
- void haveFilesChanged();
+ void hasFilesChanged();
void fileChanged(const QString &path);
void effectsDeleted(const QStringList &effectNames);
private:
- void setHaveFiles(bool value);
+ void setHasFiles(bool value);
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
void resetModel();
void createBackendModel();
void destroyBackendModel();
- bool checkHaveFiles(const QModelIndex &parentIdx) const;
- bool checkHaveFiles() const;
+ bool checkHasFiles(const QModelIndex &parentIdx) const;
+ bool checkHasFiles() const;
QString m_searchText;
QString m_rootPath;
QFileSystemModel *m_sourceFsModel = nullptr;
- bool m_haveFiles = false;
+ bool m_hasFiles = false;
Utils::FileSystemWatcher *m_fileWatcher = nullptr;
};
diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp
index 3b98eb6baf..4b270c8902 100644
--- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp
+++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp
@@ -3,20 +3,22 @@
#include "assetslibrarywidget.h"
-#include "asset.h"
#include "assetslibraryiconprovider.h"
#include "assetslibrarymodel.h"
#include "assetslibraryview.h"
-#include "designeractionmanager.h"
-#include "import.h"
-#include "modelnodeoperations.h"
-#include "nodemetainfo.h"
-#include "qmldesignerconstants.h"
-#include "qmldesignerplugin.h"
-#include "theme.h"
-#include <utils3d.h>
+#include <asset.h>
+#include <designeractionmanager.h>
+#include <designerpaths.h>
+#include <hdrimage.h>
+#include <import.h>
+#include <modelnodeoperations.h>
+#include <nodemetainfo.h>
+#include <qmldesignerconstants.h>
+#include <qmldesignerplugin.h>
#include <studioquickwidget.h>
+#include <theme.h>
+#include <utils3d.h>
#include <coreplugin/fileutils.h>
#include <coreplugin/icore.h>
@@ -287,14 +289,16 @@ void AssetsLibraryWidget::handleDeleteEffects([[maybe_unused]] const QStringList
// Remove usages of deleted effects from the current document
m_assetsView->executeInTransaction(__FUNCTION__, [&]() {
QList<ModelNode> allNodes = m_assetsView->allModelNodes();
- const QString typeTemplate = "Effects.%1.%1";
- const QString importUrlTemplate = "Effects.%1";
+ const QString typeTemplate = "%1.%2.%2";
+ const QString importUrlTemplate = "%1.%2";
const Imports imports = m_assetsView->model()->imports();
Imports removedImports;
+ const QString typePrefix = QmlDesignerPlugin::instance()->documentManager()
+ .generatedComponentUtils().composedEffectsTypePrefix();
for (const QString &effectName : effectNames) {
if (effectName.isEmpty())
continue;
- const TypeName type = typeTemplate.arg(effectName).toUtf8();
+ const TypeName type = typeTemplate.arg(typePrefix, effectName).toUtf8();
for (ModelNode &node : allNodes) {
if (node.metaInfo().typeName() == type) {
clearStacks = true;
@@ -302,7 +306,7 @@ void AssetsLibraryWidget::handleDeleteEffects([[maybe_unused]] const QStringList
}
}
- const QString importPath = importUrlTemplate.arg(effectName);
+ const QString importPath = importUrlTemplate.arg(typePrefix, effectName);
Import removedImport = Utils::findOrDefault(imports, [&importPath](const Import &import) {
return import.url() == importPath;
});
@@ -374,7 +378,7 @@ QList<QToolButton *> AssetsLibraryWidget::createToolBarWidgets()
void AssetsLibraryWidget::handleSearchFilterChanged(const QString &filterText)
{
- if (filterText == m_filterText || (!m_assetsModel->haveFiles()
+ if (filterText == m_filterText || (!m_assetsModel->hasFiles()
&& filterText.contains(m_filterText, Qt::CaseInsensitive)))
return;
@@ -643,4 +647,15 @@ void AssetsLibraryWidget::addResources(const QStringList &files, bool showDialog
}
}
+bool AssetsLibraryWidget::userBundleEnabled() const
+{
+ // TODO: this method is to be removed after user bundle implementation is complete
+ return Core::ICore::settings()->value("QML/Designer/UseExperimentalFeatures45", false).toBool();
+}
+
+void AssetsLibraryWidget::addAssetsToContentLibrary(const QStringList &assetPaths)
+{
+ m_assetsView->emitCustomNotification("add_assets_to_content_lib", {}, {assetPaths});
+}
+
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.h b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.h
index ed987d14de..8b59ae0785 100644
--- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.h
+++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.h
@@ -98,6 +98,8 @@ public:
Q_INVOKABLE void showInGraphicalShell(const QString &path);
Q_INVOKABLE QString showInGraphicalShellMsg() const;
+ Q_INVOKABLE bool userBundleEnabled() const;
+ Q_INVOKABLE void addAssetsToContentLibrary(const QStringList &assetPaths);
signals:
void itemActivated(const QString &itemName);
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectiondetails.cpp b/src/plugins/qmldesigner/components/collectioneditor/collectiondetails.cpp
index ddfb82746c..8b506affc4 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectiondetails.cpp
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectiondetails.cpp
@@ -60,28 +60,21 @@ inline static bool isValidColorName(const QString &colorName)
/**
* @brief getCustomUrl
- * MimeType = <MainType/SubType>
* Address = <Url|LocalFile>
*
* @param value The input value to be evaluated
- * @param dataType if the value is a valid url or image, the data type
+ * @param dataType if the value is a valid url, the data type
* will be stored to this parameter, otherwise, it will be Unknown
- * @param urlResult if the value is a valid url or image, the address
+ * @param urlResult if the value is a valid url, the address
* will be stored in this parameter, otherwise it will be empty.
- * @param subType if the value is a valid image, the image subtype
- * will be stored in this parameter, otherwise it will be empty.
- * @return true if the result is either url or image
+ * @return true if the result is url
*/
static bool getCustomUrl(const QString &value,
CollectionDetails::DataType &dataType,
- QUrl *urlResult = nullptr,
- QString *subType = nullptr)
+ QUrl *urlResult = nullptr)
{
static const QRegularExpression urlRegex{
- "^(?<MimeType>"
- "(?<MainType>image)\\/"
- "(?<SubType>apng|avif|gif|jpeg|png|(?:svg\\+xml)|webp|xyz)\\:)?" // end of MimeType
- "(?<Address>"
+ "^(?<Address>"
"(?<Url>https?:\\/\\/"
"(?:www\\.|(?!www))[A-z0-9][A-z0-9-]+[A-z0-9]\\.[^\\s]{2,}|www\\.[A-z0-9][A-z0-9-]+"
"[A-z0-9]\\.[^\\s]{2,}|https?:\\/\\/"
@@ -92,29 +85,18 @@ static bool getCustomUrl(const QString &value,
};
const QRegularExpressionMatch match = urlRegex.match(value.trimmed());
- if (match.hasMatch()) {
- if (match.hasCaptured("Address")) {
- if (match.hasCaptured("MimeType") && match.captured("MainType") == "image")
- dataType = CollectionDetails::DataType::Image;
- else
- dataType = CollectionDetails::DataType::Url;
+ if (match.hasCaptured("Address")) {
+ dataType = CollectionDetails::DataType::Url;
- if (urlResult)
- urlResult->setUrl(match.captured("Address"));
+ if (urlResult)
+ urlResult->setUrl(match.captured("Address"));
- if (subType)
- *subType = match.captured("SubType");
-
- return true;
- }
+ return true;
}
if (urlResult)
urlResult->clear();
- if (subType)
- subType->clear();
-
dataType = CollectionDetails::DataType::Unknown;
return false;
}
@@ -248,14 +230,8 @@ static QVariant valueToVariant(const QJsonValue &value, CollectionDetails::DataT
return variantValue.toBool();
case DataType::Color:
return variantValue.value<QColor>();
- case DataType::Image: {
- DataType type;
- QUrl url;
- if (getCustomUrl(variantValue.toString(), type, &url))
- return url;
- return variantValue.toString();
- }
case DataType::Url:
+ case DataType::Image:
return variantValue.value<QUrl>();
default:
return variantValue;
@@ -285,12 +261,7 @@ static QJsonValue variantToJsonValue(
return variant.toDouble();
case DataType::Integer:
return variant.toInt();
- case DataType::Image: {
- const QUrl url(variant.toUrl());
- if (url.isValid())
- return QString("image/xyz:%1").arg(url.toString());
- return {};
- }
+ case DataType::Image:
case DataType::String:
case DataType::Color:
case DataType::Url:
@@ -569,13 +540,6 @@ QVariant CollectionDetails::data(int row, int column) const
const QJsonValue cellValue = d->dataRecords.at(row).at(column);
- if (typeAt(column) == DataType::Image) {
- const QUrl imageUrl = valueToVariant(cellValue, DataType::Image).toUrl();
-
- if (imageUrl.isValid())
- return imageUrl;
- }
-
return cellValue.toVariant();
}
@@ -614,7 +578,10 @@ DataTypeWarning::Warning CollectionDetails::cellWarningCheck(int row, int column
if (columnType == DataType::Unknown || isEmptyJsonValue(cellValue))
return DataTypeWarning::Warning::None;
- if (columnType == DataType::Real && cellType == DataType::Integer)
+ if ((columnType == DataType::String || columnType == DataType::Real) && cellType == DataType::Integer)
+ return DataTypeWarning::Warning::None;
+
+ if ((columnType == DataType::Url || columnType == DataType::Image) && cellType == DataType::String)
return DataTypeWarning::Warning::None;
if (columnType != cellType)
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectiondetailsmodel.cpp b/src/plugins/qmldesigner/components/collectioneditor/collectiondetailsmodel.cpp
index b26b1a845e..d2917ec302 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectiondetailsmodel.cpp
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectiondetailsmodel.cpp
@@ -93,6 +93,7 @@ bool CollectionDetailsModel::setData(const QModelIndex &index, const QVariant &v
if (prevWarning != m_currentCollection.cellWarningCheck(index.row(), index.column()))
roles << DataTypeWarningRole;
+ setHasUnsavedChanges(true);
emit dataChanged(index, index, roles);
}
@@ -128,11 +129,11 @@ bool CollectionDetailsModel::insertRows(int row, int count, [[maybe_unused]] con
row = qBound(0, row, rowCount());
- beginResetModel();
+ beginInsertRows({}, row, row + count - 1);
m_currentCollection.insertEmptyRows(row, count);
- endResetModel();
+ endInsertRows();
+ setHasUnsavedChanges(true);
- selectRow(row);
return true;
}
@@ -151,12 +152,6 @@ bool CollectionDetailsModel::removeColumns(int column, int count, const QModelIn
if (!columnCount(parent))
removeRows(0, rowCount(parent), parent);
- int nextColumn = column - 1;
- if (nextColumn < 0 && columnCount(parent) > 0)
- nextColumn = 0;
-
- selectColumn(nextColumn);
-
ensureSingleCell();
return columnsRemoved;
}
@@ -254,6 +249,7 @@ bool CollectionDetailsModel::addColumn(int column, const QString &name, const QS
{},
CollectionDataTypeModel::dataTypeFromString(propertyType));
endInsertColumns();
+ setHasUnsavedChanges(true);
return m_currentCollection.containsPropertyName(name);
}
@@ -309,6 +305,7 @@ bool CollectionDetailsModel::setPropertyType(int column, const QString &newValue
{Qt::DisplayRole, Qt::EditRole, DataTypeRole, DataTypeWarningRole, ColumnDataTypeRole});
}
+ setHasUnsavedChanges(true);
return changed;
}
@@ -441,6 +438,7 @@ bool CollectionDetailsModel::saveDataStoreCollections()
if (reference != currentReference)
closeCollectionIfSaved(reference);
}
+ setHasUnsavedChanges(false);
return true;
}
}
@@ -618,4 +616,12 @@ QString CollectionDetailsModel::warningToString(DataTypeWarning::Warning warning
return DataTypeWarning::getDataTypeWarningString(warning);
}
+void CollectionDetailsModel::setHasUnsavedChanges(bool val)
+{
+ if (m_hasUnsavedChanges == val)
+ return;
+ m_hasUnsavedChanges = val;
+ emit hasUnsavedChangesChanged();
+}
+
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectiondetailsmodel.h b/src/plugins/qmldesigner/components/collectioneditor/collectiondetailsmodel.h
index 24a040cce6..8844ff4a3e 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectiondetailsmodel.h
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectiondetailsmodel.h
@@ -20,6 +20,7 @@ class CollectionDetailsModel : public QAbstractTableModel
Q_PROPERTY(int selectedColumn READ selectedColumn WRITE selectColumn NOTIFY selectedColumnChanged)
Q_PROPERTY(int selectedRow READ selectedRow WRITE selectRow NOTIFY selectedRowChanged)
Q_PROPERTY(bool isEmpty MEMBER m_isEmpty NOTIFY isEmptyChanged)
+ Q_PROPERTY(bool hasUnsavedChanges MEMBER m_hasUnsavedChanges WRITE setHasUnsavedChanges NOTIFY hasUnsavedChangesChanged)
public:
enum DataRoles { SelectedRole = Qt::UserRole + 1, DataTypeRole, ColumnDataTypeRole, DataTypeWarningRole };
@@ -70,12 +71,14 @@ public:
const CollectionDetails upToDateConstCollection(const CollectionReference &reference) const;
bool collectionHasColumn(const CollectionReference &reference, const QString &columnName) const;
QString getFirstColumnName(const CollectionReference &reference) const;
+ void setHasUnsavedChanges(bool val);
signals:
void collectionNameChanged(const QString &collectionName);
void selectedColumnChanged(int);
void selectedRowChanged(int);
void isEmptyChanged(bool);
+ void hasUnsavedChangesChanged();
void warning(const QString &title, const QString &body);
private slots:
@@ -93,6 +96,7 @@ private:
QHash<CollectionReference, CollectionDetails> m_openedCollections;
CollectionDetails m_currentCollection;
bool m_isEmpty = true;
+ bool m_hasUnsavedChanges = false;
int m_selectedColumn = -1;
int m_selectedRow = -1;
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectiondetailssortfiltermodel.cpp b/src/plugins/qmldesigner/components/collectioneditor/collectiondetailssortfiltermodel.cpp
index f56bb36e88..2cc6ac05a6 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectiondetailssortfiltermodel.cpp
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectiondetailssortfiltermodel.cpp
@@ -62,6 +62,12 @@ bool CollectionDetailsSortFilterModel::selectColumn(int column)
return m_source->selectColumn(mapToSource(index(0, column)).column());
}
+void CollectionDetailsSortFilterModel::deselectAll()
+{
+ QTC_ASSERT(m_source, return);
+ m_source->deselectAll();
+}
+
CollectionDetailsSortFilterModel::~CollectionDetailsSortFilterModel() = default;
bool CollectionDetailsSortFilterModel::filterAcceptsRow(int sourceRow,
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectiondetailssortfiltermodel.h b/src/plugins/qmldesigner/components/collectioneditor/collectiondetailssortfiltermodel.h
index 93305f3ca2..10f6e09b05 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectiondetailssortfiltermodel.h
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectiondetailssortfiltermodel.h
@@ -31,6 +31,7 @@ public:
Q_INVOKABLE bool selectRow(int row);
Q_INVOKABLE bool selectColumn(int column);
+ Q_INVOKABLE void deselectAll();
signals:
void selectedColumnChanged(int);
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.cpp b/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.cpp
index 4725987f12..29b833cc2c 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.cpp
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.cpp
@@ -3,6 +3,7 @@
#include "collectioneditorutils.h"
+#include "collectiondatatypemodel.h"
#include "model.h"
#include "nodemetainfo.h"
#include "propertymetainfo.h"
@@ -95,13 +96,17 @@ Utils::FilePath dataStoreDir()
if (!currentProject)
return {};
- return currentProject->projectDirectory().pathAppended("/imports/"
- + currentProject->displayName());
+ FilePath oldImportDirectory = currentProject->projectDirectory().pathAppended(
+ "imports/" + currentProject->displayName());
+ if (oldImportDirectory.exists())
+ return oldImportDirectory;
+
+ return currentProject->projectDirectory().pathAppended(currentProject->displayName());
}
inline Utils::FilePath collectionPath(const QString &filePath)
{
- return dataStoreDir().pathAppended("/" + filePath);
+ return dataStoreDir().pathAppended(filePath);
}
inline Utils::FilePath qmlDirFilePath()
@@ -288,7 +293,7 @@ QJsonObject defaultCollection()
QJsonArray columns;
QJsonObject defaultColumn;
defaultColumn.insert("name", "Column 1");
- defaultColumn.insert("type", "string");
+ defaultColumn.insert("type", CollectionDataTypeModel::dataTypeToString(DataType::String));
columns.append(defaultColumn);
QJsonArray collectionData;
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectionview.cpp b/src/plugins/qmldesigner/components/collectioneditor/collectionview.cpp
index f6ec821fde..0c9a2eed94 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectionview.cpp
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectionview.cpp
@@ -35,6 +35,12 @@ bool isStudioCollectionModel(const QmlDesigner::ModelNode &node)
return node.metaInfo().isQtQuickStudioUtilsJsonListModel();
}
+inline bool isProjectImport(const QmlDesigner::Import &import)
+{
+ ProjectExplorer::Project *currentProject = ProjectExplorer::ProjectManager::startupProject();
+ return currentProject && import.toString() == currentProject->displayName();
+}
+
inline void setVariantPropertyValue(const QmlDesigner::ModelNode &node,
const QmlDesigner::PropertyName &propertyName,
const QVariant &value)
@@ -60,14 +66,10 @@ CollectionView::CollectionView(ExternalDependenciesInterface &externalDependenci
, m_dataStore(std::make_unique<DataStoreModelNode>())
{
- connect(ProjectExplorer::ProjectManager::instance(),
- &ProjectExplorer::ProjectManager::startupProjectChanged, this, [this] {
- resetDataStoreNode();
- if (m_widget.get())
- m_widget->collectionDetailsModel()->removeAllCollections();
- });
}
+CollectionView::~CollectionView() = default;
+
bool CollectionView::hasWidget() const
{
return true;
@@ -75,11 +77,16 @@ bool CollectionView::hasWidget() const
QmlDesigner::WidgetInfo CollectionView::widgetInfo()
{
- if (m_widget.isNull()) {
- m_widget = new CollectionWidget(this);
+ if (!m_widget) {
+ m_widget = Utils::makeUniqueObjectPtr<CollectionWidget>(this);
m_widget->setMinimumSize(m_widget->minimumSizeHint());
+ connect(ProjectExplorer::ProjectManager::instance(),
+ &ProjectExplorer::ProjectManager::startupProjectChanged, m_widget.get(), [&] {
+ resetDataStoreNode();
+ m_widget->collectionDetailsModel()->removeAllCollections();
+ });
- auto collectionEditorContext = new Internal::CollectionEditorContext(m_widget.data());
+ auto collectionEditorContext = new Internal::CollectionEditorContext(m_widget.get());
Core::ICore::addContextObject(collectionEditorContext);
CollectionListModel *listModel = m_widget->listModel().data();
@@ -97,7 +104,7 @@ QmlDesigner::WidgetInfo CollectionView::widgetInfo()
connect(listModel, &CollectionListModel::modelReset, this, [this] {
CollectionListModel *listModel = m_widget->listModel().data();
- if (listModel->sourceNode() == m_dataStore->modelNode())
+ if (listModel->sourceNode() == dataStoreNode())
m_dataStore->setCollectionNames(listModel->collections());
});
@@ -128,7 +135,7 @@ QmlDesigner::WidgetInfo CollectionView::widgetInfo()
});
}
- return createWidgetInfo(m_widget.data(),
+ return createWidgetInfo(m_widget.get(),
"CollectionEditor",
WidgetInfo::LeftPane,
0,
@@ -139,23 +146,22 @@ QmlDesigner::WidgetInfo CollectionView::widgetInfo()
void CollectionView::modelAttached(Model *model)
{
AbstractView::modelAttached(model);
+ m_widget->setProjectImportExists(Utils::anyOf(model->imports(), isProjectImport));
resetDataStoreNode();
}
void CollectionView::modelAboutToBeDetached([[maybe_unused]] Model *model)
{
- m_libraryInfoIsUpdated = false;
- m_reloadCounter = 0;
- m_rewriterAmended = false;
- m_dataStoreTypeFound = false;
- disconnect(m_documentUpdateConnection);
- QTC_ASSERT(m_delayedTasks.isEmpty(), m_delayedTasks.clear());
- m_widget->listModel()->setDataStoreNode();
+ unloadDataStore();
+ m_widget->setProjectImportExists(false);
}
void CollectionView::selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
[[maybe_unused]] const QList<ModelNode> &lastSelectedNodeList)
{
+ if (!m_widget)
+ return;
+
QList<ModelNode> selectedCollectionNodes = Utils::filtered(selectedNodeList,
&isStudioCollectionModel);
@@ -170,10 +176,17 @@ void CollectionView::selectedNodesChanged(const QList<ModelNode> &selectedNodeLi
}
m_widget->setTargetNodeSelected(singleSelectedHasModelProperty);
+}
- // More than one model is selected. So ignore them
- if (selectedCollectionNodes.size() > 1)
- return;
+void CollectionView::importsChanged(const Imports &addedImports, const Imports &removedImports)
+{
+ if (Utils::anyOf(addedImports, isProjectImport)) {
+ m_widget->setProjectImportExists(true);
+ resetDataStoreNode();
+ } else if (Utils::anyOf(removedImports, isProjectImport)) {
+ m_widget->setProjectImportExists(false);
+ unloadDataStore();
+ }
}
void CollectionView::customNotification(const AbstractView *,
@@ -181,6 +194,9 @@ void CollectionView::customNotification(const AbstractView *,
const QList<ModelNode> &nodeList,
const QList<QVariant> &data)
{
+ if (!m_widget)
+ return;
+
if (identifier == QLatin1String("item_library_created_by_drop") && !nodeList.isEmpty())
onItemLibraryNodeCreated(nodeList.first());
else if (identifier == QLatin1String("open_collection_by_id") && !data.isEmpty())
@@ -219,8 +235,27 @@ void CollectionView::addResource(const QUrl &url, const QString &name)
});
}
+void CollectionView::addProjectImport()
+{
+ if (!m_widget)
+ return;
+
+ ProjectExplorer::Project *currentProject = ProjectExplorer::ProjectManager::startupProject();
+ if (!currentProject)
+ return;
+
+ executeInTransaction(__FUNCTION__, [&] {
+ Import import = Import::createLibraryImport(currentProject->displayName());
+ if (!model()->hasImport(import, true, true))
+ model()->changeImports({import}, {});
+ });
+}
+
void CollectionView::assignCollectionToNode(const QString &collectionName, const ModelNode &node)
{
+ if (!m_widget)
+ return;
+
using DataType = CollectionDetails::DataType;
executeInTransaction("CollectionView::assignCollectionToNode", [&]() {
m_dataStore->assignCollectionToNode(
@@ -279,12 +314,18 @@ void CollectionView::assignCollectionToSelectedNode(const QString &collectionNam
void CollectionView::addNewCollection(const QString &collectionName, const QJsonObject &localCollection)
{
+ if (!m_widget)
+ return;
+
addTask(QSharedPointer<CollectionTask>(
new AddCollectionTask(this, m_widget->listModel(), localCollection, collectionName)));
}
void CollectionView::openCollection(const QString &collectionName)
{
+ if (!m_widget)
+ return;
+
m_widget->openCollection(collectionName);
}
@@ -296,9 +337,13 @@ void CollectionView::registerDeclarativeType()
void CollectionView::resetDataStoreNode()
{
+ if (!m_widget)
+ return;
+
m_dataStore->reloadModel();
- ModelNode dataStore = m_dataStore->modelNode();
+ ModelNode dataStore = dataStoreNode();
+ m_widget->setDataStoreExists(dataStore.isValid());
if (!dataStore || m_widget->listModel()->sourceNode() == dataStore)
return;
@@ -339,28 +384,11 @@ void CollectionView::ensureDataStoreExists()
{
bool filesJustCreated = false;
bool filesExist = CollectionEditorUtils::ensureDataStoreExists(filesJustCreated);
- if (filesExist) {
- if (filesJustCreated) {
- // Force code model reset to notice changes to existing module
- auto modelManager = QmlJS::ModelManagerInterface::instance();
- if (modelManager) {
- m_libraryInfoIsUpdated = false;
-
- m_expectedDocumentUpdates.clear();
- m_expectedDocumentUpdates << CollectionEditorUtils::dataStoreQmlFilePath()
- << CollectionEditorUtils::dataStoreJsonFilePath();
-
- m_documentUpdateConnection = connect(modelManager,
- &QmlJS::ModelManagerInterface::documentUpdated,
- this,
- &CollectionView::onDocumentUpdated);
-
- modelManager->resetCodeModel();
- }
- resetDataStoreNode();
- } else {
- m_libraryInfoIsUpdated = true;
- }
+ if (filesExist && filesJustCreated) {
+ // Force code model reset to notice changes to existing module
+ if (auto modelManager = QmlJS::ModelManagerInterface::instance())
+ modelManager->resetCodeModel();
+ resetDataStoreNode();
}
}
@@ -380,6 +408,18 @@ NodeMetaInfo CollectionView::jsonCollectionMetaInfo() const
return model()->metaInfo(CollectionEditorConstants::JSONCOLLECTIONMODEL_TYPENAME);
}
+void CollectionView::unloadDataStore()
+{
+ m_reloadCounter = 0;
+ m_rewriterAmended = false;
+ m_dataStoreTypeFound = false;
+ QTC_ASSERT(m_delayedTasks.isEmpty(), m_delayedTasks.clear());
+ if (m_widget) {
+ m_widget->setDataStoreExists(dataStoreNode().isValid());
+ m_widget->listModel()->setDataStoreNode();
+ }
+}
+
void CollectionView::ensureStudioModelImport()
{
executeInTransaction(__FUNCTION__, [&] {
@@ -395,29 +435,21 @@ void CollectionView::ensureStudioModelImport()
void CollectionView::onItemLibraryNodeCreated(const ModelNode &node)
{
+ if (!m_widget)
+ return;
+
if (node.metaInfo().isQtQuickListView()) {
addTask(QSharedPointer<CollectionTask>(
new DropListViewTask(this, m_widget->listModel(), node)));
}
}
-void CollectionView::onDocumentUpdated(const QSharedPointer<const QmlJS::Document> &doc)
-{
- if (m_expectedDocumentUpdates.contains(doc->fileName()))
- m_expectedDocumentUpdates.remove(doc->fileName());
-
- if (m_expectedDocumentUpdates.isEmpty()) {
- disconnect(m_documentUpdateConnection);
- m_libraryInfoIsUpdated = true;
- }
-}
-
void CollectionView::addTask(QSharedPointer<CollectionTask> task)
{
ensureDataStoreExists();
if (m_dataStoreTypeFound)
task->process();
- else if (m_dataStore->modelNode())
+ else if (dataStoreNode())
m_delayedTasks << task;
}
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectionview.h b/src/plugins/qmldesigner/components/collectioneditor/collectionview.h
index a4b16c4c27..3de3bd7ae6 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectionview.h
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectionview.h
@@ -3,9 +3,12 @@
#pragma once
-#include "abstractview.h"
#include "datastoremodelnode.h"
-#include "modelnode.h"
+
+#include <abstractview.h>
+#include <modelnode.h>
+
+#include <utils/uniqueobjectptr.h>
#include <QJsonObject>
@@ -27,6 +30,7 @@ class CollectionView : public AbstractView
public:
explicit CollectionView(ExternalDependenciesInterface &externalDependencies);
+ ~CollectionView();
bool hasWidget() const override;
WidgetInfo widgetInfo() override;
@@ -37,6 +41,8 @@ public:
void selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
const QList<ModelNode> &lastSelectedNodeList) override;
+ void importsChanged(const Imports &addedImports, const Imports &removedImports) override;
+
void customNotification(const AbstractView *view,
const QString &identifier,
const QList<ModelNode> &nodeList,
@@ -44,6 +50,7 @@ public:
void addResource(const QUrl &url, const QString &name);
+ void addProjectImport();
void assignCollectionToNode(const QString &collectionName, const ModelNode &node);
void assignCollectionToSelectedNode(const QString &collectionName);
void addNewCollection(const QString &collectionName, const QJsonObject &localCollection);
@@ -61,17 +68,14 @@ private:
friend class CollectionTask;
NodeMetaInfo jsonCollectionMetaInfo() const;
+ void unloadDataStore();
void ensureStudioModelImport();
void onItemLibraryNodeCreated(const ModelNode &node);
- void onDocumentUpdated(const QSharedPointer<const QmlJS::Document> &doc);
void addTask(QSharedPointer<CollectionTask> task);
- QPointer<CollectionWidget> m_widget;
std::unique_ptr<DataStoreModelNode> m_dataStore;
- QSet<Utils::FilePath> m_expectedDocumentUpdates;
+ Utils::UniqueObjectPtr<CollectionWidget> m_widget;
QList<QSharedPointer<CollectionTask>> m_delayedTasks;
- QMetaObject::Connection m_documentUpdateConnection;
- bool m_libraryInfoIsUpdated = false;
bool m_dataStoreTypeFound = false;
bool m_rewriterAmended = false;
int m_reloadCounter = 0;
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.cpp b/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.cpp
index 093729dc67..dd706145cf 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.cpp
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.cpp
@@ -54,8 +54,7 @@ QString getPreferredCollectionName(const QUrl &url, const QString &collectionNam
namespace QmlDesigner {
CollectionWidget::CollectionWidget(CollectionView *view)
- : QFrame()
- , m_view(view)
+ : m_view(view)
, m_listModel(new CollectionListModel)
, m_collectionDetailsModel(new CollectionDetailsModel)
, m_collectionDetailsSortFilterModel(std::make_unique<CollectionDetailsSortFilterModel>())
@@ -104,6 +103,8 @@ CollectionWidget::CollectionWidget(CollectionView *view)
QmlDesignerPlugin::trackWidgetFocusTime(this, Constants::EVENT_MODELEDITOR_TIME);
}
+CollectionWidget::~CollectionWidget() = default;
+
void CollectionWidget::contextHelp(const Core::IContext::HelpCallback &callback) const
{
if (m_view)
@@ -250,6 +251,11 @@ bool CollectionWidget::importFile(const QString &collectionName,
return false;
}
+void CollectionWidget::addProjectImport()
+{
+ m_view->addProjectImport();
+}
+
void CollectionWidget::addCollectionToDataStore(const QString &collectionName)
{
m_view->addNewCollection(collectionName, CollectionEditorUtils::defaultCollection());
@@ -288,6 +294,24 @@ void CollectionWidget::setTargetNodeSelected(bool selected)
emit targetNodeSelectedChanged(m_targetNodeSelected);
}
+void CollectionWidget::setProjectImportExists(bool exists)
+{
+ if (m_projectImportExists == exists)
+ return;
+
+ m_projectImportExists = exists;
+ emit projectImportExistsChanged(m_projectImportExists);
+}
+
+void CollectionWidget::setDataStoreExists(bool exists)
+{
+ if (m_dataStoreExists == exists)
+ return;
+
+ m_dataStoreExists = exists;
+ emit dataStoreExistsChanged(m_dataStoreExists);
+}
+
void CollectionWidget::deleteSelectedCollection()
{
QMetaObject::invokeMethod(m_quickWidget->quickWidget()->rootObject(), "deleteSelectedCollection");
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.h b/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.h
index 0957bd81e0..13c3566c78 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.h
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.h
@@ -22,9 +22,12 @@ class CollectionWidget : public QFrame
Q_OBJECT
Q_PROPERTY(bool targetNodeSelected MEMBER m_targetNodeSelected NOTIFY targetNodeSelectedChanged)
+ Q_PROPERTY(bool projectImportExists MEMBER m_projectImportExists NOTIFY projectImportExistsChanged)
+ Q_PROPERTY(bool dataStoreExists MEMBER m_dataStoreExists NOTIFY dataStoreExistsChanged)
public:
CollectionWidget(CollectionView *view);
+ ~CollectionWidget();
void contextHelp(const Core::IContext::HelpCallback &callback) const;
QPointer<CollectionListModel> listModel() const;
@@ -32,7 +35,7 @@ public:
void reloadQmlSource();
- virtual QSize minimumSizeHint() const;
+ QSize minimumSizeHint() const override;
Q_INVOKABLE bool loadJsonFile(const QUrl &url, const QString &collectionName = {});
Q_INVOKABLE bool loadCsvFile(const QUrl &url, const QString &collectionName = {});
@@ -44,6 +47,7 @@ public:
const QUrl &url,
const bool &firstRowIsHeader = true);
+ Q_INVOKABLE void addProjectImport();
Q_INVOKABLE void addCollectionToDataStore(const QString &collectionName);
Q_INVOKABLE void assignCollectionToSelectedNode(const QString collectionName);
Q_INVOKABLE void openCollection(const QString &collectionName);
@@ -51,11 +55,15 @@ public:
void warn(const QString &title, const QString &body);
void setTargetNodeSelected(bool selected);
+ void setProjectImportExists(bool exists);
+ void setDataStoreExists(bool exists);
void deleteSelectedCollection();
signals:
void targetNodeSelectedChanged(bool);
+ void projectImportExistsChanged(bool);
+ void dataStoreExistsChanged(bool);
private:
QString generateUniqueCollectionName(const ModelNode &node, const QString &name);
@@ -66,6 +74,8 @@ private:
std::unique_ptr<CollectionDetailsSortFilterModel> m_collectionDetailsSortFilterModel;
QScopedPointer<StudioQuickWidget> m_quickWidget;
bool m_targetNodeSelected = false;
+ bool m_projectImportExists = false;
+ bool m_dataStoreExists = false;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/componentcore/dialogutils.cpp b/src/plugins/qmldesigner/components/componentcore/dialogutils.cpp
new file mode 100644
index 0000000000..f882ae528d
--- /dev/null
+++ b/src/plugins/qmldesigner/components/componentcore/dialogutils.cpp
@@ -0,0 +1,32 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include <model.h>
+
+#include <coreplugin/messagebox.h>
+
+namespace QmlDesigner {
+
+namespace DialogUtils {
+
+void showWarningForInvalidId(const QString &id)
+{
+ constexpr char text[] = R"(
+The ID <b>'%1'</b> is invalid.
+
+Make sure the ID is:
+<ul>
+<li>Unique within the QML file.</li>
+<li>Beginning with a lowercase letter.</li>
+<li>Without any blank space or symbol.</li>
+<li>Not a reserved QML keyword. </li>
+</ul>
+)";
+
+ Core::AsynchronousMessageBox::warning(Model::tr("Invalid Id"),
+ Model::tr(text).arg(id));
+}
+
+} // namespace DialogUtils
+
+} //QmlDesigner
diff --git a/src/plugins/qmldesigner/components/componentcore/dialogutils.h b/src/plugins/qmldesigner/components/componentcore/dialogutils.h
new file mode 100644
index 0000000000..3ca98016dd
--- /dev/null
+++ b/src/plugins/qmldesigner/components/componentcore/dialogutils.h
@@ -0,0 +1,17 @@
+// 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 once
+
+#include <qmldesignercomponents_global.h>
+
+#include <QString>
+
+namespace QmlDesigner {
+
+namespace DialogUtils {
+
+QMLDESIGNERCOMPONENTS_EXPORT void showWarningForInvalidId(const QString &id);
+
+} // namespace DialogUtils
+} //QmlDesigner
diff --git a/src/plugins/qmldesigner/components/componentcore/layoutingridlayout.cpp b/src/plugins/qmldesigner/components/componentcore/layoutingridlayout.cpp
index 8d3412e0e8..89b50c4d1a 100644
--- a/src/plugins/qmldesigner/components/componentcore/layoutingridlayout.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/layoutingridlayout.cpp
@@ -452,7 +452,9 @@ void LayoutInGridLayout::removeSpacersBySpanning(QList<ModelNode> &nodes)
{
for (const ModelNode &node : std::as_const(m_spacerNodes)) {
if (int index = nodes.indexOf(node)) {
- ModelNode before = nodes.at(index -1);
+ ModelNode before;
+ if (index > 0)
+ before = nodes.at(index - 1);
if (m_spacerNodes.contains(before)) {
m_spacerNodes.removeAll(node);
m_layoutedNodes.removeAll(node);
diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.cpp b/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.cpp
index f6e18458b2..4cbebd738d 100644
--- a/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.cpp
@@ -105,8 +105,10 @@ bool selectionIsImported3DAsset(const SelectionContext &selectionState)
// Node is not a file component, so we have to check if the current doc itself is
fileName = node.model()->fileUrl().toLocalFile();
}
- if (fileName.contains(Constants::QUICK_3D_ASSETS_FOLDER))
+ if (QmlDesignerPlugin::instance()->documentManager()
+ .generatedComponentUtils().isImport3dPath(fileName)) {
return true;
+ }
}
return false;
}
diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
index cebe7d7c53..a5274c70e2 100644
--- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
@@ -1138,18 +1138,12 @@ static QString getAssetDefaultDirectory(const QString &assetDir, const QString &
{
QString adjustedDefaultDirectory = defaultDirectory;
- Utils::FilePath contentPath = QmlDesignerPlugin::instance()->documentManager().currentProjectDirPath();
-
- if (contentPath.pathAppended("content").exists())
- contentPath = contentPath.pathAppended("content");
+ Utils::FilePath contentPath = QmlDesignerPlugin::instance()->documentManager().currentResourcePath();
Utils::FilePath assetPath = contentPath.pathAppended(assetDir);
- if (!assetPath.exists()) {
- // Create the default asset type directory if it doesn't exist
- QDir dir(contentPath.toString());
- dir.mkpath(assetDir);
- }
+ if (!assetPath.exists())
+ assetPath.createDir();
if (assetPath.exists() && assetPath.isDir())
adjustedDefaultDirectory = assetPath.toString();
@@ -1694,7 +1688,14 @@ void editIn3dView(const SelectionContext &selectionContext)
if (selectionContext.view() && selectionContext.hasSingleSelectedModelNode()
&& selectionContext.currentSingleSelectedNode().metaInfo().isQtQuick3DView3D()) {
QmlDesignerPlugin::instance()->mainWidget()->showDockWidget("Editor3D", true);
- selectionContext.view()->emitView3DAction(View3DActionType::AlignViewToCamera, true);
+ const QPointF scenePos = selectionContext.scenePosition();
+ if (scenePos.isNull()) {
+ selectionContext.view()->emitView3DAction(View3DActionType::AlignViewToCamera, true);
+ } else {
+ selectionContext.view()->emitCustomNotification("pick_3d_node_from_2d_scene",
+ {selectionContext.currentSingleSelectedNode()},
+ {scenePos});
+ }
}
}
@@ -1727,13 +1728,12 @@ void openOldEffectMaker(const QString &filePath)
return;
}
- Utils::FilePath projectPath = target->project()->projectDirectory();
- QString effectName = QFileInfo(filePath).baseName();
- QString effectResDir = QLatin1String(Constants::DEFAULT_EFFECTS_IMPORT_FOLDER)
- + "/" + effectName;
- Utils::FilePath effectResPath = projectPath.pathAppended(effectResDir);
+ Utils::FilePath effectResPath = QmlDesignerPlugin::instance()->documentManager()
+ .generatedComponentUtils().composedEffectsBasePath()
+ .pathAppended(QFileInfo(filePath).baseName());
+
if (!effectResPath.exists())
- QDir().mkpath(effectResPath.toString());
+ effectResPath.createDir();
const QtSupport::QtVersion *baseQtVersion = QtSupport::QtKitAspect::qtVersion(target->kit());
if (baseQtVersion) {
@@ -1769,14 +1769,11 @@ void openOldEffectMaker(const QString &filePath)
Utils::FilePath getEffectsImportDirectory()
{
- QString defaultDir = QLatin1String(Constants::DEFAULT_EFFECTS_IMPORT_FOLDER);
- Utils::FilePath projectPath = QmlDesignerPlugin::instance()->documentManager().currentProjectDirPath();
- Utils::FilePath effectsPath = projectPath.pathAppended(defaultDir);
+ Utils::FilePath effectsPath = QmlDesignerPlugin::instance()->documentManager()
+ .generatedComponentUtils().composedEffectsBasePath();
- if (!effectsPath.exists()) {
- QDir dir(projectPath.toString());
- dir.mkpath(effectsPath.toString());
- }
+ if (!effectsPath.exists())
+ effectsPath.createDir();
return effectsPath;
}
@@ -1794,12 +1791,9 @@ QString getEffectsDefaultDirectory(const QString &defaultDir)
QString getEffectIcon(const QString &effectPath)
{
- Utils::FilePath projectPath = QmlDesignerPlugin::instance()->documentManager().currentProjectDirPath();
- QString effectName = QFileInfo(effectPath).baseName();
- QString effectResDir = "asset_imports/Effects/" + effectName;
- Utils::FilePath effectResPath = projectPath.resolvePath(effectResDir + "/" + effectName + ".qml");
-
- return effectResPath.exists() ? QString("effectExported") : QString("effectClass");
+ Utils::FilePath effectFile = QmlDesignerPlugin::instance()->documentManager()
+ .generatedComponentUtils().composedEffectPath(effectPath);
+ return effectFile.exists() ? QString("effectExported") : QString("effectClass");
}
bool useLayerEffect()
diff --git a/src/plugins/qmldesigner/components/componentcore/resourcegenerator.cpp b/src/plugins/qmldesigner/components/componentcore/resourcegenerator.cpp
index 4a229564c6..24047f650f 100644
--- a/src/plugins/qmldesigner/components/componentcore/resourcegenerator.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/resourcegenerator.cpp
@@ -222,6 +222,10 @@ bool createQmlrcFile(const FilePath &qmlrcFilePath)
rccProcess.setWorkingDirectory(project->projectDirectory());
const QStringList arguments = {"--binary",
+ "--compress",
+ "9",
+ "--threshold",
+ "30",
"--output",
qmlrcFilePath.toString(),
tempQrcFile.toString()};
diff --git a/src/plugins/qmldesigner/components/componentcore/theme.h b/src/plugins/qmldesigner/components/componentcore/theme.h
index 73184d391c..392f6c94f6 100644
--- a/src/plugins/qmldesigner/components/componentcore/theme.h
+++ b/src/plugins/qmldesigner/components/componentcore/theme.h
@@ -83,6 +83,7 @@ public:
binding_medium,
bounds_small,
branch_medium,
+ cameraSpeed_medium,
camera_medium,
camera_small,
centerHorizontal,
diff --git a/src/plugins/qmldesigner/components/componentcore/viewmanager.cpp b/src/plugins/qmldesigner/components/componentcore/viewmanager.cpp
index 05d6f5fdf0..b011d9fbbf 100644
--- a/src/plugins/qmldesigner/components/componentcore/viewmanager.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/viewmanager.cpp
@@ -67,16 +67,20 @@ public:
, collectionView{externalDependencies}
, contentLibraryView{externalDependencies}
, componentView{externalDependencies}
+#ifndef QTC_USE_QML_DESIGNER_LITE
, edit3DView{externalDependencies}
+#endif
, formEditorView{externalDependencies}
, textEditorView{externalDependencies}
, assetsLibraryView{externalDependencies}
, itemLibraryView(imageCache, externalDependencies)
, navigatorView{externalDependencies}
, propertyEditorView(imageCache, externalDependencies)
+#ifndef QTC_USE_QML_DESIGNER_LITE
, materialEditorView{externalDependencies}
, materialBrowserView{imageCache, externalDependencies}
, textureEditorView{imageCache, externalDependencies}
+#endif
, statesEditorView{externalDependencies}
{}
@@ -89,16 +93,20 @@ public:
CollectionView collectionView;
ContentLibraryView contentLibraryView;
ComponentView componentView;
+#ifndef QTC_USE_QML_DESIGNER_LITE
Edit3DView edit3DView;
+#endif
FormEditorView formEditorView;
TextEditorView textEditorView;
AssetsLibraryView assetsLibraryView;
ItemLibraryView itemLibraryView;
NavigatorView navigatorView;
PropertyEditorView propertyEditorView;
+#ifndef QTC_USE_QML_DESIGNER_LITE
MaterialEditorView materialEditorView;
MaterialBrowserView materialBrowserView;
TextureEditorView textureEditorView;
+#endif
StatesEditorView statesEditorView;
std::vector<std::unique_ptr<AbstractView>> additionalViews;
@@ -203,6 +211,7 @@ QList<AbstractView *> ViewManager::views() const
QList<AbstractView *> ViewManager::standardViews() const
{
+#ifndef QTC_USE_QML_DESIGNER_LITE
QList<AbstractView *> list = {&d->edit3DView,
&d->formEditorView,
&d->textEditorView,
@@ -215,6 +224,16 @@ QList<AbstractView *> ViewManager::standardViews() const
&d->textureEditorView,
&d->statesEditorView,
&d->designerActionManagerView};
+#else
+ QList<AbstractView *> list = {&d->formEditorView,
+ &d->textEditorView,
+ &d->assetsLibraryView,
+ &d->itemLibraryView,
+ &d->navigatorView,
+ &d->propertyEditorView,
+ &d->statesEditorView,
+ &d->designerActionManagerView};
+#endif
if (enableModelEditor())
list.append(&d->collectionView);
@@ -384,16 +403,20 @@ QList<WidgetInfo> ViewManager::widgetInfos() const
{
QList<WidgetInfo> widgetInfoList;
+#ifndef QTC_USE_QML_DESIGNER_LITE
widgetInfoList.append(d->edit3DView.widgetInfo());
+#endif
widgetInfoList.append(d->formEditorView.widgetInfo());
widgetInfoList.append(d->textEditorView.widgetInfo());
widgetInfoList.append(d->assetsLibraryView.widgetInfo());
widgetInfoList.append(d->itemLibraryView.widgetInfo());
widgetInfoList.append(d->navigatorView.widgetInfo());
widgetInfoList.append(d->propertyEditorView.widgetInfo());
+#ifndef QTC_USE_QML_DESIGNER_LITE
widgetInfoList.append(d->materialEditorView.widgetInfo());
widgetInfoList.append(d->materialBrowserView.widgetInfo());
widgetInfoList.append(d->textureEditorView.widgetInfo());
+#endif
widgetInfoList.append(d->statesEditorView.widgetInfo());
if (enableModelEditor())
widgetInfoList.append(d->collectionView.widgetInfo());
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarybundleimporter.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarybundleimporter.cpp
index 9e6bdd03b9..5c8d42a306 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarybundleimporter.cpp
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarybundleimporter.cpp
@@ -32,9 +32,6 @@ ContentLibraryBundleImporter::ContentLibraryBundleImporter(const QString &bundle
{
m_importTimer.setInterval(200);
connect(&m_importTimer, &QTimer::timeout, this, &ContentLibraryBundleImporter::handleImportTimer);
- m_moduleName = QStringLiteral("%1.%2").arg(
- QLatin1String(Constants::COMPONENT_BUNDLES_FOLDER),
- m_bundleId).mid(1); // Chop leading slash
}
// Returns empty string on success or an error message on failure.
@@ -69,7 +66,7 @@ QString ContentLibraryBundleImporter::importComponent(const QString &qmlFile,
QString qmldirContent = QString::fromUtf8(qmldirPath.fileContents().value_or(QByteArray()));
if (qmldirContent.isEmpty()) {
qmldirContent.append("module ");
- qmldirContent.append(m_moduleName);
+ qmldirContent.append(moduleName());
qmldirContent.append('\n');
}
@@ -77,7 +74,9 @@ QString ContentLibraryBundleImporter::importComponent(const QString &qmlFile,
const bool qmlFileExists = qmlSourceFile.exists();
const QString qmlType = qmlSourceFile.baseName();
const QString fullTypeName = QStringLiteral("%1.%2.%3")
- .arg(QLatin1String(Constants::COMPONENT_BUNDLES_FOLDER).mid(1), m_bundleId, qmlType);
+ .arg(QmlDesignerPlugin::instance()->documentManager()
+ .generatedComponentUtils().componentBundlesTypePrefix(),
+ m_bundleId, qmlType);
if (m_pendingTypes.contains(fullTypeName) && !m_pendingTypes[fullTypeName])
return QStringLiteral("Unable to import while unimporting the same type: '%1'").arg(fullTypeName);
if (!qmldirContent.contains(qmlFile)) {
@@ -126,7 +125,7 @@ QString ContentLibraryBundleImporter::importComponent(const QString &qmlFile,
if (!model)
return "Model not available, cannot add import statement or update code model";
- Import import = Import::createLibraryImport(m_moduleName, "1.0");
+ Import import = Import::createLibraryImport(moduleName(), "1.0");
if (!model->hasImport(import)) {
if (model->possibleImports().contains(import)) {
m_importAddPending = false;
@@ -134,7 +133,7 @@ QString ContentLibraryBundleImporter::importComponent(const QString &qmlFile,
model->changeImports({import}, {});
} catch (const RewritingException &) {
// No point in trying to add import asynchronously either, so just fail out
- return QStringLiteral("Failed to add import statement for: '%1'").arg(m_moduleName);
+ return QStringLiteral("Failed to add import statement for: '%1'").arg(moduleName());
}
} else {
// If import is not yet possible, import statement needs to be added asynchronously to
@@ -188,7 +187,7 @@ void ContentLibraryBundleImporter::handleImportTimer()
if (m_importAddPending) {
try {
- Import import = Import::createLibraryImport(m_moduleName, "1.0");
+ Import import = Import::createLibraryImport(moduleName(), "1.0");
if (model->possibleImports().contains(import)) {
model->changeImports({import}, {});
m_importAddPending = false;
@@ -253,6 +252,13 @@ void ContentLibraryBundleImporter::writeAssetRefMap(const Utils::FilePath &bundl
}
}
+QString ContentLibraryBundleImporter::moduleName()
+{
+ return QStringLiteral("%1.%2").arg(QmlDesignerPlugin::instance()->documentManager()
+ .generatedComponentUtils().componentBundlesTypePrefix(),
+ m_bundleId);
+}
+
QString ContentLibraryBundleImporter::unimportComponent(const QString &qmlFile)
{
FilePath bundleImportPath = resolveBundleImportPath();
@@ -275,7 +281,9 @@ QString ContentLibraryBundleImporter::unimportComponent(const QString &qmlFile)
QString qmlType = qmlFilePath.baseName();
const QString fullTypeName = QStringLiteral("%1.%2.%3")
- .arg(QLatin1String(Constants::COMPONENT_BUNDLES_FOLDER).mid(1), m_bundleId, qmlType);
+ .arg(QmlDesignerPlugin::instance()->documentManager()
+ .generatedComponentUtils().componentBundlesTypePrefix(),
+ m_bundleId, qmlType);
if (m_pendingTypes.contains(fullTypeName) && m_pendingTypes[fullTypeName])
return QStringLiteral("Unable to unimport while importing the same type: '%1'").arg(fullTypeName);
@@ -327,7 +335,7 @@ QString ContentLibraryBundleImporter::unimportComponent(const QString &qmlFile)
auto doc = QmlDesignerPlugin::instance()->currentDesignDocument();
Model *model = doc ? doc->currentModel() : nullptr;
if (model) {
- Import import = Import::createLibraryImport(m_moduleName, "1.0");
+ Import import = Import::createLibraryImport(moduleName(), "1.0");
if (model->imports().contains(import))
model->changeImports({}, {import});
}
@@ -342,16 +350,12 @@ QString ContentLibraryBundleImporter::unimportComponent(const QString &qmlFile)
FilePath ContentLibraryBundleImporter::resolveBundleImportPath()
{
- FilePath bundleImportPath = QmlDesignerPlugin::instance()->documentManager().currentProjectDirPath();
+ FilePath bundleImportPath = QmlDesignerPlugin::instance()->documentManager()
+ .generatedComponentUtils().componentBundlesBasePath();
if (bundleImportPath.isEmpty())
return bundleImportPath;
- const QString projectBundlePath = QStringLiteral("%1%2/%3").arg(
- QLatin1String(Constants::DEFAULT_ASSET_IMPORT_FOLDER),
- QLatin1String(Constants::COMPONENT_BUNDLES_FOLDER),
- m_bundleId).mid(1); // Chop leading slash
-
- return bundleImportPath.resolvePath(projectBundlePath);
+ return bundleImportPath.resolvePath(m_bundleId);
}
} // namespace QmlDesigner::Internal
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarybundleimporter.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarybundleimporter.h
index 3aff09fe34..7fb2a48886 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarybundleimporter.h
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarybundleimporter.h
@@ -46,10 +46,10 @@ private:
void handleImportTimer();
QVariantHash loadAssetRefMap(const Utils::FilePath &bundlePath);
void writeAssetRefMap(const Utils::FilePath &bundlePath, const QVariantHash &assetRefMap);
+ QString moduleName();
Utils::FilePath m_bundleDir;
QString m_bundleId;
- QString m_moduleName;
QStringList m_sharedFiles;
QTimer m_importTimer;
int m_importTimerCount = 0;
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.cpp
index 6b1de2d2a7..334c017116 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.cpp
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryeffectsmodel.cpp
@@ -7,8 +7,8 @@
#include "contentlibraryeffect.h"
#include "contentlibraryeffectscategory.h"
#include "contentlibrarywidget.h"
-#include "qmldesignerconstants.h"
+#include <qmldesignerplugin.h>
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
#include <utils/hostosinfo.h>
@@ -187,10 +187,11 @@ void ContentLibraryEffectsModel::loadBundle()
QUrl icon = QUrl::fromLocalFile(bundleDir.filePath(itemObj.value("icon").toString()));
QString qml = itemObj.value("qml").toString();
- TypeName type = QLatin1String("%1.%2.%3").arg(
- QLatin1String(Constants::COMPONENT_BUNDLES_FOLDER).mid(1),
- bundleId,
- qml.chopped(4)).toLatin1(); // chopped(4): remove .qml
+ TypeName type = QLatin1String("%1.%2.%3")
+ .arg(QmlDesignerPlugin::instance()->documentManager()
+ .generatedComponentUtils().componentBundlesTypePrefix(),
+ bundleId,
+ qml.chopped(4)).toLatin1(); // chopped(4): remove .qml
auto bundleItem = new ContentLibraryEffect(category, item, qml, type, icon, files);
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterial.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterial.h
index f546ea98cd..55af2accbd 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterial.h
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterial.h
@@ -3,9 +3,8 @@
#pragma once
-#include "qmldesignercorelib_global.h"
+#include "nodeinstanceglobal.h"
-#include <QDataStream>
#include <QObject>
#include <QUrl>
@@ -22,6 +21,7 @@ class ContentLibraryMaterial : public QObject
Q_PROPERTY(QString bundleMaterialBaseWebUrl MEMBER m_baseWebUrl CONSTANT)
Q_PROPERTY(QString bundleMaterialParentPath READ parentDirPath CONSTANT)
Q_PROPERTY(QStringList bundleMaterialFiles READ allFiles CONSTANT)
+ Q_PROPERTY(QString itemType MEMBER m_itemType CONSTANT)
public:
ContentLibraryMaterial(QObject *parent,
@@ -31,7 +31,7 @@ public:
const QUrl &icon,
const QStringList &files,
const QString &downloadPath,
- const QString &baseWebUrl);
+ const QString &baseWebUrl = {});
bool filter(const QString &searchText);
@@ -66,6 +66,7 @@ private:
QString m_downloadPath;
QString m_baseWebUrl;
QStringList m_allFiles;
+ const QString m_itemType = "material";
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.cpp
index 7594c691b5..26747d359c 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.cpp
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.cpp
@@ -8,12 +8,12 @@
#include "contentlibrarymaterialscategory.h"
#include "contentlibrarywidget.h"
-#include <designerpaths.h>
+#include "designerpaths.h"
#include "filedownloader.h"
#include "fileextractor.h"
#include "multifiledownloader.h"
-#include "qmldesignerconstants.h"
-#include "qmldesignerplugin.h"
+
+#include <qmldesignerplugin.h>
#include <utils/algorithm.h>
#include <utils/hostosinfo.h>
@@ -275,9 +275,9 @@ void ContentLibraryMaterialsModel::loadMaterialBundle(const QDir &matBundleDir)
auto category = new ContentLibraryMaterialsCategory(this, cat);
const QJsonObject matsObj = catsObj.value(cat).toObject();
- const QStringList mats = matsObj.keys();
- for (const QString &mat : mats) {
- const QJsonObject matObj = matsObj.value(mat).toObject();
+ const QStringList matsNames = matsObj.keys();
+ for (const QString &matName : matsNames) {
+ const QJsonObject matObj = matsObj.value(matName).toObject();
QStringList files;
const QJsonArray assetsArr = matObj.value("files").toArray();
@@ -286,12 +286,13 @@ void ContentLibraryMaterialsModel::loadMaterialBundle(const QDir &matBundleDir)
QUrl icon = QUrl::fromLocalFile(matBundleDir.filePath(matObj.value("icon").toString()));
QString qml = matObj.value("qml").toString();
- TypeName type = QLatin1String("%1.%2.%3").arg(
- QLatin1String(Constants::COMPONENT_BUNDLES_FOLDER).mid(1),
- bundleId,
- qml.chopped(4)).toLatin1(); // chopped(4): remove .qml
+ TypeName type = QLatin1String("%1.%2.%3")
+ .arg(QmlDesignerPlugin::instance()->documentManager()
+ .generatedComponentUtils().componentBundlesTypePrefix(),
+ bundleId,
+ qml.chopped(4)).toLatin1(); // chopped(4): remove .qml
- auto bundleMat = new ContentLibraryMaterial(category, mat, qml, type, icon, files,
+ auto bundleMat = new ContentLibraryMaterial(category, matName, qml, type, icon, files,
m_downloadPath, m_baseUrl);
category->addBundleMaterial(bundleMat);
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.cpp
index 7ab239aab4..80dd7e816f 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.cpp
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.cpp
@@ -12,20 +12,19 @@
namespace QmlDesigner {
ContentLibraryTexture::ContentLibraryTexture(QObject *parent, const QFileInfo &iconFileInfo,
- const QString &downloadPath, const QUrl &icon,
- const QString &key, const QString &webTextureUrl,
- const QString &webIconUrl, const QString &fileExt,
+ const QString &dirPath, const QString &suffix,
const QSize &dimensions, const qint64 sizeInBytes,
- bool hasUpdate, bool isNew)
+ const QString &key, const QString &textureUrl,
+ const QString &iconUrl, bool hasUpdate, bool isNew)
: QObject(parent)
, m_iconPath(iconFileInfo.filePath())
- , m_downloadPath(downloadPath)
- , m_webTextureUrl(webTextureUrl)
- , m_webIconUrl(webIconUrl)
+ , m_dirPath(dirPath)
+ , m_textureUrl(textureUrl)
+ , m_iconUrl(iconUrl)
, m_baseName{iconFileInfo.baseName()}
- , m_fileExt(fileExt)
+ , m_suffix(suffix)
, m_textureKey(key)
- , m_icon(icon)
+ , m_icon(QUrl::fromLocalFile(iconFileInfo.absoluteFilePath()))
, m_dimensions(dimensions)
, m_sizeInBytes(sizeInBytes)
, m_hasUpdate(hasUpdate)
@@ -54,9 +53,9 @@ QString ContentLibraryTexture::iconPath() const
return m_iconPath;
}
-QString ContentLibraryTexture::resolveFileExt()
+QString ContentLibraryTexture::resolveSuffix()
{
- const QFileInfoList files = QDir(m_downloadPath).entryInfoList(QDir::Files);
+ const QFileInfoList files = QDir(m_dirPath).entryInfoList(QDir::Files);
const QFileInfoList textureFiles = Utils::filtered(files, [this](const QFileInfo &fi) {
return fi.baseName() == m_baseName;
});
@@ -76,22 +75,20 @@ QString ContentLibraryTexture::resolveFileExt()
QString ContentLibraryTexture::resolveToolTipText()
{
- if (m_fileExt.isEmpty()) {
- // No supplied or resolved extension means we have just the icon and no other data
- return m_baseName;
- }
+ if (m_suffix.isEmpty())
+ return m_baseName; // empty suffix means we have just the icon and no other data
- QString fileName = m_baseName + m_fileExt;
+ QString fileName = m_baseName + m_suffix;
QString imageInfo;
if (!m_isDownloaded && m_sizeInBytes > 0 && !m_dimensions.isNull()) {
- imageInfo = ImageUtils::imageInfo(m_dimensions, m_sizeInBytes);
+ imageInfo = ImageUtils::imageInfoString(m_dimensions, m_sizeInBytes);
} else {
- QString fullDownloadPath = m_downloadPath + '/' + fileName;
- imageInfo = ImageUtils::imageInfo(fullDownloadPath);
+ QString fullDownloadPath = m_dirPath + '/' + fileName;
+ imageInfo = ImageUtils::imageInfoString(fullDownloadPath);
}
- return QStringLiteral("%1\n%2").arg(fileName, imageInfo);
+ return QString("%1\n%2").arg(fileName, imageInfo);
}
bool ContentLibraryTexture::isDownloaded() const
@@ -99,9 +96,9 @@ bool ContentLibraryTexture::isDownloaded() const
return m_isDownloaded;
}
-QString ContentLibraryTexture::downloadedTexturePath() const
+QString ContentLibraryTexture::texturePath() const
{
- return m_downloadPath + '/' + m_baseName + m_fileExt;
+ return m_dirPath + '/' + m_baseName + m_suffix;
}
void ContentLibraryTexture::setDownloaded()
@@ -116,16 +113,16 @@ void ContentLibraryTexture::setDownloaded()
void ContentLibraryTexture::doSetDownloaded()
{
- if (m_fileExt.isEmpty())
- m_fileExt = resolveFileExt();
+ if (m_suffix.isEmpty())
+ m_suffix = resolveSuffix();
- m_isDownloaded = QFileInfo::exists(downloadedTexturePath());
+ m_isDownloaded = QFileInfo::exists(texturePath());
m_toolTip = resolveToolTipText();
}
QString ContentLibraryTexture::parentDirPath() const
{
- return m_downloadPath;
+ return m_dirPath;
}
QString ContentLibraryTexture::textureKey() const
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h
index 9f5b46630f..8f7197bc72 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h
@@ -19,17 +19,18 @@ class ContentLibraryTexture : public QObject
Q_PROPERTY(QString textureToolTip MEMBER m_toolTip NOTIFY textureToolTipChanged)
Q_PROPERTY(QUrl textureIcon MEMBER m_icon CONSTANT)
Q_PROPERTY(bool textureVisible MEMBER m_visible NOTIFY textureVisibleChanged)
- Q_PROPERTY(QString textureWebUrl MEMBER m_webTextureUrl CONSTANT)
- Q_PROPERTY(QString textureWebIconUrl MEMBER m_webIconUrl CONSTANT)
+ Q_PROPERTY(QString textureUrl MEMBER m_textureUrl CONSTANT)
+ Q_PROPERTY(QString textureIconUrl MEMBER m_iconUrl CONSTANT)
Q_PROPERTY(bool textureHasUpdate WRITE setHasUpdate READ hasUpdate NOTIFY hasUpdateChanged)
Q_PROPERTY(bool textureIsNew MEMBER m_isNew CONSTANT)
Q_PROPERTY(QString textureKey MEMBER m_textureKey CONSTANT)
+ Q_PROPERTY(QString itemType MEMBER m_itemType CONSTANT)
public:
- ContentLibraryTexture(QObject *parent, const QFileInfo &iconFileInfo, const QString &downloadPath,
- const QUrl &icon, const QString &key, const QString &webTextureUrl,
- const QString &webIconUrl, const QString &fileExt, const QSize &dimensions,
- const qint64 sizeInBytes, bool hasUpdate, bool isNew);
+ ContentLibraryTexture(QObject *parent, const QFileInfo &iconFileInfo, const QString &dirPath,
+ const QString &suffix, const QSize &dimensions, const qint64 sizeInBytes,
+ const QString &key = {}, const QString &textureUrl = {},
+ const QString &iconUrl = {}, bool hasUpdate = false, bool isNew = false);
Q_INVOKABLE bool isDownloaded() const;
Q_INVOKABLE void setDownloaded();
@@ -38,7 +39,7 @@ public:
QUrl icon() const;
QString iconPath() const;
- QString downloadedTexturePath() const;
+ QString texturePath() const;
QString parentDirPath() const;
QString textureKey() const;
@@ -51,17 +52,17 @@ signals:
void hasUpdateChanged();
private:
- QString resolveFileExt();
+ QString resolveSuffix();
QString resolveToolTipText();
void doSetDownloaded();
QString m_iconPath;
- QString m_downloadPath;
- QString m_webTextureUrl;
- QString m_webIconUrl;
+ QString m_dirPath;
+ QString m_textureUrl;
+ QString m_iconUrl;
QString m_toolTip;
QString m_baseName;
- QString m_fileExt;
+ QString m_suffix;
QString m_textureKey;
QUrl m_icon;
QSize m_dimensions;
@@ -71,6 +72,7 @@ private:
bool m_visible = true;
bool m_hasUpdate = false;
bool m_isNew = false;
+ const QString m_itemType = "texture";
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.cpp
index 77519ad88f..0cafe8d138 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.cpp
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.cpp
@@ -14,17 +14,15 @@ namespace QmlDesigner {
ContentLibraryTexturesCategory::ContentLibraryTexturesCategory(QObject *parent, const QString &name)
: QObject(parent), m_name(name) {}
-void ContentLibraryTexturesCategory::addTexture(const QFileInfo &tex, const QString &downloadPath,
+void ContentLibraryTexturesCategory::addTexture(const QFileInfo &texIcon, const QString &downloadPath,
const QString &key, const QString &webTextureUrl,
- const QString &webIconUrl, const QString &fileExt,
+ const QString &iconUrl, const QString &suffix,
const QSize &dimensions, const qint64 sizeInBytes,
bool hasUpdate, bool isNew)
{
- QUrl icon = QUrl::fromLocalFile(tex.absoluteFilePath());
-
m_categoryTextures.append(new ContentLibraryTexture(
- this, tex, downloadPath, icon, key, webTextureUrl, webIconUrl,
- fileExt, dimensions, sizeInBytes, hasUpdate, isNew));
+ this, texIcon, downloadPath, suffix, dimensions, sizeInBytes,
+ key, webTextureUrl, iconUrl, hasUpdate, isNew));
}
bool ContentLibraryTexturesCategory::filter(const QString &searchText)
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.h
index 166528f05a..857346df06 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.h
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.h
@@ -28,7 +28,7 @@ public:
ContentLibraryTexturesCategory(QObject *parent, const QString &name);
void addTexture(const QFileInfo &tex, const QString &subPath, const QString &key,
- const QString &webTextureUrl, const QString &webIconUrl, const QString &fileExt,
+ const QString &webTextureUrl, const QString &iconUrl, const QString &suffix,
const QSize &dimensions, const qint64 sizeInBytes, bool hasUpdate, bool isNew);
bool filter(const QString &searchText);
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.cpp
index 319ca2686f..b575b6b9b2 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.cpp
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.cpp
@@ -95,37 +95,37 @@ QHash<int, QByteArray> ContentLibraryTexturesModel::roleNames() const
/**
* @brief Load the bundle categorized icons. Actual textures are downloaded on demand
*
- * @param bundlePath local path to the bundle folder and icons
- * @param metaData bundle textures metadata
+ * @param textureBundleUrl remote url to the texture bundle
+ * @param bundleIconPath local path to the texture bundle icons folder
+ * @param jsonData bundle textures information from the bundle json
*/
-void ContentLibraryTexturesModel::loadTextureBundle(const QString &remoteUrl, const QString &iconsUrl,
+void ContentLibraryTexturesModel::loadTextureBundle(const QString &textureBundleUrl,
const QString &bundleIconPath,
- const QVariantMap &metaData)
+ const QVariantMap &jsonData)
{
if (!m_bundleCategories.isEmpty())
return;
QDir bundleDir = QString("%1/%2").arg(bundleIconPath, m_category);
- if (!bundleDir.exists()) {
- qWarning() << __FUNCTION__ << "textures bundle folder doesn't exist." << bundleDir.absolutePath();
- return;
- }
+ QTC_ASSERT(bundleDir.exists(), return);
- const QVariantMap imageItems = metaData.value("image_items").toMap();
+ const QVariantMap imageItems = jsonData.value("image_items").toMap();
const QFileInfoList dirs = bundleDir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
for (const QFileInfo &dir : dirs) {
auto category = new ContentLibraryTexturesCategory(this, dir.fileName());
- const QFileInfoList texFiles = QDir(dir.filePath()).entryInfoList(QDir::Files);
- for (const QFileInfo &tex : texFiles) {
- QString textureUrl = QString("%1/%2/%3.zip").arg(remoteUrl, dir.fileName(), tex.baseName());
- QString iconUrl = QString("%1/%2/%3.png").arg(iconsUrl, dir.fileName(), tex.baseName());
-
- QString localDownloadPath = QString("%1/%2/%3")
+ const QFileInfoList texIconFiles = QDir(dir.filePath()).entryInfoList(QDir::Files);
+ for (const QFileInfo &texIcon : texIconFiles) {
+ QString textureUrl = QString("%1/%2/%3/%4.zip").arg(textureBundleUrl, m_category,
+ dir.fileName(), texIcon.baseName());
+ QString iconUrl = QString("%1/icons/%2/%3/%4.png").arg(textureBundleUrl, m_category,
+ dir.fileName(), texIcon.baseName());
+
+ QString texturePath = QString("%1/%2/%3")
.arg(Paths::bundlesPathSetting(),
m_category,
dir.fileName());
- QString key = QString("%1/%2/%3").arg(m_category, dir.fileName(), tex.baseName());
+ QString key = QString("%1/%2/%3").arg(m_category, dir.fileName(), texIcon.baseName());
QString fileExt;
QSize dimensions;
qint64 sizeInBytes = -1;
@@ -141,7 +141,7 @@ void ContentLibraryTexturesModel::loadTextureBundle(const QString &remoteUrl, co
isNew = m_newFiles.contains(key);
}
- category->addTexture(tex, localDownloadPath, key, textureUrl, iconUrl, fileExt,
+ category->addTexture(texIcon, texturePath, key, textureUrl, iconUrl, fileExt,
dimensions, sizeInBytes, hasUpdate, isNew);
}
m_bundleCategories.append(category);
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.h
index 92db4151a8..94e223a251 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.h
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.h
@@ -37,8 +37,8 @@ public:
void setHasSceneEnv(bool b);
void resetModel();
- void loadTextureBundle(const QString &remoteUrl, const QString &iconsUrl,
- const QString &bundlePath, const QVariantMap &metaData);
+ void loadTextureBundle(const QString &textureBundleUrl, const QString &bundlePath,
+ const QVariantMap &metaData);
signals:
void isEmptyChanged();
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.cpp
new file mode 100644
index 0000000000..18d6e45fa8
--- /dev/null
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.cpp
@@ -0,0 +1,423 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "contentlibraryusermodel.h"
+
+#include "contentlibrarybundleimporter.h"
+#include "contentlibrarymaterial.h"
+#include "contentlibrarymaterialscategory.h"
+#include "contentlibrarytexture.h"
+#include "contentlibrarywidget.h"
+
+#include <designerpaths.h>
+#include <imageutils.h>
+#include <qmldesignerplugin.h>
+
+#include <utils/algorithm.h>
+#include <utils/hostosinfo.h>
+#include <utils/qtcassert.h>
+
+#include <QCoreApplication>
+#include <QFileInfo>
+#include <QJsonArray>
+#include <QJsonDocument>
+#include <QQmlEngine>
+#include <QStandardPaths>
+#include <QUrl>
+
+namespace QmlDesigner {
+
+ContentLibraryUserModel::ContentLibraryUserModel(ContentLibraryWidget *parent)
+ : QAbstractListModel(parent)
+ , m_widget(parent)
+{
+ m_userCategories = {tr("Materials"), tr("Textures")/*, tr("3D"), tr("Effects"), tr("2D components")*/}; // TODO
+
+ loadMaterialBundle();
+ loadTextureBundle();
+}
+
+int ContentLibraryUserModel::rowCount(const QModelIndex &) const
+{
+ return m_userCategories.size();
+}
+
+QVariant ContentLibraryUserModel::data(const QModelIndex &index, int role) const
+{
+ QTC_ASSERT(index.isValid() && index.row() < m_userCategories.size(), return {});
+ QTC_ASSERT(roleNames().contains(role), return {});
+
+ if (role == NameRole)
+ return m_userCategories.at(index.row());
+
+ if (role == ItemsRole) {
+ if (index.row() == 0)
+ return QVariant::fromValue(m_userMaterials);
+ if (index.row() == 1)
+ return QVariant::fromValue(m_userTextures);
+ if (index.row() == 2)
+ return QVariant::fromValue(m_user3DItems);
+ if (index.row() == 3)
+ return QVariant::fromValue(m_userEffects);
+ }
+
+ if (role == VisibleRole)
+ return true; // TODO
+
+ return {};
+}
+
+bool ContentLibraryUserModel::isValidIndex(int idx) const
+{
+ return idx > -1 && idx < rowCount();
+}
+
+void ContentLibraryUserModel::updateIsEmpty()
+{
+ bool anyMatVisible = Utils::anyOf(m_userMaterials, [&](ContentLibraryMaterial *mat) {
+ return mat->visible();
+ });
+
+ bool newEmpty = !anyMatVisible || !m_widget->hasMaterialLibrary() || !hasRequiredQuick3DImport();
+
+ if (newEmpty != m_isEmpty) {
+ m_isEmpty = newEmpty;
+ emit isEmptyChanged();
+ }
+}
+
+void ContentLibraryUserModel::addMaterial(const QString &name, const QString &qml,
+ const QUrl &icon, const QStringList &files)
+{
+ auto libMat = new ContentLibraryMaterial(this, name, qml, qmlToModule(qml), icon, files,
+ Paths::bundlesPathSetting().append("/User/materials"));
+
+ m_userMaterials.append(libMat);
+ int matSectionIdx = 0;
+ emit dataChanged(index(matSectionIdx), index(matSectionIdx));
+}
+
+void ContentLibraryUserModel::addTextures(const QStringList &paths)
+{
+ QDir bundleDir{Paths::bundlesPathSetting() + "/User/textures"};
+ bundleDir.mkpath(".");
+ bundleDir.mkdir("icons");
+
+ for (const QString &path : paths) {
+ QFileInfo fileInfo(path);
+ QString suffix = '.' + fileInfo.suffix();
+ auto iconFileInfo = QFileInfo(fileInfo.path().append("/icons/").append(fileInfo.baseName() + ".png"));
+ QPair<QSize, qint64> info = ImageUtils::imageInfo(path);
+ QString dirPath = fileInfo.path();
+ QSize imgDims = info.first;
+ qint64 imgFileSize = info.second;
+
+ auto tex = new ContentLibraryTexture(this, iconFileInfo, dirPath, suffix, imgDims, imgFileSize);
+ m_userTextures.append(tex);
+ }
+
+ int texSectionIdx = 1;
+ emit dataChanged(index(texSectionIdx), index(texSectionIdx));
+}
+
+// returns unique library material's name and qml component
+QPair<QString, QString> ContentLibraryUserModel::getUniqueLibMaterialNameAndQml(const QString &matName) const
+{
+ QTC_ASSERT(!m_bundleObj.isEmpty(), return {});
+
+ const QJsonObject matsObj = m_bundleObj.value("materials").toObject();
+ const QStringList matNames = matsObj.keys();
+
+ QStringList matQmls;
+ for (const QString &matName : matNames)
+ matQmls.append(matsObj.value(matName).toObject().value("qml").toString().chopped(4)); // remove .qml
+
+ QString retName = matName.isEmpty() ? "Material" : matName;
+ retName = retName.trimmed();
+
+ QString retQml = retName;
+ retQml.remove(' ');
+ if (retQml.at(0).isLower())
+ retQml[0] = retQml.at(0).toUpper();
+ retQml.prepend("My");
+
+ int num = 1;
+ if (matNames.contains(retName) || matQmls.contains(retQml)) {
+ while (matNames.contains(retName + QString::number(num))
+ || matQmls.contains(retQml + QString::number(num))) {
+ ++num;
+ }
+
+ retName += QString::number(num);
+ retQml += QString::number(num);
+ }
+
+ return {retName, retQml + ".qml"};
+}
+
+TypeName ContentLibraryUserModel::qmlToModule(const QString &qmlName) const
+{
+ return QLatin1String("%1.%2.%3").arg(QmlDesignerPlugin::instance()->documentManager()
+ .generatedComponentUtils().componentBundlesTypePrefix(),
+ m_bundleId,
+ qmlName.chopped(4)).toLatin1(); // chopped(4): remove .qml
+}
+
+QHash<int, QByteArray> ContentLibraryUserModel::roleNames() const
+{
+ static const QHash<int, QByteArray> roles {
+ {NameRole, "categoryName"},
+ {VisibleRole, "categoryVisible"},
+ {ItemsRole, "categoryItems"}
+ };
+ return roles;
+}
+
+void ContentLibraryUserModel::createImporter(const QString &bundlePath, const QString &bundleId,
+ const QStringList &sharedFiles)
+{
+ m_importer = new Internal::ContentLibraryBundleImporter(bundlePath, bundleId, sharedFiles);
+#ifdef QDS_USE_PROJECTSTORAGE
+ connect(m_importer,
+ &Internal::ContentLibraryBundleImporter::importFinished,
+ this,
+ [&](const QmlDesigner::TypeName &typeName) {
+ m_importerRunning = false;
+ emit importerRunningChanged();
+ if (typeName.size())
+ emit bundleMaterialImported(typeName);
+ });
+#else
+ connect(m_importer,
+ &Internal::ContentLibraryBundleImporter::importFinished,
+ this,
+ [&](const QmlDesigner::NodeMetaInfo &metaInfo) {
+ m_importerRunning = false;
+ emit importerRunningChanged();
+ if (metaInfo.isValid())
+ emit bundleMaterialImported(metaInfo);
+ });
+#endif
+
+ connect(m_importer, &Internal::ContentLibraryBundleImporter::unimportFinished, this,
+ [&](const QmlDesigner::NodeMetaInfo &metaInfo) {
+ Q_UNUSED(metaInfo)
+ m_importerRunning = false;
+ emit importerRunningChanged();
+ emit bundleMaterialUnimported(metaInfo);
+ });
+
+ resetModel();
+ updateIsEmpty();
+}
+
+QJsonObject &ContentLibraryUserModel::bundleJsonObjectRef()
+{
+ return m_bundleObj;
+}
+
+void ContentLibraryUserModel::loadMaterialBundle()
+{
+ if (m_matBundleExists)
+ return;
+
+ QDir bundleDir{Paths::bundlesPathSetting() + "/User/materials"};
+ bundleDir.mkpath(".");
+
+ if (m_bundleObj.isEmpty()) {
+ auto jsonFilePath = Utils::FilePath::fromString(bundleDir.filePath("user_materials_bundle.json"));
+ if (!jsonFilePath.exists()) {
+ QString jsonContent = "{\n";
+ jsonContent += " \"id\": \"UserMaterialBundle\",\n";
+ jsonContent += " \"materials\": {\n";
+ jsonContent += " }\n";
+ jsonContent += "}";
+ jsonFilePath.writeFileContents(jsonContent.toLatin1());
+ }
+
+ QFile jsonFile(jsonFilePath.path());
+ if (!jsonFile.open(QIODevice::ReadOnly)) {
+ qWarning("Couldn't open user_materials_bundle.json");
+ return;
+ }
+
+ QJsonDocument matBundleJsonDoc = QJsonDocument::fromJson(jsonFile.readAll());
+ if (matBundleJsonDoc.isNull()) {
+ qWarning("Invalid user_materials_bundle.json file");
+ return;
+ } else {
+ m_bundleObj = matBundleJsonDoc.object();
+ }
+ }
+
+ m_bundleId = m_bundleObj.value("id").toString();
+
+ // parse materials
+ const QJsonObject matsObj = m_bundleObj.value("materials").toObject();
+ const QStringList materialNames = matsObj.keys();
+ for (const QString &matName : materialNames) {
+ const QJsonObject matObj = matsObj.value(matName).toObject();
+
+ QStringList files;
+ const QJsonArray assetsArr = matObj.value("files").toArray();
+ for (const auto /*QJson{Const,}ValueRef*/ &asset : assetsArr)
+ files.append(asset.toString());
+
+ QUrl icon = QUrl::fromLocalFile(bundleDir.filePath(matObj.value("icon").toString()));
+ QString qml = matObj.value("qml").toString();
+
+ TypeName type = qmlToModule(qml);
+
+ auto userMat = new ContentLibraryMaterial(this, matName, qml, type, icon, files,
+ bundleDir.path(), "");
+
+ m_userMaterials.append(userMat);
+ }
+
+ QStringList sharedFiles;
+ const QJsonArray sharedFilesArr = m_bundleObj.value("sharedFiles").toArray();
+ for (const auto /*QJson{Const,}ValueRef*/ &file : sharedFilesArr)
+ sharedFiles.append(file.toString());
+
+ createImporter(bundleDir.path(), m_bundleId, sharedFiles);
+
+ m_matBundleExists = true;
+ emit matBundleExistsChanged();
+}
+
+void ContentLibraryUserModel::loadTextureBundle()
+{
+ if (!m_userTextures.isEmpty())
+ return;
+
+ QDir bundleDir{Paths::bundlesPathSetting() + "/User/textures"};
+ bundleDir.mkpath(".");
+ bundleDir.mkdir("icons");
+
+ const QFileInfoList fileInfos = bundleDir.entryInfoList(QDir::Files);
+ for (const QFileInfo &fileInfo : fileInfos) {
+ QString suffix = '.' + fileInfo.suffix();
+ auto iconFileInfo = QFileInfo(fileInfo.path().append("/icons/").append(fileInfo.baseName() + ".png"));
+ QPair<QSize, qint64> info = ImageUtils::imageInfo(fileInfo.path());
+ QString dirPath = fileInfo.path();
+ QSize imgDims = info.first;
+ qint64 imgFileSize = info.second;
+
+ auto tex = new ContentLibraryTexture(this, iconFileInfo, dirPath, suffix, imgDims, imgFileSize);
+ m_userTextures.append(tex);
+ }
+
+ int texSectionIdx = 1;
+ emit dataChanged(index(texSectionIdx), index(texSectionIdx));
+}
+
+bool ContentLibraryUserModel::hasRequiredQuick3DImport() const
+{
+ return m_widget->hasQuick3DImport() && m_quick3dMajorVersion == 6 && m_quick3dMinorVersion >= 3;
+}
+
+bool ContentLibraryUserModel::matBundleExists() const
+{
+ return m_matBundleExists;
+}
+
+Internal::ContentLibraryBundleImporter *ContentLibraryUserModel::bundleImporter() const
+{
+ return m_importer;
+}
+
+void ContentLibraryUserModel::setSearchText(const QString &searchText)
+{
+ QString lowerSearchText = searchText.toLower();
+
+ if (m_searchText == lowerSearchText)
+ return;
+
+ m_searchText = lowerSearchText;
+
+ for (ContentLibraryMaterial *mat : std::as_const(m_userMaterials))
+ mat->filter(m_searchText);
+
+ updateIsEmpty();
+}
+
+void ContentLibraryUserModel::updateImportedState(const QStringList &importedMats)
+{
+ bool changed = false;
+
+ for (ContentLibraryMaterial *mat : std::as_const(m_userMaterials))
+ changed |= mat->setImported(importedMats.contains(mat->qml().chopped(4)));
+
+ if (changed)
+ resetModel();
+}
+
+void ContentLibraryUserModel::setQuick3DImportVersion(int major, int minor)
+{
+ bool oldRequiredImport = hasRequiredQuick3DImport();
+
+ m_quick3dMajorVersion = major;
+ m_quick3dMinorVersion = minor;
+
+ bool newRequiredImport = hasRequiredQuick3DImport();
+
+ if (oldRequiredImport == newRequiredImport)
+ return;
+
+ emit hasRequiredQuick3DImportChanged();
+
+ updateIsEmpty();
+}
+
+void ContentLibraryUserModel::resetModel()
+{
+ beginResetModel();
+ endResetModel();
+}
+
+void ContentLibraryUserModel::applyToSelected(ContentLibraryMaterial *mat, bool add)
+{
+ emit applyToSelectedTriggered(mat, add);
+}
+
+void ContentLibraryUserModel::addToProject(ContentLibraryMaterial *mat)
+{
+ QString err = m_importer->importComponent(mat->qml(), mat->files());
+
+ if (err.isEmpty()) {
+ m_importerRunning = true;
+ emit importerRunningChanged();
+ } else {
+ qWarning() << __FUNCTION__ << err;
+ }
+}
+
+void ContentLibraryUserModel::removeFromProject(ContentLibraryMaterial *mat)
+{
+ emit bundleMaterialAboutToUnimport(mat->type());
+
+ QString err = m_importer->unimportComponent(mat->qml());
+
+ if (err.isEmpty()) {
+ m_importerRunning = true;
+ emit importerRunningChanged();
+ } else {
+ qWarning() << __FUNCTION__ << err;
+ }
+}
+
+bool ContentLibraryUserModel::hasModelSelection() const
+{
+ return m_hasModelSelection;
+}
+
+void ContentLibraryUserModel::setHasModelSelection(bool b)
+{
+ if (b == m_hasModelSelection)
+ return;
+
+ m_hasModelSelection = b;
+ emit hasModelSelectionChanged();
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.h
new file mode 100644
index 0000000000..3e9a96fd9d
--- /dev/null
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.h
@@ -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
+
+#pragma once
+
+#include "modelfwd.h"
+
+#include <QAbstractListModel>
+#include <QJsonObject>
+
+QT_FORWARD_DECLARE_CLASS(QUrl)
+
+namespace QmlDesigner {
+
+class ContentLibraryEffect;
+class ContentLibraryMaterial;
+class ContentLibraryTexture;
+class ContentLibraryWidget;
+class NodeMetaInfo;
+
+namespace Internal {
+class ContentLibraryBundleImporter;
+}
+
+class ContentLibraryUserModel : public QAbstractListModel
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool matBundleExists READ matBundleExists NOTIFY matBundleExistsChanged)
+ Q_PROPERTY(bool isEmpty MEMBER m_isEmpty NOTIFY isEmptyChanged)
+ Q_PROPERTY(bool hasRequiredQuick3DImport READ hasRequiredQuick3DImport NOTIFY hasRequiredQuick3DImportChanged)
+ Q_PROPERTY(bool hasModelSelection READ hasModelSelection NOTIFY hasModelSelectionChanged)
+ Q_PROPERTY(bool importerRunning MEMBER m_importerRunning NOTIFY importerRunningChanged)
+ Q_PROPERTY(QList<ContentLibraryMaterial *> userMaterials MEMBER m_userMaterials NOTIFY userMaterialsChanged)
+ Q_PROPERTY(QList<ContentLibraryTexture *> userTextures MEMBER m_userTextures NOTIFY userTexturesChanged)
+ Q_PROPERTY(QList<ContentLibraryEffect *> user3DItems MEMBER m_user3DItems NOTIFY user3DItemsChanged)
+ Q_PROPERTY(QList<ContentLibraryEffect *> userEffects MEMBER m_userEffects NOTIFY userEffectsChanged)
+
+public:
+ ContentLibraryUserModel(ContentLibraryWidget *parent = nullptr);
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+ QHash<int, QByteArray> roleNames() const override;
+
+ void setSearchText(const QString &searchText);
+ void updateImportedState(const QStringList &importedMats);
+
+ QPair<QString, QString> getUniqueLibMaterialNameAndQml(const QString &matName) const;
+ TypeName qmlToModule(const QString &qmlName) const;
+
+ void setQuick3DImportVersion(int major, int minor);
+
+ bool hasRequiredQuick3DImport() const;
+
+ bool matBundleExists() const;
+
+ bool hasModelSelection() const;
+ void setHasModelSelection(bool b);
+
+ void resetModel();
+ void updateIsEmpty();
+
+ void addMaterial(const QString &name, const QString &qml, const QUrl &icon, const QStringList &files);
+ void addTextures(const QStringList &paths);
+
+ void setBundleObj(const QJsonObject &newBundleObj);
+ QJsonObject &bundleJsonObjectRef();
+
+ Internal::ContentLibraryBundleImporter *bundleImporter() const;
+
+ Q_INVOKABLE void applyToSelected(QmlDesigner::ContentLibraryMaterial *mat, bool add = false);
+ Q_INVOKABLE void addToProject(QmlDesigner::ContentLibraryMaterial *mat);
+ Q_INVOKABLE void removeFromProject(QmlDesigner::ContentLibraryMaterial *mat);
+
+signals:
+ void isEmptyChanged();
+ void hasRequiredQuick3DImportChanged();
+ void hasModelSelectionChanged();
+ void userMaterialsChanged();
+ void userTexturesChanged();
+ void user3DItemsChanged();
+ void userEffectsChanged();
+
+ void applyToSelectedTriggered(QmlDesigner::ContentLibraryMaterial *mat, bool add = false);
+
+#ifdef QDS_USE_PROJECTSTORAGE
+ void bundleMaterialImported(const QmlDesigner::TypeName &typeName);
+#else
+ void bundleMaterialImported(const QmlDesigner::NodeMetaInfo &metaInfo);
+#endif
+ void bundleMaterialAboutToUnimport(const QmlDesigner::TypeName &type);
+ void bundleMaterialUnimported(const QmlDesigner::NodeMetaInfo &metaInfo);
+ void importerRunningChanged();
+ void matBundleExistsChanged();
+
+private:
+ void loadMaterialBundle();
+ void loadTextureBundle();
+ bool isValidIndex(int idx) const;
+ void createImporter(const QString &bundlePath, const QString &bundleId,
+ const QStringList &sharedFiles);
+
+ ContentLibraryWidget *m_widget = nullptr;
+ QString m_searchText;
+ QString m_bundleId;
+
+ QList<ContentLibraryMaterial *> m_userMaterials;
+ QList<ContentLibraryTexture *> m_userTextures;
+ QList<ContentLibraryEffect *> m_userEffects;
+ QList<ContentLibraryEffect *> m_user3DItems;
+ QStringList m_userCategories;
+
+ QJsonObject m_bundleObj;
+ Internal::ContentLibraryBundleImporter *m_importer = nullptr;
+
+ bool m_isEmpty = true;
+ bool m_matBundleExists = false;
+ bool m_hasModelSelection = false;
+ bool m_importerRunning = false;
+
+ int m_quick3dMajorVersion = -1;
+ int m_quick3dMinorVersion = -1;
+
+ QString m_importerBundlePath;
+ QString m_importerBundleId;
+ QStringList m_importerSharedFiles;
+
+ enum Roles { NameRole = Qt::UserRole + 1, VisibleRole, ItemsRole };
+};
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp
index 61ae078ea8..dd8a4d9919 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp
@@ -3,6 +3,8 @@
#include "contentlibraryview.h"
+#include "asset.h"
+#include "bindingproperty.h"
#include "contentlibrarybundleimporter.h"
#include "contentlibraryeffect.h"
#include "contentlibraryeffectsmodel.h"
@@ -10,13 +12,17 @@
#include "contentlibrarymaterialsmodel.h"
#include "contentlibrarytexture.h"
#include "contentlibrarytexturesmodel.h"
+#include "contentlibraryusermodel.h"
#include "contentlibrarywidget.h"
+#include "documentmanager.h"
#include "externaldependenciesinterface.h"
#include "nodelistproperty.h"
#include "qmldesignerconstants.h"
#include "qmlobjectnode.h"
#include "variantproperty.h"
-#include <utils3d.h>
+#include "utils3d.h"
+
+#include <designerpaths.h>
#include <coreplugin/messagebox.h>
#include <enumeration.h>
@@ -30,6 +36,10 @@
#include <qtsupport/qtkitaspect.h>
#endif
+#include <QJsonArray>
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <QPixmap>
#include <QVector3D>
namespace QmlDesigner {
@@ -204,6 +214,8 @@ WidgetInfo ContentLibraryView::widgetInfo()
connect(effectsModel, &ContentLibraryEffectsModel::bundleItemUnimported, this,
&ContentLibraryView::updateBundleEffectsImportedState);
+
+ connectUserBundle();
}
return createWidgetInfo(m_widget.data(),
@@ -213,6 +225,64 @@ WidgetInfo ContentLibraryView::widgetInfo()
tr("Content Library"));
}
+void ContentLibraryView::connectUserBundle()
+{
+ ContentLibraryUserModel *userModel = m_widget->userModel().data();
+
+ connect(userModel,
+ &ContentLibraryUserModel::applyToSelectedTriggered,
+ this,
+ [&](ContentLibraryMaterial *bundleMat, bool add) {
+ if (m_selectedModels.isEmpty())
+ return;
+
+ m_bundleMaterialTargets = m_selectedModels;
+ m_bundleMaterialAddToSelected = add;
+
+ ModelNode defaultMat = getBundleMaterialDefaultInstance(bundleMat->type());
+ if (defaultMat.isValid())
+ applyBundleMaterialToDropTarget(defaultMat);
+ else
+ m_widget->userModel()->addToProject(bundleMat);
+ });
+
+#ifdef QDS_USE_PROJECTSTORAGE
+ connect(userModel,
+ &ContentLibraryUserModel::bundleMaterialImported,
+ this,
+ [&](const QmlDesigner::TypeName &typeName) {
+ applyBundleMaterialToDropTarget({}, typeName);
+ updateBundleUserMaterialsImportedState();
+ });
+#else
+ connect(userModel,
+ &ContentLibraryUserModel::bundleMaterialImported,
+ this,
+ [&](const QmlDesigner::NodeMetaInfo &metaInfo) {
+ applyBundleMaterialToDropTarget({}, metaInfo);
+ updateBundleUserMaterialsImportedState();
+ });
+#endif
+
+ connect(userModel, &ContentLibraryUserModel::bundleMaterialAboutToUnimport, this,
+ [&] (const QmlDesigner::TypeName &type) {
+ // delete instances of the bundle material that is about to be unimported
+ executeInTransaction("ContentLibraryView::connectUserModel", [&] {
+ ModelNode matLib = Utils3D::materialLibraryNode(this);
+ if (!matLib.isValid())
+ return;
+
+ Utils::reverseForeach(matLib.directSubModelNodes(), [&](const ModelNode &mat) {
+ if (mat.isValid() && mat.type() == type)
+ QmlObjectNode(mat).destroy();
+ });
+ });
+ });
+
+ connect(userModel, &ContentLibraryUserModel::bundleMaterialUnimported, this,
+ &ContentLibraryView::updateBundleUserMaterialsImportedState);
+}
+
void ContentLibraryView::modelAttached(Model *model)
{
AbstractView::modelAttached(model);
@@ -276,6 +346,7 @@ void ContentLibraryView::selectedNodesChanged(const QList<ModelNode> &selectedNo
});
m_widget->materialsModel()->setHasModelSelection(!m_selectedModels.isEmpty());
+ m_widget->userModel()->setHasModelSelection(!m_selectedModels.isEmpty());
}
void ContentLibraryView::customNotification(const AbstractView *view,
@@ -283,8 +354,6 @@ void ContentLibraryView::customNotification(const AbstractView *view,
const QList<ModelNode> &nodeList,
const QList<QVariant> &data)
{
- Q_UNUSED(data)
-
if (view == this)
return;
@@ -324,6 +393,12 @@ void ContentLibraryView::customNotification(const AbstractView *view,
m_bundleEffectPos = data.size() == 1 ? data.first() : QVariant();
m_widget->effectsModel()->addInstance(m_draggedBundleEffect);
m_bundleEffectTarget = nodeList.first() ? nodeList.first() : Utils3D::active3DSceneNode(this);
+ } else if (identifier == "add_material_to_content_lib") {
+ QTC_ASSERT(nodeList.size() == 1 && data.size() == 1, return);
+
+ addLibMaterial(nodeList.first(), data.first().value<QPixmap>());
+ } else if (identifier == "add_assets_to_content_lib") {
+ addLibAssets(data.first().toStringList());
}
}
@@ -452,6 +527,163 @@ void ContentLibraryView::applyBundleMaterialToDropTarget(const ModelNode &bundle
}
#endif
+// Add a project material to Content Library's user tab
+void ContentLibraryView::addLibMaterial(const ModelNode &mat, const QPixmap &icon)
+{
+ auto bundlePath = Utils::FilePath::fromString(Paths::bundlesPathSetting() + "/User/materials/");
+
+ auto [name, qml] = m_widget->userModel()->getUniqueLibMaterialNameAndQml(
+ mat.variantProperty("objectName").value().toString());
+
+ bundlePath.pathAppended("icons").createDir();
+ bundlePath.pathAppended("images").createDir();
+ bundlePath.pathAppended("shaders").createDir();
+
+ QString iconPath = QLatin1String("icons/%1.png").arg(mat.id());
+ QString fullIconPath = bundlePath.pathAppended(iconPath).toString();
+
+ // save icon
+ bool iconSaved = icon.save(fullIconPath);
+ if (!iconSaved)
+ qWarning() << __FUNCTION__ << "icon save failed";
+
+ // generate and save material Qml file
+ const QStringList depAssets = writeLibMaterialQml(mat, qml);
+
+ // add the material to the bundle json
+ QJsonObject &jsonRef = m_widget->userModel()->bundleJsonObjectRef();
+ QJsonObject matsObj = jsonRef.value("materials").toObject();
+ QJsonObject matObj;
+ matObj.insert("qml", qml);
+ matObj.insert("icon", iconPath);
+ QJsonArray filesArr;
+ for (const QString &assetPath : depAssets)
+ filesArr.append(assetPath);
+ matObj.insert("files", filesArr);
+
+ matsObj.insert(name, matObj);
+ jsonRef.insert("materials", matsObj);
+ auto result = bundlePath.pathAppended("user_materials_bundle.json")
+ .writeFileContents(QJsonDocument(jsonRef).toJson());
+ if (!result)
+ qWarning() << __FUNCTION__ << result.error();
+
+ // copy material assets to bundle folder
+ for (const QString &assetPath : depAssets) {
+ Asset asset(assetPath);
+ QString subDir;
+ if (asset.isImage())
+ subDir = "images";
+ else if (asset.isShader())
+ subDir = "shaders";
+
+ Utils::FilePath assetPathSource = DocumentManager::currentResourcePath().pathAppended(assetPath);
+ Utils::FilePath assetPathTarget = bundlePath.pathAppended(QString("%1/%2")
+ .arg(subDir, "/" + asset.fileName()));
+
+ auto result = assetPathSource.copyFile(assetPathTarget);
+ if (!result)
+ qWarning() << __FUNCTION__ << result.error();
+ }
+
+ m_widget->userModel()->addMaterial(name, qml, QUrl::fromLocalFile(fullIconPath), depAssets);
+}
+
+QStringList ContentLibraryView::writeLibMaterialQml(const ModelNode &mat, const QString &qml)
+{
+ QStringList depListIds;
+ auto [qmlString, assets] = modelNodeToQmlString(mat, depListIds);
+
+ qmlString.prepend("import QtQuick\nimport QtQuick3D\n\n");
+
+ auto qmlPath = Utils::FilePath::fromString(Paths::bundlesPathSetting() + "/User/materials/" + qml);
+ auto result = qmlPath.writeFileContents(qmlString.toUtf8());
+ if (!result)
+ qWarning() << __FUNCTION__ << result.error();
+
+ return assets.values();
+}
+
+QPair<QString, QSet<QString>> ContentLibraryView::modelNodeToQmlString(const ModelNode &node,
+ QStringList &depListIds,
+ int depth)
+{
+ QString qml;
+ QSet<QString> assets;
+
+ QString indent = QString(" ").repeated(depth * 4);
+
+ qml += indent + node.simplifiedTypeName() + " {\n";
+
+ indent = QString(" ").repeated((depth + 1) * 4);
+
+ qml += indent + "id: " + (depth == 0 ? "root" : node.id()) + " \n\n";
+
+ const QList<AbstractProperty> matProps = node.properties();
+ for (const AbstractProperty &p : matProps) {
+ if (p.isVariantProperty()) {
+ QVariant pValue = p.toVariantProperty().value();
+ QString val;
+ if (strcmp(pValue.typeName(), "QString") == 0 || strcmp(pValue.typeName(), "QColor") == 0) {
+ val = QLatin1String("\"%1\"").arg(pValue.toString());
+ } else if (strcmp(pValue.typeName(), "QUrl") == 0) {
+ val = QLatin1String("\"%1\"").arg(pValue.toString());
+ assets.insert(pValue.toString());
+ } else if (strcmp(pValue.typeName(), "QmlDesigner::Enumeration") == 0) {
+ val = pValue.value<QmlDesigner::Enumeration>().toString();
+ } else {
+ val = pValue.toString();
+ }
+
+ qml += indent + p.name() + ": " + val + "\n";
+ } else if (p.isBindingProperty()) {
+ qml += indent + p.name() + ": " + p.toBindingProperty().expression() + "\n";
+
+ ModelNode depNode = modelNodeForId(p.toBindingProperty().expression());
+
+ if (depNode && !depListIds.contains(depNode.id())) {
+ depListIds.append(depNode.id());
+ auto [depQml, depAssets] = modelNodeToQmlString(depNode, depListIds, depth + 1);
+ qml += "\n" + depQml + "\n";
+ assets.unite(depAssets);
+ }
+ }
+ }
+
+ indent = QString(" ").repeated(depth * 4);
+
+ qml += indent + "}\n";
+
+ return {qml, assets};
+}
+
+void ContentLibraryView::addLibAssets(const QStringList &paths)
+{
+ auto bundlePath = Utils::FilePath::fromString(Paths::bundlesPathSetting() + "/User/textures");
+ QStringList pathsInBundle;
+
+ for (const QString &path : paths) {
+ Asset asset(path);
+ auto assetPath = Utils::FilePath::fromString(path);
+
+ // save icon
+ QString iconSavePath = bundlePath.pathAppended("icons/" + assetPath.baseName() + ".png").toString();
+ QPixmap icon = asset.pixmap({120, 120});
+ bool iconSaved = icon.save(iconSavePath);
+ if (!iconSaved)
+ qWarning() << __FUNCTION__ << "icon save failed";
+
+ // save asset
+ auto result = assetPath.copyFile(bundlePath.pathAppended(asset.fileName()));
+ if (!result)
+ qWarning() << __FUNCTION__ << result.error();
+
+ pathsInBundle.append(bundlePath.pathAppended(asset.fileName()).toString());
+ }
+
+ m_widget->userModel()->addTextures(pathsInBundle);
+}
+
ModelNode ContentLibraryView::getBundleMaterialDefaultInstance(const TypeName &type)
{
ModelNode matLib = Utils3D::materialLibraryNode(this);
@@ -477,6 +709,7 @@ ModelNode ContentLibraryView::getBundleMaterialDefaultInstance(const TypeName &t
return {};
}
+
#ifdef QDS_USE_PROJECTSTORAGE
ModelNode ContentLibraryView::createMaterial(const TypeName &typeName)
{
@@ -548,6 +781,25 @@ void ContentLibraryView::updateBundleMaterialsImportedState()
m_widget->materialsModel()->updateImportedState(importedBundleMats);
}
+void ContentLibraryView::updateBundleUserMaterialsImportedState()
+{
+ using namespace Utils;
+
+ if (!m_widget->userModel()->bundleImporter())
+ return;
+
+ QStringList importedBundleMats;
+
+ FilePath bundlePath = m_widget->userModel()->bundleImporter()->resolveBundleImportPath();
+
+ if (bundlePath.exists()) {
+ importedBundleMats = transform(bundlePath.dirEntries({{"*.qml"}, QDir::Files}),
+ [](const FilePath &f) { return f.fileName().chopped(4); });
+ }
+
+ m_widget->userModel()->updateImportedState(importedBundleMats);
+}
+
void ContentLibraryView::updateBundleEffectsImportedState()
{
using namespace Utils;
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h
index 3b57b7a4ab..03d42fa8bc 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h
@@ -10,6 +10,8 @@
#include <QObject>
#include <QPointer>
+QT_FORWARD_DECLARE_CLASS(QPixmap)
+
namespace QmlDesigner {
class ContentLibraryEffect;
@@ -46,10 +48,18 @@ public:
const QVariant &data) override;
private:
+ void connectUserBundle();
void active3DSceneChanged(qint32 sceneId);
void updateBundleMaterialsImportedState();
+ void updateBundleUserMaterialsImportedState();
void updateBundleEffectsImportedState();
void updateBundlesQuick3DVersion();
+ void addLibMaterial(const ModelNode &mat, const QPixmap &icon);
+ void addLibAssets(const QStringList &paths);
+ QStringList writeLibMaterialQml(const ModelNode &mat, const QString &qml);
+ QPair<QString, QSet<QString>> modelNodeToQmlString(const ModelNode &node, QStringList &depListIds,
+ int depth = 0);
+
#ifdef QDS_USE_PROJECTSTORAGE
void applyBundleMaterialToDropTarget(const ModelNode &bundleMat, const TypeName &typeName = {});
#else
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp
index c885a76ba7..9375d43fd4 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp
@@ -10,6 +10,7 @@
#include "contentlibrarytexture.h"
#include "contentlibrarytexturesmodel.h"
#include "contentlibraryiconprovider.h"
+#include "contentlibraryusermodel.h"
#include "utils/filedownloader.h"
#include "utils/fileextractor.h"
@@ -100,10 +101,10 @@ bool ContentLibraryWidget::eventFilter(QObject *obj, QEvent *event)
&& m_textureToDrag->isDownloaded()) {
QMimeData *mimeData = new QMimeData;
mimeData->setData(Constants::MIME_TYPE_BUNDLE_TEXTURE,
- {m_textureToDrag->downloadedTexturePath().toUtf8()});
+ {m_textureToDrag->texturePath().toUtf8()});
// Allows standard file drag-n-drop. As of now needed to drop on Assets view
- mimeData->setUrls({QUrl::fromLocalFile(m_textureToDrag->downloadedTexturePath())});
+ mimeData->setUrls({QUrl::fromLocalFile(m_textureToDrag->texturePath())});
emit bundleTextureDragStarted(m_textureToDrag);
model->startDrag(mimeData, m_textureToDrag->icon().toLocalFile());
@@ -126,6 +127,7 @@ ContentLibraryWidget::ContentLibraryWidget()
, m_texturesModel(new ContentLibraryTexturesModel("Textures", this))
, m_environmentsModel(new ContentLibraryTexturesModel("Environments", this))
, m_effectsModel(new ContentLibraryEffectsModel(this))
+ , m_userModel(new ContentLibraryUserModel(this))
{
qmlRegisterType<QmlDesigner::FileDownloader>("WebFetcher", 1, 0, "FileDownloader");
qmlRegisterType<QmlDesigner::FileExtractor>("WebFetcher", 1, 0, "FileExtractor");
@@ -140,18 +142,12 @@ ContentLibraryWidget::ContentLibraryWidget()
m_quickWidget->engine()->addImportPath(propertyEditorResourcesPath() + "/imports");
m_quickWidget->setClearColor(Theme::getColor(Theme::Color::DSpanelBackground));
- m_baseUrl = QmlDesignerPlugin::settings()
- .value(DesignerSettingsKey::DOWNLOADABLE_BUNDLES_URL).toString()
- + "/textures";
+ m_textureBundleUrl = QmlDesignerPlugin::settings()
+ .value(DesignerSettingsKey::DOWNLOADABLE_BUNDLES_URL).toString() + "/textures";
- m_texturesUrl = m_baseUrl + "/Textures";
- m_textureIconsUrl = m_baseUrl + "/icons/Textures";
- m_environmentIconsUrl = m_baseUrl + "/icons/Environments";
- m_environmentsUrl = m_baseUrl + "/Environments";
+ m_bundlePath = Paths::bundlesPathSetting();
- m_downloadPath = Paths::bundlesPathSetting();
-
- loadTextureBundle();
+ loadTextureBundles();
Theme::setupTheme(m_quickWidget->engine());
m_quickWidget->quickWidget()->installEventFilter(this);
@@ -177,38 +173,34 @@ ContentLibraryWidget::ContentLibraryWidget()
{"materialsModel", QVariant::fromValue(m_materialsModel.data())},
{"texturesModel", QVariant::fromValue(m_texturesModel.data())},
{"environmentsModel", QVariant::fromValue(m_environmentsModel.data())},
- {"effectsModel", QVariant::fromValue(m_effectsModel.data())}});
+ {"effectsModel", QVariant::fromValue(m_effectsModel.data())},
+ {"userModel", QVariant::fromValue(m_userModel.data())}});
reloadQmlSource();
}
-QVariantMap ContentLibraryWidget::readBundleMetadata()
+QVariantMap ContentLibraryWidget::readTextureBundleJson()
{
- QVariantMap metaData;
- QFile jsonFile(m_downloadPath + "/texture_bundle.json");
+ QVariantMap jsonData;
+ QFile jsonFile(m_bundlePath + "/texture_bundle.json");
if (jsonFile.open(QIODevice::ReadOnly | QIODevice::Text))
- metaData = QJsonDocument::fromJson(jsonFile.readAll()).toVariant().toMap();
+ jsonData = QJsonDocument::fromJson(jsonFile.readAll()).toVariant().toMap();
- int version = metaData["version"].toInt();
+ int version = jsonData["version"].toInt();
if (version > TextureBundleMetadataVersion) {
qWarning() << "Unrecognized texture metadata file version: " << version;
return {};
}
- return metaData;
+ return jsonData;
}
-void ContentLibraryWidget::loadTextureBundle()
+void ContentLibraryWidget::loadTextureBundles()
{
- QDir bundleDir{m_downloadPath};
+ QDir bundleDir{m_bundlePath};
- if (fetchTextureBundleMetadata(bundleDir) && fetchTextureBundleIcons(bundleDir)) {
- QString bundleIconPath = m_downloadPath + "/TextureBundleIcons";
- QVariantMap metaData = readBundleMetadata();
- m_texturesModel->loadTextureBundle(m_texturesUrl, m_textureIconsUrl, bundleIconPath, metaData);
- m_environmentsModel->loadTextureBundle(m_environmentsUrl, m_environmentIconsUrl,
- bundleIconPath, metaData);
- }
+ if (fetchTextureBundleJson(bundleDir) && fetchTextureBundleIcons(bundleDir))
+ populateTextureBundleModels();
}
std::tuple<QVariantMap, QVariantMap, QVariantMap> ContentLibraryWidget::compareTextureMetaFiles(
@@ -272,9 +264,9 @@ void ContentLibraryWidget::fetchNewTextureIcons(const QVariantMap &existingFiles
});
auto multidownloader = new MultiFileDownloader(this);
- multidownloader->setBaseUrl(QString(m_baseUrl + "/icons"));
+ multidownloader->setBaseUrl(QString(m_textureBundleUrl + "/icons"));
multidownloader->setFiles(fileList);
- multidownloader->setTargetDirPath(m_downloadPath + "/TextureBundleIcons");
+ multidownloader->setTargetDirPath(m_bundlePath + "/TextureBundleIcons");
auto downloader = new FileDownloader(this);
downloader->setDownloadEnabled(true);
@@ -314,15 +306,8 @@ void ContentLibraryWidget::fetchNewTextureIcons(const QVariantMap &existingFiles
existingFile.flush();
}
- if (fetchTextureBundleIcons(bundleDir)) {
- QString bundleIconPath = m_downloadPath + "/TextureBundleIcons";
- QVariantMap metaData = readBundleMetadata();
- m_texturesModel->loadTextureBundle(m_texturesUrl, m_textureIconsUrl, bundleIconPath,
- metaData);
- m_environmentsModel->loadTextureBundle(m_environmentsUrl, m_environmentIconsUrl,
- bundleIconPath, metaData);
- }
-
+ if (fetchTextureBundleIcons(bundleDir))
+ populateTextureBundleModels();
});
multidownloader->start();
@@ -433,50 +418,45 @@ QStringList ContentLibraryWidget::saveNewTextures(const QDir &bundleDir, const Q
}
}
-bool ContentLibraryWidget::fetchTextureBundleMetadata(const QDir &bundleDir)
+bool ContentLibraryWidget::fetchTextureBundleJson(const QDir &bundleDir)
{
QString filePath = bundleDir.filePath("texture_bundle.json");
QFileInfo fi(filePath);
- bool metaFileExists = fi.exists() && fi.size() > 0;
+ bool jsonFileExists = fi.exists() && fi.size() > 0;
- QString metaFileUrl = m_baseUrl + "/texture_bundle.zip";
+ QString bundleZipUrl = m_textureBundleUrl + "/texture_bundle.zip";
FileDownloader *downloader = new FileDownloader(this);
- downloader->setUrl(metaFileUrl);
+ downloader->setUrl(bundleZipUrl);
downloader->setProbeUrl(false);
downloader->setDownloadEnabled(true);
+ downloader->start();
QObject::connect(downloader, &FileDownloader::downloadFailed, this,
- [this, metaFileExists, bundleDir] {
- if (metaFileExists) {
- if (fetchTextureBundleIcons(bundleDir)) {
- QString bundleIconPath = m_downloadPath + "/TextureBundleIcons";
- QVariantMap metaData = readBundleMetadata();
- m_texturesModel->loadTextureBundle(m_texturesUrl, m_textureIconsUrl, bundleIconPath,
- metaData);
- m_environmentsModel->loadTextureBundle(m_environmentsUrl, m_environmentIconsUrl,
- bundleIconPath, metaData);
- }
+ [this, jsonFileExists, bundleDir] {
+ if (jsonFileExists) {
+ if (fetchTextureBundleIcons(bundleDir))
+ populateTextureBundleModels();
}
});
QObject::connect(downloader, &FileDownloader::finishedChanged, this,
- [this, downloader, bundleDir, metaFileExists, filePath] {
+ [this, downloader, bundleDir, jsonFileExists, filePath] {
FileExtractor *extractor = new FileExtractor(this);
extractor->setArchiveName(downloader->completeBaseName());
extractor->setSourceFile(downloader->outputFile());
- if (!metaFileExists)
+ if (!jsonFileExists)
extractor->setTargetPath(bundleDir.absolutePath());
extractor->setAlwaysCreateDir(false);
extractor->setClearTargetPathContents(false);
QObject::connect(extractor, &FileExtractor::finishedChanged, this,
- [this, downloader, bundleDir, extractor, metaFileExists, filePath] {
+ [this, downloader, bundleDir, extractor, jsonFileExists, filePath] {
downloader->deleteLater();
extractor->deleteLater();
- if (metaFileExists) {
+ if (jsonFileExists) {
QVariantMap newFiles, existing;
QVariantMap modifiedFilesEntries;
@@ -498,32 +478,35 @@ bool ContentLibraryWidget::fetchTextureBundleMetadata(const QDir &bundleDir)
}
}
- if (fetchTextureBundleIcons(bundleDir)) {
- QString bundleIconPath = m_downloadPath + "/TextureBundleIcons";
- QVariantMap metaData = readBundleMetadata();
- m_texturesModel->loadTextureBundle(m_texturesUrl, m_textureIconsUrl, bundleIconPath,
- metaData);
- m_environmentsModel->loadTextureBundle(m_environmentsUrl, m_environmentIconsUrl,
- bundleIconPath, metaData);
- }
+ if (fetchTextureBundleIcons(bundleDir))
+ populateTextureBundleModels();
});
extractor->extract();
});
- downloader->start();
return false;
}
+void ContentLibraryWidget::populateTextureBundleModels()
+{
+ QVariantMap jsonData = readTextureBundleJson();
+
+ QString bundleIconPath = m_bundlePath + "/TextureBundleIcons";
+
+ m_texturesModel->loadTextureBundle(m_textureBundleUrl, bundleIconPath, jsonData);
+ m_environmentsModel->loadTextureBundle(m_textureBundleUrl, bundleIconPath, jsonData);
+}
+
bool ContentLibraryWidget::fetchTextureBundleIcons(const QDir &bundleDir)
{
QString iconsPath = bundleDir.filePath("TextureBundleIcons");
QDir iconsDir(iconsPath);
- if (iconsDir.exists() && iconsDir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot).length() > 0)
+ if (iconsDir.exists() && !iconsDir.isEmpty())
return true;
- QString zipFileUrl = m_baseUrl + "/icons.zip";
+ QString zipFileUrl = m_textureBundleUrl + "/icons.zip";
FileDownloader *downloader = new FileDownloader(this);
downloader->setUrl(zipFileUrl);
@@ -543,13 +526,7 @@ bool ContentLibraryWidget::fetchTextureBundleIcons(const QDir &bundleDir)
[this, downloader, extractor] {
downloader->deleteLater();
extractor->deleteLater();
-
- QString bundleIconPath = m_downloadPath + "/TextureBundleIcons";
- QVariantMap metaData = readBundleMetadata();
- m_texturesModel->loadTextureBundle(m_texturesUrl, m_textureIconsUrl, bundleIconPath,
- metaData);
- m_environmentsModel->loadTextureBundle(m_environmentsUrl, m_environmentIconsUrl,
- bundleIconPath, metaData);
+ populateTextureBundleModels();
});
extractor->extract();
@@ -572,7 +549,7 @@ void ContentLibraryWidget::markTextureUpdated(const QString &textureKey)
checksumOnServer = m_environmentsModel->removeModifiedFileEntry(textureKey);
QJsonObject metaDataObj;
- QFile jsonFile(m_downloadPath + "/texture_bundle.json");
+ QFile jsonFile(m_bundlePath + "/texture_bundle.json");
if (jsonFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
metaDataObj = QJsonDocument::fromJson(jsonFile.readAll()).object();
jsonFile.close();
@@ -589,7 +566,7 @@ void ContentLibraryWidget::markTextureUpdated(const QString &textureKey)
QJsonDocument outDoc(metaDataObj);
QByteArray data = outDoc.toJson();
- QFile outFile(m_downloadPath + "/texture_bundle.json");
+ QFile outFile(m_bundlePath + "/texture_bundle.json");
if (outFile.open(QIODeviceBase::WriteOnly | QIODeviceBase::Text)) {
outFile.write(data);
outFile.flush();
@@ -601,6 +578,12 @@ void ContentLibraryWidget::markTextureUpdated(const QString &textureKey)
m_environmentsModel->markTextureHasNoUpdates(subcategory, textureKey);
}
+bool ContentLibraryWidget::userBundleEnabled() const
+{
+ // TODO: this method is to be removed after user bundle implementation is complete
+ return Core::ICore::settings()->value("QML/Designer/UseExperimentalFeatures45", false).toBool();
+}
+
QSize ContentLibraryWidget::sizeHint() const
{
return {420, 420};
@@ -715,6 +698,7 @@ void ContentLibraryWidget::updateSearch()
m_effectsModel->setSearchText(m_filterText);
m_texturesModel->setSearchText(m_filterText);
m_environmentsModel->setSearchText(m_filterText);
+ m_userModel->setSearchText(m_filterText);
m_quickWidget->update();
}
@@ -777,7 +761,7 @@ void ContentLibraryWidget::addImage(ContentLibraryTexture *tex)
if (!tex->isDownloaded())
return;
- emit addTextureRequested(tex->downloadedTexturePath(), AddTextureMode::Image);
+ emit addTextureRequested(tex->texturePath(), AddTextureMode::Image);
}
void ContentLibraryWidget::addTexture(ContentLibraryTexture *tex)
@@ -785,7 +769,7 @@ void ContentLibraryWidget::addTexture(ContentLibraryTexture *tex)
if (!tex->isDownloaded())
return;
- emit addTextureRequested(tex->downloadedTexturePath(), AddTextureMode::Texture);
+ emit addTextureRequested(tex->texturePath(), AddTextureMode::Texture);
}
void ContentLibraryWidget::addLightProbe(ContentLibraryTexture *tex)
@@ -793,7 +777,7 @@ void ContentLibraryWidget::addLightProbe(ContentLibraryTexture *tex)
if (!tex->isDownloaded())
return;
- emit addTextureRequested(tex->downloadedTexturePath(), AddTextureMode::LightProbe);
+ emit addTextureRequested(tex->texturePath(), AddTextureMode::LightProbe);
}
void ContentLibraryWidget::updateSceneEnvState()
@@ -821,4 +805,9 @@ QPointer<ContentLibraryEffectsModel> ContentLibraryWidget::effectsModel() const
return m_effectsModel;
}
+QPointer<ContentLibraryUserModel> ContentLibraryWidget::userModel() const
+{
+ return m_userModel;
+}
+
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.h
index ab71a3dc79..c4d51d0362 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.h
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.h
@@ -24,6 +24,7 @@ class ContentLibraryMaterial;
class ContentLibraryMaterialsModel;
class ContentLibraryTexture;
class ContentLibraryTexturesModel;
+class ContentLibraryUserModel;
class ContentLibraryWidget : public QFrame
{
@@ -65,6 +66,7 @@ public:
QPointer<ContentLibraryTexturesModel> texturesModel() const;
QPointer<ContentLibraryTexturesModel> environmentsModel() const;
QPointer<ContentLibraryEffectsModel> effectsModel() const;
+ QPointer<ContentLibraryUserModel> userModel() const;
Q_INVOKABLE void startDragEffect(QmlDesigner::ContentLibraryEffect *eff, const QPointF &mousePos);
Q_INVOKABLE void startDragMaterial(QmlDesigner::ContentLibraryMaterial *mat, const QPointF &mousePos);
@@ -74,6 +76,7 @@ public:
Q_INVOKABLE void addLightProbe(QmlDesigner::ContentLibraryTexture *tex);
Q_INVOKABLE void updateSceneEnvState();
Q_INVOKABLE void markTextureUpdated(const QString &textureKey);
+ Q_INVOKABLE bool userBundleEnabled() const;
QSize sizeHint() const override;
@@ -97,21 +100,23 @@ private:
void updateSearch();
void setIsDragging(bool val);
QString findTextureBundlePath();
- void loadTextureBundle();
- QVariantMap readBundleMetadata();
- bool fetchTextureBundleMetadata(const QDir &bundleDir);
+ void loadTextureBundles();
+ QVariantMap readTextureBundleJson();
+ bool fetchTextureBundleJson(const QDir &bundleDir);
bool fetchTextureBundleIcons(const QDir &bundleDir);
void fetchNewTextureIcons(const QVariantMap &existingFiles, const QVariantMap &newFiles,
const QString &existingMetaFilePath, const QDir &bundleDir);
std::tuple<QVariantMap, QVariantMap, QVariantMap> compareTextureMetaFiles(
const QString &existingMetaFile, const QString downloadedMetaFile);
QStringList saveNewTextures(const QDir &bundleDir, const QStringList &newFiles);
+ void populateTextureBundleModels();
QScopedPointer<StudioQuickWidget> m_quickWidget;
QPointer<ContentLibraryMaterialsModel> m_materialsModel;
QPointer<ContentLibraryTexturesModel> m_texturesModel;
QPointer<ContentLibraryTexturesModel> m_environmentsModel;
QPointer<ContentLibraryEffectsModel> m_effectsModel;
+ QPointer<ContentLibraryUserModel> m_userModel;
QShortcut *m_qmlSourceUpdateShortcut = nullptr;
@@ -127,12 +132,8 @@ private:
bool m_hasQuick3DImport = false;
bool m_isDragging = false;
bool m_isQt6Project = false;
- QString m_baseUrl;
- QString m_texturesUrl;
- QString m_textureIconsUrl;
- QString m_environmentIconsUrl;
- QString m_environmentsUrl;
- QString m_downloadPath;
+ QString m_textureBundleUrl;
+ QString m_bundlePath;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/createtexture.cpp b/src/plugins/qmldesigner/components/createtexture.cpp
index b6e99ae972..56056e3fd2 100644
--- a/src/plugins/qmldesigner/components/createtexture.cpp
+++ b/src/plugins/qmldesigner/components/createtexture.cpp
@@ -17,6 +17,7 @@
#include <coreplugin/messagebox.h>
#include <QTimer>
+#include <QUrl>
namespace QmlDesigner {
@@ -94,7 +95,7 @@ ModelNode CreateTexture::createTextureFromImage(const Utils::FilePath &assetPat
newTexNode.setIdWithoutRefactoring(m_view->model()->generateNewId(assetPath.baseName()));
VariantProperty sourceProp = newTexNode.variantProperty("source");
- sourceProp.setValue(textureSource);
+ sourceProp.setValue(QUrl(textureSource));
matLib.defaultNodeListProperty().reparentHere(newTexNode);
}
diff --git a/src/plugins/qmldesigner/components/curveeditor/curveeditor.cpp b/src/plugins/qmldesigner/components/curveeditor/curveeditor.cpp
index e84623e26c..36ce3373e5 100644
--- a/src/plugins/qmldesigner/components/curveeditor/curveeditor.cpp
+++ b/src/plugins/qmldesigner/components/curveeditor/curveeditor.cpp
@@ -77,8 +77,8 @@ CurveEditor::CurveEditor(CurveEditorModel *model, QWidget *parent)
connect(m_toolbar, &CurveEditorToolBar::currentFrameChanged, [this, model](int frame) {
model->setCurrentFrame(frame);
+ m_view->setCurrentFrame(frame, false);
updateStatusLine();
- m_view->viewport()->update();
});
connect(m_toolbar, &CurveEditorToolBar::zoomChanged, [this](double zoom) {
diff --git a/src/plugins/qmldesigner/components/curveeditor/curveeditortoolbar.cpp b/src/plugins/qmldesigner/components/curveeditor/curveeditortoolbar.cpp
index 72410ffb07..8da87ce119 100644
--- a/src/plugins/qmldesigner/components/curveeditor/curveeditortoolbar.cpp
+++ b/src/plugins/qmldesigner/components/curveeditor/curveeditortoolbar.cpp
@@ -129,6 +129,8 @@ CurveEditorToolBar::CurveEditorToolBar(CurveEditorModel *model, QWidget* parent)
m_currentSpin->setFrame(false);
connect(m_currentSpin, &QSpinBox::valueChanged, this, &CurveEditorToolBar::currentFrameChanged);
+ connect(model, &CurveEditorModel::commitCurrentFrame,
+ this, [this](int frame) { m_currentSpin->setValue(frame); });
addSpacer();
diff --git a/src/plugins/qmldesigner/components/edit3d/bakelightsdatamodel.cpp b/src/plugins/qmldesigner/components/edit3d/bakelightsdatamodel.cpp
index 95a260c26f..a1dfcc8f98 100644
--- a/src/plugins/qmldesigner/components/edit3d/bakelightsdatamodel.cpp
+++ b/src/plugins/qmldesigner/components/edit3d/bakelightsdatamodel.cpp
@@ -15,6 +15,8 @@
#include "qmlobjectnode.h"
#include "variantproperty.h"
+#include <model/modelutils.h>
+
#include <utils3d.h>
#include <utils/expected.h>
@@ -292,7 +294,7 @@ bool BakeLightsDataModel::reset()
if (!hasExposedProps && node.metaInfo().isFileComponent()
&& node.metaInfo().isQtQuick3DNode()) {
- const QString compFile = node.metaInfo().componentFileName();
+ const QString compFile = ModelUtils::componentFilePath(node);
const QString projPath = m_view->externalDependencies().currentProjectDirPath();
if (compFile.startsWith(projPath)) {
// Quick and dirty scan of the component source to check if it potentially has
diff --git a/src/plugins/qmldesigner/components/edit3d/cameraspeedconfiguration.cpp b/src/plugins/qmldesigner/components/edit3d/cameraspeedconfiguration.cpp
index 76560ac192..f5a74ee864 100644
--- a/src/plugins/qmldesigner/components/edit3d/cameraspeedconfiguration.cpp
+++ b/src/plugins/qmldesigner/components/edit3d/cameraspeedconfiguration.cpp
@@ -66,9 +66,11 @@ void CameraSpeedConfiguration::resetDefaults()
void CameraSpeedConfiguration::hideCursor()
{
- if (QGuiApplication::overrideCursor())
+ if (m_cursorHidden)
return;
+ m_cursorHidden = true;
+
QGuiApplication::setOverrideCursor(QCursor(Qt::BlankCursor));
if (QWindow *w = QGuiApplication::focusWindow())
@@ -77,9 +79,11 @@ void CameraSpeedConfiguration::hideCursor()
void CameraSpeedConfiguration::restoreCursor()
{
- if (!QGuiApplication::overrideCursor())
+ if (!m_cursorHidden)
return;
+ m_cursorHidden = false;
+
QGuiApplication::restoreOverrideCursor();
if (QWindow *w = QGuiApplication::focusWindow())
@@ -88,7 +92,7 @@ void CameraSpeedConfiguration::restoreCursor()
void CameraSpeedConfiguration::holdCursorInPlace()
{
- if (!QGuiApplication::overrideCursor())
+ if (!m_cursorHidden)
return;
if (QWindow *w = QGuiApplication::focusWindow())
diff --git a/src/plugins/qmldesigner/components/edit3d/cameraspeedconfiguration.h b/src/plugins/qmldesigner/components/edit3d/cameraspeedconfiguration.h
index 55256890cb..fef06efc49 100644
--- a/src/plugins/qmldesigner/components/edit3d/cameraspeedconfiguration.h
+++ b/src/plugins/qmldesigner/components/edit3d/cameraspeedconfiguration.h
@@ -71,6 +71,7 @@ private:
double m_multiplier = 0.;
bool m_changes = false;
QPoint m_lastPos;
+ bool m_cursorHidden = false;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp
index 911ee1fb15..a20904b2e5 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp
@@ -279,6 +279,14 @@ void Edit3DView::modelAttached(Model *model)
{
AbstractView::modelAttached(model);
+ QString currProjectPath = QmlDesigner::DocumentManager::currentProjectDirPath().toString();
+ if (m_currProjectPath != currProjectPath) {
+ // Opening a new project -> reset camera speeds
+ m_currProjectPath = currProjectPath;
+ m_previousCameraSpeed = -1.;
+ m_previousCameraMultiplier = -1.;
+ }
+
syncSnapAuxPropsToSettings();
rootModelNode().setAuxiliaryData(edit3dGridColorProperty,
@@ -356,7 +364,12 @@ void Edit3DView::handleEntriesChanged()
append(model()->qtQuick3DOrthographicCameraMetaInfo(), EK_cameras);
append(model()->qtQuick3DPerspectiveCameraMetaInfo(), EK_cameras);
- auto assetsModule = model()->module("Quick3DAssets");
+ Utils::PathString import3dTypePrefix = QmlDesignerPlugin::instance()
+ ->documentManager()
+ .generatedComponentUtils()
+ .import3dTypePrefix();
+
+ auto assetsModule = model()->module(import3dTypePrefix);
for (const auto &metaInfo : model()->metaInfosForModule(assetsModule))
append(metaInfo, EK_importedModels);
@@ -373,7 +386,8 @@ void Edit3DView::handleEntriesChanged()
} else if (entry.typeName() == "QtQuick3D.OrthographicCamera"
|| entry.typeName() == "QtQuick3D.PerspectiveCamera") {
entryKey = EK_cameras;
- } else if (entry.typeName().startsWith("Quick3DAssets.")
+ } else if (entry.typeName().startsWith(QmlDesignerPlugin::instance()->documentManager()
+ .generatedComponentUtils().import3dTypePrefix().toUtf8())
&& NodeHints::fromItemLibraryEntry(entry).canBeDroppedInView3D()) {
entryKey = EK_importedModels;
} else {
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.h b/src/plugins/qmldesigner/components/edit3d/edit3dview.h
index 781b26d8d8..fad87aae1f 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dview.h
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.h
@@ -192,6 +192,7 @@ private:
double m_previousCameraSpeed = -1.;
double m_previousCameraMultiplier = -1.;
+ QString m_currProjectPath;
friend class Edit3DAction;
};
diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp
index 07102ae893..6f1cf2e183 100644
--- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp
+++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp
@@ -766,7 +766,11 @@ void Edit3DWidget::dropEvent(QDropEvent *dropEvent)
QString fileName = QFileInfo(assetPath).baseName();
fileName = fileName.at(0).toUpper() + fileName.mid(1); // capitalize first letter
auto model = m_view->model();
- auto metaInfo = model->metaInfo(model->module("Quick3DAssets"), fileName.toUtf8());
+ Utils::PathString import3dTypePrefix = QmlDesignerPlugin::instance()
+ ->documentManager()
+ .generatedComponentUtils()
+ .import3dTypePrefix();
+ auto metaInfo = model->metaInfo(model->module(import3dTypePrefix), fileName.toUtf8());
if (auto entries = metaInfo.itemLibrariesEntries(); entries.size()) {
auto entry = ItemLibraryEntry{entries.front(), *model->projectStorage()};
QmlVisualNode::createQml3DNode(view(), entry, m_canvas->activeScene(), {}, false);
@@ -780,7 +784,9 @@ void Edit3DWidget::dropEvent(QDropEvent *dropEvent)
for (const QString &assetPath : added3DAssets) {
QString fileName = QFileInfo(assetPath).baseName();
fileName = fileName.at(0).toUpper() + fileName.mid(1); // capitalize first letter
- QString type = QString("Quick3DAssets.%1.%1").arg(fileName);
+ QString type = QString("%1.%2.%2").arg(QmlDesignerPlugin::instance()->documentManager()
+ .generatedComponentUtils().import3dTypePrefix(),
+ fileName);
QList<ItemLibraryEntry> entriesForType = itemLibInfo->entriesForType(type.toUtf8());
if (!entriesForType.isEmpty()) { // should always be true, but just in case
QmlVisualNode::createQml3DNode(view(),
diff --git a/src/plugins/qmldesigner/components/edit3d/snapconfiguration.cpp b/src/plugins/qmldesigner/components/edit3d/snapconfiguration.cpp
index 26c5fe0eb2..8890ea8964 100644
--- a/src/plugins/qmldesigner/components/edit3d/snapconfiguration.cpp
+++ b/src/plugins/qmldesigner/components/edit3d/snapconfiguration.cpp
@@ -87,9 +87,11 @@ void SnapConfiguration::resetDefaults()
void SnapConfiguration::hideCursor()
{
- if (QGuiApplication::overrideCursor())
+ if (m_cursorHidden)
return;
+ m_cursorHidden = true;
+
QGuiApplication::setOverrideCursor(QCursor(Qt::BlankCursor));
if (QWindow *w = QGuiApplication::focusWindow())
@@ -98,9 +100,11 @@ void SnapConfiguration::hideCursor()
void SnapConfiguration::restoreCursor()
{
- if (!QGuiApplication::overrideCursor())
+ if (!m_cursorHidden)
return;
+ m_cursorHidden = false;
+
QGuiApplication::restoreOverrideCursor();
if (QWindow *w = QGuiApplication::focusWindow())
@@ -109,7 +113,7 @@ void SnapConfiguration::restoreCursor()
void SnapConfiguration::holdCursorInPlace()
{
- if (!QGuiApplication::overrideCursor())
+ if (!m_cursorHidden)
return;
if (QWindow *w = QGuiApplication::focusWindow())
diff --git a/src/plugins/qmldesigner/components/edit3d/snapconfiguration.h b/src/plugins/qmldesigner/components/edit3d/snapconfiguration.h
index 729e6ce7d1..ae401f60f9 100644
--- a/src/plugins/qmldesigner/components/edit3d/snapconfiguration.h
+++ b/src/plugins/qmldesigner/components/edit3d/snapconfiguration.h
@@ -103,6 +103,7 @@ private:
double m_scaleInterval = 0.;
bool m_changes = false;
QPoint m_lastPos;
+ bool m_cursorHidden = false;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/integration/designdocument.cpp b/src/plugins/qmldesigner/components/integration/designdocument.cpp
index c0bebbb82b..804ac076e6 100644
--- a/src/plugins/qmldesigner/components/integration/designdocument.cpp
+++ b/src/plugins/qmldesigner/components/integration/designdocument.cpp
@@ -64,13 +64,14 @@ namespace QmlDesigner {
DesignDocument acts as a facade to a model representing a qml document,
and the different views/widgets accessing it.
*/
-DesignDocument::DesignDocument(ProjectStorageDependencies projectStorageDependencies,
+DesignDocument::DesignDocument([[maybe_unused]] const QUrl &filePath,
+ ProjectStorageDependencies projectStorageDependencies,
ExternalDependenciesInterface &externalDependencies)
#ifdef QDS_USE_PROJECTSTORAGE
: m_documentModel(Model::create(projectStorageDependencies,
"Item",
{Import::createLibraryImport("QtQuick")},
- {},
+ filePath,
std::make_unique<ModelResourceManagement>()))
#else
: m_documentModel(
diff --git a/src/plugins/qmldesigner/components/integration/designdocument.h b/src/plugins/qmldesigner/components/integration/designdocument.h
index 0d75141205..52089d67c1 100644
--- a/src/plugins/qmldesigner/components/integration/designdocument.h
+++ b/src/plugins/qmldesigner/components/integration/designdocument.h
@@ -41,7 +41,8 @@ class QMLDESIGNERCOMPONENTS_EXPORT DesignDocument : public QObject
Q_OBJECT
public:
- DesignDocument(ProjectStorageDependencies projectStorageDependencies,
+ DesignDocument(const QUrl &filePath,
+ ProjectStorageDependencies projectStorageDependencies,
ExternalDependenciesInterface &externalDependencies);
~DesignDocument() override;
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp
index 29fff4b359..2c69072602 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp
@@ -12,6 +12,7 @@
#include <variantproperty.h>
#include <theme.h>
+#include <utils/filepath.h>
#include <utils/outputformatter.h>
#include <projectexplorer/project.h>
@@ -130,43 +131,8 @@ ItemLibraryAssetImportDialog::ItemLibraryAssetImportDialog(
if (targetDir.isEmpty())
targetDir = defaulTargetDirectory;
- // Import is always done under known folder. The order of preference for folder is:
- // 1) An existing QUICK_3D_ASSETS_FOLDER under DEFAULT_ASSET_IMPORT_FOLDER project import path
- // 2) An existing QUICK_3D_ASSETS_FOLDER under any project import path
- // 3) New QUICK_3D_ASSETS_FOLDER under DEFAULT_ASSET_IMPORT_FOLDER project import path
- // 4) New QUICK_3D_ASSETS_FOLDER under any project import path
- // 5) New QUICK_3D_ASSETS_FOLDER under new DEFAULT_ASSET_IMPORT_FOLDER under project
- const QString defaultAssetFolder = QLatin1String(Constants::DEFAULT_ASSET_IMPORT_FOLDER);
- const QString quick3DFolder = QLatin1String(Constants::QUICK_3D_ASSETS_FOLDER);
- QString candidatePath = targetDir + defaultAssetFolder + quick3DFolder;
- int candidatePriority = 5;
-
- for (const auto &importPath : std::as_const(importPaths)) {
- if (importPath.startsWith(targetDir)) {
- const bool isDefaultFolder = importPath.endsWith(defaultAssetFolder);
- const QString assetFolder = importPath + quick3DFolder;
- const bool exists = QFileInfo::exists(assetFolder);
- if (exists) {
- if (isDefaultFolder) {
- // Priority one location, stop looking
- candidatePath = assetFolder;
- break;
- } else if (candidatePriority > 2) {
- candidatePriority = 2;
- candidatePath = assetFolder;
- }
- } else {
- if (candidatePriority > 3 && isDefaultFolder) {
- candidatePriority = 3;
- candidatePath = assetFolder;
- } else if (candidatePriority > 4) {
- candidatePriority = 4;
- candidatePath = assetFolder;
- }
- }
- }
- }
- m_quick3DImportPath = candidatePath;
+ m_quick3DImportPath = QmlDesignerPlugin::instance()->documentManager()
+ .generatedComponentUtils().import3dBasePath().toString();
if (!m_quick3DFiles.isEmpty()) {
QVector<QJsonObject> groups;
@@ -294,11 +260,14 @@ void ItemLibraryAssetImportDialog::updateImport(const ModelNode &updateNode,
QFileInfo compFileInfo{compFileName};
// Find to top asset folder
- const QString assetFolder = QLatin1String(Constants::QUICK_3D_ASSETS_FOLDER).mid(1);
+ const QString oldAssetFolder = QLatin1String(Constants::OLD_QUICK_3D_ASSETS_FOLDER);
+ QString assetFolder = QLatin1String(Constants::QUICK_3D_COMPONENTS_FOLDER);
const QStringList parts = compFileName.split('/');
int i = parts.size() - 1;
int previousSize = 0;
for (; i >= 0; --i) {
+ if (parts[i] == oldAssetFolder)
+ assetFolder = oldAssetFolder;
if (parts[i] == assetFolder)
break;
previousSize = parts[i].size();
@@ -733,8 +702,10 @@ QGridLayout *ItemLibraryAssetImportDialog::createOptionsGrid(
// and move the remaining member to ungrouped options
// Note: <= 2 instead of < 2 because each group has group label member
if (i != 0 && groupWidgets.size() <= 2) {
- widgets[0].prepend(groupWidgets[1]);
- groupWidgets[0].first->hide(); // hide group label
+ if (groupWidgets.size() == 2)
+ widgets[0].prepend(groupWidgets[1]);
+ if (groupWidgets.size() >= 1)
+ groupWidgets[0].first->hide(); // hide group label
groupWidgets.clear();
}
}
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp
index 48958ceec9..ed1f8041e9 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp
@@ -1,6 +1,7 @@
// Copyright (C) 2019 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "itemlibraryassetimporter.h"
+
#include "assetimportupdatedialog.h"
#include "qmldesignerplugin.h"
#include "qmldesignerconstants.h"
@@ -329,12 +330,15 @@ void ItemLibraryAssetImporter::postParseQuick3DAsset(ParseData &pd)
if (qmldirFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
QString qmlInfo;
qmlInfo.append("module ");
- qmlInfo.append(m_importPath.split('/').last());
+ qmlInfo.append(QmlDesignerPlugin::instance()->documentManager()
+ .generatedComponentUtils().import3dTypePrefix());
qmlInfo.append(".");
qmlInfo.append(pd.assetName);
qmlInfo.append('\n');
m_requiredImports.append(
- QStringLiteral("%1.%2").arg(pd.targetDir.dirName(), pd.assetName));
+ QStringLiteral("%1.%2").arg(QmlDesignerPlugin::instance()->documentManager()
+ .generatedComponentUtils().import3dTypePrefix(),
+ pd.assetName));
while (qmlIt.hasNext()) {
qmlIt.next();
QFileInfo fi = QFileInfo(qmlIt.filePath());
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp
index dbeacc7595..3bff210520 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp
@@ -296,15 +296,16 @@ void ItemLibraryModel::setSearchText(const QString &searchText)
Import ItemLibraryModel::entryToImport(const ItemLibraryEntry &entry)
{
+#ifndef QDS_USE_PROJECTSTORAGE
if (entry.majorVersion() == -1 && entry.minorVersion() == -1)
return Import::createFileImport(entry.requiredImport());
-
+#endif
return Import::createLibraryImport(entry.requiredImport(), QString::number(entry.majorVersion()) + QLatin1Char('.') +
QString::number(entry.minorVersion()));
}
-void ItemLibraryModel::update([[maybe_unused]] ItemLibraryInfo *itemLibraryInfo, Model *model)
+void ItemLibraryModel::update(Model *model)
{
if (!model)
return;
@@ -312,9 +313,12 @@ void ItemLibraryModel::update([[maybe_unused]] ItemLibraryInfo *itemLibraryInfo,
beginResetModel();
clearSections();
+ GeneratedComponentUtils compUtils = QmlDesignerPlugin::instance()->documentManager()
+ .generatedComponentUtils();
+
QStringList excludedImports {
- QLatin1String(Constants::COMPONENT_BUNDLES_FOLDER).mid(1) + ".MaterialBundle",
- QLatin1String(Constants::COMPONENT_BUNDLES_FOLDER).mid(1) + ".EffectBundle"
+ compUtils.componentBundlesTypePrefix() + ".MaterialBundle",
+ compUtils.componentBundlesTypePrefix() + ".EffectBundle"
};
// create import sections
@@ -323,10 +327,12 @@ void ItemLibraryModel::update([[maybe_unused]] ItemLibraryInfo *itemLibraryInfo,
QHash<QString, ItemLibraryImport *> importHash;
for (const Import &import : model->imports()) {
if (import.url() != projectName) {
- if (excludedImports.contains(import.url()) || import.url().startsWith("Effects."))
+ if (excludedImports.contains(import.url())
+ || import.url().startsWith(compUtils.composedEffectsTypePrefix())) {
continue;
+ }
bool addNew = true;
- bool isQuick3DAsset = import.url().startsWith("Quick3DAssets.");
+ bool isQuick3DAsset = import.url().startsWith(compUtils.import3dTypePrefix());
QString importUrl = import.url();
if (isQuick3DAsset)
importUrl = ItemLibraryImport::quick3DAssetsTitle();
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.h
index 212ddf8e04..b04ea492d2 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.h
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.h
@@ -37,7 +37,7 @@ public:
QString searchText() const;
ItemLibraryImport *importByUrl(const QString &importName) const;
- void update(ItemLibraryInfo *itemLibraryInfo, Model *model);
+ void update(Model *model);
void updateUsedImports(const Imports &usedImports);
QMimeData *getMimeData(const ItemLibraryEntry &itemLibraryEntry);
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp
index b710a8226f..ffefc43178 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp
@@ -118,9 +118,9 @@ void ItemLibraryWidget::resizeEvent(QResizeEvent *event)
ItemLibraryWidget::ItemLibraryWidget(AsynchronousImageCache &imageCache)
: m_itemIconSize(24, 24)
- , m_itemLibraryModel(new ItemLibraryModel(this))
- , m_addModuleModel(new ItemLibraryAddImportModel(this))
- , m_itemsWidget(new StudioQuickWidget(this))
+ , m_itemLibraryModel(std::make_unique<ItemLibraryModel>())
+ , m_addModuleModel(std::make_unique<ItemLibraryAddImportModel>())
+ , m_itemsWidget(Utils::makeUniqueObjectPtr<StudioQuickWidget>())
, m_imageCache{imageCache}
{
m_compressionTimer.setInterval(1000);
@@ -146,7 +146,7 @@ ItemLibraryWidget::ItemLibraryWidget(AsynchronousImageCache &imageCache)
auto layout = new QVBoxLayout(this);
layout->setContentsMargins({});
layout->setSpacing(0);
- layout->addWidget(m_itemsWidget.data());
+ layout->addWidget(m_itemsWidget.get());
updateSearch();
@@ -167,8 +167,8 @@ ItemLibraryWidget::ItemLibraryWidget(AsynchronousImageCache &imageCache)
auto map = m_itemsWidget->registerPropertyMap("ItemLibraryBackend");
- map->setProperties({{"itemLibraryModel", QVariant::fromValue(m_itemLibraryModel.data())},
- {"addModuleModel", QVariant::fromValue(m_addModuleModel.data())},
+ map->setProperties({{"itemLibraryModel", QVariant::fromValue(m_itemLibraryModel.get())},
+ {"addModuleModel", QVariant::fromValue(m_addModuleModel.get())},
{"itemLibraryIconWidth", m_itemIconSize.width()},
{"itemLibraryIconHeight", m_itemIconSize.height()},
{"rootView", QVariant::fromValue(this)},
@@ -333,9 +333,7 @@ void ItemLibraryWidget::updateModel()
m_compressionTimer.stop();
}
-#ifndef QDS_USE_PROJECTSTORAGE
- m_itemLibraryModel->update(m_itemLibraryInfo.data(), m_model.data());
-#endif
+ m_itemLibraryModel->update(m_model.data());
if (m_itemLibraryModel->rowCount() == 0 && !m_updateRetry) {
m_updateRetry = true; // Only retry once to avoid endless loops
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h
index b56532b218..2940db7a73 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h
@@ -10,9 +10,10 @@
#include <studioquickwidget.h>
-#include <utils/fancylineedit.h>
-#include <utils/dropsupport.h>
#include <previewtooltip/previewtooltipbackend.h>
+#include <utils/dropsupport.h>
+#include <utils/fancylineedit.h>
+#include <utils/uniqueobjectptr.h>
#include <QFileIconProvider>
#include <QFrame>
@@ -104,10 +105,10 @@ private:
#ifndef QDS_USE_PROJECTSTORAGE
QPointer<ItemLibraryInfo> m_itemLibraryInfo;
#endif
- QPointer<ItemLibraryModel> m_itemLibraryModel;
- QPointer<ItemLibraryAddImportModel> m_addModuleModel;
+ std::unique_ptr<ItemLibraryModel> m_itemLibraryModel;
+ std::unique_ptr<ItemLibraryAddImportModel> m_addModuleModel;
- QScopedPointer<StudioQuickWidget> m_itemsWidget;
+ Utils::UniqueObjectPtr<StudioQuickWidget> m_itemsWidget;
std::unique_ptr<PreviewTooltipBackend> m_previewTooltipBackend;
QShortcut *m_qmlSourceUpdateShortcut;
diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.cpp
index ec95f3e5d3..918956a04c 100644
--- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.cpp
+++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.cpp
@@ -63,7 +63,7 @@ QVariant MaterialBrowserTexturesModel::data(const QModelIndex &index, int role)
return tr("Texture has no source image.");
ModelNode texNode = m_textureList.at(index.row());
- QString info = ImageUtils::imageInfo(source);
+ QString info = ImageUtils::imageInfoString(source);
if (info.isEmpty())
return tr("Texture has no data.");
diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp
index 47a1e8d293..7cf0a875bc 100644
--- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp
+++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp
@@ -56,6 +56,13 @@ public:
m_pixmaps.insert(node.internalId(), pixmap);
}
+ QPixmap getPixmap(const ModelNode &node)
+ {
+ QTC_ASSERT(node, return {});
+
+ return m_pixmaps.value(node.internalId());
+ }
+
void clearPixmapCache()
{
m_pixmaps.clear();
@@ -357,6 +364,13 @@ void MaterialBrowserWidget::focusMaterialSection(bool focusMatSec)
}
}
+void MaterialBrowserWidget::addMaterialToContentLibrary()
+{
+ ModelNode mat = m_materialBrowserModel->selectedMaterial();
+ m_materialBrowserView->emitCustomNotification("add_material_to_content_lib", {mat},
+ {m_previewImageProvider->getPixmap(mat)});
+}
+
QString MaterialBrowserWidget::qmlSourcesPath()
{
#ifdef SHARE_QML_PATH
@@ -420,4 +434,10 @@ QPointer<MaterialBrowserTexturesModel> MaterialBrowserWidget::materialBrowserTex
return m_materialBrowserTexturesModel;
}
+bool MaterialBrowserWidget::userBundleEnabled() const
+{
+ // TODO: this method is to be removed after user bundle implementation is complete
+ return Core::ICore::settings()->value("QML/Designer/UseExperimentalFeatures45", false).toBool();
+}
+
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.h b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.h
index bfe7ace34d..97c994e565 100644
--- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.h
+++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.h
@@ -60,6 +60,8 @@ public:
Q_INVOKABLE void acceptAssetsDropOnMaterial(int matIndex, const QList<QUrl> &urls);
Q_INVOKABLE void acceptTextureDropOnMaterial(int matIndex, const QString &texId);
Q_INVOKABLE void focusMaterialSection(bool focusMatSec);
+ Q_INVOKABLE void addMaterialToContentLibrary();
+ Q_INVOKABLE bool userBundleEnabled() const;
StudioQuickWidget *quickWidget() const;
diff --git a/src/plugins/qmldesigner/components/navigator/choosefrompropertylistdialog.cpp b/src/plugins/qmldesigner/components/navigator/choosefrompropertylistdialog.cpp
index 58b4c42749..a3ab5f2cd7 100644
--- a/src/plugins/qmldesigner/components/navigator/choosefrompropertylistdialog.cpp
+++ b/src/plugins/qmldesigner/components/navigator/choosefrompropertylistdialog.cpp
@@ -5,6 +5,8 @@
#include "nodemetainfo.h"
#include "ui_choosefrompropertylistdialog.h"
+#include <qmldesignerplugin.h>
+
namespace QmlDesigner {
// This will filter and return possible properties that the given type can be bound to
@@ -100,7 +102,10 @@ ChooseFromPropertyListFilter::ChooseFromPropertyListFilter(const NodeMetaInfo &i
#ifdef QDS_USE_PROJECTSTORAGE
// TODO add the types here or use the module
#else
- } else if (insertInfo.typeName().startsWith("ComponentBundles.MaterialBundle")) {
+ } else if (insertInfo.typeName().startsWith(
+ QString("%1.MaterialBundle").arg(QmlDesignerPlugin::instance()->documentManager()
+ .generatedComponentUtils().componentBundlesTypePrefix())
+ .toUtf8())) {
if (parentInfo.isQtQuick3DModel())
propertyList.append("materials");
#endif
diff --git a/src/plugins/qmldesigner/components/navigator/nameitemdelegate.cpp b/src/plugins/qmldesigner/components/navigator/nameitemdelegate.cpp
index aacaf6dc0d..223e04fd96 100644
--- a/src/plugins/qmldesigner/components/navigator/nameitemdelegate.cpp
+++ b/src/plugins/qmldesigner/components/navigator/nameitemdelegate.cpp
@@ -9,9 +9,8 @@
#include "navigatortreeview.h"
#include "navigatorwidget.h"
#include "choosefrompropertylistdialog.h"
-#include "qproxystyle.h"
-
#include <model/modelutils.h>
+#include <dialogutils.h>
#include <modelnodecontextmenu.h>
#include <theme.h>
#include <qmldesignerconstants.h>
@@ -169,8 +168,7 @@ static void setId(const QModelIndex &index, const QString &newId)
return;
if (!ModelNode::isValidId(newId)) {
- Core::AsynchronousMessageBox::warning(NavigatorTreeView::tr("Invalid Id"),
- NavigatorTreeView::tr("%1 is an invalid id.").arg(newId));
+ DialogUtils::showWarningForInvalidId(newId);
} else if (modelNode.view()->hasId(newId)) {
Core::AsynchronousMessageBox::warning(NavigatorTreeView::tr("Invalid Id"),
NavigatorTreeView::tr("%1 already exists.").arg(newId));
diff --git a/src/plugins/qmldesigner/components/propertyeditor/dynamicpropertiesproxymodel.cpp b/src/plugins/qmldesigner/components/propertyeditor/dynamicpropertiesproxymodel.cpp
index 45f89ae339..fdd58c77a3 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/dynamicpropertiesproxymodel.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/dynamicpropertiesproxymodel.cpp
@@ -143,7 +143,7 @@ QString DynamicPropertiesProxyModel::newPropertyName() const
{
DynamicPropertiesModel *propsModel = dynamicPropertiesModel();
- return QString::fromUtf8(uniquePropertyName("property", propsModel->singleSelectedNode()));
+ return QString::fromUtf8(uniquePropertyName("newName", propsModel->singleSelectedNode()));
}
void DynamicPropertiesProxyModel::createProperty(const QString &name, const QString &type)
@@ -167,6 +167,10 @@ void DynamicPropertiesProxyModel::createProperty(const QString &name, const QStr
QVariant value = defaultValueForType(typeName);
VariantProperty variantProp = modelNode.variantProperty(name.toUtf8());
variantProp.setDynamicTypeNameAndValue(typeName, value);
+ } else if (type == "signal") {
+ SignalDeclarationProperty signalDeclarationProperty
+ = modelNode.signalDeclarationProperty(name.toUtf8());
+ signalDeclarationProperty.setSignature("()");
} else {
QString expression = defaultExpressionForType(typeName);
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp
index 7f1ab00bb9..6f3242a18e 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp
@@ -284,6 +284,27 @@ void PropertyEditorQmlBackend::setupAuxiliaryProperties(const QmlObjectNode &qml
}
}
+void PropertyEditorQmlBackend::handleInstancePropertyChangedInModelNodeProxy(
+ const ModelNode &modelNode, const PropertyName &propertyName)
+{
+ m_backendModelNode.handleInstancePropertyChanged(modelNode, propertyName);
+}
+
+void PropertyEditorQmlBackend::handleVariantPropertyChangedInModelNodeProxy(const VariantProperty &property)
+{
+ m_backendModelNode.handleVariantPropertyChanged(property);
+}
+
+void PropertyEditorQmlBackend::handleBindingPropertyChangedInModelNodeProxy(const BindingProperty &property)
+{
+ m_backendModelNode.handleBindingPropertyChanged(property);
+}
+
+void PropertyEditorQmlBackend::handlePropertiesRemovedInModelNodeProxy(const AbstractProperty &property)
+{
+ m_backendModelNode.handlePropertiesRemoved(property);
+}
+
void PropertyEditorQmlBackend::createPropertyEditorValue(const QmlObjectNode &qmlObjectNode,
const PropertyName &name,
const QVariant &value,
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.h b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.h
index b677258488..d4e158fca4 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.h
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.h
@@ -3,10 +3,10 @@
#pragma once
-#include "qmlanchorbindingproxy.h"
#include "designerpropertymap.h"
-#include "propertyeditorvalue.h"
#include "propertyeditorcontextobject.h"
+#include "propertyeditorvalue.h"
+#include "qmlanchorbindingproxy.h"
#include "qmlmodelnodeproxy.h"
#include "quick2propertyeditorview.h"
@@ -71,7 +71,15 @@ public:
PropertyEditorView *propertyEditor);
void setupInsightAttachedProperties(const QmlObjectNode &qmlObjectNode,
PropertyEditorView *propertyEditor);
- void setupAuxiliaryProperties(const QmlObjectNode &qmlObjectNode, PropertyEditorView *propertyEditor);
+ void setupAuxiliaryProperties(const QmlObjectNode &qmlObjectNode,
+ PropertyEditorView *propertyEditor);
+
+ void handleInstancePropertyChangedInModelNodeProxy(const ModelNode &modelNode,
+ const PropertyName &propertyName);
+
+ void handleVariantPropertyChangedInModelNodeProxy(const VariantProperty &property);
+ void handleBindingPropertyChangedInModelNodeProxy(const BindingProperty &property);
+ void handlePropertiesRemovedInModelNodeProxy(const AbstractProperty &property);
static NodeMetaInfo findCommonAncestor(const ModelNode &node);
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp
index 663ebafb65..70686f31ae 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp
@@ -10,9 +10,12 @@
#include "designmodewidget.h"
#include "nodemetainfo.h"
#include "nodeproperty.h"
+#include "propertyeditorview.h"
+#include "qmldesignerplugin.h"
#include "qmlitemnode.h"
#include "qmlobjectnode.h"
-#include "qmldesignerplugin.h"
+#include "rewritertransaction.h"
+#include "rewritingexception.h"
#include <enumeration.h>
@@ -153,7 +156,8 @@ void PropertyEditorValue::setExpressionWithEmit(const QString &expression)
if (m_expression != expression) {
setExpression(expression);
m_value.clear();
- emit expressionChanged(nameAsQString()); // Note that we set the name in this case
+ emit expressionChanged(nameAsQString());
+ emit expressionChangedQml();// Note that we set the name in this case
}
}
@@ -180,7 +184,7 @@ bool PropertyEditorValue::isInSubState() const
bool PropertyEditorValue::isBound() const
{
const QmlObjectNode objectNode(modelNode());
- return objectNode.isValid() && objectNode.hasBindingProperty(name());
+ return m_forceBound || (objectNode.isValid() && objectNode.hasBindingProperty(name()));
}
bool PropertyEditorValue::isInModel() const
@@ -334,6 +338,7 @@ void PropertyEditorValue::resetValue()
m_expression = QString();
emit valueChanged(nameAsQString(), QVariant());
emit expressionChanged({});
+ emit expressionChangedQml();
}
}
@@ -425,6 +430,34 @@ QStringList PropertyEditorValue::getExpressionAsList() const
return generateStringList(expression());
}
+QVector<double> PropertyEditorValue::getExpressionAsVector() const
+{
+ const QRegularExpression rx(
+ QRegularExpression::anchoredPattern("Qt.vector(2|3|4)d\\((.*?)\\)"));
+ const QRegularExpressionMatch match = rx.match(expression());
+ if (!match.hasMatch())
+ return {};
+
+ const QStringList floats = match.captured(2).split(',', Qt::SkipEmptyParts);
+
+ bool ok;
+
+ const int num = match.captured(1).toInt();
+
+ if (num != floats.count())
+ return {};
+
+ QVector<double> ret;
+ for (const QString &number : floats) {
+ ret.append(number.toDouble(&ok));
+
+ if (!ok)
+ return {};
+ }
+
+ return ret;
+}
+
bool PropertyEditorValue::idListAdd(const QString &value)
{
const QmlObjectNode objectNode(modelNode());
@@ -507,6 +540,15 @@ void PropertyEditorValue::openMaterialEditor(int idx)
m_modelNode.view()->emitCustomNotification("select_material", {}, {idx});
}
+void PropertyEditorValue::setForceBound(bool b)
+{
+ if (m_forceBound == b)
+ return;
+ m_forceBound = b;
+
+ emit isBoundChanged();
+}
+
QStringList PropertyEditorValue::generateStringList(const QString &string) const
{
QString copy = string;
@@ -687,4 +729,260 @@ void PropertyEditorNodeWrapper::update()
emit typeChanged();
}
+QQmlPropertyMap *PropertyEditorSubSelectionWrapper::properties()
+{
+ return &m_valuesPropertyMap;
+}
+
+static QObject *variantToQObject(const QVariant &value)
+{
+ if (value.typeId() == QMetaType::QObjectStar || value.typeId() > QMetaType::User)
+ return *(QObject **)value.constData();
+
+ return nullptr;
+}
+
+void PropertyEditorSubSelectionWrapper::createPropertyEditorValue(const QmlObjectNode &qmlObjectNode,
+ const PropertyName &name,
+ const QVariant &value)
+{
+ PropertyName propertyName(name);
+ propertyName.replace('.', '_');
+ auto valueObject = qobject_cast<PropertyEditorValue*>(variantToQObject(m_valuesPropertyMap.value(QString::fromUtf8(propertyName))));
+ if (!valueObject) {
+ valueObject = new PropertyEditorValue(&m_valuesPropertyMap);
+ QObject::connect(valueObject, &PropertyEditorValue::valueChanged, this, &PropertyEditorSubSelectionWrapper::changeValue);
+ QObject::connect(valueObject, &PropertyEditorValue::expressionChanged, this, &PropertyEditorSubSelectionWrapper::changeExpression);
+ QObject::connect(valueObject, &PropertyEditorValue::exportPropertyAsAliasRequested, this, &PropertyEditorSubSelectionWrapper::exportPropertyAsAlias);
+ QObject::connect(valueObject, &PropertyEditorValue::removeAliasExportRequested, this, &PropertyEditorSubSelectionWrapper::removeAliasExport);
+ m_valuesPropertyMap.insert(QString::fromUtf8(propertyName), QVariant::fromValue(valueObject));
+ }
+ valueObject->setName(name);
+ valueObject->setModelNode(qmlObjectNode);
+
+ if (qmlObjectNode.propertyAffectedByCurrentState(name) && !(qmlObjectNode.modelNode().property(name).isBindingProperty()))
+ valueObject->setValue(qmlObjectNode.modelValue(name));
+
+ else
+ valueObject->setValue(value);
+
+ if (propertyName != "id" &&
+ qmlObjectNode.currentState().isBaseState() &&
+ qmlObjectNode.modelNode().property(propertyName).isBindingProperty()) {
+ valueObject->setExpression(qmlObjectNode.modelNode().bindingProperty(propertyName).expression());
+ } else {
+ if (qmlObjectNode.hasBindingProperty(name))
+ valueObject->setExpression(qmlObjectNode.expression(name));
+ else
+ valueObject->setExpression(qmlObjectNode.instanceValue(name).toString());
+ }
+}
+
+void PropertyEditorSubSelectionWrapper::exportPropertyAsAlias(const QString &name)
+{
+ if (name.isNull())
+ return;
+
+ if (locked())
+ return;
+
+ QTC_ASSERT(m_modelNode.isValid(), return);
+
+ view()->executeInTransaction("PropertyEditorView::exportPropertyAsAlias", [this, name](){
+ PropertyEditorView::generateAliasForProperty(m_modelNode, name);
+ });
+}
+
+void PropertyEditorSubSelectionWrapper::removeAliasExport(const QString &name)
+{
+ if (name.isNull())
+ return;
+
+ if (locked())
+ return;
+
+ QTC_ASSERT(m_modelNode.isValid(), return );
+
+ view()->executeInTransaction("PropertyEditorView::exportPropertyAsAlias", [this, name]() {
+ PropertyEditorView::removeAliasForProperty(m_modelNode, name);
+ });
+}
+
+bool PropertyEditorSubSelectionWrapper::locked() const
+{
+ return m_locked;
+}
+
+PropertyEditorSubSelectionWrapper::PropertyEditorSubSelectionWrapper(const ModelNode &modelNode)
+ : m_modelNode(modelNode)
+{
+ QmlObjectNode qmlObjectNode(modelNode);
+
+ QTC_ASSERT(qmlObjectNode.isValid(), return );
+
+ for (const auto &property : qmlObjectNode.modelNode().metaInfo().properties()) {
+ auto propertyName = property.name();
+ createPropertyEditorValue(qmlObjectNode,
+ propertyName,
+ qmlObjectNode.instanceValue(propertyName));
+ }
+}
+
+ModelNode PropertyEditorSubSelectionWrapper::modelNode() const
+{
+ return m_modelNode;
+}
+
+void PropertyEditorSubSelectionWrapper::deleteModelNode()
+{
+ QmlObjectNode objectNode(m_modelNode);
+
+ view()->executeInTransaction("PropertyEditorView::changeExpression", [&] {
+ if (objectNode.isValid())
+ objectNode.destroy();
+ });
+}
+
+void PropertyEditorSubSelectionWrapper::changeValue(const QString &name)
+{
+ QTC_ASSERT(m_modelNode.isValid(), return );
+
+ if (name.isNull())
+ return;
+
+ if (locked())
+ return;
+
+ const QScopeGuard cleanup([&] { m_locked = false; });
+ m_locked = true;
+
+ const NodeMetaInfo metaInfo = m_modelNode.metaInfo();
+ QVariant castedValue;
+ PropertyEditorValue *value = qobject_cast<PropertyEditorValue *>(
+ variantToQObject(m_valuesPropertyMap.value(name)));
+
+ if (auto property = metaInfo.property(name.toUtf8())) {
+ castedValue = property.castedValue(value->value());
+
+ if (castedValue.typeId() == QVariant::Color) {
+ QColor color = castedValue.value<QColor>();
+ QColor newColor = QColor(color.name());
+ newColor.setAlpha(color.alpha());
+ castedValue = QVariant(newColor);
+ }
+
+ if (!value->value().isValid()) { // reset
+ removePropertyFromModel(name.toUtf8());
+ } else {
+ if (castedValue.isValid())
+ commitVariantValueToModel(name.toUtf8(), castedValue);
+ }
+ }
+}
+
+void PropertyEditorSubSelectionWrapper::setValueFromModel(const PropertyName &name,
+ const QVariant &value)
+{
+ m_locked = true;
+
+ QmlObjectNode qmlObjectNode(m_modelNode);
+
+ PropertyName propertyName = name;
+ propertyName.replace('.', '_');
+ auto propertyValue = qobject_cast<PropertyEditorValue *>(
+ variantToQObject(m_valuesPropertyMap.value(QString::fromUtf8(propertyName))));
+ if (propertyValue)
+ propertyValue->setValue(value);
+ m_locked = false;
+}
+
+void PropertyEditorSubSelectionWrapper::resetValue(const PropertyName &name)
+{
+ auto propertyValue = qobject_cast<PropertyEditorValue *>(
+ variantToQObject(m_valuesPropertyMap.value(QString::fromUtf8(name))));
+ if (propertyValue)
+ propertyValue->resetValue();
+}
+
+bool PropertyEditorSubSelectionWrapper::isRelevantModelNode(const ModelNode &modelNode) const
+{
+ QmlObjectNode objectNode(m_modelNode);
+ return modelNode == m_modelNode || objectNode.propertyChangeForCurrentState() == modelNode;
+}
+
+void PropertyEditorSubSelectionWrapper::changeExpression(const QString &propertyName)
+{
+ PropertyName name = propertyName.toUtf8();
+
+ QTC_ASSERT(m_modelNode.isValid(), return );
+
+ if (name.isNull())
+ return;
+
+ if (locked())
+ return;
+
+ const QScopeGuard cleanup([&] { m_locked = false; });
+ m_locked = true;
+
+ view()->executeInTransaction("PropertyEditorView::changeExpression", [this, name, propertyName] {
+ QmlObjectNode qmlObjectNode{m_modelNode};
+ PropertyEditorValue *value = qobject_cast<PropertyEditorValue *>(
+ variantToQObject(m_valuesPropertyMap.value(propertyName)));
+
+ if (!value) {
+ qWarning() << "PropertyEditor::changeExpression no value for " << propertyName;
+ return;
+ }
+
+ if (value->expression().isEmpty()) {
+ value->resetValue();
+ return;
+ }
+ PropertyEditorView::setExpressionOnObjectNode(qmlObjectNode, name, value->expression());
+ }); /* end of transaction */
+}
+
+void PropertyEditorSubSelectionWrapper::removePropertyFromModel(const PropertyName &propertyName)
+{
+ QTC_ASSERT(m_modelNode.isValid(), return );
+
+ m_locked = true;
+ try {
+ RewriterTransaction transaction = view()->beginRewriterTransaction(
+ "PropertyEditorView::removePropertyFromModel");
+
+ QmlObjectNode(m_modelNode).removeProperty(propertyName);
+
+ transaction.commit();
+ } catch (const RewritingException &e) {
+ e.showException();
+ }
+ m_locked = false;
+}
+
+void PropertyEditorSubSelectionWrapper::commitVariantValueToModel(const PropertyName &propertyName,
+ const QVariant &value)
+{
+ QTC_ASSERT(m_modelNode.isValid(), return );
+
+ try {
+ RewriterTransaction transaction = view()->beginRewriterTransaction(
+ "PropertyEditorView::commitVariantValueToMode");
+
+ QmlObjectNode(m_modelNode).setVariantProperty(propertyName, value);
+
+ transaction.commit();
+ } catch (const RewritingException &e) {
+ e.showException();
+ }
+}
+
+AbstractView *PropertyEditorSubSelectionWrapper::view() const
+{
+ QTC_CHECK(m_modelNode.isValid());
+
+ return m_modelNode.view();
+}
+
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.h b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.h
index 59236c4fe2..70a51fffc2 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.h
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.h
@@ -14,6 +14,43 @@ namespace QmlDesigner {
class PropertyEditorValue;
+class PropertyEditorSubSelectionWrapper : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QQmlPropertyMap *properties READ properties NOTIFY propertiesChanged)
+
+signals:
+ void propertiesChanged();
+
+public:
+ QQmlPropertyMap *properties();
+ PropertyEditorSubSelectionWrapper(const ModelNode &modelNode);
+ ModelNode modelNode() const;
+
+ Q_INVOKABLE void deleteModelNode();
+
+ void setValueFromModel(const PropertyName &name, const QVariant &value);
+ void resetValue(const PropertyName &name);
+
+ bool isRelevantModelNode(const ModelNode &modelNode) const;
+
+private:
+ void changeValue(const QString &name);
+ void changeExpression(const QString &propertyName);
+ void createPropertyEditorValue(const QmlObjectNode &qmlObjectNode, const PropertyName &name, const QVariant &value);
+ void exportPropertyAsAlias(const QString &name);
+ void removeAliasExport(const QString &name);
+ bool locked() const;
+
+ ModelNode m_modelNode;
+ QQmlPropertyMap m_valuesPropertyMap;
+ bool m_locked = false;
+ void removePropertyFromModel(const PropertyName &propertyName);
+ void commitVariantValueToModel(const PropertyName &propertyName, const QVariant &value);
+ AbstractView *view() const;
+};
+
class PropertyEditorNodeWrapper : public QObject
{
Q_OBJECT
@@ -126,12 +163,15 @@ public:
bool isIdList() const;
Q_INVOKABLE QStringList getExpressionAsList() const;
+ Q_INVOKABLE QVector<double> getExpressionAsVector() const;
Q_INVOKABLE bool idListAdd(const QString &value);
Q_INVOKABLE bool idListRemove(int idx);
Q_INVOKABLE bool idListReplace(int idx, const QString &value);
Q_INVOKABLE void commitDrop(const QString &dropData);
Q_INVOKABLE void openMaterialEditor(int idx);
+ Q_INVOKABLE void setForceBound(bool b);
+
public slots:
void resetValue();
void setEnumeration(const QString &scope, const QString &name);
@@ -143,6 +183,8 @@ signals:
void expressionChanged(const QString &name); // HACK - We use the same notifer for the backend and frontend.
// If name is empty the signal is used for QML.
+ void expressionChangedQml();
+
void exportPropertyAsAliasRequested(const QString &name);
void removeAliasExportRequested(const QString &name);
@@ -168,6 +210,7 @@ private:
bool m_hasActiveDrag = false;
bool m_isValid = false; // if the property value belongs to a non-existing complexProperty it is invalid
PropertyEditorNodeWrapper *m_complexNode;
+ bool m_forceBound = false;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp
index 1ff098f4ea..b22b39e238 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.cpp
@@ -256,66 +256,19 @@ void PropertyEditorView::changeExpression(const QString &propertyName)
underscoreName.replace('.', '_');
QmlObjectNode qmlObjectNode{m_selectedNode};
- PropertyEditorValue *value = m_qmlBackEndForCurrentType->propertyValueForName(QString::fromLatin1(underscoreName));
+ PropertyEditorValue *value = m_qmlBackEndForCurrentType->propertyValueForName(
+ QString::fromUtf8(underscoreName));
if (!value) {
qWarning() << "PropertyEditor::changeExpression no value for " << underscoreName;
return;
}
- if (auto property = qmlObjectNode.modelNode().metaInfo().property(name)) {
- const auto &propertType = property.propertyType();
- if (propertType.isColor()) {
- if (QColor(value->expression().remove('"')).isValid()) {
- qmlObjectNode.setVariantProperty(name, QColor(value->expression().remove('"')));
- return;
- }
- } else if (propertType.isBool()) {
- if (isTrueFalseLiteral(value->expression())) {
- if (value->expression().compare("true", Qt::CaseInsensitive) == 0)
- qmlObjectNode.setVariantProperty(name, true);
- else
- qmlObjectNode.setVariantProperty(name, false);
- return;
- }
- } else if (propertType.isInteger()) {
- bool ok;
- int intValue = value->expression().toInt(&ok);
- if (ok) {
- qmlObjectNode.setVariantProperty(name, intValue);
- return;
- }
- } else if (propertType.isFloat()) {
- bool ok;
- qreal realValue = value->expression().toDouble(&ok);
- if (ok) {
- qmlObjectNode.setVariantProperty(name, realValue);
- return;
- }
- } else if (propertType.isVariant()) {
- bool ok;
- qreal realValue = value->expression().toDouble(&ok);
- if (ok) {
- qmlObjectNode.setVariantProperty(name, realValue);
- return;
- } else if (isTrueFalseLiteral(value->expression())) {
- if (value->expression().compare("true", Qt::CaseInsensitive) == 0)
- qmlObjectNode.setVariantProperty(name, true);
- else
- qmlObjectNode.setVariantProperty(name, false);
- return;
- }
- }
- }
-
if (value->expression().isEmpty()) {
value->resetValue();
return;
}
-
- if (qmlObjectNode.expression(name) != value->expression()
- || !qmlObjectNode.propertyAffectedByCurrentState(name))
- qmlObjectNode.setBindingProperty(name, value->expression());
+ setExpressionOnObjectNode(qmlObjectNode, name, value->expression());
}); /* end of transaction */
}
@@ -330,21 +283,8 @@ void PropertyEditorView::exportPropertyAsAlias(const QString &name)
if (noValidSelection())
return;
- executeInTransaction("PropertyEditorView::exportPropertyAsAlias", [this, name](){
- const QString id = m_selectedNode.validId();
- QString upperCasePropertyName = name;
- upperCasePropertyName.replace(0, 1, upperCasePropertyName.at(0).toUpper());
- QString aliasName = id + upperCasePropertyName;
- aliasName.replace(".", ""); //remove all dots
-
- PropertyName propertyName = aliasName.toUtf8();
- if (rootModelNode().hasProperty(propertyName)) {
- Core::AsynchronousMessageBox::warning(tr("Cannot Export Property as Alias"),
- tr("Property %1 does already exist for root component.").arg(aliasName));
- return;
- }
- rootModelNode().bindingProperty(propertyName).setDynamicTypeNameAndExpression("alias", id + "." + name);
- });
+ executeInTransaction("PropertyEditorView::exportPropertyAsAlias",
+ [this, name]() { generateAliasForProperty(m_selectedNode, name); });
}
void PropertyEditorView::removeAliasExport(const QString &name)
@@ -358,15 +298,8 @@ void PropertyEditorView::removeAliasExport(const QString &name)
if (noValidSelection())
return;
- executeInTransaction("PropertyEditorView::exportPropertyAsAlias", [this, name](){
- const QString id = m_selectedNode.validId();
-
- for (const BindingProperty &property : rootModelNode().bindingProperties())
- if (property.expression() == (id + "." + name)) {
- rootModelNode().removeProperty(property.name());
- break;
- }
- });
+ executeInTransaction("PropertyEditorView::exportPropertyAsAlias",
+ [this, name]() { removeAliasForProperty(m_selectedNode, name); });
}
bool PropertyEditorView::locked() const
@@ -384,11 +317,113 @@ void PropertyEditorView::refreshMetaInfos(const TypeIds &deletedTypeIds)
m_propertyComponentGenerator.refreshMetaInfos(deletedTypeIds);
}
+void PropertyEditorView::setExpressionOnObjectNode(const QmlObjectNode &constObjectNode,
+ const PropertyName &name,
+ const QString &newExpression)
+{
+ auto qmlObjectNode = constObjectNode;
+ auto expression = newExpression;
+ if (auto property = qmlObjectNode.modelNode().metaInfo().property(name)) {
+ const auto &propertType = property.propertyType();
+ if (propertType.isColor()) {
+ if (QColor(expression.remove('"')).isValid()) {
+ qmlObjectNode.setVariantProperty(name, QColor(expression.remove('"')));
+ return;
+ }
+ } else if (propertType.isBool()) {
+ if (isTrueFalseLiteral(expression)) {
+ if (expression.compare("true", Qt::CaseInsensitive) == 0)
+ qmlObjectNode.setVariantProperty(name, true);
+ else
+ qmlObjectNode.setVariantProperty(name, false);
+ return;
+ }
+ } else if (propertType.isInteger()) {
+ bool ok;
+ int intValue = expression.toInt(&ok);
+ if (ok) {
+ qmlObjectNode.setVariantProperty(name, intValue);
+ return;
+ }
+ } else if (propertType.isFloat()) {
+ bool ok;
+ qreal realValue = expression.toDouble(&ok);
+ if (ok) {
+ qmlObjectNode.setVariantProperty(name, realValue);
+ return;
+ }
+ } else if (propertType.isVariant()) {
+ bool ok;
+ qreal realValue = expression.toDouble(&ok);
+ if (ok) {
+ qmlObjectNode.setVariantProperty(name, realValue);
+ return;
+ } else if (isTrueFalseLiteral(expression)) {
+ if (expression.compare("true", Qt::CaseInsensitive) == 0)
+ qmlObjectNode.setVariantProperty(name, true);
+ else
+ qmlObjectNode.setVariantProperty(name, false);
+ return;
+ }
+ }
+ }
+
+ if (qmlObjectNode.expression(name) != expression
+ || !qmlObjectNode.propertyAffectedByCurrentState(name))
+ qmlObjectNode.setBindingProperty(name, expression);
+}
+
+void PropertyEditorView::generateAliasForProperty(const ModelNode &modelNode, const QString &name)
+{
+ QTC_ASSERT(modelNode.isValid(), return );
+
+ auto view = modelNode.view();
+
+ auto rootNode = view->rootModelNode();
+
+ auto nonConstModelNode = modelNode;
+ const QString id = nonConstModelNode.validId();
+
+ QString upperCasePropertyName = name;
+ upperCasePropertyName.replace(0, 1, upperCasePropertyName.at(0).toUpper());
+ QString aliasName = id + upperCasePropertyName;
+ aliasName.replace(".", ""); //remove all dots
+
+ PropertyName propertyName = aliasName.toUtf8();
+ if (rootNode.hasProperty(propertyName)) {
+ Core::AsynchronousMessageBox::warning(
+ tr("Cannot Export Property as Alias"),
+ tr("Property %1 does already exist for root component.").arg(aliasName));
+ return;
+ }
+ rootNode.bindingProperty(propertyName).setDynamicTypeNameAndExpression("alias", id + "." + name);
+}
+
+void PropertyEditorView::removeAliasForProperty(const ModelNode &modelNode, const QString &propertyName)
+{
+ QTC_ASSERT(modelNode.isValid(), return );
+
+ auto view = modelNode.view();
+
+ auto rootNode = view->rootModelNode();
+
+ auto nonConstModelNode = modelNode;
+
+ const QString id = nonConstModelNode.validId();
+
+ for (const BindingProperty &property : rootNode.bindingProperties()) {
+ if (property.expression() == (id + "." + propertyName)) {
+ rootNode.removeProperty(property.name());
+ break;
+ }
+ }
+}
+
void PropertyEditorView::updateSize()
{
if (!m_qmlBackEndForCurrentType)
return;
- auto frame = m_qmlBackEndForCurrentType->widget()->findChild<QWidget*>("propertyEditorFrame");
+ auto frame = m_qmlBackEndForCurrentType->widget()->findChild<QWidget *>("propertyEditorFrame");
if (frame)
frame->resize(m_stackedWidget->size());
}
@@ -747,7 +782,11 @@ void PropertyEditorView::propertiesRemoved(const QList<AbstractProperty> &proper
if (noValidSelection())
return;
+ QTC_ASSERT(m_qmlBackEndForCurrentType, return );
+
for (const AbstractProperty &property : propertyList) {
+ m_qmlBackEndForCurrentType->handlePropertiesRemovedInModelNodeProxy(property);
+
ModelNode node(property.parentModelNode());
if (node.isRootNode() && !m_selectedNode.isRootNode())
@@ -805,7 +844,11 @@ void PropertyEditorView::variantPropertiesChanged(const QList<VariantProperty>&
if (noValidSelection())
return;
+ QTC_ASSERT(m_qmlBackEndForCurrentType, return );
+
for (const VariantProperty &property : propertyList) {
+ m_qmlBackEndForCurrentType->handleVariantPropertyChangedInModelNodeProxy(property);
+
ModelNode node(property.parentModelNode());
if (propertyIsAttachedLayoutProperty(property.name()))
@@ -830,7 +873,11 @@ void PropertyEditorView::bindingPropertiesChanged(const QList<BindingProperty> &
if (locked() || noValidSelection())
return;
+ QTC_ASSERT(m_qmlBackEndForCurrentType, return );
+
for (const BindingProperty &property : propertyList) {
+ m_qmlBackEndForCurrentType->handleBindingPropertyChangedInModelNodeProxy(property);
+
ModelNode node(property.parentModelNode());
if (property.isAliasExport())
@@ -952,6 +999,9 @@ void PropertyEditorView::instancePropertyChanged(const QList<QPair<ModelNode, Pr
{
if (!m_selectedNode.isValid())
return;
+
+ QTC_ASSERT(m_qmlBackEndForCurrentType, return );
+
m_locked = true;
using ModelNodePropertyPair = QPair<ModelNode, PropertyName>;
@@ -960,7 +1010,11 @@ void PropertyEditorView::instancePropertyChanged(const QList<QPair<ModelNode, Pr
const QmlObjectNode qmlObjectNode(modelNode);
const PropertyName propertyName = propertyPair.second;
- if (qmlObjectNode.isValid() && m_qmlBackEndForCurrentType && modelNode == m_selectedNode && qmlObjectNode.currentState().isValid()) {
+ m_qmlBackEndForCurrentType->handleInstancePropertyChangedInModelNodeProxy(modelNode,
+ propertyName);
+
+ if (qmlObjectNode.isValid() && m_qmlBackEndForCurrentType && modelNode == m_selectedNode
+ && qmlObjectNode.currentState().isValid()) {
const AbstractProperty property = modelNode.property(propertyName);
if (modelNode == m_selectedNode || qmlObjectNode.propertyChangeForCurrentState() == qmlObjectNode) {
if ( !modelNode.hasProperty(propertyName) || modelNode.property(property.name()).isBindingProperty() )
@@ -969,7 +1023,6 @@ void PropertyEditorView::instancePropertyChanged(const QList<QPair<ModelNode, Pr
setValue(modelNode, property.name(), qmlObjectNode.modelValue(property.name()));
}
}
-
}
m_locked = false;
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.h b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.h
index cc9b522839..ef2b71f558 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.h
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorview.h
@@ -84,6 +84,16 @@ public:
void refreshMetaInfos(const TypeIds &deletedTypeIds) override;
+ static void setExpressionOnObjectNode(const QmlObjectNode &objectNode,
+ const PropertyName &name,
+ const QString &expression);
+
+ static void generateAliasForProperty(const ModelNode &modelNode,
+ const QString &propertyName);
+
+ static void removeAliasForProperty(const ModelNode &modelNode,
+ const QString &propertyName);
+
protected:
void timerEvent(QTimerEvent *event) override;
void setupPane(const TypeName &typeName);
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.cpp b/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.cpp
index 96ec5f92e7..fc39b37137 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.cpp
@@ -4,6 +4,15 @@
#include "abstractview.h"
#include "qmlmodelnodeproxy.h"
+#include <nodemetainfo.h>
+
+#include <nodeabstractproperty.h>
+#include <nodelistproperty.h>
+#include <variantproperty.h>
+
+#include <utils/qtcassert.h>
+#include <utils/algorithm.h>
+
#include <QtQml>
namespace QmlDesigner {
@@ -17,6 +26,8 @@ void QmlModelNodeProxy::setup(const QmlObjectNode &objectNode)
{
m_qmlObjectNode = objectNode;
+ m_subselection.clear();
+
emit modelNodeChanged();
}
@@ -75,4 +86,227 @@ QString QmlModelNodeProxy::simplifiedTypeName() const
return m_qmlObjectNode.simplifiedTypeName();
}
+static QList<int> toInternalIdList(const QList<ModelNode> &nodes)
+{
+ return Utils::transform(nodes, [](const ModelNode &node) { return node.internalId(); });
+}
+
+QList<int> QmlModelNodeProxy::allChildren(int internalId) const
+{
+ ModelNode modelNode = m_qmlObjectNode.modelNode();
+
+ QTC_ASSERT(modelNode.isValid(), return {});
+
+ if (internalId >= 0)
+ modelNode = modelNode.view()->modelNodeForInternalId(internalId);
+
+ return allChildren(modelNode);
+}
+
+QList<int> QmlModelNodeProxy::allChildrenOfType(const QString &typeName, int internalId) const
+{
+ ModelNode modelNode = m_qmlObjectNode.modelNode();
+
+ QTC_ASSERT(modelNode.isValid(), return {});
+
+ if (internalId >= 0)
+ modelNode = modelNode.view()->modelNodeForInternalId(internalId);
+
+ return allChildrenOfType(modelNode, typeName);
+}
+
+QString QmlModelNodeProxy::simplifiedTypeName(int internalId) const
+{
+ ModelNode modelNode = m_qmlObjectNode.modelNode();
+
+ QTC_ASSERT(modelNode.isValid(), return {});
+
+ return modelNode.view()->modelNodeForInternalId(internalId).simplifiedTypeName();
+}
+
+PropertyEditorSubSelectionWrapper *QmlModelNodeProxy::findWrapper(int internalId) const
+{
+ for (const auto &item : qAsConst(m_subselection)) {
+ if (item->modelNode().internalId() == internalId)
+ return item.data();
+ }
+
+ return nullptr;
+}
+
+PropertyEditorSubSelectionWrapper *QmlModelNodeProxy::registerSubSelectionWrapper(int internalId)
+{
+ auto result = findWrapper(internalId);
+
+ if (result)
+ return result;
+
+ QTC_ASSERT(m_qmlObjectNode.isValid(), return nullptr);
+
+ ModelNode node = m_qmlObjectNode.view()->modelNodeForInternalId(internalId);
+
+ QTC_ASSERT(node.isValid(), return nullptr);
+
+ QSharedPointer<PropertyEditorSubSelectionWrapper> wrapper(
+ new PropertyEditorSubSelectionWrapper(node));
+ m_subselection.append(wrapper);
+
+ QJSEngine::setObjectOwnership(wrapper.data(), QJSEngine::CppOwnership);
+
+ return wrapper.data();
+}
+
+void QmlModelNodeProxy::createModelNode(int internalIdParent,
+ const QString &property,
+ const QString &typeName,
+ const QString &requiredImport)
+{
+ QTC_ASSERT(m_qmlObjectNode.isValid(), return );
+
+ auto modelNode = m_qmlObjectNode.modelNode();
+
+ AbstractView *view = modelNode.view();
+
+ auto parentModelNode = m_qmlObjectNode.modelNode();
+ if (internalIdParent >= 0)
+ parentModelNode = view->modelNodeForInternalId(internalIdParent);
+
+ QTC_ASSERT(parentModelNode.isValid(), return );
+
+ Import import;
+ Q_ASSERT(import.isEmpty());
+
+ if (!requiredImport.isEmpty() && !view->model()->hasImport(requiredImport))
+ import = Import::createLibraryImport(requiredImport);
+
+ view->executeInTransaction("QmlModelNodeProxy::createModelNode", [&] {
+ if (!import.isEmpty())
+ view->model()->changeImports({import}, {});
+
+#ifdef QDS_USE_PROJECTSTORAGE
+ ModelNode newNode = view->createModelNode(typeName.toUtf8());
+#else
+ NodeMetaInfo metaInfo = modelNode.model()->metaInfo(typeName.toUtf8());
+ ModelNode newNode = view->createModelNode(metaInfo.typeName(),
+ metaInfo.majorVersion(),
+ metaInfo.minorVersion());
+#endif
+ parentModelNode.nodeAbstractProperty(property.toUtf8()).reparentHere(newNode);
+ });
+}
+
+void QmlModelNodeProxy::moveNode(int internalIdParent,
+ const QString &propertyName,
+ int fromIndex,
+ int toIndex)
+{
+ QTC_ASSERT(m_qmlObjectNode.isValid(), return );
+
+ ModelNode node = m_qmlObjectNode.view()->modelNodeForInternalId(internalIdParent);
+
+ QTC_ASSERT(node.isValid(), return );
+ AbstractView *view = m_qmlObjectNode.view();
+ view->executeInTransaction("QmlModelNodeProxy::swapNode", [&] {
+ node.nodeListProperty(propertyName.toUtf8()).slide(fromIndex, toIndex);
+ });
+}
+
+bool QmlModelNodeProxy::isInstanceOf(const QString &typeName, int internalId) const
+{
+ ModelNode modelNode = m_qmlObjectNode.modelNode();
+
+ QTC_ASSERT(modelNode.isValid(), return {});
+
+ if (internalId >= 0)
+ modelNode = modelNode.view()->modelNodeForInternalId(internalId);
+
+ NodeMetaInfo metaInfo = modelNode.model()->metaInfo(typeName.toUtf8());
+
+ return modelNode.metaInfo().isBasedOn(metaInfo);
+}
+
+void QmlModelNodeProxy::changeType(int internalId, const QString &typeName)
+{
+ QTC_ASSERT(m_qmlObjectNode.isValid(), return );
+
+ ModelNode node = m_qmlObjectNode.view()->modelNodeForInternalId(internalId);
+
+ QTC_ASSERT(node.isValid(), return );
+
+ QTC_ASSERT(!node.isRootNode(), return );
+#ifdef QDS_USE_PROJECTSTORAGE
+ node.changeType(typeName.toUtf8(), -1, -1);
+#else
+ NodeMetaInfo metaInfo = node.model()->metaInfo(typeName.toUtf8());
+ node.changeType(metaInfo.typeName(), metaInfo.majorVersion(), metaInfo.minorVersion());
+#endif
+}
+
+void QmlModelNodeProxy::handleInstancePropertyChanged(const ModelNode &modelNode,
+ const PropertyName &propertyName)
+{
+ const QmlObjectNode qmlObjectNode(modelNode);
+
+ for (const auto &item : qAsConst(m_subselection)) {
+ if (item && item->isRelevantModelNode(modelNode)) {
+ if (!modelNode.hasProperty(propertyName)
+ || modelNode.property(propertyName).isBindingProperty()) {
+ item->setValueFromModel(propertyName, qmlObjectNode.instanceValue(propertyName));
+ } else {
+ item->setValueFromModel(propertyName, qmlObjectNode.modelValue(propertyName));
+ }
+ }
+ }
+}
+
+void QmlModelNodeProxy::handleBindingPropertyChanged(const BindingProperty &property)
+{
+ for (const auto &item : qAsConst(m_subselection)) {
+ if (item && item->isRelevantModelNode(property.parentModelNode())) {
+ QmlObjectNode objectNode(item->modelNode());
+ if (objectNode.modelNode().property(property.name()).isBindingProperty())
+ item->setValueFromModel(property.name(), objectNode.instanceValue(property.name()));
+ else
+ item->setValueFromModel(property.name(), objectNode.modelValue(property.name()));
+ }
+ }
+}
+
+void QmlModelNodeProxy::handleVariantPropertyChanged(const VariantProperty &property)
+{
+ for (const auto &item : qAsConst(m_subselection)) {
+ if (item && item->isRelevantModelNode(property.parentModelNode())) {
+ QmlObjectNode objectNode(item->modelNode());
+ if (objectNode.modelNode().property(property.name()).isBindingProperty())
+ item->setValueFromModel(property.name(), objectNode.instanceValue(property.name()));
+ else
+ item->setValueFromModel(property.name(), objectNode.modelValue(property.name()));
+ }
+ }
+}
+
+void QmlModelNodeProxy::handlePropertiesRemoved(const AbstractProperty &property)
+{
+ for (const auto &item : qAsConst(m_subselection)) {
+ if (item && item->isRelevantModelNode(property.parentModelNode())) {
+ QmlObjectNode objectNode(item->modelNode());
+ item->resetValue(property.name());
+ item->setValueFromModel(property.name(), objectNode.instanceValue(property.name()));
+ }
+ }
+}
+
+QList<int> QmlModelNodeProxy::allChildren(const ModelNode &modelNode) const
+{
+ return toInternalIdList(modelNode.directSubModelNodes());
+}
+
+QList<int> QmlModelNodeProxy::allChildrenOfType(const ModelNode &modelNode, const QString &typeName) const
+{
+ QTC_ASSERT(modelNode.isValid(), return {});
+
+ NodeMetaInfo metaInfo = modelNode.model()->metaInfo(typeName.toUtf8());
+
+ return toInternalIdList(modelNode.directSubModelNodesOfType(metaInfo));
}
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.h b/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.h
index 4740b01fbd..d8a49d7e10 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.h
+++ b/src/plugins/qmldesigner/components/propertyeditor/qmlmodelnodeproxy.h
@@ -3,6 +3,8 @@
#pragma once
+#include "propertyeditorvalue.h"
+
#include <qmlitemnode.h>
#include <QObject>
@@ -16,6 +18,7 @@ class QMLDESIGNERCORE_EXPORT QmlModelNodeProxy : public QObject
Q_PROPERTY(QmlDesigner::ModelNode modelNode READ modelNode NOTIFY modelNodeChanged)
Q_PROPERTY(bool multiSelection READ multiSelection NOTIFY modelNodeChanged)
+
public:
explicit QmlModelNodeProxy(QObject *parent = nullptr);
@@ -36,13 +39,45 @@ public:
QString simplifiedTypeName() const;
+ Q_INVOKABLE QList<int> allChildren(int internalId = -1) const;
+ Q_INVOKABLE QList<int> allChildrenOfType(const QString &typeName, int internalId = -1) const;
+
+ Q_INVOKABLE QString simplifiedTypeName(int internalId) const;
+
+ Q_INVOKABLE PropertyEditorSubSelectionWrapper *registerSubSelectionWrapper(int internalId);
+
+ Q_INVOKABLE void createModelNode(int internalIdParent,
+ const QString &property,
+ const QString &typeName,
+ const QString &requiredImport = {});
+
+ Q_INVOKABLE void moveNode(int internalIdParent,
+ const QString &propertyName,
+ int fromIndex,
+ int toIndex);
+
+ Q_INVOKABLE bool isInstanceOf(const QString &typeName, int internalId = -1) const;
+
+ Q_INVOKABLE void changeType(int internalId, const QString &typeName);
+
+ void handleInstancePropertyChanged(const ModelNode &modelNode, const PropertyName &propertyName);
+
+ void handleBindingPropertyChanged(const BindingProperty &property);
+ void handleVariantPropertyChanged(const VariantProperty &property);
+ void handlePropertiesRemoved(const AbstractProperty &property);
+
signals:
void modelNodeChanged();
void selectionToBeChanged();
void selectionChanged();
private:
+ QList<int> allChildren(const ModelNode &modelNode) const;
+ QList<int> allChildrenOfType(const ModelNode &modelNode, const QString &typeName) const;
+ PropertyEditorSubSelectionWrapper *findWrapper(int internalId) const;
+
QmlObjectNode m_qmlObjectNode;
+ QList<QSharedPointer<PropertyEditorSubSelectionWrapper>> m_subselection;
};
} //QmlDesigner
diff --git a/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.cpp b/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.cpp
index 2d8998404a..f289583cc3 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.cpp
@@ -40,7 +40,7 @@ SetFrameValueDialog::SetFrameValueDialog(qreal frame, const QVariant &value,
valueLabel->setAlignment(Qt::AlignRight);
valueLabel->setFixedWidth(labelWidth);
- m_frameControl->setRange(std::numeric_limits<int>::min(), std::numeric_limits<int>::max());
+ m_frameControl->setRange(std::numeric_limits<int>::lowest(), std::numeric_limits<int>::max());
m_frameControl->setValue(static_cast<int>(frame));
m_frameControl->setAlignment(Qt::AlignRight);
@@ -86,7 +86,6 @@ QWidget* SetFrameValueDialog::createValueControl(const QVariant& value)
switch (value.metaType().id())
{
-
case QMetaType::QColor: {
auto* widget = new ColorControl(value.value<QColor>());
m_valueGetter = [widget]() { return widget->value(); };
@@ -102,7 +101,7 @@ QWidget* SetFrameValueDialog::createValueControl(const QVariant& value)
case QMetaType::Int: {
auto* widget = new QSpinBox;
- widget->setRange(std::numeric_limits<int>::min(), std::numeric_limits<int>::max());
+ widget->setRange(std::numeric_limits<int>::lowest(), std::numeric_limits<int>::max());
widget->setAlignment(Qt::AlignRight);
widget->setValue(value.toInt());
m_valueGetter = [widget]() { return widget->value(); };
@@ -120,7 +119,7 @@ QWidget* SetFrameValueDialog::createValueControl(const QVariant& value)
case QMetaType::Float: {
auto* widget = new QDoubleSpinBox;
- widget->setRange(std::numeric_limits<float>::min(), std::numeric_limits<float>::max());
+ widget->setRange(std::numeric_limits<float>::lowest(), std::numeric_limits<float>::max());
widget->setAlignment(Qt::AlignRight);
widget->setValue(value.toFloat());
m_valueGetter = [widget]() { return static_cast<float>(widget->value()); };
@@ -132,7 +131,7 @@ QWidget* SetFrameValueDialog::createValueControl(const QVariant& value)
default: {
auto* widget = new QDoubleSpinBox;
- widget->setRange(std::numeric_limits<double>::min(), std::numeric_limits<double>::max());
+ widget->setRange(std::numeric_limits<double>::lowest(), std::numeric_limits<double>::max());
widget->setAlignment(Qt::AlignRight);
widget->setValue(value.toDouble());
m_valueGetter = [widget]() { return widget->value(); };
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelineanimationform.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelineanimationform.cpp
index 83551378ee..e65c05c39f 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/timelineanimationform.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelineanimationform.cpp
@@ -13,6 +13,7 @@
#include <variantproperty.h>
#include <qmlitemnode.h>
#include <qmlobjectnode.h>
+#include <dialogutils.h>
#include <coreplugin/messagebox.h>
@@ -141,8 +142,7 @@ TimelineAnimationForm::TimelineAnimationForm(QWidget *parent)
bool error = false;
if (!ModelNode::isValidId(newId)) {
- Core::AsynchronousMessageBox::warning(tr("Invalid Id"),
- tr("%1 is an invalid id.").arg(newId));
+ DialogUtils::showWarningForInvalidId(newId);
error = true;
} else if (animation().view()->hasId(newId)) {
Core::AsynchronousMessageBox::warning(tr("Invalid Id"),
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelineform.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelineform.cpp
index b3d408dc0d..08915b6577 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/timelineform.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelineform.cpp
@@ -10,6 +10,7 @@
#include <nodemetainfo.h>
#include <rewritertransaction.h>
#include <variantproperty.h>
+#include <dialogutils.h>
#include <coreplugin/messagebox.h>
@@ -125,8 +126,7 @@ TimelineForm::TimelineForm(QWidget *parent)
bool error = false;
if (!ModelNode::isValidId(newId)) {
- Core::AsynchronousMessageBox::warning(tr("Invalid Id"),
- tr("%1 is an invalid id.").arg(newId));
+ DialogUtils::showWarningForInvalidId(newId);
error = true;
} else if (m_timeline.view()->hasId(newId)) {
Core::AsynchronousMessageBox::warning(tr("Invalid Id"),
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelineview.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelineview.cpp
index 7905df68e9..8288e69316 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/timelineview.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelineview.cpp
@@ -644,11 +644,12 @@ void TimelineView::registerActions()
TimelineWidget *TimelineView::createWidget()
{
- if (!m_timelineWidget)
+ if (!m_timelineWidget) {
m_timelineWidget = new TimelineWidget(this);
- auto *timelineContext = new TimelineContext(m_timelineWidget);
- Core::ICore::addContextObject(timelineContext);
+ auto *timelineContext = new TimelineContext(m_timelineWidget);
+ Core::ICore::addContextObject(timelineContext);
+ }
return m_timelineWidget;
}
diff --git a/src/plugins/qmldesigner/components/toolbar/toolbarbackend.cpp b/src/plugins/qmldesigner/components/toolbar/toolbarbackend.cpp
index e9df928c96..cb84183f92 100644
--- a/src/plugins/qmldesigner/components/toolbar/toolbarbackend.cpp
+++ b/src/plugins/qmldesigner/components/toolbar/toolbarbackend.cpp
@@ -21,6 +21,9 @@
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/icore.h>
#include <coreplugin/modemanager.h>
+
+#include <texteditor/textdocument.h>
+
#include <projectexplorer/kitmanager.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h>
@@ -302,6 +305,20 @@ ToolBarBackend::ToolBarBackend(QObject *parent)
this,
&ToolBarBackend::documentIndexChanged);
+ connect(Core::EditorManager::instance(), &Core::EditorManager::currentEditorChanged, this, [this]() {
+ static QMetaObject::Connection *lastConnection = nullptr;
+ delete lastConnection;
+
+ if (auto textDocument = qobject_cast<TextEditor::TextDocument *>(
+ Core::EditorManager::currentDocument())) {
+ connect(textDocument->document(),
+ &QTextDocument::modificationChanged,
+ this,
+ &ToolBarBackend::isDocumentDirtyChanged);
+ emit isDocumentDirtyChanged();
+ }
+ });
+
connect(Core::EditorManager::instance(),
&Core::EditorManager::currentEditorChanged,
this,
@@ -740,6 +757,12 @@ bool ToolBarBackend::isSharingEnabled()
return QmlDesigner::checkEnterpriseLicense();
}
+bool ToolBarBackend::isDocumentDirty() const
+{
+ return Core::EditorManager::currentDocument()
+ && Core::EditorManager::currentDocument()->isModified();
+}
+
void ToolBarBackend::launchGlobalAnnotations()
{
QmlDesignerPlugin::emitUsageStatistics(Constants::EVENT_TOOLBAR_EDIT_GLOBAL_ANNOTATION);
diff --git a/src/plugins/qmldesigner/components/toolbar/toolbarbackend.h b/src/plugins/qmldesigner/components/toolbar/toolbarbackend.h
index 5d0b0e712a..02bdae1717 100644
--- a/src/plugins/qmldesigner/components/toolbar/toolbarbackend.h
+++ b/src/plugins/qmldesigner/components/toolbar/toolbarbackend.h
@@ -97,6 +97,7 @@ class ToolBarBackend : public QObject
Q_PROPERTY(bool isMCUs READ isMCUs NOTIFY isMCUsChanged)
Q_PROPERTY(bool projectOpened READ projectOpened NOTIFY projectOpenedChanged)
Q_PROPERTY(bool isSharingEnabled READ isSharingEnabled NOTIFY isSharingEnabledChanged)
+ Q_PROPERTY(bool isDocumentDirty READ isDocumentDirty NOTIFY isDocumentDirtyChanged)
public:
ToolBarBackend(QObject *parent = nullptr);
@@ -147,6 +148,8 @@ public:
bool isSharingEnabled();
+ bool isDocumentDirty() const;
+
static void launchGlobalAnnotations();
signals:
@@ -167,6 +170,7 @@ signals:
void isMCUsChanged();
void projectOpenedChanged();
void isSharingEnabledChanged();
+ void isDocumentDirtyChanged();
private:
void setupWorkspaces();
diff --git a/src/plugins/qmldesigner/components/transitioneditor/transitioneditorview.cpp b/src/plugins/qmldesigner/components/transitioneditor/transitioneditorview.cpp
index 104127bd49..9f9e888823 100644
--- a/src/plugins/qmldesigner/components/transitioneditor/transitioneditorview.cpp
+++ b/src/plugins/qmldesigner/components/transitioneditor/transitioneditorview.cpp
@@ -318,11 +318,12 @@ ModelNode TransitionEditorView::addNewTransition()
TransitionEditorWidget *TransitionEditorView::createWidget()
{
- if (!m_transitionEditorWidget)
+ if (!m_transitionEditorWidget) {
m_transitionEditorWidget = new TransitionEditorWidget(this);
- auto *transitionContext = new TransitionContext(m_transitionEditorWidget);
- Core::ICore::addContextObject(transitionContext);
+ auto *transitionContext = new TransitionContext(m_transitionEditorWidget);
+ Core::ICore::addContextObject(transitionContext);
+ }
return m_transitionEditorWidget;
}
diff --git a/src/plugins/qmldesigner/components/transitioneditor/transitionform.cpp b/src/plugins/qmldesigner/components/transitioneditor/transitionform.cpp
index 1770ba63fc..dcbb0b23b3 100644
--- a/src/plugins/qmldesigner/components/transitioneditor/transitionform.cpp
+++ b/src/plugins/qmldesigner/components/transitioneditor/transitionform.cpp
@@ -13,6 +13,7 @@
#include <rewritertransaction.h>
#include <variantproperty.h>
#include <qmlitemnode.h>
+#include <dialogutils.h>
#include <coreplugin/messagebox.h>
@@ -45,8 +46,7 @@ TransitionForm::TransitionForm(QWidget *parent)
bool error = false;
if (!ModelNode::isValidId(newId)) {
- Core::AsynchronousMessageBox::warning(tr("Invalid ID"),
- tr("%1 is an invalid ID.").arg(newId));
+ DialogUtils::showWarningForInvalidId(newId);
error = true;
} else if (m_transition.view()->hasId(newId)) {
Core::AsynchronousMessageBox::warning(tr("Invalid ID"),
diff --git a/src/plugins/qmldesigner/componentsplugin/components.metainfo b/src/plugins/qmldesigner/componentsplugin/components.metainfo
index 8a1e365266..2e070aa322 100644
--- a/src/plugins/qmldesigner/componentsplugin/components.metainfo
+++ b/src/plugins/qmldesigner/componentsplugin/components.metainfo
@@ -12,6 +12,7 @@ MetaInfo {
Property { name: "width"; type: "int"; value: 100; }
Property { name: "height"; type: "int"; value: 100; }
+ toolTip: qsTr("Organizes items in a row.")
}
}
@@ -28,6 +29,7 @@ MetaInfo {
Property { name: "width"; type: "int"; value: 100; }
Property { name: "height"; type: "int"; value: 100; }
+ toolTip: qsTr("Organizes items in a column.")
}
}
@@ -44,6 +46,7 @@ MetaInfo {
Property { name: "width"; type: "int"; value: 100; }
Property { name: "height"; type: "int"; value: 100; }
+ toolTip: qsTr("Organizes items in a grid.")
}
}
@@ -57,7 +60,7 @@ MetaInfo {
}
ItemLibraryEntry {
- name: "StackLayout"
+ name: "Stack Layout"
category: "Qt Quick - Layouts"
libraryIcon: ":/componentsplugin/images/stack-layouts-icon.png"
version: "1.0"
@@ -65,6 +68,7 @@ MetaInfo {
Property { name: "width"; type: "int"; value: 100; }
Property { name: "height"; type: "int"; value: 100; }
+ toolTip: qsTr("Organizes items in a grid. Only the top item is visible.")
}
}
}
diff --git a/src/plugins/qmldesigner/designercore/generatedcomponentutils.cpp b/src/plugins/qmldesigner/designercore/generatedcomponentutils.cpp
new file mode 100644
index 0000000000..5ee5790b53
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/generatedcomponentutils.cpp
@@ -0,0 +1,139 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "generatedcomponentutils.h"
+
+#include <qmldesignerconstants.h>
+
+namespace QmlDesigner {
+
+GeneratedComponentUtils::GeneratedComponentUtils(ExternalDependenciesInterface &externalDependencies)
+ : m_externalDependencies(externalDependencies)
+{
+}
+
+Utils::FilePath GeneratedComponentUtils::generatedComponentsPath() const
+{
+ Utils::FilePath projectPath = Utils::FilePath::fromString(m_externalDependencies.currentProjectDirPath());
+ if (projectPath.isEmpty())
+ return {};
+
+ Utils::FilePath assetImportsPath = projectPath.resolvePath(QLatin1String(Constants::OLD_ASSET_IMPORT_FOLDER));
+ if (assetImportsPath.exists())
+ return assetImportsPath;
+
+ Utils::FilePath componentsPath = projectPath.resolvePath(QLatin1String(Constants::GENERATED_COMPONENTS_FOLDER));
+ if (!componentsPath.exists())
+ componentsPath.createDir();
+
+ return componentsPath;
+}
+
+Utils::FilePath GeneratedComponentUtils::composedEffectsBasePath() const
+{
+ Utils::FilePath basePath = generatedComponentsPath();
+ if (basePath.isEmpty())
+ return {};
+
+ QString effectsImportPath;
+ if (basePath.endsWith(Constants::OLD_ASSET_IMPORT_FOLDER))
+ effectsImportPath = Constants::OLD_EFFECTS_FOLDER;
+ else
+ effectsImportPath = Constants::COMPOSED_EFFECTS_TYPE;
+
+ return basePath.resolvePath(effectsImportPath);
+}
+
+Utils::FilePath GeneratedComponentUtils::composedEffectPath(const QString &effectPath) const
+{
+ Utils::FilePath effectsBasePath = composedEffectsBasePath();
+
+ QString effectName = Utils::FilePath::fromString(effectPath).baseName();
+
+ return effectsBasePath.resolvePath(effectName + "/" + effectName + ".qml");
+}
+
+Utils::FilePath GeneratedComponentUtils::componentBundlesBasePath() const
+{
+ Utils::FilePath basePath = generatedComponentsPath();
+
+ if (basePath.isEmpty())
+ return {};
+
+ return basePath.resolvePath(QLatin1String(Constants::COMPONENT_BUNDLES_TYPE));
+}
+
+Utils::FilePath GeneratedComponentUtils::import3dBasePath() const
+{
+ Utils::FilePath basePath = generatedComponentsPath();
+
+ if (basePath.isEmpty())
+ return {};
+
+ Utils::FilePath import3dPath;
+ if (basePath.endsWith(Constants::OLD_ASSET_IMPORT_FOLDER))
+ return basePath.resolvePath(QLatin1String(Constants::OLD_QUICK_3D_ASSETS_FOLDER));
+
+ return basePath.resolvePath(QLatin1String(Constants::QUICK_3D_COMPONENTS_FOLDER));
+}
+
+bool GeneratedComponentUtils::isImport3dPath(const QString &path) const
+{
+ return path.contains('/' + QLatin1String(Constants::OLD_QUICK_3D_ASSETS_FOLDER))
+ || path.contains(QLatin1String(Constants::GENERATED_COMPONENTS_FOLDER) + '/'
+ + QLatin1String(Constants::QUICK_3D_COMPONENTS_FOLDER));
+}
+
+bool GeneratedComponentUtils::isComposedEffectPath(const QString &path) const
+{
+ return path.contains(Constants::OLD_EFFECTS_IMPORT_FOLDER)
+ || path.contains('/' + QLatin1String(Constants::COMPOSED_EFFECTS_TYPE));
+}
+
+QString GeneratedComponentUtils::generatedComponentTypePrefix() const
+{
+ Utils::FilePath basePath = generatedComponentsPath();
+ if (basePath.isEmpty() || basePath.endsWith(Constants::OLD_ASSET_IMPORT_FOLDER))
+ return {};
+
+ return Constants::GENERATED_COMPONENTS_FOLDER;
+}
+
+QString GeneratedComponentUtils::import3dTypePrefix() const
+{
+ QString basePrefix = generatedComponentTypePrefix();
+
+ if (basePrefix == Constants::GENERATED_COMPONENTS_FOLDER)
+ return basePrefix + '.' + QLatin1String(Constants::QUICK_3D_COMPONENTS_FOLDER);
+
+ return Constants::OLD_QUICK_3D_ASSETS_FOLDER;
+}
+
+QString GeneratedComponentUtils::import3dTypePath() const
+{
+ QString prefix = import3dTypePrefix();
+ prefix.replace('.', '/');
+ return prefix;
+}
+
+QString GeneratedComponentUtils::componentBundlesTypePrefix() const
+{
+ QString basePrefix = generatedComponentTypePrefix();
+
+ if (basePrefix.endsWith(Constants::GENERATED_COMPONENTS_FOLDER))
+ return basePrefix + '.' + QLatin1String(Constants::COMPONENT_BUNDLES_TYPE);
+
+ return Constants::COMPONENT_BUNDLES_TYPE;
+}
+
+QString GeneratedComponentUtils::composedEffectsTypePrefix() const
+{
+ QString basePrefix = generatedComponentTypePrefix();
+
+ if (basePrefix == Constants::GENERATED_COMPONENTS_FOLDER)
+ return basePrefix + '.' + QLatin1String(Constants::COMPOSED_EFFECTS_TYPE);
+
+ return Constants::OLD_EFFECTS_FOLDER;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/generatedcomponentutils.h b/src/plugins/qmldesigner/designercore/generatedcomponentutils.h
new file mode 100644
index 0000000000..e2e9baf3e7
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/generatedcomponentutils.h
@@ -0,0 +1,38 @@
+// 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 once
+
+#include <externaldependenciesinterface.h>
+#include <qmldesignercorelib_exports.h>
+
+#include <utils/filepath.h>
+
+#include <QString>
+
+namespace QmlDesigner {
+
+class QMLDESIGNERCORE_EXPORT GeneratedComponentUtils {
+public:
+ GeneratedComponentUtils(ExternalDependenciesInterface &externalDependencies);
+
+ Utils::FilePath generatedComponentsPath() const;
+ Utils::FilePath composedEffectsBasePath() const;
+ Utils::FilePath composedEffectPath(const QString &effectPath) const;
+ Utils::FilePath componentBundlesBasePath() const;
+ Utils::FilePath import3dBasePath() const;
+
+ bool isImport3dPath(const QString &path) const;
+ bool isComposedEffectPath(const QString &path) const;
+
+ QString generatedComponentTypePrefix() const;
+ QString import3dTypePrefix() const;
+ QString import3dTypePath() const;
+ QString componentBundlesTypePrefix() const;
+ QString composedEffectsTypePrefix() const;
+
+private:
+ ExternalDependenciesInterface &m_externalDependencies;
+};
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.cpp b/src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.cpp
index 955e676d3b..97148e664f 100644
--- a/src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.cpp
+++ b/src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.cpp
@@ -76,8 +76,10 @@ void ImageCacheCollector::start(Utils::SmallStringView name,
AbortCallback abortCallback,
ImageCache::TraceToken traceToken)
{
+#ifdef QDS_USE_PROJECTSTORAGE
if (!m_projectStorage || !m_pathCache)
return;
+#endif
using namespace NanotraceHR::Literals;
auto [collectorTraceToken, flowtoken] = traceToken.beginDurationWithFlow(
diff --git a/src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.h b/src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.h
index c2a912cc3a..fec68c2894 100644
--- a/src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.h
+++ b/src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.h
@@ -64,8 +64,10 @@ private:
QSize captureImageMaximumSize;
ExternalDependenciesInterface &m_externalDependencies;
ImageCacheCollectorNullImageHandling nullImageHandling{};
+#ifdef QDS_USE_PROJECTSTORAGE
ProjectStorageType *m_projectStorage = nullptr;
PathCacheType *m_pathCache = nullptr;
+#endif
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/imagecache/taskqueue.h b/src/plugins/qmldesigner/designercore/imagecache/taskqueue.h
index fac7e7d9bf..dc5ed3de23 100644
--- a/src/plugins/qmldesigner/designercore/imagecache/taskqueue.h
+++ b/src/plugins/qmldesigner/designercore/imagecache/taskqueue.h
@@ -31,7 +31,7 @@ public:
{
std::unique_lock lock{m_mutex};
- ensureThreadIsRunning(std::move(traceToken));
+ ensureThreadIsRunning(lock, std::move(traceToken));
m_tasks.emplace_back(std::forward<Arguments>(arguments)...);
}
@@ -54,6 +54,15 @@ public:
clearTasks(oldTasks);
}
+ void putThreadToSleep()
+ {
+ {
+ std::unique_lock lock{m_mutex};
+ m_sleeping = true;
+ }
+ m_condition.notify_all();
+ }
+
private:
void destroy()
{
@@ -66,19 +75,20 @@ private:
{
using namespace std::literals::chrono_literals;
std::unique_lock lock{m_mutex};
- if (m_finishing)
+
+ if (m_finishing || m_sleeping)
return {std::move(lock), true};
+
if (m_tasks.empty()) {
auto timedOutWithoutEntriesOrFinishing = !m_condition.wait_for(lock, 10min, [&] {
- return m_tasks.size() || m_finishing;
+ return m_tasks.size() || m_finishing || m_sleeping;
});
- if (timedOutWithoutEntriesOrFinishing || m_finishing) {
+ if (timedOutWithoutEntriesOrFinishing)
m_sleeping = true;
- return {std::move(lock), true};
- }
}
- return {std::move(lock), false};
+
+ return {std::move(lock), m_finishing || m_sleeping};
}
[[nodiscard]] std::optional<Task> getTask(std::unique_lock<std::mutex> lock)
@@ -94,29 +104,38 @@ private:
return {std::move(task)};
}
- template<typename TraceToken>
- void ensureThreadIsRunning(TraceToken traceToken)
+ template<typename Lock, typename TraceToken>
+ void ensureThreadIsRunning(Lock &lock, TraceToken traceToken)
{
using namespace NanotraceHR::Literals;
if (m_finishing || !m_sleeping)
return;
+ if (m_sleeping) {
+ lock.unlock();
+ joinThread();
+ lock.lock();
+
+ m_sleeping = false;
+ }
+
if (m_backgroundThread.joinable())
return;
- m_sleeping = false;
-
auto [threadCreateToken, flowToken] = traceToken.beginDurationWithFlow(
"thread is created in the task queue"_t);
m_backgroundThread = std::thread{[this](auto traceToken) {
auto duration = traceToken.beginDuration(
"thread is ready"_t);
+
while (true) {
auto [lock, abort] = waitForTasks();
duration.end();
+
if (abort)
return;
+
auto getTaskToken = duration.beginDuration(
"get task from queue"_t);
if (auto task = getTask(std::move(lock)); task) {
diff --git a/src/plugins/qmldesigner/designercore/include/model.h b/src/plugins/qmldesigner/designercore/include/model.h
index b907e6c5d8..85f129cdbc 100644
--- a/src/plugins/qmldesigner/designercore/include/model.h
+++ b/src/plugins/qmldesigner/designercore/include/model.h
@@ -166,6 +166,7 @@ public:
NodeMetaInfo qtQmlConnectionsMetaInfo() const;
NodeMetaInfo qtQmlModelsListModelMetaInfo() const;
NodeMetaInfo qtQmlModelsListElementMetaInfo() const;
+ NodeMetaInfo qtQmlXmlListModelXmlListModelRoleMetaInfo() const;
NodeMetaInfo qtQuick3DBakedLightmapMetaInfo() const;
NodeMetaInfo qtQuick3DDefaultMaterialMetaInfo() const;
NodeMetaInfo qtQuick3DDirectionalLightMetaInfo() const;
@@ -218,14 +219,17 @@ public:
// Imports:
const Imports &imports() const;
- const Imports &possibleImports() const;
- const Imports &usedImports() const;
+ Imports possibleImports() const;
+ Imports usedImports() const;
void changeImports(Imports importsToBeAdded, Imports importsToBeRemoved);
+#ifndef QDS_USE_PROJECTSTORAGE
void setPossibleImports(Imports possibleImports);
+#endif
+#ifndef QDS_USE_PROJECTSTORAGE
void setUsedImports(Imports usedImports);
+#endif
bool hasImport(const Import &import, bool ignoreAlias = true, bool allowHigherVersion = false) const;
bool isImportPossible(const Import &import, bool ignoreAlias = true, bool allowHigherVersion = false) const;
- QString pathForImport(const Import &import);
QStringList importPaths() const;
Import highestPossibleImport(const QString &importPath);
diff --git a/src/plugins/qmldesigner/designercore/include/modelfwd.h b/src/plugins/qmldesigner/designercore/include/modelfwd.h
index 0a062289fd..91c533fe7b 100644
--- a/src/plugins/qmldesigner/designercore/include/modelfwd.h
+++ b/src/plugins/qmldesigner/designercore/include/modelfwd.h
@@ -77,7 +77,7 @@ constexpr bool useProjectStorage()
using ProjectStorageType = ProjectStorageInterface;
using PathCacheType = SourcePathCacheInterface;
#else
-using ProjectStorageType = ProjectStorage<Sqlite::Database>;
+using ProjectStorageType = ProjectStorage;
using PathCacheType = SourcePathCache<ProjectStorageType, NonLockingMutex>;
#endif
diff --git a/src/plugins/qmldesigner/designercore/include/nodemetainfo.h b/src/plugins/qmldesigner/designercore/include/nodemetainfo.h
index 53c755ddc8..ba2e2cda65 100644
--- a/src/plugins/qmldesigner/designercore/include/nodemetainfo.h
+++ b/src/plugins/qmldesigner/designercore/include/nodemetainfo.h
@@ -27,9 +27,11 @@ QT_END_NAMESPACE
# define DEPRECATED_VERSION_NUMBER \
[[deprecated( \
"In most cases you don't need them anymore because the import is setting them!")]]
+# define DEPRECATED_COMPONENT_FILE_NAME [[deprecated("Use sourceId() instead.")]]
#else
# define DEPRECATED_TYPENAME
# define DEPRECATED_VERSION_NUMBER
+# define DEPRECATED_COMPONENT_FILE_NAME
#endif
namespace QmlDesigner {
@@ -116,7 +118,7 @@ public:
Storage::Info::ItemLibraryEntries itemLibrariesEntries() const;
SourceId sourceId() const;
- QString componentFileName() const;
+ DEPRECATED_COMPONENT_FILE_NAME QString componentFileName() const;
bool isBasedOn(const NodeMetaInfo &metaInfo) const;
bool isBasedOn(const NodeMetaInfo &metaInfo1, const NodeMetaInfo &metaInfo2) const;
@@ -167,6 +169,7 @@ public:
bool isQtMultimediaSoundEffect() const;
bool isQtObject() const;
bool isQtQmlConnections() const;
+ bool isQtQmlModelsListElement() const;
bool isQtQuick3DBakedLightmap() const;
bool isQtQuick3DBuffer() const;
bool isQtQuick3DCamera() const;
@@ -176,7 +179,6 @@ public:
bool isQtQuick3DInstanceList() const;
bool isQtQuick3DInstanceListEntry() const;
bool isQtQuick3DLight() const;
- bool isQtQuickListElement() const;
bool isQtQuickListModel() const;
bool isQtQuickListView() const;
bool isQtQuick3DMaterial() const;
@@ -265,12 +267,14 @@ public:
private:
const Storage::Info::Type &typeData() const;
+ PropertyDeclarationId defaultPropertyDeclarationId() const;
bool isSubclassOf(const TypeName &type, int majorVersion = -1, int minorVersion = -1) const;
private:
TypeId m_typeId;
NotNullPointer<const ProjectStorageType> m_projectStorage = {};
mutable std::optional<Storage::Info::Type> m_typeData;
+ mutable std::optional<PropertyDeclarationId> m_defaultPropertyId;
std::shared_ptr<NodeMetaInfoPrivate> m_privateData;
};
diff --git a/src/plugins/qmldesigner/designercore/include/projectstorageids.h b/src/plugins/qmldesigner/designercore/include/projectstorageids.h
index bc66e0d2b2..0b157e55e7 100644
--- a/src/plugins/qmldesigner/designercore/include/projectstorageids.h
+++ b/src/plugins/qmldesigner/designercore/include/projectstorageids.h
@@ -7,6 +7,8 @@
#include <utils/span.h>
+#include <QVarLengthArray>
+
namespace QmlDesigner {
enum class BasicIdType {
@@ -29,6 +31,8 @@ enum class BasicIdType {
using TypeId = Sqlite::BasicId<BasicIdType::Type>;
using TypeIds = std::vector<TypeId>;
+template<std::size_t size>
+using SmallTypeIds = QVarLengthArray<TypeId, size>;
using PropertyDeclarationId = Sqlite::BasicId<BasicIdType::PropertyDeclaration>;
using PropertyDeclarationIds = std::vector<PropertyDeclarationId>;
@@ -47,6 +51,8 @@ using SourceContextIds = std::vector<SourceContextId>;
using SourceId = Sqlite::BasicId<BasicIdType::Source, int>;
using SourceIds = std::vector<SourceId>;
+template<std::size_t size>
+using SmallSourceIds = QVarLengthArray<SourceId, size>;
using ModuleId = Sqlite::BasicId<BasicIdType::Module, int>;
using ModuleIds = std::vector<ModuleId>;
diff --git a/src/plugins/qmldesigner/designercore/include/qmlitemnode.h b/src/plugins/qmldesigner/designercore/include/qmlitemnode.h
index dde5515a5a..e11f201cdb 100644
--- a/src/plugins/qmldesigner/designercore/include/qmlitemnode.h
+++ b/src/plugins/qmldesigner/designercore/include/qmlitemnode.h
@@ -174,6 +174,7 @@ public:
ModelNode targetTransition() const;
void assignTargetFlowItem(const QmlFlowTargetNode &flowItem);
QmlFlowItemNode flowItemParent() const;
+private:
void destroyTarget();
};
diff --git a/src/plugins/qmldesigner/designercore/include/rewriterview.h b/src/plugins/qmldesigner/designercore/include/rewriterview.h
index 23841accda..0134349682 100644
--- a/src/plugins/qmldesigner/designercore/include/rewriterview.h
+++ b/src/plugins/qmldesigner/designercore/include/rewriterview.h
@@ -123,7 +123,10 @@ public:
bool renameId(const QString& oldId, const QString& newId);
const QmlJS::Document *document() const;
+
+#ifndef QDS_USE_PROJECTSTORAGE
const QmlJS::ScopeChain *scopeChain() const;
+#endif
QString convertTypeToImportAlias(const QString &type) const;
@@ -135,8 +138,6 @@ public:
void setCheckLinkErrors(bool b) { m_checkLinkErrors = b; }
- QString pathForImport(const Import &import);
-
QStringList importDirectories() const;
QSet<QPair<QString, QString> > qrcMapping() const;
diff --git a/src/plugins/qmldesigner/designercore/include/subcomponentmanager.h b/src/plugins/qmldesigner/designercore/include/subcomponentmanager.h
index 7fa2348854..a42164d1bd 100644
--- a/src/plugins/qmldesigner/designercore/include/subcomponentmanager.h
+++ b/src/plugins/qmldesigner/designercore/include/subcomponentmanager.h
@@ -7,6 +7,7 @@
# include "qmldesignercorelib_global.h"
+# include <generatedcomponentutils.h>
# include <import.h>
# include <QObject>
@@ -62,6 +63,7 @@ private: // variables
QDir m_filePathDir;
QPointer<Model> m_model;
ExternalDependenciesInterface &m_externalDependencies;
+ GeneratedComponentUtils m_componentUtils;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
index 33a100f7b2..1b965db66a 100644
--- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
@@ -64,6 +64,8 @@
#include <qmlitemnode.h>
#include <rewriterview.h>
+#include <projectstorage/projectstorage.h>
+
#include <utils/hdrimage.h>
#include <coreplugin/messagemanager.h>
@@ -205,22 +207,17 @@ NodeInstanceView::~NodeInstanceView()
static bool isSkippedRootNode(const ModelNode &node)
{
- static const PropertyNameList skipList({"Qt.ListModel", "QtQuick.ListModel", "Qt.ListModel", "QtQuick.ListModel"});
-
- if (skipList.contains(node.type()))
- return true;
-
- return false;
+ return node.metaInfo().isQtQuickListModel();
}
static bool isSkippedNode(const ModelNode &node)
{
- static const PropertyNameList skipList({"QtQuick.XmlRole", "Qt.XmlRole", "QtQuick.ListElement", "Qt.ListElement"});
+ auto model = node.model();
- if (skipList.contains(node.type()))
- return true;
+ auto listElement = model->qtQmlModelsListElementMetaInfo();
+ auto xmlRole = model->qtQmlXmlListModelXmlListModelRoleMetaInfo();
- return false;
+ return node.metaInfo().isBasedOn(listElement, xmlRole);
}
static bool parentTakesOverRendering(const ModelNode &modelNode)
@@ -644,7 +641,7 @@ void NodeInstanceView::auxiliaryDataChanged(const ModelNode &node,
TypeName(),
key.type};
m_nodeInstanceServer->changeAuxiliaryValues({{container}});
- };
+ }
break;
case AuxiliaryDataType::NodeInstanceAuxiliary:
@@ -656,7 +653,7 @@ void NodeInstanceView::auxiliaryDataChanged(const ModelNode &node,
TypeName(),
key.type};
m_nodeInstanceServer->changeAuxiliaryValues({{container}});
- };
+ }
break;
case AuxiliaryDataType::NodeInstancePropertyOverwrite:
@@ -991,6 +988,8 @@ QRectF NodeInstanceView::sceneRect() const
return {};
}
+namespace {
+
QList<ModelNode> filterNodesForSkipItems(const QList<ModelNode> &nodeList)
{
QList<ModelNode> filteredNodeList;
@@ -1003,14 +1002,12 @@ QList<ModelNode> filterNodesForSkipItems(const QList<ModelNode> &nodeList)
return filteredNodeList;
}
-namespace {
bool shouldSendAuxiliary(const AuxiliaryDataKey &key)
{
return key.type == AuxiliaryDataType::NodeInstancePropertyOverwrite
|| key.type == AuxiliaryDataType::NodeInstanceAuxiliary || key == invisibleProperty
|| key == lockedProperty;
}
-} // namespace
bool parentIsBehavior(ModelNode node)
{
@@ -1024,6 +1021,31 @@ bool parentIsBehavior(ModelNode node)
return false;
}
+TypeName createQualifiedTypeName(const ModelNode &node)
+{
+ if (!node)
+ return {};
+
+#ifdef QDS_USE_PROJECTSTORAGE
+ auto model = node.model();
+ auto exportedTypes = node.metaInfo().exportedTypeNamesForSourceId(model->fileUrlSourceId());
+ if (exportedTypes.size()) {
+ const auto &exportedType = exportedTypes.front();
+ Utils::PathString typeName = model->projectStorage()->moduleName(exportedType.moduleId);
+ typeName += '/';
+ typeName += exportedType.name;
+
+ return typeName.toQByteArray();
+ }
+
+ return {};
+#else
+ return node.type();
+#endif
+}
+
+} // namespace
+
CreateSceneCommand NodeInstanceView::createCreateSceneCommand()
{
QList<ModelNode> nodeList = allModelNodes();
@@ -1079,8 +1101,9 @@ CreateSceneCommand NodeInstanceView::createCreateSceneCommand()
nodeFlags |= InstanceContainer::ParentTakesOverRendering;
const auto modelNode = instance.modelNode();
+
InstanceContainer container(instance.instanceId(),
- modelNode.type(),
+ createQualifiedTypeName(modelNode),
modelNode.majorVersion(),
modelNode.minorVersion(),
ModelUtils::componentFilePath(modelNode),
@@ -1243,7 +1266,7 @@ CreateInstancesCommand NodeInstanceView::createCreateInstancesCommand(const QLis
const auto modelNode = instance.modelNode();
InstanceContainer container(instance.instanceId(),
- modelNode.type(),
+ createQualifiedTypeName(modelNode),
modelNode.majorVersion(),
modelNode.minorVersion(),
ModelUtils::componentFilePath(modelNode),
@@ -1850,7 +1873,7 @@ QVariant NodeInstanceView::previewImageDataForImageNode(const ModelNode &modelNo
ModelNodePreviewImageData imageData;
imageData.id = modelNode.id();
- imageData.type = QString::fromLatin1(modelNode.type());
+ imageData.type = QString::fromUtf8(createQualifiedTypeName(modelNode));
const double ratio = m_externalDependencies.formEditorDevicePixelRatio();
if (imageSource.isEmpty() && modelNode.metaInfo().isQtQuick3DTexture()) {
@@ -1923,7 +1946,7 @@ QVariant NodeInstanceView::previewImageDataForImageNode(const ModelNode &modelNo
imageData.pixmap = originalPixmap.scaled(dim, dim, Qt::KeepAspectRatio);
imageData.pixmap.setDevicePixelRatio(ratio);
imageData.time = modified;
- imageData.info = ImageUtils::imageInfo(imageSource);
+ imageData.info = ImageUtils::imageInfoString(imageSource);
m_imageDataMap.insert(imageData.id, imageData);
}
}
@@ -1958,7 +1981,7 @@ QVariant NodeInstanceView::previewImageDataForGenericNode(const ModelNode &model
if (m_imageDataMap.contains(id)) {
imageData = m_imageDataMap[id];
} else {
- imageData.type = QString::fromLatin1(modelNode.type());
+ imageData.type = QString::fromLatin1(createQualifiedTypeName(modelNode));
imageData.id = id;
m_imageDataMap.insert(id, imageData);
}
diff --git a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp
index 85f904666c..b8c3e610be 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp
@@ -919,8 +919,11 @@ const ObjectValue *NodeMetaInfoPrivate::getObjectValue() const
ContextPtr NodeMetaInfoPrivate::context() const
{
+#ifndef QDS_USE_PROJECTSTORAGE
if (m_model && m_model->rewriterView() && m_model->rewriterView()->scopeChain())
return m_model->rewriterView()->scopeChain()->context();
+#endif
+
return ContextPtr(nullptr);
}
@@ -1832,7 +1835,7 @@ PropertyName NodeMetaInfo::defaultPropertyName() const
{
if constexpr (useProjectStorage()) {
if (isValid()) {
- if (auto name = m_projectStorage->propertyName(typeData().defaultPropertyId)) {
+ if (auto name = m_projectStorage->propertyName(defaultPropertyDeclarationId())) {
return name->toQByteArray();
}
}
@@ -1848,7 +1851,7 @@ PropertyMetaInfo NodeMetaInfo::defaultProperty() const
{
if constexpr (useProjectStorage()) {
if (isValid()) {
- return PropertyMetaInfo(typeData().defaultPropertyId, m_projectStorage);
+ return PropertyMetaInfo(defaultPropertyDeclarationId(), m_projectStorage);
}
} else {
return property(defaultPropertyName());
@@ -1859,7 +1862,7 @@ PropertyMetaInfo NodeMetaInfo::defaultProperty() const
bool NodeMetaInfo::hasDefaultProperty() const
{
if constexpr (useProjectStorage())
- return isValid() && bool(typeData().defaultPropertyId);
+ return isValid() && bool(defaultPropertyDeclarationId());
else
return !defaultPropertyName().isEmpty();
}
@@ -2086,6 +2089,14 @@ const Storage::Info::Type &NodeMetaInfo::typeData() const
return *m_typeData;
}
+PropertyDeclarationId NodeMetaInfo::defaultPropertyDeclarationId() const
+{
+ if (!m_defaultPropertyId)
+ m_defaultPropertyId.emplace(m_projectStorage->defaultPropertyDeclarationId(m_typeId));
+
+ return *m_defaultPropertyId;
+}
+
bool NodeMetaInfo::isSubclassOf(const TypeName &type, int majorVersion, int minorVersion) const
{
if (!isValid()) {
@@ -2444,12 +2455,9 @@ bool NodeMetaInfo::usesCustomParser() const
if (!isValid())
return false;
- auto type = typeName();
- return type == "QtQuick.VisualItemModel" || type == "Qt.VisualItemModel"
- || type == "QtQuick.VisualDataModel" || type == "Qt.VisualDataModel"
- || type == "QtQuick.ListModel" || type == "Qt.ListModel"
- || type == "QtQml.Models.ListModel" || type == "QtQuick.XmlListModel"
- || type == "Qt.XmlListModel" || type == "QtQml.XmlListModel.XmlListModel";
+ auto type = simplifiedTypeName();
+ return type == "VisualItemModel" || type == "VisualDataModel" || type == "ListModel"
+ || type == "XmlListModel";
}
}
@@ -2763,7 +2771,7 @@ bool NodeMetaInfo::isQtQuick3DLight() const
}
}
-bool NodeMetaInfo::isQtQuickListElement() const
+bool NodeMetaInfo::isQtQmlModelsListElement() const
{
if constexpr (useProjectStorage()) {
using namespace Storage::Info;
diff --git a/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp b/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp
index 403731d1c4..16d9217f6a 100644
--- a/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp
+++ b/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp
@@ -44,6 +44,7 @@ SubComponentManager::SubComponentManager(Model *model,
ExternalDependenciesInterface &externalDependencies)
: m_model(model)
, m_externalDependencies{externalDependencies}
+ , m_componentUtils{externalDependencies}
{
connect(&m_watcher, &QFileSystemWatcher::directoryChanged,
this, [this](const QString &path) { parseDirectory(path); });
@@ -192,7 +193,7 @@ void SubComponentManager::parseDirectory(const QString &canonicalDirPath, bool a
if (!model() || !model()->rewriterView())
return;
- if (canonicalDirPath.endsWith(QLatin1String(Constants::QUICK_3D_ASSETS_FOLDER))) {
+ if (m_componentUtils.isImport3dPath(canonicalDirPath)) {
parseQuick3DAssetsDir(canonicalDirPath);
return;
}
@@ -345,8 +346,8 @@ void SubComponentManager::registerQmlFile(const QFileInfo &fileInfo, const QStri
bool addToLibrary)
{
if (!addToLibrary || !model()
- || fileInfo.path().contains(QLatin1String(Constants::QUICK_3D_ASSETS_FOLDER))
- || fileInfo.path().contains(QLatin1String(Constants::DEFAULT_EFFECTS_IMPORT_FOLDER))) {
+ || m_componentUtils.isImport3dPath(fileInfo.path())
+ || m_componentUtils.isComposedEffectPath(fileInfo.path())) {
return;
}
@@ -395,7 +396,7 @@ void SubComponentManager::parseQuick3DAssetsDir(const QString &quick3DAssetsPath
QDir quick3DAssetsDir(quick3DAssetsPath);
QStringList assets = quick3DAssetsDir.entryList(QDir::Dirs | QDir::NoDot | QDir::NoDotDot);
for (QString &asset : assets)
- asset.prepend(QString(Constants::QUICK_3D_ASSETS_FOLDER).mid(1) + '.');
+ asset.prepend(m_componentUtils.import3dTypePrefix() + '.');
// Create item library entries for Quick3D assets that are imported by document
for (auto &import : std::as_const(m_imports)) {
@@ -460,7 +461,8 @@ QStringList SubComponentManager::quick3DAssetPaths() const
const auto impPaths = importPaths();
QStringList retPaths;
for (const auto &impPath : impPaths) {
- const QString assetPath = impPath + QLatin1String(Constants::QUICK_3D_ASSETS_FOLDER);
+ QString path3d = m_componentUtils.import3dTypePath();
+ const QString assetPath = impPath + '/' + path3d;
if (QFileInfo::exists(assetPath))
retPaths << assetPath;
}
@@ -520,7 +522,7 @@ void SubComponentManager::update(const QUrl &filePath, const Imports &imports)
// Remove old watched asset paths
const QStringList watchPaths = m_watcher.directories();
- const QString &quick3DAssetFolder = QLatin1String(Constants::QUICK_3D_ASSETS_FOLDER);
+ const QString &quick3DAssetFolder = m_componentUtils.import3dTypePath();
for (const auto &watchPath : watchPaths) {
if (watchPath.endsWith(quick3DAssetFolder))
m_watcher.removePath(watchPath);
@@ -580,7 +582,7 @@ void SubComponentManager::addAndParseImport(const Import &import)
} else {
QString url = import.url();
- if (url.startsWith(QString(Constants::QUICK_3D_ASSETS_FOLDER).mid(1))) {
+ if (url.startsWith(m_componentUtils.import3dTypePrefix())) {
parseQuick3DAssetsItem(import.url());
return;
}
diff --git a/src/plugins/qmldesigner/designercore/model/abstractview.cpp b/src/plugins/qmldesigner/designercore/model/abstractview.cpp
index 061ab8ae2b..125c7195a8 100644
--- a/src/plugins/qmldesigner/designercore/model/abstractview.cpp
+++ b/src/plugins/qmldesigner/designercore/model/abstractview.cpp
@@ -567,8 +567,10 @@ void AbstractView::disableWidget()
void AbstractView::enableWidget()
{
- if (hasWidget() && widgetInfo().widgetFlags == DesignerWidgetFlags::DisableOnError)
- widgetInfo().widget->setEnabled(true);
+ if (hasWidget()) {
+ if (auto info = widgetInfo(); info.widgetFlags == DesignerWidgetFlags::DisableOnError)
+ info.widget->setEnabled(true);
+ }
}
QString AbstractView::contextHelpId() const
diff --git a/src/plugins/qmldesigner/designercore/model/bindingproperty.cpp b/src/plugins/qmldesigner/designercore/model/bindingproperty.cpp
index 141548047e..23c17dc61a 100644
--- a/src/plugins/qmldesigner/designercore/model/bindingproperty.cpp
+++ b/src/plugins/qmldesigner/designercore/model/bindingproperty.cpp
@@ -37,10 +37,11 @@ BindingProperty::BindingProperty(const PropertyName &propertyName, const Interna
void BindingProperty::setExpression(const QString &expression)
{
- Internal::WriteLocker locker(model());
if (!isValid())
return;
+ Internal::WriteLocker locker(model());
+
if (isDynamic())
qWarning() << "Calling BindingProperty::setExpression on dynamic property.";
diff --git a/src/plugins/qmldesigner/designercore/model/model.cpp b/src/plugins/qmldesigner/designercore/model/model.cpp
index a4cd31b2a8..4f0bfba1ce 100644
--- a/src/plugins/qmldesigner/designercore/model/model.cpp
+++ b/src/plugins/qmldesigner/designercore/model/model.cpp
@@ -1758,14 +1758,22 @@ Storage::Info::ExportedTypeName Model::exportedTypeNameForMetaInfo(const NodeMet
return {};
}
-const Imports &Model::possibleImports() const
+Imports Model::possibleImports() const
{
+#ifdef QDS_USE_PROJECTSTORAGE
+ return {};
+#else
return d->m_possibleImportList;
+#endif
}
-const Imports &Model::usedImports() const
+Imports Model::usedImports() const
{
+#ifdef QDS_USE_PROJECTSTORAGE
+ return {};
+#else
return d->m_usedImportList;
+#endif
}
void Model::changeImports(Imports importsToBeAdded, Imports importsToBeRemoved)
@@ -1773,6 +1781,7 @@ void Model::changeImports(Imports importsToBeAdded, Imports importsToBeRemoved)
d->changeImports(std::move(importsToBeAdded), std::move(importsToBeRemoved));
}
+#ifndef QDS_USE_PROJECTSTORAGE
void Model::setPossibleImports(Imports possibleImports)
{
auto tracer = d->traceToken.begin("possible imports"_t);
@@ -1784,7 +1793,9 @@ void Model::setPossibleImports(Imports possibleImports)
d->notifyPossibleImportsChanged(d->m_possibleImportList);
}
}
+#endif
+#ifndef QDS_USE_PROJECTSTORAGE
void Model::setUsedImports(Imports usedImports)
{
auto tracer = d->traceToken.begin("used imports"_t);
@@ -1796,6 +1807,7 @@ void Model::setUsedImports(Imports usedImports)
d->notifyUsedImportsChanged(d->m_usedImportList);
}
}
+#endif
static bool compareVersions(const Import &import1, const Import &import2, bool allowHigherVersion)
{
@@ -1869,8 +1881,9 @@ QString Model::generateNewId(const QString &prefixName,
int counter = 0;
- QString newBaseId = QStringView(u"%1").arg(firstCharToLower(prefixName));
- newBaseId.remove(QRegularExpression(QStringLiteral("[^a-zA-Z0-9_]")));
+ static const QRegularExpression nonWordCharsRegex("\\W");
+ QString newBaseId = firstCharToLower(prefixName);
+ newBaseId.remove(nonWordCharsRegex);
if (!newBaseId.isEmpty()) {
QChar firstChar = newBaseId.at(0);
@@ -2021,14 +2034,6 @@ bool Model::isImportPossible(const Import &import, bool ignoreAlias, bool allowH
return false;
}
-QString Model::pathForImport(const Import &import)
-{
- if (!rewriterView())
- return QString();
-
- return rewriterView()->pathForImport(import);
-}
-
QStringList Model::importPaths() const
{
if (rewriterView())
@@ -2205,6 +2210,16 @@ NodeMetaInfo Model::qtQmlModelsListElementMetaInfo() const
}
}
+NodeMetaInfo Model::qtQmlXmlListModelXmlListModelRoleMetaInfo() const
+{
+ if constexpr (useProjectStorage()) {
+ using namespace Storage::Info;
+ return createNodeMetaInfo<QtQml_XmlListModel, XmlListModelRole>();
+ } else {
+ return metaInfo("QtQml.XmlListModel.XmlListModelRole");
+ }
+}
+
NodeMetaInfo Model::qmlQtObjectMetaInfo() const
{
if constexpr (useProjectStorage()) {
diff --git a/src/plugins/qmldesigner/designercore/model/modelresourcemanagement.cpp b/src/plugins/qmldesigner/designercore/model/modelresourcemanagement.cpp
index a61f1001f9..27ac2e67ab 100644
--- a/src/plugins/qmldesigner/designercore/model/modelresourcemanagement.cpp
+++ b/src/plugins/qmldesigner/designercore/model/modelresourcemanagement.cpp
@@ -515,8 +515,7 @@ struct BindingFilter
struct TargetFilter
{
TargetFilter(NodeDependencies &dependencies, Model *model)
- : flowViewFlowActionAreaMetaInfo{model->flowViewFlowActionAreaMetaInfo()}
- , flowViewFlowTransitionMetaInfo{model->flowViewFlowTransitionMetaInfo()}
+ : flowViewFlowTransitionMetaInfo{model->flowViewFlowTransitionMetaInfo()}
, qtQuickPropertyChangesMetaInfo{model->qtQuickPropertyChangesMetaInfo()}
, qtQuickTimelineKeyframeGroupMetaInfo{model->qtQuickTimelineKeyframeGroupMetaInfo()}
, qtQuickPropertyAnimationMetaInfo{model->qtQuickPropertyAnimationMetaInfo()}
diff --git a/src/plugins/qmldesigner/designercore/model/modelutils.cpp b/src/plugins/qmldesigner/designercore/model/modelutils.cpp
index cb3f482289..6c3e1ea50f 100644
--- a/src/plugins/qmldesigner/designercore/model/modelutils.cpp
+++ b/src/plugins/qmldesigner/designercore/model/modelutils.cpp
@@ -9,6 +9,8 @@
#include <projectstorage/projectstorage.h>
#include <projectstorage/sourcepathcache.h>
+#include <coreplugin/messagebox.h>
+
#include <utils/expected.h>
#include <utils/ranges.h>
@@ -107,19 +109,19 @@ PropertyMetaInfo metainfo(const ModelNode &node, const PropertyName &propertyNam
return node.metaInfo().property(propertyName);
}
-QString componentFilePath(const PathCacheType &pathCache, const NodeMetaInfo &metaInfo)
+QString componentFilePath([[maybe_unused]] const PathCacheType &pathCache, const NodeMetaInfo &metaInfo)
{
- if constexpr (useProjectStorage()) {
- auto typeSourceId = metaInfo.sourceId();
+#ifdef QDS_USE_PROJECTSTORAGE
+ auto typeSourceId = metaInfo.sourceId();
- if (typeSourceId && metaInfo.isFileComponent()) {
- return pathCache.sourcePath(typeSourceId).toQString();
- }
- } else {
- return metaInfo.componentFileName();
+ if (typeSourceId && metaInfo.isFileComponent()) {
+ return pathCache.sourcePath(typeSourceId).toQString();
}
return {};
+#else
+ return metaInfo.componentFileName();
+#endif
}
QString componentFilePath(const ModelNode &node)
diff --git a/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp
index 826856428b..6e3b739096 100644
--- a/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp
@@ -9,8 +9,9 @@
#include "bindingproperty.h"
#include "qmlanchors.h"
-#include <model.h>
#include <abstractview.h>
+#include <generatedcomponentutils.h>
+#include <model.h>
#include <coreplugin/icore.h>
@@ -196,7 +197,9 @@ QmlItemNode QmlItemNode::createQmlItemNodeForEffect(AbstractView *view,
auto createEffectNode = [=, &newQmlItemNode, &parentProperty]() {
const QString effectName = QFileInfo(effectPath).baseName();
- Import import = Import::createLibraryImport("Effects." + effectName, "1.0");
+ Import import = Import::createLibraryImport(GeneratedComponentUtils(view->externalDependencies())
+ .composedEffectsTypePrefix()
+ + '.' + effectName, "1.0");
try {
if (!view->model()->hasImport(import, true, true))
view->model()->changeImports({import}, {});
@@ -748,7 +751,6 @@ void QmlFlowActionAreaNode::assignTargetFlowItem(const QmlFlowTargetNode &flowIt
ModelNode transition = flowView.addTransition(flowParent.modelNode(),
flowItem.modelNode());
-
modelNode().bindingProperty("target").setExpression(transition.validId());
}
diff --git a/src/plugins/qmldesigner/designercore/model/rewriterview.cpp b/src/plugins/qmldesigner/designercore/model/rewriterview.cpp
index 4ae2261e60..17d40daca3 100644
--- a/src/plugins/qmldesigner/designercore/model/rewriterview.cpp
+++ b/src/plugins/qmldesigner/designercore/model/rewriterview.cpp
@@ -933,10 +933,12 @@ bool RewriterView::renameId(const QString& oldId, const QString& newId)
return false;
}
+#ifndef QDS_USE_PROJECTSTORAGE
const QmlJS::ScopeChain *RewriterView::scopeChain() const
{
return textToModelMerger()->scopeChain();
}
+#endif
const QmlJS::Document *RewriterView::document() const
{
@@ -989,25 +991,6 @@ QString RewriterView::convertTypeToImportAlias(const QString &type) const
return result;
}
-QString RewriterView::pathForImport(const Import &import)
-{
- if (scopeChain() && scopeChain()->context() && document()) {
- const QString importStr = import.isFileImport() ? import.file() : import.url();
- const QmlJS::Imports *imports = scopeChain()->context()->imports(document());
-
- QmlJS::ImportInfo importInfo;
-
- for (const QmlJS::Import &qmljsImport : imports->all()) {
- if (qmljsImport.info.name() == importStr)
- importInfo = qmljsImport.info;
- }
- const QString importPath = importInfo.path();
- return importPath;
- }
-
- return QString();
-}
-
QStringList RewriterView::importDirectories() const
{
const QList<Utils::FilePath> list(m_textToModelMerger->vContext().paths.begin(),
diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
index f7be6cf5e4..1c1aba5feb 100644
--- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
+++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
@@ -57,7 +57,7 @@ using namespace QmlJS;
using namespace Qt::StringLiterals;
static Q_LOGGING_CATEGORY(rewriterBenchmark, "qtc.rewriter.load", QtWarningMsg)
-static Q_LOGGING_CATEGORY(texttomodelMergerDebug, "qtc.texttomodelmerger.debug", QtDebugMsg)
+static Q_LOGGING_CATEGORY(texttomodelMergerLog, "qtc.texttomodelmerger", QtWarningMsg)
namespace {
@@ -67,17 +67,6 @@ bool isSupportedAttachedProperties(const QString &propertyName)
|| propertyName.startsWith(QLatin1String("InsightCategory."));
}
-bool isSupportedVersion(QmlDesigner::Version version)
-{
- if (version.major == 2)
- return version.minor <= 15;
-
- if (version.major == 6)
- return version.minor <= 6;
-
- return false;
-}
-
bool isGlobalQtEnums(QStringView value)
{
static constexpr auto list = Utils::to_array<std::u16string_view>(
@@ -95,6 +84,9 @@ bool isGlobalQtEnums(QStringView value)
u"TopToBottom", u"UpArrowCursor", u"Vertical", u"WaitCursor",
u"WhatsThisCursor", u"WheelFocus"});
+ if (value.toString().startsWith("Key_"))
+ return true;
+
return std::binary_search(std::begin(list),
std::end(list),
QmlDesigner::ModelUtils::toStdStringView(value));
@@ -122,12 +114,6 @@ bool isKnownEnumScopes(QStringView value)
!= std::end(list);
}
-bool supportedQtQuickVersion(const QmlDesigner::Import &import)
-{
- auto version = import.toVersion();
- return version.isEmpty() || isSupportedVersion(version);
-}
-
QString stripQuotes(const QString &str)
{
if ((str.startsWith(QLatin1Char('"')) && str.endsWith(QLatin1Char('"')))
@@ -431,14 +417,19 @@ namespace Internal {
class ReadingContext
{
public:
- ReadingContext(const Snapshot &snapshot, const Document::Ptr &doc,
- const ViewerContext &vContext, Model *model)
+ ReadingContext([[maybe_unused]] const Snapshot &snapshot,
+ [[maybe_unused]] const Document::Ptr &doc,
+ [[maybe_unused]] const ViewerContext &vContext,
+ Model *model)
: m_doc(doc)
+#ifndef QDS_USE_PROJECTSTORAGE
, m_context(
- Link(snapshot, vContext, ModelManagerInterface::instance()->builtins(doc))
- (doc, &m_diagnosticLinkMessages))
+ Link(snapshot,
+ vContext,
+ ModelManagerInterface::instance()->builtins(doc))(doc, &m_diagnosticLinkMessages))
, m_scopeChain(doc, m_context)
, m_scopeBuilder(&m_scopeChain)
+#endif
, m_model(model)
{
}
@@ -446,12 +437,19 @@ public:
~ReadingContext() = default;
Document::Ptr doc() const
- { return m_doc; }
+ {
+ return m_doc;
+ }
+#ifndef QDS_USE_PROJECTSTORAGE
void enterScope(AST::Node *node)
{ m_scopeBuilder.push(node); }
- void leaveScope() { m_scopeBuilder.pop(); }
+ void leaveScope()
+ {
+ m_scopeBuilder.pop();
+ }
+#endif
std::tuple<NodeMetaInfo, TypeName> lookup(AST::UiQualifiedId *astTypeNode)
{
@@ -481,113 +479,6 @@ public:
return node.metaInfo().hasProperty(propertyName.toUtf8());
}
- /// When something is changed here, also change Check::checkScopeObjectMember in
- /// qmljscheck.cpp
- /// ### Maybe put this into the context as a helper function.
- ///
- bool lookupProperty(const QString &prefix,
- const AST::UiQualifiedId *id,
- const Value **property = nullptr,
- const ObjectValue **parentObject = nullptr,
- QString *name = nullptr)
- {
- QList<const ObjectValue *> scopeObjects = m_scopeChain.qmlScopeObjects();
- if (scopeObjects.isEmpty())
- return false;
-
- if (!id)
- return false; // ### error?
-
- if (id->name.isEmpty()) // possible after error recovery
- return false;
-
- QString propertyName;
- if (prefix.isEmpty())
- propertyName = id->name.toString();
- else
- propertyName = prefix;
-
- if (name)
- *name = propertyName;
-
- if (propertyName == u"id" && !id->next)
- return false; // ### should probably be a special value
-
- // attached properties
- bool isAttachedProperty = false;
- if (! propertyName.isEmpty() && propertyName[0].isUpper()) {
- isAttachedProperty = true;
- if (const ObjectValue *qmlTypes = m_scopeChain.qmlTypes())
- scopeObjects += qmlTypes;
- }
-
- if (scopeObjects.isEmpty())
- return false;
-
- // global lookup for first part of id
- const ObjectValue *objectValue = nullptr;
- const Value *value = nullptr;
- for (int i = scopeObjects.size() - 1; i >= 0; --i) {
- objectValue = scopeObjects[i];
- value = objectValue->lookupMember(propertyName, m_context);
- if (value)
- break;
- }
- if (parentObject)
- *parentObject = objectValue;
- if (!value) {
- qCInfo(texttomodelMergerDebug) << Q_FUNC_INFO << "Skipping invalid property name" << propertyName;
- return false;
- }
-
- // can't look up members for attached properties
- if (isAttachedProperty)
- return false;
-
- // resolve references
- if (const Reference *ref = value->asReference())
- value = m_context->lookupReference(ref);
-
- // member lookup
- const AST::UiQualifiedId *idPart = id;
- if (prefix.isEmpty())
- idPart = idPart->next;
- for (; idPart; idPart = idPart->next) {
- objectValue = value_cast<ObjectValue>(value);
- if (! objectValue) {
-// if (idPart->name)
-// qDebug() << idPart->name->asString() << "has no property named"
-// << propertyName;
- return false;
- }
- if (parentObject)
- *parentObject = objectValue;
-
- if (idPart->name.isEmpty()) {
- // somebody typed "id." and error recovery still gave us a valid tree,
- // so just bail out here.
- return false;
- }
-
- propertyName = idPart->name.toString();
- if (name)
- *name = propertyName;
-
- value = objectValue->lookupMember(propertyName, m_context);
- if (! value) {
-// if (idPart->name)
-// qDebug() << "In" << idPart->name->asString() << ":"
-// << objectValue->className() << "has no property named"
-// << propertyName;
- return false;
- }
- }
-
- if (property)
- *property = value;
- return true;
- }
-
bool isArrayProperty(const AbstractProperty &property)
{
return ModelUtils::metainfo(property).isListProperty();
@@ -610,9 +501,9 @@ public:
if (!propertyMetaInfo.isValid()) {
const bool isAttached = !propertyName.isEmpty() && propertyName[0].isUpper();
// Only list elements might have unknown properties.
- if (!node.metaInfo().isQtQuickListElement() && !isAttached) {
- qCInfo(texttomodelMergerDebug)
- << Q_FUNC_INFO << "Unknown property"
+ if (!node.metaInfo().isQtQmlModelsListElement() && !isAttached) {
+ qCInfo(texttomodelMergerLog)
+ << Q_FUNC_INFO << "\nUnknown property"
<< propertyPrefix + QLatin1Char('.') + toString(propertyId) << "on line"
<< propertyId->identifierToken.startLine << "column"
<< propertyId->identifierToken.startColumn;
@@ -685,9 +576,12 @@ public:
return QVariant();
}
-
+#ifndef QDS_USE_PROJECTSTORAGE
const ScopeChain &scopeChain() const
- { return m_scopeChain; }
+ {
+ return m_scopeChain;
+ }
+#endif
QList<DiagnosticMessage> diagnosticLinkMessages() const
{ return m_diagnosticLinkMessages; }
@@ -695,9 +589,11 @@ public:
private:
Document::Ptr m_doc;
QList<DiagnosticMessage> m_diagnosticLinkMessages;
+#ifndef QDS_USE_PROJECTSTORAGE
ContextPtr m_context;
ScopeChain m_scopeChain;
ScopeBuilder m_scopeBuilder;
+#endif
Model *m_model;
};
@@ -841,6 +737,7 @@ constexpr auto skipModules = std::make_tuple(EndsWith(u".impl"),
Equals(u"QtQuick.Controls.NativeStyle"),
Equals(u"QtQuick.Controls.Universal"),
Equals(u"QtQuick.Controls.Windows"),
+ Equals(u"QtQuick3D.MaterialEditor"),
StartsWith(u"QtQuick.LocalStorage"),
StartsWith(u"QtQuick.NativeStyle"),
StartsWith(u"QtQuick.Pdf"),
@@ -866,6 +763,7 @@ constexpr auto skipModules = std::make_tuple(EndsWith(u".impl"),
StartsWith(u"QtWebSockets"),
StartsWith(u"QtWebView"));
+#ifndef QDS_USE_PROJECTSTORAGE
bool skipModule(QStringView moduleName)
{
return std::apply([=](const auto &...skipModule) { return (skipModule(moduleName) || ...); },
@@ -931,9 +829,11 @@ QmlDesigner::Imports createQt5Modules()
QmlDesigner::Import::createLibraryImport("QtQuick.Studio.MultiText", "1.0"),
QmlDesigner::Import::createLibraryImport("Qt.SafeRenderer", "2.0")};
}
+#endif
} // namespace
+#ifndef QDS_USE_PROJECTSTORAGE
void TextToModelMerger::setupPossibleImports()
{
if (!m_rewriterView->possibleImportsEnabled())
@@ -942,10 +842,10 @@ void TextToModelMerger::setupPossibleImports()
static QUrl lastProjectUrl;
auto &externalDependencies = m_rewriterView->externalDependencies();
auto projectUrl = externalDependencies.projectUrl();
+
auto allUsedImports = m_scopeChain->context()->imports(m_document.data())->all();
if (m_possibleModules.isEmpty() || projectUrl != lastProjectUrl) {
-
auto &externalDependencies = m_rewriterView->externalDependencies();
if (externalDependencies.isQt6Project()) {
ModuleScanner moduleScanner{[&](QStringView moduleName) {
@@ -975,7 +875,9 @@ void TextToModelMerger::setupPossibleImports()
if (m_rewriterView->isAttached())
m_rewriterView->model()->setPossibleImports(modules);
}
+#endif
+#ifndef QDS_USE_PROJECTSTORAGE
void TextToModelMerger::setupUsedImports()
{
const QmlJS::Imports *imports = m_scopeChain->context()->imports(m_document.data());
@@ -1010,6 +912,7 @@ void TextToModelMerger::setupUsedImports()
if (m_rewriterView->isAttached())
m_rewriterView->model()->setUsedImports(usedImports);
}
+#endif
Document::MutablePtr TextToModelMerger::createParsedDocument(const QUrl &url, const QString &data, QList<DocumentMessage> *errors)
{
@@ -1100,15 +1003,16 @@ bool TextToModelMerger::load(const QString &data, DifferenceHandler &differenceH
m_vContext = ModelManagerInterface::instance()->projectVContext(Dialect::Qml, m_document);
ReadingContext ctxt(snapshot, m_document, m_vContext, m_rewriterView->model());
- m_scopeChain = QSharedPointer<const ScopeChain>(
- new ScopeChain(ctxt.scopeChain()));
+
+#ifndef QDS_USE_PROJECTSTORAGE
+ m_scopeChain = QSharedPointer<const ScopeChain>(new ScopeChain(ctxt.scopeChain()));
if (view()->checkLinkErrors()) {
qCInfo(rewriterBenchmark) << "linked:" << time.elapsed();
collectLinkErrors(&errors, ctxt);
}
-
setupPossibleImports();
+#endif
qCInfo(rewriterBenchmark) << "possible imports:" << time.elapsed();
@@ -1142,7 +1046,9 @@ bool TextToModelMerger::load(const QString &data, DifferenceHandler &differenceH
qCInfo(rewriterBenchmark) << "synced nodes:" << time.elapsed();
+#ifndef QDS_USE_PROJECTSTORAGE
setupUsedImports();
+#endif
setActive(false);
@@ -1239,8 +1145,9 @@ void TextToModelMerger::syncNode(ModelNode &modelNode,
else if (!modelNode.nodeSource().isEmpty() || modelNode.nodeSourceType() != ModelNode::NodeWithoutSource)
clearImplicitComponentDelayed(modelNode, differenceHandler.isAmender());
-
+#ifndef QDS_USE_PROJECTSTORAGE
context->enterScope(astNode);
+#endif
QSet<PropertyName> modelPropertyNames = Utils::toSet(modelNode.propertyNames());
if (!modelNode.id().isEmpty())
@@ -1254,7 +1161,8 @@ void TextToModelMerger::syncNode(ModelNode &modelNode,
if (auto array = AST::cast<AST::UiArrayBinding *>(member)) {
const QString astPropertyName = toString(array->qualifiedId);
- if (isPropertyChangesType(typeName) || isConnectionsType(typeName) || context->lookupProperty(QString(), array->qualifiedId)) {
+ if (isPropertyChangesType(typeName) || isConnectionsType(typeName)
+ || modelNode.metaInfo().hasProperty(astPropertyName.toUtf8())) {
AbstractProperty modelProperty = modelNode.property(astPropertyName.toUtf8());
QList<AST::UiObjectMember *> arrayMembers;
for (AST::UiArrayMemberList *iter = array->members; iter; iter = iter->next)
@@ -1286,13 +1194,8 @@ void TextToModelMerger::syncNode(ModelNode &modelNode,
// Store Behaviours in the default property
defaultPropertyItems.append(member);
} else {
- const Value *propertyType = nullptr;
- const ObjectValue *containingObject = nullptr;
- if (context->lookupProperty({},
- binding->qualifiedId,
- &propertyType,
- &containingObject)
- || isPropertyChangesType(typeName) || isConnectionsType(typeName)) {
+ if (isPropertyChangesType(typeName) || isConnectionsType(typeName)
+ || modelNode.metaInfo().hasProperty(astPropertyName.toUtf8())) {
AbstractProperty modelProperty = modelNode.property(astPropertyName.toUtf8());
if (context->isArrayProperty(modelProperty))
syncArrayProperty(modelProperty, {member}, context, differenceHandler);
@@ -1396,7 +1299,9 @@ void TextToModelMerger::syncNode(ModelNode &modelNode,
differenceHandler.propertyAbsentFromQml(modelProperty);
}
+#ifndef QDS_USE_PROJECTSTORAGE
context->leaveScope();
+#endif
}
static QVariant parsePropertyExpression(AST::ExpressionNode *expressionNode)
@@ -1476,9 +1381,8 @@ QmlDesigner::PropertyName TextToModelMerger::syncScriptBinding(ModelNode &modelN
}
if (isLiteralValue(script)) {
- if (isPropertyChangesType(modelNode.type())
- || isConnectionsType(modelNode.type())
- || isListElementType(modelNode.type())) {
+ if (isPropertyChangesType(modelNode.type()) || isConnectionsType(modelNode.type())
+ || isListElementType(modelNode.type())) {
AbstractProperty modelProperty = modelNode.property(astPropertyName.toUtf8());
QVariant variantValue = parsePropertyScriptBinding(script);
if (!variantValue.isValid())
@@ -1512,15 +1416,14 @@ QmlDesigner::PropertyName TextToModelMerger::syncScriptBinding(ModelNode &modelN
syncVariantProperty(modelProperty, enumValue, TypeName(), differenceHandler); // TODO: parse type
return astPropertyName.toUtf8();
} else { // Not an enum, so:
- if (isPropertyChangesType(modelNode.type())
- || isConnectionsType(modelNode.type())
- || context->lookupProperty(prefix, script->qualifiedId)
- || isSupportedAttachedProperties(astPropertyName)) {
+ if (isPropertyChangesType(modelNode.type()) || isConnectionsType(modelNode.type())
+ || isSupportedAttachedProperties(astPropertyName)
+ || modelNode.metaInfo().hasProperty(astPropertyName.toUtf8())) {
AbstractProperty modelProperty = modelNode.property(astPropertyName.toUtf8());
syncExpressionProperty(modelProperty, astValue, TypeName(), differenceHandler); // TODO: parse type
return astPropertyName.toUtf8();
} else {
- qWarning() << Q_FUNC_INFO << "Skipping invalid expression property" << astPropertyName
+ qCInfo(texttomodelMergerLog) << Q_FUNC_INFO << "\nSkipping invalid expression property" << astPropertyName
<< "for node type" << modelNode.type();
return PropertyName();
}
@@ -2232,42 +2135,31 @@ void TextToModelMerger::collectImportErrors(QList<DocumentMessage> *errors)
bool hasQtQuick = false;
for (const QmlDesigner::Import &import : m_rewriterView->model()->imports()) {
if (import.isLibraryImport() && import.url() == u"QtQuick") {
- if (supportedQtQuickVersion(import)) {
- hasQtQuick = true;
-
- auto &externalDependencies = m_rewriterView->externalDependencies();
- if (externalDependencies.hasStartupTarget()) {
- const bool qt6import = !import.hasVersion() || import.majorVersion() == 6;
-
- if (!externalDependencies.isQt6Import() && (m_hasVersionlessImport || qt6import)) {
- const QmlJS::DiagnosticMessage diagnosticMessage(
- QmlJS::Severity::Error,
- SourceLocation(0, 0, 0, 0),
- QCoreApplication::translate(
- "QmlDesigner::TextToModelMerger",
- "Qt Quick 6 is not supported with a Qt 5 kit."));
- errors->prepend(
- DocumentMessage(diagnosticMessage,
- QUrl::fromLocalFile(m_document->fileName().path())));
- }
- } else {
+ hasQtQuick = true;
+
+ auto &externalDependencies = m_rewriterView->externalDependencies();
+ if (externalDependencies.hasStartupTarget()) {
+ const bool qt6import = !import.hasVersion() || import.majorVersion() == 6;
+
+ if (!externalDependencies.isQt6Import() && (m_hasVersionlessImport || qt6import)) {
const QmlJS::DiagnosticMessage diagnosticMessage(
QmlJS::Severity::Error,
SourceLocation(0, 0, 0, 0),
- QCoreApplication::translate("QmlDesigner::TextToModelMerger",
- "The Design Mode requires a valid Qt kit."));
+ QCoreApplication::translate(
+ "QmlDesigner::TextToModelMerger",
+ "Qt Quick 6 is not supported with a Qt 5 kit."));
errors->prepend(
DocumentMessage(diagnosticMessage,
QUrl::fromLocalFile(m_document->fileName().path())));
}
} else {
- const QmlJS::DiagnosticMessage
- diagnosticMessage(QmlJS::Severity::Error,
- SourceLocation(0, 0, 0, 0),
- QCoreApplication::translate("QmlDesigner::TextToModelMerger",
- "Unsupported Qt Quick version."));
- errors->append(DocumentMessage(diagnosticMessage,
- QUrl::fromLocalFile(m_document->fileName().path())));
+ const QmlJS::DiagnosticMessage diagnosticMessage(
+ QmlJS::Severity::Error,
+ SourceLocation(0, 0, 0, 0),
+ QCoreApplication::translate("QmlDesigner::TextToModelMerger",
+ "The Design Mode requires a valid Qt kit."));
+ errors->prepend(DocumentMessage(diagnosticMessage,
+ QUrl::fromLocalFile(m_document->fileName().path())));
}
}
}
@@ -2276,8 +2168,10 @@ void TextToModelMerger::collectImportErrors(QList<DocumentMessage> *errors)
errors->append(DocumentMessage(QCoreApplication::translate("QmlDesigner::TextToModelMerger", "No import for Qt Quick found.")));
}
-void TextToModelMerger::collectSemanticErrorsAndWarnings(QList<DocumentMessage> *errors, QList<DocumentMessage> *warnings)
+void TextToModelMerger::collectSemanticErrorsAndWarnings(
+ [[maybe_unused]] QList<DocumentMessage> *errors, [[maybe_unused]] QList<DocumentMessage> *warnings)
{
+#ifndef QDS_USE_PROJECTSTORAGE
Check check(m_document, m_scopeChain->context());
check.disableMessage(StaticAnalysis::ErrPrototypeCycle);
check.disableMessage(StaticAnalysis::ErrCouldNotResolvePrototype);
@@ -2306,6 +2200,7 @@ void TextToModelMerger::collectSemanticErrorsAndWarnings(QList<DocumentMessage>
if (message.severity == Severity::Warning)
warnings->append(DocumentMessage(message.toDiagnosticMessage(), fileNameUrl));
}
+#endif
}
void TextToModelMerger::populateQrcMapping(const QString &filePath)
@@ -2410,6 +2305,9 @@ QSet<QPair<QString, QString> > TextToModelMerger::qrcMapping() const
QList<QmlTypeData> TextToModelMerger::getQMLSingletons() const
{
+#ifdef QDS_USE_PROJECTSTORAGE
+ return {};
+#else
QList<QmlTypeData> list;
if (!m_scopeChain || !m_scopeChain->document())
return list;
@@ -2440,6 +2338,7 @@ QList<QmlTypeData> TextToModelMerger::getQMLSingletons() const
}
}
return list;
+#endif
}
void TextToModelMerger::clearPossibleImportKeys()
diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h
index f511906040..e22f747718 100644
--- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h
+++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h
@@ -37,15 +37,19 @@ public:
bool isActive() const;
void setupImports(const QmlJS::Document::Ptr &doc, DifferenceHandler &differenceHandler);
+#ifndef QDS_USE_PROJECTSTORAGE
void setupPossibleImports();
+#endif
void setupUsedImports();
bool load(const QString &data, DifferenceHandler &differenceHandler);
RewriterView *view() const
{ return m_rewriterView; }
+#ifndef QDS_USE_PROJECTSTORAGE
const QmlJS::ScopeChain *scopeChain() const
{ return m_scopeChain.data(); }
+#endif
const QmlJS::Document *document() const
{ return m_document.data(); }
@@ -141,7 +145,9 @@ private:
private:
RewriterView *m_rewriterView;
bool m_isActive;
+#ifndef QDS_USE_PROJECTSTORAGE
QSharedPointer<const QmlJS::ScopeChain> m_scopeChain;
+#endif
QmlJS::Document::Ptr m_document;
QTimer m_setupTimer;
QSet<ModelNode> m_setupComponentList;
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/commontypecache.h b/src/plugins/qmldesigner/designercore/projectstorage/commontypecache.h
index 03c25dfac7..35658c005f 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/commontypecache.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/commontypecache.h
@@ -91,6 +91,7 @@ inline constexpr char QtMultimedia[] = "QtMultimedia";
inline constexpr char QtObject[] = "QtObject";
inline constexpr char QtQml[] = "QtQml";
inline constexpr char QtQml_Models[] = "QtQml.Models";
+inline constexpr char QtQml_XmlListModel[] = "QtQml.XmlListModel";
inline constexpr char QtQuick3D[] = "QtQuick3D";
inline constexpr char QtQuick3D_Particles3D[] = "QtQuick3D.Particles3D";
inline constexpr char QtQuick3D_Particles3D_cppnative[] = "QtQuick3D.Particles3D-cppnative";
@@ -131,6 +132,7 @@ inline constexpr char Transition[] = "Transition";
inline constexpr char UIntType[] = "uint";
inline constexpr char View3D[] = "View3D";
inline constexpr char Window[] = "Window";
+inline constexpr char XmlListModelRole[] = "XmlListModelRole";
inline constexpr char color[] = "color";
inline constexpr char date[] = "date";
inline constexpr char font[] = "font";
@@ -176,6 +178,7 @@ class CommonTypeCache
CacheType<QtMultimedia, SoundEffect>,
CacheType<QtQml_Models, ListElement>,
CacheType<QtQml_Models, ListModel>,
+ CacheType<QtQml_XmlListModel, XmlListModelRole>,
CacheType<QtQuick, BorderImage>,
CacheType<QtQuick, GridView>,
CacheType<QtQuick, Image>,
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/filestatus.h b/src/plugins/qmldesigner/designercore/projectstorage/filestatus.h
index f3e275b8f3..48b3ba2700 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/filestatus.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/filestatus.h
@@ -50,6 +50,18 @@ public:
explicit operator bool() const { return isValid(); }
+ template<typename String>
+ friend void convertToString(String &string, const FileStatus &fileStatus)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("source id", fileStatus.sourceId),
+ keyValue("size", fileStatus.size),
+ keyValue("last modified", fileStatus.lastModified));
+
+ convertToString(string, dict);
+ }
+
public:
SourceId sourceId;
long long size = -1;
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/filesystem.h b/src/plugins/qmldesigner/designercore/projectstorage/filesystem.h
index 078fd1ee98..28754a8560 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/filesystem.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/filesystem.h
@@ -6,6 +6,7 @@
#include "filestatuscache.h"
#include "filesysteminterface.h"
#include "nonlockingmutex.h"
+#include "projectstoragefwd.h"
namespace Sqlite {
class Database;
@@ -16,12 +17,9 @@ namespace QmlDesigner {
template<typename ProjectStorage, typename Mutex>
class SourcePathCache;
-template<typename Database>
-class ProjectStorage;
-
class FileSystem : public FileSystemInterface
{
- using PathCache = SourcePathCache<ProjectStorage<Sqlite::Database>, NonLockingMutex>;
+ using PathCache = SourcePathCache<ProjectStorage, NonLockingMutex>;
public:
FileSystem(PathCache &sourcePathCache)
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.cpp b/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.cpp
index 3e493e8772..a7577d3ab7 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.cpp
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.cpp
@@ -3,20 +3,4542 @@
#include "projectstorage.h"
-#include <tracing/qmldesignertracing.h>
-
#include <sqlitedatabase.h>
namespace QmlDesigner {
-NanotraceHR::StringViewCategory<projectStorageTracingStatus()> &projectStorageCategory()
+struct ProjectStorage::Statements
+{
+ Statements(Sqlite::Database &database)
+ : database{database}
+ {}
+
+ Sqlite::Database &database;
+ Sqlite::ReadWriteStatement<1, 2> insertTypeStatement{
+ "INSERT OR IGNORE INTO types(sourceId, name) VALUES(?1, ?2) RETURNING typeId", database};
+ Sqlite::WriteStatement<5> updatePrototypeAndExtensionStatement{
+ "UPDATE types SET prototypeId=?2, prototypeNameId=?3, extensionId=?4, extensionNameId=?5 "
+ "WHERE typeId=?1 AND (prototypeId IS NOT ?2 OR extensionId IS NOT ?3 AND prototypeId "
+ "IS NOT ?4 OR extensionNameId IS NOT ?5)",
+ database};
+ mutable Sqlite::ReadStatement<1, 1> selectTypeIdByExportedNameStatement{
+ "SELECT typeId FROM exportedTypeNames WHERE name=?1", database};
+ mutable Sqlite::ReadStatement<1, 2> selectTypeIdByModuleIdAndExportedNameStatement{
+ "SELECT typeId FROM exportedTypeNames "
+ "WHERE moduleId=?1 AND name=?2 "
+ "ORDER BY majorVersion DESC, minorVersion DESC "
+ "LIMIT 1",
+ database};
+ mutable Sqlite::ReadStatement<1, 3> selectTypeIdByModuleIdAndExportedNameAndMajorVersionStatement{
+ "SELECT typeId FROM exportedTypeNames "
+ "WHERE moduleId=?1 AND name=?2 AND majorVersion=?3"
+ "ORDER BY minorVersion DESC "
+ "LIMIT 1",
+ database};
+ mutable Sqlite::ReadStatement<1, 4> selectTypeIdByModuleIdAndExportedNameAndVersionStatement{
+ "SELECT typeId FROM exportedTypeNames "
+ "WHERE moduleId=?1 AND name=?2 AND majorVersion=?3 AND minorVersion<=?4"
+ "ORDER BY minorVersion DESC "
+ "LIMIT 1",
+ database};
+ mutable Sqlite::ReadStatement<3, 1> selectPropertyDeclarationResultByPropertyDeclarationIdStatement{
+ "SELECT propertyTypeId, propertyDeclarationId, propertyTraits "
+ "FROM propertyDeclarations "
+ "WHERE propertyDeclarationId=?1 "
+ "LIMIT 1",
+ database};
+ mutable Sqlite::ReadStatement<1, 1> selectSourceContextIdFromSourceContextsBySourceContextPathStatement{
+ "SELECT sourceContextId FROM sourceContexts WHERE sourceContextPath = ?", database};
+ mutable Sqlite::ReadStatement<1, 1> selectSourceContextPathFromSourceContextsBySourceContextIdStatement{
+ "SELECT sourceContextPath FROM sourceContexts WHERE sourceContextId = ?", database};
+ mutable Sqlite::ReadStatement<2> selectAllSourceContextsStatement{
+ "SELECT sourceContextPath, sourceContextId FROM sourceContexts", database};
+ Sqlite::WriteStatement<1> insertIntoSourceContextsStatement{
+ "INSERT INTO sourceContexts(sourceContextPath) VALUES (?)", database};
+ mutable Sqlite::ReadStatement<1, 2> selectSourceIdFromSourcesBySourceContextIdAndSourceNameStatement{
+ "SELECT sourceId FROM sources WHERE sourceContextId = ? AND sourceName = ?", database};
+ mutable Sqlite::ReadStatement<2, 1> selectSourceNameAndSourceContextIdFromSourcesBySourceIdStatement{
+ "SELECT sourceName, sourceContextId FROM sources WHERE sourceId = ?", database};
+ mutable Sqlite::ReadStatement<1, 1> selectSourceContextIdFromSourcesBySourceIdStatement{
+ "SELECT sourceContextId FROM sources WHERE sourceId = ?", database};
+ Sqlite::WriteStatement<2> insertIntoSourcesStatement{
+ "INSERT INTO sources(sourceContextId, sourceName) VALUES (?,?)", database};
+ mutable Sqlite::ReadStatement<3> selectAllSourcesStatement{
+ "SELECT sourceName, sourceContextId, sourceId FROM sources", database};
+ mutable Sqlite::ReadStatement<8, 1> selectTypeByTypeIdStatement{
+ "SELECT sourceId, t.name, t.typeId, prototypeId, extensionId, traits, annotationTraits, "
+ "pd.name "
+ "FROM types AS t LEFT JOIN propertyDeclarations AS pd ON "
+ "defaultPropertyId=propertyDeclarationId "
+ "WHERE t.typeId=?",
+ database};
+ mutable Sqlite::ReadStatement<4, 1> selectExportedTypesByTypeIdStatement{
+ "SELECT moduleId, name, ifnull(majorVersion, -1), ifnull(minorVersion, -1) FROM "
+ "exportedTypeNames WHERE typeId=?",
+ database};
+ mutable Sqlite::ReadStatement<4, 2> selectExportedTypesByTypeIdAndSourceIdStatement{
+ "SELECT etn.moduleId, name, ifnull(etn.majorVersion, -1), ifnull(etn.minorVersion, -1) "
+ "FROM exportedTypeNames AS etn JOIN documentImports USING(moduleId) WHERE typeId=?1 AND "
+ "sourceId=?2",
+ database};
+ mutable Sqlite::ReadStatement<8> selectTypesStatement{
+ "SELECT sourceId, t.name, t.typeId, prototypeId, extensionId, traits, annotationTraits, "
+ "pd.name "
+ "FROM types AS t LEFT JOIN propertyDeclarations AS pd ON "
+ "defaultPropertyId=propertyDeclarationId",
+ database};
+ Sqlite::WriteStatement<2> updateTypeTraitStatement{
+ "UPDATE types SET traits = ?2 WHERE typeId=?1", database};
+ Sqlite::WriteStatement<2> updateTypeAnnotationTraitStatement{
+ "UPDATE types SET annotationTraits = ?2 WHERE typeId=?1", database};
+ Sqlite::ReadStatement<1, 2> selectNotUpdatedTypesInSourcesStatement{
+ "SELECT DISTINCT typeId FROM types WHERE (sourceId IN carray(?1) AND typeId NOT IN "
+ "carray(?2))",
+ database};
+ Sqlite::WriteStatement<1> deleteTypeNamesByTypeIdStatement{
+ "DELETE FROM exportedTypeNames WHERE typeId=?", database};
+ Sqlite::WriteStatement<1> deleteEnumerationDeclarationByTypeIdStatement{
+ "DELETE FROM enumerationDeclarations WHERE typeId=?", database};
+ Sqlite::WriteStatement<1> deletePropertyDeclarationByTypeIdStatement{
+ "DELETE FROM propertyDeclarations WHERE typeId=?", database};
+ Sqlite::WriteStatement<1> deleteFunctionDeclarationByTypeIdStatement{
+ "DELETE FROM functionDeclarations WHERE typeId=?", database};
+ Sqlite::WriteStatement<1> deleteSignalDeclarationByTypeIdStatement{
+ "DELETE FROM signalDeclarations WHERE typeId=?", database};
+ Sqlite::WriteStatement<1> deleteTypeStatement{"DELETE FROM types WHERE typeId=?", database};
+ mutable Sqlite::ReadStatement<4, 1> selectPropertyDeclarationsByTypeIdStatement{
+ "SELECT name, propertyTypeId, propertyTraits, (SELECT name FROM "
+ "propertyDeclarations WHERE propertyDeclarationId=pd.aliasPropertyDeclarationId) FROM "
+ "propertyDeclarations AS pd WHERE typeId=?",
+ database};
+ Sqlite::ReadStatement<6, 1> selectPropertyDeclarationsForTypeIdStatement{
+ "SELECT name, propertyTraits, propertyTypeId, propertyImportedTypeNameId, "
+ "propertyDeclarationId, aliasPropertyDeclarationId FROM propertyDeclarations "
+ "WHERE typeId=? ORDER BY name",
+ database};
+ Sqlite::ReadWriteStatement<1, 5> insertPropertyDeclarationStatement{
+ "INSERT INTO propertyDeclarations(typeId, name, propertyTypeId, propertyTraits, "
+ "propertyImportedTypeNameId, aliasPropertyDeclarationId) VALUES(?1, ?2, ?3, ?4, ?5, NULL) "
+ "RETURNING propertyDeclarationId",
+ database};
+ Sqlite::WriteStatement<4> updatePropertyDeclarationStatement{
+ "UPDATE propertyDeclarations SET propertyTypeId=?2, propertyTraits=?3, "
+ "propertyImportedTypeNameId=?4, aliasPropertyDeclarationId=NULL WHERE "
+ "propertyDeclarationId=?1",
+ database};
+ Sqlite::WriteStatement<3> updatePropertyAliasDeclarationRecursivelyWithTypeAndTraitsStatement{
+ "WITH RECURSIVE "
+ " properties(aliasPropertyDeclarationId) AS ( "
+ " SELECT propertyDeclarationId FROM propertyDeclarations WHERE "
+ " aliasPropertyDeclarationId=?1 "
+ " UNION ALL "
+ " SELECT pd.propertyDeclarationId FROM "
+ " propertyDeclarations AS pd JOIN properties USING(aliasPropertyDeclarationId)) "
+ "UPDATE propertyDeclarations AS pd "
+ "SET propertyTypeId=?2, propertyTraits=?3 "
+ "FROM properties AS p "
+ "WHERE pd.propertyDeclarationId=p.aliasPropertyDeclarationId",
+ database};
+ Sqlite::WriteStatement<1> updatePropertyAliasDeclarationRecursivelyStatement{
+ "WITH RECURSIVE "
+ " propertyValues(propertyTypeId, propertyTraits) AS ("
+ " SELECT propertyTypeId, propertyTraits FROM propertyDeclarations "
+ " WHERE propertyDeclarationId=?1), "
+ " properties(aliasPropertyDeclarationId) AS ( "
+ " SELECT propertyDeclarationId FROM propertyDeclarations WHERE "
+ " aliasPropertyDeclarationId=?1 "
+ " UNION ALL "
+ " SELECT pd.propertyDeclarationId FROM "
+ " propertyDeclarations AS pd JOIN properties USING(aliasPropertyDeclarationId)) "
+ "UPDATE propertyDeclarations AS pd "
+ "SET propertyTypeId=pv.propertyTypeId, propertyTraits=pv.propertyTraits "
+ "FROM properties AS p, propertyValues AS pv "
+ "WHERE pd.propertyDeclarationId=p.aliasPropertyDeclarationId",
+ database};
+ Sqlite::WriteStatement<1> deletePropertyDeclarationStatement{
+ "DELETE FROM propertyDeclarations WHERE propertyDeclarationId=?", database};
+ Sqlite::ReadStatement<3, 1> selectPropertyDeclarationsWithAliasForTypeIdStatement{
+ "SELECT name, propertyDeclarationId, aliasPropertyDeclarationId FROM propertyDeclarations "
+ "WHERE typeId=? AND aliasPropertyDeclarationId IS NOT NULL ORDER BY name",
+ database};
+ Sqlite::WriteStatement<5> updatePropertyDeclarationWithAliasAndTypeStatement{
+ "UPDATE propertyDeclarations SET propertyTypeId=?2, propertyTraits=?3, "
+ "propertyImportedTypeNameId=?4, aliasPropertyDeclarationId=?5 WHERE "
+ "propertyDeclarationId=?1",
+ database};
+ Sqlite::ReadWriteStatement<1, 2> insertAliasPropertyDeclarationStatement{
+ "INSERT INTO propertyDeclarations(typeId, name) VALUES(?1, ?2) RETURNING "
+ "propertyDeclarationId",
+ database};
+ mutable Sqlite::ReadStatement<4, 1> selectFunctionDeclarationsForTypeIdStatement{
+ "SELECT name, returnTypeName, signature, functionDeclarationId FROM "
+ "functionDeclarations WHERE typeId=? ORDER BY name, signature",
+ database};
+ mutable Sqlite::ReadStatement<3, 1> selectFunctionDeclarationsForTypeIdWithoutSignatureStatement{
+ "SELECT name, returnTypeName, functionDeclarationId FROM "
+ "functionDeclarations WHERE typeId=? ORDER BY name",
+ database};
+ mutable Sqlite::ReadStatement<3, 1> selectFunctionParameterDeclarationsStatement{
+ "SELECT json_extract(json_each.value, '$.n'), json_extract(json_each.value, '$.tn'), "
+ "json_extract(json_each.value, '$.tr') FROM functionDeclarations, "
+ "json_each(functionDeclarations.signature) WHERE functionDeclarationId=?",
+ database};
+ Sqlite::WriteStatement<4> insertFunctionDeclarationStatement{
+ "INSERT INTO functionDeclarations(typeId, name, returnTypeName, signature) VALUES(?1, ?2, "
+ "?3, ?4)",
+ database};
+ Sqlite::WriteStatement<3> updateFunctionDeclarationStatement{
+ "UPDATE functionDeclarations "
+ "SET returnTypeName=?2, signature=?3 "
+ "WHERE functionDeclarationId=?1",
+ database};
+ Sqlite::WriteStatement<1> deleteFunctionDeclarationStatement{
+ "DELETE FROM functionDeclarations WHERE functionDeclarationId=?", database};
+ mutable Sqlite::ReadStatement<3, 1> selectSignalDeclarationsForTypeIdStatement{
+ "SELECT name, signature, signalDeclarationId FROM signalDeclarations WHERE typeId=? ORDER "
+ "BY name, signature",
+ database};
+ mutable Sqlite::ReadStatement<2, 1> selectSignalDeclarationsForTypeIdWithoutSignatureStatement{
+ "SELECT name, signalDeclarationId FROM signalDeclarations WHERE typeId=? ORDER BY name",
+ database};
+ mutable Sqlite::ReadStatement<3, 1> selectSignalParameterDeclarationsStatement{
+ "SELECT json_extract(json_each.value, '$.n'), json_extract(json_each.value, '$.tn'), "
+ "json_extract(json_each.value, '$.tr') FROM signalDeclarations, "
+ "json_each(signalDeclarations.signature) WHERE signalDeclarationId=?",
+ database};
+ Sqlite::WriteStatement<3> insertSignalDeclarationStatement{
+ "INSERT INTO signalDeclarations(typeId, name, signature) VALUES(?1, ?2, ?3)", database};
+ Sqlite::WriteStatement<2> updateSignalDeclarationStatement{
+ "UPDATE signalDeclarations SET signature=?2 WHERE signalDeclarationId=?1", database};
+ Sqlite::WriteStatement<1> deleteSignalDeclarationStatement{
+ "DELETE FROM signalDeclarations WHERE signalDeclarationId=?", database};
+ mutable Sqlite::ReadStatement<3, 1> selectEnumerationDeclarationsForTypeIdStatement{
+ "SELECT name, enumeratorDeclarations, enumerationDeclarationId FROM "
+ "enumerationDeclarations WHERE typeId=? ORDER BY name",
+ database};
+ mutable Sqlite::ReadStatement<2, 1> selectEnumerationDeclarationsForTypeIdWithoutEnumeratorDeclarationsStatement{
+ "SELECT name, enumerationDeclarationId FROM enumerationDeclarations WHERE typeId=? ORDER "
+ "BY name",
+ database};
+ mutable Sqlite::ReadStatement<3, 1> selectEnumeratorDeclarationStatement{
+ "SELECT json_each.key, json_each.value, json_each.type!='null' FROM "
+ "enumerationDeclarations, json_each(enumerationDeclarations.enumeratorDeclarations) WHERE "
+ "enumerationDeclarationId=?",
+ database};
+ Sqlite::WriteStatement<3> insertEnumerationDeclarationStatement{
+ "INSERT INTO enumerationDeclarations(typeId, name, enumeratorDeclarations) VALUES(?1, ?2, "
+ "?3)",
+ database};
+ Sqlite::WriteStatement<2> updateEnumerationDeclarationStatement{
+ "UPDATE enumerationDeclarations SET enumeratorDeclarations=?2 WHERE "
+ "enumerationDeclarationId=?1",
+ database};
+ Sqlite::WriteStatement<1> deleteEnumerationDeclarationStatement{
+ "DELETE FROM enumerationDeclarations WHERE enumerationDeclarationId=?", database};
+ mutable Sqlite::ReadStatement<1, 1> selectModuleIdByNameStatement{
+ "SELECT moduleId FROM modules WHERE name=? LIMIT 1", database};
+ mutable Sqlite::ReadWriteStatement<1, 1> insertModuleNameStatement{
+ "INSERT INTO modules(name) VALUES(?1) RETURNING moduleId", database};
+ mutable Sqlite::ReadStatement<1, 1> selectModuleNameStatement{
+ "SELECT name FROM modules WHERE moduleId =?1", database};
+ mutable Sqlite::ReadStatement<2> selectAllModulesStatement{"SELECT name, moduleId FROM modules",
+ database};
+ mutable Sqlite::ReadStatement<1, 2> selectTypeIdBySourceIdAndNameStatement{
+ "SELECT typeId FROM types WHERE sourceId=?1 and name=?2", database};
+ mutable Sqlite::ReadStatement<1, 3> selectTypeIdByModuleIdsAndExportedNameStatement{
+ "SELECT typeId FROM exportedTypeNames WHERE moduleId IN carray(?1, ?2, 'int32') AND "
+ "name=?3",
+ database};
+ mutable Sqlite::ReadStatement<4> selectAllDocumentImportForSourceIdStatement{
+ "SELECT moduleId, majorVersion, minorVersion, sourceId "
+ "FROM documentImports ",
+ database};
+ mutable Sqlite::ReadStatement<5, 2> selectDocumentImportForSourceIdStatement{
+ "SELECT importId, sourceId, moduleId, majorVersion, minorVersion "
+ "FROM documentImports WHERE sourceId IN carray(?1) AND kind=?2 ORDER BY sourceId, "
+ "moduleId, majorVersion, minorVersion",
+ database};
+ Sqlite::ReadWriteStatement<1, 5> insertDocumentImportWithoutVersionStatement{
+ "INSERT INTO documentImports(sourceId, moduleId, sourceModuleId, kind, "
+ "parentImportId) VALUES (?1, ?2, ?3, ?4, ?5) RETURNING importId",
+ database};
+ Sqlite::ReadWriteStatement<1, 6> insertDocumentImportWithMajorVersionStatement{
+ "INSERT INTO documentImports(sourceId, moduleId, sourceModuleId, kind, majorVersion, "
+ "parentImportId) VALUES (?1, ?2, ?3, ?4, ?5, ?6) RETURNING importId",
+ database};
+ Sqlite::ReadWriteStatement<1, 7> insertDocumentImportWithVersionStatement{
+ "INSERT INTO documentImports(sourceId, moduleId, sourceModuleId, kind, majorVersion, "
+ "minorVersion, parentImportId) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7) RETURNING "
+ "importId",
+ database};
+ Sqlite::WriteStatement<1> deleteDocumentImportStatement{
+ "DELETE FROM documentImports WHERE importId=?1", database};
+ Sqlite::WriteStatement<2> deleteDocumentImportsWithParentImportIdStatement{
+ "DELETE FROM documentImports WHERE sourceId=?1 AND parentImportId=?2", database};
+ Sqlite::WriteStatement<1> deleteDocumentImportsWithSourceIdsStatement{
+ "DELETE FROM documentImports WHERE sourceId IN carray(?1)", database};
+ mutable Sqlite::ReadStatement<1, 2> selectPropertyDeclarationIdByTypeIdAndNameStatement{
+ "SELECT propertyDeclarationId "
+ "FROM propertyDeclarations "
+ "WHERE typeId=?1 AND name=?2 "
+ "LIMIT 1",
+ database};
+ Sqlite::WriteStatement<2> updateAliasIdPropertyDeclarationStatement{
+ "UPDATE propertyDeclarations SET aliasPropertyDeclarationId=?2 WHERE "
+ "aliasPropertyDeclarationId=?1",
+ database};
+ Sqlite::WriteStatement<2> updateAliasPropertyDeclarationByAliasPropertyDeclarationIdStatement{
+ "UPDATE propertyDeclarations SET propertyTypeId=new.propertyTypeId, "
+ "propertyTraits=new.propertyTraits, aliasPropertyDeclarationId=?1 FROM (SELECT "
+ "propertyTypeId, propertyTraits FROM propertyDeclarations WHERE propertyDeclarationId=?1) "
+ "AS new WHERE aliasPropertyDeclarationId=?2",
+ database};
+ Sqlite::WriteStatement<1> updateAliasPropertyDeclarationToNullStatement{
+ "UPDATE propertyDeclarations SET aliasPropertyDeclarationId=NULL, propertyTypeId=NULL, "
+ "propertyTraits=NULL WHERE propertyDeclarationId=? AND (aliasPropertyDeclarationId IS NOT "
+ "NULL OR propertyTypeId IS NOT NULL OR propertyTraits IS NOT NULL)",
+ database};
+ Sqlite::ReadStatement<5, 1> selectAliasPropertiesDeclarationForPropertiesWithTypeIdStatement{
+ "SELECT alias.typeId, alias.propertyDeclarationId, alias.propertyImportedTypeNameId, "
+ " alias.aliasPropertyDeclarationId, alias.aliasPropertyDeclarationTailId "
+ "FROM propertyDeclarations AS alias JOIN propertyDeclarations AS target "
+ " ON alias.aliasPropertyDeclarationId=target.propertyDeclarationId OR "
+ " alias.aliasPropertyDeclarationTailId=target.propertyDeclarationId "
+ "WHERE alias.propertyTypeId=?1 "
+ "UNION ALL "
+ "SELECT alias.typeId, alias.propertyDeclarationId, alias.propertyImportedTypeNameId, "
+ " alias.aliasPropertyDeclarationId, alias.aliasPropertyDeclarationTailId "
+ "FROM propertyDeclarations AS alias JOIN propertyDeclarations AS target "
+ " ON alias.aliasPropertyDeclarationId=target.propertyDeclarationId OR "
+ " alias.aliasPropertyDeclarationTailId=target.propertyDeclarationId "
+ "WHERE target.typeId=?1 "
+ "UNION ALL "
+ "SELECT alias.typeId, alias.propertyDeclarationId, alias.propertyImportedTypeNameId, "
+ " alias.aliasPropertyDeclarationId, alias.aliasPropertyDeclarationTailId "
+ "FROM propertyDeclarations AS alias JOIN propertyDeclarations AS target "
+ " ON alias.aliasPropertyDeclarationId=target.propertyDeclarationId OR "
+ " alias.aliasPropertyDeclarationTailId=target.propertyDeclarationId "
+ "WHERE alias.propertyImportedTypeNameId IN "
+ " (SELECT importedTypeNameId FROM exportedTypeNames JOIN importedTypeNames USING(name) "
+ " WHERE typeId=?1)",
+ database};
+ Sqlite::ReadStatement<3, 1> selectAliasPropertiesDeclarationForPropertiesWithAliasIdStatement{
+ "WITH RECURSIVE "
+ " properties(propertyDeclarationId, propertyImportedTypeNameId, typeId, "
+ " aliasPropertyDeclarationId) AS ("
+ " SELECT propertyDeclarationId, propertyImportedTypeNameId, typeId, "
+ " aliasPropertyDeclarationId FROM propertyDeclarations WHERE "
+ " aliasPropertyDeclarationId=?1"
+ " UNION ALL "
+ " SELECT pd.propertyDeclarationId, pd.propertyImportedTypeNameId, pd.typeId, "
+ " pd.aliasPropertyDeclarationId FROM propertyDeclarations AS pd JOIN properties AS "
+ " p ON pd.aliasPropertyDeclarationId=p.propertyDeclarationId)"
+ "SELECT propertyDeclarationId, propertyImportedTypeNameId, aliasPropertyDeclarationId "
+ " FROM properties",
+ database};
+ Sqlite::ReadWriteStatement<3, 1> updatesPropertyDeclarationPropertyTypeToNullStatement{
+ "UPDATE propertyDeclarations SET propertyTypeId=NULL WHERE propertyTypeId=?1 AND "
+ "aliasPropertyDeclarationId IS NULL RETURNING typeId, propertyDeclarationId, "
+ "propertyImportedTypeNameId",
+ database};
+ mutable Sqlite::ReadStatement<1, 1> selectPropertyNameStatement{
+ "SELECT name FROM propertyDeclarations WHERE propertyDeclarationId=?", database};
+ Sqlite::WriteStatement<2> updatePropertyDeclarationTypeStatement{
+ "UPDATE propertyDeclarations SET propertyTypeId=?2 WHERE propertyDeclarationId=?1", database};
+ Sqlite::ReadWriteStatement<2, 1> updatePrototypeIdToNullStatement{
+ "UPDATE types SET prototypeId=NULL WHERE prototypeId=?1 RETURNING "
+ "typeId, prototypeNameId",
+ database};
+ Sqlite::ReadWriteStatement<2, 1> updateExtensionIdToNullStatement{
+ "UPDATE types SET extensionId=NULL WHERE extensionId=?1 RETURNING "
+ "typeId, extensionNameId",
+ database};
+ Sqlite::WriteStatement<2> updateTypePrototypeStatement{
+ "UPDATE types SET prototypeId=?2 WHERE typeId=?1", database};
+ Sqlite::WriteStatement<2> updateTypeExtensionStatement{
+ "UPDATE types SET extensionId=?2 WHERE typeId=?1", database};
+ mutable Sqlite::ReadStatement<1, 1> selectPrototypeAndExtensionIdsStatement{
+ "WITH RECURSIVE "
+ " prototypes(typeId) AS ( "
+ " SELECT prototypeId FROM types WHERE typeId=?1 "
+ " UNION ALL "
+ " SELECT extensionId FROM types WHERE typeId=?1 "
+ " UNION ALL "
+ " SELECT prototypeId FROM types JOIN prototypes USING(typeId) "
+ " UNION ALL "
+ " SELECT extensionId FROM types JOIN prototypes USING(typeId)) "
+ "SELECT typeId FROM prototypes WHERE typeId IS NOT NULL",
+ database};
+ Sqlite::WriteStatement<3> updatePropertyDeclarationAliasIdAndTypeNameIdStatement{
+ "UPDATE propertyDeclarations SET aliasPropertyDeclarationId=?2, "
+ "propertyImportedTypeNameId=?3 WHERE propertyDeclarationId=?1 AND "
+ "(aliasPropertyDeclarationId IS NOT ?2 OR propertyImportedTypeNameId IS NOT ?3)",
+ database};
+ Sqlite::WriteStatement<1> updatetPropertiesDeclarationValuesOfAliasStatement{
+ "WITH RECURSIVE "
+ " properties(propertyDeclarationId, propertyTypeId, propertyTraits) AS ( "
+ " SELECT aliasPropertyDeclarationId, propertyTypeId, propertyTraits FROM "
+ " propertyDeclarations WHERE propertyDeclarationId=?1 "
+ " UNION ALL "
+ " SELECT pd.aliasPropertyDeclarationId, pd.propertyTypeId, pd.propertyTraits FROM "
+ " propertyDeclarations AS pd JOIN properties USING(propertyDeclarationId)) "
+ "UPDATE propertyDeclarations AS pd SET propertyTypeId=p.propertyTypeId, "
+ " propertyTraits=p.propertyTraits "
+ "FROM properties AS p "
+ "WHERE pd.propertyDeclarationId=?1 AND p.propertyDeclarationId IS NULL AND "
+ " (pd.propertyTypeId IS NOT p.propertyTypeId OR pd.propertyTraits IS NOT "
+ " p.propertyTraits)",
+ database};
+ Sqlite::WriteStatement<1> updatePropertyDeclarationAliasIdToNullStatement{
+ "UPDATE propertyDeclarations SET aliasPropertyDeclarationId=NULL WHERE "
+ "propertyDeclarationId=?1",
+ database};
+ mutable Sqlite::ReadStatement<1, 1> selectPropertyDeclarationIdsForAliasChainStatement{
+ "WITH RECURSIVE "
+ " properties(propertyDeclarationId) AS ( "
+ " SELECT aliasPropertyDeclarationId FROM propertyDeclarations WHERE "
+ " propertyDeclarationId=?1 "
+ " UNION ALL "
+ " SELECT aliasPropertyDeclarationId FROM propertyDeclarations JOIN properties "
+ " USING(propertyDeclarationId)) "
+ "SELECT propertyDeclarationId FROM properties",
+ database};
+ mutable Sqlite::ReadStatement<3> selectAllFileStatusesStatement{
+ "SELECT sourceId, size, lastModified FROM fileStatuses ORDER BY sourceId", database};
+ mutable Sqlite::ReadStatement<3, 1> selectFileStatusesForSourceIdsStatement{
+ "SELECT sourceId, size, lastModified FROM fileStatuses WHERE sourceId IN carray(?1) ORDER "
+ "BY sourceId",
+ database};
+ mutable Sqlite::ReadStatement<3, 1> selectFileStatusesForSourceIdStatement{
+ "SELECT sourceId, size, lastModified FROM fileStatuses WHERE sourceId=?1 ORDER BY sourceId",
+ database};
+ Sqlite::WriteStatement<3> insertFileStatusStatement{
+ "INSERT INTO fileStatuses(sourceId, size, lastModified) VALUES(?1, ?2, ?3)", database};
+ Sqlite::WriteStatement<1> deleteFileStatusStatement{
+ "DELETE FROM fileStatuses WHERE sourceId=?1", database};
+ Sqlite::WriteStatement<3> updateFileStatusStatement{
+ "UPDATE fileStatuses SET size=?2, lastModified=?3 WHERE sourceId=?1", database};
+ Sqlite::ReadStatement<1, 1> selectTypeIdBySourceIdStatement{
+ "SELECT typeId FROM types WHERE sourceId=?", database};
+ mutable Sqlite::ReadStatement<1, 3> selectImportedTypeNameIdStatement{
+ "SELECT importedTypeNameId FROM importedTypeNames WHERE kind=?1 AND importOrSourceId=?2 "
+ "AND name=?3 LIMIT 1",
+ database};
+ mutable Sqlite::ReadWriteStatement<1, 3> insertImportedTypeNameIdStatement{
+ "INSERT INTO importedTypeNames(kind, importOrSourceId, name) VALUES (?1, ?2, ?3) "
+ "RETURNING importedTypeNameId",
+ database};
+ mutable Sqlite::ReadStatement<1, 2> selectImportIdBySourceIdAndModuleIdStatement{
+ "SELECT importId FROM documentImports WHERE sourceId=?1 AND moduleId=?2 AND majorVersion "
+ "IS NULL AND minorVersion IS NULL LIMIT 1",
+ database};
+ mutable Sqlite::ReadStatement<1, 3> selectImportIdBySourceIdAndModuleIdAndMajorVersionStatement{
+ "SELECT importId FROM documentImports WHERE sourceId=?1 AND moduleId=?2 AND "
+ "majorVersion=?3 AND minorVersion IS NULL LIMIT 1",
+ database};
+ mutable Sqlite::ReadStatement<1, 4> selectImportIdBySourceIdAndModuleIdAndVersionStatement{
+ "SELECT importId FROM documentImports WHERE sourceId=?1 AND moduleId=?2 AND "
+ "majorVersion=?3 AND minorVersion=?4 LIMIT 1",
+ database};
+ mutable Sqlite::ReadStatement<1, 1> selectKindFromImportedTypeNamesStatement{
+ "SELECT kind FROM importedTypeNames WHERE importedTypeNameId=?1", database};
+ mutable Sqlite::ReadStatement<1, 1> selectNameFromImportedTypeNamesStatement{
+ "SELECT name FROM importedTypeNames WHERE importedTypeNameId=?1", database};
+ mutable Sqlite::ReadStatement<1, 1> selectTypeIdForQualifiedImportedTypeNameNamesStatement{
+ "SELECT typeId FROM importedTypeNames AS itn JOIN documentImports AS di ON "
+ "importOrSourceId=di.importId JOIN documentImports AS di2 ON di.sourceId=di2.sourceId AND "
+ "di.moduleId=di2.sourceModuleId "
+ "JOIN exportedTypeNames AS etn ON di2.moduleId=etn.moduleId WHERE "
+ "itn.kind=2 AND importedTypeNameId=?1 AND itn.name=etn.name AND "
+ "(di.majorVersion IS NULL OR (di.majorVersion=etn.majorVersion AND (di.minorVersion IS "
+ "NULL OR di.minorVersion>=etn.minorVersion))) ORDER BY etn.majorVersion DESC NULLS FIRST, "
+ "etn.minorVersion DESC NULLS FIRST LIMIT 1",
+ database};
+ mutable Sqlite::ReadStatement<1, 1> selectTypeIdForImportedTypeNameNamesStatement{
+ "WITH "
+ " importTypeNames(moduleId, name, kind, majorVersion, minorVersion) AS ( "
+ " SELECT moduleId, name, di.kind, majorVersion, minorVersion "
+ " FROM importedTypeNames AS itn JOIN documentImports AS di ON "
+ " importOrSourceId=sourceId "
+ " WHERE "
+ " importedTypeNameId=?1 AND itn.kind=1) "
+ "SELECT typeId FROM importTypeNames AS itn "
+ " JOIN exportedTypeNames AS etn USING(moduleId, name) "
+ "WHERE (itn.majorVersion IS NULL OR (itn.majorVersion=etn.majorVersion "
+ " AND (itn.minorVersion IS NULL OR itn.minorVersion>=etn.minorVersion))) "
+ "ORDER BY itn.kind, etn.majorVersion DESC NULLS FIRST, etn.minorVersion DESC NULLS FIRST "
+ "LIMIT 1",
+ database};
+ Sqlite::WriteStatement<0> deleteAllSourcesStatement{"DELETE FROM sources", database};
+ Sqlite::WriteStatement<0> deleteAllSourceContextsStatement{"DELETE FROM sourceContexts", database};
+ mutable Sqlite::ReadStatement<6, 1> selectExportedTypesForSourceIdsStatement{
+ "SELECT moduleId, name, ifnull(majorVersion, -1), ifnull(minorVersion, -1), typeId, "
+ "exportedTypeNameId FROM exportedTypeNames WHERE typeId in carray(?1) ORDER BY moduleId, "
+ "name, majorVersion, minorVersion",
+ database};
+ Sqlite::WriteStatement<5> insertExportedTypeNamesWithVersionStatement{
+ "INSERT INTO exportedTypeNames(moduleId, name, majorVersion, minorVersion, typeId) "
+ "VALUES(?1, ?2, ?3, ?4, ?5)",
+ database};
+ Sqlite::WriteStatement<4> insertExportedTypeNamesWithMajorVersionStatement{
+ "INSERT INTO exportedTypeNames(moduleId, name, majorVersion, typeId) "
+ "VALUES(?1, ?2, ?3, ?4)",
+ database};
+ Sqlite::WriteStatement<3> insertExportedTypeNamesWithoutVersionStatement{
+ "INSERT INTO exportedTypeNames(moduleId, name, typeId) VALUES(?1, ?2, ?3)", database};
+ Sqlite::WriteStatement<1> deleteExportedTypeNameStatement{
+ "DELETE FROM exportedTypeNames WHERE exportedTypeNameId=?", database};
+ Sqlite::WriteStatement<2> updateExportedTypeNameTypeIdStatement{
+ "UPDATE exportedTypeNames SET typeId=?2 WHERE exportedTypeNameId=?1", database};
+ mutable Sqlite::ReadStatement<4, 1> selectProjectDatasForSourceIdsStatement{
+ "SELECT projectSourceId, sourceId, moduleId, fileType FROM projectDatas WHERE "
+ "projectSourceId IN carray(?1) ORDER BY projectSourceId, sourceId",
+ database};
+ Sqlite::WriteStatement<4> insertProjectDataStatement{
+ "INSERT INTO projectDatas(projectSourceId, sourceId, "
+ "moduleId, fileType) VALUES(?1, ?2, ?3, ?4)",
+ database};
+ Sqlite::WriteStatement<2> deleteProjectDataStatement{
+ "DELETE FROM projectDatas WHERE projectSourceId=?1 AND sourceId=?2", database};
+ Sqlite::WriteStatement<4> updateProjectDataStatement{
+ "UPDATE projectDatas SET moduleId=?3, fileType=?4 WHERE projectSourceId=?1 AND sourceId=?2",
+ database};
+ mutable Sqlite::ReadStatement<4, 1> selectProjectDatasForSourceIdStatement{
+ "SELECT projectSourceId, sourceId, moduleId, fileType FROM projectDatas WHERE "
+ "projectSourceId=?1",
+ database};
+ mutable Sqlite::ReadStatement<4, 1> selectProjectDataForSourceIdStatement{
+ "SELECT projectSourceId, sourceId, moduleId, fileType FROM projectDatas WHERE "
+ "sourceId=?1 LIMIT 1",
+ database};
+ mutable Sqlite::ReadStatement<1, 1> selectTypeIdsForSourceIdsStatement{
+ "SELECT typeId FROM types WHERE sourceId IN carray(?1)", database};
+ mutable Sqlite::ReadStatement<6, 1> selectModuleExportedImportsForSourceIdStatement{
+ "SELECT moduleExportedImportId, moduleId, exportedModuleId, ifnull(majorVersion, -1), "
+ "ifnull(minorVersion, -1), isAutoVersion FROM moduleExportedImports WHERE moduleId IN "
+ "carray(?1) ORDER BY moduleId, exportedModuleId",
+ database};
+ Sqlite::WriteStatement<3> insertModuleExportedImportWithoutVersionStatement{
+ "INSERT INTO moduleExportedImports(moduleId, exportedModuleId, isAutoVersion) "
+ "VALUES (?1, ?2, ?3)",
+ database};
+ Sqlite::WriteStatement<4> insertModuleExportedImportWithMajorVersionStatement{
+ "INSERT INTO moduleExportedImports(moduleId, exportedModuleId, isAutoVersion, "
+ "majorVersion) VALUES (?1, ?2, ?3, ?4)",
+ database};
+ Sqlite::WriteStatement<5> insertModuleExportedImportWithVersionStatement{
+ "INSERT INTO moduleExportedImports(moduleId, exportedModuleId, isAutoVersion, "
+ "majorVersion, minorVersion) VALUES (?1, ?2, ?3, ?4, ?5)",
+ database};
+ Sqlite::WriteStatement<1> deleteModuleExportedImportStatement{
+ "DELETE FROM moduleExportedImports WHERE moduleExportedImportId=?1", database};
+ mutable Sqlite::ReadStatement<3, 3> selectModuleExportedImportsForModuleIdStatement{
+ "WITH RECURSIVE "
+ " imports(moduleId, majorVersion, minorVersion, moduleExportedImportId) AS ( "
+ " SELECT exportedModuleId, "
+ " iif(isAutoVersion=1, ?2, majorVersion), "
+ " iif(isAutoVersion=1, ?3, minorVersion), "
+ " moduleExportedImportId "
+ " FROM moduleExportedImports WHERE moduleId=?1 "
+ " UNION ALL "
+ " SELECT exportedModuleId, "
+ " iif(mei.isAutoVersion=1, i.majorVersion, mei.majorVersion), "
+ " iif(mei.isAutoVersion=1, i.minorVersion, mei.minorVersion), "
+ " mei.moduleExportedImportId "
+ " FROM moduleExportedImports AS mei JOIN imports AS i USING(moduleId)) "
+ "SELECT DISTINCT moduleId, ifnull(majorVersion, -1), ifnull(minorVersion, -1) "
+ "FROM imports",
+ database};
+ mutable Sqlite::ReadStatement<1, 1> selectLocalPropertyDeclarationIdsForTypeStatement{
+ "SELECT propertyDeclarationId "
+ "FROM propertyDeclarations "
+ "WHERE typeId=? "
+ "ORDER BY propertyDeclarationId",
+ database};
+ mutable Sqlite::ReadStatement<1, 2> selectLocalPropertyDeclarationIdForTypeAndPropertyNameStatement{
+ "SELECT propertyDeclarationId "
+ "FROM propertyDeclarations "
+ "WHERE typeId=?1 AND name=?2 LIMIT 1",
+ database};
+ mutable Sqlite::ReadStatement<4, 1> selectPropertyDeclarationForPropertyDeclarationIdStatement{
+ "SELECT typeId, name, propertyTraits, propertyTypeId "
+ "FROM propertyDeclarations "
+ "WHERE propertyDeclarationId=?1 LIMIT 1",
+ database};
+ mutable Sqlite::ReadStatement<1, 1> selectSignalDeclarationNamesForTypeStatement{
+ "WITH RECURSIVE "
+ " all_prototype_and_extension(typeId, prototypeId) AS ("
+ " SELECT typeId, prototypeId FROM types WHERE prototypeId IS NOT NULL"
+ " UNION ALL "
+ " SELECT typeId, extensionId FROM types WHERE extensionId IS NOT NULL),"
+ " typeChain(typeId) AS ("
+ " VALUES(?1)"
+ " UNION ALL "
+ " SELECT prototypeId FROM all_prototype_and_extension JOIN typeChain "
+ " USING(typeId)) "
+ "SELECT name FROM typeChain JOIN signalDeclarations "
+ " USING(typeId) ORDER BY name",
+ database};
+ mutable Sqlite::ReadStatement<1, 1> selectFuncionDeclarationNamesForTypeStatement{
+ "WITH RECURSIVE "
+ " all_prototype_and_extension(typeId, prototypeId) AS ("
+ " SELECT typeId, prototypeId FROM types WHERE prototypeId IS NOT NULL"
+ " UNION ALL "
+ " SELECT typeId, extensionId FROM types WHERE extensionId IS NOT NULL),"
+ " typeChain(typeId) AS ("
+ " VALUES(?1)"
+ " UNION ALL "
+ " SELECT prototypeId FROM all_prototype_and_extension JOIN typeChain "
+ " USING(typeId))"
+ "SELECT name FROM typeChain JOIN functionDeclarations "
+ " USING(typeId) ORDER BY name",
+ database};
+ mutable Sqlite::ReadStatement<2> selectTypesWithDefaultPropertyStatement{
+ "SELECT typeId, defaultPropertyId FROM types ORDER BY typeId", database};
+ Sqlite::WriteStatement<2> updateDefaultPropertyIdStatement{
+ "UPDATE types SET defaultPropertyId=?2 WHERE typeId=?1", database};
+ Sqlite::WriteStatement<1> updateDefaultPropertyIdToNullStatement{
+ "UPDATE types SET defaultPropertyId=NULL WHERE defaultPropertyId=?1", database};
+ mutable Sqlite::ReadStatement<3, 1> selectInfoTypeByTypeIdStatement{
+ "SELECT sourceId, traits, annotationTraits FROM types WHERE typeId=?", database};
+ mutable Sqlite::ReadStatement<1, 1> selectDefaultPropertyDeclarationIdStatement{
+ "SELECT defaultPropertyId FROM types WHERE typeId=?", database};
+ mutable Sqlite::ReadStatement<1, 1> selectPrototypeIdsForTypeIdInOrderStatement{
+ "WITH RECURSIVE "
+ " all_prototype_and_extension(typeId, prototypeId) AS ("
+ " SELECT typeId, prototypeId FROM types WHERE prototypeId IS NOT NULL"
+ " UNION ALL "
+ " SELECT typeId, extensionId FROM types WHERE extensionId IS NOT NULL),"
+ " prototypes(typeId, level) AS ("
+ " SELECT prototypeId, 0 FROM all_prototype_and_extension WHERE typeId=?"
+ " UNION ALL "
+ " SELECT prototypeId, p.level+1 FROM all_prototype_and_extension JOIN "
+ " prototypes AS p USING(typeId)) "
+ "SELECT typeId FROM prototypes ORDER BY level",
+ database};
+ Sqlite::WriteStatement<2> upsertPropertyEditorPathIdStatement{
+ "INSERT INTO propertyEditorPaths(typeId, pathSourceId) VALUES(?1, ?2) ON CONFLICT DO "
+ "UPDATE SET pathSourceId=excluded.pathSourceId WHERE pathSourceId IS NOT "
+ "excluded.pathSourceId",
+ database};
+ mutable Sqlite::ReadStatement<1, 1> selectPropertyEditorPathIdStatement{
+ "SELECT pathSourceId FROM propertyEditorPaths WHERE typeId=?", database};
+ mutable Sqlite::ReadStatement<3, 1> selectPropertyEditorPathsForForSourceIdsStatement{
+ "SELECT typeId, pathSourceId, directoryId "
+ "FROM propertyEditorPaths "
+ "WHERE directoryId IN carray(?1) "
+ "ORDER BY typeId",
+ database};
+ Sqlite::WriteStatement<3> insertPropertyEditorPathStatement{
+ "INSERT INTO propertyEditorPaths(typeId, pathSourceId, directoryId) VALUES (?1, ?2, ?3)",
+ database};
+ Sqlite::WriteStatement<3> updatePropertyEditorPathsStatement{
+ "UPDATE propertyEditorPaths "
+ "SET pathSourceId=?2, directoryId=?3 "
+ "WHERE typeId=?1",
+ database};
+ Sqlite::WriteStatement<1> deletePropertyEditorPathStatement{
+ "DELETE FROM propertyEditorPaths WHERE typeId=?1", database};
+ mutable Sqlite::ReadStatement<4, 1> selectTypeAnnotationsForSourceIdsStatement{
+ "SELECT typeId, iconPath, itemLibrary, hints FROM typeAnnotations WHERE "
+ "sourceId IN carray(?1) ORDER BY typeId",
+ database};
+ Sqlite::WriteStatement<6> insertTypeAnnotationStatement{
+ "INSERT INTO "
+ " typeAnnotations(typeId, sourceId, directorySourceId, iconPath, itemLibrary, hints) "
+ "VALUES(?1, ?2, ?3, ?4, ?5, ?6)",
+ database};
+ Sqlite::WriteStatement<4> updateTypeAnnotationStatement{
+ "UPDATE typeAnnotations SET iconPath=?2, itemLibrary=?3, hints=?4 WHERE typeId=?1", database};
+ Sqlite::WriteStatement<1> deleteTypeAnnotationStatement{
+ "DELETE FROM typeAnnotations WHERE typeId=?1", database};
+ mutable Sqlite::ReadStatement<1, 1> selectTypeIconPathStatement{
+ "SELECT iconPath FROM typeAnnotations WHERE typeId=?1", database};
+ mutable Sqlite::ReadStatement<2, 1> selectTypeHintsStatement{
+ "SELECT hints.key, hints.value "
+ "FROM typeAnnotations, json_each(typeAnnotations.hints) AS hints "
+ "WHERE typeId=?1 AND hints IS NOT NULL",
+ database};
+ mutable Sqlite::ReadStatement<1, 1> selectTypeAnnotationSourceIdsStatement{
+ "SELECT sourceId FROM typeAnnotations WHERE directorySourceId=?1 ORDER BY sourceId", database};
+ mutable Sqlite::ReadStatement<1, 0> selectTypeAnnotationDirectorySourceIdsStatement{
+ "SELECT DISTINCT directorySourceId FROM typeAnnotations ORDER BY directorySourceId", database};
+ mutable Sqlite::ReadStatement<9> selectItemLibraryEntriesStatement{
+ "SELECT typeId, i.value->>'$.name', i.value->>'$.iconPath', i.value->>'$.category', "
+ " i.value->>'$.import', i.value->>'$.toolTip', i.value->>'$.properties', "
+ " i.value->>'$.extraFilePaths', i.value->>'$.templatePath' "
+ "FROM typeAnnotations AS ta , json_each(ta.itemLibrary) AS i "
+ "WHERE ta.itemLibrary IS NOT NULL",
+ database};
+ mutable Sqlite::ReadStatement<9, 1> selectItemLibraryEntriesByTypeIdStatement{
+ "SELECT typeId, i.value->>'$.name', i.value->>'$.iconPath', i.value->>'$.category', "
+ " i.value->>'$.import', i.value->>'$.toolTip', i.value->>'$.properties', "
+ " i.value->>'$.extraFilePaths', i.value->>'$.templatePath' "
+ "FROM typeAnnotations AS ta, json_each(ta.itemLibrary) AS i "
+ "WHERE typeId=?1 AND ta.itemLibrary IS NOT NULL",
+ database};
+ mutable Sqlite::ReadStatement<9, 1> selectItemLibraryEntriesBySourceIdStatement{
+ "SELECT typeId, i.value->>'$.name', i.value->>'$.iconPath', "
+ "i.value->>'$.category', "
+ " i.value->>'$.import', i.value->>'$.toolTip', i.value->>'$.properties', "
+ " i.value->>'$.extraFilePaths', i.value->>'$.templatePath' "
+ "FROM typeAnnotations, json_each(typeAnnotations.itemLibrary) AS i "
+ "WHERE typeId IN (SELECT DISTINCT typeId "
+ " FROM documentImports AS di JOIN exportedTypeNames "
+ " USING(moduleId) "
+ " WHERE di.sourceId=?)",
+ database};
+ mutable Sqlite::ReadStatement<3, 1> selectItemLibraryPropertiesStatement{
+ "SELECT p.value->>0, p.value->>1, p.value->>2 FROM json_each(?1) AS p", database};
+ mutable Sqlite::ReadStatement<1, 1> selectItemLibraryExtraFilePathsStatement{
+ "SELECT p.value FROM json_each(?1) AS p", database};
+ mutable Sqlite::ReadStatement<1, 1> selectTypeIdsByModuleIdStatement{
+ "SELECT DISTINCT typeId FROM exportedTypeNames WHERE moduleId=?", database};
+ mutable Sqlite::ReadStatement<1, 1> selectHeirTypeIdsStatement{
+ "WITH RECURSIVE "
+ " typeSelection(typeId) AS ("
+ " SELECT typeId FROM types WHERE prototypeId=?1 OR extensionId=?1"
+ " UNION ALL "
+ " SELECT t.typeId "
+ " FROM types AS t JOIN typeSelection AS ts "
+ " WHERE prototypeId=ts.typeId OR extensionId=ts.typeId)"
+ "SELECT typeId FROM typeSelection",
+ database};
+};
+
+class ProjectStorage::Initializer
+{
+public:
+ Initializer(Database &database, bool isInitialized)
+ {
+ if (!isInitialized) {
+ auto moduleIdColumn = createModulesTable(database);
+ createSourceContextsTable(database);
+ createSourcesTable(database);
+ createTypesAndePropertyDeclarationsTables(database, moduleIdColumn);
+ createExportedTypeNamesTable(database, moduleIdColumn);
+ createImportedTypeNamesTable(database);
+ createEnumerationsTable(database);
+ createFunctionsTable(database);
+ createSignalsTable(database);
+ createModuleExportedImportsTable(database, moduleIdColumn);
+ createDocumentImportsTable(database, moduleIdColumn);
+ createFileStatusesTable(database);
+ createProjectDatasTable(database);
+ createPropertyEditorPathsTable(database);
+ createTypeAnnotionsTable(database);
+ }
+ database.setIsInitialized(true);
+ }
+
+ void createSourceContextsTable(Database &database)
+ {
+ Sqlite::Table table;
+ table.setUseIfNotExists(true);
+ table.setName("sourceContexts");
+ table.addColumn("sourceContextId", Sqlite::ColumnType::Integer, {Sqlite::PrimaryKey{}});
+ const Sqlite::Column &sourceContextPathColumn = table.addColumn("sourceContextPath");
+
+ table.addUniqueIndex({sourceContextPathColumn});
+
+ table.initialize(database);
+ }
+
+ void createSourcesTable(Database &database)
+ {
+ Sqlite::StrictTable table;
+ table.setUseIfNotExists(true);
+ table.setName("sources");
+ table.addColumn("sourceId", Sqlite::StrictColumnType::Integer, {Sqlite::PrimaryKey{}});
+ const auto &sourceContextIdColumn = table.addColumn(
+ "sourceContextId",
+ Sqlite::StrictColumnType::Integer,
+ {Sqlite::NotNull{},
+ Sqlite::ForeignKey{"sourceContexts",
+ "sourceContextId",
+ Sqlite::ForeignKeyAction::NoAction,
+ Sqlite::ForeignKeyAction::Cascade}});
+ const auto &sourceNameColumn = table.addColumn("sourceName", Sqlite::StrictColumnType::Text);
+ table.addUniqueIndex({sourceContextIdColumn, sourceNameColumn});
+
+ table.initialize(database);
+ }
+
+ void createTypesAndePropertyDeclarationsTables(
+ Database &database, [[maybe_unused]] const Sqlite::StrictColumn &foreignModuleIdColumn)
+ {
+ Sqlite::StrictTable typesTable;
+ typesTable.setUseIfNotExists(true);
+ typesTable.setName("types");
+ typesTable.addColumn("typeId", Sqlite::StrictColumnType::Integer, {Sqlite::PrimaryKey{}});
+ auto &sourceIdColumn = typesTable.addColumn("sourceId", Sqlite::StrictColumnType::Integer);
+ auto &typesNameColumn = typesTable.addColumn("name", Sqlite::StrictColumnType::Text);
+ typesTable.addColumn("traits", Sqlite::StrictColumnType::Integer);
+ auto &prototypeIdColumn = typesTable.addForeignKeyColumn("prototypeId",
+ typesTable,
+ Sqlite::ForeignKeyAction::NoAction,
+ Sqlite::ForeignKeyAction::Restrict);
+ typesTable.addColumn("prototypeNameId", Sqlite::StrictColumnType::Integer);
+ auto &extensionIdColumn = typesTable.addForeignKeyColumn("extensionId",
+ typesTable,
+ Sqlite::ForeignKeyAction::NoAction,
+ Sqlite::ForeignKeyAction::Restrict);
+ typesTable.addColumn("extensionNameId", Sqlite::StrictColumnType::Integer);
+ auto &defaultPropertyIdColumn = typesTable.addColumn("defaultPropertyId",
+ Sqlite::StrictColumnType::Integer);
+ typesTable.addColumn("annotationTraits", Sqlite::StrictColumnType::Integer);
+ typesTable.addUniqueIndex({sourceIdColumn, typesNameColumn});
+ typesTable.addIndex({defaultPropertyIdColumn});
+ typesTable.addIndex({prototypeIdColumn});
+ typesTable.addIndex({extensionIdColumn});
+
+ typesTable.initialize(database);
+
+ {
+ Sqlite::StrictTable propertyDeclarationTable;
+ propertyDeclarationTable.setUseIfNotExists(true);
+ propertyDeclarationTable.setName("propertyDeclarations");
+ propertyDeclarationTable.addColumn("propertyDeclarationId",
+ Sqlite::StrictColumnType::Integer,
+ {Sqlite::PrimaryKey{}});
+ auto &typeIdColumn = propertyDeclarationTable.addColumn("typeId");
+ auto &nameColumn = propertyDeclarationTable.addColumn("name");
+ auto &propertyTypeIdColumn = propertyDeclarationTable.addForeignKeyColumn(
+ "propertyTypeId",
+ typesTable,
+ Sqlite::ForeignKeyAction::NoAction,
+ Sqlite::ForeignKeyAction::Restrict);
+ propertyDeclarationTable.addColumn("propertyTraits", Sqlite::StrictColumnType::Integer);
+ propertyDeclarationTable.addColumn("propertyImportedTypeNameId",
+ Sqlite::StrictColumnType::Integer);
+ auto &aliasPropertyDeclarationIdColumn = propertyDeclarationTable.addForeignKeyColumn(
+ "aliasPropertyDeclarationId",
+ propertyDeclarationTable,
+ Sqlite::ForeignKeyAction::NoAction,
+ Sqlite::ForeignKeyAction::Restrict);
+ auto &aliasPropertyDeclarationTailIdColumn = propertyDeclarationTable.addForeignKeyColumn(
+ "aliasPropertyDeclarationTailId",
+ propertyDeclarationTable,
+ Sqlite::ForeignKeyAction::NoAction,
+ Sqlite::ForeignKeyAction::Restrict);
+
+ propertyDeclarationTable.addUniqueIndex({typeIdColumn, nameColumn});
+ propertyDeclarationTable.addIndex({propertyTypeIdColumn});
+ propertyDeclarationTable.addIndex({aliasPropertyDeclarationIdColumn},
+ "aliasPropertyDeclarationId IS NOT NULL");
+ propertyDeclarationTable.addIndex({aliasPropertyDeclarationTailIdColumn},
+ "aliasPropertyDeclarationTailId IS NOT NULL");
+
+ propertyDeclarationTable.initialize(database);
+ }
+ }
+
+ void createExportedTypeNamesTable(Database &database,
+ const Sqlite::StrictColumn &foreignModuleIdColumn)
+ {
+ Sqlite::StrictTable table;
+ table.setUseIfNotExists(true);
+ table.setName("exportedTypeNames");
+ table.addColumn("exportedTypeNameId",
+ Sqlite::StrictColumnType::Integer,
+ {Sqlite::PrimaryKey{}});
+ auto &moduleIdColumn = table.addForeignKeyColumn("moduleId",
+ foreignModuleIdColumn,
+ Sqlite::ForeignKeyAction::NoAction,
+ Sqlite::ForeignKeyAction::NoAction);
+ auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text);
+ auto &typeIdColumn = table.addColumn("typeId", Sqlite::StrictColumnType::Integer);
+ auto &majorVersionColumn = table.addColumn("majorVersion", Sqlite::StrictColumnType::Integer);
+ auto &minorVersionColumn = table.addColumn("minorVersion", Sqlite::StrictColumnType::Integer);
+
+ table.addUniqueIndex({moduleIdColumn, nameColumn},
+ "majorVersion IS NULL AND minorVersion IS NULL");
+ table.addUniqueIndex({moduleIdColumn, nameColumn, majorVersionColumn},
+ "majorVersion IS NOT NULL AND minorVersion IS NULL");
+ table.addUniqueIndex({moduleIdColumn, nameColumn, majorVersionColumn, minorVersionColumn},
+ "majorVersion IS NOT NULL AND minorVersion IS NOT NULL");
+
+ table.addIndex({typeIdColumn});
+ table.addIndex({moduleIdColumn, nameColumn});
+
+ table.initialize(database);
+ }
+
+ void createImportedTypeNamesTable(Database &database)
+ {
+ Sqlite::StrictTable table;
+ table.setUseIfNotExists(true);
+ table.setName("importedTypeNames");
+ table.addColumn("importedTypeNameId",
+ Sqlite::StrictColumnType::Integer,
+ {Sqlite::PrimaryKey{}});
+ auto &importOrSourceIdColumn = table.addColumn("importOrSourceId");
+ auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text);
+ auto &kindColumn = table.addColumn("kind", Sqlite::StrictColumnType::Integer);
+
+ table.addUniqueIndex({kindColumn, importOrSourceIdColumn, nameColumn});
+ table.addIndex({nameColumn});
+
+ table.initialize(database);
+ }
+
+ void createEnumerationsTable(Database &database)
+ {
+ Sqlite::StrictTable table;
+ table.setUseIfNotExists(true);
+ table.setName("enumerationDeclarations");
+ table.addColumn("enumerationDeclarationId",
+ Sqlite::StrictColumnType::Integer,
+ {Sqlite::PrimaryKey{}});
+ auto &typeIdColumn = table.addColumn("typeId", Sqlite::StrictColumnType::Integer);
+ auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text);
+ table.addColumn("enumeratorDeclarations", Sqlite::StrictColumnType::Text);
+
+ table.addUniqueIndex({typeIdColumn, nameColumn});
+
+ table.initialize(database);
+ }
+
+ void createFunctionsTable(Database &database)
+ {
+ Sqlite::StrictTable table;
+ table.setUseIfNotExists(true);
+ table.setName("functionDeclarations");
+ table.addColumn("functionDeclarationId",
+ Sqlite::StrictColumnType::Integer,
+ {Sqlite::PrimaryKey{}});
+ auto &typeIdColumn = table.addColumn("typeId", Sqlite::StrictColumnType::Integer);
+ auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text);
+ auto &signatureColumn = table.addColumn("signature", Sqlite::StrictColumnType::Text);
+ table.addColumn("returnTypeName");
+
+ table.addUniqueIndex({typeIdColumn, nameColumn, signatureColumn});
+
+ table.initialize(database);
+ }
+
+ void createSignalsTable(Database &database)
+ {
+ Sqlite::StrictTable table;
+ table.setUseIfNotExists(true);
+ table.setName("signalDeclarations");
+ table.addColumn("signalDeclarationId",
+ Sqlite::StrictColumnType::Integer,
+ {Sqlite::PrimaryKey{}});
+ auto &typeIdColumn = table.addColumn("typeId", Sqlite::StrictColumnType::Integer);
+ auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text);
+ auto &signatureColumn = table.addColumn("signature", Sqlite::StrictColumnType::Text);
+
+ table.addUniqueIndex({typeIdColumn, nameColumn, signatureColumn});
+
+ table.initialize(database);
+ }
+
+ Sqlite::StrictColumn createModulesTable(Database &database)
+ {
+ Sqlite::StrictTable table;
+ table.setUseIfNotExists(true);
+ table.setName("modules");
+ auto &modelIdColumn = table.addColumn("moduleId",
+ Sqlite::StrictColumnType::Integer,
+ {Sqlite::PrimaryKey{}});
+ auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text);
+
+ table.addUniqueIndex({nameColumn});
+
+ table.initialize(database);
+
+ return std::move(modelIdColumn);
+ }
+
+ void createModuleExportedImportsTable(Database &database,
+ const Sqlite::StrictColumn &foreignModuleIdColumn)
+ {
+ Sqlite::StrictTable table;
+ table.setUseIfNotExists(true);
+ table.setName("moduleExportedImports");
+ table.addColumn("moduleExportedImportId",
+ Sqlite::StrictColumnType::Integer,
+ {Sqlite::PrimaryKey{}});
+ auto &moduleIdColumn = table.addForeignKeyColumn("moduleId",
+ foreignModuleIdColumn,
+ Sqlite::ForeignKeyAction::NoAction,
+ Sqlite::ForeignKeyAction::Cascade,
+ Sqlite::Enforment::Immediate);
+ auto &sourceIdColumn = table.addColumn("exportedModuleId", Sqlite::StrictColumnType::Integer);
+ table.addColumn("isAutoVersion", Sqlite::StrictColumnType::Integer);
+ table.addColumn("majorVersion", Sqlite::StrictColumnType::Integer);
+ table.addColumn("minorVersion", Sqlite::StrictColumnType::Integer);
+
+ table.addUniqueIndex({sourceIdColumn, moduleIdColumn});
+
+ table.initialize(database);
+ }
+
+ void createDocumentImportsTable(Database &database,
+ const Sqlite::StrictColumn &foreignModuleIdColumn)
+ {
+ Sqlite::StrictTable table;
+ table.setUseIfNotExists(true);
+ table.setName("documentImports");
+ table.addColumn("importId", Sqlite::StrictColumnType::Integer, {Sqlite::PrimaryKey{}});
+ auto &sourceIdColumn = table.addColumn("sourceId", Sqlite::StrictColumnType::Integer);
+ auto &moduleIdColumn = table.addForeignKeyColumn("moduleId",
+ foreignModuleIdColumn,
+ Sqlite::ForeignKeyAction::NoAction,
+ Sqlite::ForeignKeyAction::Cascade,
+ Sqlite::Enforment::Immediate);
+ auto &sourceModuleIdColumn = table.addForeignKeyColumn("sourceModuleId",
+ foreignModuleIdColumn,
+ Sqlite::ForeignKeyAction::NoAction,
+ Sqlite::ForeignKeyAction::Cascade,
+ Sqlite::Enforment::Immediate);
+ auto &kindColumn = table.addColumn("kind", Sqlite::StrictColumnType::Integer);
+ auto &majorVersionColumn = table.addColumn("majorVersion", Sqlite::StrictColumnType::Integer);
+ auto &minorVersionColumn = table.addColumn("minorVersion", Sqlite::StrictColumnType::Integer);
+ auto &parentImportIdColumn = table.addColumn("parentImportId",
+ Sqlite::StrictColumnType::Integer);
+
+ table.addUniqueIndex(
+ {sourceIdColumn, moduleIdColumn, kindColumn, sourceModuleIdColumn, parentImportIdColumn},
+ "majorVersion IS NULL AND minorVersion IS NULL");
+ table.addUniqueIndex({sourceIdColumn,
+ moduleIdColumn,
+ kindColumn,
+ sourceModuleIdColumn,
+ majorVersionColumn,
+ parentImportIdColumn},
+ "majorVersion IS NOT NULL AND minorVersion IS NULL");
+ table.addUniqueIndex({sourceIdColumn,
+ moduleIdColumn,
+ kindColumn,
+ sourceModuleIdColumn,
+ majorVersionColumn,
+ minorVersionColumn,
+ parentImportIdColumn},
+ "majorVersion IS NOT NULL AND minorVersion IS NOT NULL");
+
+ table.addIndex({sourceIdColumn, kindColumn});
+
+ table.initialize(database);
+ }
+
+ void createFileStatusesTable(Database &database)
+ {
+ Sqlite::StrictTable table;
+ table.setUseIfNotExists(true);
+ table.setName("fileStatuses");
+ table.addColumn("sourceId",
+ Sqlite::StrictColumnType::Integer,
+ {Sqlite::PrimaryKey{},
+ Sqlite::ForeignKey{"sources",
+ "sourceId",
+ Sqlite::ForeignKeyAction::NoAction,
+ Sqlite::ForeignKeyAction::Cascade}});
+ table.addColumn("size", Sqlite::StrictColumnType::Integer);
+ table.addColumn("lastModified", Sqlite::StrictColumnType::Integer);
+
+ table.initialize(database);
+ }
+
+ void createProjectDatasTable(Database &database)
+ {
+ Sqlite::StrictTable table;
+ table.setUseIfNotExists(true);
+ table.setUseWithoutRowId(true);
+ table.setName("projectDatas");
+ auto &projectSourceIdColumn = table.addColumn("projectSourceId",
+ Sqlite::StrictColumnType::Integer);
+ auto &sourceIdColumn = table.addColumn("sourceId", Sqlite::StrictColumnType::Integer);
+ table.addColumn("moduleId", Sqlite::StrictColumnType::Integer);
+ table.addColumn("fileType", Sqlite::StrictColumnType::Integer);
+
+ table.addPrimaryKeyContraint({projectSourceIdColumn, sourceIdColumn});
+ table.addUniqueIndex({sourceIdColumn});
+
+ table.initialize(database);
+ }
+
+ void createPropertyEditorPathsTable(Database &database)
+ {
+ Sqlite::StrictTable table;
+ table.setUseIfNotExists(true);
+ table.setUseWithoutRowId(true);
+ table.setName("propertyEditorPaths");
+ table.addColumn("typeId", Sqlite::StrictColumnType::Integer, {Sqlite::PrimaryKey{}});
+ table.addColumn("pathSourceId", Sqlite::StrictColumnType::Integer);
+ auto &directoryIdColumn = table.addColumn("directoryId", Sqlite::StrictColumnType::Integer);
+
+ table.addIndex({directoryIdColumn});
+
+ table.initialize(database);
+ }
+
+ void createTypeAnnotionsTable(Database &database)
+ {
+ Sqlite::StrictTable table;
+ table.setUseIfNotExists(true);
+ table.setUseWithoutRowId(true);
+ table.setName("typeAnnotations");
+ auto &typeIdColumn = table.addColumn("typeId",
+ Sqlite::StrictColumnType::Integer,
+ {Sqlite::PrimaryKey{}});
+ auto &sourceIdColumn = table.addColumn("sourceId", Sqlite::StrictColumnType::Integer);
+ auto &directorySourceIdColumn = table.addColumn("directorySourceId",
+ Sqlite::StrictColumnType::Integer);
+
+ table.addColumn("iconPath", Sqlite::StrictColumnType::Text);
+ table.addColumn("itemLibrary", Sqlite::StrictColumnType::Text);
+ table.addColumn("hints", Sqlite::StrictColumnType::Text);
+
+ table.addUniqueIndex({sourceIdColumn, typeIdColumn});
+ table.addIndex({directorySourceIdColumn});
+
+ table.initialize(database);
+ }
+};
+
+ProjectStorage::ProjectStorage(Database &database, bool isInitialized)
+ : database{database}
+ , exclusiveTransaction{database}
+ , initializer{std::make_unique<ProjectStorage::Initializer>(database, isInitialized)}
+ , moduleCache{ModuleStorageAdapter{*this}}
+ , s{std::make_unique<ProjectStorage::Statements>(database)}
{
- thread_local NanotraceHR::StringViewCategory<projectStorageTracingStatus()>
- projectStorageCategory_{"project storage"_t, Tracing::eventQueue(), projectStorageCategory};
+ NanotraceHR::Tracer tracer{"initialize"_t, projectStorageCategory()};
+
+ exclusiveTransaction.commit();
- return projectStorageCategory_;
+ database.walCheckpointFull();
+
+ moduleCache.populate();
}
-} // namespace QmlDesigner
+ProjectStorage::~ProjectStorage() = default;
+
+void ProjectStorage::synchronize(Storage::Synchronization::SynchronizationPackage package)
+{
+ NanotraceHR::Tracer tracer{"synchronize"_t, projectStorageCategory()};
+
+ TypeIds deletedTypeIds;
+ Sqlite::withImmediateTransaction(database, [&] {
+ AliasPropertyDeclarations insertedAliasPropertyDeclarations;
+ AliasPropertyDeclarations updatedAliasPropertyDeclarations;
+
+ AliasPropertyDeclarations relinkableAliasPropertyDeclarations;
+ PropertyDeclarations relinkablePropertyDeclarations;
+ Prototypes relinkablePrototypes;
+ Prototypes relinkableExtensions;
+
+ TypeIds updatedTypeIds;
+ updatedTypeIds.reserve(package.types.size());
+
+ TypeIds typeIdsToBeDeleted;
+
+ std::sort(package.updatedSourceIds.begin(), package.updatedSourceIds.end());
+
+ synchronizeFileStatuses(package.fileStatuses, package.updatedFileStatusSourceIds);
+ synchronizeImports(package.imports,
+ package.updatedSourceIds,
+ package.moduleDependencies,
+ package.updatedModuleDependencySourceIds,
+ package.moduleExportedImports,
+ package.updatedModuleIds);
+ synchronizeTypes(package.types,
+ updatedTypeIds,
+ insertedAliasPropertyDeclarations,
+ updatedAliasPropertyDeclarations,
+ relinkableAliasPropertyDeclarations,
+ relinkablePropertyDeclarations,
+ relinkablePrototypes,
+ relinkableExtensions,
+ package.updatedSourceIds);
+ synchronizeTypeAnnotations(package.typeAnnotations, package.updatedTypeAnnotationSourceIds);
+ synchronizePropertyEditorQmlPaths(package.propertyEditorQmlPaths,
+ package.updatedPropertyEditorQmlPathSourceIds);
+
+ deleteNotUpdatedTypes(updatedTypeIds,
+ package.updatedSourceIds,
+ typeIdsToBeDeleted,
+ relinkableAliasPropertyDeclarations,
+ relinkablePropertyDeclarations,
+ relinkablePrototypes,
+ relinkableExtensions,
+ deletedTypeIds);
+
+ relink(relinkableAliasPropertyDeclarations,
+ relinkablePropertyDeclarations,
+ relinkablePrototypes,
+ relinkableExtensions,
+ deletedTypeIds);
+
+ linkAliases(insertedAliasPropertyDeclarations, updatedAliasPropertyDeclarations);
+
+ synchronizeProjectDatas(package.projectDatas, package.updatedProjectSourceIds);
+
+ commonTypeCache_.resetTypeIds();
+ });
+
+ callRefreshMetaInfoCallback(deletedTypeIds);
+}
+
+void ProjectStorage::synchronizeDocumentImports(Storage::Imports imports, SourceId sourceId)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"synchronize document imports"_t,
+ projectStorageCategory(),
+ keyValue("imports", imports),
+ keyValue("source id", sourceId)};
+
+ Sqlite::withImmediateTransaction(database, [&] {
+ synchronizeDocumentImports(imports, {sourceId}, Storage::Synchronization::ImportKind::Import);
+ });
+}
+
+void ProjectStorage::addObserver(ProjectStorageObserver *observer)
+{
+ NanotraceHR::Tracer tracer{"add observer"_t, projectStorageCategory()};
+ observers.push_back(observer);
+}
+
+void ProjectStorage::removeObserver(ProjectStorageObserver *observer)
+{
+ NanotraceHR::Tracer tracer{"remove observer"_t, projectStorageCategory()};
+ observers.removeOne(observer);
+}
+
+ModuleId ProjectStorage::moduleId(Utils::SmallStringView moduleName) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get module id"_t,
+ projectStorageCategory(),
+ keyValue("module name", moduleName)};
+
+ auto moduleId = moduleCache.id(moduleName);
+
+ tracer.end(keyValue("module id", moduleId));
+
+ return moduleId;
+}
+
+Utils::SmallString ProjectStorage::moduleName(ModuleId moduleId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get module name"_t,
+ projectStorageCategory(),
+ keyValue("module id", moduleId)};
+
+ if (!moduleId)
+ throw ModuleDoesNotExists{};
+
+ auto moduleName = moduleCache.value(moduleId);
+
+ tracer.end(keyValue("module name", moduleName));
+
+ return moduleName;
+}
+
+TypeId ProjectStorage::typeId(ModuleId moduleId,
+ Utils::SmallStringView exportedTypeName,
+ Storage::Version version) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get type id by exported name"_t,
+ projectStorageCategory(),
+ keyValue("module id", moduleId),
+ keyValue("exported type name", exportedTypeName),
+ keyValue("version", version)};
+
+ TypeId typeId;
+
+ if (version.minor) {
+ typeId = s->selectTypeIdByModuleIdAndExportedNameAndVersionStatement.valueWithTransaction<TypeId>(
+ moduleId, exportedTypeName, version.major.value, version.minor.value);
+
+ } else if (version.major) {
+ typeId = s->selectTypeIdByModuleIdAndExportedNameAndMajorVersionStatement
+ .valueWithTransaction<TypeId>(moduleId, exportedTypeName, version.major.value);
+
+ } else {
+ typeId = s->selectTypeIdByModuleIdAndExportedNameStatement
+ .valueWithTransaction<TypeId>(moduleId, exportedTypeName);
+ }
+
+ tracer.end(keyValue("type id", typeId));
+
+ return typeId;
+}
+
+TypeId ProjectStorage::typeId(ImportedTypeNameId typeNameId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get type id by imported type name"_t,
+ projectStorageCategory(),
+ keyValue("imported type name id", typeNameId)};
+
+ auto typeId = Sqlite::withDeferredTransaction(database, [&] { return fetchTypeId(typeNameId); });
+
+ tracer.end(keyValue("type id", typeId));
+
+ return typeId;
+}
+
+QVarLengthArray<TypeId, 256> ProjectStorage::typeIds(ModuleId moduleId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get type ids by module id"_t,
+ projectStorageCategory(),
+ keyValue("module id", moduleId)};
+
+ auto typeIds = s->selectTypeIdsByModuleIdStatement
+ .valuesWithTransaction<QVarLengthArray<TypeId, 256>>(moduleId);
+
+ tracer.end(keyValue("type ids", typeIds));
+
+ return typeIds;
+}
+
+Storage::Info::ExportedTypeNames ProjectStorage::exportedTypeNames(TypeId typeId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get exported type names by type id"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId)};
+
+ auto exportedTypenames = s->selectExportedTypesByTypeIdStatement
+ .valuesWithTransaction<Storage::Info::ExportedTypeName, 4>(typeId);
+
+ tracer.end(keyValue("exported type names", exportedTypenames));
+
+ return exportedTypenames;
+}
+
+Storage::Info::ExportedTypeNames ProjectStorage::exportedTypeNames(TypeId typeId, SourceId sourceId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get exported type names by source id"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId),
+ keyValue("source id", sourceId)};
+
+ auto exportedTypenames = s->selectExportedTypesByTypeIdAndSourceIdStatement
+ .valuesWithTransaction<Storage::Info::ExportedTypeName, 4>(typeId,
+ sourceId);
+
+ tracer.end(keyValue("exported type names", exportedTypenames));
+
+ return exportedTypenames;
+}
+
+ImportId ProjectStorage::importId(const Storage::Import &import) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get import id by import"_t,
+ projectStorageCategory(),
+ keyValue("import", import)};
+
+ auto importId = Sqlite::withDeferredTransaction(database, [&] {
+ return fetchImportId(import.sourceId, import);
+ });
+
+ tracer.end(keyValue("import id", importId));
+
+ return importId;
+}
+
+ImportedTypeNameId ProjectStorage::importedTypeNameId(ImportId importId,
+ Utils::SmallStringView typeName)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get imported type name id by import id"_t,
+ projectStorageCategory(),
+ keyValue("import id", importId),
+ keyValue("imported type name", typeName)};
+
+ auto importedTypeNameId = Sqlite::withDeferredTransaction(database, [&] {
+ return fetchImportedTypeNameId(Storage::Synchronization::TypeNameKind::QualifiedExported,
+ importId,
+ typeName);
+ });
+
+ tracer.end(keyValue("imported type name id", importedTypeNameId));
+
+ return importedTypeNameId;
+}
+
+ImportedTypeNameId ProjectStorage::importedTypeNameId(SourceId sourceId,
+ Utils::SmallStringView typeName)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get imported type name id by source id"_t,
+ projectStorageCategory(),
+ keyValue("source id", sourceId),
+ keyValue("imported type name", typeName)};
+
+ auto importedTypeNameId = Sqlite::withDeferredTransaction(database, [&] {
+ return fetchImportedTypeNameId(Storage::Synchronization::TypeNameKind::Exported,
+ sourceId,
+ typeName);
+ });
+
+ tracer.end(keyValue("imported type name id", importedTypeNameId));
+
+ return importedTypeNameId;
+}
+
+QVarLengthArray<PropertyDeclarationId, 128> ProjectStorage::propertyDeclarationIds(TypeId typeId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get property declaration ids"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId)};
+
+ auto propertyDeclarationIds = Sqlite::withDeferredTransaction(database, [&] {
+ return fetchPropertyDeclarationIds(typeId);
+ });
+
+ std::sort(propertyDeclarationIds.begin(), propertyDeclarationIds.end());
+
+ tracer.end(keyValue("property declaration ids", propertyDeclarationIds));
+
+ return propertyDeclarationIds;
+}
+
+QVarLengthArray<PropertyDeclarationId, 128> ProjectStorage::localPropertyDeclarationIds(TypeId typeId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get local property declaration ids"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId)};
+
+ auto propertyDeclarationIds = s->selectLocalPropertyDeclarationIdsForTypeStatement
+ .valuesWithTransaction<QVarLengthArray<PropertyDeclarationId, 128>>(
+ typeId);
+
+ tracer.end(keyValue("property declaration ids", propertyDeclarationIds));
+
+ return propertyDeclarationIds;
+}
+
+PropertyDeclarationId ProjectStorage::propertyDeclarationId(TypeId typeId,
+ Utils::SmallStringView propertyName) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get property declaration id"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId),
+ keyValue("property name", propertyName)};
+
+ auto propertyDeclarationId = Sqlite::withDeferredTransaction(database, [&] {
+ return fetchPropertyDeclarationId(typeId, propertyName);
+ });
+
+ tracer.end(keyValue("property declaration id", propertyDeclarationId));
+
+ return propertyDeclarationId;
+}
+
+PropertyDeclarationId ProjectStorage::localPropertyDeclarationId(TypeId typeId,
+ Utils::SmallStringView propertyName) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get local property declaration id"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId),
+ keyValue("property name", propertyName)};
+
+ auto propertyDeclarationId = s->selectLocalPropertyDeclarationIdForTypeAndPropertyNameStatement
+ .valueWithTransaction<PropertyDeclarationId>(typeId,
+ propertyName);
+
+ tracer.end(keyValue("property declaration id", propertyDeclarationId));
+
+ return propertyDeclarationId;
+}
+
+PropertyDeclarationId ProjectStorage::defaultPropertyDeclarationId(TypeId typeId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get default property declaration id"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId)};
+
+ auto propertyDeclarationId = Sqlite::withDeferredTransaction(database, [&] {
+ return fetchDefaultPropertyDeclarationId(typeId);
+ });
+
+ tracer.end(keyValue("property declaration id", propertyDeclarationId));
+
+ return propertyDeclarationId;
+}
+
+std::optional<Storage::Info::PropertyDeclaration> ProjectStorage::propertyDeclaration(
+ PropertyDeclarationId propertyDeclarationId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get property declaration"_t,
+ projectStorageCategory(),
+ keyValue("property declaration id", propertyDeclarationId)};
+
+ auto propertyDeclaration = s->selectPropertyDeclarationForPropertyDeclarationIdStatement
+ .optionalValueWithTransaction<Storage::Info::PropertyDeclaration>(
+ propertyDeclarationId);
+
+ tracer.end(keyValue("property declaration", propertyDeclaration));
+
+ return propertyDeclaration;
+}
+
+std::optional<Storage::Info::Type> ProjectStorage::type(TypeId typeId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get type"_t, projectStorageCategory(), keyValue("type id", typeId)};
+
+ auto type = s->selectInfoTypeByTypeIdStatement.optionalValueWithTransaction<Storage::Info::Type>(
+ typeId);
+
+ tracer.end(keyValue("type", type));
+
+ return type;
+}
+
+Utils::PathString ProjectStorage::typeIconPath(TypeId typeId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get type icon path"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId)};
+
+ auto typeIconPath = s->selectTypeIconPathStatement.valueWithTransaction<Utils::PathString>(typeId);
+
+ tracer.end(keyValue("type icon path", typeIconPath));
+
+ return typeIconPath;
+}
+
+Storage::Info::TypeHints ProjectStorage::typeHints(TypeId typeId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get type hints"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId)};
+
+ auto typeHints = s->selectTypeHintsStatement.valuesWithTransaction<Storage::Info::TypeHints, 4>(
+ typeId);
+
+ tracer.end(keyValue("type hints", typeHints));
+
+ return typeHints;
+}
+
+SmallSourceIds<4> ProjectStorage::typeAnnotationSourceIds(SourceId directoryId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get type annotaion source ids"_t,
+ projectStorageCategory(),
+ keyValue("source id", directoryId)};
+
+ auto sourceIds = s->selectTypeAnnotationSourceIdsStatement.valuesWithTransaction<SmallSourceIds<4>>(
+ directoryId);
+
+ tracer.end(keyValue("source ids", sourceIds));
+
+ return sourceIds;
+}
+
+SmallSourceIds<64> ProjectStorage::typeAnnotationDirectorySourceIds() const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get type annotaion source ids"_t, projectStorageCategory()};
+
+ auto sourceIds = s->selectTypeAnnotationDirectorySourceIdsStatement
+ .valuesWithTransaction<SmallSourceIds<64>>();
+
+ tracer.end(keyValue("source ids", sourceIds));
+
+ return sourceIds;
+}
+
+Storage::Info::ItemLibraryEntries ProjectStorage::itemLibraryEntries(TypeId typeId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get item library entries by type id"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId)};
+
+ using Storage::Info::ItemLibraryProperties;
+ Storage::Info::ItemLibraryEntries entries;
+
+ auto callback = [&](TypeId typeId_,
+ Utils::SmallStringView name,
+ Utils::SmallStringView iconPath,
+ Utils::SmallStringView category,
+ Utils::SmallStringView import,
+ Utils::SmallStringView toolTip,
+ Utils::SmallStringView properties,
+ Utils::SmallStringView extraFilePaths,
+ Utils::SmallStringView templatePath) {
+ auto &last = entries.emplace_back(typeId_, name, iconPath, category, import, toolTip, templatePath);
+ if (properties.size())
+ s->selectItemLibraryPropertiesStatement.readTo(last.properties, properties);
+ if (extraFilePaths.size())
+ s->selectItemLibraryExtraFilePathsStatement.readTo(last.extraFilePaths, extraFilePaths);
+ };
+
+ s->selectItemLibraryEntriesByTypeIdStatement.readCallbackWithTransaction(callback, typeId);
+
+ tracer.end(keyValue("item library entries", entries));
+
+ return entries;
+}
+
+Storage::Info::ItemLibraryEntries ProjectStorage::itemLibraryEntries(ImportId importId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get item library entries by import id"_t,
+ projectStorageCategory(),
+ keyValue("import id", importId)};
+
+ using Storage::Info::ItemLibraryProperties;
+ Storage::Info::ItemLibraryEntries entries;
+
+ auto callback = [&](TypeId typeId_,
+ Utils::SmallStringView name,
+ Utils::SmallStringView iconPath,
+ Utils::SmallStringView category,
+ Utils::SmallStringView import,
+ Utils::SmallStringView toolTip,
+ Utils::SmallStringView properties,
+ Utils::SmallStringView extraFilePaths,
+ Utils::SmallStringView templatePath) {
+ auto &last = entries.emplace_back(typeId_, name, iconPath, category, import, toolTip, templatePath);
+ if (properties.size())
+ s->selectItemLibraryPropertiesStatement.readTo(last.properties, properties);
+ if (extraFilePaths.size())
+ s->selectItemLibraryExtraFilePathsStatement.readTo(last.extraFilePaths, extraFilePaths);
+ };
+
+ s->selectItemLibraryEntriesByTypeIdStatement.readCallbackWithTransaction(callback, importId);
+
+ tracer.end(keyValue("item library entries", entries));
+
+ return entries;
+}
+
+Storage::Info::ItemLibraryEntries ProjectStorage::itemLibraryEntries(SourceId sourceId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get item library entries by source id"_t,
+ projectStorageCategory(),
+ keyValue("source id", sourceId)};
+
+ using Storage::Info::ItemLibraryProperties;
+ Storage::Info::ItemLibraryEntries entries;
+
+ auto callback = [&](TypeId typeId,
+ Utils::SmallStringView name,
+ Utils::SmallStringView iconPath,
+ Utils::SmallStringView category,
+ Utils::SmallStringView import,
+ Utils::SmallStringView toolTip,
+ Utils::SmallStringView properties,
+ Utils::SmallStringView extraFilePaths,
+ Utils::SmallStringView templatePath) {
+ auto &last = entries.emplace_back(typeId, name, iconPath, category, import, toolTip, templatePath);
+ if (properties.size())
+ s->selectItemLibraryPropertiesStatement.readTo(last.properties, properties);
+ if (extraFilePaths.size())
+ s->selectItemLibraryExtraFilePathsStatement.readTo(last.extraFilePaths, extraFilePaths);
+ };
+
+ s->selectItemLibraryEntriesBySourceIdStatement.readCallbackWithTransaction(callback, sourceId);
+
+ tracer.end(keyValue("item library entries", entries));
+
+ return entries;
+}
+
+Storage::Info::ItemLibraryEntries ProjectStorage::allItemLibraryEntries() const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get all item library entries"_t, projectStorageCategory()};
+
+ using Storage::Info::ItemLibraryProperties;
+ Storage::Info::ItemLibraryEntries entries;
+
+ auto callback = [&](TypeId typeId,
+ Utils::SmallStringView name,
+ Utils::SmallStringView iconPath,
+ Utils::SmallStringView category,
+ Utils::SmallStringView import,
+ Utils::SmallStringView toolTip,
+ Utils::SmallStringView properties,
+ Utils::SmallStringView extraFilePaths,
+ Utils::SmallStringView templatePath) {
+ auto &last = entries.emplace_back(typeId, name, iconPath, category, import, toolTip, templatePath);
+ if (properties.size())
+ s->selectItemLibraryPropertiesStatement.readTo(last.properties, properties);
+ if (extraFilePaths.size())
+ s->selectItemLibraryExtraFilePathsStatement.readTo(last.extraFilePaths, extraFilePaths);
+ };
+
+ s->selectItemLibraryEntriesStatement.readCallbackWithTransaction(callback);
+
+ tracer.end(keyValue("item library entries", entries));
+
+ return entries;
+}
+
+std::vector<Utils::SmallString> ProjectStorage::signalDeclarationNames(TypeId typeId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get signal names"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId)};
+
+ auto signalDeclarationNames = s->selectSignalDeclarationNamesForTypeStatement
+ .valuesWithTransaction<Utils::SmallString, 32>(typeId);
+
+ tracer.end(keyValue("signal names", signalDeclarationNames));
+
+ return signalDeclarationNames;
+}
+
+std::vector<Utils::SmallString> ProjectStorage::functionDeclarationNames(TypeId typeId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get function names"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId)};
+
+ auto functionDeclarationNames = s->selectFuncionDeclarationNamesForTypeStatement
+ .valuesWithTransaction<Utils::SmallString, 32>(typeId);
+
+ tracer.end(keyValue("function names", functionDeclarationNames));
+
+ return functionDeclarationNames;
+}
+
+std::optional<Utils::SmallString> ProjectStorage::propertyName(
+ PropertyDeclarationId propertyDeclarationId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get property name"_t,
+ projectStorageCategory(),
+ keyValue("property declaration id", propertyDeclarationId)};
+
+ auto propertyName = s->selectPropertyNameStatement.optionalValueWithTransaction<Utils::SmallString>(
+ propertyDeclarationId);
+
+ tracer.end(keyValue("property name", propertyName));
+
+ return propertyName;
+}
+
+SmallTypeIds<16> ProjectStorage::prototypeIds(TypeId type) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get prototypes"_t, projectStorageCategory(), keyValue("type id", type)};
+
+ auto prototypeIds = s->selectPrototypeAndExtensionIdsStatement
+ .valuesWithTransaction<SmallTypeIds<16>>(type);
+
+ tracer.end(keyValue("type ids", prototypeIds));
+
+ return prototypeIds;
+}
+
+SmallTypeIds<16> ProjectStorage::prototypeAndSelfIds(TypeId typeId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get prototypes and self"_t, projectStorageCategory()};
+
+ SmallTypeIds<16> prototypeAndSelfIds;
+ prototypeAndSelfIds.push_back(typeId);
+
+ s->selectPrototypeAndExtensionIdsStatement.readToWithTransaction(prototypeAndSelfIds, typeId);
+
+ tracer.end(keyValue("type ids", prototypeAndSelfIds));
+
+ return prototypeAndSelfIds;
+}
+
+SmallTypeIds<64> ProjectStorage::heirIds(TypeId typeId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get heirs"_t, projectStorageCategory()};
+
+ auto heirIds = s->selectHeirTypeIdsStatement.valuesWithTransaction<SmallTypeIds<64>>(typeId);
+
+ tracer.end(keyValue("type ids", heirIds));
+
+ return heirIds;
+}
+
+bool ProjectStorage::isBasedOn(TypeId) const
+{
+ return false;
+}
+
+bool ProjectStorage::isBasedOn(TypeId typeId, TypeId id1) const
+{
+ return isBasedOn_(typeId, id1);
+}
+
+bool ProjectStorage::isBasedOn(TypeId typeId, TypeId id1, TypeId id2) const
+{
+ return isBasedOn_(typeId, id1, id2);
+}
+
+bool ProjectStorage::isBasedOn(TypeId typeId, TypeId id1, TypeId id2, TypeId id3) const
+{
+ return isBasedOn_(typeId, id1, id2, id3);
+}
+
+bool ProjectStorage::isBasedOn(TypeId typeId, TypeId id1, TypeId id2, TypeId id3, TypeId id4) const
+{
+ return isBasedOn_(typeId, id1, id2, id3, id4);
+}
+
+bool ProjectStorage::isBasedOn(TypeId typeId, TypeId id1, TypeId id2, TypeId id3, TypeId id4, TypeId id5) const
+{
+ return isBasedOn_(typeId, id1, id2, id3, id4, id5);
+}
+
+bool ProjectStorage::isBasedOn(
+ TypeId typeId, TypeId id1, TypeId id2, TypeId id3, TypeId id4, TypeId id5, TypeId id6) const
+{
+ return isBasedOn_(typeId, id1, id2, id3, id4, id5, id6);
+}
+
+bool ProjectStorage::isBasedOn(
+ TypeId typeId, TypeId id1, TypeId id2, TypeId id3, TypeId id4, TypeId id5, TypeId id6, TypeId id7) const
+{
+ return isBasedOn_(typeId, id1, id2, id3, id4, id5, id6, id7);
+}
+
+TypeId ProjectStorage::fetchTypeIdByExportedName(Utils::SmallStringView name) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is based on"_t,
+ projectStorageCategory(),
+ keyValue("exported type name", name)};
+
+ auto typeId = s->selectTypeIdByExportedNameStatement.valueWithTransaction<TypeId>(name);
+
+ tracer.end(keyValue("type id", typeId));
+
+ return typeId;
+}
+
+TypeId ProjectStorage::fetchTypeIdByModuleIdsAndExportedName(ModuleIds moduleIds,
+ Utils::SmallStringView name) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch type id by module ids and exported name"_t,
+ projectStorageCategory(),
+ keyValue("module ids", NanotraceHR::array(moduleIds)),
+ keyValue("exported type name", name)};
+ auto typeId = s->selectTypeIdByModuleIdsAndExportedNameStatement.valueWithTransaction<TypeId>(
+ static_cast<void *>(moduleIds.data()), static_cast<long long>(moduleIds.size()), name);
+
+ tracer.end(keyValue("type id", typeId));
+
+ return typeId;
+}
+
+TypeId ProjectStorage::fetchTypeIdByName(SourceId sourceId, Utils::SmallStringView name)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch type id by name"_t,
+ projectStorageCategory(),
+ keyValue("source id", sourceId),
+ keyValue("internal type name", name)};
+
+ auto typeId = s->selectTypeIdBySourceIdAndNameStatement.valueWithTransaction<TypeId>(sourceId,
+ name);
+
+ tracer.end(keyValue("type id", typeId));
+
+ return typeId;
+}
+
+Storage::Synchronization::Type ProjectStorage::fetchTypeByTypeId(TypeId typeId)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch type by type id"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId)};
+
+ auto type = Sqlite::withDeferredTransaction(database, [&] {
+ auto type = s->selectTypeByTypeIdStatement.value<Storage::Synchronization::Type>(typeId);
+
+ type.exportedTypes = fetchExportedTypes(typeId);
+ type.propertyDeclarations = fetchPropertyDeclarations(type.typeId);
+ type.functionDeclarations = fetchFunctionDeclarations(type.typeId);
+ type.signalDeclarations = fetchSignalDeclarations(type.typeId);
+ type.enumerationDeclarations = fetchEnumerationDeclarations(type.typeId);
+
+ return type;
+ });
+
+ tracer.end(keyValue("type", type));
+
+ return type;
+}
+
+Storage::Synchronization::Types ProjectStorage::fetchTypes()
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch types"_t, projectStorageCategory()};
+
+ auto types = Sqlite::withDeferredTransaction(database, [&] {
+ auto types = s->selectTypesStatement.values<Storage::Synchronization::Type, 64>();
+
+ for (Storage::Synchronization::Type &type : types) {
+ type.exportedTypes = fetchExportedTypes(type.typeId);
+ type.propertyDeclarations = fetchPropertyDeclarations(type.typeId);
+ type.functionDeclarations = fetchFunctionDeclarations(type.typeId);
+ type.signalDeclarations = fetchSignalDeclarations(type.typeId);
+ type.enumerationDeclarations = fetchEnumerationDeclarations(type.typeId);
+ }
+
+ return types;
+ });
+
+ tracer.end(keyValue("type", types));
+
+ return types;
+}
+
+SourceContextId ProjectStorage::fetchSourceContextIdUnguarded(Utils::SmallStringView sourceContextPath)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch source context id unguarded"_t, projectStorageCategory()};
+
+ auto sourceContextId = readSourceContextId(sourceContextPath);
+
+ return sourceContextId ? sourceContextId : writeSourceContextId(sourceContextPath);
+}
+
+SourceContextId ProjectStorage::fetchSourceContextId(Utils::SmallStringView sourceContextPath)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch source context id"_t,
+ projectStorageCategory(),
+ keyValue("source context path", sourceContextPath)};
+
+ SourceContextId sourceContextId;
+ try {
+ sourceContextId = Sqlite::withDeferredTransaction(database, [&] {
+ return fetchSourceContextIdUnguarded(sourceContextPath);
+ });
+ } catch (const Sqlite::ConstraintPreventsModification &) {
+ sourceContextId = fetchSourceContextId(sourceContextPath);
+ }
+
+ tracer.end(keyValue("source context id", sourceContextId));
+
+ return sourceContextId;
+}
+
+Utils::PathString ProjectStorage::fetchSourceContextPath(SourceContextId sourceContextId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch source context path"_t,
+ projectStorageCategory(),
+ keyValue("source context id", sourceContextId)};
+
+ auto path = Sqlite::withDeferredTransaction(database, [&] {
+ auto optionalSourceContextPath = s->selectSourceContextPathFromSourceContextsBySourceContextIdStatement
+ .optionalValue<Utils::PathString>(sourceContextId);
+
+ if (!optionalSourceContextPath)
+ throw SourceContextIdDoesNotExists();
+
+ return std::move(*optionalSourceContextPath);
+ });
+
+ tracer.end(keyValue("source context path", path));
+
+ return path;
+}
+
+Cache::SourceContexts ProjectStorage::fetchAllSourceContexts() const
+{
+ NanotraceHR::Tracer tracer{"fetch all source contexts"_t, projectStorageCategory()};
+
+ return s->selectAllSourceContextsStatement.valuesWithTransaction<Cache::SourceContext, 128>();
+}
+
+SourceId ProjectStorage::fetchSourceId(SourceContextId sourceContextId,
+ Utils::SmallStringView sourceName)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch source id"_t,
+ projectStorageCategory(),
+ keyValue("source context id", sourceContextId),
+ keyValue("source name", sourceName)};
+
+ auto sourceId = Sqlite::withDeferredTransaction(database, [&] {
+ return fetchSourceIdUnguarded(sourceContextId, sourceName);
+ });
+
+ tracer.end(keyValue("source id", sourceId));
+
+ return sourceId;
+}
+
+Cache::SourceNameAndSourceContextId ProjectStorage::fetchSourceNameAndSourceContextId(SourceId sourceId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch source name and source context id"_t,
+ projectStorageCategory(),
+ keyValue("source id", sourceId)};
+
+ auto value = s->selectSourceNameAndSourceContextIdFromSourcesBySourceIdStatement
+ .valueWithTransaction<Cache::SourceNameAndSourceContextId>(sourceId);
+
+ if (!value.sourceContextId)
+ throw SourceIdDoesNotExists();
+
+ tracer.end(keyValue("source name", value.sourceName),
+ keyValue("source context id", value.sourceContextId));
+
+ return value;
+}
+
+void ProjectStorage::clearSources()
+{
+ Sqlite::withImmediateTransaction(database, [&] {
+ s->deleteAllSourceContextsStatement.execute();
+ s->deleteAllSourcesStatement.execute();
+ });
+}
+
+SourceContextId ProjectStorage::fetchSourceContextId(SourceId sourceId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch source context id"_t,
+ projectStorageCategory(),
+ keyValue("source id", sourceId)};
+
+ auto sourceContextId = s->selectSourceContextIdFromSourcesBySourceIdStatement
+ .valueWithTransaction<SourceContextId>(sourceId);
+
+ if (!sourceContextId)
+ throw SourceIdDoesNotExists();
+
+ tracer.end(keyValue("source context id", sourceContextId));
+
+ return sourceContextId;
+}
+
+Cache::Sources ProjectStorage::fetchAllSources() const
+{
+ NanotraceHR::Tracer tracer{"fetch all sources"_t, projectStorageCategory()};
+
+ return s->selectAllSourcesStatement.valuesWithTransaction<Cache::Source, 1024>();
+}
+
+SourceId ProjectStorage::fetchSourceIdUnguarded(SourceContextId sourceContextId,
+ Utils::SmallStringView sourceName)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch source id unguarded"_t,
+ projectStorageCategory(),
+ keyValue("source context id", sourceContextId),
+ keyValue("source name", sourceName)};
+
+ auto sourceId = readSourceId(sourceContextId, sourceName);
+
+ if (!sourceId)
+ sourceId = writeSourceId(sourceContextId, sourceName);
+
+ tracer.end(keyValue("source id", sourceId));
+
+ return sourceId;
+}
+
+FileStatuses ProjectStorage::fetchAllFileStatuses() const
+{
+ NanotraceHR::Tracer tracer{"fetch all file statuses"_t, projectStorageCategory()};
+
+ return s->selectAllFileStatusesStatement.valuesWithTransaction<FileStatus>();
+}
+
+FileStatus ProjectStorage::fetchFileStatus(SourceId sourceId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch file status"_t,
+ projectStorageCategory(),
+ keyValue("source id", sourceId)};
+
+ auto fileStatus = s->selectFileStatusesForSourceIdStatement.valueWithTransaction<FileStatus>(
+ sourceId);
+
+ tracer.end(keyValue("file status", fileStatus));
+
+ return fileStatus;
+}
+
+std::optional<Storage::Synchronization::ProjectData> ProjectStorage::fetchProjectData(SourceId sourceId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch project data"_t,
+ projectStorageCategory(),
+ keyValue("source id", sourceId)};
+
+ auto projectData = s->selectProjectDataForSourceIdStatement
+ .optionalValueWithTransaction<Storage::Synchronization::ProjectData>(
+ sourceId);
+
+ tracer.end(keyValue("project data", projectData));
+
+ return projectData;
+}
+
+Storage::Synchronization::ProjectDatas ProjectStorage::fetchProjectDatas(SourceId projectSourceId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch project datas by source id"_t,
+ projectStorageCategory(),
+ keyValue("source id", projectSourceId)};
+
+ auto projectDatas = s->selectProjectDatasForSourceIdStatement
+ .valuesWithTransaction<Storage::Synchronization::ProjectData, 1024>(
+ projectSourceId);
+
+ tracer.end(keyValue("project datas", projectDatas));
+
+ return projectDatas;
+}
+
+Storage::Synchronization::ProjectDatas ProjectStorage::fetchProjectDatas(
+ const SourceIds &projectSourceIds) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch project datas by source ids"_t,
+ projectStorageCategory(),
+ keyValue("source ids", projectSourceIds)};
+
+ auto projectDatas = s->selectProjectDatasForSourceIdsStatement
+ .valuesWithTransaction<Storage::Synchronization::ProjectData, 64>(
+ toIntegers(projectSourceIds));
+
+ tracer.end(keyValue("project datas", projectDatas));
+
+ return projectDatas;
+}
+
+void ProjectStorage::setPropertyEditorPathId(TypeId typeId, SourceId pathId)
+{
+ Sqlite::ImmediateSessionTransaction transaction{database};
+
+ s->upsertPropertyEditorPathIdStatement.write(typeId, pathId);
+
+ transaction.commit();
+}
+
+SourceId ProjectStorage::propertyEditorPathId(TypeId typeId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"property editor path id"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId)};
+
+ auto sourceId = s->selectPropertyEditorPathIdStatement.valueWithTransaction<SourceId>(typeId);
+
+ tracer.end(keyValue("source id", sourceId));
+
+ return sourceId;
+}
+
+Storage::Imports ProjectStorage::fetchDocumentImports() const
+{
+ NanotraceHR::Tracer tracer{"fetch document imports"_t, projectStorageCategory()};
+
+ return s->selectAllDocumentImportForSourceIdStatement.valuesWithTransaction<Storage::Imports>();
+}
+
+void ProjectStorage::resetForTestsOnly()
+{
+ database.clearAllTablesForTestsOnly();
+ commonTypeCache_.clearForTestsOnly();
+ moduleCache.clearForTestOnly();
+}
+
+bool ProjectStorage::moduleNameLess(Utils::SmallStringView first, Utils::SmallStringView second) noexcept
+{
+ return first < second;
+}
+
+ModuleId ProjectStorage::fetchModuleId(Utils::SmallStringView moduleName)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch module id"_t,
+ projectStorageCategory(),
+ keyValue("module name", moduleName)};
+
+ auto moduleId = Sqlite::withDeferredTransaction(database, [&] {
+ return fetchModuleIdUnguarded(moduleName);
+ });
+
+ tracer.end(keyValue("module id", moduleId));
+
+ return moduleId;
+}
+
+Utils::PathString ProjectStorage::fetchModuleName(ModuleId id)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch module name"_t,
+ projectStorageCategory(),
+ keyValue("module id", id)};
+
+ auto moduleName = Sqlite::withDeferredTransaction(database,
+ [&] { return fetchModuleNameUnguarded(id); });
+
+ tracer.end(keyValue("module name", moduleName));
+
+ return moduleName;
+}
+
+ProjectStorage::Modules ProjectStorage::fetchAllModules() const
+{
+ NanotraceHR::Tracer tracer{"fetch all modules"_t, projectStorageCategory()};
+
+ return s->selectAllModulesStatement.valuesWithTransaction<Module, 128>();
+}
+
+void ProjectStorage::callRefreshMetaInfoCallback(const TypeIds &deletedTypeIds)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"call refresh meta info callback"_t,
+ projectStorageCategory(),
+ keyValue("type ids", deletedTypeIds)};
+
+ if (deletedTypeIds.size()) {
+ for (ProjectStorageObserver *observer : observers)
+ observer->removedTypeIds(deletedTypeIds);
+ }
+}
+
+SourceIds ProjectStorage::filterSourceIdsWithoutType(const SourceIds &updatedSourceIds,
+ SourceIds &sourceIdsOfTypes)
+{
+ std::sort(sourceIdsOfTypes.begin(), sourceIdsOfTypes.end());
+
+ SourceIds sourceIdsWithoutTypeSourceIds;
+ sourceIdsWithoutTypeSourceIds.reserve(updatedSourceIds.size());
+ std::set_difference(updatedSourceIds.begin(),
+ updatedSourceIds.end(),
+ sourceIdsOfTypes.begin(),
+ sourceIdsOfTypes.end(),
+ std::back_inserter(sourceIdsWithoutTypeSourceIds));
+
+ return sourceIdsWithoutTypeSourceIds;
+}
+
+TypeIds ProjectStorage::fetchTypeIds(const SourceIds &sourceIds)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch type ids"_t,
+ projectStorageCategory(),
+ keyValue("source ids", sourceIds)};
+
+ return s->selectTypeIdsForSourceIdsStatement.values<TypeId, 128>(toIntegers(sourceIds));
+}
+
+void ProjectStorage::unique(SourceIds &sourceIds)
+{
+ std::sort(sourceIds.begin(), sourceIds.end());
+ auto newEnd = std::unique(sourceIds.begin(), sourceIds.end());
+ sourceIds.erase(newEnd, sourceIds.end());
+}
+
+void ProjectStorage::synchronizeTypeTraits(TypeId typeId, Storage::TypeTraits traits)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"synchronize type traits"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId),
+ keyValue("type traits", traits)};
+
+ s->updateTypeAnnotationTraitStatement.write(typeId, traits.annotation);
+}
+
+void ProjectStorage::updateTypeIdInTypeAnnotations(Storage::Synchronization::TypeAnnotations &typeAnnotations)
+{
+ NanotraceHR::Tracer tracer{"update type id in type annotations"_t, projectStorageCategory()};
+
+ for (auto &annotation : typeAnnotations) {
+ annotation.typeId = fetchTypeIdByModuleIdAndExportedName(annotation.moduleId,
+ annotation.typeName);
+ }
+
+ for (auto &annotation : typeAnnotations) {
+ if (!annotation.typeId)
+ qWarning() << moduleName(annotation.moduleId).toQString()
+ << annotation.typeName.toQString();
+ }
+
+ typeAnnotations.erase(std::remove_if(typeAnnotations.begin(),
+ typeAnnotations.end(),
+ [](const auto &annotation) { return !annotation.typeId; }),
+ typeAnnotations.end());
+}
+
+void ProjectStorage::synchronizeTypeAnnotations(Storage::Synchronization::TypeAnnotations &typeAnnotations,
+ const SourceIds &updatedTypeAnnotationSourceIds)
+{
+ NanotraceHR::Tracer tracer{"synchronize type annotations"_t, projectStorageCategory()};
+
+ using Storage::Synchronization::TypeAnnotation;
+
+ updateTypeIdInTypeAnnotations(typeAnnotations);
+
+ auto compareKey = [](auto &&first, auto &&second) { return first.typeId - second.typeId; };
+
+ std::sort(typeAnnotations.begin(), typeAnnotations.end(), [&](auto &&first, auto &&second) {
+ return first.typeId < second.typeId;
+ });
+
+ auto range = s->selectTypeAnnotationsForSourceIdsStatement.range<TypeAnnotationView>(
+ toIntegers(updatedTypeAnnotationSourceIds));
+
+ auto insert = [&](const TypeAnnotation &annotation) {
+ if (!annotation.sourceId)
+ throw TypeAnnotationHasInvalidSourceId{};
+
+ synchronizeTypeTraits(annotation.typeId, annotation.traits);
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"insert type annotations"_t,
+ projectStorageCategory(),
+ keyValue("type annotation", annotation)};
+
+ s->insertTypeAnnotationStatement.write(annotation.typeId,
+ annotation.sourceId,
+ annotation.directorySourceId,
+ annotation.iconPath,
+ createEmptyAsNull(annotation.itemLibraryJson),
+ createEmptyAsNull(annotation.hintsJson));
+ };
+
+ auto update = [&](const TypeAnnotationView &annotationFromDatabase,
+ const TypeAnnotation &annotation) {
+ synchronizeTypeTraits(annotation.typeId, annotation.traits);
+
+ if (annotationFromDatabase.iconPath != annotation.iconPath
+ || annotationFromDatabase.itemLibraryJson != annotation.itemLibraryJson
+ || annotationFromDatabase.hintsJson != annotation.hintsJson) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"update type annotations"_t,
+ projectStorageCategory(),
+ keyValue("type annotation from database",
+ annotationFromDatabase),
+ keyValue("type annotation", annotation)};
+
+ s->updateTypeAnnotationStatement.write(annotation.typeId,
+ annotation.iconPath,
+ createEmptyAsNull(annotation.itemLibraryJson),
+ createEmptyAsNull(annotation.hintsJson));
+ return Sqlite::UpdateChange::Update;
+ }
+
+ return Sqlite::UpdateChange::No;
+ };
+
+ auto remove = [&](const TypeAnnotationView &annotationFromDatabase) {
+ synchronizeTypeTraits(annotationFromDatabase.typeId, Storage::TypeTraits{});
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"remove type annotations"_t,
+ projectStorageCategory(),
+ keyValue("type annotation", annotationFromDatabase)};
+
+ s->deleteTypeAnnotationStatement.write(annotationFromDatabase.typeId);
+ };
+
+ Sqlite::insertUpdateDelete(range, typeAnnotations, compareKey, insert, update, remove);
+}
+
+void ProjectStorage::synchronizeTypeTrait(const Storage::Synchronization::Type &type)
+{
+ s->updateTypeTraitStatement.write(type.typeId, type.traits.type);
+}
+
+void ProjectStorage::synchronizeTypes(Storage::Synchronization::Types &types,
+ TypeIds &updatedTypeIds,
+ AliasPropertyDeclarations &insertedAliasPropertyDeclarations,
+ AliasPropertyDeclarations &updatedAliasPropertyDeclarations,
+ AliasPropertyDeclarations &relinkableAliasPropertyDeclarations,
+ PropertyDeclarations &relinkablePropertyDeclarations,
+ Prototypes &relinkablePrototypes,
+ Prototypes &relinkableExtensions,
+ const SourceIds &updatedSourceIds)
+{
+ NanotraceHR::Tracer tracer{"synchronize types"_t, projectStorageCategory()};
+
+ Storage::Synchronization::ExportedTypes exportedTypes;
+ exportedTypes.reserve(types.size() * 3);
+ SourceIds sourceIdsOfTypes;
+ sourceIdsOfTypes.reserve(updatedSourceIds.size());
+ SourceIds notUpdatedExportedSourceIds;
+ notUpdatedExportedSourceIds.reserve(updatedSourceIds.size());
+ SourceIds exportedSourceIds;
+ exportedSourceIds.reserve(types.size());
+
+ for (auto &type : types) {
+ if (!type.sourceId)
+ throw TypeHasInvalidSourceId{};
+
+ TypeId typeId = declareType(type);
+ synchronizeTypeTrait(type);
+ sourceIdsOfTypes.push_back(type.sourceId);
+ updatedTypeIds.push_back(typeId);
+ if (type.changeLevel != Storage::Synchronization::ChangeLevel::ExcludeExportedTypes) {
+ exportedSourceIds.push_back(type.sourceId);
+ extractExportedTypes(typeId, type, exportedTypes);
+ }
+ }
+
+ std::sort(types.begin(), types.end(), [](const auto &first, const auto &second) {
+ return first.typeId < second.typeId;
+ });
+
+ unique(exportedSourceIds);
+
+ SourceIds sourceIdsWithoutType = filterSourceIdsWithoutType(updatedSourceIds, sourceIdsOfTypes);
+ exportedSourceIds.insert(exportedSourceIds.end(),
+ sourceIdsWithoutType.begin(),
+ sourceIdsWithoutType.end());
+ TypeIds exportedTypeIds = fetchTypeIds(exportedSourceIds);
+ synchronizeExportedTypes(exportedTypeIds,
+ exportedTypes,
+ relinkableAliasPropertyDeclarations,
+ relinkablePropertyDeclarations,
+ relinkablePrototypes,
+ relinkableExtensions);
+
+ syncPrototypesAndExtensions(types, relinkablePrototypes, relinkableExtensions);
+ resetDefaultPropertiesIfChanged(types);
+ resetRemovedAliasPropertyDeclarationsToNull(types, relinkableAliasPropertyDeclarations);
+ syncDeclarations(types,
+ insertedAliasPropertyDeclarations,
+ updatedAliasPropertyDeclarations,
+ relinkablePropertyDeclarations);
+ syncDefaultProperties(types);
+}
+
+void ProjectStorage::synchronizeProjectDatas(Storage::Synchronization::ProjectDatas &projectDatas,
+ const SourceIds &updatedProjectSourceIds)
+{
+ NanotraceHR::Tracer tracer{"synchronize project datas"_t, projectStorageCategory()};
+
+ auto compareKey = [](auto &&first, auto &&second) {
+ auto projectSourceIdDifference = first.projectSourceId - second.projectSourceId;
+ if (projectSourceIdDifference != 0)
+ return projectSourceIdDifference;
+
+ return first.sourceId - second.sourceId;
+ };
+
+ std::sort(projectDatas.begin(), projectDatas.end(), [&](auto &&first, auto &&second) {
+ return std::tie(first.projectSourceId, first.sourceId)
+ < std::tie(second.projectSourceId, second.sourceId);
+ });
+
+ auto range = s->selectProjectDatasForSourceIdsStatement.range<Storage::Synchronization::ProjectData>(
+ toIntegers(updatedProjectSourceIds));
+
+ auto insert = [&](const Storage::Synchronization::ProjectData &projectData) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"insert project data"_t,
+ projectStorageCategory(),
+ keyValue("project data", projectData)};
+
+ if (!projectData.projectSourceId)
+ throw ProjectDataHasInvalidProjectSourceId{};
+ if (!projectData.sourceId)
+ throw ProjectDataHasInvalidSourceId{};
+
+ s->insertProjectDataStatement.write(projectData.projectSourceId,
+ projectData.sourceId,
+ projectData.moduleId,
+ projectData.fileType);
+ };
+
+ auto update = [&](const Storage::Synchronization::ProjectData &projectDataFromDatabase,
+ const Storage::Synchronization::ProjectData &projectData) {
+ if (projectDataFromDatabase.fileType != projectData.fileType
+ || !compareInvalidAreTrue(projectDataFromDatabase.moduleId, projectData.moduleId)) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"update project data"_t,
+ projectStorageCategory(),
+ keyValue("project data", projectData),
+ keyValue("project data from database", projectDataFromDatabase)};
+
+ s->updateProjectDataStatement.write(projectData.projectSourceId,
+ projectData.sourceId,
+ projectData.moduleId,
+ projectData.fileType);
+ return Sqlite::UpdateChange::Update;
+ }
+
+ return Sqlite::UpdateChange::No;
+ };
+
+ auto remove = [&](const Storage::Synchronization::ProjectData &projectData) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"remove project data"_t,
+ projectStorageCategory(),
+ keyValue("project data", projectData)};
+
+ s->deleteProjectDataStatement.write(projectData.projectSourceId, projectData.sourceId);
+ };
+
+ Sqlite::insertUpdateDelete(range, projectDatas, compareKey, insert, update, remove);
+}
+
+void ProjectStorage::synchronizeFileStatuses(FileStatuses &fileStatuses,
+ const SourceIds &updatedSourceIds)
+{
+ NanotraceHR::Tracer tracer{"synchronize file statuses"_t, projectStorageCategory()};
+
+ auto compareKey = [](auto &&first, auto &&second) { return first.sourceId - second.sourceId; };
+
+ std::sort(fileStatuses.begin(), fileStatuses.end(), [&](auto &&first, auto &&second) {
+ return first.sourceId < second.sourceId;
+ });
+
+ auto range = s->selectFileStatusesForSourceIdsStatement.range<FileStatus>(
+ toIntegers(updatedSourceIds));
+
+ auto insert = [&](const FileStatus &fileStatus) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"insert file status"_t,
+ projectStorageCategory(),
+ keyValue("file status", fileStatus)};
+
+ if (!fileStatus.sourceId)
+ throw FileStatusHasInvalidSourceId{};
+ s->insertFileStatusStatement.write(fileStatus.sourceId,
+ fileStatus.size,
+ fileStatus.lastModified);
+ };
+
+ auto update = [&](const FileStatus &fileStatusFromDatabase, const FileStatus &fileStatus) {
+ if (fileStatusFromDatabase.lastModified != fileStatus.lastModified
+ || fileStatusFromDatabase.size != fileStatus.size) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"update file status"_t,
+ projectStorageCategory(),
+ keyValue("file status", fileStatus),
+ keyValue("file status from database", fileStatusFromDatabase)};
+
+ s->updateFileStatusStatement.write(fileStatus.sourceId,
+ fileStatus.size,
+ fileStatus.lastModified);
+ return Sqlite::UpdateChange::Update;
+ }
+
+ return Sqlite::UpdateChange::No;
+ };
+
+ auto remove = [&](const FileStatus &fileStatus) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"remove file status"_t,
+ projectStorageCategory(),
+ keyValue("file status", fileStatus)};
+
+ s->deleteFileStatusStatement.write(fileStatus.sourceId);
+ };
+
+ Sqlite::insertUpdateDelete(range, fileStatuses, compareKey, insert, update, remove);
+}
+
+void ProjectStorage::synchronizeImports(Storage::Imports &imports,
+ const SourceIds &updatedSourceIds,
+ Storage::Imports &moduleDependencies,
+ const SourceIds &updatedModuleDependencySourceIds,
+ Storage::Synchronization::ModuleExportedImports &moduleExportedImports,
+ const ModuleIds &updatedModuleIds)
+{
+ NanotraceHR::Tracer tracer{"synchronize imports"_t, projectStorageCategory()};
-template class QmlDesigner::ProjectStorage<Sqlite::Database>;
+ synchromizeModuleExportedImports(moduleExportedImports, updatedModuleIds);
+ NanotraceHR::Tracer importTracer{"synchronize qml document imports"_t, projectStorageCategory()};
+ synchronizeDocumentImports(imports, updatedSourceIds, Storage::Synchronization::ImportKind::Import);
+ importTracer.end();
+ NanotraceHR::Tracer moduleDependenciesTracer{"synchronize module depdencies"_t,
+ projectStorageCategory()};
+ synchronizeDocumentImports(moduleDependencies,
+ updatedModuleDependencySourceIds,
+ Storage::Synchronization::ImportKind::ModuleDependency);
+ moduleDependenciesTracer.end();
+}
+
+void ProjectStorage::synchromizeModuleExportedImports(
+ Storage::Synchronization::ModuleExportedImports &moduleExportedImports,
+ const ModuleIds &updatedModuleIds)
+{
+ NanotraceHR::Tracer tracer{"synchronize module exported imports"_t, projectStorageCategory()};
+ std::sort(moduleExportedImports.begin(),
+ moduleExportedImports.end(),
+ [](auto &&first, auto &&second) {
+ return std::tie(first.moduleId, first.exportedModuleId)
+ < std::tie(second.moduleId, second.exportedModuleId);
+ });
+
+ auto range = s->selectModuleExportedImportsForSourceIdStatement
+ .range<Storage::Synchronization::ModuleExportedImportView>(
+ toIntegers(updatedModuleIds));
+
+ auto compareKey = [](const Storage::Synchronization::ModuleExportedImportView &view,
+ const Storage::Synchronization::ModuleExportedImport &import) -> long long {
+ auto moduleIdDifference = view.moduleId - import.moduleId;
+ if (moduleIdDifference != 0)
+ return moduleIdDifference;
+
+ return view.exportedModuleId - import.exportedModuleId;
+ };
+
+ auto insert = [&](const Storage::Synchronization::ModuleExportedImport &import) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"insert module exported import"_t,
+ projectStorageCategory(),
+ keyValue("module exported import", import),
+ keyValue("module id", import.moduleId)};
+ tracer.tick("exported module"_t, keyValue("module id", import.exportedModuleId));
+
+ if (import.version.minor) {
+ s->insertModuleExportedImportWithVersionStatement.write(import.moduleId,
+ import.exportedModuleId,
+ import.isAutoVersion,
+ import.version.major.value,
+ import.version.minor.value);
+ } else if (import.version.major) {
+ s->insertModuleExportedImportWithMajorVersionStatement.write(import.moduleId,
+ import.exportedModuleId,
+ import.isAutoVersion,
+ import.version.major.value);
+ } else {
+ s->insertModuleExportedImportWithoutVersionStatement.write(import.moduleId,
+ import.exportedModuleId,
+ import.isAutoVersion);
+ }
+ };
+
+ auto update = [](const Storage::Synchronization::ModuleExportedImportView &,
+ const Storage::Synchronization::ModuleExportedImport &) {
+ return Sqlite::UpdateChange::No;
+ };
+
+ auto remove = [&](const Storage::Synchronization::ModuleExportedImportView &view) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"remove module exported import"_t,
+ projectStorageCategory(),
+ keyValue("module exported import view", view),
+ keyValue("module id", view.moduleId)};
+ tracer.tick("exported module"_t, keyValue("module id", view.exportedModuleId));
+
+ s->deleteModuleExportedImportStatement.write(view.moduleExportedImportId);
+ };
+
+ Sqlite::insertUpdateDelete(range, moduleExportedImports, compareKey, insert, update, remove);
+}
+
+ModuleId ProjectStorage::fetchModuleIdUnguarded(Utils::SmallStringView name) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch module id ungarded"_t,
+ projectStorageCategory(),
+ keyValue("module name", name)};
+
+ auto moduleId = s->selectModuleIdByNameStatement.value<ModuleId>(name);
+
+ if (!moduleId)
+ moduleId = s->insertModuleNameStatement.value<ModuleId>(name);
+
+ tracer.end(keyValue("module id", moduleId));
+
+ return moduleId;
+}
+
+Utils::PathString ProjectStorage::fetchModuleNameUnguarded(ModuleId id) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch module name ungarded"_t,
+ projectStorageCategory(),
+ keyValue("module id", id)};
+
+ auto moduleName = s->selectModuleNameStatement.value<Utils::PathString>(id);
+
+ if (moduleName.empty())
+ throw ModuleDoesNotExists{};
+
+ tracer.end(keyValue("module name", moduleName));
+
+ return moduleName;
+}
+
+void ProjectStorage::handleAliasPropertyDeclarationsWithPropertyType(
+ TypeId typeId, AliasPropertyDeclarations &relinkableAliasPropertyDeclarations)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"handle alias property declarations with property type"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId),
+ keyValue("relinkable alias property declarations",
+ relinkableAliasPropertyDeclarations)};
+
+ auto callback = [&](TypeId typeId_,
+ PropertyDeclarationId propertyDeclarationId,
+ ImportedTypeNameId propertyImportedTypeNameId,
+ PropertyDeclarationId aliasPropertyDeclarationId,
+ PropertyDeclarationId aliasPropertyDeclarationTailId) {
+ auto aliasPropertyName = s->selectPropertyNameStatement.value<Utils::SmallString>(
+ aliasPropertyDeclarationId);
+ Utils::SmallString aliasPropertyNameTail;
+ if (aliasPropertyDeclarationTailId)
+ aliasPropertyNameTail = s->selectPropertyNameStatement.value<Utils::SmallString>(
+ aliasPropertyDeclarationTailId);
+
+ relinkableAliasPropertyDeclarations.emplace_back(TypeId{typeId_},
+ PropertyDeclarationId{propertyDeclarationId},
+ ImportedTypeNameId{propertyImportedTypeNameId},
+ std::move(aliasPropertyName),
+ std::move(aliasPropertyNameTail));
+
+ s->updateAliasPropertyDeclarationToNullStatement.write(propertyDeclarationId);
+ };
+
+ s->selectAliasPropertiesDeclarationForPropertiesWithTypeIdStatement.readCallback(callback, typeId);
+}
+
+void ProjectStorage::handlePropertyDeclarationWithPropertyType(
+ TypeId typeId, PropertyDeclarations &relinkablePropertyDeclarations)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"handle property declarations with property type"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId),
+ keyValue("relinkable property declarations",
+ relinkablePropertyDeclarations)};
+
+ s->updatesPropertyDeclarationPropertyTypeToNullStatement.readTo(relinkablePropertyDeclarations,
+ typeId);
+}
+
+void ProjectStorage::handlePrototypes(TypeId prototypeId, Prototypes &relinkablePrototypes)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"handle prototypes"_t,
+ projectStorageCategory(),
+ keyValue("type id", prototypeId),
+ keyValue("relinkable prototypes", relinkablePrototypes)};
+
+ auto callback = [&](TypeId typeId, ImportedTypeNameId prototypeNameId) {
+ relinkablePrototypes.emplace_back(typeId, prototypeNameId);
+ };
+
+ s->updatePrototypeIdToNullStatement.readCallback(callback, prototypeId);
+}
+
+void ProjectStorage::handleExtensions(TypeId extensionId, Prototypes &relinkableExtensions)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"handle extension"_t,
+ projectStorageCategory(),
+ keyValue("type id", extensionId),
+ keyValue("relinkable extensions", relinkableExtensions)};
+
+ auto callback = [&](TypeId typeId, ImportedTypeNameId extensionNameId) {
+ relinkableExtensions.emplace_back(typeId, extensionNameId);
+ };
+
+ s->updateExtensionIdToNullStatement.readCallback(callback, extensionId);
+}
+
+void ProjectStorage::deleteType(TypeId typeId,
+ AliasPropertyDeclarations &relinkableAliasPropertyDeclarations,
+ PropertyDeclarations &relinkablePropertyDeclarations,
+ Prototypes &relinkablePrototypes,
+ Prototypes &relinkableExtensions)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"delete type"_t, projectStorageCategory(), keyValue("type id", typeId)};
+
+ handlePropertyDeclarationWithPropertyType(typeId, relinkablePropertyDeclarations);
+ handleAliasPropertyDeclarationsWithPropertyType(typeId, relinkableAliasPropertyDeclarations);
+ handlePrototypes(typeId, relinkablePrototypes);
+ handleExtensions(typeId, relinkableExtensions);
+ s->deleteTypeNamesByTypeIdStatement.write(typeId);
+ s->deleteEnumerationDeclarationByTypeIdStatement.write(typeId);
+ s->deletePropertyDeclarationByTypeIdStatement.write(typeId);
+ s->deleteFunctionDeclarationByTypeIdStatement.write(typeId);
+ s->deleteSignalDeclarationByTypeIdStatement.write(typeId);
+ s->deleteTypeStatement.write(typeId);
+}
+
+void ProjectStorage::relinkAliasPropertyDeclarations(AliasPropertyDeclarations &aliasPropertyDeclarations,
+ const TypeIds &deletedTypeIds)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"relink alias properties"_t,
+ projectStorageCategory(),
+ keyValue("alias property declarations", aliasPropertyDeclarations),
+ keyValue("deleted type ids", deletedTypeIds)};
+
+ std::sort(aliasPropertyDeclarations.begin(), aliasPropertyDeclarations.end());
+
+ Utils::set_greedy_difference(
+ aliasPropertyDeclarations.cbegin(),
+ aliasPropertyDeclarations.cend(),
+ deletedTypeIds.begin(),
+ deletedTypeIds.end(),
+ [&](const AliasPropertyDeclaration &alias) {
+ auto typeId = fetchTypeId(alias.aliasImportedTypeNameId);
+
+ if (!typeId)
+ throw TypeNameDoesNotExists{fetchImportedTypeName(alias.aliasImportedTypeNameId)};
+
+ auto [propertyTypeId, aliasId, propertyTraits] = fetchPropertyDeclarationByTypeIdAndNameUngarded(
+ typeId, alias.aliasPropertyName);
+
+ s->updatePropertyDeclarationWithAliasAndTypeStatement.write(alias.propertyDeclarationId,
+ propertyTypeId,
+ propertyTraits,
+ alias.aliasImportedTypeNameId,
+ aliasId);
+ },
+ TypeCompare<AliasPropertyDeclaration>{});
+}
+
+void ProjectStorage::relinkPropertyDeclarations(PropertyDeclarations &relinkablePropertyDeclaration,
+ const TypeIds &deletedTypeIds)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"relink property declarations"_t,
+ projectStorageCategory(),
+ keyValue("relinkable property declarations",
+ relinkablePropertyDeclaration),
+ keyValue("deleted type ids", deletedTypeIds)};
+
+ std::sort(relinkablePropertyDeclaration.begin(), relinkablePropertyDeclaration.end());
+
+ Utils::set_greedy_difference(
+ relinkablePropertyDeclaration.cbegin(),
+ relinkablePropertyDeclaration.cend(),
+ deletedTypeIds.begin(),
+ deletedTypeIds.end(),
+ [&](const PropertyDeclaration &property) {
+ TypeId propertyTypeId = fetchTypeId(property.importedTypeNameId);
+
+ if (!propertyTypeId)
+ throw TypeNameDoesNotExists{fetchImportedTypeName(property.importedTypeNameId)};
+
+ s->updatePropertyDeclarationTypeStatement.write(property.propertyDeclarationId,
+ propertyTypeId);
+ },
+ TypeCompare<PropertyDeclaration>{});
+}
+
+void ProjectStorage::deleteNotUpdatedTypes(const TypeIds &updatedTypeIds,
+ const SourceIds &updatedSourceIds,
+ const TypeIds &typeIdsToBeDeleted,
+ AliasPropertyDeclarations &relinkableAliasPropertyDeclarations,
+ PropertyDeclarations &relinkablePropertyDeclarations,
+ Prototypes &relinkablePrototypes,
+ Prototypes &relinkableExtensions,
+ TypeIds &deletedTypeIds)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"delete not updated types"_t,
+ projectStorageCategory(),
+ keyValue("updated type ids", updatedTypeIds),
+ keyValue("updated source ids", updatedSourceIds),
+ keyValue("type ids to be deleted", typeIdsToBeDeleted)};
+
+ auto callback = [&](TypeId typeId) {
+ deletedTypeIds.push_back(typeId);
+ deleteType(typeId,
+ relinkableAliasPropertyDeclarations,
+ relinkablePropertyDeclarations,
+ relinkablePrototypes,
+ relinkableExtensions);
+ };
+
+ s->selectNotUpdatedTypesInSourcesStatement.readCallback(callback,
+ toIntegers(updatedSourceIds),
+ toIntegers(updatedTypeIds));
+ for (TypeId typeIdToBeDeleted : typeIdsToBeDeleted)
+ callback(typeIdToBeDeleted);
+}
+
+void ProjectStorage::relink(AliasPropertyDeclarations &relinkableAliasPropertyDeclarations,
+ PropertyDeclarations &relinkablePropertyDeclarations,
+ Prototypes &relinkablePrototypes,
+ Prototypes &relinkableExtensions,
+ TypeIds &deletedTypeIds)
+{
+ NanotraceHR::Tracer tracer{"relink"_t, projectStorageCategory()};
+
+ std::sort(deletedTypeIds.begin(), deletedTypeIds.end());
+
+ relinkPrototypes(relinkablePrototypes, deletedTypeIds, [&](TypeId typeId, TypeId prototypeId) {
+ s->updateTypePrototypeStatement.write(typeId, prototypeId);
+ });
+ relinkPrototypes(relinkableExtensions, deletedTypeIds, [&](TypeId typeId, TypeId prototypeId) {
+ s->updateTypeExtensionStatement.write(typeId, prototypeId);
+ });
+ relinkPropertyDeclarations(relinkablePropertyDeclarations, deletedTypeIds);
+ relinkAliasPropertyDeclarations(relinkableAliasPropertyDeclarations, deletedTypeIds);
+}
+
+PropertyDeclarationId ProjectStorage::fetchAliasId(TypeId aliasTypeId,
+ Utils::SmallStringView aliasPropertyName,
+ Utils::SmallStringView aliasPropertyNameTail)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch alias id"_t,
+ projectStorageCategory(),
+ keyValue("alias type id", aliasTypeId),
+ keyValue("alias property name", aliasPropertyName),
+ keyValue("alias property name tail", aliasPropertyNameTail)};
+
+ if (aliasPropertyNameTail.empty())
+ return fetchPropertyDeclarationIdByTypeIdAndNameUngarded(aliasTypeId, aliasPropertyName);
+
+ auto stemAlias = fetchPropertyDeclarationByTypeIdAndNameUngarded(aliasTypeId, aliasPropertyName);
+
+ return fetchPropertyDeclarationIdByTypeIdAndNameUngarded(stemAlias.propertyTypeId,
+ aliasPropertyNameTail);
+}
+
+void ProjectStorage::linkAliasPropertyDeclarationAliasIds(const AliasPropertyDeclarations &aliasDeclarations)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"link alias property declarations alias ids"_t,
+ projectStorageCategory(),
+ keyValue("alias property declarations", aliasDeclarations)};
+
+ for (const auto &aliasDeclaration : aliasDeclarations) {
+ auto aliasTypeId = fetchTypeId(aliasDeclaration.aliasImportedTypeNameId);
+
+ if (!aliasTypeId) {
+ throw TypeNameDoesNotExists{
+ fetchImportedTypeName(aliasDeclaration.aliasImportedTypeNameId)};
+ }
+
+ auto aliasId = fetchAliasId(aliasTypeId,
+ aliasDeclaration.aliasPropertyName,
+ aliasDeclaration.aliasPropertyNameTail);
+
+ s->updatePropertyDeclarationAliasIdAndTypeNameIdStatement.write(
+ aliasDeclaration.propertyDeclarationId, aliasId, aliasDeclaration.aliasImportedTypeNameId);
+ }
+}
+
+void ProjectStorage::updateAliasPropertyDeclarationValues(const AliasPropertyDeclarations &aliasDeclarations)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"update alias property declarations"_t,
+ projectStorageCategory(),
+ keyValue("alias property declarations", aliasDeclarations)};
+
+ for (const auto &aliasDeclaration : aliasDeclarations) {
+ s->updatetPropertiesDeclarationValuesOfAliasStatement.write(
+ aliasDeclaration.propertyDeclarationId);
+ s->updatePropertyAliasDeclarationRecursivelyStatement.write(
+ aliasDeclaration.propertyDeclarationId);
+ }
+}
+
+void ProjectStorage::checkAliasPropertyDeclarationCycles(const AliasPropertyDeclarations &aliasDeclarations)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"check alias property declarations cycles"_t,
+ projectStorageCategory(),
+ keyValue("alias property declarations", aliasDeclarations)};
+ for (const auto &aliasDeclaration : aliasDeclarations)
+ checkForAliasChainCycle(aliasDeclaration.propertyDeclarationId);
+}
+
+void ProjectStorage::linkAliases(const AliasPropertyDeclarations &insertedAliasPropertyDeclarations,
+ const AliasPropertyDeclarations &updatedAliasPropertyDeclarations)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"link aliases"_t, projectStorageCategory()};
+
+ linkAliasPropertyDeclarationAliasIds(insertedAliasPropertyDeclarations);
+ linkAliasPropertyDeclarationAliasIds(updatedAliasPropertyDeclarations);
+
+ checkAliasPropertyDeclarationCycles(insertedAliasPropertyDeclarations);
+ checkAliasPropertyDeclarationCycles(updatedAliasPropertyDeclarations);
+
+ updateAliasPropertyDeclarationValues(insertedAliasPropertyDeclarations);
+ updateAliasPropertyDeclarationValues(updatedAliasPropertyDeclarations);
+}
+
+void ProjectStorage::synchronizeExportedTypes(const TypeIds &updatedTypeIds,
+ Storage::Synchronization::ExportedTypes &exportedTypes,
+ AliasPropertyDeclarations &relinkableAliasPropertyDeclarations,
+ PropertyDeclarations &relinkablePropertyDeclarations,
+ Prototypes &relinkablePrototypes,
+ Prototypes &relinkableExtensions)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"synchronize exported types"_t, projectStorageCategory()};
+
+ std::sort(exportedTypes.begin(), exportedTypes.end(), [](auto &&first, auto &&second) {
+ if (first.moduleId < second.moduleId)
+ return true;
+ else if (first.moduleId > second.moduleId)
+ return false;
+
+ auto nameCompare = Sqlite::compare(first.name, second.name);
+
+ if (nameCompare < 0)
+ return true;
+ else if (nameCompare > 0)
+ return false;
+
+ return first.version < second.version;
+ });
+
+ auto range = s->selectExportedTypesForSourceIdsStatement
+ .range<Storage::Synchronization::ExportedTypeView>(toIntegers(updatedTypeIds));
+
+ auto compareKey = [](const Storage::Synchronization::ExportedTypeView &view,
+ const Storage::Synchronization::ExportedType &type) -> long long {
+ auto moduleIdDifference = view.moduleId - type.moduleId;
+ if (moduleIdDifference != 0)
+ return moduleIdDifference;
+
+ auto nameDifference = Sqlite::compare(view.name, type.name);
+ if (nameDifference != 0)
+ return nameDifference;
+
+ auto versionDifference = view.version.major.value - type.version.major.value;
+ if (versionDifference != 0)
+ return versionDifference;
+
+ return view.version.minor.value - type.version.minor.value;
+ };
+
+ auto insert = [&](const Storage::Synchronization::ExportedType &type) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"insert exported type"_t,
+ projectStorageCategory(),
+ keyValue("exported type", type),
+ keyValue("type id", type.typeId),
+ keyValue("module id", type.moduleId)};
+ if (!type.moduleId)
+ throw QmlDesigner::ModuleDoesNotExists{};
+
+ try {
+ if (type.version) {
+ s->insertExportedTypeNamesWithVersionStatement.write(type.moduleId,
+ type.name,
+ type.version.major.value,
+ type.version.minor.value,
+ type.typeId);
+
+ } else if (type.version.major) {
+ s->insertExportedTypeNamesWithMajorVersionStatement.write(type.moduleId,
+ type.name,
+ type.version.major.value,
+ type.typeId);
+ } else {
+ s->insertExportedTypeNamesWithoutVersionStatement.write(type.moduleId,
+ type.name,
+ type.typeId);
+ }
+ } catch (const Sqlite::ConstraintPreventsModification &) {
+ throw QmlDesigner::ExportedTypeCannotBeInserted{type.name};
+ }
+ };
+
+ auto update = [&](const Storage::Synchronization::ExportedTypeView &view,
+ const Storage::Synchronization::ExportedType &type) {
+ if (view.typeId != type.typeId) {
+ NanotraceHR::Tracer tracer{"update exported type"_t,
+ projectStorageCategory(),
+ keyValue("exported type", type),
+ keyValue("exported type view", view),
+ keyValue("type id", type.typeId),
+ keyValue("module id", type.typeId)};
+
+ handlePropertyDeclarationWithPropertyType(view.typeId, relinkablePropertyDeclarations);
+ handleAliasPropertyDeclarationsWithPropertyType(view.typeId,
+ relinkableAliasPropertyDeclarations);
+ handlePrototypes(view.typeId, relinkablePrototypes);
+ handleExtensions(view.typeId, relinkableExtensions);
+ s->updateExportedTypeNameTypeIdStatement.write(view.exportedTypeNameId, type.typeId);
+ return Sqlite::UpdateChange::Update;
+ }
+ return Sqlite::UpdateChange::No;
+ };
+
+ auto remove = [&](const Storage::Synchronization::ExportedTypeView &view) {
+ NanotraceHR::Tracer tracer{"remove exported type"_t,
+ projectStorageCategory(),
+ keyValue("exported type", view),
+ keyValue("type id", view.typeId),
+ keyValue("module id", view.moduleId)};
+
+ handlePropertyDeclarationWithPropertyType(view.typeId, relinkablePropertyDeclarations);
+ handleAliasPropertyDeclarationsWithPropertyType(view.typeId,
+ relinkableAliasPropertyDeclarations);
+ handlePrototypes(view.typeId, relinkablePrototypes);
+ handleExtensions(view.typeId, relinkableExtensions);
+ s->deleteExportedTypeNameStatement.write(view.exportedTypeNameId);
+ };
+
+ Sqlite::insertUpdateDelete(range, exportedTypes, compareKey, insert, update, remove);
+}
+
+void ProjectStorage::synchronizePropertyDeclarationsInsertAlias(
+ AliasPropertyDeclarations &insertedAliasPropertyDeclarations,
+ const Storage::Synchronization::PropertyDeclaration &value,
+ SourceId sourceId,
+ TypeId typeId)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"insert property declaration to alias"_t,
+ projectStorageCategory(),
+ keyValue("property declaration", value)};
+
+ auto callback = [&](PropertyDeclarationId propertyDeclarationId) {
+ insertedAliasPropertyDeclarations.emplace_back(typeId,
+ propertyDeclarationId,
+ fetchImportedTypeNameId(value.typeName,
+ sourceId),
+ value.aliasPropertyName,
+ value.aliasPropertyNameTail);
+ return Sqlite::CallbackControl::Abort;
+ };
+
+ s->insertAliasPropertyDeclarationStatement.readCallback(callback, typeId, value.name);
+}
+
+QVarLengthArray<PropertyDeclarationId, 128> ProjectStorage::fetchPropertyDeclarationIds(
+ TypeId baseTypeId) const
+{
+ QVarLengthArray<PropertyDeclarationId, 128> propertyDeclarationIds;
+
+ s->selectLocalPropertyDeclarationIdsForTypeStatement.readTo(propertyDeclarationIds, baseTypeId);
+
+ auto range = s->selectPrototypeAndExtensionIdsStatement.range<TypeId>(baseTypeId);
+
+ for (TypeId prototype : range) {
+ s->selectLocalPropertyDeclarationIdsForTypeStatement.readTo(propertyDeclarationIds, prototype);
+ }
+
+ return propertyDeclarationIds;
+}
+
+PropertyDeclarationId ProjectStorage::fetchNextPropertyDeclarationId(
+ TypeId baseTypeId, Utils::SmallStringView propertyName) const
+{
+ auto range = s->selectPrototypeAndExtensionIdsStatement.range<TypeId>(baseTypeId);
+
+ for (TypeId prototype : range) {
+ auto propertyDeclarationId = s->selectPropertyDeclarationIdByTypeIdAndNameStatement
+ .value<PropertyDeclarationId>(prototype, propertyName);
+
+ if (propertyDeclarationId)
+ return propertyDeclarationId;
+ }
+
+ return PropertyDeclarationId{};
+}
+
+PropertyDeclarationId ProjectStorage::fetchPropertyDeclarationId(TypeId typeId,
+ Utils::SmallStringView propertyName) const
+{
+ auto propertyDeclarationId = s->selectPropertyDeclarationIdByTypeIdAndNameStatement
+ .value<PropertyDeclarationId>(typeId, propertyName);
+
+ if (propertyDeclarationId)
+ return propertyDeclarationId;
+
+ return fetchNextPropertyDeclarationId(typeId, propertyName);
+}
+
+PropertyDeclarationId ProjectStorage::fetchNextDefaultPropertyDeclarationId(TypeId baseTypeId) const
+{
+ auto range = s->selectPrototypeAndExtensionIdsStatement.range<TypeId>(baseTypeId);
+
+ for (TypeId prototype : range) {
+ auto propertyDeclarationId = s->selectDefaultPropertyDeclarationIdStatement
+ .value<PropertyDeclarationId>(prototype);
+
+ if (propertyDeclarationId)
+ return propertyDeclarationId;
+ }
+
+ return PropertyDeclarationId{};
+}
+
+PropertyDeclarationId ProjectStorage::fetchDefaultPropertyDeclarationId(TypeId typeId) const
+{
+ auto propertyDeclarationId = s->selectDefaultPropertyDeclarationIdStatement
+ .value<PropertyDeclarationId>(typeId);
+
+ if (propertyDeclarationId)
+ return propertyDeclarationId;
+
+ return fetchNextDefaultPropertyDeclarationId(typeId);
+}
+
+void ProjectStorage::synchronizePropertyDeclarationsInsertProperty(
+ const Storage::Synchronization::PropertyDeclaration &value, SourceId sourceId, TypeId typeId)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"insert property declaration"_t,
+ projectStorageCategory(),
+ keyValue("property declaration", value)};
+
+ auto propertyImportedTypeNameId = fetchImportedTypeNameId(value.typeName, sourceId);
+ auto propertyTypeId = fetchTypeId(propertyImportedTypeNameId);
+
+ if (!propertyTypeId)
+ throw TypeNameDoesNotExists{fetchImportedTypeName(propertyImportedTypeNameId), sourceId};
+
+ auto propertyDeclarationId = s->insertPropertyDeclarationStatement.value<PropertyDeclarationId>(
+ typeId, value.name, propertyTypeId, value.traits, propertyImportedTypeNameId);
+
+ auto nextPropertyDeclarationId = fetchNextPropertyDeclarationId(typeId, value.name);
+ if (nextPropertyDeclarationId) {
+ s->updateAliasIdPropertyDeclarationStatement.write(nextPropertyDeclarationId,
+ propertyDeclarationId);
+ s->updatePropertyAliasDeclarationRecursivelyWithTypeAndTraitsStatement
+ .write(propertyDeclarationId, propertyTypeId, value.traits);
+ }
+}
+
+void ProjectStorage::synchronizePropertyDeclarationsUpdateAlias(
+ AliasPropertyDeclarations &updatedAliasPropertyDeclarations,
+ const Storage::Synchronization::PropertyDeclarationView &view,
+ const Storage::Synchronization::PropertyDeclaration &value,
+ SourceId sourceId)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"update property declaration to alias"_t,
+ projectStorageCategory(),
+ keyValue("property declaration", value),
+ keyValue("property declaration view", view)};
+
+ updatedAliasPropertyDeclarations.emplace_back(view.typeId,
+ view.id,
+ fetchImportedTypeNameId(value.typeName, sourceId),
+ value.aliasPropertyName,
+ value.aliasPropertyNameTail,
+ view.aliasId);
+}
+
+Sqlite::UpdateChange ProjectStorage::synchronizePropertyDeclarationsUpdateProperty(
+ const Storage::Synchronization::PropertyDeclarationView &view,
+ const Storage::Synchronization::PropertyDeclaration &value,
+ SourceId sourceId,
+ PropertyDeclarationIds &propertyDeclarationIds)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"update property declaration"_t,
+ projectStorageCategory(),
+ keyValue("property declaration", value),
+ keyValue("property declaration view", view)};
+
+ auto propertyImportedTypeNameId = fetchImportedTypeNameId(value.typeName, sourceId);
+
+ auto propertyTypeId = fetchTypeId(propertyImportedTypeNameId);
+
+ if (!propertyTypeId)
+ throw TypeNameDoesNotExists{fetchImportedTypeName(propertyImportedTypeNameId), sourceId};
+
+ if (view.traits == value.traits && propertyTypeId == view.typeId
+ && propertyImportedTypeNameId == view.typeNameId)
+ return Sqlite::UpdateChange::No;
+
+ s->updatePropertyDeclarationStatement.write(view.id,
+ propertyTypeId,
+ value.traits,
+ propertyImportedTypeNameId);
+ s->updatePropertyAliasDeclarationRecursivelyWithTypeAndTraitsStatement.write(view.id,
+ propertyTypeId,
+ value.traits);
+ propertyDeclarationIds.push_back(view.id);
+
+ tracer.end(keyValue("updated", "yes"));
+
+ return Sqlite::UpdateChange::Update;
+}
+
+void ProjectStorage::synchronizePropertyDeclarations(
+ TypeId typeId,
+ Storage::Synchronization::PropertyDeclarations &propertyDeclarations,
+ SourceId sourceId,
+ AliasPropertyDeclarations &insertedAliasPropertyDeclarations,
+ AliasPropertyDeclarations &updatedAliasPropertyDeclarations,
+ PropertyDeclarationIds &propertyDeclarationIds)
+{
+ NanotraceHR::Tracer tracer{"synchronize property declaration"_t, projectStorageCategory()};
+
+ std::sort(propertyDeclarations.begin(), propertyDeclarations.end(), [](auto &&first, auto &&second) {
+ return Sqlite::compare(first.name, second.name) < 0;
+ });
+
+ auto range = s->selectPropertyDeclarationsForTypeIdStatement
+ .range<Storage::Synchronization::PropertyDeclarationView>(typeId);
+
+ auto compareKey = [](const Storage::Synchronization::PropertyDeclarationView &view,
+ const Storage::Synchronization::PropertyDeclaration &value) {
+ return Sqlite::compare(view.name, value.name);
+ };
+
+ auto insert = [&](const Storage::Synchronization::PropertyDeclaration &value) {
+ if (value.kind == Storage::Synchronization::PropertyKind::Alias) {
+ synchronizePropertyDeclarationsInsertAlias(insertedAliasPropertyDeclarations,
+ value,
+ sourceId,
+ typeId);
+ } else {
+ synchronizePropertyDeclarationsInsertProperty(value, sourceId, typeId);
+ }
+ };
+
+ auto update = [&](const Storage::Synchronization::PropertyDeclarationView &view,
+ const Storage::Synchronization::PropertyDeclaration &value) {
+ if (value.kind == Storage::Synchronization::PropertyKind::Alias) {
+ synchronizePropertyDeclarationsUpdateAlias(updatedAliasPropertyDeclarations,
+ view,
+ value,
+ sourceId);
+ propertyDeclarationIds.push_back(view.id);
+ } else {
+ return synchronizePropertyDeclarationsUpdateProperty(view,
+ value,
+ sourceId,
+ propertyDeclarationIds);
+ }
+
+ return Sqlite::UpdateChange::No;
+ };
+
+ auto remove = [&](const Storage::Synchronization::PropertyDeclarationView &view) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"remove property declaration"_t,
+ projectStorageCategory(),
+ keyValue("property declaratio viewn", view)};
+
+ auto nextPropertyDeclarationId = fetchNextPropertyDeclarationId(typeId, view.name);
+
+ if (nextPropertyDeclarationId) {
+ s->updateAliasPropertyDeclarationByAliasPropertyDeclarationIdStatement
+ .write(nextPropertyDeclarationId, view.id);
+ }
+
+ s->updateDefaultPropertyIdToNullStatement.write(view.id);
+ s->deletePropertyDeclarationStatement.write(view.id);
+ propertyDeclarationIds.push_back(view.id);
+ };
+
+ Sqlite::insertUpdateDelete(range, propertyDeclarations, compareKey, insert, update, remove);
+}
+
+void ProjectStorage::resetRemovedAliasPropertyDeclarationsToNull(
+ Storage::Synchronization::Type &type, PropertyDeclarationIds &propertyDeclarationIds)
+{
+ NanotraceHR::Tracer tracer{"reset removed alias property declaration to null"_t,
+ projectStorageCategory()};
+
+ if (type.changeLevel == Storage::Synchronization::ChangeLevel::Minimal)
+ return;
+
+ Storage::Synchronization::PropertyDeclarations &aliasDeclarations = type.propertyDeclarations;
+
+ std::sort(aliasDeclarations.begin(), aliasDeclarations.end(), [](auto &&first, auto &&second) {
+ return Sqlite::compare(first.name, second.name) < 0;
+ });
+
+ auto range = s->selectPropertyDeclarationsWithAliasForTypeIdStatement
+ .range<AliasPropertyDeclarationView>(type.typeId);
+
+ auto compareKey = [](const AliasPropertyDeclarationView &view,
+ const Storage::Synchronization::PropertyDeclaration &value) {
+ return Sqlite::compare(view.name, value.name);
+ };
+
+ auto insert = [&](const Storage::Synchronization::PropertyDeclaration &) {};
+
+ auto update = [&](const AliasPropertyDeclarationView &,
+ const Storage::Synchronization::PropertyDeclaration &) {
+ return Sqlite::UpdateChange::No;
+ };
+
+ auto remove = [&](const AliasPropertyDeclarationView &view) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"reset removed alias property declaration to null"_t,
+ projectStorageCategory(),
+ keyValue("alias property declaration view", view)};
+
+ s->updatePropertyDeclarationAliasIdToNullStatement.write(view.id);
+ propertyDeclarationIds.push_back(view.id);
+ };
+
+ Sqlite::insertUpdateDelete(range, aliasDeclarations, compareKey, insert, update, remove);
+}
+
+void ProjectStorage::resetRemovedAliasPropertyDeclarationsToNull(
+ Storage::Synchronization::Types &types,
+ AliasPropertyDeclarations &relinkableAliasPropertyDeclarations)
+{
+ NanotraceHR::Tracer tracer{"reset removed alias properties to null"_t, projectStorageCategory()};
+
+ PropertyDeclarationIds propertyDeclarationIds;
+ propertyDeclarationIds.reserve(types.size());
+
+ for (auto &&type : types)
+ resetRemovedAliasPropertyDeclarationsToNull(type, propertyDeclarationIds);
+
+ removeRelinkableEntries(relinkableAliasPropertyDeclarations,
+ propertyDeclarationIds,
+ PropertyCompare<AliasPropertyDeclaration>{});
+}
+
+ImportId ProjectStorage::insertDocumentImport(const Storage::Import &import,
+ Storage::Synchronization::ImportKind importKind,
+ ModuleId sourceModuleId,
+ ImportId parentImportId)
+{
+ if (import.version.minor) {
+ return s->insertDocumentImportWithVersionStatement.value<ImportId>(import.sourceId,
+ import.moduleId,
+ sourceModuleId,
+ importKind,
+ import.version.major.value,
+ import.version.minor.value,
+ parentImportId);
+ } else if (import.version.major) {
+ return s->insertDocumentImportWithMajorVersionStatement.value<ImportId>(import.sourceId,
+ import.moduleId,
+ sourceModuleId,
+ importKind,
+ import.version.major.value,
+ parentImportId);
+ } else {
+ return s->insertDocumentImportWithoutVersionStatement.value<ImportId>(import.sourceId,
+ import.moduleId,
+ sourceModuleId,
+ importKind,
+ parentImportId);
+ }
+}
+
+void ProjectStorage::synchronizeDocumentImports(Storage::Imports &imports,
+ const SourceIds &updatedSourceIds,
+ Storage::Synchronization::ImportKind importKind)
+{
+ std::sort(imports.begin(), imports.end(), [](auto &&first, auto &&second) {
+ return std::tie(first.sourceId, first.moduleId, first.version)
+ < std::tie(second.sourceId, second.moduleId, second.version);
+ });
+
+ auto range = s->selectDocumentImportForSourceIdStatement
+ .range<Storage::Synchronization::ImportView>(toIntegers(updatedSourceIds),
+ importKind);
+
+ auto compareKey = [](const Storage::Synchronization::ImportView &view,
+ const Storage::Import &import) -> long long {
+ auto sourceIdDifference = view.sourceId - import.sourceId;
+ if (sourceIdDifference != 0)
+ return sourceIdDifference;
+
+ auto moduleIdDifference = view.moduleId - import.moduleId;
+ if (moduleIdDifference != 0)
+ return moduleIdDifference;
+
+ auto versionDifference = view.version.major.value - import.version.major.value;
+ if (versionDifference != 0)
+ return versionDifference;
+
+ return view.version.minor.value - import.version.minor.value;
+ };
+
+ auto insert = [&](const Storage::Import &import) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"insert import"_t,
+ projectStorageCategory(),
+ keyValue("import", import),
+ keyValue("import kind", importKind),
+ keyValue("source id", import.sourceId),
+ keyValue("module id", import.moduleId)};
+
+ auto importId = insertDocumentImport(import, importKind, import.moduleId, ImportId{});
+ auto callback = [&](ModuleId exportedModuleId, int majorVersion, int minorVersion) {
+ Storage::Import additionImport{exportedModuleId,
+ Storage::Version{majorVersion, minorVersion},
+ import.sourceId};
+
+ auto exportedImportKind = importKind == Storage::Synchronization::ImportKind::Import
+ ? Storage::Synchronization::ImportKind::ModuleExportedImport
+ : Storage::Synchronization::ImportKind::ModuleExportedModuleDependency;
+
+ NanotraceHR::Tracer tracer{"insert indirect import"_t,
+ projectStorageCategory(),
+ keyValue("import", import),
+ keyValue("import kind", exportedImportKind),
+ keyValue("source id", import.sourceId),
+ keyValue("module id", import.moduleId)};
+
+ auto indirectImportId = insertDocumentImport(additionImport,
+ exportedImportKind,
+ import.moduleId,
+ importId);
+
+ tracer.end(keyValue("import id", indirectImportId));
+ };
+
+ s->selectModuleExportedImportsForModuleIdStatement.readCallback(callback,
+ import.moduleId,
+ import.version.major.value,
+ import.version.minor.value);
+ tracer.end(keyValue("import id", importId));
+ };
+
+ auto update = [](const Storage::Synchronization::ImportView &, const Storage::Import &) {
+ return Sqlite::UpdateChange::No;
+ };
+
+ auto remove = [&](const Storage::Synchronization::ImportView &view) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"remove import"_t,
+ projectStorageCategory(),
+ keyValue("import", view),
+ keyValue("import id", view.importId),
+ keyValue("source id", view.sourceId),
+ keyValue("module id", view.moduleId)};
+
+ s->deleteDocumentImportStatement.write(view.importId);
+ s->deleteDocumentImportsWithParentImportIdStatement.write(view.sourceId, view.importId);
+ };
+
+ Sqlite::insertUpdateDelete(range, imports, compareKey, insert, update, remove);
+}
+
+Utils::PathString ProjectStorage::createJson(const Storage::Synchronization::ParameterDeclarations &parameters)
+{
+ NanotraceHR::Tracer tracer{"create json from parameter declarations"_t, projectStorageCategory()};
+
+ Utils::PathString json;
+ json.append("[");
+
+ Utils::SmallStringView comma{""};
+
+ for (const auto &parameter : parameters) {
+ json.append(comma);
+ comma = ",";
+ json.append(R"({"n":")");
+ json.append(parameter.name);
+ json.append(R"(","tn":")");
+ json.append(parameter.typeName);
+ if (parameter.traits == Storage::PropertyDeclarationTraits::None) {
+ json.append("\"}");
+ } else {
+ json.append(R"(","tr":)");
+ json.append(Utils::SmallString::number(to_underlying(parameter.traits)));
+ json.append("}");
+ }
+ }
+
+ json.append("]");
+
+ return json;
+}
+
+TypeId ProjectStorage::fetchTypeIdByModuleIdAndExportedName(ModuleId moduleId,
+ Utils::SmallStringView name) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch type id by module id and exported name"_t,
+ projectStorageCategory(),
+ keyValue("module id", moduleId),
+ keyValue("exported name", name)};
+
+ return s->selectTypeIdByModuleIdAndExportedNameStatement.value<TypeId>(moduleId, name);
+}
+
+void ProjectStorage::addTypeIdToPropertyEditorQmlPaths(
+ Storage::Synchronization::PropertyEditorQmlPaths &paths)
+{
+ NanotraceHR::Tracer tracer{"add type id to property editor qml paths"_t, projectStorageCategory()};
+
+ for (auto &path : paths)
+ path.typeId = fetchTypeIdByModuleIdAndExportedName(path.moduleId, path.typeName);
+}
+
+void ProjectStorage::synchronizePropertyEditorPaths(Storage::Synchronization::PropertyEditorQmlPaths &paths,
+ SourceIds updatedPropertyEditorQmlPathsSourceIds)
+{
+ using Storage::Synchronization::PropertyEditorQmlPath;
+ std::sort(paths.begin(), paths.end(), [](auto &&first, auto &&second) {
+ return first.typeId < second.typeId;
+ });
+
+ auto range = s->selectPropertyEditorPathsForForSourceIdsStatement.range<PropertyEditorQmlPathView>(
+ toIntegers(updatedPropertyEditorQmlPathsSourceIds));
+
+ auto compareKey = [](const PropertyEditorQmlPathView &view,
+ const PropertyEditorQmlPath &value) -> long long {
+ return view.typeId - value.typeId;
+ };
+
+ auto insert = [&](const PropertyEditorQmlPath &path) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"insert property editor paths"_t,
+ projectStorageCategory(),
+ keyValue("property editor qml path", path)};
+
+ if (path.typeId)
+ s->insertPropertyEditorPathStatement.write(path.typeId, path.pathId, path.directoryId);
+ };
+
+ auto update = [&](const PropertyEditorQmlPathView &view, const PropertyEditorQmlPath &value) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"update property editor paths"_t,
+ projectStorageCategory(),
+ keyValue("property editor qml path", value),
+ keyValue("property editor qml path view", view)};
+
+ if (value.pathId != view.pathId || value.directoryId != view.directoryId) {
+ s->updatePropertyEditorPathsStatement.write(value.typeId, value.pathId, value.directoryId);
+
+ tracer.end(keyValue("updated", "yes"));
+
+ return Sqlite::UpdateChange::Update;
+ }
+ return Sqlite::UpdateChange::No;
+ };
+
+ auto remove = [&](const PropertyEditorQmlPathView &view) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"remove property editor paths"_t,
+ projectStorageCategory(),
+ keyValue("property editor qml path view", view)};
+
+ s->deletePropertyEditorPathStatement.write(view.typeId);
+ };
+
+ Sqlite::insertUpdateDelete(range, paths, compareKey, insert, update, remove);
+}
+
+void ProjectStorage::synchronizePropertyEditorQmlPaths(
+ Storage::Synchronization::PropertyEditorQmlPaths &paths,
+ SourceIds updatedPropertyEditorQmlPathsSourceIds)
+{
+ NanotraceHR::Tracer tracer{"synchronize property editor qml paths"_t, projectStorageCategory()};
+
+ addTypeIdToPropertyEditorQmlPaths(paths);
+ synchronizePropertyEditorPaths(paths, updatedPropertyEditorQmlPathsSourceIds);
+}
+
+void ProjectStorage::synchronizeFunctionDeclarations(
+ TypeId typeId, Storage::Synchronization::FunctionDeclarations &functionsDeclarations)
+{
+ NanotraceHR::Tracer tracer{"synchronize function declaration"_t, projectStorageCategory()};
+
+ std::sort(functionsDeclarations.begin(),
+ functionsDeclarations.end(),
+ [](auto &&first, auto &&second) {
+ auto compare = Sqlite::compare(first.name, second.name);
+
+ if (compare == 0) {
+ Utils::PathString firstSignature{createJson(first.parameters)};
+ Utils::PathString secondSignature{createJson(second.parameters)};
+
+ return Sqlite::compare(firstSignature, secondSignature) < 0;
+ }
+
+ return compare < 0;
+ });
+
+ auto range = s->selectFunctionDeclarationsForTypeIdStatement
+ .range<Storage::Synchronization::FunctionDeclarationView>(typeId);
+
+ auto compareKey = [](const Storage::Synchronization::FunctionDeclarationView &view,
+ const Storage::Synchronization::FunctionDeclaration &value) {
+ auto nameKey = Sqlite::compare(view.name, value.name);
+ if (nameKey != 0)
+ return nameKey;
+
+ Utils::PathString valueSignature{createJson(value.parameters)};
+
+ return Sqlite::compare(view.signature, valueSignature);
+ };
+
+ auto insert = [&](const Storage::Synchronization::FunctionDeclaration &value) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"insert function declaration"_t,
+ projectStorageCategory(),
+ keyValue("function declaration", value)};
+
+ Utils::PathString signature{createJson(value.parameters)};
+
+ s->insertFunctionDeclarationStatement.write(typeId, value.name, value.returnTypeName, signature);
+ };
+
+ auto update = [&](const Storage::Synchronization::FunctionDeclarationView &view,
+ const Storage::Synchronization::FunctionDeclaration &value) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"update function declaration"_t,
+ projectStorageCategory(),
+ keyValue("function declaration", value),
+ keyValue("function declaration view", view)};
+
+ Utils::PathString signature{createJson(value.parameters)};
+
+ if (value.returnTypeName == view.returnTypeName && signature == view.signature)
+ return Sqlite::UpdateChange::No;
+
+ s->updateFunctionDeclarationStatement.write(view.id, value.returnTypeName, signature);
+
+ tracer.end(keyValue("updated", "yes"));
+
+ return Sqlite::UpdateChange::Update;
+ };
+
+ auto remove = [&](const Storage::Synchronization::FunctionDeclarationView &view) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"remove function declaration"_t,
+ projectStorageCategory(),
+ keyValue("function declaration view", view)};
+
+ s->deleteFunctionDeclarationStatement.write(view.id);
+ };
+
+ Sqlite::insertUpdateDelete(range, functionsDeclarations, compareKey, insert, update, remove);
+}
+
+void ProjectStorage::synchronizeSignalDeclarations(
+ TypeId typeId, Storage::Synchronization::SignalDeclarations &signalDeclarations)
+{
+ NanotraceHR::Tracer tracer{"synchronize signal declaration"_t, projectStorageCategory()};
+
+ std::sort(signalDeclarations.begin(), signalDeclarations.end(), [](auto &&first, auto &&second) {
+ auto compare = Sqlite::compare(first.name, second.name);
+
+ if (compare == 0) {
+ Utils::PathString firstSignature{createJson(first.parameters)};
+ Utils::PathString secondSignature{createJson(second.parameters)};
+
+ return Sqlite::compare(firstSignature, secondSignature) < 0;
+ }
+
+ return compare < 0;
+ });
+
+ auto range = s->selectSignalDeclarationsForTypeIdStatement
+ .range<Storage::Synchronization::SignalDeclarationView>(typeId);
+
+ auto compareKey = [](const Storage::Synchronization::SignalDeclarationView &view,
+ const Storage::Synchronization::SignalDeclaration &value) {
+ auto nameKey = Sqlite::compare(view.name, value.name);
+ if (nameKey != 0)
+ return nameKey;
+
+ Utils::PathString valueSignature{createJson(value.parameters)};
+
+ return Sqlite::compare(view.signature, valueSignature);
+ };
+
+ auto insert = [&](const Storage::Synchronization::SignalDeclaration &value) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"insert signal declaration"_t,
+ projectStorageCategory(),
+ keyValue("signal declaration", value)};
+
+ Utils::PathString signature{createJson(value.parameters)};
+
+ s->insertSignalDeclarationStatement.write(typeId, value.name, signature);
+ };
+
+ auto update = [&]([[maybe_unused]] const Storage::Synchronization::SignalDeclarationView &view,
+ [[maybe_unused]] const Storage::Synchronization::SignalDeclaration &value) {
+ return Sqlite::UpdateChange::No;
+ };
+
+ auto remove = [&](const Storage::Synchronization::SignalDeclarationView &view) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"remove signal declaration"_t,
+ projectStorageCategory(),
+ keyValue("signal declaration view", view)};
+
+ s->deleteSignalDeclarationStatement.write(view.id);
+ };
+
+ Sqlite::insertUpdateDelete(range, signalDeclarations, compareKey, insert, update, remove);
+}
+
+Utils::PathString ProjectStorage::createJson(
+ const Storage::Synchronization::EnumeratorDeclarations &enumeratorDeclarations)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"create json from enumerator declarations"_t, projectStorageCategory()};
+
+ Utils::PathString json;
+ json.append("{");
+
+ Utils::SmallStringView comma{"\""};
+
+ for (const auto &enumerator : enumeratorDeclarations) {
+ json.append(comma);
+ comma = ",\"";
+ json.append(enumerator.name);
+ if (enumerator.hasValue) {
+ json.append("\":\"");
+ json.append(Utils::SmallString::number(enumerator.value));
+ json.append("\"");
+ } else {
+ json.append("\":null");
+ }
+ }
+
+ json.append("}");
+
+ return json;
+}
+
+void ProjectStorage::synchronizeEnumerationDeclarations(
+ TypeId typeId, Storage::Synchronization::EnumerationDeclarations &enumerationDeclarations)
+{
+ NanotraceHR::Tracer tracer{"synchronize enumeration declaration"_t, projectStorageCategory()};
+
+ std::sort(enumerationDeclarations.begin(),
+ enumerationDeclarations.end(),
+ [](auto &&first, auto &&second) {
+ return Sqlite::compare(first.name, second.name) < 0;
+ });
+
+ auto range = s->selectEnumerationDeclarationsForTypeIdStatement
+ .range<Storage::Synchronization::EnumerationDeclarationView>(typeId);
+
+ auto compareKey = [](const Storage::Synchronization::EnumerationDeclarationView &view,
+ const Storage::Synchronization::EnumerationDeclaration &value) {
+ return Sqlite::compare(view.name, value.name);
+ };
+
+ auto insert = [&](const Storage::Synchronization::EnumerationDeclaration &value) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"insert enumeration declaration"_t,
+ projectStorageCategory(),
+ keyValue("enumeration declaration", value)};
+
+ Utils::PathString signature{createJson(value.enumeratorDeclarations)};
+
+ s->insertEnumerationDeclarationStatement.write(typeId, value.name, signature);
+ };
+
+ auto update = [&](const Storage::Synchronization::EnumerationDeclarationView &view,
+ const Storage::Synchronization::EnumerationDeclaration &value) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"update enumeration declaration"_t,
+ projectStorageCategory(),
+ keyValue("enumeration declaration", value),
+ keyValue("enumeration declaration view", view)};
+
+ Utils::PathString enumeratorDeclarations{createJson(value.enumeratorDeclarations)};
+
+ if (enumeratorDeclarations == view.enumeratorDeclarations)
+ return Sqlite::UpdateChange::No;
+
+ s->updateEnumerationDeclarationStatement.write(view.id, enumeratorDeclarations);
+
+ tracer.end(keyValue("updated", "yes"));
+
+ return Sqlite::UpdateChange::Update;
+ };
+
+ auto remove = [&](const Storage::Synchronization::EnumerationDeclarationView &view) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"remove enumeration declaration"_t,
+ projectStorageCategory(),
+ keyValue("enumeration declaration view", view)};
+
+ s->deleteEnumerationDeclarationStatement.write(view.id);
+ };
+
+ Sqlite::insertUpdateDelete(range, enumerationDeclarations, compareKey, insert, update, remove);
+}
+
+void ProjectStorage::extractExportedTypes(TypeId typeId,
+ const Storage::Synchronization::Type &type,
+ Storage::Synchronization::ExportedTypes &exportedTypes)
+{
+ for (const auto &exportedType : type.exportedTypes)
+ exportedTypes.emplace_back(exportedType.name, exportedType.version, typeId, exportedType.moduleId);
+}
+
+TypeId ProjectStorage::declareType(Storage::Synchronization::Type &type)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"declare type"_t,
+ projectStorageCategory(),
+ keyValue("source id", type.sourceId),
+ keyValue("type name", type.typeName)};
+
+ if (type.typeName.isEmpty()) {
+ type.typeId = s->selectTypeIdBySourceIdStatement.value<TypeId>(type.sourceId);
+
+ tracer.end(keyValue("type id", type.typeId));
+
+ return type.typeId;
+ }
+
+ type.typeId = s->insertTypeStatement.value<TypeId>(type.sourceId, type.typeName);
+
+ if (!type.typeId)
+ type.typeId = s->selectTypeIdBySourceIdAndNameStatement.value<TypeId>(type.sourceId,
+ type.typeName);
+
+ tracer.end(keyValue("type id", type.typeId));
+
+ return type.typeId;
+}
+
+void ProjectStorage::syncDeclarations(Storage::Synchronization::Type &type,
+ AliasPropertyDeclarations &insertedAliasPropertyDeclarations,
+ AliasPropertyDeclarations &updatedAliasPropertyDeclarations,
+ PropertyDeclarationIds &propertyDeclarationIds)
+{
+ NanotraceHR::Tracer tracer{"synchronize declaration per type"_t, projectStorageCategory()};
+
+ if (type.changeLevel == Storage::Synchronization::ChangeLevel::Minimal)
+ return;
+
+ synchronizePropertyDeclarations(type.typeId,
+ type.propertyDeclarations,
+ type.sourceId,
+ insertedAliasPropertyDeclarations,
+ updatedAliasPropertyDeclarations,
+ propertyDeclarationIds);
+ synchronizeFunctionDeclarations(type.typeId, type.functionDeclarations);
+ synchronizeSignalDeclarations(type.typeId, type.signalDeclarations);
+ synchronizeEnumerationDeclarations(type.typeId, type.enumerationDeclarations);
+}
+
+void ProjectStorage::syncDeclarations(Storage::Synchronization::Types &types,
+ AliasPropertyDeclarations &insertedAliasPropertyDeclarations,
+ AliasPropertyDeclarations &updatedAliasPropertyDeclarations,
+ PropertyDeclarations &relinkablePropertyDeclarations)
+{
+ NanotraceHR::Tracer tracer{"synchronize declaration"_t, projectStorageCategory()};
+
+ PropertyDeclarationIds propertyDeclarationIds;
+ propertyDeclarationIds.reserve(types.size() * 10);
+
+ for (auto &&type : types)
+ syncDeclarations(type,
+ insertedAliasPropertyDeclarations,
+ updatedAliasPropertyDeclarations,
+ propertyDeclarationIds);
+
+ removeRelinkableEntries(relinkablePropertyDeclarations,
+ propertyDeclarationIds,
+ PropertyCompare<PropertyDeclaration>{});
+}
+
+void ProjectStorage::syncDefaultProperties(Storage::Synchronization::Types &types)
+{
+ NanotraceHR::Tracer tracer{"synchronize default properties"_t, projectStorageCategory()};
+
+ auto range = s->selectTypesWithDefaultPropertyStatement.range<TypeWithDefaultPropertyView>();
+
+ auto compareKey = [](const TypeWithDefaultPropertyView &view,
+ const Storage::Synchronization::Type &value) {
+ return view.typeId - value.typeId;
+ };
+
+ auto insert = [&](const Storage::Synchronization::Type &) {
+
+ };
+
+ auto update = [&](const TypeWithDefaultPropertyView &view,
+ const Storage::Synchronization::Type &value) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"synchronize default properties by update"_t,
+ projectStorageCategory(),
+ keyValue("type id", value.typeId),
+ keyValue("value", value),
+ keyValue("view", view)};
+
+ PropertyDeclarationId valueDefaultPropertyId;
+ if (value.defaultPropertyName.size())
+ valueDefaultPropertyId = fetchPropertyDeclarationByTypeIdAndNameUngarded(value.typeId,
+ value.defaultPropertyName)
+ .propertyDeclarationId;
+
+ if (compareInvalidAreTrue(valueDefaultPropertyId, view.defaultPropertyId))
+ return Sqlite::UpdateChange::No;
+
+ s->updateDefaultPropertyIdStatement.write(value.typeId, valueDefaultPropertyId);
+
+ tracer.end(keyValue("updated", "yes"),
+ keyValue("default property id", valueDefaultPropertyId));
+
+ return Sqlite::UpdateChange::Update;
+ };
+
+ auto remove = [&](const TypeWithDefaultPropertyView &) {};
+
+ Sqlite::insertUpdateDelete(range, types, compareKey, insert, update, remove);
+}
+
+void ProjectStorage::resetDefaultPropertiesIfChanged(Storage::Synchronization::Types &types)
+{
+ NanotraceHR::Tracer tracer{"reset changed default properties"_t, projectStorageCategory()};
+
+ auto range = s->selectTypesWithDefaultPropertyStatement.range<TypeWithDefaultPropertyView>();
+
+ auto compareKey = [](const TypeWithDefaultPropertyView &view,
+ const Storage::Synchronization::Type &value) {
+ return view.typeId - value.typeId;
+ };
+
+ auto insert = [&](const Storage::Synchronization::Type &) {
+
+ };
+
+ auto update = [&](const TypeWithDefaultPropertyView &view,
+ const Storage::Synchronization::Type &value) {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"reset changed default properties by update"_t,
+ projectStorageCategory(),
+ keyValue("type id", value.typeId),
+ keyValue("value", value),
+ keyValue("view", view)};
+
+ PropertyDeclarationId valueDefaultPropertyId;
+ if (value.defaultPropertyName.size()) {
+ auto optionalValueDefaultPropertyId = fetchOptionalPropertyDeclarationByTypeIdAndNameUngarded(
+ value.typeId, value.defaultPropertyName);
+ if (optionalValueDefaultPropertyId)
+ valueDefaultPropertyId = optionalValueDefaultPropertyId->propertyDeclarationId;
+ }
+
+ if (compareInvalidAreTrue(valueDefaultPropertyId, view.defaultPropertyId))
+ return Sqlite::UpdateChange::No;
+
+ s->updateDefaultPropertyIdStatement.write(value.typeId, Sqlite::NullValue{});
+
+ tracer.end(keyValue("updated", "yes"));
+
+ return Sqlite::UpdateChange::Update;
+ };
+
+ auto remove = [&](const TypeWithDefaultPropertyView &) {};
+
+ Sqlite::insertUpdateDelete(range, types, compareKey, insert, update, remove);
+}
+
+void ProjectStorage::checkForPrototypeChainCycle(TypeId typeId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"check for prototype chain cycle"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId)};
+
+ auto callback = [=](TypeId currentTypeId) {
+ if (typeId == currentTypeId)
+ throw PrototypeChainCycle{};
+ };
+
+ s->selectPrototypeAndExtensionIdsStatement.readCallback(callback, typeId);
+}
+
+void ProjectStorage::checkForAliasChainCycle(PropertyDeclarationId propertyDeclarationId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"check for alias chain cycle"_t,
+ projectStorageCategory(),
+ keyValue("property declaration id", propertyDeclarationId)};
+ auto callback = [=](PropertyDeclarationId currentPropertyDeclarationId) {
+ if (propertyDeclarationId == currentPropertyDeclarationId)
+ throw AliasChainCycle{};
+ };
+
+ s->selectPropertyDeclarationIdsForAliasChainStatement.readCallback(callback,
+ propertyDeclarationId);
+}
+
+std::pair<TypeId, ImportedTypeNameId> ProjectStorage::fetchImportedTypeNameIdAndTypeId(
+ const Storage::Synchronization::ImportedTypeName &typeName, SourceId sourceId)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch imported type name id and type id"_t,
+ projectStorageCategory(),
+ keyValue("imported type name", typeName),
+ keyValue("source id", sourceId)};
+
+ TypeId typeId;
+ ImportedTypeNameId typeNameId;
+ if (!std::visit([](auto &&typeName_) -> bool { return typeName_.name.isEmpty(); }, typeName)) {
+ typeNameId = fetchImportedTypeNameId(typeName, sourceId);
+
+ typeId = fetchTypeId(typeNameId);
+
+ tracer.end(keyValue("type id", typeId), keyValue("type name id", typeNameId));
+
+ if (!typeId)
+ throw TypeNameDoesNotExists{fetchImportedTypeName(typeNameId), sourceId};
+ }
+
+ return {typeId, typeNameId};
+}
+
+void ProjectStorage::syncPrototypeAndExtension(Storage::Synchronization::Type &type, TypeIds &typeIds)
+{
+ if (type.changeLevel == Storage::Synchronization::ChangeLevel::Minimal)
+ return;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"synchronize prototype and extension"_t,
+ projectStorageCategory(),
+ keyValue("prototype", type.prototype),
+ keyValue("extension", type.extension),
+ keyValue("type id", type.typeId),
+ keyValue("source id", type.sourceId)};
+
+ auto [prototypeId, prototypeTypeNameId] = fetchImportedTypeNameIdAndTypeId(type.prototype,
+ type.sourceId);
+ auto [extensionId, extensionTypeNameId] = fetchImportedTypeNameIdAndTypeId(type.extension,
+ type.sourceId);
+
+ s->updatePrototypeAndExtensionStatement.write(type.typeId,
+ prototypeId,
+ prototypeTypeNameId,
+ extensionId,
+ extensionTypeNameId);
+
+ if (prototypeId || extensionId)
+ checkForPrototypeChainCycle(type.typeId);
+
+ typeIds.push_back(type.typeId);
+
+ tracer.end(keyValue("prototype id", prototypeId),
+ keyValue("prototype type name id", prototypeTypeNameId),
+ keyValue("extension id", extensionId),
+ keyValue("extension type name id", extensionTypeNameId));
+}
+
+void ProjectStorage::syncPrototypesAndExtensions(Storage::Synchronization::Types &types,
+ Prototypes &relinkablePrototypes,
+ Prototypes &relinkableExtensions)
+{
+ NanotraceHR::Tracer tracer{"synchronize prototypes and extensions"_t, projectStorageCategory()};
+
+ TypeIds typeIds;
+ typeIds.reserve(types.size());
+
+ for (auto &type : types)
+ syncPrototypeAndExtension(type, typeIds);
+
+ removeRelinkableEntries(relinkablePrototypes, typeIds, TypeCompare<Prototype>{});
+ removeRelinkableEntries(relinkableExtensions, typeIds, TypeCompare<Prototype>{});
+}
+
+ImportId ProjectStorage::fetchImportId(SourceId sourceId, const Storage::Import &import) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch imported type name id"_t,
+ projectStorageCategory(),
+ keyValue("import", import),
+ keyValue("source id", sourceId)};
+
+ ImportId importId;
+ if (import.version) {
+ importId = s->selectImportIdBySourceIdAndModuleIdAndVersionStatement.value<ImportId>(
+ sourceId, import.moduleId, import.version.major.value, import.version.minor.value);
+ } else if (import.version.major) {
+ importId = s->selectImportIdBySourceIdAndModuleIdAndMajorVersionStatement
+ .value<ImportId>(sourceId, import.moduleId, import.version.major.value);
+ } else {
+ importId = s->selectImportIdBySourceIdAndModuleIdStatement.value<ImportId>(sourceId,
+ import.moduleId);
+ }
+
+ tracer.end(keyValue("import id", importId));
+
+ return importId;
+}
+
+ImportedTypeNameId ProjectStorage::fetchImportedTypeNameId(
+ const Storage::Synchronization::ImportedTypeName &name, SourceId sourceId)
+{
+ struct Inspect
+ {
+ auto operator()(const Storage::Synchronization::ImportedType &importedType)
+ {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch imported type name id"_t,
+ projectStorageCategory(),
+ keyValue("imported type name", importedType.name),
+ keyValue("source id", sourceId),
+ keyValue("type name kind", "exported"sv)};
+
+ return storage.fetchImportedTypeNameId(Storage::Synchronization::TypeNameKind::Exported,
+ sourceId,
+ importedType.name);
+ }
+
+ auto operator()(const Storage::Synchronization::QualifiedImportedType &importedType)
+ {
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch imported type name id"_t,
+ projectStorageCategory(),
+ keyValue("imported type name", importedType.name),
+ keyValue("import", importedType.import),
+ keyValue("type name kind", "qualified exported"sv)};
+
+ ImportId importId = storage.fetchImportId(sourceId, importedType.import);
+
+ auto importedTypeNameId = storage.fetchImportedTypeNameId(
+ Storage::Synchronization::TypeNameKind::QualifiedExported, importId, importedType.name);
+
+ tracer.end(keyValue("import id", importId), keyValue("source id", sourceId));
+
+ return importedTypeNameId;
+ }
+
+ ProjectStorage &storage;
+ SourceId sourceId;
+ };
+
+ return std::visit(Inspect{*this, sourceId}, name);
+}
+
+TypeId ProjectStorage::fetchTypeId(ImportedTypeNameId typeNameId) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch type id with type name kind"_t,
+ projectStorageCategory(),
+ keyValue("type name id", typeNameId)};
+
+ auto kind = s->selectKindFromImportedTypeNamesStatement.value<Storage::Synchronization::TypeNameKind>(
+ typeNameId);
+
+ auto typeId = fetchTypeId(typeNameId, kind);
+
+ tracer.end(keyValue("type id", typeId), keyValue("type name kind", kind));
+
+ return typeId;
+}
+
+Utils::SmallString ProjectStorage::fetchImportedTypeName(ImportedTypeNameId typeNameId) const
+{
+ return s->selectNameFromImportedTypeNamesStatement.value<Utils::SmallString>(typeNameId);
+}
+
+TypeId ProjectStorage::fetchTypeId(ImportedTypeNameId typeNameId,
+ Storage::Synchronization::TypeNameKind kind) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch type id"_t,
+ projectStorageCategory(),
+ keyValue("type name id", typeNameId),
+ keyValue("type name kind", kind)};
+
+ TypeId typeId;
+ if (kind == Storage::Synchronization::TypeNameKind::Exported) {
+ typeId = s->selectTypeIdForImportedTypeNameNamesStatement.value<TypeId>(typeNameId);
+ } else {
+ typeId = s->selectTypeIdForQualifiedImportedTypeNameNamesStatement.value<TypeId>(typeNameId);
+ }
+
+ tracer.end(keyValue("type id", typeId));
+
+ return typeId;
+}
+
+std::optional<ProjectStorage::FetchPropertyDeclarationResult>
+ProjectStorage::fetchOptionalPropertyDeclarationByTypeIdAndNameUngarded(TypeId typeId,
+ Utils::SmallStringView name)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch optional property declaration by type id and name ungarded"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId),
+ keyValue("property name", name)};
+
+ auto propertyDeclarationId = fetchPropertyDeclarationId(typeId, name);
+ auto propertyDeclaration = s->selectPropertyDeclarationResultByPropertyDeclarationIdStatement
+ .optionalValue<FetchPropertyDeclarationResult>(
+ propertyDeclarationId);
+
+ tracer.end(keyValue("property declaration", propertyDeclaration));
+
+ return propertyDeclaration;
+}
+
+ProjectStorage::FetchPropertyDeclarationResult ProjectStorage::fetchPropertyDeclarationByTypeIdAndNameUngarded(
+ TypeId typeId, Utils::SmallStringView name)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch property declaration by type id and name ungarded"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId),
+ keyValue("property name", name)};
+
+ auto propertyDeclaration = fetchOptionalPropertyDeclarationByTypeIdAndNameUngarded(typeId, name);
+ tracer.end(keyValue("property declaration", propertyDeclaration));
+
+ if (propertyDeclaration)
+ return *propertyDeclaration;
+
+ throw PropertyNameDoesNotExists{};
+}
+
+PropertyDeclarationId ProjectStorage::fetchPropertyDeclarationIdByTypeIdAndNameUngarded(
+ TypeId typeId, Utils::SmallStringView name)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch property declaration id by type id and name ungarded"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId),
+ keyValue("property name", name)};
+
+ auto propertyDeclarationId = fetchPropertyDeclarationId(typeId, name);
+
+ tracer.end(keyValue("property declaration id", propertyDeclarationId));
+
+ if (propertyDeclarationId)
+ return propertyDeclarationId;
+
+ throw PropertyNameDoesNotExists{};
+}
+
+SourceContextId ProjectStorage::readSourceContextId(Utils::SmallStringView sourceContextPath)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"read source context id"_t,
+ projectStorageCategory(),
+ keyValue("source context path", sourceContextPath)};
+
+ auto sourceContextId = s->selectSourceContextIdFromSourceContextsBySourceContextPathStatement
+ .value<SourceContextId>(sourceContextPath);
+
+ tracer.end(keyValue("source context id", sourceContextId));
+
+ return sourceContextId;
+}
+
+SourceContextId ProjectStorage::writeSourceContextId(Utils::SmallStringView sourceContextPath)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"write source context id"_t,
+ projectStorageCategory(),
+ keyValue("source context path", sourceContextPath)};
+
+ s->insertIntoSourceContextsStatement.write(sourceContextPath);
+
+ auto sourceContextId = SourceContextId::create(static_cast<int>(database.lastInsertedRowId()));
+
+ tracer.end(keyValue("source context id", sourceContextId));
+
+ return sourceContextId;
+}
+
+SourceId ProjectStorage::writeSourceId(SourceContextId sourceContextId,
+ Utils::SmallStringView sourceName)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"write source id"_t,
+ projectStorageCategory(),
+ keyValue("source context id", sourceContextId),
+ keyValue("source name", sourceName)};
+
+ s->insertIntoSourcesStatement.write(sourceContextId, sourceName);
+
+ auto sourceId = SourceId::create(static_cast<int>(database.lastInsertedRowId()));
+
+ tracer.end(keyValue("source id", sourceId));
+
+ return sourceId;
+}
+
+SourceId ProjectStorage::readSourceId(SourceContextId sourceContextId,
+ Utils::SmallStringView sourceName)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"read source id"_t,
+ projectStorageCategory(),
+ keyValue("source context id", sourceContextId),
+ keyValue("source name", sourceName)};
+
+ auto sourceId = s->selectSourceIdFromSourcesBySourceContextIdAndSourceNameStatement
+ .value<SourceId>(sourceContextId, sourceName);
+
+ tracer.end(keyValue("source id", sourceId));
+
+ return sourceId;
+}
+
+Storage::Synchronization::ExportedTypes ProjectStorage::fetchExportedTypes(TypeId typeId)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch exported type"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId)};
+
+ auto exportedTypes = s->selectExportedTypesByTypeIdStatement
+ .values<Storage::Synchronization::ExportedType, 12>(typeId);
+
+ tracer.end(keyValue("exported types", exportedTypes));
+
+ return exportedTypes;
+}
+
+Storage::Synchronization::PropertyDeclarations ProjectStorage::fetchPropertyDeclarations(TypeId typeId)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch property declarations"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId)};
+
+ auto propertyDeclarations = s->selectPropertyDeclarationsByTypeIdStatement
+ .values<Storage::Synchronization::PropertyDeclaration, 24>(typeId);
+
+ tracer.end(keyValue("property declarations", propertyDeclarations));
+
+ return propertyDeclarations;
+}
+
+Storage::Synchronization::FunctionDeclarations ProjectStorage::fetchFunctionDeclarations(TypeId typeId)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch signal declarations"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId)};
+
+ Storage::Synchronization::FunctionDeclarations functionDeclarations;
+
+ auto callback = [&](Utils::SmallStringView name,
+ Utils::SmallStringView returnType,
+ FunctionDeclarationId functionDeclarationId) {
+ auto &functionDeclaration = functionDeclarations.emplace_back(name, returnType);
+ functionDeclaration.parameters = s->selectFunctionParameterDeclarationsStatement
+ .values<Storage::Synchronization::ParameterDeclaration, 8>(
+ functionDeclarationId);
+ };
+
+ s->selectFunctionDeclarationsForTypeIdWithoutSignatureStatement.readCallback(callback, typeId);
+
+ tracer.end(keyValue("function declarations", functionDeclarations));
+
+ return functionDeclarations;
+}
+
+Storage::Synchronization::SignalDeclarations ProjectStorage::fetchSignalDeclarations(TypeId typeId)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch signal declarations"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId)};
+
+ Storage::Synchronization::SignalDeclarations signalDeclarations;
+
+ auto callback = [&](Utils::SmallStringView name, SignalDeclarationId signalDeclarationId) {
+ auto &signalDeclaration = signalDeclarations.emplace_back(name);
+ signalDeclaration.parameters = s->selectSignalParameterDeclarationsStatement
+ .values<Storage::Synchronization::ParameterDeclaration, 8>(
+ signalDeclarationId);
+ };
+
+ s->selectSignalDeclarationsForTypeIdWithoutSignatureStatement.readCallback(callback, typeId);
+
+ tracer.end(keyValue("signal declarations", signalDeclarations));
+
+ return signalDeclarations;
+}
+
+Storage::Synchronization::EnumerationDeclarations ProjectStorage::fetchEnumerationDeclarations(TypeId typeId)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch enumeration declarations"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId)};
+
+ Storage::Synchronization::EnumerationDeclarations enumerationDeclarations;
+
+ auto callback = [&](Utils::SmallStringView name,
+ EnumerationDeclarationId enumerationDeclarationId) {
+ enumerationDeclarations.emplace_back(
+ name,
+ s->selectEnumeratorDeclarationStatement
+ .values<Storage::Synchronization::EnumeratorDeclaration, 8>(enumerationDeclarationId));
+ };
+
+ s->selectEnumerationDeclarationsForTypeIdWithoutEnumeratorDeclarationsStatement
+ .readCallback(callback, typeId);
+
+ tracer.end(keyValue("enumeration declarations", enumerationDeclarations));
+
+ return enumerationDeclarations;
+}
+
+template<typename... TypeIds>
+bool ProjectStorage::isBasedOn_(TypeId typeId, TypeIds... baseTypeIds) const
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is based on"_t,
+ projectStorageCategory(),
+ keyValue("type id", typeId),
+ keyValue("base type ids", NanotraceHR::array(baseTypeIds...))};
+
+ static_assert(((std::is_same_v<TypeId, TypeIds>) &&...), "Parameter must be a TypeId!");
+
+ if (((typeId == baseTypeIds) || ...)) {
+ tracer.end(keyValue("is based on", true));
+ return true;
+ }
+
+ auto range = s->selectPrototypeAndExtensionIdsStatement.rangeWithTransaction<TypeId>(typeId);
+
+ auto isBasedOn = std::any_of(range.begin(), range.end(), [&](TypeId currentTypeId) {
+ return ((currentTypeId == baseTypeIds) || ...);
+ });
+
+ tracer.end(keyValue("is based on", isBasedOn));
+
+ return isBasedOn;
+}
+
+template<typename Id>
+ImportedTypeNameId ProjectStorage::fetchImportedTypeNameId(Storage::Synchronization::TypeNameKind kind,
+ Id id,
+ Utils::SmallStringView typeName)
+{
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"fetch imported type name id"_t,
+ projectStorageCategory(),
+ keyValue("imported type name", typeName),
+ keyValue("kind", kind)};
+
+ auto importedTypeNameId = s->selectImportedTypeNameIdStatement.value<ImportedTypeNameId>(kind,
+ id,
+ typeName);
+
+ if (!importedTypeNameId)
+ importedTypeNameId = s->insertImportedTypeNameIdStatement.value<ImportedTypeNameId>(kind,
+ id,
+ typeName);
+
+ tracer.end(keyValue("imported type name id", importedTypeNameId));
+
+ return importedTypeNameId;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h
index a770577a65..e7826f531b 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h
@@ -6,9 +6,12 @@
#include "commontypecache.h"
#include "projectstorageexceptions.h"
#include "projectstorageinterface.h"
+#include "projectstoragetypes.h"
#include "sourcepathcachetypes.h"
#include "storagecache.h"
+#include <tracing/qmldesignertracing.h>
+
#include <sqlitealgorithms.h>
#include <sqlitedatabase.h>
#include <sqlitetable.h>
@@ -28,414 +31,87 @@ namespace QmlDesigner {
using namespace NanotraceHR::Literals;
-constexpr NanotraceHR::Tracing projectStorageTracingStatus()
-{
-#ifdef ENABLE_PROJECT_STORAGE_TRACING
- return NanotraceHR::Tracing::IsEnabled;
-#else
- return NanotraceHR::Tracing::IsDisabled;
-#endif
-}
-
-[[gnu::pure]] NanotraceHR::StringViewCategory<projectStorageTracingStatus()> &projectStorageCategory();
+using ProjectStorageTracing::projectStorageCategory;
-template<typename Database>
class ProjectStorage final : public ProjectStorageInterface
{
- friend Storage::Info::CommonTypeCache<Database>;
+ using Database = Sqlite::Database;
+ friend Storage::Info::CommonTypeCache<ProjectStorageType>;
public:
- template<int ResultCount, int BindParameterCount = 0>
- using ReadStatement = typename Database::template ReadStatement<ResultCount, BindParameterCount>;
- template<int ResultCount, int BindParameterCount = 0>
- using ReadWriteStatement = typename Database::template ReadWriteStatement<ResultCount, BindParameterCount>;
- template<int BindParameterCount>
- using WriteStatement = typename Database::template WriteStatement<BindParameterCount>;
-
- ProjectStorage(Database &database, bool isInitialized)
- : database{database}
- , exclusiveTransaction{database}
- , initializer{database, isInitialized}
- {
- NanotraceHR::Tracer tracer{"initialize"_t, projectStorageCategory()};
-
- exclusiveTransaction.commit();
-
- database.walCheckpointFull();
-
- moduleCache.populate();
- }
-
- void synchronize(Storage::Synchronization::SynchronizationPackage package) override
- {
- NanotraceHR::Tracer tracer{"synchronize"_t, projectStorageCategory()};
-
- TypeIds deletedTypeIds;
- Sqlite::withImmediateTransaction(database, [&] {
- AliasPropertyDeclarations insertedAliasPropertyDeclarations;
- AliasPropertyDeclarations updatedAliasPropertyDeclarations;
-
- AliasPropertyDeclarations relinkableAliasPropertyDeclarations;
- PropertyDeclarations relinkablePropertyDeclarations;
- Prototypes relinkablePrototypes;
- Prototypes relinkableExtensions;
-
- TypeIds updatedTypeIds;
- updatedTypeIds.reserve(package.types.size());
-
- TypeIds typeIdsToBeDeleted;
-
- std::sort(package.updatedSourceIds.begin(), package.updatedSourceIds.end());
-
- synchronizeFileStatuses(package.fileStatuses, package.updatedFileStatusSourceIds);
- synchronizeImports(package.imports,
- package.updatedSourceIds,
- package.moduleDependencies,
- package.updatedModuleDependencySourceIds,
- package.moduleExportedImports,
- package.updatedModuleIds);
- synchronizeTypes(package.types,
- updatedTypeIds,
- insertedAliasPropertyDeclarations,
- updatedAliasPropertyDeclarations,
- relinkableAliasPropertyDeclarations,
- relinkablePropertyDeclarations,
- relinkablePrototypes,
- relinkableExtensions,
- package.updatedSourceIds);
- synchronizeTypeAnnotations(package.typeAnnotations,
- package.updatedTypeAnnotationSourceIds);
- synchronizePropertyEditorQmlPaths(package.propertyEditorQmlPaths,
- package.updatedPropertyEditorQmlPathSourceIds);
-
- deleteNotUpdatedTypes(updatedTypeIds,
- package.updatedSourceIds,
- typeIdsToBeDeleted,
- relinkableAliasPropertyDeclarations,
- relinkablePropertyDeclarations,
- relinkablePrototypes,
- relinkableExtensions,
- deletedTypeIds);
-
- relink(relinkableAliasPropertyDeclarations,
- relinkablePropertyDeclarations,
- relinkablePrototypes,
- relinkableExtensions,
- deletedTypeIds);
-
- linkAliases(insertedAliasPropertyDeclarations, updatedAliasPropertyDeclarations);
-
- synchronizeProjectDatas(package.projectDatas, package.updatedProjectSourceIds);
-
- commonTypeCache_.resetTypeIds();
- });
-
- callRefreshMetaInfoCallback(deletedTypeIds);
- }
-
- void synchronizeDocumentImports(Storage::Imports imports, SourceId sourceId) override
- {
- NanotraceHR::Tracer tracer{"synchronize document imports"_t, projectStorageCategory()};
-
- Sqlite::withImmediateTransaction(database, [&] {
- synchronizeDocumentImports(imports,
- {sourceId},
- Storage::Synchronization::ImportKind::Import);
- });
- }
+ ProjectStorage(Database &database, bool isInitialized);
+ ~ProjectStorage();
- void addObserver(ProjectStorageObserver *observer) override { observers.push_back(observer); }
+ void synchronize(Storage::Synchronization::SynchronizationPackage package) override;
- void removeObserver(ProjectStorageObserver *observer) override
- {
- observers.removeOne(observer);
- }
+ void synchronizeDocumentImports(Storage::Imports imports, SourceId sourceId) override;
- ModuleId moduleId(Utils::SmallStringView moduleName) const override
- {
- NanotraceHR::Tracer tracer{"get module id"_t, projectStorageCategory()};
-
- return moduleCache.id(moduleName);
- }
+ void addObserver(ProjectStorageObserver *observer) override;
- Utils::SmallString moduleName(ModuleId moduleId) const
- {
- NanotraceHR::Tracer tracer{"get module name"_t, projectStorageCategory()};
+ void removeObserver(ProjectStorageObserver *observer) override;
- if (!moduleId)
- throw ModuleDoesNotExists{};
+ ModuleId moduleId(Utils::SmallStringView moduleName) const override;
- return moduleCache.value(moduleId);
- }
+ Utils::SmallString moduleName(ModuleId moduleId) const override;
TypeId typeId(ModuleId moduleId,
Utils::SmallStringView exportedTypeName,
- Storage::Version version) const override
- {
- NanotraceHR::Tracer tracer{"get type id by exported name"_t, projectStorageCategory()};
-
- if (version.minor)
- return selectTypeIdByModuleIdAndExportedNameAndVersionStatement
- .template valueWithTransaction<TypeId>(moduleId,
- exportedTypeName,
- version.major.value,
- version.minor.value);
-
- if (version.major)
- return selectTypeIdByModuleIdAndExportedNameAndMajorVersionStatement
- .template valueWithTransaction<TypeId>(moduleId, exportedTypeName, version.major.value);
+ Storage::Version version) const override;
- return selectTypeIdByModuleIdAndExportedNameStatement
- .template valueWithTransaction<TypeId>(moduleId, exportedTypeName);
- }
-
- TypeId typeId(ImportedTypeNameId typeNameId) const override
- {
- NanotraceHR::Tracer tracer{"get type id by imported type name"_t, projectStorageCategory()};
-
- return Sqlite::withDeferredTransaction(database, [&] { return fetchTypeId(typeNameId); });
- }
+ TypeId typeId(ImportedTypeNameId typeNameId) const override;
- QVarLengthArray<TypeId, 256> typeIds(ModuleId moduleId) const override
- {
- NanotraceHR::Tracer tracer{"get type ids by module id"_t, projectStorageCategory()};
+ QVarLengthArray<TypeId, 256> typeIds(ModuleId moduleId) const override;
- return selectTypeIdsByModuleIdStatement
- .template valuesWithTransaction<QVarLengthArray<TypeId, 256>>(moduleId);
- }
+ Storage::Info::ExportedTypeNames exportedTypeNames(TypeId typeId) const override;
- Storage::Info::ExportedTypeNames exportedTypeNames(TypeId typeId) const override
- {
- NanotraceHR::Tracer tracer{"get exported type names by type id"_t, projectStorageCategory()};
+ Storage::Info::ExportedTypeNames exportedTypeNames(TypeId typeId, SourceId sourceId) const override;
- return selectExportedTypesByTypeIdStatement
- .template valuesWithTransaction<Storage::Info::ExportedTypeName, 4>(typeId);
- }
+ ImportId importId(const Storage::Import &import) const override;
- Storage::Info::ExportedTypeNames exportedTypeNames(TypeId typeId,
- SourceId sourceId) const override
- {
- NanotraceHR::Tracer tracer{"get exported type names by source id"_t, projectStorageCategory()};
+ ImportedTypeNameId importedTypeNameId(ImportId importId, Utils::SmallStringView typeName) override;
- return selectExportedTypesByTypeIdAndSourceIdStatement
- .template valuesWithTransaction<Storage::Info::ExportedTypeName, 4>(typeId, sourceId);
- }
+ ImportedTypeNameId importedTypeNameId(SourceId sourceId, Utils::SmallStringView typeName) override;
- ImportId importId(const Storage::Import &import) const override
- {
- NanotraceHR::Tracer tracer{"get import id by import"_t, projectStorageCategory()};
+ QVarLengthArray<PropertyDeclarationId, 128> propertyDeclarationIds(TypeId typeId) const override;
- return Sqlite::withDeferredTransaction(database, [&] {
- return fetchImportId(import.sourceId, import);
- });
- }
-
- ImportedTypeNameId importedTypeNameId(ImportId importId,
- Utils::SmallStringView typeName) override
- {
- NanotraceHR::Tracer tracer{"get imported type name id by import id"_t,
- projectStorageCategory()};
-
- return Sqlite::withDeferredTransaction(database, [&] {
- return fetchImportedTypeNameId(Storage::Synchronization::TypeNameKind::QualifiedExported,
- importId,
- typeName);
- });
- }
-
- ImportedTypeNameId importedTypeNameId(SourceId sourceId,
- Utils::SmallStringView typeName) override
- {
- NanotraceHR::Tracer tracer{"get imported type name id by source id"_t,
- projectStorageCategory()};
-
- return Sqlite::withDeferredTransaction(database, [&] {
- return fetchImportedTypeNameId(Storage::Synchronization::TypeNameKind::Exported,
- sourceId,
- typeName);
- });
- }
-
- QVarLengthArray<PropertyDeclarationId, 128> propertyDeclarationIds(TypeId typeId) const override
- {
- NanotraceHR::Tracer tracer{"get property declaration ids"_t, projectStorageCategory()};
-
- return selectPropertyDeclarationIdsForTypeStatement
- .template valuesWithTransaction<QVarLengthArray<PropertyDeclarationId, 128>>(typeId);
- }
-
- QVarLengthArray<PropertyDeclarationId, 128> localPropertyDeclarationIds(TypeId typeId) const override
- {
- NanotraceHR::Tracer tracer{"get local property declaration ids"_t, projectStorageCategory()};
-
- return selectLocalPropertyDeclarationIdsForTypeStatement
- .template valuesWithTransaction<QVarLengthArray<PropertyDeclarationId, 128>>(typeId);
- }
+ QVarLengthArray<PropertyDeclarationId, 128> localPropertyDeclarationIds(TypeId typeId) const override;
PropertyDeclarationId propertyDeclarationId(TypeId typeId,
- Utils::SmallStringView propertyName) const override
- {
- NanotraceHR::Tracer tracer{"get property declaration id"_t, projectStorageCategory()};
-
- return selectPropertyDeclarationIdForTypeAndPropertyNameStatement
- .template valueWithTransaction<PropertyDeclarationId>(typeId, propertyName);
- }
+ Utils::SmallStringView propertyName) const override;
PropertyDeclarationId localPropertyDeclarationId(TypeId typeId,
- Utils::SmallStringView propertyName) const
- {
- NanotraceHR::Tracer tracer{"get local property declaration id"_t, projectStorageCategory()};
+ Utils::SmallStringView propertyName) const;
- return selectLocalPropertyDeclarationIdForTypeAndPropertyNameStatement
- .template valueWithTransaction<PropertyDeclarationId>(typeId, propertyName);
- }
+ PropertyDeclarationId defaultPropertyDeclarationId(TypeId typeId) const override;
std::optional<Storage::Info::PropertyDeclaration> propertyDeclaration(
- PropertyDeclarationId propertyDeclarationId) const override
- {
- NanotraceHR::Tracer tracer{"get property declaration"_t, projectStorageCategory()};
-
- return selectPropertyDeclarationForPropertyDeclarationIdStatement
- .template optionalValueWithTransaction<Storage::Info::PropertyDeclaration>(
- propertyDeclarationId);
- }
-
- std::optional<Storage::Info::Type> type(TypeId typeId) const override
- {
- NanotraceHR::Tracer tracer{"get type"_t, projectStorageCategory()};
+ PropertyDeclarationId propertyDeclarationId) const override;
- return selectInfoTypeByTypeIdStatement.template optionalValueWithTransaction<Storage::Info::Type>(
- typeId);
- }
+ std::optional<Storage::Info::Type> type(TypeId typeId) const override;
- Utils::PathString typeIconPath(TypeId typeId) const override
- {
- NanotraceHR::Tracer tracer{"get type icon path"_t, projectStorageCategory()};
+ Utils::PathString typeIconPath(TypeId typeId) const override;
- return selectTypeIconPathStatement.template valueWithTransaction<Utils::PathString>(typeId);
- }
+ Storage::Info::TypeHints typeHints(TypeId typeId) const override;
- Storage::Info::TypeHints typeHints(TypeId typeId) const override
- {
- NanotraceHR::Tracer tracer{"get type hints"_t, projectStorageCategory()};
+ SmallSourceIds<4> typeAnnotationSourceIds(SourceId directoryId) const override;
- return selectTypeHintsStatement.template valuesWithTransaction<Storage::Info::TypeHints, 4>(
- typeId);
- }
-
- Storage::Info::ItemLibraryEntries itemLibraryEntries(TypeId typeId) const override
- {
- NanotraceHR::Tracer tracer{"get item library entries by type id"_t, projectStorageCategory()};
-
- using Storage::Info::ItemLibraryProperties;
- Storage::Info::ItemLibraryEntries entries;
-
- auto callback = [&](TypeId typeId_,
- Utils::SmallStringView name,
- Utils::SmallStringView iconPath,
- Utils::SmallStringView category,
- Utils::SmallStringView import,
- Utils::SmallStringView toolTip,
- Utils::SmallStringView properties,
- Utils::SmallStringView extraFilePaths,
- Utils::SmallStringView templatePath) {
- auto &last = entries.emplace_back(
- typeId_, name, iconPath, category, import, toolTip, templatePath);
- if (properties.size())
- selectItemLibraryPropertiesStatement.readTo(last.properties, properties);
- if (extraFilePaths.size())
- selectItemLibraryExtraFilePathsStatement.readTo(last.extraFilePaths, extraFilePaths);
- };
-
- selectItemLibraryEntriesByTypeIdStatement.readCallbackWithTransaction(callback, typeId);
-
- return entries;
- }
-
- Storage::Info::ItemLibraryEntries itemLibraryEntries(SourceId sourceId) const override
- {
- NanotraceHR::Tracer tracer{"get item library entries by source id"_t,
- projectStorageCategory()};
-
- using Storage::Info::ItemLibraryProperties;
- Storage::Info::ItemLibraryEntries entries;
-
- auto callback = [&](TypeId typeId,
- Utils::SmallStringView name,
- Utils::SmallStringView iconPath,
- Utils::SmallStringView category,
- Utils::SmallStringView import,
- Utils::SmallStringView toolTip,
- Utils::SmallStringView properties,
- Utils::SmallStringView extraFilePaths,
- Utils::SmallStringView templatePath) {
- auto &last = entries.emplace_back(
- typeId, name, iconPath, category, import, toolTip, templatePath);
- if (properties.size())
- selectItemLibraryPropertiesStatement.readTo(last.properties, properties);
- if (extraFilePaths.size())
- selectItemLibraryExtraFilePathsStatement.readTo(last.extraFilePaths, extraFilePaths);
- };
-
- selectItemLibraryEntriesBySourceIdStatement.readCallbackWithTransaction(callback, sourceId);
-
- return entries;
- }
+ SmallSourceIds<64> typeAnnotationDirectorySourceIds() const override;
- Storage::Info::ItemLibraryEntries allItemLibraryEntries() const override
- {
- NanotraceHR::Tracer tracer{"get all item library entries"_t, projectStorageCategory()};
-
- using Storage::Info::ItemLibraryProperties;
- Storage::Info::ItemLibraryEntries entries;
-
- auto callback = [&](TypeId typeId,
- Utils::SmallStringView name,
- Utils::SmallStringView iconPath,
- Utils::SmallStringView category,
- Utils::SmallStringView import,
- Utils::SmallStringView toolTip,
- Utils::SmallStringView properties,
- Utils::SmallStringView extraFilePaths,
- Utils::SmallStringView templatePath) {
- auto &last = entries.emplace_back(
- typeId, name, iconPath, category, import, toolTip, templatePath);
- if (properties.size())
- selectItemLibraryPropertiesStatement.readTo(last.properties, properties);
- if (extraFilePaths.size())
- selectItemLibraryExtraFilePathsStatement.readTo(last.extraFilePaths, extraFilePaths);
- };
-
- selectItemLibraryEntriesStatement.readCallbackWithTransaction(callback);
-
- return entries;
- }
+ Storage::Info::ItemLibraryEntries itemLibraryEntries(TypeId typeId) const override;
- std::vector<Utils::SmallString> signalDeclarationNames(TypeId typeId) const override
- {
- NanotraceHR::Tracer tracer{"get signal names"_t, projectStorageCategory()};
+ Storage::Info::ItemLibraryEntries itemLibraryEntries(ImportId importId) const;
- return selectSignalDeclarationNamesForTypeStatement
- .template valuesWithTransaction<Utils::SmallString, 32>(typeId);
- }
+ Storage::Info::ItemLibraryEntries itemLibraryEntries(SourceId sourceId) const override;
- std::vector<Utils::SmallString> functionDeclarationNames(TypeId typeId) const override
- {
- NanotraceHR::Tracer tracer{"get function names"_t, projectStorageCategory()};
+ Storage::Info::ItemLibraryEntries allItemLibraryEntries() const override;
- return selectFuncionDeclarationNamesForTypeStatement
- .template valuesWithTransaction<Utils::SmallString, 32>(typeId);
- }
+ std::vector<Utils::SmallString> signalDeclarationNames(TypeId typeId) const override;
- std::optional<Utils::SmallString> propertyName(PropertyDeclarationId propertyDeclarationId) const override
- {
- NanotraceHR::Tracer tracer{"get property name"_t, projectStorageCategory()};
+ std::vector<Utils::SmallString> functionDeclarationNames(TypeId typeId) const override;
- return selectPropertyNameStatement.template optionalValueWithTransaction<Utils::SmallString>(
- propertyDeclarationId);
- }
+ std::optional<Utils::SmallString> propertyName(PropertyDeclarationId propertyDeclarationId) const override;
- const Storage::Info::CommonTypeCache<ProjectStorageInterface> &commonTypeCache() const override
+ const Storage::Info::CommonTypeCache<ProjectStorageType> &commonTypeCache() const override
{
return commonTypeCache_;
}
@@ -443,101 +119,70 @@ public:
template<const char *moduleName, const char *typeName>
TypeId commonTypeId() const
{
- NanotraceHR::Tracer tracer{"get type id from common type cache"_t, projectStorageCategory()};
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get type id from common type cache"_t,
+ projectStorageCategory(),
+ keyValue("module name", std::string_view{moduleName}),
+ keyValue("type name", std::string_view{typeName})};
+
+ auto typeId = commonTypeCache_.typeId<moduleName, typeName>();
+
+ tracer.end(keyValue("type id", typeId));
- return commonTypeCache_.template typeId<moduleName, typeName>();
+ return typeId;
}
template<typename BuiltinType>
TypeId builtinTypeId() const
{
+ using NanotraceHR::keyValue;
NanotraceHR::Tracer tracer{"get builtin type id from common type cache"_t,
projectStorageCategory()};
- return commonTypeCache_.template builtinTypeId<BuiltinType>();
+ auto typeId = commonTypeCache_.builtinTypeId<BuiltinType>();
+
+ tracer.end(keyValue("type id", typeId));
+
+ return typeId;
}
template<const char *builtinType>
TypeId builtinTypeId() const
{
+ using NanotraceHR::keyValue;
NanotraceHR::Tracer tracer{"get builtin type id from common type cache"_t,
projectStorageCategory()};
- return commonTypeCache_.template builtinTypeId<builtinType>();
- }
+ auto typeId = commonTypeCache_.builtinTypeId<builtinType>();
- TypeIds prototypeIds(TypeId type) const override
- {
- NanotraceHR::Tracer tracer{"get prototypes"_t, projectStorageCategory()};
+ tracer.end(keyValue("type id", typeId));
- return selectPrototypeIdsForTypeIdInOrderStatement.template valuesWithTransaction<TypeId, 16>(
- type);
+ return typeId;
}
- TypeIds prototypeAndSelfIds(TypeId type) const override
- {
- NanotraceHR::Tracer tracer{"get prototypes and self"_t, projectStorageCategory()};
-
- return selectPrototypeAndSelfIdsForTypeIdInOrderStatement
- .template valuesWithTransaction<TypeId, 16>(type);
- }
+ SmallTypeIds<16> prototypeIds(TypeId type) const override;
- TypeIds heirIds(TypeId typeId) const override
- {
- NanotraceHR::Tracer tracer{"get heirs"_t, projectStorageCategory()};
+ SmallTypeIds<16> prototypeAndSelfIds(TypeId typeId) const override;
- return selectHeirTypeIdsStatement.template valuesWithTransaction<TypeId, 64>(typeId);
- }
+ SmallTypeIds<64> heirIds(TypeId typeId) const override;
template<typename... TypeIds>
- bool isBasedOn_(TypeId typeId, TypeIds... baseTypeIds) const
- {
- NanotraceHR::Tracer tracer{"is based on"_t, projectStorageCategory()};
+ bool isBasedOn_(TypeId typeId, TypeIds... baseTypeIds) const;
- static_assert(((std::is_same_v<TypeId, TypeIds>) &&...), "Parameter must be a TypeId!");
+ bool isBasedOn(TypeId) const;
- if (((typeId == baseTypeIds) || ...))
- return true;
+ bool isBasedOn(TypeId typeId, TypeId id1) const override;
- auto range = selectPrototypeIdsStatement.template rangeWithTransaction<TypeId>(typeId);
+ bool isBasedOn(TypeId typeId, TypeId id1, TypeId id2) const override;
- for ([[maybe_unused]] TypeId currentTypeId : range) {
- if (((currentTypeId == baseTypeIds) || ...))
- return true;
- }
-
- return false;
- }
-
- bool isBasedOn(TypeId typeId) const { return isBasedOn_(typeId); }
-
- bool isBasedOn(TypeId typeId, TypeId id1) const override { return isBasedOn_(typeId, id1); }
-
- bool isBasedOn(TypeId typeId, TypeId id1, TypeId id2) const override
- {
- return isBasedOn_(typeId, id1, id2);
- }
-
- bool isBasedOn(TypeId typeId, TypeId id1, TypeId id2, TypeId id3) const override
- {
- return isBasedOn_(typeId, id1, id2, id3);
- }
+ bool isBasedOn(TypeId typeId, TypeId id1, TypeId id2, TypeId id3) const override;
- bool isBasedOn(TypeId typeId, TypeId id1, TypeId id2, TypeId id3, TypeId id4) const override
- {
- return isBasedOn_(typeId, id1, id2, id3, id4);
- }
+ bool isBasedOn(TypeId typeId, TypeId id1, TypeId id2, TypeId id3, TypeId id4) const override;
- bool isBasedOn(TypeId typeId, TypeId id1, TypeId id2, TypeId id3, TypeId id4, TypeId id5) const override
- {
- return isBasedOn_(typeId, id1, id2, id3, id4, id5);
- }
+ bool isBasedOn(TypeId typeId, TypeId id1, TypeId id2, TypeId id3, TypeId id4, TypeId id5) const override;
- bool isBasedOn(
- TypeId typeId, TypeId id1, TypeId id2, TypeId id3, TypeId id4, TypeId id5, TypeId id6) const override
- {
- return isBasedOn_(typeId, id1, id2, id3, id4, id5, id6);
- }
+ bool isBasedOn(TypeId typeId, TypeId id1, TypeId id2, TypeId id3, TypeId id4, TypeId id5, TypeId id6)
+ const override;
bool isBasedOn(TypeId typeId,
TypeId id1,
@@ -546,251 +191,57 @@ public:
TypeId id4,
TypeId id5,
TypeId id6,
- TypeId id7) const override
- {
- return isBasedOn_(typeId, id1, id2, id3, id4, id5, id6, id7);
- }
-
- TypeId fetchTypeIdByExportedName(Utils::SmallStringView name) const
- {
- NanotraceHR::Tracer tracer{"is based on"_t, projectStorageCategory()};
-
- return selectTypeIdByExportedNameStatement.template valueWithTransaction<TypeId>(name);
- }
-
- TypeId fetchTypeIdByModuleIdsAndExportedName(ModuleIds moduleIds, Utils::SmallStringView name) const
- {
- return selectTypeIdByModuleIdsAndExportedNameStatement.template valueWithTransaction<TypeId>(
- static_cast<void *>(moduleIds.data()), static_cast<long long>(moduleIds.size()), name);
- }
-
- TypeId fetchTypeIdByName(SourceId sourceId, Utils::SmallStringView name)
- {
- return selectTypeIdBySourceIdAndNameStatement.template valueWithTransaction<TypeId>(sourceId,
- name);
- }
-
- Storage::Synchronization::Type fetchTypeByTypeId(TypeId typeId)
- {
- return Sqlite::withDeferredTransaction(database, [&] {
- auto type = selectTypeByTypeIdStatement.template value<Storage::Synchronization::Type>(
- typeId);
-
- type.exportedTypes = fetchExportedTypes(typeId);
- type.propertyDeclarations = fetchPropertyDeclarations(type.typeId);
- type.functionDeclarations = fetchFunctionDeclarations(type.typeId);
- type.signalDeclarations = fetchSignalDeclarations(type.typeId);
- type.enumerationDeclarations = fetchEnumerationDeclarations(type.typeId);
-
- return type;
- });
- }
-
- Storage::Synchronization::Types fetchTypes()
- {
- return Sqlite::withDeferredTransaction(database, [&] {
- auto types = selectTypesStatement.template values<Storage::Synchronization::Type, 64>();
-
- for (Storage::Synchronization::Type &type : types) {
- type.exportedTypes = fetchExportedTypes(type.typeId);
- type.propertyDeclarations = fetchPropertyDeclarations(type.typeId);
- type.functionDeclarations = fetchFunctionDeclarations(type.typeId);
- type.signalDeclarations = fetchSignalDeclarations(type.typeId);
- type.enumerationDeclarations = fetchEnumerationDeclarations(type.typeId);
- }
-
- return types;
- });
- }
-
- bool fetchIsProtype(TypeId type, TypeId prototype)
- {
- return bool(selectPrototypeIdStatement.template valueWithTransaction<TypeId>(type, prototype));
- }
-
- auto fetchPrototypes(TypeId type)
- {
- return selectPrototypeIdsInOrderStatement.template rangeWithTransaction<TypeId>(type);
- }
-
- SourceContextId fetchSourceContextIdUnguarded(Utils::SmallStringView sourceContextPath)
- {
- NanotraceHR::Tracer tracer{"fetch source context id unguarded"_t, projectStorageCategory()};
-
- auto sourceContextId = readSourceContextId(sourceContextPath);
-
- return sourceContextId ? sourceContextId : writeSourceContextId(sourceContextPath);
- }
-
- SourceContextId fetchSourceContextId(Utils::SmallStringView sourceContextPath)
- {
- NanotraceHR::Tracer tracer{"fetch source context id"_t, projectStorageCategory()};
-
- try {
- return Sqlite::withDeferredTransaction(database, [&] {
- return fetchSourceContextIdUnguarded(sourceContextPath);
- });
- } catch (const Sqlite::ConstraintPreventsModification &) {
- return fetchSourceContextId(sourceContextPath);
- }
- }
-
- Utils::PathString fetchSourceContextPath(SourceContextId sourceContextId) const
- {
- NanotraceHR::Tracer tracer{"fetch source context path"_t, projectStorageCategory()};
-
- return Sqlite::withDeferredTransaction(database, [&] {
- auto optionalSourceContextPath = selectSourceContextPathFromSourceContextsBySourceContextIdStatement
- .template optionalValue<Utils::PathString>(
- sourceContextId);
-
- if (!optionalSourceContextPath)
- throw SourceContextIdDoesNotExists();
-
- return std::move(*optionalSourceContextPath);
- });
- }
-
- auto fetchAllSourceContexts() const
- {
- NanotraceHR::Tracer tracer{"fetch all source contexts"_t, projectStorageCategory()};
-
- return selectAllSourceContextsStatement
- .template valuesWithTransaction<Cache::SourceContext, 128>();
- }
-
- SourceId fetchSourceId(SourceContextId sourceContextId, Utils::SmallStringView sourceName)
- {
- NanotraceHR::Tracer tracer{"fetch source id"_t, projectStorageCategory()};
-
- return Sqlite::withDeferredTransaction(database, [&] {
- return fetchSourceIdUnguarded(sourceContextId, sourceName);
- });
- }
-
- auto fetchSourceNameAndSourceContextId(SourceId sourceId) const
- {
- NanotraceHR::Tracer tracer{"fetch source name and source context id"_t,
- projectStorageCategory()};
-
- auto value = selectSourceNameAndSourceContextIdFromSourcesBySourceIdStatement
- .template valueWithTransaction<Cache::SourceNameAndSourceContextId>(sourceId);
-
- if (!value.sourceContextId)
- throw SourceIdDoesNotExists();
+ TypeId id7) const override;
- return value;
- }
-
- void clearSources()
- {
- Sqlite::withImmediateTransaction(database, [&] {
- deleteAllSourceContextsStatement.execute();
- deleteAllSourcesStatement.execute();
- });
- }
-
- SourceContextId fetchSourceContextId(SourceId sourceId) const
- {
- NanotraceHR::Tracer tracer{"fetch source context id"_t, projectStorageCategory()};
-
- auto sourceContextId = selectSourceContextIdFromSourcesBySourceIdStatement
- .template valueWithTransaction<SourceContextId>(sourceId);
+ TypeId fetchTypeIdByExportedName(Utils::SmallStringView name) const;
- if (!sourceContextId)
- throw SourceIdDoesNotExists();
+ TypeId fetchTypeIdByModuleIdsAndExportedName(ModuleIds moduleIds,
+ Utils::SmallStringView name) const;
- return sourceContextId;
- }
-
- auto fetchAllSources() const
- {
- NanotraceHR::Tracer tracer{"fetch all sources"_t, projectStorageCategory()};
+ TypeId fetchTypeIdByName(SourceId sourceId, Utils::SmallStringView name);
- return selectAllSourcesStatement.template valuesWithTransaction<Cache::Source, 1024>();
- }
+ Storage::Synchronization::Type fetchTypeByTypeId(TypeId typeId);
- SourceId fetchSourceIdUnguarded(SourceContextId sourceContextId, Utils::SmallStringView sourceName)
- {
- NanotraceHR::Tracer tracer{"fetch source id unguarded"_t, projectStorageCategory()};
+ Storage::Synchronization::Types fetchTypes();
- auto sourceId = readSourceId(sourceContextId, sourceName);
+ SourceContextId fetchSourceContextIdUnguarded(Utils::SmallStringView sourceContextPath);
- if (sourceId)
- return sourceId;
+ SourceContextId fetchSourceContextId(Utils::SmallStringView sourceContextPath);
- return writeSourceId(sourceContextId, sourceName);
- }
+ Utils::PathString fetchSourceContextPath(SourceContextId sourceContextId) const;
- auto fetchAllFileStatuses() const
- {
- NanotraceHR::Tracer tracer{"fetch all file statuses"_t, projectStorageCategory()};
+ Cache::SourceContexts fetchAllSourceContexts() const;
- return selectAllFileStatusesStatement.template rangeWithTransaction<FileStatus>();
- }
+ SourceId fetchSourceId(SourceContextId sourceContextId, Utils::SmallStringView sourceName);
- FileStatus fetchFileStatus(SourceId sourceId) const override
- {
- NanotraceHR::Tracer tracer{"fetch file status"_t, projectStorageCategory()};
+ Cache::SourceNameAndSourceContextId fetchSourceNameAndSourceContextId(SourceId sourceId) const;
- return selectFileStatusesForSourceIdStatement.template valueWithTransaction<FileStatus>(
- sourceId);
- }
+ void clearSources();
- std::optional<Storage::Synchronization::ProjectData> fetchProjectData(SourceId sourceId) const override
- {
- NanotraceHR::Tracer tracer{"fetch project data"_t, projectStorageCategory()};
+ SourceContextId fetchSourceContextId(SourceId sourceId) const;
- return selectProjectDataForSourceIdStatement
- .template optionalValueWithTransaction<Storage::Synchronization::ProjectData>(sourceId);
- }
+ Cache::Sources fetchAllSources() const;
- Storage::Synchronization::ProjectDatas fetchProjectDatas(SourceId projectSourceId) const override
- {
- NanotraceHR::Tracer tracer{"fetch project datas by source id"_t, projectStorageCategory()};
+ SourceId fetchSourceIdUnguarded(SourceContextId sourceContextId,
+ Utils::SmallStringView sourceName);
- return selectProjectDatasForSourceIdStatement
- .template valuesWithTransaction<Storage::Synchronization::ProjectData, 1024>(
- projectSourceId);
- }
+ FileStatuses fetchAllFileStatuses() const;
- Storage::Synchronization::ProjectDatas fetchProjectDatas(const SourceIds &projectSourceIds) const
- {
- NanotraceHR::Tracer tracer{"fetch project datas by source ids"_t, projectStorageCategory()};
+ FileStatus fetchFileStatus(SourceId sourceId) const override;
- return selectProjectDatasForSourceIdsStatement
- .template valuesWithTransaction<Storage::Synchronization::ProjectData, 64>(
- toIntegers(projectSourceIds));
- }
+ std::optional<Storage::Synchronization::ProjectData> fetchProjectData(SourceId sourceId) const override;
- void setPropertyEditorPathId(TypeId typeId, SourceId pathId)
- {
- Sqlite::ImmediateSessionTransaction transaction{database};
+ Storage::Synchronization::ProjectDatas fetchProjectDatas(SourceId projectSourceId) const override;
- upsertPropertyEditorPathIdStatement.write(typeId, pathId);
+ Storage::Synchronization::ProjectDatas fetchProjectDatas(const SourceIds &projectSourceIds) const;
- transaction.commit();
- }
+ void setPropertyEditorPathId(TypeId typeId, SourceId pathId);
- SourceId propertyEditorPathId(TypeId typeId) const override
- {
- return selectPropertyEditorPathIdStatement.template valueWithTransaction<SourceId>(typeId);
- }
+ SourceId propertyEditorPathId(TypeId typeId) const override;
- Storage::Imports fetchDocumentImports() const
- {
- NanotraceHR::Tracer tracer{"fetch document imports"_t, projectStorageCategory()};
+ Storage::Imports fetchDocumentImports() const;
- return selectAllDocumentImportForSourceIdStatement
- .template valuesWithTransaction<Storage::Imports>();
- }
-
- void resetForTestsOnly()
- {
- database.clearAllTablesForTestsOnly();
- commonTypeCache_.clearForTestsOnly();
- moduleCache.clearForTestOnly();
- }
+ void resetForTestsOnly();
private:
class ModuleStorageAdapter
@@ -818,12 +269,11 @@ private:
}
};
+ using Modules = std::vector<Module>;
+
friend ModuleStorageAdapter;
- static bool moduleNameLess(Utils::SmallStringView first, Utils::SmallStringView second) noexcept
- {
- return first < second;
- }
+ static bool moduleNameLess(Utils::SmallStringView first, Utils::SmallStringView second) noexcept;
using ModuleCache = StorageCache<Utils::PathString,
Utils::SmallStringView,
@@ -833,29 +283,13 @@ private:
moduleNameLess,
Module>;
- ModuleId fetchModuleId(Utils::SmallStringView moduleName)
- {
- return Sqlite::withDeferredTransaction(database,
- [&] { return fetchModuleIdUnguarded(moduleName); });
- }
+ ModuleId fetchModuleId(Utils::SmallStringView moduleName);
- auto fetchModuleName(ModuleId id)
- {
- return Sqlite::withDeferredTransaction(database, [&] { return fetchModuleNameUnguarded(id); });
- }
+ Utils::PathString fetchModuleName(ModuleId id);
- auto fetchAllModules() const
- {
- return selectAllModulesStatement.template valuesWithTransaction<Module, 128>();
- }
+ Modules fetchAllModules() const;
- void callRefreshMetaInfoCallback(const TypeIds &deletedTypeIds)
- {
- if (deletedTypeIds.size()) {
- for (ProjectStorageObserver *observer : observers)
- observer->removedTypeIds(deletedTypeIds);
- }
- }
+ void callRefreshMetaInfoCallback(const TypeIds &deletedTypeIds);
class AliasPropertyDeclaration
{
@@ -882,6 +316,25 @@ private:
< std::tie(second.typeId, second.propertyDeclarationId);
}
+ template<typename String>
+ friend void convertToString(String &string,
+ const AliasPropertyDeclaration &aliasPropertyDeclaration)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(
+ keyValue("type id", aliasPropertyDeclaration.typeId),
+ keyValue("property declaration id", aliasPropertyDeclaration.propertyDeclarationId),
+ keyValue("alias imported type name id",
+ aliasPropertyDeclaration.aliasImportedTypeNameId),
+ keyValue("alias property name", aliasPropertyDeclaration.aliasPropertyName),
+ keyValue("alias property name tail", aliasPropertyDeclaration.aliasPropertyNameTail),
+ keyValue("alias property declaration id",
+ aliasPropertyDeclaration.aliasPropertyDeclarationId));
+
+ convertToString(string, dict);
+ }
+
public:
TypeId typeId;
PropertyDeclarationId propertyDeclarationId;
@@ -910,6 +363,20 @@ private:
< std::tie(second.typeId, second.propertyDeclarationId);
}
+ template<typename String>
+ friend void convertToString(String &string, const PropertyDeclaration &propertyDeclaration)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("type id", propertyDeclaration.typeId),
+ keyValue("property declaration id",
+ propertyDeclaration.propertyDeclarationId),
+ keyValue("imported type name id",
+ propertyDeclaration.importedTypeNameId));
+
+ convertToString(string, dict);
+ }
+
public:
TypeId typeId;
PropertyDeclarationId propertyDeclarationId;
@@ -931,6 +398,17 @@ private:
return first.typeId < second.typeId;
}
+ template<typename String>
+ friend void convertToString(String &string, const Prototype &prototype)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("type id", prototype.typeId),
+ keyValue("prototype name id", prototype.prototypeNameId));
+
+ convertToString(string, dict);
+ }
+
public:
TypeId typeId;
ImportedTypeNameId prototypeNameId;
@@ -970,37 +448,14 @@ private:
}
};
- SourceIds filterSourceIdsWithoutType(const SourceIds &updatedSourceIds, SourceIds &sourceIdsOfTypes)
- {
- std::sort(sourceIdsOfTypes.begin(), sourceIdsOfTypes.end());
+ SourceIds filterSourceIdsWithoutType(const SourceIds &updatedSourceIds,
+ SourceIds &sourceIdsOfTypes);
- SourceIds sourceIdsWithoutTypeSourceIds;
- sourceIdsWithoutTypeSourceIds.reserve(updatedSourceIds.size());
- std::set_difference(updatedSourceIds.begin(),
- updatedSourceIds.end(),
- sourceIdsOfTypes.begin(),
- sourceIdsOfTypes.end(),
- std::back_inserter(sourceIdsWithoutTypeSourceIds));
+ TypeIds fetchTypeIds(const SourceIds &sourceIds);
- return sourceIdsWithoutTypeSourceIds;
- }
+ void unique(SourceIds &sourceIds);
- TypeIds fetchTypeIds(const SourceIds &sourceIds)
- {
- return selectTypeIdsForSourceIdsStatement.template values<TypeId, 128>(toIntegers(sourceIds));
- }
-
- void unique(SourceIds &sourceIds)
- {
- std::sort(sourceIds.begin(), sourceIds.end());
- auto newEnd = std::unique(sourceIds.begin(), sourceIds.end());
- sourceIds.erase(newEnd, sourceIds.end());
- }
-
- void synchronizeTypeTraits(TypeId typeId, Storage::TypeTraits traits)
- {
- updateTypeAnnotationTraitStatement.write(typeId, traits.annotation);
- }
+ void synchronizeTypeTraits(TypeId typeId, Storage::TypeTraits traits);
class TypeAnnotationView
{
@@ -1015,6 +470,19 @@ private:
, hintsJson{hintsJson}
{}
+ template<typename String>
+ friend void convertToString(String &string, const TypeAnnotationView &typeAnnotationView)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("type id", typeAnnotationView.typeId),
+ keyValue("icon path", typeAnnotationView.iconPath),
+ keyValue("item library json", typeAnnotationView.itemLibraryJson),
+ keyValue("hints json", typeAnnotationView.hintsJson));
+
+ convertToString(string, dict);
+ }
+
public:
TypeId typeId;
Utils::SmallStringView iconPath;
@@ -1022,75 +490,21 @@ private:
Utils::PathString hintsJson;
};
- void updateTypeIdInTypeAnnotations(Storage::Synchronization::TypeAnnotations &typeAnnotations)
- {
- for (auto &annotation : typeAnnotations) {
- annotation.typeId = fetchTypeIdByModuleIdAndExportedName(annotation.moduleId,
- annotation.typeName);
- }
- }
+ void updateTypeIdInTypeAnnotations(Storage::Synchronization::TypeAnnotations &typeAnnotations);
- void synchronizeTypeAnnotations(Storage::Synchronization::TypeAnnotations &typeAnnotations,
- const SourceIds &updatedTypeAnnotationSourceIds)
+ template<typename Value>
+ static Sqlite::ValueView createEmptyAsNull(const Value &value)
{
- NanotraceHR::Tracer tracer{"synchronize type annotations"_t, projectStorageCategory()};
-
- using Storage::Synchronization::TypeAnnotation;
-
- updateTypeIdInTypeAnnotations(typeAnnotations);
-
- auto compareKey = [](auto &&first, auto &&second) { return first.typeId - second.typeId; };
-
- std::sort(typeAnnotations.begin(), typeAnnotations.end(), [&](auto &&first, auto &&second) {
- return first.typeId < second.typeId;
- });
+ if (value.size())
+ return Sqlite::ValueView::create(value);
- auto range = selectTypeAnnotationsForSourceIdsStatement.template range<TypeAnnotationView>(
- toIntegers(updatedTypeAnnotationSourceIds));
-
- auto insert = [&](const TypeAnnotation &annotation) {
- if (!annotation.sourceId)
- throw TypeAnnotationHasInvalidSourceId{};
-
- synchronizeTypeTraits(annotation.typeId, annotation.traits);
-
- insertTypeAnnotationStatement.write(annotation.typeId,
- annotation.sourceId,
- annotation.iconPath,
- annotation.itemLibraryJson,
- annotation.hintsJson);
- };
-
- auto update = [&](const TypeAnnotationView &annotationFromDatabase,
- const TypeAnnotation &annotation) {
- synchronizeTypeTraits(annotation.typeId, annotation.traits);
-
- if (annotationFromDatabase.iconPath != annotation.iconPath
- || annotationFromDatabase.itemLibraryJson != annotation.itemLibraryJson
- || annotationFromDatabase.hintsJson != annotation.hintsJson) {
- updateTypeAnnotationStatement.write(annotation.typeId,
- annotation.iconPath,
- annotation.itemLibraryJson,
- annotation.hintsJson);
- return Sqlite::UpdateChange::Update;
- }
-
- return Sqlite::UpdateChange::No;
- };
-
- auto remove = [&](const TypeAnnotationView &annotationFromDatabase) {
- synchronizeTypeTraits(annotationFromDatabase.typeId, Storage::TypeTraits{});
-
- deleteTypeAnnotationStatement.write(annotationFromDatabase.typeId);
- };
-
- Sqlite::insertUpdateDelete(range, typeAnnotations, compareKey, insert, update, remove);
+ return Sqlite::ValueView{};
}
- void synchronizeTypeTrait(const Storage::Synchronization::Type &type)
- {
- updateTypeTraitStatement.write(type.typeId, type.traits.type);
- }
+ void synchronizeTypeAnnotations(Storage::Synchronization::TypeAnnotations &typeAnnotations,
+ const SourceIds &updatedTypeAnnotationSourceIds);
+
+ void synchronizeTypeTrait(const Storage::Synchronization::Type &type);
void synchronizeTypes(Storage::Synchronization::Types &types,
TypeIds &updatedTypeIds,
@@ -1100,384 +514,60 @@ private:
PropertyDeclarations &relinkablePropertyDeclarations,
Prototypes &relinkablePrototypes,
Prototypes &relinkableExtensions,
- const SourceIds &updatedSourceIds)
- {
- NanotraceHR::Tracer tracer{"synchronize types"_t, projectStorageCategory()};
-
- Storage::Synchronization::ExportedTypes exportedTypes;
- exportedTypes.reserve(types.size() * 3);
- SourceIds sourceIdsOfTypes;
- sourceIdsOfTypes.reserve(updatedSourceIds.size());
- SourceIds notUpdatedExportedSourceIds;
- notUpdatedExportedSourceIds.reserve(updatedSourceIds.size());
- SourceIds exportedSourceIds;
- exportedSourceIds.reserve(types.size());
-
- for (auto &type : types) {
- if (!type.sourceId)
- throw TypeHasInvalidSourceId{};
-
- TypeId typeId = declareType(type);
- synchronizeTypeTrait(type);
- sourceIdsOfTypes.push_back(type.sourceId);
- updatedTypeIds.push_back(typeId);
- if (type.changeLevel != Storage::Synchronization::ChangeLevel::ExcludeExportedTypes) {
- exportedSourceIds.push_back(type.sourceId);
- extractExportedTypes(typeId, type, exportedTypes);
- }
- }
-
- std::sort(types.begin(), types.end(), [](const auto &first, const auto &second) {
- return first.typeId < second.typeId;
- });
-
- unique(exportedSourceIds);
-
- SourceIds sourceIdsWithoutType = filterSourceIdsWithoutType(updatedSourceIds,
- sourceIdsOfTypes);
- exportedSourceIds.insert(exportedSourceIds.end(),
- sourceIdsWithoutType.begin(),
- sourceIdsWithoutType.end());
- TypeIds exportedTypeIds = fetchTypeIds(exportedSourceIds);
- synchronizeExportedTypes(exportedTypeIds,
- exportedTypes,
- relinkableAliasPropertyDeclarations,
- relinkablePropertyDeclarations,
- relinkablePrototypes,
- relinkableExtensions);
-
- syncPrototypesAndExtensions(types, relinkablePrototypes, relinkableExtensions);
- resetDefaultPropertiesIfChanged(types);
- resetRemovedAliasPropertyDeclarationsToNull(types, relinkableAliasPropertyDeclarations);
- syncDeclarations(types,
- insertedAliasPropertyDeclarations,
- updatedAliasPropertyDeclarations,
- relinkablePropertyDeclarations);
- syncDefaultProperties(types);
- }
+ const SourceIds &updatedSourceIds);
void synchronizeProjectDatas(Storage::Synchronization::ProjectDatas &projectDatas,
- const SourceIds &updatedProjectSourceIds)
- {
- NanotraceHR::Tracer tracer{"synchronize project datas"_t, projectStorageCategory()};
-
- auto compareKey = [](auto &&first, auto &&second) {
- auto projectSourceIdDifference = first.projectSourceId - second.projectSourceId;
- if (projectSourceIdDifference != 0)
- return projectSourceIdDifference;
-
- return first.sourceId - second.sourceId;
- };
-
- std::sort(projectDatas.begin(), projectDatas.end(), [&](auto &&first, auto &&second) {
- return std::tie(first.projectSourceId, first.sourceId)
- < std::tie(second.projectSourceId, second.sourceId);
- });
-
- auto range = selectProjectDatasForSourceIdsStatement
- .template range<Storage::Synchronization::ProjectData>(
- toIntegers(updatedProjectSourceIds));
-
- auto insert = [&](const Storage::Synchronization::ProjectData &projectData) {
- if (!projectData.projectSourceId)
- throw ProjectDataHasInvalidProjectSourceId{};
- if (!projectData.sourceId)
- throw ProjectDataHasInvalidSourceId{};
-
- insertProjectDataStatement.write(projectData.projectSourceId,
- projectData.sourceId,
- projectData.moduleId,
- projectData.fileType);
- };
-
- auto update = [&](const Storage::Synchronization::ProjectData &projectDataFromDatabase,
- const Storage::Synchronization::ProjectData &projectData) {
- if (projectDataFromDatabase.fileType != projectData.fileType
- || !compareInvalidAreTrue(projectDataFromDatabase.moduleId, projectData.moduleId)) {
- updateProjectDataStatement.write(projectData.projectSourceId,
- projectData.sourceId,
- projectData.moduleId,
- projectData.fileType);
- return Sqlite::UpdateChange::Update;
- }
-
- return Sqlite::UpdateChange::No;
- };
-
- auto remove = [&](const Storage::Synchronization::ProjectData &projectData) {
- deleteProjectDataStatement.write(projectData.projectSourceId, projectData.sourceId);
- };
-
- Sqlite::insertUpdateDelete(range, projectDatas, compareKey, insert, update, remove);
- }
+ const SourceIds &updatedProjectSourceIds);
- void synchronizeFileStatuses(FileStatuses &fileStatuses, const SourceIds &updatedSourceIds)
- {
- NanotraceHR::Tracer tracer{"synchronize file statuses"_t, projectStorageCategory()};
-
- auto compareKey = [](auto &&first, auto &&second) {
- return first.sourceId - second.sourceId;
- };
-
- std::sort(fileStatuses.begin(), fileStatuses.end(), [&](auto &&first, auto &&second) {
- return first.sourceId < second.sourceId;
- });
-
- auto range = selectFileStatusesForSourceIdsStatement.template range<FileStatus>(
- toIntegers(updatedSourceIds));
-
- auto insert = [&](const FileStatus &fileStatus) {
- if (!fileStatus.sourceId)
- throw FileStatusHasInvalidSourceId{};
- insertFileStatusStatement.write(fileStatus.sourceId,
- fileStatus.size,
- fileStatus.lastModified);
- };
-
- auto update = [&](const FileStatus &fileStatusFromDatabase, const FileStatus &fileStatus) {
- if (fileStatusFromDatabase.lastModified != fileStatus.lastModified
- || fileStatusFromDatabase.size != fileStatus.size) {
- updateFileStatusStatement.write(fileStatus.sourceId,
- fileStatus.size,
- fileStatus.lastModified);
- return Sqlite::UpdateChange::Update;
- }
-
- return Sqlite::UpdateChange::No;
- };
-
- auto remove = [&](const FileStatus &fileStatus) {
- deleteFileStatusStatement.write(fileStatus.sourceId);
- };
-
- Sqlite::insertUpdateDelete(range, fileStatuses, compareKey, insert, update, remove);
- }
+ void synchronizeFileStatuses(FileStatuses &fileStatuses, const SourceIds &updatedSourceIds);
void synchronizeImports(Storage::Imports &imports,
const SourceIds &updatedSourceIds,
Storage::Imports &moduleDependencies,
const SourceIds &updatedModuleDependencySourceIds,
Storage::Synchronization::ModuleExportedImports &moduleExportedImports,
- const ModuleIds &updatedModuleIds)
- {
- NanotraceHR::Tracer tracer{"synchronize imports"_t, projectStorageCategory()};
-
- synchromizeModuleExportedImports(moduleExportedImports, updatedModuleIds);
- synchronizeDocumentImports(imports,
- updatedSourceIds,
- Storage::Synchronization::ImportKind::Import);
- synchronizeDocumentImports(moduleDependencies,
- updatedModuleDependencySourceIds,
- Storage::Synchronization::ImportKind::ModuleDependency);
- }
+ const ModuleIds &updatedModuleIds);
void synchromizeModuleExportedImports(
Storage::Synchronization::ModuleExportedImports &moduleExportedImports,
- const ModuleIds &updatedModuleIds)
- {
- std::sort(moduleExportedImports.begin(),
- moduleExportedImports.end(),
- [](auto &&first, auto &&second) {
- return std::tie(first.moduleId, first.exportedModuleId)
- < std::tie(second.moduleId, second.exportedModuleId);
- });
-
- auto range = selectModuleExportedImportsForSourceIdStatement
- .template range<Storage::Synchronization::ModuleExportedImportView>(
- toIntegers(updatedModuleIds));
-
- auto compareKey = [](const Storage::Synchronization::ModuleExportedImportView &view,
- const Storage::Synchronization::ModuleExportedImport &import) -> long long {
- auto moduleIdDifference = view.moduleId - import.moduleId;
- if (moduleIdDifference != 0)
- return moduleIdDifference;
-
- return view.exportedModuleId - import.exportedModuleId;
- };
-
- auto insert = [&](const Storage::Synchronization::ModuleExportedImport &import) {
- if (import.version.minor) {
- insertModuleExportedImportWithVersionStatement.write(import.moduleId,
- import.exportedModuleId,
- import.isAutoVersion,
- import.version.major.value,
- import.version.minor.value);
- } else if (import.version.major) {
- insertModuleExportedImportWithMajorVersionStatement.write(import.moduleId,
- import.exportedModuleId,
- import.isAutoVersion,
- import.version.major.value);
- } else {
- insertModuleExportedImportWithoutVersionStatement.write(import.moduleId,
- import.exportedModuleId,
- import.isAutoVersion);
- }
- };
-
- auto update = [](const Storage::Synchronization::ModuleExportedImportView &,
- const Storage::Synchronization::ModuleExportedImport &) {
- return Sqlite::UpdateChange::No;
- };
-
- auto remove = [&](const Storage::Synchronization::ModuleExportedImportView &view) {
- deleteModuleExportedImportStatement.write(view.moduleExportedImportId);
- };
-
- Sqlite::insertUpdateDelete(range, moduleExportedImports, compareKey, insert, update, remove);
- }
+ const ModuleIds &updatedModuleIds);
- ModuleId fetchModuleIdUnguarded(Utils::SmallStringView name) const override
- {
- auto moduleId = selectModuleIdByNameStatement.template value<ModuleId>(name);
+ ModuleId fetchModuleIdUnguarded(Utils::SmallStringView name) const override;
- if (moduleId)
- return moduleId;
-
- return insertModuleNameStatement.template value<ModuleId>(name);
- }
-
- auto fetchModuleNameUnguarded(ModuleId id) const
- {
- auto moduleName = selectModuleNameStatement.template value<Utils::PathString>(id);
-
- if (moduleName.empty())
- throw ModuleDoesNotExists{};
-
- return moduleName;
- }
+ Utils::PathString fetchModuleNameUnguarded(ModuleId id) const;
void handleAliasPropertyDeclarationsWithPropertyType(
- TypeId typeId, AliasPropertyDeclarations &relinkableAliasPropertyDeclarations)
- {
- auto callback = [&](TypeId typeId_,
- PropertyDeclarationId propertyDeclarationId,
- ImportedTypeNameId propertyImportedTypeNameId,
- PropertyDeclarationId aliasPropertyDeclarationId,
- PropertyDeclarationId aliasPropertyDeclarationTailId) {
- auto aliasPropertyName = selectPropertyNameStatement.template value<Utils::SmallString>(
- aliasPropertyDeclarationId);
- Utils::SmallString aliasPropertyNameTail;
- if (aliasPropertyDeclarationTailId)
- aliasPropertyNameTail = selectPropertyNameStatement.template value<Utils::SmallString>(
- aliasPropertyDeclarationTailId);
-
- relinkableAliasPropertyDeclarations
- .emplace_back(TypeId{typeId_},
- PropertyDeclarationId{propertyDeclarationId},
- ImportedTypeNameId{propertyImportedTypeNameId},
- std::move(aliasPropertyName),
- std::move(aliasPropertyNameTail));
-
- updateAliasPropertyDeclarationToNullStatement.write(propertyDeclarationId);
- };
-
- selectAliasPropertiesDeclarationForPropertiesWithTypeIdStatement.readCallback(callback,
- typeId);
- }
+ TypeId typeId, AliasPropertyDeclarations &relinkableAliasPropertyDeclarations);
void handlePropertyDeclarationWithPropertyType(TypeId typeId,
- PropertyDeclarations &relinkablePropertyDeclarations)
- {
- updatesPropertyDeclarationPropertyTypeToNullStatement.readTo(relinkablePropertyDeclarations,
- typeId);
- }
-
- void handlePrototypes(TypeId prototypeId, Prototypes &relinkablePrototypes)
- {
- auto callback = [&](TypeId typeId, ImportedTypeNameId prototypeNameId) {
- relinkablePrototypes.emplace_back(typeId, prototypeNameId);
- };
+ PropertyDeclarations &relinkablePropertyDeclarations);
- updatePrototypeIdToNullStatement.readCallback(callback, prototypeId);
- }
+ void handlePrototypes(TypeId prototypeId, Prototypes &relinkablePrototypes);
- void handleExtensions(TypeId extensionId, Prototypes &relinkableExtensions)
- {
- auto callback = [&](TypeId typeId, ImportedTypeNameId extensionNameId) {
- relinkableExtensions.emplace_back(typeId, extensionNameId);
- };
-
- updateExtensionIdToNullStatement.readCallback(callback, extensionId);
- }
+ void handleExtensions(TypeId extensionId, Prototypes &relinkableExtensions);
void deleteType(TypeId typeId,
AliasPropertyDeclarations &relinkableAliasPropertyDeclarations,
PropertyDeclarations &relinkablePropertyDeclarations,
Prototypes &relinkablePrototypes,
- Prototypes &relinkableExtensions)
- {
- handlePropertyDeclarationWithPropertyType(typeId, relinkablePropertyDeclarations);
- handleAliasPropertyDeclarationsWithPropertyType(typeId, relinkableAliasPropertyDeclarations);
- handlePrototypes(typeId, relinkablePrototypes);
- handleExtensions(typeId, relinkableExtensions);
- deleteTypeNamesByTypeIdStatement.write(typeId);
- deleteEnumerationDeclarationByTypeIdStatement.write(typeId);
- deletePropertyDeclarationByTypeIdStatement.write(typeId);
- deleteFunctionDeclarationByTypeIdStatement.write(typeId);
- deleteSignalDeclarationByTypeIdStatement.write(typeId);
- deleteTypeStatement.write(typeId);
- }
+ Prototypes &relinkableExtensions);
void relinkAliasPropertyDeclarations(AliasPropertyDeclarations &aliasPropertyDeclarations,
- const TypeIds &deletedTypeIds)
- {
- NanotraceHR::Tracer tracer{"relink alias properties"_t, projectStorageCategory()};
-
- std::sort(aliasPropertyDeclarations.begin(), aliasPropertyDeclarations.end());
-
- Utils::set_greedy_difference(
- aliasPropertyDeclarations.cbegin(),
- aliasPropertyDeclarations.cend(),
- deletedTypeIds.begin(),
- deletedTypeIds.end(),
- [&](const AliasPropertyDeclaration &alias) {
- auto typeId = fetchTypeId(alias.aliasImportedTypeNameId);
-
- if (!typeId)
- throw TypeNameDoesNotExists{fetchImportedTypeName(alias.aliasImportedTypeNameId)};
-
- auto [propertyTypeId, aliasId, propertyTraits] = fetchPropertyDeclarationByTypeIdAndNameUngarded(
- typeId, alias.aliasPropertyName);
-
- updatePropertyDeclarationWithAliasAndTypeStatement.write(alias.propertyDeclarationId,
- propertyTypeId,
- propertyTraits,
- alias.aliasImportedTypeNameId,
- aliasId);
- },
- TypeCompare<AliasPropertyDeclaration>{});
- }
+ const TypeIds &deletedTypeIds);
void relinkPropertyDeclarations(PropertyDeclarations &relinkablePropertyDeclaration,
- const TypeIds &deletedTypeIds)
- {
- NanotraceHR::Tracer tracer{"relink properties"_t, projectStorageCategory()};
-
- std::sort(relinkablePropertyDeclaration.begin(), relinkablePropertyDeclaration.end());
-
- Utils::set_greedy_difference(
- relinkablePropertyDeclaration.cbegin(),
- relinkablePropertyDeclaration.cend(),
- deletedTypeIds.begin(),
- deletedTypeIds.end(),
- [&](const PropertyDeclaration &property) {
- TypeId propertyTypeId = fetchTypeId(property.importedTypeNameId);
-
- if (!propertyTypeId)
- throw TypeNameDoesNotExists{fetchImportedTypeName(property.importedTypeNameId)};
-
- updatePropertyDeclarationTypeStatement.write(property.propertyDeclarationId,
- propertyTypeId);
- },
- TypeCompare<PropertyDeclaration>{});
- }
+ const TypeIds &deletedTypeIds);
template<typename Callable>
void relinkPrototypes(Prototypes &relinkablePrototypes,
const TypeIds &deletedTypeIds,
Callable updateStatement)
{
- NanotraceHR::Tracer tracer{"relink prototypes"_t, projectStorageCategory()};
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"relink prototypes"_t,
+ projectStorageCategory(),
+ keyValue("relinkable prototypes", relinkablePrototypes),
+ keyValue("deleted type ids", deletedTypeIds)};
std::sort(relinkablePrototypes.begin(), relinkablePrototypes.end());
@@ -1505,295 +595,66 @@ private:
PropertyDeclarations &relinkablePropertyDeclarations,
Prototypes &relinkablePrototypes,
Prototypes &relinkableExtensions,
- TypeIds &deletedTypeIds)
- {
- NanotraceHR::Tracer tracer{"delete not updated types"_t, projectStorageCategory()};
-
- auto callback = [&](TypeId typeId) {
- deletedTypeIds.push_back(typeId);
- deleteType(typeId,
- relinkableAliasPropertyDeclarations,
- relinkablePropertyDeclarations,
- relinkablePrototypes,
- relinkableExtensions);
- };
-
- selectNotUpdatedTypesInSourcesStatement.readCallback(callback,
- toIntegers(updatedSourceIds),
- toIntegers(updatedTypeIds));
- for (TypeId typeIdToBeDeleted : typeIdsToBeDeleted)
- callback(typeIdToBeDeleted);
- }
+ TypeIds &deletedTypeIds);
void relink(AliasPropertyDeclarations &relinkableAliasPropertyDeclarations,
PropertyDeclarations &relinkablePropertyDeclarations,
Prototypes &relinkablePrototypes,
Prototypes &relinkableExtensions,
- TypeIds &deletedTypeIds)
- {
- NanotraceHR::Tracer tracer{"relink"_t, projectStorageCategory()};
-
- std::sort(deletedTypeIds.begin(), deletedTypeIds.end());
-
- relinkPrototypes(relinkablePrototypes, deletedTypeIds, [&](TypeId typeId, TypeId prototypeId) {
- updateTypePrototypeStatement.write(typeId, prototypeId);
- });
- relinkPrototypes(relinkableExtensions, deletedTypeIds, [&](TypeId typeId, TypeId prototypeId) {
- updateTypeExtensionStatement.write(typeId, prototypeId);
- });
- relinkPropertyDeclarations(relinkablePropertyDeclarations, deletedTypeIds);
- relinkAliasPropertyDeclarations(relinkableAliasPropertyDeclarations, deletedTypeIds);
- }
+ TypeIds &deletedTypeIds);
PropertyDeclarationId fetchAliasId(TypeId aliasTypeId,
Utils::SmallStringView aliasPropertyName,
- Utils::SmallStringView aliasPropertyNameTail)
- {
- if (aliasPropertyNameTail.empty())
- return fetchPropertyDeclarationIdByTypeIdAndNameUngarded(aliasTypeId, aliasPropertyName);
-
- auto stemAlias = fetchPropertyDeclarationByTypeIdAndNameUngarded(aliasTypeId,
- aliasPropertyName);
-
- return fetchPropertyDeclarationIdByTypeIdAndNameUngarded(stemAlias.propertyTypeId,
- aliasPropertyNameTail);
- }
+ Utils::SmallStringView aliasPropertyNameTail);
- void linkAliasPropertyDeclarationAliasIds(const AliasPropertyDeclarations &aliasDeclarations)
- {
- for (const auto &aliasDeclaration : aliasDeclarations) {
- auto aliasTypeId = fetchTypeId(aliasDeclaration.aliasImportedTypeNameId);
-
- if (!aliasTypeId) {
- throw TypeNameDoesNotExists{
- fetchImportedTypeName(aliasDeclaration.aliasImportedTypeNameId)};
- }
-
- auto aliasId = fetchAliasId(aliasTypeId,
- aliasDeclaration.aliasPropertyName,
- aliasDeclaration.aliasPropertyNameTail);
-
- updatePropertyDeclarationAliasIdAndTypeNameIdStatement
- .write(aliasDeclaration.propertyDeclarationId,
- aliasId,
- aliasDeclaration.aliasImportedTypeNameId);
- }
- }
+ void linkAliasPropertyDeclarationAliasIds(const AliasPropertyDeclarations &aliasDeclarations);
- void updateAliasPropertyDeclarationValues(const AliasPropertyDeclarations &aliasDeclarations)
- {
- for (const auto &aliasDeclaration : aliasDeclarations) {
- updatetPropertiesDeclarationValuesOfAliasStatement.write(
- aliasDeclaration.propertyDeclarationId);
- updatePropertyAliasDeclarationRecursivelyStatement.write(
- aliasDeclaration.propertyDeclarationId);
- }
- }
+ void updateAliasPropertyDeclarationValues(const AliasPropertyDeclarations &aliasDeclarations);
- void checkAliasPropertyDeclarationCycles(const AliasPropertyDeclarations &aliasDeclarations)
- {
- for (const auto &aliasDeclaration : aliasDeclarations)
- checkForAliasChainCycle(aliasDeclaration.propertyDeclarationId);
- }
+ void checkAliasPropertyDeclarationCycles(const AliasPropertyDeclarations &aliasDeclarations);
void linkAliases(const AliasPropertyDeclarations &insertedAliasPropertyDeclarations,
- const AliasPropertyDeclarations &updatedAliasPropertyDeclarations)
- {
- NanotraceHR::Tracer tracer{"link aliases"_t, projectStorageCategory()};
-
- linkAliasPropertyDeclarationAliasIds(insertedAliasPropertyDeclarations);
- linkAliasPropertyDeclarationAliasIds(updatedAliasPropertyDeclarations);
-
- checkAliasPropertyDeclarationCycles(insertedAliasPropertyDeclarations);
- checkAliasPropertyDeclarationCycles(updatedAliasPropertyDeclarations);
-
- updateAliasPropertyDeclarationValues(insertedAliasPropertyDeclarations);
- updateAliasPropertyDeclarationValues(updatedAliasPropertyDeclarations);
- }
+ const AliasPropertyDeclarations &updatedAliasPropertyDeclarations);
void synchronizeExportedTypes(const TypeIds &updatedTypeIds,
Storage::Synchronization::ExportedTypes &exportedTypes,
AliasPropertyDeclarations &relinkableAliasPropertyDeclarations,
PropertyDeclarations &relinkablePropertyDeclarations,
Prototypes &relinkablePrototypes,
- Prototypes &relinkableExtensions)
- {
- NanotraceHR::Tracer tracer{"synchronize exported types"_t, projectStorageCategory()};
-
- std::sort(exportedTypes.begin(), exportedTypes.end(), [](auto &&first, auto &&second) {
- if (first.moduleId < second.moduleId)
- return true;
- else if (first.moduleId > second.moduleId)
- return false;
-
- auto nameCompare = Sqlite::compare(first.name, second.name);
-
- if (nameCompare < 0)
- return true;
- else if (nameCompare > 0)
- return false;
-
- return first.version < second.version;
- });
-
- auto range = selectExportedTypesForSourceIdsStatement
- .template range<Storage::Synchronization::ExportedTypeView>(
- toIntegers(updatedTypeIds));
-
- auto compareKey = [](const Storage::Synchronization::ExportedTypeView &view,
- const Storage::Synchronization::ExportedType &type) -> long long {
- auto moduleIdDifference = view.moduleId - type.moduleId;
- if (moduleIdDifference != 0)
- return moduleIdDifference;
-
- auto nameDifference = Sqlite::compare(view.name, type.name);
- if (nameDifference != 0)
- return nameDifference;
-
- auto versionDifference = view.version.major.value - type.version.major.value;
- if (versionDifference != 0)
- return versionDifference;
-
- return view.version.minor.value - type.version.minor.value;
- };
-
- auto insert = [&](const Storage::Synchronization::ExportedType &type) {
- if (!type.moduleId)
- throw QmlDesigner::ModuleDoesNotExists{};
-
- try {
- if (type.version) {
- insertExportedTypeNamesWithVersionStatement.write(type.moduleId,
- type.name,
- type.version.major.value,
- type.version.minor.value,
- type.typeId);
-
- } else if (type.version.major) {
- insertExportedTypeNamesWithMajorVersionStatement.write(type.moduleId,
- type.name,
- type.version.major.value,
- type.typeId);
- } else {
- insertExportedTypeNamesWithoutVersionStatement.write(type.moduleId,
- type.name,
- type.typeId);
- }
- } catch (const Sqlite::ConstraintPreventsModification &) {
- throw QmlDesigner::ExportedTypeCannotBeInserted{type.name};
- }
- };
-
- auto update = [&](const Storage::Synchronization::ExportedTypeView &view,
- const Storage::Synchronization::ExportedType &type) {
- if (view.typeId != type.typeId) {
- handlePropertyDeclarationWithPropertyType(view.typeId, relinkablePropertyDeclarations);
- handleAliasPropertyDeclarationsWithPropertyType(view.typeId,
- relinkableAliasPropertyDeclarations);
- handlePrototypes(view.typeId, relinkablePrototypes);
- handleExtensions(view.typeId, relinkableExtensions);
- updateExportedTypeNameTypeIdStatement.write(view.exportedTypeNameId, type.typeId);
- return Sqlite::UpdateChange::Update;
- }
- return Sqlite::UpdateChange::No;
- };
-
- auto remove = [&](const Storage::Synchronization::ExportedTypeView &view) {
- handlePropertyDeclarationWithPropertyType(view.typeId, relinkablePropertyDeclarations);
- handleAliasPropertyDeclarationsWithPropertyType(view.typeId,
- relinkableAliasPropertyDeclarations);
- handlePrototypes(view.typeId, relinkablePrototypes);
- handleExtensions(view.typeId, relinkableExtensions);
- deleteExportedTypeNameStatement.write(view.exportedTypeNameId);
- };
-
- Sqlite::insertUpdateDelete(range, exportedTypes, compareKey, insert, update, remove);
- }
+ Prototypes &relinkableExtensions);
void synchronizePropertyDeclarationsInsertAlias(
AliasPropertyDeclarations &insertedAliasPropertyDeclarations,
const Storage::Synchronization::PropertyDeclaration &value,
SourceId sourceId,
- TypeId typeId)
- {
- auto callback = [&](PropertyDeclarationId propertyDeclarationId) {
- insertedAliasPropertyDeclarations.emplace_back(typeId,
- propertyDeclarationId,
- fetchImportedTypeNameId(value.typeName,
- sourceId),
- value.aliasPropertyName,
- value.aliasPropertyNameTail);
- return Sqlite::CallbackControl::Abort;
- };
-
- insertAliasPropertyDeclarationStatement.readCallback(callback, typeId, value.name);
- }
+ TypeId typeId);
+
+ QVarLengthArray<PropertyDeclarationId, 128> fetchPropertyDeclarationIds(TypeId baseTypeId) const;
+
+ PropertyDeclarationId fetchNextPropertyDeclarationId(TypeId baseTypeId,
+ Utils::SmallStringView propertyName) const;
+
+ PropertyDeclarationId fetchPropertyDeclarationId(TypeId typeId,
+ Utils::SmallStringView propertyName) const;
+
+ PropertyDeclarationId fetchNextDefaultPropertyDeclarationId(TypeId baseTypeId) const;
+
+ PropertyDeclarationId fetchDefaultPropertyDeclarationId(TypeId typeId) const;
void synchronizePropertyDeclarationsInsertProperty(
- const Storage::Synchronization::PropertyDeclaration &value, SourceId sourceId, TypeId typeId)
- {
- auto propertyImportedTypeNameId = fetchImportedTypeNameId(value.typeName, sourceId);
- auto propertyTypeId = fetchTypeId(propertyImportedTypeNameId);
-
- if (!propertyTypeId)
- throw TypeNameDoesNotExists{fetchImportedTypeName(propertyImportedTypeNameId)};
-
- auto propertyDeclarationId = insertPropertyDeclarationStatement.template value<PropertyDeclarationId>(
- typeId, value.name, propertyTypeId, value.traits, propertyImportedTypeNameId);
-
- auto nextPropertyDeclarationId = selectPropertyDeclarationIdPrototypeChainDownStatement
- .template value<PropertyDeclarationId>(typeId,
- value.name);
- if (nextPropertyDeclarationId) {
- updateAliasIdPropertyDeclarationStatement.write(nextPropertyDeclarationId,
- propertyDeclarationId);
- updatePropertyAliasDeclarationRecursivelyWithTypeAndTraitsStatement
- .write(propertyDeclarationId, propertyTypeId, value.traits);
- }
- }
+ const Storage::Synchronization::PropertyDeclaration &value, SourceId sourceId, TypeId typeId);
void synchronizePropertyDeclarationsUpdateAlias(
AliasPropertyDeclarations &updatedAliasPropertyDeclarations,
const Storage::Synchronization::PropertyDeclarationView &view,
const Storage::Synchronization::PropertyDeclaration &value,
- SourceId sourceId)
- {
- auto last = updatedAliasPropertyDeclarations.emplace_back(view.typeId,
- view.id,
- fetchImportedTypeNameId(value.typeName,
- sourceId),
- value.aliasPropertyName,
- value.aliasPropertyNameTail,
- view.aliasId);
- }
+ SourceId sourceId);
- auto synchronizePropertyDeclarationsUpdateProperty(
+ Sqlite::UpdateChange synchronizePropertyDeclarationsUpdateProperty(
const Storage::Synchronization::PropertyDeclarationView &view,
const Storage::Synchronization::PropertyDeclaration &value,
SourceId sourceId,
- PropertyDeclarationIds &propertyDeclarationIds)
- {
- auto propertyImportedTypeNameId = fetchImportedTypeNameId(value.typeName, sourceId);
-
- auto propertyTypeId = fetchTypeId(propertyImportedTypeNameId);
-
- if (!propertyTypeId)
- throw TypeNameDoesNotExists{fetchImportedTypeName(propertyImportedTypeNameId)};
-
- if (view.traits == value.traits && propertyTypeId == view.typeId
- && propertyImportedTypeNameId == view.typeNameId)
- return Sqlite::UpdateChange::No;
-
- updatePropertyDeclarationStatement.write(view.id,
- propertyTypeId,
- value.traits,
- propertyImportedTypeNameId);
- updatePropertyAliasDeclarationRecursivelyWithTypeAndTraitsStatement.write(view.id,
- propertyTypeId,
- value.traits);
- propertyDeclarationIds.push_back(view.id);
- return Sqlite::UpdateChange::Update;
- }
+ PropertyDeclarationIds &propertyDeclarationIds);
void synchronizePropertyDeclarations(
TypeId typeId,
@@ -1801,270 +662,60 @@ private:
SourceId sourceId,
AliasPropertyDeclarations &insertedAliasPropertyDeclarations,
AliasPropertyDeclarations &updatedAliasPropertyDeclarations,
- PropertyDeclarationIds &propertyDeclarationIds)
- {
- NanotraceHR::Tracer tracer{"synchronize property declaration"_t, projectStorageCategory()};
-
- std::sort(propertyDeclarations.begin(),
- propertyDeclarations.end(),
- [](auto &&first, auto &&second) {
- return Sqlite::compare(first.name, second.name) < 0;
- });
-
- auto range = selectPropertyDeclarationsForTypeIdStatement
- .template range<Storage::Synchronization::PropertyDeclarationView>(typeId);
-
- auto compareKey = [](const Storage::Synchronization::PropertyDeclarationView &view,
- const Storage::Synchronization::PropertyDeclaration &value) {
- return Sqlite::compare(view.name, value.name);
- };
-
- auto insert = [&](const Storage::Synchronization::PropertyDeclaration &value) {
- if (value.kind == Storage::Synchronization::PropertyKind::Alias) {
- synchronizePropertyDeclarationsInsertAlias(insertedAliasPropertyDeclarations,
- value,
- sourceId,
- typeId);
- } else {
- synchronizePropertyDeclarationsInsertProperty(value, sourceId, typeId);
- }
- };
-
- auto update = [&](const Storage::Synchronization::PropertyDeclarationView &view,
- const Storage::Synchronization::PropertyDeclaration &value) {
- if (value.kind == Storage::Synchronization::PropertyKind::Alias) {
- synchronizePropertyDeclarationsUpdateAlias(updatedAliasPropertyDeclarations,
- view,
- value,
- sourceId);
- propertyDeclarationIds.push_back(view.id);
- } else {
- return synchronizePropertyDeclarationsUpdateProperty(view,
- value,
- sourceId,
- propertyDeclarationIds);
- }
-
- return Sqlite::UpdateChange::No;
- };
-
- auto remove = [&](const Storage::Synchronization::PropertyDeclarationView &view) {
- auto nextPropertyDeclarationId = selectPropertyDeclarationIdPrototypeChainDownStatement
- .template value<PropertyDeclarationId>(typeId,
- view.name);
- if (nextPropertyDeclarationId) {
- updateAliasPropertyDeclarationByAliasPropertyDeclarationIdStatement
- .write(nextPropertyDeclarationId, view.id);
- }
-
- updateDefaultPropertyIdToNullStatement.write(view.id);
- deletePropertyDeclarationStatement.write(view.id);
- propertyDeclarationIds.push_back(view.id);
- };
-
- Sqlite::insertUpdateDelete(range, propertyDeclarations, compareKey, insert, update, remove);
- }
+ PropertyDeclarationIds &propertyDeclarationIds);
- void resetRemovedAliasPropertyDeclarationsToNull(Storage::Synchronization::Type &type,
- PropertyDeclarationIds &propertyDeclarationIds)
+ class AliasPropertyDeclarationView
{
- if (type.changeLevel == Storage::Synchronization::ChangeLevel::Minimal)
- return;
-
- Storage::Synchronization::PropertyDeclarations &aliasDeclarations = type.propertyDeclarations;
+ public:
+ explicit AliasPropertyDeclarationView(Utils::SmallStringView name,
+ PropertyDeclarationId id,
+ PropertyDeclarationId aliasId)
+ : name{name}
+ , id{id}
+ , aliasId{aliasId}
+ {}
- class AliasPropertyDeclarationView
+ template<typename String>
+ friend void convertToString(String &string,
+ const AliasPropertyDeclarationView &aliasPropertyDeclarationView)
{
- public:
- explicit AliasPropertyDeclarationView(Utils::SmallStringView name,
- PropertyDeclarationId id,
- PropertyDeclarationId aliasId)
- : name{name}
- , id{id}
- , aliasId{aliasId}
- {}
-
- public:
- Utils::SmallStringView name;
- PropertyDeclarationId id;
- PropertyDeclarationId aliasId;
- };
-
- std::sort(aliasDeclarations.begin(), aliasDeclarations.end(), [](auto &&first, auto &&second) {
- return Sqlite::compare(first.name, second.name) < 0;
- });
-
- auto range = selectPropertyDeclarationsWithAliasForTypeIdStatement
- .template range<AliasPropertyDeclarationView>(type.typeId);
-
- auto compareKey = [](const AliasPropertyDeclarationView &view,
- const Storage::Synchronization::PropertyDeclaration &value) {
- return Sqlite::compare(view.name, value.name);
- };
-
- auto insert = [&](const Storage::Synchronization::PropertyDeclaration &) {};
-
- auto update = [&](const AliasPropertyDeclarationView &,
- const Storage::Synchronization::PropertyDeclaration &) {
- return Sqlite::UpdateChange::No;
- };
-
- auto remove = [&](const AliasPropertyDeclarationView &view) {
- updatePropertyDeclarationAliasIdToNullStatement.write(view.id);
- propertyDeclarationIds.push_back(view.id);
- };
-
- Sqlite::insertUpdateDelete(range, aliasDeclarations, compareKey, insert, update, remove);
- }
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", aliasPropertyDeclarationView.name),
+ keyValue("id", aliasPropertyDeclarationView.id),
+ keyValue("alias id", aliasPropertyDeclarationView.aliasId));
- void resetRemovedAliasPropertyDeclarationsToNull(
- Storage::Synchronization::Types &types,
- AliasPropertyDeclarations &relinkableAliasPropertyDeclarations)
- {
- NanotraceHR::Tracer tracer{"reset removed alias properties to null"_t,
- projectStorageCategory()};
+ convertToString(string, dict);
+ }
- PropertyDeclarationIds propertyDeclarationIds;
- propertyDeclarationIds.reserve(types.size());
+ public:
+ Utils::SmallStringView name;
+ PropertyDeclarationId id;
+ PropertyDeclarationId aliasId;
+ };
- for (auto &&type : types)
- resetRemovedAliasPropertyDeclarationsToNull(type, propertyDeclarationIds);
+ void resetRemovedAliasPropertyDeclarationsToNull(Storage::Synchronization::Type &type,
+ PropertyDeclarationIds &propertyDeclarationIds);
- removeRelinkableEntries(relinkableAliasPropertyDeclarations,
- propertyDeclarationIds,
- PropertyCompare<AliasPropertyDeclaration>{});
- }
+ void resetRemovedAliasPropertyDeclarationsToNull(
+ Storage::Synchronization::Types &types,
+ AliasPropertyDeclarations &relinkableAliasPropertyDeclarations);
ImportId insertDocumentImport(const Storage::Import &import,
Storage::Synchronization::ImportKind importKind,
ModuleId sourceModuleId,
- ImportId parentImportId)
- {
- if (import.version.minor) {
- return insertDocumentImportWithVersionStatement
- .template value<ImportId>(import.sourceId,
- import.moduleId,
- sourceModuleId,
- importKind,
- import.version.major.value,
- import.version.minor.value,
- parentImportId);
- } else if (import.version.major) {
- return insertDocumentImportWithMajorVersionStatement
- .template value<ImportId>(import.sourceId,
- import.moduleId,
- sourceModuleId,
- importKind,
- import.version.major.value,
- parentImportId);
- } else {
- return insertDocumentImportWithoutVersionStatement.template value<ImportId>(
- import.sourceId, import.moduleId, sourceModuleId, importKind, parentImportId);
- }
- }
+ ImportId parentImportId);
void synchronizeDocumentImports(Storage::Imports &imports,
const SourceIds &updatedSourceIds,
- Storage::Synchronization::ImportKind importKind)
- {
- std::sort(imports.begin(), imports.end(), [](auto &&first, auto &&second) {
- return std::tie(first.sourceId, first.moduleId, first.version)
- < std::tie(second.sourceId, second.moduleId, second.version);
- });
-
- auto range = selectDocumentImportForSourceIdStatement
- .template range<Storage::Synchronization::ImportView>(toIntegers(
- updatedSourceIds),
- importKind);
-
- auto compareKey = [](const Storage::Synchronization::ImportView &view,
- const Storage::Import &import) -> long long {
- auto sourceIdDifference = view.sourceId - import.sourceId;
- if (sourceIdDifference != 0)
- return sourceIdDifference;
-
- auto moduleIdDifference = view.moduleId - import.moduleId;
- if (moduleIdDifference != 0)
- return moduleIdDifference;
-
- auto versionDifference = view.version.major.value - import.version.major.value;
- if (versionDifference != 0)
- return versionDifference;
-
- return view.version.minor.value - import.version.minor.value;
- };
-
- auto insert = [&](const Storage::Import &import) {
- auto importId = insertDocumentImport(import, importKind, import.moduleId, ImportId{});
- auto callback = [&](ModuleId exportedModuleId, int majorVersion, int minorVersion) {
- Storage::Import additionImport{exportedModuleId,
- Storage::Version{majorVersion, minorVersion},
- import.sourceId};
-
- auto exportedImportKind = importKind == Storage::Synchronization::ImportKind::Import
- ? Storage::Synchronization::ImportKind::ModuleExportedImport
- : Storage::Synchronization::ImportKind::ModuleExportedModuleDependency;
-
- insertDocumentImport(additionImport, exportedImportKind, import.moduleId, importId);
- };
-
- selectModuleExportedImportsForModuleIdStatement.readCallback(callback,
- import.moduleId,
- import.version.major.value,
- import.version.minor.value);
- };
-
- auto update = [](const Storage::Synchronization::ImportView &, const Storage::Import &) {
- return Sqlite::UpdateChange::No;
- };
-
- auto remove = [&](const Storage::Synchronization::ImportView &view) {
- deleteDocumentImportStatement.write(view.importId);
- deleteDocumentImportsWithParentImportIdStatement.write(view.sourceId, view.importId);
- };
-
- Sqlite::insertUpdateDelete(range, imports, compareKey, insert, update, remove);
- }
+ Storage::Synchronization::ImportKind importKind);
- static Utils::PathString createJson(const Storage::Synchronization::ParameterDeclarations &parameters)
- {
- Utils::PathString json;
- json.append("[");
-
- Utils::SmallStringView comma{""};
-
- for (const auto &parameter : parameters) {
- json.append(comma);
- comma = ",";
- json.append(R"({"n":")");
- json.append(parameter.name);
- json.append(R"(","tn":")");
- json.append(parameter.typeName);
- if (parameter.traits == Storage::PropertyDeclarationTraits::None) {
- json.append("\"}");
- } else {
- json.append(R"(","tr":)");
- json.append(Utils::SmallString::number(to_underlying(parameter.traits)));
- json.append("}");
- }
- }
-
- json.append("]");
-
- return json;
- }
+ static Utils::PathString createJson(const Storage::Synchronization::ParameterDeclarations &parameters);
TypeId fetchTypeIdByModuleIdAndExportedName(ModuleId moduleId,
- Utils::SmallStringView name) const override
- {
- return selectTypeIdByModuleIdAndExportedNameStatement.template value<TypeId>(moduleId, name);
- }
+ Utils::SmallStringView name) const override;
- void addTypeIdToPropertyEditorQmlPaths(Storage::Synchronization::PropertyEditorQmlPaths &paths)
- {
- for (auto &path : paths)
- path.typeId = fetchTypeIdByModuleIdAndExportedName(path.moduleId, path.typeName);
- }
+ void addTypeIdToPropertyEditorQmlPaths(Storage::Synchronization::PropertyEditorQmlPaths &paths);
class PropertyEditorQmlPathView
{
@@ -2075,6 +726,19 @@ private:
, directoryId{directoryId}
{}
+ template<typename String>
+ friend void convertToString(String &string,
+ const PropertyEditorQmlPathView &propertyEditorQmlPathView)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("type id", propertyEditorQmlPathView.typeId),
+ keyValue("source id", propertyEditorQmlPathView.pathId),
+ keyValue("directory id", propertyEditorQmlPathView.directoryId));
+
+ convertToString(string, dict);
+ }
+
public:
TypeId typeId;
SourceId pathId;
@@ -2082,279 +746,33 @@ private:
};
void synchronizePropertyEditorPaths(Storage::Synchronization::PropertyEditorQmlPaths &paths,
- SourceIds updatedPropertyEditorQmlPathsSourceIds)
- {
- using Storage::Synchronization::PropertyEditorQmlPath;
- std::sort(paths.begin(), paths.end(), [](auto &&first, auto &&second) {
- return first.typeId < second.typeId;
- });
-
- auto range = selectPropertyEditorPathsForForSourceIdsStatement
- .template range<PropertyEditorQmlPathView>(
- toIntegers(updatedPropertyEditorQmlPathsSourceIds));
-
- auto compareKey = [](const PropertyEditorQmlPathView &view,
- const PropertyEditorQmlPath &value) -> long long {
- return view.typeId - value.typeId;
- };
-
- auto insert = [&](const PropertyEditorQmlPath &path) {
- if (path.typeId)
- insertPropertyEditorPathStatement.write(path.typeId, path.pathId, path.directoryId);
- };
-
- auto update = [&](const PropertyEditorQmlPathView &view, const PropertyEditorQmlPath &value) {
- if (value.pathId != view.pathId || value.directoryId != view.directoryId) {
- updatePropertyEditorPathsStatement.write(value.typeId, value.pathId, value.directoryId);
- return Sqlite::UpdateChange::Update;
- }
- return Sqlite::UpdateChange::No;
- };
-
- auto remove = [&](const PropertyEditorQmlPathView &view) {
- deletePropertyEditorPathStatement.write(view.typeId);
- };
-
- Sqlite::insertUpdateDelete(range, paths, compareKey, insert, update, remove);
- }
+ SourceIds updatedPropertyEditorQmlPathsSourceIds);
void synchronizePropertyEditorQmlPaths(Storage::Synchronization::PropertyEditorQmlPaths &paths,
- SourceIds updatedPropertyEditorQmlPathsSourceIds)
- {
- NanotraceHR::Tracer tracer{"synchronize property editor qml paths"_t,
- projectStorageCategory()};
-
- addTypeIdToPropertyEditorQmlPaths(paths);
- synchronizePropertyEditorPaths(paths, updatedPropertyEditorQmlPathsSourceIds);
- }
+ SourceIds updatedPropertyEditorQmlPathsSourceIds);
void synchronizeFunctionDeclarations(
- TypeId typeId, Storage::Synchronization::FunctionDeclarations &functionsDeclarations)
- {
- NanotraceHR::Tracer tracer{"synchronize function declaration"_t, projectStorageCategory()};
-
- std::sort(functionsDeclarations.begin(),
- functionsDeclarations.end(),
- [](auto &&first, auto &&second) {
- auto compare = Sqlite::compare(first.name, second.name);
-
- if (compare == 0) {
- Utils::PathString firstSignature{createJson(first.parameters)};
- Utils::PathString secondSignature{createJson(second.parameters)};
-
- return Sqlite::compare(firstSignature, secondSignature) < 0;
- }
-
- return compare < 0;
- });
-
- auto range = selectFunctionDeclarationsForTypeIdStatement
- .template range<Storage::Synchronization::FunctionDeclarationView>(typeId);
-
- auto compareKey = [](const Storage::Synchronization::FunctionDeclarationView &view,
- const Storage::Synchronization::FunctionDeclaration &value) {
- auto nameKey = Sqlite::compare(view.name, value.name);
- if (nameKey != 0)
- return nameKey;
-
- Utils::PathString valueSignature{createJson(value.parameters)};
-
- return Sqlite::compare(view.signature, valueSignature);
- };
-
- auto insert = [&](const Storage::Synchronization::FunctionDeclaration &value) {
- Utils::PathString signature{createJson(value.parameters)};
-
- insertFunctionDeclarationStatement.write(typeId, value.name, value.returnTypeName, signature);
- };
-
- auto update = [&](const Storage::Synchronization::FunctionDeclarationView &view,
- const Storage::Synchronization::FunctionDeclaration &value) {
- Utils::PathString signature{createJson(value.parameters)};
-
- if (value.returnTypeName == view.returnTypeName)
- return Sqlite::UpdateChange::No;
-
- updateFunctionDeclarationStatement.write(view.id, value.returnTypeName);
-
- return Sqlite::UpdateChange::Update;
- };
-
- auto remove = [&](const Storage::Synchronization::FunctionDeclarationView &view) {
- deleteFunctionDeclarationStatement.write(view.id);
- };
-
- Sqlite::insertUpdateDelete(range, functionsDeclarations, compareKey, insert, update, remove);
- }
+ TypeId typeId, Storage::Synchronization::FunctionDeclarations &functionsDeclarations);
void synchronizeSignalDeclarations(TypeId typeId,
- Storage::Synchronization::SignalDeclarations &signalDeclarations)
- {
- NanotraceHR::Tracer tracer{"synchronize signal declaration"_t, projectStorageCategory()};
-
- std::sort(signalDeclarations.begin(), signalDeclarations.end(), [](auto &&first, auto &&second) {
- auto compare = Sqlite::compare(first.name, second.name);
-
- if (compare == 0) {
- Utils::PathString firstSignature{createJson(first.parameters)};
- Utils::PathString secondSignature{createJson(second.parameters)};
-
- return Sqlite::compare(firstSignature, secondSignature) < 0;
- }
-
- return compare < 0;
- });
-
- auto range = selectSignalDeclarationsForTypeIdStatement
- .template range<Storage::Synchronization::SignalDeclarationView>(typeId);
-
- auto compareKey = [](const Storage::Synchronization::SignalDeclarationView &view,
- const Storage::Synchronization::SignalDeclaration &value) {
- auto nameKey = Sqlite::compare(view.name, value.name);
- if (nameKey != 0)
- return nameKey;
-
- Utils::PathString valueSignature{createJson(value.parameters)};
-
- return Sqlite::compare(view.signature, valueSignature);
- };
-
- auto insert = [&](const Storage::Synchronization::SignalDeclaration &value) {
- Utils::PathString signature{createJson(value.parameters)};
-
- insertSignalDeclarationStatement.write(typeId, value.name, signature);
- };
-
- auto update = [&]([[maybe_unused]] const Storage::Synchronization::SignalDeclarationView &view,
- [[maybe_unused]] const Storage::Synchronization::SignalDeclaration &value) {
- return Sqlite::UpdateChange::No;
- };
-
- auto remove = [&](const Storage::Synchronization::SignalDeclarationView &view) {
- deleteSignalDeclarationStatement.write(view.id);
- };
-
- Sqlite::insertUpdateDelete(range, signalDeclarations, compareKey, insert, update, remove);
- }
+ Storage::Synchronization::SignalDeclarations &signalDeclarations);
static Utils::PathString createJson(
- const Storage::Synchronization::EnumeratorDeclarations &enumeratorDeclarations)
- {
- Utils::PathString json;
- json.append("{");
-
- Utils::SmallStringView comma{"\""};
-
- for (const auto &enumerator : enumeratorDeclarations) {
- json.append(comma);
- comma = ",\"";
- json.append(enumerator.name);
- if (enumerator.hasValue) {
- json.append("\":\"");
- json.append(Utils::SmallString::number(enumerator.value));
- json.append("\"");
- } else {
- json.append("\":null");
- }
- }
-
- json.append("}");
-
- return json;
- }
+ const Storage::Synchronization::EnumeratorDeclarations &enumeratorDeclarations);
void synchronizeEnumerationDeclarations(
- TypeId typeId, Storage::Synchronization::EnumerationDeclarations &enumerationDeclarations)
- {
- NanotraceHR::Tracer tracer{"synchronize enumeation declaration"_t, projectStorageCategory()};
-
- std::sort(enumerationDeclarations.begin(),
- enumerationDeclarations.end(),
- [](auto &&first, auto &&second) {
- return Sqlite::compare(first.name, second.name) < 0;
- });
-
- auto range = selectEnumerationDeclarationsForTypeIdStatement
- .template range<Storage::Synchronization::EnumerationDeclarationView>(typeId);
-
- auto compareKey = [](const Storage::Synchronization::EnumerationDeclarationView &view,
- const Storage::Synchronization::EnumerationDeclaration &value) {
- return Sqlite::compare(view.name, value.name);
- };
-
- auto insert = [&](const Storage::Synchronization::EnumerationDeclaration &value) {
- Utils::PathString signature{createJson(value.enumeratorDeclarations)};
-
- insertEnumerationDeclarationStatement.write(typeId, value.name, signature);
- };
-
- auto update = [&](const Storage::Synchronization::EnumerationDeclarationView &view,
- const Storage::Synchronization::EnumerationDeclaration &value) {
- Utils::PathString enumeratorDeclarations{createJson(value.enumeratorDeclarations)};
-
- if (enumeratorDeclarations == view.enumeratorDeclarations)
- return Sqlite::UpdateChange::No;
-
- updateEnumerationDeclarationStatement.write(view.id, enumeratorDeclarations);
-
- return Sqlite::UpdateChange::Update;
- };
-
- auto remove = [&](const Storage::Synchronization::EnumerationDeclarationView &view) {
- deleteEnumerationDeclarationStatement.write(view.id);
- };
-
- Sqlite::insertUpdateDelete(range, enumerationDeclarations, compareKey, insert, update, remove);
- }
+ TypeId typeId, Storage::Synchronization::EnumerationDeclarations &enumerationDeclarations);
void extractExportedTypes(TypeId typeId,
const Storage::Synchronization::Type &type,
- Storage::Synchronization::ExportedTypes &exportedTypes)
- {
- for (const auto &exportedType : type.exportedTypes)
- exportedTypes.emplace_back(exportedType.name,
- exportedType.version,
- typeId,
- exportedType.moduleId);
- }
-
- TypeId declareType(Storage::Synchronization::Type &type)
- {
- if (type.typeName.isEmpty()) {
- type.typeId = selectTypeIdBySourceIdStatement.template value<TypeId>(type.sourceId);
-
- return type.typeId;
- }
-
- type.typeId = insertTypeStatement.template value<TypeId>(type.sourceId, type.typeName);
+ Storage::Synchronization::ExportedTypes &exportedTypes);
- if (!type.typeId)
- type.typeId = selectTypeIdBySourceIdAndNameStatement.template value<TypeId>(type.sourceId,
- type.typeName);
-
- return type.typeId;
- }
+ TypeId declareType(Storage::Synchronization::Type &type);
void syncDeclarations(Storage::Synchronization::Type &type,
AliasPropertyDeclarations &insertedAliasPropertyDeclarations,
AliasPropertyDeclarations &updatedAliasPropertyDeclarations,
- PropertyDeclarationIds &propertyDeclarationIds)
- {
- NanotraceHR::Tracer tracer{"synchronize declaration per type"_t, projectStorageCategory()};
-
- if (type.changeLevel == Storage::Synchronization::ChangeLevel::Minimal)
- return;
-
- synchronizePropertyDeclarations(type.typeId,
- type.propertyDeclarations,
- type.sourceId,
- insertedAliasPropertyDeclarations,
- updatedAliasPropertyDeclarations,
- propertyDeclarationIds);
- synchronizeFunctionDeclarations(type.typeId, type.functionDeclarations);
- synchronizeSignalDeclarations(type.typeId, type.signalDeclarations);
- synchronizeEnumerationDeclarations(type.typeId, type.enumerationDeclarations);
- }
+ PropertyDeclarationIds &propertyDeclarationIds);
template<typename Relinkable, typename Ids, typename Compare>
void removeRelinkableEntries(std::vector<Relinkable> &relinkables, Ids &ids, Compare compare)
@@ -2381,23 +799,7 @@ private:
void syncDeclarations(Storage::Synchronization::Types &types,
AliasPropertyDeclarations &insertedAliasPropertyDeclarations,
AliasPropertyDeclarations &updatedAliasPropertyDeclarations,
- PropertyDeclarations &relinkablePropertyDeclarations)
- {
- NanotraceHR::Tracer tracer{"synchronize declaration"_t, projectStorageCategory()};
-
- PropertyDeclarationIds propertyDeclarationIds;
- propertyDeclarationIds.reserve(types.size() * 10);
-
- for (auto &&type : types)
- syncDeclarations(type,
- insertedAliasPropertyDeclarations,
- updatedAliasPropertyDeclarations,
- propertyDeclarationIds);
-
- removeRelinkableEntries(relinkablePropertyDeclarations,
- propertyDeclarationIds,
- PropertyCompare<PropertyDeclaration>{});
- }
+ PropertyDeclarations &relinkablePropertyDeclarations);
class TypeWithDefaultPropertyView
{
@@ -2407,240 +809,54 @@ private:
, defaultPropertyId{defaultPropertyId}
{}
+ template<typename String>
+ friend void convertToString(String &string, const TypeWithDefaultPropertyView &view)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("type id", view.typeId),
+ keyValue("property id", view.defaultPropertyId));
+
+ convertToString(string, dict);
+ }
+
TypeId typeId;
PropertyDeclarationId defaultPropertyId;
};
- void syncDefaultProperties(Storage::Synchronization::Types &types)
- {
- NanotraceHR::Tracer tracer{"synchronize default properties"_t, projectStorageCategory()};
-
- auto range = selectTypesWithDefaultPropertyStatement.template range<TypeWithDefaultPropertyView>();
-
- auto compareKey = [](const TypeWithDefaultPropertyView &view,
- const Storage::Synchronization::Type &value) {
- return view.typeId - value.typeId;
- };
-
- auto insert = [&](const Storage::Synchronization::Type &) {
-
- };
-
- auto update = [&](const TypeWithDefaultPropertyView &view,
- const Storage::Synchronization::Type &value) {
- PropertyDeclarationId valueDefaultPropertyId;
- if (value.defaultPropertyName.size())
- valueDefaultPropertyId = fetchPropertyDeclarationByTypeIdAndNameUngarded(
- value.typeId, value.defaultPropertyName)
- .propertyDeclarationId;
-
- if (compareInvalidAreTrue(valueDefaultPropertyId, view.defaultPropertyId))
- return Sqlite::UpdateChange::No;
-
- updateDefaultPropertyIdStatement.write(value.typeId, valueDefaultPropertyId);
-
- return Sqlite::UpdateChange::Update;
- };
+ void syncDefaultProperties(Storage::Synchronization::Types &types);
- auto remove = [&](const TypeWithDefaultPropertyView &) {};
+ void resetDefaultPropertiesIfChanged(Storage::Synchronization::Types &types);
- Sqlite::insertUpdateDelete(range, types, compareKey, insert, update, remove);
- }
-
- void resetDefaultPropertiesIfChanged(Storage::Synchronization::Types &types)
- {
- NanotraceHR::Tracer tracer{"reset changed default properties"_t, projectStorageCategory()};
-
- auto range = selectTypesWithDefaultPropertyStatement.template range<TypeWithDefaultPropertyView>();
-
- auto compareKey = [](const TypeWithDefaultPropertyView &view,
- const Storage::Synchronization::Type &value) {
- return view.typeId - value.typeId;
- };
-
- auto insert = [&](const Storage::Synchronization::Type &) {
-
- };
-
- auto update = [&](const TypeWithDefaultPropertyView &view,
- const Storage::Synchronization::Type &value) {
- PropertyDeclarationId valueDefaultPropertyId;
- if (value.defaultPropertyName.size()) {
- auto optionalValueDefaultPropertyId = fetchOptionalPropertyDeclarationByTypeIdAndNameUngarded(
- value.typeId, value.defaultPropertyName);
- if (optionalValueDefaultPropertyId)
- valueDefaultPropertyId = optionalValueDefaultPropertyId->propertyDeclarationId;
- }
-
- if (compareInvalidAreTrue(valueDefaultPropertyId, view.defaultPropertyId))
- return Sqlite::UpdateChange::No;
-
- updateDefaultPropertyIdStatement.write(value.typeId, Sqlite::NullValue{});
-
- return Sqlite::UpdateChange::Update;
- };
-
- auto remove = [&](const TypeWithDefaultPropertyView &) {};
-
- Sqlite::insertUpdateDelete(range, types, compareKey, insert, update, remove);
- }
-
- void checkForPrototypeChainCycle(TypeId typeId) const
- {
- auto callback = [=](TypeId currentTypeId) {
- if (typeId == currentTypeId)
- throw PrototypeChainCycle{};
- };
-
- selectTypeIdsForPrototypeChainIdStatement.readCallback(callback, typeId);
- }
-
- void checkForAliasChainCycle(PropertyDeclarationId propertyDeclarationId) const
- {
- auto callback = [=](PropertyDeclarationId currentPropertyDeclarationId) {
- if (propertyDeclarationId == currentPropertyDeclarationId)
- throw AliasChainCycle{};
- };
+ void checkForPrototypeChainCycle(TypeId typeId) const;
- selectPropertyDeclarationIdsForAliasChainStatement.readCallback(callback,
- propertyDeclarationId);
- }
+ void checkForAliasChainCycle(PropertyDeclarationId propertyDeclarationId) const;
std::pair<TypeId, ImportedTypeNameId> fetchImportedTypeNameIdAndTypeId(
- const Storage::Synchronization::ImportedTypeName &typeName, SourceId sourceId)
- {
- TypeId typeId;
- ImportedTypeNameId typeNameId;
- if (!std::visit([](auto &&typeName_) -> bool { return typeName_.name.isEmpty(); }, typeName)) {
- typeNameId = fetchImportedTypeNameId(typeName, sourceId);
-
- typeId = fetchTypeId(typeNameId);
-
- if (!typeId)
- throw TypeNameDoesNotExists{fetchImportedTypeName(typeNameId)};
- }
-
- return {typeId, typeNameId};
- }
-
- void syncPrototypeAndExtension(Storage::Synchronization::Type &type, TypeIds &typeIds)
- {
- if (type.changeLevel == Storage::Synchronization::ChangeLevel::Minimal)
- return;
+ const Storage::Synchronization::ImportedTypeName &typeName, SourceId sourceId);
- auto [prototypeId, prototypeTypeNameId] = fetchImportedTypeNameIdAndTypeId(type.prototype,
- type.sourceId);
- auto [extensionId, extensionTypeNameId] = fetchImportedTypeNameIdAndTypeId(type.extension,
- type.sourceId);
-
- updatePrototypeAndExtensionStatement.write(type.typeId,
- prototypeId,
- prototypeTypeNameId,
- extensionId,
- extensionTypeNameId);
-
- if (prototypeId || extensionId)
- checkForPrototypeChainCycle(type.typeId);
-
- typeIds.push_back(type.typeId);
- }
+ void syncPrototypeAndExtension(Storage::Synchronization::Type &type, TypeIds &typeIds);
void syncPrototypesAndExtensions(Storage::Synchronization::Types &types,
Prototypes &relinkablePrototypes,
- Prototypes &relinkableExtensions)
- {
- NanotraceHR::Tracer tracer{"synchronize prototypes"_t, projectStorageCategory()};
+ Prototypes &relinkableExtensions);
- TypeIds typeIds;
- typeIds.reserve(types.size());
-
- for (auto &type : types)
- syncPrototypeAndExtension(type, typeIds);
-
- removeRelinkableEntries(relinkablePrototypes, typeIds, TypeCompare<Prototype>{});
- removeRelinkableEntries(relinkableExtensions, typeIds, TypeCompare<Prototype>{});
- }
-
- ImportId fetchImportId(SourceId sourceId, const Storage::Import &import) const
- {
- if (import.version) {
- return selectImportIdBySourceIdAndModuleIdAndVersionStatement.template value<ImportId>(
- sourceId, import.moduleId, import.version.major.value, import.version.minor.value);
- }
-
- if (import.version.major) {
- return selectImportIdBySourceIdAndModuleIdAndMajorVersionStatement
- .template value<ImportId>(sourceId, import.moduleId, import.version.major.value);
- }
-
- return selectImportIdBySourceIdAndModuleIdStatement.template value<ImportId>(sourceId,
- import.moduleId);
- }
+ ImportId fetchImportId(SourceId sourceId, const Storage::Import &import) const;
ImportedTypeNameId fetchImportedTypeNameId(const Storage::Synchronization::ImportedTypeName &name,
- SourceId sourceId)
- {
- struct Inspect
- {
- auto operator()(const Storage::Synchronization::ImportedType &importedType)
- {
- return storage.fetchImportedTypeNameId(Storage::Synchronization::TypeNameKind::Exported,
- sourceId,
- importedType.name);
- }
-
- auto operator()(const Storage::Synchronization::QualifiedImportedType &importedType)
- {
- ImportId importId = storage.fetchImportId(sourceId, importedType.import);
-
- return storage.fetchImportedTypeNameId(Storage::Synchronization::TypeNameKind::QualifiedExported,
- importId,
- importedType.name);
- }
-
- ProjectStorage &storage;
- SourceId sourceId;
- };
-
- return std::visit(Inspect{*this, sourceId}, name);
- }
+ SourceId sourceId);
template<typename Id>
ImportedTypeNameId fetchImportedTypeNameId(Storage::Synchronization::TypeNameKind kind,
Id id,
- Utils::SmallStringView typeName)
- {
- auto importedTypeNameId = selectImportedTypeNameIdStatement
- .template value<ImportedTypeNameId>(kind, id, typeName);
-
- if (importedTypeNameId)
- return importedTypeNameId;
+ Utils::SmallStringView typeName);
- return insertImportedTypeNameIdStatement.template value<ImportedTypeNameId>(kind, id, typeName);
- }
-
- TypeId fetchTypeId(ImportedTypeNameId typeNameId) const
- {
- auto kind = selectKindFromImportedTypeNamesStatement
- .template value<Storage::Synchronization::TypeNameKind>(typeNameId);
-
- return fetchTypeId(typeNameId, kind);
- }
+ TypeId fetchTypeId(ImportedTypeNameId typeNameId) const;
- Utils::SmallString fetchImportedTypeName(ImportedTypeNameId typeNameId) const
- {
- return selectNameFromImportedTypeNamesStatement.template value<Utils::SmallString>(typeNameId);
- }
+ Utils::SmallString fetchImportedTypeName(ImportedTypeNameId typeNameId) const;
- TypeId fetchTypeId(ImportedTypeNameId typeNameId, Storage::Synchronization::TypeNameKind kind) const
- {
- if (kind == Storage::Synchronization::TypeNameKind::QualifiedExported) {
- return selectTypeIdForQualifiedImportedTypeNameNamesStatement.template value<TypeId>(
- typeNameId);
- }
-
- return selectTypeIdForImportedTypeNameNamesStatement.template value<TypeId>(typeNameId);
- }
+ TypeId fetchTypeId(ImportedTypeNameId typeNameId,
+ Storage::Synchronization::TypeNameKind kind) const;
class FetchPropertyDeclarationResult
{
@@ -2653,1303 +869,64 @@ private:
, propertyTraits{propertyTraits}
{}
+ template<typename String>
+ friend void convertToString(String &string, const FetchPropertyDeclarationResult &result)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("property type id", result.propertyTypeId),
+ keyValue("property declaration id", result.propertyDeclarationId),
+ keyValue("property traits", result.propertyTraits));
+
+ convertToString(string, dict);
+ }
+
public:
TypeId propertyTypeId;
PropertyDeclarationId propertyDeclarationId;
Storage::PropertyDeclarationTraits propertyTraits;
};
- auto fetchOptionalPropertyDeclarationByTypeIdAndNameUngarded(TypeId typeId,
- Utils::SmallStringView name)
- {
- return selectPropertyDeclarationByTypeIdAndNameStatement
- .template optionalValue<FetchPropertyDeclarationResult>(typeId, name);
- }
+ std::optional<FetchPropertyDeclarationResult> fetchOptionalPropertyDeclarationByTypeIdAndNameUngarded(
+ TypeId typeId, Utils::SmallStringView name);
FetchPropertyDeclarationResult fetchPropertyDeclarationByTypeIdAndNameUngarded(
- TypeId typeId, Utils::SmallStringView name)
- {
- auto propertyDeclaration = fetchOptionalPropertyDeclarationByTypeIdAndNameUngarded(typeId,
- name);
-
- if (propertyDeclaration)
- return *propertyDeclaration;
-
- throw PropertyNameDoesNotExists{};
- }
+ TypeId typeId, Utils::SmallStringView name);
PropertyDeclarationId fetchPropertyDeclarationIdByTypeIdAndNameUngarded(TypeId typeId,
- Utils::SmallStringView name)
- {
- auto propertyDeclarationId = selectPropertyDeclarationIdByTypeIdAndNameStatement
- .template value<PropertyDeclarationId>(typeId, name);
-
- if (propertyDeclarationId)
- return propertyDeclarationId;
-
- throw PropertyNameDoesNotExists{};
- }
-
- SourceContextId readSourceContextId(Utils::SmallStringView sourceContextPath)
- {
- return selectSourceContextIdFromSourceContextsBySourceContextPathStatement
- .template value<SourceContextId>(sourceContextPath);
- }
-
- SourceContextId writeSourceContextId(Utils::SmallStringView sourceContextPath)
- {
- insertIntoSourceContextsStatement.write(sourceContextPath);
-
- return SourceContextId::create(database.lastInsertedRowId());
- }
-
- SourceId writeSourceId(SourceContextId sourceContextId, Utils::SmallStringView sourceName)
- {
- insertIntoSourcesStatement.write(sourceContextId, sourceName);
-
- return SourceId::create(database.lastInsertedRowId());
- }
-
- SourceId readSourceId(SourceContextId sourceContextId, Utils::SmallStringView sourceName)
- {
- return selectSourceIdFromSourcesBySourceContextIdAndSourceNameStatement
- .template value<SourceId>(sourceContextId, sourceName);
- }
-
- auto fetchExportedTypes(TypeId typeId)
- {
- return selectExportedTypesByTypeIdStatement
- .template values<Storage::Synchronization::ExportedType, 12>(typeId);
- }
-
- auto fetchPropertyDeclarations(TypeId typeId)
- {
- return selectPropertyDeclarationsByTypeIdStatement
- .template values<Storage::Synchronization::PropertyDeclaration, 24>(typeId);
- }
-
- auto fetchFunctionDeclarations(TypeId typeId)
- {
- Storage::Synchronization::FunctionDeclarations functionDeclarations;
-
- auto callback = [&](Utils::SmallStringView name,
- Utils::SmallStringView returnType,
- FunctionDeclarationId functionDeclarationId) {
- auto &functionDeclaration = functionDeclarations.emplace_back(name, returnType);
- functionDeclaration.parameters = selectFunctionParameterDeclarationsStatement
- .template values<Storage::Synchronization::ParameterDeclaration,
- 8>(functionDeclarationId);
- };
-
- selectFunctionDeclarationsForTypeIdWithoutSignatureStatement.readCallback(callback, typeId);
+ Utils::SmallStringView name);
- return functionDeclarations;
- }
-
- auto fetchSignalDeclarations(TypeId typeId)
- {
- Storage::Synchronization::SignalDeclarations signalDeclarations;
-
- auto callback = [&](Utils::SmallStringView name, SignalDeclarationId signalDeclarationId) {
- auto &signalDeclaration = signalDeclarations.emplace_back(name);
- signalDeclaration.parameters = selectSignalParameterDeclarationsStatement
- .template values<Storage::Synchronization::ParameterDeclaration,
- 8>(signalDeclarationId);
- };
-
- selectSignalDeclarationsForTypeIdWithoutSignatureStatement.readCallback(callback, typeId);
+ SourceContextId readSourceContextId(Utils::SmallStringView sourceContextPath);
- return signalDeclarations;
- }
-
- auto fetchEnumerationDeclarations(TypeId typeId)
- {
- Storage::Synchronization::EnumerationDeclarations enumerationDeclarations;
+ SourceContextId writeSourceContextId(Utils::SmallStringView sourceContextPath);
- auto callback = [&](Utils::SmallStringView name,
- EnumerationDeclarationId enumerationDeclarationId) {
- enumerationDeclarations.emplace_back(
- name,
- selectEnumeratorDeclarationStatement
- .template values<Storage::Synchronization::EnumeratorDeclaration, 8>(
- enumerationDeclarationId));
- };
+ SourceId writeSourceId(SourceContextId sourceContextId, Utils::SmallStringView sourceName);
- selectEnumerationDeclarationsForTypeIdWithoutEnumeratorDeclarationsStatement
- .readCallback(callback, typeId);
-
- return enumerationDeclarations;
- }
+ SourceId readSourceId(SourceContextId sourceContextId, Utils::SmallStringView sourceName);
- class Initializer
- {
- public:
- Initializer(Database &database, bool isInitialized)
- {
- if (!isInitialized) {
- auto moduleIdColumn = createModulesTable(database);
- createSourceContextsTable(database);
- createSourcesTable(database);
- createTypesAndePropertyDeclarationsTables(database, moduleIdColumn);
- createExportedTypeNamesTable(database, moduleIdColumn);
- createImportedTypeNamesTable(database);
- createEnumerationsTable(database);
- createFunctionsTable(database);
- createSignalsTable(database);
- createModuleExportedImportsTable(database, moduleIdColumn);
- createDocumentImportsTable(database, moduleIdColumn);
- createFileStatusesTable(database);
- createProjectDatasTable(database);
- createPropertyEditorPathsTable(database);
- createTypeAnnotionsTable(database);
- }
- database.setIsInitialized(true);
- }
+ Storage::Synchronization::ExportedTypes fetchExportedTypes(TypeId typeId);
- void createSourceContextsTable(Database &database)
- {
- Sqlite::Table table;
- table.setUseIfNotExists(true);
- table.setName("sourceContexts");
- table.addColumn("sourceContextId", Sqlite::ColumnType::Integer, {Sqlite::PrimaryKey{}});
- const Sqlite::Column &sourceContextPathColumn = table.addColumn("sourceContextPath");
+ Storage::Synchronization::PropertyDeclarations fetchPropertyDeclarations(TypeId typeId);
- table.addUniqueIndex({sourceContextPathColumn});
+ Storage::Synchronization::FunctionDeclarations fetchFunctionDeclarations(TypeId typeId);
- table.initialize(database);
- }
+ Storage::Synchronization::SignalDeclarations fetchSignalDeclarations(TypeId typeId);
- void createSourcesTable(Database &database)
- {
- Sqlite::StrictTable table;
- table.setUseIfNotExists(true);
- table.setName("sources");
- table.addColumn("sourceId", Sqlite::StrictColumnType::Integer, {Sqlite::PrimaryKey{}});
- const auto &sourceContextIdColumn = table.addColumn(
- "sourceContextId",
- Sqlite::StrictColumnType::Integer,
- {Sqlite::NotNull{},
- Sqlite::ForeignKey{"sourceContexts",
- "sourceContextId",
- Sqlite::ForeignKeyAction::NoAction,
- Sqlite::ForeignKeyAction::Cascade}});
- const auto &sourceNameColumn = table.addColumn("sourceName",
- Sqlite::StrictColumnType::Text);
- table.addUniqueIndex({sourceContextIdColumn, sourceNameColumn});
-
- table.initialize(database);
- }
+ Storage::Synchronization::EnumerationDeclarations fetchEnumerationDeclarations(TypeId typeId);
- void createTypesAndePropertyDeclarationsTables(
- Database &database, [[maybe_unused]] const Sqlite::StrictColumn &foreignModuleIdColumn)
- {
- Sqlite::StrictTable typesTable;
- typesTable.setUseIfNotExists(true);
- typesTable.setName("types");
- typesTable.addColumn("typeId", Sqlite::StrictColumnType::Integer, {Sqlite::PrimaryKey{}});
- auto &sourceIdColumn = typesTable.addColumn("sourceId", Sqlite::StrictColumnType::Integer);
- auto &typesNameColumn = typesTable.addColumn("name", Sqlite::StrictColumnType::Text);
- typesTable.addColumn("traits", Sqlite::StrictColumnType::Integer);
- auto &prototypeIdColumn = typesTable.addForeignKeyColumn("prototypeId",
- typesTable,
- Sqlite::ForeignKeyAction::NoAction,
- Sqlite::ForeignKeyAction::Restrict);
- typesTable.addColumn("prototypeNameId", Sqlite::StrictColumnType::Integer);
- auto &extensionIdColumn = typesTable.addForeignKeyColumn("extensionId",
- typesTable,
- Sqlite::ForeignKeyAction::NoAction,
- Sqlite::ForeignKeyAction::Restrict);
- typesTable.addColumn("extensionNameId", Sqlite::StrictColumnType::Integer);
- auto &defaultPropertyIdColumn = typesTable.addColumn("defaultPropertyId",
- Sqlite::StrictColumnType::Integer);
- typesTable.addColumn("annotationTraits", Sqlite::StrictColumnType::Integer);
- typesTable.addUniqueIndex({sourceIdColumn, typesNameColumn});
- typesTable.addIndex({defaultPropertyIdColumn});
- typesTable.addIndex({prototypeIdColumn});
- typesTable.addIndex({extensionIdColumn});
-
- typesTable.initialize(database);
-
- {
- Sqlite::StrictTable propertyDeclarationTable;
- propertyDeclarationTable.setUseIfNotExists(true);
- propertyDeclarationTable.setName("propertyDeclarations");
- propertyDeclarationTable.addColumn("propertyDeclarationId",
- Sqlite::StrictColumnType::Integer,
- {Sqlite::PrimaryKey{}});
- auto &typeIdColumn = propertyDeclarationTable.addColumn("typeId");
- auto &nameColumn = propertyDeclarationTable.addColumn("name");
- propertyDeclarationTable.addForeignKeyColumn("propertyTypeId",
- typesTable,
- Sqlite::ForeignKeyAction::NoAction,
- Sqlite::ForeignKeyAction::Restrict);
- propertyDeclarationTable.addColumn("propertyTraits",
- Sqlite::StrictColumnType::Integer);
- propertyDeclarationTable.addColumn("propertyImportedTypeNameId",
- Sqlite::StrictColumnType::Integer);
- auto &aliasPropertyDeclarationIdColumn = propertyDeclarationTable.addForeignKeyColumn(
- "aliasPropertyDeclarationId",
- propertyDeclarationTable,
- Sqlite::ForeignKeyAction::NoAction,
- Sqlite::ForeignKeyAction::Restrict);
- auto &aliasPropertyDeclarationTailIdColumn = propertyDeclarationTable.addForeignKeyColumn(
- "aliasPropertyDeclarationTailId",
- propertyDeclarationTable,
- Sqlite::ForeignKeyAction::NoAction,
- Sqlite::ForeignKeyAction::Restrict);
-
- propertyDeclarationTable.addUniqueIndex({typeIdColumn, nameColumn});
- propertyDeclarationTable.addIndex({aliasPropertyDeclarationIdColumn},
- "aliasPropertyDeclarationId IS NOT NULL");
- propertyDeclarationTable.addIndex({aliasPropertyDeclarationTailIdColumn},
- "aliasPropertyDeclarationTailId IS NOT NULL");
-
- propertyDeclarationTable.initialize(database);
- }
- }
+ class Initializer;
- void createExportedTypeNamesTable(Database &database,
- const Sqlite::StrictColumn &foreignModuleIdColumn)
- {
- Sqlite::StrictTable table;
- table.setUseIfNotExists(true);
- table.setName("exportedTypeNames");
- table.addColumn("exportedTypeNameId",
- Sqlite::StrictColumnType::Integer,
- {Sqlite::PrimaryKey{}});
- auto &moduleIdColumn = table.addForeignKeyColumn("moduleId",
- foreignModuleIdColumn,
- Sqlite::ForeignKeyAction::NoAction,
- Sqlite::ForeignKeyAction::NoAction);
- auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text);
- auto &typeIdColumn = table.addColumn("typeId", Sqlite::StrictColumnType::Integer);
- auto &majorVersionColumn = table.addColumn("majorVersion",
- Sqlite::StrictColumnType::Integer);
- auto &minorVersionColumn = table.addColumn("minorVersion",
- Sqlite::StrictColumnType::Integer);
-
- table.addUniqueIndex({moduleIdColumn, nameColumn},
- "majorVersion IS NULL AND minorVersion IS NULL");
- table.addUniqueIndex({moduleIdColumn, nameColumn, majorVersionColumn},
- "majorVersion IS NOT NULL AND minorVersion IS NULL");
- table.addUniqueIndex({moduleIdColumn, nameColumn, majorVersionColumn, minorVersionColumn},
- "majorVersion IS NOT NULL AND minorVersion IS NOT NULL");
-
- table.addIndex({typeIdColumn});
-
- table.initialize(database);
- }
-
- void createImportedTypeNamesTable(Database &database)
- {
- Sqlite::StrictTable table;
- table.setUseIfNotExists(true);
- table.setName("importedTypeNames");
- table.addColumn("importedTypeNameId",
- Sqlite::StrictColumnType::Integer,
- {Sqlite::PrimaryKey{}});
- auto &importOrSourceIdColumn = table.addColumn("importOrSourceId");
- auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text);
- auto &kindColumn = table.addColumn("kind", Sqlite::StrictColumnType::Integer);
-
- table.addUniqueIndex({kindColumn, importOrSourceIdColumn, nameColumn});
-
- table.initialize(database);
- }
-
- void createEnumerationsTable(Database &database)
- {
- Sqlite::StrictTable table;
- table.setUseIfNotExists(true);
- table.setName("enumerationDeclarations");
- table.addColumn("enumerationDeclarationId",
- Sqlite::StrictColumnType::Integer,
- {Sqlite::PrimaryKey{}});
- auto &typeIdColumn = table.addColumn("typeId", Sqlite::StrictColumnType::Integer);
- auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text);
- table.addColumn("enumeratorDeclarations", Sqlite::StrictColumnType::Text);
-
- table.addUniqueIndex({typeIdColumn, nameColumn});
-
- table.initialize(database);
- }
-
- void createFunctionsTable(Database &database)
- {
- Sqlite::StrictTable table;
- table.setUseIfNotExists(true);
- table.setName("functionDeclarations");
- table.addColumn("functionDeclarationId",
- Sqlite::StrictColumnType::Integer,
- {Sqlite::PrimaryKey{}});
- auto &typeIdColumn = table.addColumn("typeId", Sqlite::StrictColumnType::Integer);
- auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text);
- auto &signatureColumn = table.addColumn("signature", Sqlite::StrictColumnType::Text);
- table.addColumn("returnTypeName");
-
- table.addUniqueIndex({typeIdColumn, nameColumn, signatureColumn});
-
- table.initialize(database);
- }
-
- void createSignalsTable(Database &database)
- {
- Sqlite::StrictTable table;
- table.setUseIfNotExists(true);
- table.setName("signalDeclarations");
- table.addColumn("signalDeclarationId",
- Sqlite::StrictColumnType::Integer,
- {Sqlite::PrimaryKey{}});
- auto &typeIdColumn = table.addColumn("typeId", Sqlite::StrictColumnType::Integer);
- auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text);
- auto &signatureColumn = table.addColumn("signature", Sqlite::StrictColumnType::Text);
-
- table.addUniqueIndex({typeIdColumn, nameColumn, signatureColumn});
-
- table.initialize(database);
- }
-
- Sqlite::StrictColumn createModulesTable(Database &database)
- {
- Sqlite::StrictTable table;
- table.setUseIfNotExists(true);
- table.setName("modules");
- auto &modelIdColumn = table.addColumn("moduleId",
- Sqlite::StrictColumnType::Integer,
- {Sqlite::PrimaryKey{}});
- auto &nameColumn = table.addColumn("name", Sqlite::StrictColumnType::Text);
-
- table.addUniqueIndex({nameColumn});
-
- table.initialize(database);
-
- return std::move(modelIdColumn);
- }
-
- void createModuleExportedImportsTable(Database &database,
- const Sqlite::StrictColumn &foreignModuleIdColumn)
- {
- Sqlite::StrictTable table;
- table.setUseIfNotExists(true);
- table.setName("moduleExportedImports");
- table.addColumn("moduleExportedImportId",
- Sqlite::StrictColumnType::Integer,
- {Sqlite::PrimaryKey{}});
- auto &moduleIdColumn = table.addForeignKeyColumn("moduleId",
- foreignModuleIdColumn,
- Sqlite::ForeignKeyAction::NoAction,
- Sqlite::ForeignKeyAction::Cascade,
- Sqlite::Enforment::Immediate);
- auto &sourceIdColumn = table.addColumn("exportedModuleId",
- Sqlite::StrictColumnType::Integer);
- table.addColumn("isAutoVersion", Sqlite::StrictColumnType::Integer);
- table.addColumn("majorVersion", Sqlite::StrictColumnType::Integer);
- table.addColumn("minorVersion", Sqlite::StrictColumnType::Integer);
-
- table.addUniqueIndex({sourceIdColumn, moduleIdColumn});
-
- table.initialize(database);
- }
-
- void createDocumentImportsTable(Database &database,
- const Sqlite::StrictColumn &foreignModuleIdColumn)
- {
- Sqlite::StrictTable table;
- table.setUseIfNotExists(true);
- table.setName("documentImports");
- table.addColumn("importId", Sqlite::StrictColumnType::Integer, {Sqlite::PrimaryKey{}});
- auto &sourceIdColumn = table.addColumn("sourceId", Sqlite::StrictColumnType::Integer);
- auto &moduleIdColumn = table.addForeignKeyColumn("moduleId",
- foreignModuleIdColumn,
- Sqlite::ForeignKeyAction::NoAction,
- Sqlite::ForeignKeyAction::Cascade,
- Sqlite::Enforment::Immediate);
- auto &sourceModuleIdColumn = table.addForeignKeyColumn("sourceModuleId",
- foreignModuleIdColumn,
- Sqlite::ForeignKeyAction::NoAction,
- Sqlite::ForeignKeyAction::Cascade,
- Sqlite::Enforment::Immediate);
- auto &kindColumn = table.addColumn("kind", Sqlite::StrictColumnType::Integer);
- auto &majorVersionColumn = table.addColumn("majorVersion",
- Sqlite::StrictColumnType::Integer);
- auto &minorVersionColumn = table.addColumn("minorVersion",
- Sqlite::StrictColumnType::Integer);
- auto &parentImportIdColumn = table.addColumn("parentImportId",
- Sqlite::StrictColumnType::Integer);
-
- table.addUniqueIndex({sourceIdColumn,
- moduleIdColumn,
- kindColumn,
- sourceModuleIdColumn,
- parentImportIdColumn},
- "majorVersion IS NULL AND minorVersion IS NULL");
- table.addUniqueIndex({sourceIdColumn,
- moduleIdColumn,
- kindColumn,
- sourceModuleIdColumn,
- majorVersionColumn,
- parentImportIdColumn},
- "majorVersion IS NOT NULL AND minorVersion IS NULL");
- table.addUniqueIndex({sourceIdColumn,
- moduleIdColumn,
- kindColumn,
- sourceModuleIdColumn,
- majorVersionColumn,
- minorVersionColumn,
- parentImportIdColumn},
- "majorVersion IS NOT NULL AND minorVersion IS NOT NULL");
-
- table.initialize(database);
- }
-
- void createFileStatusesTable(Database &database)
- {
- Sqlite::StrictTable table;
- table.setUseIfNotExists(true);
- table.setName("fileStatuses");
- table.addColumn("sourceId",
- Sqlite::StrictColumnType::Integer,
- {Sqlite::PrimaryKey{},
- Sqlite::ForeignKey{"sources",
- "sourceId",
- Sqlite::ForeignKeyAction::NoAction,
- Sqlite::ForeignKeyAction::Cascade}});
- table.addColumn("size", Sqlite::StrictColumnType::Integer);
- table.addColumn("lastModified", Sqlite::StrictColumnType::Integer);
-
- table.initialize(database);
- }
-
- void createProjectDatasTable(Database &database)
- {
- Sqlite::StrictTable table;
- table.setUseIfNotExists(true);
- table.setUseWithoutRowId(true);
- table.setName("projectDatas");
- auto &projectSourceIdColumn = table.addColumn("projectSourceId",
- Sqlite::StrictColumnType::Integer);
- auto &sourceIdColumn = table.addColumn("sourceId", Sqlite::StrictColumnType::Integer);
- table.addColumn("moduleId", Sqlite::StrictColumnType::Integer);
- table.addColumn("fileType", Sqlite::StrictColumnType::Integer);
-
- table.addPrimaryKeyContraint({projectSourceIdColumn, sourceIdColumn});
- table.addUniqueIndex({sourceIdColumn});
-
- table.initialize(database);
- }
-
- void createPropertyEditorPathsTable(Database &database)
- {
- Sqlite::StrictTable table;
- table.setUseIfNotExists(true);
- table.setUseWithoutRowId(true);
- table.setName("propertyEditorPaths");
- table.addColumn("typeId", Sqlite::StrictColumnType::Integer, {Sqlite::PrimaryKey{}});
- table.addColumn("pathSourceId", Sqlite::StrictColumnType::Integer);
- auto &directoryIdColumn = table.addColumn("directoryId",
- Sqlite::StrictColumnType::Integer);
-
- table.addIndex({directoryIdColumn});
-
- table.initialize(database);
- }
-
- void createTypeAnnotionsTable(Database &database)
- {
- Sqlite::StrictTable table;
- table.setUseIfNotExists(true);
- table.setUseWithoutRowId(true);
- table.setName("typeAnnotations");
- auto &typeIdColumn = table.addColumn("typeId",
- Sqlite::StrictColumnType::Integer,
- {Sqlite::PrimaryKey{}});
- auto &sourceIdColumn = table.addColumn("sourceId", Sqlite::StrictColumnType::Integer);
- table.addColumn("iconPath", Sqlite::StrictColumnType::Text);
- table.addColumn("itemLibrary", Sqlite::StrictColumnType::Text);
- table.addColumn("hints", Sqlite::StrictColumnType::Text);
-
- table.addUniqueIndex({sourceIdColumn, typeIdColumn});
-
- table.initialize(database);
- }
- };
+ struct Statements;
public:
Database &database;
Sqlite::ExclusiveNonThrowingDestructorTransaction<Database> exclusiveTransaction;
- Initializer initializer;
+ std::unique_ptr<Initializer> initializer;
mutable ModuleCache moduleCache{ModuleStorageAdapter{*this}};
- Storage::Info::CommonTypeCache<ProjectStorageInterface> commonTypeCache_{*this};
+ Storage::Info::CommonTypeCache<ProjectStorageType> commonTypeCache_{*this};
QVarLengthArray<ProjectStorageObserver *, 24> observers;
- ReadWriteStatement<1, 2> insertTypeStatement{
- "INSERT OR IGNORE INTO types(sourceId, name) VALUES(?1, ?2) RETURNING typeId", database};
- WriteStatement<5> updatePrototypeAndExtensionStatement{
- "UPDATE types SET prototypeId=?2, prototypeNameId=?3, extensionId=?4, extensionNameId=?5 "
- "WHERE typeId=?1 AND (prototypeId IS NOT ?2 OR extensionId IS NOT ?3 AND prototypeId "
- "IS NOT ?4 OR extensionNameId IS NOT ?5)",
- database};
- mutable ReadStatement<1, 1> selectTypeIdByExportedNameStatement{
- "SELECT typeId FROM exportedTypeNames WHERE name=?1", database};
- mutable ReadStatement<1, 2> selectTypeIdByModuleIdAndExportedNameStatement{
- "SELECT typeId FROM exportedTypeNames "
- "WHERE moduleId=?1 AND name=?2 "
- "ORDER BY majorVersion DESC, minorVersion DESC "
- "LIMIT 1",
- database};
- mutable ReadStatement<1, 3> selectTypeIdByModuleIdAndExportedNameAndMajorVersionStatement{
- "SELECT typeId FROM exportedTypeNames "
- "WHERE moduleId=?1 AND name=?2 AND majorVersion=?3"
- "ORDER BY minorVersion DESC "
- "LIMIT 1",
- database};
- mutable ReadStatement<1, 4> selectTypeIdByModuleIdAndExportedNameAndVersionStatement{
- "SELECT typeId FROM exportedTypeNames "
- "WHERE moduleId=?1 AND name=?2 AND majorVersion=?3 AND minorVersion<=?4"
- "ORDER BY minorVersion DESC "
- "LIMIT 1",
- database};
- mutable ReadStatement<1, 2> selectPrototypeIdStatement{
- "WITH RECURSIVE "
- " all_prototype_and_extension(typeId, prototypeId) AS ("
- " SELECT typeId, prototypeId FROM types WHERE prototypeId IS NOT NULL"
- " UNION ALL "
- " SELECT typeId, extensionId FROM types WHERE extensionId IS NOT NULL),"
- " typeSelection(typeId) AS ("
- " VALUES(?1) "
- " UNION ALL "
- " SELECT prototypeId FROM all_prototype_and_extension JOIN typeSelection "
- " USING(typeId))"
- "SELECT typeId FROM typeSelection WHERE typeId=?2 LIMIT 1",
- database};
- mutable ReadStatement<1, 2> selectPropertyDeclarationIdByTypeIdAndNameStatement{
- "WITH RECURSIVE "
- " all_prototype_and_extension(typeId, prototypeId) AS ("
- " SELECT typeId, prototypeId FROM types WHERE prototypeId IS NOT NULL"
- " UNION ALL "
- " SELECT typeId, extensionId FROM types WHERE extensionId IS NOT NULL),"
- " typeSelection(typeId, level) AS ("
- " VALUES(?1, 0) "
- " UNION ALL "
- " SELECT prototypeId, typeSelection.level+1 FROM all_prototype_and_extension JOIN "
- " typeSelection USING(typeId)) "
- "SELECT propertyDeclarationId FROM propertyDeclarations JOIN typeSelection USING(typeId) "
- " WHERE name=?2 ORDER BY level LIMIT 1",
- database};
- mutable ReadStatement<3, 2> selectPropertyDeclarationByTypeIdAndNameStatement{
- "WITH RECURSIVE "
- " all_prototype_and_extension(typeId, prototypeId) AS ("
- " SELECT typeId, prototypeId FROM types WHERE prototypeId IS NOT NULL"
- " UNION ALL "
- " SELECT typeId, extensionId FROM types WHERE extensionId IS NOT NULL),"
- " typeSelection(typeId, level) AS ("
- " VALUES(?1, 0) "
- " UNION ALL "
- " SELECT prototypeId, typeSelection.level+1 FROM all_prototype_and_extension JOIN "
- " typeSelection USING(typeId))"
- "SELECT propertyTypeId, propertyDeclarationId, propertyTraits "
- " FROM propertyDeclarations JOIN typeSelection USING(typeId) "
- " WHERE name=?2 ORDER BY level LIMIT 1",
- database};
- mutable ReadStatement<1, 1> selectPrototypeIdsInOrderStatement{
- "WITH RECURSIVE "
- " all_prototype_and_extension(typeId, prototypeId) AS ("
- " SELECT typeId, prototypeId FROM types WHERE prototypeId IS NOT NULL"
- " UNION ALL "
- " SELECT typeId, extensionId FROM types WHERE extensionId IS NOT NULL),"
- " typeSelection(typeId, level) AS ("
- " VALUES(?1, 0) "
- " UNION ALL "
- " SELECT prototypeId, typeSelection.level+1 FROM all_prototype_and_extension JOIN "
- " typeSelection USING(typeId) WHERE prototypeId IS NOT NULL) "
- "SELECT typeId FROM typeSelection ORDER BY level DESC",
- database};
- mutable ReadStatement<1, 1> selectSourceContextIdFromSourceContextsBySourceContextPathStatement{
- "SELECT sourceContextId FROM sourceContexts WHERE sourceContextPath = ?", database};
- mutable ReadStatement<1, 1> selectSourceContextPathFromSourceContextsBySourceContextIdStatement{
- "SELECT sourceContextPath FROM sourceContexts WHERE sourceContextId = ?", database};
- mutable ReadStatement<2> selectAllSourceContextsStatement{
- "SELECT sourceContextPath, sourceContextId FROM sourceContexts", database};
- WriteStatement<1> insertIntoSourceContextsStatement{
- "INSERT INTO sourceContexts(sourceContextPath) VALUES (?)", database};
- mutable ReadStatement<1, 2> selectSourceIdFromSourcesBySourceContextIdAndSourceNameStatement{
- "SELECT sourceId FROM sources WHERE sourceContextId = ? AND sourceName = ?", database};
- mutable ReadStatement<2, 1> selectSourceNameAndSourceContextIdFromSourcesBySourceIdStatement{
- "SELECT sourceName, sourceContextId FROM sources WHERE sourceId = ?", database};
- mutable ReadStatement<1, 1> selectSourceContextIdFromSourcesBySourceIdStatement{
- "SELECT sourceContextId FROM sources WHERE sourceId = ?", database};
- WriteStatement<2> insertIntoSourcesStatement{
- "INSERT INTO sources(sourceContextId, sourceName) VALUES (?,?)", database};
- mutable ReadStatement<3> selectAllSourcesStatement{
- "SELECT sourceName, sourceContextId, sourceId FROM sources", database};
- mutable ReadStatement<8, 1> selectTypeByTypeIdStatement{
- "SELECT sourceId, t.name, t.typeId, prototypeId, extensionId, traits, annotationTraits, "
- "pd.name "
- "FROM types AS t LEFT JOIN propertyDeclarations AS pd ON "
- "defaultPropertyId=propertyDeclarationId "
- "WHERE t.typeId=?",
- database};
- mutable ReadStatement<4, 1> selectExportedTypesByTypeIdStatement{
- "SELECT moduleId, name, ifnull(majorVersion, -1), ifnull(minorVersion, -1) FROM "
- "exportedTypeNames WHERE typeId=?",
- database};
- mutable ReadStatement<4, 2> selectExportedTypesByTypeIdAndSourceIdStatement{
- "SELECT etn.moduleId, name, ifnull(etn.majorVersion, -1), ifnull(etn.minorVersion, -1) "
- "FROM exportedTypeNames AS etn JOIN documentImports USING(moduleId) WHERE typeId=?1 AND "
- "sourceId=?2",
- database};
- mutable ReadStatement<8> selectTypesStatement{
- "SELECT sourceId, t.name, t.typeId, prototypeId, extensionId, traits, annotationTraits, "
- "pd.name "
- "FROM types AS t LEFT JOIN propertyDeclarations AS pd ON "
- "defaultPropertyId=propertyDeclarationId",
- database};
- WriteStatement<2> updateTypeTraitStatement{"UPDATE types SET traits = ?2 WHERE typeId=?1",
- database};
- WriteStatement<2> updateTypeAnnotationTraitStatement{
- "UPDATE types SET annotationTraits = ?2 WHERE typeId=?1", database};
- ReadStatement<1, 2> selectNotUpdatedTypesInSourcesStatement{
- "SELECT DISTINCT typeId FROM types WHERE (sourceId IN carray(?1) AND typeId NOT IN "
- "carray(?2))",
- database};
- WriteStatement<1> deleteTypeNamesByTypeIdStatement{
- "DELETE FROM exportedTypeNames WHERE typeId=?", database};
- WriteStatement<1> deleteEnumerationDeclarationByTypeIdStatement{
- "DELETE FROM enumerationDeclarations WHERE typeId=?", database};
- WriteStatement<1> deletePropertyDeclarationByTypeIdStatement{
- "DELETE FROM propertyDeclarations WHERE typeId=?", database};
- WriteStatement<1> deleteFunctionDeclarationByTypeIdStatement{
- "DELETE FROM functionDeclarations WHERE typeId=?", database};
- WriteStatement<1> deleteSignalDeclarationByTypeIdStatement{
- "DELETE FROM signalDeclarations WHERE typeId=?", database};
- WriteStatement<1> deleteTypeStatement{"DELETE FROM types WHERE typeId=?", database};
- mutable ReadStatement<4, 1> selectPropertyDeclarationsByTypeIdStatement{
- "SELECT name, propertyTypeId, propertyTraits, (SELECT name FROM "
- "propertyDeclarations WHERE propertyDeclarationId=pd.aliasPropertyDeclarationId) FROM "
- "propertyDeclarations AS pd WHERE typeId=?",
- database};
- ReadStatement<6, 1> selectPropertyDeclarationsForTypeIdStatement{
- "SELECT name, propertyTraits, propertyTypeId, propertyImportedTypeNameId, "
- "propertyDeclarationId, aliasPropertyDeclarationId FROM propertyDeclarations "
- "WHERE typeId=? ORDER BY name",
- database};
- ReadWriteStatement<1, 5> insertPropertyDeclarationStatement{
- "INSERT INTO propertyDeclarations(typeId, name, propertyTypeId, propertyTraits, "
- "propertyImportedTypeNameId, aliasPropertyDeclarationId) VALUES(?1, ?2, ?3, ?4, ?5, NULL) "
- "RETURNING propertyDeclarationId",
- database};
- WriteStatement<4> updatePropertyDeclarationStatement{
- "UPDATE propertyDeclarations SET propertyTypeId=?2, propertyTraits=?3, "
- "propertyImportedTypeNameId=?4, aliasPropertyDeclarationId=NULL WHERE "
- "propertyDeclarationId=?1",
- database};
- WriteStatement<3> updatePropertyAliasDeclarationRecursivelyWithTypeAndTraitsStatement{
- "WITH RECURSIVE "
- " properties(aliasPropertyDeclarationId) AS ( "
- " SELECT propertyDeclarationId FROM propertyDeclarations WHERE "
- " aliasPropertyDeclarationId=?1 "
- " UNION ALL "
- " SELECT pd.propertyDeclarationId FROM "
- " propertyDeclarations AS pd JOIN properties USING(aliasPropertyDeclarationId)) "
- "UPDATE propertyDeclarations AS pd "
- "SET propertyTypeId=?2, propertyTraits=?3 "
- "FROM properties AS p "
- "WHERE pd.propertyDeclarationId=p.aliasPropertyDeclarationId",
- database};
- WriteStatement<1> updatePropertyAliasDeclarationRecursivelyStatement{
- "WITH RECURSIVE "
- " propertyValues(propertyTypeId, propertyTraits) AS ("
- " SELECT propertyTypeId, propertyTraits FROM propertyDeclarations "
- " WHERE propertyDeclarationId=?1), "
- " properties(aliasPropertyDeclarationId) AS ( "
- " SELECT propertyDeclarationId FROM propertyDeclarations WHERE "
- " aliasPropertyDeclarationId=?1 "
- " UNION ALL "
- " SELECT pd.propertyDeclarationId FROM "
- " propertyDeclarations AS pd JOIN properties USING(aliasPropertyDeclarationId)) "
- "UPDATE propertyDeclarations AS pd "
- "SET propertyTypeId=pv.propertyTypeId, propertyTraits=pv.propertyTraits "
- "FROM properties AS p, propertyValues AS pv "
- "WHERE pd.propertyDeclarationId=p.aliasPropertyDeclarationId",
- database};
- WriteStatement<1> deletePropertyDeclarationStatement{
- "DELETE FROM propertyDeclarations WHERE propertyDeclarationId=?", database};
- ReadStatement<3, 1> selectPropertyDeclarationsWithAliasForTypeIdStatement{
- "SELECT name, propertyDeclarationId, aliasPropertyDeclarationId FROM propertyDeclarations "
- "WHERE typeId=? AND aliasPropertyDeclarationId IS NOT NULL ORDER BY name",
- database};
- WriteStatement<5> updatePropertyDeclarationWithAliasAndTypeStatement{
- "UPDATE propertyDeclarations SET propertyTypeId=?2, propertyTraits=?3, "
- "propertyImportedTypeNameId=?4, aliasPropertyDeclarationId=?5 WHERE "
- "propertyDeclarationId=?1",
- database};
- ReadWriteStatement<1, 2> insertAliasPropertyDeclarationStatement{
- "INSERT INTO propertyDeclarations(typeId, name) VALUES(?1, ?2) RETURNING "
- "propertyDeclarationId",
- database};
- mutable ReadStatement<4, 1> selectFunctionDeclarationsForTypeIdStatement{
- "SELECT name, returnTypeName, signature, functionDeclarationId FROM "
- "functionDeclarations WHERE typeId=? ORDER BY name, signature",
- database};
- mutable ReadStatement<3, 1> selectFunctionDeclarationsForTypeIdWithoutSignatureStatement{
- "SELECT name, returnTypeName, functionDeclarationId FROM "
- "functionDeclarations WHERE typeId=? ORDER BY name",
- database};
- mutable ReadStatement<3, 1> selectFunctionParameterDeclarationsStatement{
- "SELECT json_extract(json_each.value, '$.n'), json_extract(json_each.value, '$.tn'), "
- "json_extract(json_each.value, '$.tr') FROM functionDeclarations, "
- "json_each(functionDeclarations.signature) WHERE functionDeclarationId=?",
- database};
- WriteStatement<4> insertFunctionDeclarationStatement{
- "INSERT INTO functionDeclarations(typeId, name, returnTypeName, signature) VALUES(?1, ?2, "
- "?3, ?4)",
- database};
- WriteStatement<2> updateFunctionDeclarationStatement{
- "UPDATE functionDeclarations SET returnTypeName=?2 WHERE functionDeclarationId=?1", database};
- WriteStatement<1> deleteFunctionDeclarationStatement{
- "DELETE FROM functionDeclarations WHERE functionDeclarationId=?", database};
- mutable ReadStatement<3, 1> selectSignalDeclarationsForTypeIdStatement{
- "SELECT name, signature, signalDeclarationId FROM signalDeclarations WHERE typeId=? ORDER "
- "BY name, signature",
- database};
- mutable ReadStatement<2, 1> selectSignalDeclarationsForTypeIdWithoutSignatureStatement{
- "SELECT name, signalDeclarationId FROM signalDeclarations WHERE typeId=? ORDER BY name",
- database};
- mutable ReadStatement<3, 1> selectSignalParameterDeclarationsStatement{
- "SELECT json_extract(json_each.value, '$.n'), json_extract(json_each.value, '$.tn'), "
- "json_extract(json_each.value, '$.tr') FROM signalDeclarations, "
- "json_each(signalDeclarations.signature) WHERE signalDeclarationId=?",
- database};
- WriteStatement<3> insertSignalDeclarationStatement{
- "INSERT INTO signalDeclarations(typeId, name, signature) VALUES(?1, ?2, ?3)", database};
- WriteStatement<2> updateSignalDeclarationStatement{
- "UPDATE signalDeclarations SET signature=?2 WHERE signalDeclarationId=?1", database};
- WriteStatement<1> deleteSignalDeclarationStatement{
- "DELETE FROM signalDeclarations WHERE signalDeclarationId=?", database};
- mutable ReadStatement<3, 1> selectEnumerationDeclarationsForTypeIdStatement{
- "SELECT name, enumeratorDeclarations, enumerationDeclarationId FROM "
- "enumerationDeclarations WHERE typeId=? ORDER BY name",
- database};
- mutable ReadStatement<2, 1> selectEnumerationDeclarationsForTypeIdWithoutEnumeratorDeclarationsStatement{
- "SELECT name, enumerationDeclarationId FROM enumerationDeclarations WHERE typeId=? ORDER "
- "BY name",
- database};
- mutable ReadStatement<3, 1> selectEnumeratorDeclarationStatement{
- "SELECT json_each.key, json_each.value, json_each.type!='null' FROM "
- "enumerationDeclarations, json_each(enumerationDeclarations.enumeratorDeclarations) WHERE "
- "enumerationDeclarationId=?",
- database};
- WriteStatement<3> insertEnumerationDeclarationStatement{
- "INSERT INTO enumerationDeclarations(typeId, name, enumeratorDeclarations) VALUES(?1, ?2, "
- "?3)",
- database};
- WriteStatement<2> updateEnumerationDeclarationStatement{
- "UPDATE enumerationDeclarations SET enumeratorDeclarations=?2 WHERE "
- "enumerationDeclarationId=?1",
- database};
- WriteStatement<1> deleteEnumerationDeclarationStatement{
- "DELETE FROM enumerationDeclarations WHERE enumerationDeclarationId=?", database};
- mutable ReadStatement<1, 1> selectModuleIdByNameStatement{
- "SELECT moduleId FROM modules WHERE name=? LIMIT 1", database};
- mutable ReadWriteStatement<1, 1> insertModuleNameStatement{
- "INSERT INTO modules(name) VALUES(?1) RETURNING moduleId", database};
- mutable ReadStatement<1, 1> selectModuleNameStatement{
- "SELECT name FROM modules WHERE moduleId =?1", database};
- mutable ReadStatement<2> selectAllModulesStatement{"SELECT name, moduleId FROM modules", database};
- mutable ReadStatement<1, 2> selectTypeIdBySourceIdAndNameStatement{
- "SELECT typeId FROM types WHERE sourceId=?1 and name=?2", database};
- mutable ReadStatement<1, 3> selectTypeIdByModuleIdsAndExportedNameStatement{
- "SELECT typeId FROM exportedTypeNames WHERE moduleId IN carray(?1, ?2, 'int32') AND "
- "name=?3",
- database};
- mutable ReadStatement<4> selectAllDocumentImportForSourceIdStatement{
- "SELECT moduleId, majorVersion, minorVersion, sourceId "
- "FROM documentImports ",
- database};
- mutable ReadStatement<5, 2> selectDocumentImportForSourceIdStatement{
- "SELECT importId, sourceId, moduleId, majorVersion, minorVersion "
- "FROM documentImports WHERE sourceId IN carray(?1) AND kind=?2 ORDER BY sourceId, "
- "moduleId, majorVersion, minorVersion",
- database};
- ReadWriteStatement<1, 5> insertDocumentImportWithoutVersionStatement{
- "INSERT INTO documentImports(sourceId, moduleId, sourceModuleId, kind, "
- "parentImportId) VALUES (?1, ?2, ?3, ?4, ?5) RETURNING importId",
- database};
- ReadWriteStatement<1, 6> insertDocumentImportWithMajorVersionStatement{
- "INSERT INTO documentImports(sourceId, moduleId, sourceModuleId, kind, majorVersion, "
- "parentImportId) VALUES (?1, ?2, ?3, ?4, ?5, ?6) RETURNING importId",
- database};
- ReadWriteStatement<1, 7> insertDocumentImportWithVersionStatement{
- "INSERT INTO documentImports(sourceId, moduleId, sourceModuleId, kind, majorVersion, "
- "minorVersion, parentImportId) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7) RETURNING "
- "importId",
- database};
- WriteStatement<1> deleteDocumentImportStatement{"DELETE FROM documentImports WHERE importId=?1",
- database};
- WriteStatement<2> deleteDocumentImportsWithParentImportIdStatement{
- "DELETE FROM documentImports WHERE sourceId=?1 AND parentImportId=?2", database};
- WriteStatement<1> deleteDocumentImportsWithSourceIdsStatement{
- "DELETE FROM documentImports WHERE sourceId IN carray(?1)", database};
- ReadStatement<1, 2> selectPropertyDeclarationIdPrototypeChainDownStatement{
- "WITH RECURSIVE "
- " all_prototype_and_extension(typeId, prototypeId) AS ("
- " SELECT typeId, prototypeId FROM types WHERE prototypeId IS NOT NULL"
- " UNION ALL "
- " SELECT typeId, extensionId FROM types WHERE extensionId IS NOT NULL),"
- " typeSelection(typeId, level) AS ("
- " SELECT prototypeId, 0 FROM types WHERE typeId=?1 AND prototypeId IS NOT NULL"
- " UNION ALL "
- " SELECT prototypeId, typeSelection.level+1 FROM all_prototype_and_extension JOIN "
- " typeSelection USING(typeId))"
- "SELECT propertyDeclarationId FROM typeSelection JOIN propertyDeclarations "
- " USING(typeId) WHERE name=?2 ORDER BY level LIMIT 1",
- database};
- WriteStatement<2> updateAliasIdPropertyDeclarationStatement{
- "UPDATE propertyDeclarations SET aliasPropertyDeclarationId=?2 WHERE "
- "aliasPropertyDeclarationId=?1",
- database};
- WriteStatement<2> updateAliasPropertyDeclarationByAliasPropertyDeclarationIdStatement{
- "UPDATE propertyDeclarations SET propertyTypeId=new.propertyTypeId, "
- "propertyTraits=new.propertyTraits, aliasPropertyDeclarationId=?1 FROM (SELECT "
- "propertyTypeId, propertyTraits FROM propertyDeclarations WHERE propertyDeclarationId=?1) "
- "AS new WHERE aliasPropertyDeclarationId=?2",
- database};
- WriteStatement<1> updateAliasPropertyDeclarationToNullStatement{
- "UPDATE propertyDeclarations SET aliasPropertyDeclarationId=NULL, propertyTypeId=NULL, "
- "propertyTraits=NULL WHERE propertyDeclarationId=? AND (aliasPropertyDeclarationId IS NOT "
- "NULL OR propertyTypeId IS NOT NULL OR propertyTraits IS NOT NULL)",
- database};
- ReadStatement<5, 1> selectAliasPropertiesDeclarationForPropertiesWithTypeIdStatement{
- "SELECT alias.typeId, alias.propertyDeclarationId, alias.propertyImportedTypeNameId, "
- "alias.aliasPropertyDeclarationId, alias.aliasPropertyDeclarationTailId FROM "
- "propertyDeclarations AS alias JOIN propertyDeclarations AS target ON "
- "alias.aliasPropertyDeclarationId=target.propertyDeclarationId OR "
- "alias.aliasPropertyDeclarationTailId=target.propertyDeclarationId WHERE "
- "alias.propertyTypeId=?1 OR target.typeId=?1 OR alias.propertyImportedTypeNameId IN "
- "(SELECT importedTypeNameId FROM exportedTypeNames JOIN importedTypeNames USING(name) "
- "WHERE typeId=?1)",
- database};
- ReadStatement<3, 1> selectAliasPropertiesDeclarationForPropertiesWithAliasIdStatement{
- "WITH RECURSIVE "
- " properties(propertyDeclarationId, propertyImportedTypeNameId, typeId, "
- " aliasPropertyDeclarationId) AS ("
- " SELECT propertyDeclarationId, propertyImportedTypeNameId, typeId, "
- " aliasPropertyDeclarationId FROM propertyDeclarations WHERE "
- " aliasPropertyDeclarationId=?1"
- " UNION ALL "
- " SELECT pd.propertyDeclarationId, pd.propertyImportedTypeNameId, pd.typeId, "
- " pd.aliasPropertyDeclarationId FROM propertyDeclarations AS pd JOIN properties AS "
- " p ON pd.aliasPropertyDeclarationId=p.propertyDeclarationId)"
- "SELECT propertyDeclarationId, propertyImportedTypeNameId, aliasPropertyDeclarationId "
- " FROM properties",
- database};
- ReadWriteStatement<3, 1> updatesPropertyDeclarationPropertyTypeToNullStatement{
- "UPDATE propertyDeclarations SET propertyTypeId=NULL WHERE propertyTypeId=?1 AND "
- "aliasPropertyDeclarationId IS NULL RETURNING typeId, propertyDeclarationId, "
- "propertyImportedTypeNameId",
- database};
- mutable ReadStatement<1, 1> selectPropertyNameStatement{
- "SELECT name FROM propertyDeclarations WHERE propertyDeclarationId=?", database};
- WriteStatement<2> updatePropertyDeclarationTypeStatement{
- "UPDATE propertyDeclarations SET propertyTypeId=?2 WHERE propertyDeclarationId=?1", database};
- ReadWriteStatement<2, 1> updatePrototypeIdToNullStatement{
- "UPDATE types SET prototypeId=NULL WHERE prototypeId=?1 RETURNING "
- "typeId, prototypeNameId",
- database};
- ReadWriteStatement<2, 1> updateExtensionIdToNullStatement{
- "UPDATE types SET extensionId=NULL WHERE extensionId=?1 RETURNING "
- "typeId, extensionNameId",
- database};
- WriteStatement<2> updateTypePrototypeStatement{
- "UPDATE types SET prototypeId=?2 WHERE typeId=?1", database};
- WriteStatement<2> updateTypeExtensionStatement{
- "UPDATE types SET extensionId=?2 WHERE typeId=?1", database};
- mutable ReadStatement<1, 1> selectTypeIdsForPrototypeChainIdStatement{
- "WITH RECURSIVE "
- " all_prototype_and_extension(typeId, prototypeId) AS ("
- " SELECT typeId, prototypeId FROM types WHERE prototypeId IS NOT NULL"
- " UNION ALL "
- " SELECT typeId, extensionId FROM types WHERE extensionId IS NOT NULL),"
- " prototypes(typeId) AS ("
- " SELECT prototypeId FROM all_prototype_and_extension WHERE typeId=?"
- " UNION ALL "
- " SELECT prototypeId FROM all_prototype_and_extension JOIN "
- " prototypes USING(typeId)) "
- "SELECT typeId FROM prototypes",
- database};
- WriteStatement<3> updatePropertyDeclarationAliasIdAndTypeNameIdStatement{
- "UPDATE propertyDeclarations SET aliasPropertyDeclarationId=?2, "
- "propertyImportedTypeNameId=?3 WHERE propertyDeclarationId=?1 AND "
- "(aliasPropertyDeclarationId IS NOT ?2 OR propertyImportedTypeNameId IS NOT ?3)",
- database};
- WriteStatement<1> updatetPropertiesDeclarationValuesOfAliasStatement{
- "WITH RECURSIVE "
- " properties(propertyDeclarationId, propertyTypeId, propertyTraits) AS ( "
- " SELECT aliasPropertyDeclarationId, propertyTypeId, propertyTraits FROM "
- " propertyDeclarations WHERE propertyDeclarationId=?1 "
- " UNION ALL "
- " SELECT pd.aliasPropertyDeclarationId, pd.propertyTypeId, pd.propertyTraits FROM "
- " propertyDeclarations AS pd JOIN properties USING(propertyDeclarationId)) "
- "UPDATE propertyDeclarations AS pd SET propertyTypeId=p.propertyTypeId, "
- " propertyTraits=p.propertyTraits "
- "FROM properties AS p "
- "WHERE pd.propertyDeclarationId=?1 AND p.propertyDeclarationId IS NULL AND "
- " (pd.propertyTypeId IS NOT p.propertyTypeId OR pd.propertyTraits IS NOT "
- " p.propertyTraits)",
- database};
- WriteStatement<1> updatePropertyDeclarationAliasIdToNullStatement{
- "UPDATE propertyDeclarations SET aliasPropertyDeclarationId=NULL WHERE "
- "propertyDeclarationId=?1",
- database};
- mutable ReadStatement<1, 1> selectPropertyDeclarationIdsForAliasChainStatement{
- "WITH RECURSIVE "
- " properties(propertyDeclarationId) AS ( "
- " SELECT aliasPropertyDeclarationId FROM propertyDeclarations WHERE "
- " propertyDeclarationId=?1 "
- " UNION ALL "
- " SELECT aliasPropertyDeclarationId FROM propertyDeclarations JOIN properties "
- " USING(propertyDeclarationId)) "
- "SELECT propertyDeclarationId FROM properties",
- database};
- mutable ReadStatement<3> selectAllFileStatusesStatement{
- "SELECT sourceId, size, lastModified FROM fileStatuses ORDER BY sourceId", database};
- mutable ReadStatement<3, 1> selectFileStatusesForSourceIdsStatement{
- "SELECT sourceId, size, lastModified FROM fileStatuses WHERE sourceId IN carray(?1) ORDER "
- "BY sourceId",
- database};
- mutable ReadStatement<3, 1> selectFileStatusesForSourceIdStatement{
- "SELECT sourceId, size, lastModified FROM fileStatuses WHERE sourceId=?1 ORDER BY sourceId",
- database};
- WriteStatement<3> insertFileStatusStatement{
- "INSERT INTO fileStatuses(sourceId, size, lastModified) VALUES(?1, ?2, ?3)", database};
- WriteStatement<1> deleteFileStatusStatement{"DELETE FROM fileStatuses WHERE sourceId=?1",
- database};
- WriteStatement<3> updateFileStatusStatement{
- "UPDATE fileStatuses SET size=?2, lastModified=?3 WHERE sourceId=?1", database};
- ReadStatement<1, 1> selectTypeIdBySourceIdStatement{"SELECT typeId FROM types WHERE sourceId=?",
- database};
- mutable ReadStatement<1, 3> selectImportedTypeNameIdStatement{
- "SELECT importedTypeNameId FROM importedTypeNames WHERE kind=?1 AND importOrSourceId=?2 "
- "AND name=?3 LIMIT 1",
- database};
- mutable ReadWriteStatement<1, 3> insertImportedTypeNameIdStatement{
- "INSERT INTO importedTypeNames(kind, importOrSourceId, name) VALUES (?1, ?2, ?3) "
- "RETURNING importedTypeNameId",
- database};
- mutable ReadStatement<1, 2> selectImportIdBySourceIdAndModuleIdStatement{
- "SELECT importId FROM documentImports WHERE sourceId=?1 AND moduleId=?2 AND majorVersion "
- "IS NULL AND minorVersion IS NULL LIMIT 1",
- database};
- mutable ReadStatement<1, 3> selectImportIdBySourceIdAndModuleIdAndMajorVersionStatement{
- "SELECT importId FROM documentImports WHERE sourceId=?1 AND moduleId=?2 AND "
- "majorVersion=?3 AND minorVersion IS NULL LIMIT 1",
- database};
- mutable ReadStatement<1, 4> selectImportIdBySourceIdAndModuleIdAndVersionStatement{
- "SELECT importId FROM documentImports WHERE sourceId=?1 AND moduleId=?2 AND "
- "majorVersion=?3 AND minorVersion=?4 LIMIT 1",
- database};
- mutable ReadStatement<1, 1> selectKindFromImportedTypeNamesStatement{
- "SELECT kind FROM importedTypeNames WHERE importedTypeNameId=?1", database};
- mutable ReadStatement<1, 1> selectNameFromImportedTypeNamesStatement{
- "SELECT name FROM importedTypeNames WHERE importedTypeNameId=?1", database};
- mutable ReadStatement<1, 1> selectTypeIdForQualifiedImportedTypeNameNamesStatement{
- "SELECT typeId FROM importedTypeNames AS itn JOIN documentImports AS di ON "
- "importOrSourceId=di.importId JOIN documentImports AS di2 ON di.sourceId=di2.sourceId AND "
- "di.moduleId=di2.sourceModuleId "
- "JOIN exportedTypeNames AS etn ON di2.moduleId=etn.moduleId WHERE "
- "itn.kind=2 AND importedTypeNameId=?1 AND itn.name=etn.name AND "
- "(di.majorVersion IS NULL OR (di.majorVersion=etn.majorVersion AND (di.minorVersion IS "
- "NULL OR di.minorVersion>=etn.minorVersion))) ORDER BY etn.majorVersion DESC NULLS FIRST, "
- "etn.minorVersion DESC NULLS FIRST LIMIT 1",
- database};
- mutable ReadStatement<1, 1> selectTypeIdForImportedTypeNameNamesStatement{
- "SELECT typeId FROM importedTypeNames AS itn JOIN documentImports AS di ON "
- "importOrSourceId=sourceId JOIN exportedTypeNames AS etn USING(moduleId) WHERE "
- "itn.kind=1 AND importedTypeNameId=?1 AND itn.name=etn.name AND "
- "(di.majorVersion IS NULL OR (di.majorVersion=etn.majorVersion AND (di.minorVersion IS "
- "NULL OR di.minorVersion>=etn.minorVersion))) ORDER BY di.kind, etn.majorVersion DESC "
- "NULLS FIRST, etn.minorVersion DESC NULLS FIRST LIMIT 1",
- database};
- WriteStatement<0> deleteAllSourcesStatement{"DELETE FROM sources", database};
- WriteStatement<0> deleteAllSourceContextsStatement{"DELETE FROM sourceContexts", database};
- mutable ReadStatement<6, 1> selectExportedTypesForSourceIdsStatement{
- "SELECT moduleId, name, ifnull(majorVersion, -1), ifnull(minorVersion, -1), typeId, "
- "exportedTypeNameId FROM exportedTypeNames WHERE typeId in carray(?1) ORDER BY moduleId, "
- "name, majorVersion, minorVersion",
- database};
- WriteStatement<5> insertExportedTypeNamesWithVersionStatement{
- "INSERT INTO exportedTypeNames(moduleId, name, majorVersion, minorVersion, typeId) "
- "VALUES(?1, ?2, ?3, ?4, ?5)",
- database};
- WriteStatement<4> insertExportedTypeNamesWithMajorVersionStatement{
- "INSERT INTO exportedTypeNames(moduleId, name, majorVersion, typeId) "
- "VALUES(?1, ?2, ?3, ?4)",
- database};
- WriteStatement<3> insertExportedTypeNamesWithoutVersionStatement{
- "INSERT INTO exportedTypeNames(moduleId, name, typeId) VALUES(?1, ?2, ?3)", database};
- WriteStatement<1> deleteExportedTypeNameStatement{
- "DELETE FROM exportedTypeNames WHERE exportedTypeNameId=?", database};
- WriteStatement<2> updateExportedTypeNameTypeIdStatement{
- "UPDATE exportedTypeNames SET typeId=?2 WHERE exportedTypeNameId=?1", database};
- mutable ReadStatement<4, 1> selectProjectDatasForSourceIdsStatement{
- "SELECT projectSourceId, sourceId, moduleId, fileType FROM projectDatas WHERE "
- "projectSourceId IN carray(?1) ORDER BY projectSourceId, sourceId",
- database};
- WriteStatement<4> insertProjectDataStatement{
- "INSERT INTO projectDatas(projectSourceId, sourceId, "
- "moduleId, fileType) VALUES(?1, ?2, ?3, ?4)",
- database};
- WriteStatement<2> deleteProjectDataStatement{
- "DELETE FROM projectDatas WHERE projectSourceId=?1 AND sourceId=?2", database};
- WriteStatement<4> updateProjectDataStatement{
- "UPDATE projectDatas SET moduleId=?3, fileType=?4 WHERE projectSourceId=?1 AND sourceId=?2",
- database};
- mutable ReadStatement<4, 1> selectProjectDatasForSourceIdStatement{
- "SELECT projectSourceId, sourceId, moduleId, fileType FROM projectDatas WHERE "
- "projectSourceId=?1",
- database};
- mutable ReadStatement<4, 1> selectProjectDataForSourceIdStatement{
- "SELECT projectSourceId, sourceId, moduleId, fileType FROM projectDatas WHERE "
- "sourceId=?1 LIMIT 1",
- database};
- mutable ReadStatement<1, 1> selectTypeIdsForSourceIdsStatement{
- "SELECT typeId FROM types WHERE sourceId IN carray(?1)", database};
- mutable ReadStatement<6, 1> selectModuleExportedImportsForSourceIdStatement{
- "SELECT moduleExportedImportId, moduleId, exportedModuleId, ifnull(majorVersion, -1), "
- "ifnull(minorVersion, -1), isAutoVersion FROM moduleExportedImports WHERE moduleId IN "
- "carray(?1) ORDER BY moduleId, exportedModuleId",
- database};
- WriteStatement<3> insertModuleExportedImportWithoutVersionStatement{
- "INSERT INTO moduleExportedImports(moduleId, exportedModuleId, isAutoVersion) "
- "VALUES (?1, ?2, ?3)",
- database};
- WriteStatement<4> insertModuleExportedImportWithMajorVersionStatement{
- "INSERT INTO moduleExportedImports(moduleId, exportedModuleId, isAutoVersion, "
- "majorVersion) VALUES (?1, ?2, ?3, ?4)",
- database};
- WriteStatement<5> insertModuleExportedImportWithVersionStatement{
- "INSERT INTO moduleExportedImports(moduleId, exportedModuleId, isAutoVersion, "
- "majorVersion, minorVersion) VALUES (?1, ?2, ?3, ?4, ?5)",
- database};
- WriteStatement<1> deleteModuleExportedImportStatement{
- "DELETE FROM moduleExportedImports WHERE moduleExportedImportId=?1", database};
- mutable ReadStatement<3, 3> selectModuleExportedImportsForModuleIdStatement{
- "WITH RECURSIVE "
- " imports(moduleId, majorVersion, minorVersion, moduleExportedImportId) AS ( "
- " SELECT exportedModuleId, "
- " iif(isAutoVersion=1, ?2, majorVersion), "
- " iif(isAutoVersion=1, ?3, minorVersion), "
- " moduleExportedImportId "
- " FROM moduleExportedImports WHERE moduleId=?1 "
- " UNION ALL "
- " SELECT exportedModuleId, "
- " iif(mei.isAutoVersion=1, i.majorVersion, mei.majorVersion), "
- " iif(mei.isAutoVersion=1, i.minorVersion, mei.minorVersion), "
- " mei.moduleExportedImportId "
- " FROM moduleExportedImports AS mei JOIN imports AS i USING(moduleId)) "
- "SELECT DISTINCT moduleId, ifnull(majorVersion, -1), ifnull(minorVersion, -1) "
- "FROM imports",
- database};
- mutable ReadStatement<1, 1> selectPropertyDeclarationIdsForTypeStatement{
- "WITH RECURSIVE "
- " all_prototype_and_extension(typeId, prototypeId) AS ("
- " SELECT typeId, prototypeId FROM types WHERE prototypeId IS NOT NULL"
- " UNION ALL "
- " SELECT typeId, extensionId FROM types WHERE extensionId IS NOT NULL),"
- " typeChain(typeId) AS ("
- " VALUES(?1)"
- " UNION ALL "
- " SELECT prototypeId FROM all_prototype_and_extension JOIN typeChain "
- " USING(typeId))"
- "SELECT propertyDeclarationId FROM typeChain JOIN propertyDeclarations "
- " USING(typeId) ORDER BY propertyDeclarationId",
- database};
- mutable ReadStatement<1, 1> selectLocalPropertyDeclarationIdsForTypeStatement{
- "SELECT propertyDeclarationId "
- "FROM propertyDeclarations "
- "WHERE typeId=? "
- "ORDER BY propertyDeclarationId",
- database};
- mutable ReadStatement<1, 2> selectPropertyDeclarationIdForTypeAndPropertyNameStatement{
- "WITH RECURSIVE "
- " all_prototype_and_extension(typeId, prototypeId) AS ("
- " SELECT typeId, prototypeId FROM types WHERE prototypeId IS NOT NULL"
- " UNION ALL "
- " SELECT typeId, extensionId FROM types WHERE extensionId IS NOT NULL),"
- " typeChain(typeId, level) AS ("
- " VALUES(?1, 0)"
- " UNION ALL "
- " SELECT prototypeId, typeChain.level + 1 FROM all_prototype_and_extension JOIN "
- " typeChain USING(typeId))"
- "SELECT propertyDeclarationId FROM typeChain JOIN propertyDeclarations "
- " USING(typeId) WHERE name=?2 ORDER BY level LIMIT 1",
- database};
- mutable ReadStatement<1, 2> selectLocalPropertyDeclarationIdForTypeAndPropertyNameStatement{
- "SELECT propertyDeclarationId "
- "FROM propertyDeclarations "
- "WHERE typeId=?1 AND name=?2 LIMIT 1",
- database};
- mutable ReadStatement<4, 1> selectPropertyDeclarationForPropertyDeclarationIdStatement{
- "SELECT typeId, name, propertyTraits, propertyTypeId "
- "FROM propertyDeclarations "
- "WHERE propertyDeclarationId=?1 LIMIT 1",
- database};
- mutable ReadStatement<1, 1> selectSignalDeclarationNamesForTypeStatement{
- "WITH RECURSIVE "
- " all_prototype_and_extension(typeId, prototypeId) AS ("
- " SELECT typeId, prototypeId FROM types WHERE prototypeId IS NOT NULL"
- " UNION ALL "
- " SELECT typeId, extensionId FROM types WHERE extensionId IS NOT NULL),"
- " typeChain(typeId) AS ("
- " VALUES(?1)"
- " UNION ALL "
- " SELECT prototypeId FROM all_prototype_and_extension JOIN typeChain "
- " USING(typeId)) "
- "SELECT name FROM typeChain JOIN signalDeclarations "
- " USING(typeId) ORDER BY name",
- database};
- mutable ReadStatement<1, 1> selectFuncionDeclarationNamesForTypeStatement{
- "WITH RECURSIVE "
- " all_prototype_and_extension(typeId, prototypeId) AS ("
- " SELECT typeId, prototypeId FROM types WHERE prototypeId IS NOT NULL"
- " UNION ALL "
- " SELECT typeId, extensionId FROM types WHERE extensionId IS NOT NULL),"
- " typeChain(typeId) AS ("
- " VALUES(?1)"
- " UNION ALL "
- " SELECT prototypeId FROM all_prototype_and_extension JOIN typeChain "
- " USING(typeId))"
- "SELECT name FROM typeChain JOIN functionDeclarations "
- " USING(typeId) ORDER BY name",
- database};
- mutable ReadStatement<2> selectTypesWithDefaultPropertyStatement{
- "SELECT typeId, defaultPropertyId FROM types ORDER BY typeId", database};
- WriteStatement<2> updateDefaultPropertyIdStatement{
- "UPDATE types SET defaultPropertyId=?2 WHERE typeId=?1", database};
- WriteStatement<1> updateDefaultPropertyIdToNullStatement{
- "UPDATE types SET defaultPropertyId=NULL WHERE defaultPropertyId=?1", database};
- mutable ReadStatement<4, 1> selectInfoTypeByTypeIdStatement{
- "SELECT defaultPropertyId, sourceId, traits, annotationTraits FROM types WHERE typeId=?",
- database};
- mutable ReadStatement<1, 1> selectPrototypeIdsForTypeIdInOrderStatement{
- "WITH RECURSIVE "
- " all_prototype_and_extension(typeId, prototypeId) AS ("
- " SELECT typeId, prototypeId FROM types WHERE prototypeId IS NOT NULL"
- " UNION ALL "
- " SELECT typeId, extensionId FROM types WHERE extensionId IS NOT NULL),"
- " prototypes(typeId, level) AS ("
- " SELECT prototypeId, 0 FROM all_prototype_and_extension WHERE typeId=?"
- " UNION ALL "
- " SELECT prototypeId, p.level+1 FROM all_prototype_and_extension JOIN "
- " prototypes AS p USING(typeId)) "
- "SELECT typeId FROM prototypes ORDER BY level",
- database};
- mutable ReadStatement<1, 1> selectPrototypeAndSelfIdsForTypeIdInOrderStatement{
- "WITH RECURSIVE "
- " all_prototype_and_extension(typeId, prototypeId) AS ("
- " SELECT typeId, prototypeId FROM types WHERE prototypeId IS NOT NULL"
- " UNION ALL "
- " SELECT typeId, extensionId FROM types WHERE extensionId IS NOT NULL),"
- " typeChain(typeId, level) AS ("
- " VALUES(?1, 0)"
- " UNION ALL "
- " SELECT prototypeId, tc.level+1 FROM all_prototype_and_extension JOIN "
- " typeChain AS tc USING(typeId)) "
- "SELECT typeId FROM typeChain ORDER BY level",
- database};
- mutable ReadStatement<1, 1> selectPrototypeIdsStatement{
- "WITH RECURSIVE "
- " all_prototype_and_extension(typeId, prototypeId) AS ("
- " SELECT typeId, prototypeId FROM types WHERE prototypeId IS NOT NULL"
- " UNION ALL "
- " SELECT typeId, extensionId FROM types WHERE extensionId IS NOT NULL),"
- " typeSelection(typeId) AS ("
- " SELECT prototypeId FROM all_prototype_and_extension WHERE typeId=?1 "
- " UNION ALL "
- " SELECT prototypeId FROM all_prototype_and_extension JOIN typeSelection "
- " USING(typeId))"
- "SELECT typeId FROM typeSelection",
- database};
- WriteStatement<2> upsertPropertyEditorPathIdStatement{
- "INSERT INTO propertyEditorPaths(typeId, pathSourceId) VALUES(?1, ?2) ON CONFLICT DO "
- "UPDATE SET pathSourceId=excluded.pathSourceId WHERE pathSourceId IS NOT "
- "excluded.pathSourceId",
- database};
- mutable ReadStatement<1, 1> selectPropertyEditorPathIdStatement{
- "SELECT pathSourceId FROM propertyEditorPaths WHERE typeId=?", database};
- mutable ReadStatement<3, 1> selectPropertyEditorPathsForForSourceIdsStatement{
- "SELECT typeId, pathSourceId, directoryId "
- "FROM propertyEditorPaths "
- "WHERE directoryId IN carray(?1) "
- "ORDER BY typeId",
- database};
- WriteStatement<3> insertPropertyEditorPathStatement{
- "INSERT INTO propertyEditorPaths(typeId, pathSourceId, directoryId) VALUES (?1, ?2, ?3)",
- database};
- WriteStatement<3> updatePropertyEditorPathsStatement{"UPDATE propertyEditorPaths "
- "SET pathSourceId=?2, directoryId=?3 "
- "WHERE typeId=?1",
- database};
- WriteStatement<1> deletePropertyEditorPathStatement{
- "DELETE FROM propertyEditorPaths WHERE typeId=?1", database};
- mutable ReadStatement<4, 1> selectTypeAnnotationsForSourceIdsStatement{
- "SELECT typeId, iconPath, itemLibrary, hints FROM typeAnnotations WHERE "
- "sourceId IN carray(?1) ORDER BY typeId",
- database};
- WriteStatement<5> insertTypeAnnotationStatement{
- "INSERT INTO typeAnnotations(typeId, sourceId, iconPath, itemLibrary, hints) VALUES(?1, "
- "?2, ?3, ?4, ?5)",
- database};
- WriteStatement<4> updateTypeAnnotationStatement{
- "UPDATE typeAnnotations SET iconPath=?2, itemLibrary=?3, hints=?4 WHERE typeId=?1", database};
- WriteStatement<1> deleteTypeAnnotationStatement{"DELETE FROM typeAnnotations WHERE typeId=?1",
- database};
- mutable ReadStatement<1, 1> selectTypeIconPathStatement{
- "SELECT iconPath FROM typeAnnotations WHERE typeId=?1", database};
- mutable ReadStatement<2, 1> selectTypeHintsStatement{
- "SELECT hints.key, hints.value "
- "FROM typeAnnotations, json_each(typeAnnotations.hints) AS hints "
- "WHERE typeId=?1",
- database};
- mutable ReadStatement<9> selectItemLibraryEntriesStatement{
- "SELECT typeId, i.value->>'$.name', i.value->>'$.iconPath', i.value->>'$.category', "
- " i.value->>'$.import', i.value->>'$.toolTip', i.value->>'$.properties', "
- " i.value->>'$.extraFilePaths', i.value->>'$.templatePath' "
- "FROM typeAnnotations, json_each(typeAnnotations.itemLibrary) AS i",
- database};
- mutable ReadStatement<9, 1> selectItemLibraryEntriesByTypeIdStatement{
- "SELECT typeId, i.value->>'$.name', i.value->>'$.iconPath', i.value->>'$.category', "
- " i.value->>'$.import', i.value->>'$.toolTip', i.value->>'$.properties', "
- " i.value->>'$.extraFilePaths', i.value->>'$.templatePath' "
- "FROM typeAnnotations, json_each(typeAnnotations.itemLibrary) AS i "
- "WHERE typeId=?1",
- database};
- mutable ReadStatement<9, 1> selectItemLibraryEntriesBySourceIdStatement{
- "SELECT typeId, i.value->>'$.name', i.value->>'$.iconPath', i.value->>'$.category', "
- " i.value->>'$.import', i.value->>'$.toolTip', i.value->>'$.properties', "
- " i.value->>'$.extraFilePaths', i.value->>'$.templatePath' "
- "FROM typeAnnotations, json_each(typeAnnotations.itemLibrary) AS i "
- "WHERE typeId IN (SELECT DISTINCT typeId "
- " FROM documentImports AS di JOIN exportedTypeNames USING(moduleId) "
- " WHERE di.sourceId=?)",
- database};
- mutable ReadStatement<3, 1> selectItemLibraryPropertiesStatement{
- "SELECT p.value->>0, p.value->>1, p.value->>2 FROM json_each(?1) AS p", database};
- mutable ReadStatement<1, 1> selectItemLibraryExtraFilePathsStatement{
- "SELECT p.value FROM json_each(?1) AS p", database};
- mutable ReadStatement<1, 1> selectTypeIdsByModuleIdStatement{
- "SELECT DISTINCT typeId FROM exportedTypeNames WHERE moduleId=?", database};
- mutable ReadStatement<1, 1> selectHeirTypeIdsStatement{
- "WITH RECURSIVE "
- " typeSelection(typeId) AS ("
- " SELECT typeId FROM types WHERE prototypeId=?1 OR extensionId=?1"
- " UNION ALL "
- " SELECT t.typeId "
- " FROM types AS t JOIN typeSelection AS ts "
- " WHERE prototypeId=ts.typeId OR extensionId=ts.typeId)"
- "SELECT typeId FROM typeSelection",
- database};
+ std::unique_ptr<Statements> s;
};
-extern template class ProjectStorage<Sqlite::Database>;
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.cpp b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.cpp
index efe9bc58f5..a5dc60c4fa 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.cpp
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.cpp
@@ -3,87 +3,186 @@
#include "projectstorageexceptions.h"
+#include <tracing/qmldesignertracing.h>
+
namespace QmlDesigner {
+using namespace NanotraceHR::Literals;
+using NanotraceHR::keyValue;
+
+namespace {
+auto &category()
+{
+ return ProjectStorageTracing::projectStorageCategory();
+}
+} // namespace
+
+NoSourcePathForInvalidSourceId::NoSourcePathForInvalidSourceId()
+{
+ category().threadEvent("NoSourcePathForInvalidSourceId"_t);
+}
+
const char *NoSourcePathForInvalidSourceId::what() const noexcept
{
return "You cannot get a file path for an invalid file path id!";
}
+NoSourceContextPathForInvalidSourceContextId::NoSourceContextPathForInvalidSourceContextId()
+{
+ category().threadEvent("NoSourceContextPathForInvalidSourceContextId"_t);
+}
+
const char *NoSourceContextPathForInvalidSourceContextId::what() const noexcept
{
return "You cannot get a directory path for an invalid directory path id!";
}
+SourceContextIdDoesNotExists::SourceContextIdDoesNotExists()
+{
+ category().threadEvent("SourceContextIdDoesNotExists"_t);
+}
+
const char *SourceContextIdDoesNotExists::what() const noexcept
{
return "The source context id does not exist in the database!";
}
+SourceIdDoesNotExists::SourceIdDoesNotExists()
+{
+ category().threadEvent("SourceIdDoesNotExists"_t);
+}
+
const char *SourceIdDoesNotExists::what() const noexcept
{
return "The source id does not exist in the database!";
}
+TypeHasInvalidSourceId::TypeHasInvalidSourceId()
+{
+ category().threadEvent("TypeHasInvalidSourceId"_t);
+}
+
const char *TypeHasInvalidSourceId::what() const noexcept
{
return "The source id is invalid!";
}
+ModuleDoesNotExists::ModuleDoesNotExists()
+{
+ category().threadEvent("ModuleDoesNotExists"_t);
+}
+
const char *ModuleDoesNotExists::what() const noexcept
{
return "The module does not exist!";
}
+ModuleAlreadyExists::ModuleAlreadyExists()
+{
+ category().threadEvent("ModuleAlreadyExists"_t);
+}
+
const char *ModuleAlreadyExists::what() const noexcept
{
return "The module does already exist!";
}
-TypeNameDoesNotExists::TypeNameDoesNotExists(std::string_view errorMessage)
- : ProjectStorageErrorWithMessage{"TypeNameDoesNotExists"sv, errorMessage}
-{}
+TypeNameDoesNotExists::TypeNameDoesNotExists(std::string_view typeName, SourceId sourceId)
+ : ProjectStorageErrorWithMessage{
+ "TypeNameDoesNotExists"sv,
+ Utils::SmallString::join(
+ {"type: ", typeName, ", source id: ", Utils::SmallString::number(sourceId.internalId())})}
+{
+ category().threadEvent("TypeNameDoesNotExists"_t,
+ keyValue("type name", typeName),
+ keyValue("source id", sourceId));
+}
+
+PropertyNameDoesNotExists::PropertyNameDoesNotExists()
+{
+ category().threadEvent("PropertyNameDoesNotExists"_t);
+}
const char *PropertyNameDoesNotExists::what() const noexcept
{
return "The property name does not exist!";
}
+PrototypeChainCycle::PrototypeChainCycle()
+{
+ category().threadEvent("PrototypeChainCycle"_t);
+}
+
const char *PrototypeChainCycle::what() const noexcept
{
return "There is a prototype chain cycle!";
}
+AliasChainCycle::AliasChainCycle()
+{
+ category().threadEvent("AliasChainCycle"_t);
+}
+
const char *AliasChainCycle::what() const noexcept
{
return "There is a prototype chain cycle!";
}
+CannotParseQmlTypesFile::CannotParseQmlTypesFile()
+{
+ category().threadEvent("CannotParseQmlTypesFile"_t);
+}
+
const char *CannotParseQmlTypesFile::what() const noexcept
{
return "Cannot parse qml types file!";
}
+CannotParseQmlDocumentFile::CannotParseQmlDocumentFile()
+{
+ category().threadEvent("CannotParseQmlDocumentFile"_t);
+}
+
const char *CannotParseQmlDocumentFile::what() const noexcept
{
return "Cannot parse qml types file!";
}
+ProjectDataHasInvalidProjectSourceId::ProjectDataHasInvalidProjectSourceId()
+{
+ category().threadEvent("ProjectDataHasInvalidProjectSourceId"_t);
+}
+
const char *ProjectDataHasInvalidProjectSourceId::what() const noexcept
{
return "The project source id is invalid!";
}
+ProjectDataHasInvalidSourceId::ProjectDataHasInvalidSourceId()
+{
+ category().threadEvent("ProjectDataHasInvalidSourceId"_t);
+}
+
const char *ProjectDataHasInvalidSourceId::what() const noexcept
{
return "The source id is invalid!";
}
+ProjectDataHasInvalidModuleId::ProjectDataHasInvalidModuleId()
+{
+ category().threadEvent("ProjectDataHasInvalidModuleId"_t);
+}
+
const char *ProjectDataHasInvalidModuleId::what() const noexcept
{
return "The module id is invalid!";
}
+FileStatusHasInvalidSourceId::FileStatusHasInvalidSourceId()
+{
+ category().threadEvent("FileStatusHasInvalidSourceId"_t);
+}
+
const char *FileStatusHasInvalidSourceId::what() const noexcept
{
return "The source id in file status is invalid!";
@@ -110,7 +209,14 @@ const char *ProjectStorageErrorWithMessage::what() const noexcept
ExportedTypeCannotBeInserted::ExportedTypeCannotBeInserted(std::string_view errorMessage)
: ProjectStorageErrorWithMessage{"ExportedTypeCannotBeInserted"sv, errorMessage}
-{}
+{
+ category().threadEvent("ExportedTypeCannotBeInserted"_t, keyValue("error message", errorMessage));
+}
+
+TypeAnnotationHasInvalidSourceId::TypeAnnotationHasInvalidSourceId()
+{
+ category().threadEvent("TypeAnnotationHasInvalidSourceId"_t);
+}
const char *TypeAnnotationHasInvalidSourceId::what() const noexcept
{
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.h
index 412dd4a9ff..d85f1f7f9e 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageexceptions.h
@@ -5,6 +5,8 @@
#include "../include/qmldesignercorelib_global.h"
+#include "projectstorageids.h"
+
#include <exception>
namespace QmlDesigner {
@@ -13,15 +15,19 @@ using namespace std::literals::string_view_literals;
class QMLDESIGNERCORE_EXPORT ProjectStorageError : public std::exception
{
+protected:
+ ProjectStorageError() = default;
+
public:
const char *what() const noexcept override;
};
class ProjectStorageErrorWithMessage : public ProjectStorageError
{
-public:
+protected:
ProjectStorageErrorWithMessage(std::string_view error, std::string_view errorMessage);
+public:
const char *what() const noexcept override;
public:
@@ -31,42 +37,49 @@ public:
class QMLDESIGNERCORE_EXPORT NoSourcePathForInvalidSourceId : public ProjectStorageError
{
public:
+ NoSourcePathForInvalidSourceId();
const char *what() const noexcept override;
};
class QMLDESIGNERCORE_EXPORT NoSourceContextPathForInvalidSourceContextId : public ProjectStorageError
{
public:
+ NoSourceContextPathForInvalidSourceContextId();
const char *what() const noexcept override;
};
class QMLDESIGNERCORE_EXPORT SourceContextIdDoesNotExists : public ProjectStorageError
{
public:
+ SourceContextIdDoesNotExists();
const char *what() const noexcept override;
};
class QMLDESIGNERCORE_EXPORT SourceIdDoesNotExists : public ProjectStorageError
{
public:
+ SourceIdDoesNotExists();
const char *what() const noexcept override;
};
class QMLDESIGNERCORE_EXPORT TypeHasInvalidSourceId : public ProjectStorageError
{
public:
+ TypeHasInvalidSourceId();
const char *what() const noexcept override;
};
class QMLDESIGNERCORE_EXPORT ModuleDoesNotExists : public ProjectStorageError
{
public:
+ ModuleDoesNotExists();
const char *what() const noexcept override;
};
class QMLDESIGNERCORE_EXPORT ModuleAlreadyExists : public ProjectStorageError
{
public:
+ ModuleAlreadyExists();
const char *what() const noexcept override;
};
@@ -79,66 +92,76 @@ public:
class QMLDESIGNERCORE_EXPORT TypeNameDoesNotExists : public ProjectStorageErrorWithMessage
{
public:
- TypeNameDoesNotExists(std::string_view errorMessage);
+ TypeNameDoesNotExists(std::string_view typeName, SourceId sourceId = SourceId{});
};
class QMLDESIGNERCORE_EXPORT PropertyNameDoesNotExists : public ProjectStorageError
{
public:
+ PropertyNameDoesNotExists();
const char *what() const noexcept override;
};
class QMLDESIGNERCORE_EXPORT PrototypeChainCycle : public ProjectStorageError
{
public:
+ PrototypeChainCycle();
const char *what() const noexcept override;
};
class QMLDESIGNERCORE_EXPORT AliasChainCycle : public ProjectStorageError
{
public:
+ AliasChainCycle();
const char *what() const noexcept override;
};
class QMLDESIGNERCORE_EXPORT CannotParseQmlTypesFile : public ProjectStorageError
{
public:
+ CannotParseQmlTypesFile();
const char *what() const noexcept override;
};
class QMLDESIGNERCORE_EXPORT CannotParseQmlDocumentFile : public ProjectStorageError
{
public:
+ CannotParseQmlDocumentFile();
const char *what() const noexcept override;
};
class QMLDESIGNERCORE_EXPORT ProjectDataHasInvalidProjectSourceId : public ProjectStorageError
{
public:
+ ProjectDataHasInvalidProjectSourceId();
const char *what() const noexcept override;
};
class QMLDESIGNERCORE_EXPORT ProjectDataHasInvalidSourceId : public ProjectStorageError
{
public:
+ ProjectDataHasInvalidSourceId();
const char *what() const noexcept override;
};
class QMLDESIGNERCORE_EXPORT ProjectDataHasInvalidModuleId : public ProjectStorageError
{
public:
+ ProjectDataHasInvalidModuleId();
const char *what() const noexcept override;
};
class QMLDESIGNERCORE_EXPORT FileStatusHasInvalidSourceId : public ProjectStorageError
{
public:
+ FileStatusHasInvalidSourceId();
const char *what() const noexcept override;
};
class QMLDESIGNERCORE_EXPORT TypeAnnotationHasInvalidSourceId : public ProjectStorageError
{
public:
+ TypeAnnotationHasInvalidSourceId();
const char *what() const noexcept override;
};
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragefwd.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragefwd.h
index b33c609509..cbb7d4265a 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragefwd.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragefwd.h
@@ -11,7 +11,6 @@ namespace QmlDesigner {
class ProjectStorageInterface;
class SourcePathCacheInterface;
-template<typename Database>
class ProjectStorage;
template<typename Type>
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinfotypes.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinfotypes.h
index 427c0ff8d6..9f0c134ed3 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinfotypes.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinfotypes.h
@@ -24,6 +24,20 @@ constexpr std::underlying_type_t<Enumeration> to_underlying(Enumeration enumerat
enum class FlagIs : unsigned int { False, Set, True };
+template<typename String>
+void convertToString(String &string, const FlagIs &flagIs)
+{
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+
+ if (flagIs == FlagIs::False)
+ convertToString(string, false);
+ else if (flagIs == FlagIs::True)
+ convertToString(string, true);
+ else
+ convertToString(string, "is set");
+}
+
} // namespace QmlDesigner
namespace QmlDesigner::Storage {
@@ -46,6 +60,18 @@ constexpr bool operator&(PropertyDeclarationTraits first, PropertyDeclarationTra
return static_cast<int>(first) & static_cast<int>(second);
}
+template<typename String>
+void convertToString(String &string, const PropertyDeclarationTraits &traits)
+{
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("is read only", traits & PropertyDeclarationTraits::IsReadOnly),
+ keyValue("is pointer", traits & PropertyDeclarationTraits::IsPointer),
+ keyValue("is list", traits & PropertyDeclarationTraits::IsList));
+
+ convertToString(string, dict);
+}
+
enum class TypeTraitsKind : unsigned int {
None,
Reference,
@@ -53,6 +79,25 @@ enum class TypeTraitsKind : unsigned int {
Sequence,
};
+template<typename String>
+void convertToString(String &string, const TypeTraitsKind &kind)
+{
+ switch (kind) {
+ case TypeTraitsKind::None:
+ convertToString(string, "None");
+ break;
+ case TypeTraitsKind::Reference:
+ convertToString(string, "Reference");
+ break;
+ case TypeTraitsKind::Value:
+ convertToString(string, "Value");
+ break;
+ case TypeTraitsKind::Sequence:
+ convertToString(string, "Sequence");
+ break;
+ }
+}
+
struct TypeTraits
{
constexpr TypeTraits()
@@ -100,6 +145,35 @@ struct TypeTraits
return first.type == second.type && first.annotation == second.annotation;
}
+ template<typename String>
+ friend void convertToString(String &string, const TypeTraits &typeTraits)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(
+ keyValue("kind", typeTraits.kind),
+ keyValue("is enum", typeTraits.isEnum),
+ keyValue("is file component", typeTraits.isFileComponent),
+ keyValue("is project component", typeTraits.isProjectComponent),
+ keyValue("is in project module", typeTraits.isInProjectModule),
+ keyValue("uses custom parser", typeTraits.usesCustomParser),
+ keyValue("can be container", typeTraits.canBeContainer),
+ keyValue("force clip", typeTraits.forceClip),
+ keyValue("does layout children", typeTraits.doesLayoutChildren),
+ keyValue("can be dropped in form editor", typeTraits.canBeDroppedInFormEditor),
+ keyValue("can be dropped in navigator", typeTraits.canBeDroppedInNavigator),
+ keyValue("can be dropped in view 3D", typeTraits.canBeDroppedInView3D),
+ keyValue("is movable", typeTraits.isMovable),
+ keyValue("is resizable", typeTraits.isResizable),
+ keyValue("has form editor item", typeTraits.hasFormEditorItem),
+ keyValue("is stacked container", typeTraits.isStackedContainer),
+ keyValue("takes over rendering of children", typeTraits.takesOverRenderingOfChildren),
+ keyValue("visible in navigator", typeTraits.visibleInNavigator),
+ keyValue("visible in library", typeTraits.visibleInLibrary));
+
+ convertToString(string, dict);
+ }
+
union {
struct
{
@@ -202,10 +276,22 @@ public:
explicit operator bool() const { return major && minor; }
+ template<typename String>
+ friend void convertToString(String &string, const Version &version)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("major version", version.major.value),
+ keyValue("minor version", version.minor.value));
+
+ convertToString(string, dict);
+ }
+
public:
VersionNumber major;
VersionNumber minor;
};
+
} // namespace QmlDesigner::Storage
namespace QmlDesigner::Storage::Info {
@@ -217,6 +303,17 @@ struct TypeHint
, expression{expression}
{}
+ template<typename String>
+ friend void convertToString(String &string, const TypeHint &typeHint)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", typeHint.name),
+ keyValue("expression", typeHint.expression));
+
+ convertToString(string, dict);
+ }
+
Utils::SmallString name;
Utils::PathString expression;
};
@@ -231,6 +328,18 @@ struct ItemLibraryProperty
, value{value}
{}
+ template<typename String>
+ friend void convertToString(String &string, const ItemLibraryProperty &property)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", property.name),
+ keyValue("type", property.type),
+ keyValue("value", property.value));
+
+ convertToString(string, dict);
+ }
+
Utils::SmallString name;
Utils::SmallString type;
Sqlite::Value value;
@@ -274,6 +383,24 @@ struct ItemLibraryEntry
, properties{std::move(properties)}
{}
+ template<typename String>
+ friend void convertToString(String &string, const ItemLibraryEntry &entry)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("type id", entry.typeId),
+ keyValue("name", entry.name),
+ keyValue("icon path", entry.iconPath),
+ keyValue("category", entry.category),
+ keyValue("import", entry.import),
+ keyValue("tool tip", entry.toolTip),
+ keyValue("template path", entry.templatePath),
+ keyValue("properties", entry.properties),
+ keyValue("extra file paths", entry.extraFilePaths));
+
+ convertToString(string, dict);
+ }
+
TypeId typeId;
Utils::SmallString name;
Utils::PathString iconPath;
@@ -321,6 +448,18 @@ public:
< std::tie(second.moduleId, second.name, second.version);
}
+ template<typename String>
+ friend void convertToString(String &string, const ExportedTypeName &exportedTypeName)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", exportedTypeName.name),
+ keyValue("version", exportedTypeName.version),
+ keyValue("module id", exportedTypeName.moduleId));
+
+ convertToString(string, dict);
+ }
+
public:
::Utils::SmallString name;
Storage::Version version;
@@ -342,6 +481,19 @@ public:
, propertyTypeId{propertyTypeId}
{}
+ template<typename String>
+ friend void convertToString(String &string, const PropertyDeclaration &propertyDeclaration)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("type id", propertyDeclaration.typeId),
+ keyValue("name", propertyDeclaration.name),
+ keyValue("traits", propertyDeclaration.traits),
+ keyValue("property type id", propertyDeclaration.propertyTypeId));
+
+ convertToString(string, dict);
+ }
+
TypeId typeId;
::Utils::SmallString name;
PropertyDeclarationTraits traits;
@@ -351,22 +503,26 @@ public:
class Type
{
public:
- Type(PropertyDeclarationId defaultPropertyId,
- SourceId sourceId,
- long long typeTraits,
- long long typeAnnotationTraits)
- : defaultPropertyId{defaultPropertyId}
- , sourceId{sourceId}
+ Type(SourceId sourceId, long long typeTraits, long long typeAnnotationTraits)
+ : sourceId{sourceId}
, traits{typeTraits, typeAnnotationTraits}
{}
- Type(PropertyDeclarationId defaultPropertyId, SourceId sourceId, TypeTraits traits)
- : defaultPropertyId{defaultPropertyId}
- , sourceId{sourceId}
+ Type(SourceId sourceId, TypeTraits traits)
+ : sourceId{sourceId}
, traits{traits}
{}
- PropertyDeclarationId defaultPropertyId;
+ template<typename String>
+ friend void convertToString(String &string, const Type &type)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("source id", type.sourceId), keyValue("traits", type.traits));
+
+ convertToString(string, dict);
+ }
+
SourceId sourceId;
TypeTraits traits;
};
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h
index 266c6ee7ca..971e635517 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageinterface.h
@@ -32,6 +32,7 @@ public:
virtual void removeObserver(ProjectStorageObserver *observer) = 0;
virtual ModuleId moduleId(::Utils::SmallStringView name) const = 0;
+ virtual Utils::SmallString moduleName(ModuleId moduleId) const = 0;
virtual std::optional<Storage::Info::PropertyDeclaration>
propertyDeclaration(PropertyDeclarationId propertyDeclarationId) const = 0;
virtual TypeId typeId(ModuleId moduleId,
@@ -54,7 +55,10 @@ public:
virtual PropertyDeclarationId propertyDeclarationId(TypeId typeId,
::Utils::SmallStringView propertyName) const
= 0;
+ virtual PropertyDeclarationId defaultPropertyDeclarationId(TypeId typeId) const = 0;
virtual std::optional<Storage::Info::Type> type(TypeId typeId) const = 0;
+ virtual SmallSourceIds<4> typeAnnotationSourceIds(SourceId directoryId) const = 0;
+ virtual SmallSourceIds<64> typeAnnotationDirectorySourceIds() const = 0;
virtual Utils::PathString typeIconPath(TypeId typeId) const = 0;
virtual Storage::Info::TypeHints typeHints(TypeId typeId) const = 0;
virtual Storage::Info::ItemLibraryEntries itemLibraryEntries(TypeId typeId) const = 0;
@@ -64,9 +68,9 @@ public:
virtual std::vector<::Utils::SmallString> functionDeclarationNames(TypeId typeId) const = 0;
virtual std::optional<::Utils::SmallString>
propertyName(PropertyDeclarationId propertyDeclarationId) const = 0;
- virtual TypeIds prototypeAndSelfIds(TypeId type) const = 0;
- virtual TypeIds prototypeIds(TypeId type) const = 0;
- virtual TypeIds heirIds(TypeId typeId) const = 0;
+ virtual SmallTypeIds<16> prototypeAndSelfIds(TypeId type) const = 0;
+ virtual SmallTypeIds<16> prototypeIds(TypeId type) const = 0;
+ virtual SmallTypeIds<64> heirIds(TypeId typeId) const = 0;
virtual bool isBasedOn(TypeId, TypeId) const = 0;
virtual bool isBasedOn(TypeId, TypeId, TypeId) const = 0;
virtual bool isBasedOn(TypeId, TypeId, TypeId, TypeId) const = 0;
@@ -80,7 +84,7 @@ public:
virtual std::optional<Storage::Synchronization::ProjectData> fetchProjectData(SourceId sourceId) const = 0;
virtual SourceId propertyEditorPathId(TypeId typeId) const = 0;
- virtual const Storage::Info::CommonTypeCache<ProjectStorageInterface> &commonTypeCache() const = 0;
+ virtual const Storage::Info::CommonTypeCache<ProjectStorageType> &commonTypeCache() const = 0;
template<const char *moduleName, const char *typeName>
TypeId commonTypeId() const
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragepathwatchertypes.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragepathwatchertypes.h
index a9185d91e8..04f11096bd 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragepathwatchertypes.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragepathwatchertypes.h
@@ -12,6 +12,28 @@ namespace QmlDesigner {
enum class SourceType : int { Qml, QmlUi, QmlTypes, QmlDir, Directory };
+template<typename String>
+void convertToString(String &string, SourceType sourceType)
+{
+ switch (sourceType) {
+ case SourceType::Qml:
+ convertToString(string, "Qml");
+ break;
+ case SourceType::QmlUi:
+ convertToString(string, "QmlUi");
+ break;
+ case SourceType::QmlTypes:
+ convertToString(string, "QmlTypes");
+ break;
+ case SourceType::QmlDir:
+ convertToString(string, "QmlDir");
+ break;
+ case SourceType::Directory:
+ convertToString(string, "Directory");
+ break;
+ }
+}
+
class ProjectChunkId
{
public:
@@ -46,6 +68,17 @@ public:
friend bool operator<(ProjectChunkId first, ProjectPartId second) { return first.id < second; }
friend bool operator<(ProjectPartId first, ProjectChunkId second) { return first < second.id; }
+
+ template<typename String>
+ friend void convertToString(String &string, const ProjectChunkId &id)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("project part id", id.id),
+ keyValue("source type", id.sourceType));
+
+ convertToString(string, dict);
+ }
};
using ProjectChunkIds = std::vector<ProjectChunkId>;
@@ -67,6 +100,16 @@ public:
return first.id == second.id && first.sourceIds == second.sourceIds;
}
+ template<typename String>
+ friend void convertToString(String &string, const IdPaths &idPaths)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("id", idPaths.id), keyValue("source ids", idPaths.sourceIds));
+
+ convertToString(string, dict);
+ }
+
public:
ProjectChunkId id;
SourceIds sourceIds;
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragetypes.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragetypes.h
index 18c3931249..8d810d94bd 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstoragetypes.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstoragetypes.h
@@ -7,6 +7,7 @@
#include "projectstorageids.h"
#include "projectstorageinfotypes.h"
+#include <nanotrace/nanotracehr.h>
#include <sqlite/sqlitevalue.h>
#include <utils/smallstring.h>
@@ -45,6 +46,17 @@ public:
< std::tie(second.sourceId, second.moduleId, second.version);
}
+ template<typename String>
+ friend void convertToString(String &string, const Import &import)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("module id", import.moduleId),
+ keyValue("source id", import.sourceId),
+ keyValue("version", import.version));
+ convertToString(string, dict);
+ }
+
public:
Storage::Version version;
ModuleId moduleId;
@@ -57,11 +69,50 @@ namespace Synchronization {
enum class TypeNameKind { Exported = 1, QualifiedExported = 2 };
+template<typename String>
+void convertToString(String &string, const TypeNameKind &kind)
+{
+ switch (kind) {
+ case TypeNameKind::Exported:
+ convertToString(string, "Exported");
+ break;
+ case TypeNameKind::QualifiedExported:
+ convertToString(string, "QualifiedExported");
+ break;
+ }
+}
+
enum class FileType : char { QmlTypes, QmlDocument };
+template<typename String>
+void convertToString(String &string, const FileType &type)
+{
+ switch (type) {
+ case FileType::QmlTypes:
+ convertToString(string, "QmlTypes");
+ break;
+ case FileType::QmlDocument:
+ convertToString(string, "QmlDocument");
+ break;
+ }
+}
+
enum class IsQualified : int { No, Yes };
-inline int operator-(IsQualified first, IsQualified second)
+template<typename String>
+void convertToString(String &string, const IsQualified &isQualified)
+{
+ switch (isQualified) {
+ case IsQualified::No:
+ convertToString(string, "No");
+ break;
+ case IsQualified::Yes:
+ convertToString(string, "Yes");
+ break;
+ }
+}
+
+inline int operator-(IsQualified first, const IsQualified &second)
{
return static_cast<int>(first) - static_cast<int>(second);
}
@@ -78,6 +129,25 @@ enum class ImportKind : char {
ModuleExportedModuleDependency
};
+template<typename String>
+void convertToString(String &string, const ImportKind &kind)
+{
+ switch (kind) {
+ case ImportKind::Import:
+ convertToString(string, "Import");
+ break;
+ case ImportKind::ModuleDependency:
+ convertToString(string, "ModuleDependency");
+ break;
+ case ImportKind::ModuleExportedImport:
+ convertToString(string, "ModuleExportedImport");
+ break;
+ case ImportKind::ModuleExportedModuleDependency:
+ convertToString(string, "ModuleExportedModuleDependency");
+ break;
+ }
+}
+
class ImportView
{
public:
@@ -97,6 +167,19 @@ public:
&& first.version == second.version;
}
+ template<typename String>
+ friend void convertToString(String &string, const ImportView &import)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("import id", import.importId),
+ keyValue("source id", import.sourceId),
+ keyValue("module id", import.moduleId),
+ keyValue("version", import.version));
+
+ convertToString(string, dict);
+ }
+
public:
ImportId importId;
SourceId sourceId;
@@ -106,6 +189,19 @@ public:
enum class IsAutoVersion : char { No, Yes };
+template<typename String>
+void convertToString(String &string, const IsAutoVersion &isAutoVersion)
+{
+ switch (isAutoVersion) {
+ case IsAutoVersion::No:
+ convertToString(string, "No");
+ break;
+ case IsAutoVersion::Yes:
+ convertToString(string, "Yes");
+ break;
+ }
+}
+
constexpr bool operator<(IsAutoVersion first, IsAutoVersion second)
{
return to_underlying(first) < to_underlying(second);
@@ -137,6 +233,19 @@ public:
< std::tie(second.moduleId, second.exportedModuleId, second.isAutoVersion, second.version);
}
+ template<typename String>
+ friend void convertToString(String &string, const ModuleExportedImport &import)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("module id", import.moduleId),
+ keyValue("exported module id", import.exportedModuleId),
+ keyValue("version", import.version),
+ keyValue("is auto version", import.isAutoVersion));
+
+ convertToString(string, dict);
+ }
+
public:
Storage::Version version;
ModuleId moduleId;
@@ -171,6 +280,20 @@ public:
&& first.version == second.version && first.isAutoVersion == second.isAutoVersion;
}
+ template<typename String>
+ friend void convertToString(String &string, const ModuleExportedImportView &import)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("module exported import id", import.moduleExportedImportId),
+ keyValue("module id", import.moduleId),
+ keyValue("exported module id", import.exportedModuleId),
+ keyValue("version", import.version),
+ keyValue("is auto version", import.isAutoVersion));
+
+ convertToString(string, dict);
+ }
+
public:
ModuleExportedImportId moduleExportedImportId;
Storage::Version version;
@@ -192,6 +315,16 @@ public:
return first.name == second.name;
}
+ template<typename String>
+ friend void convertToString(String &string, const ImportedType &importedType)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", importedType.name));
+
+ convertToString(string, dict);
+ }
+
public:
TypeNameString name;
};
@@ -210,6 +343,17 @@ public:
return first.name == second.name && first.import == second.import;
}
+ template<typename String>
+ friend void convertToString(String &string, const QualifiedImportedType &importedType)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", importedType.name),
+ keyValue("import", importedType.import));
+
+ convertToString(string, dict);
+ }
+
public:
TypeNameString name;
Import import;
@@ -264,6 +408,19 @@ public:
< std::tie(second.moduleId, second.name, second.version);
}
+ template<typename String>
+ friend void convertToString(String &string, const ExportedType &exportedType)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", exportedType.name),
+ keyValue("module id", exportedType.moduleId),
+ keyValue("type id", exportedType.typeId),
+ keyValue("version", exportedType.version));
+
+ convertToString(string, dict);
+ }
+
public:
::Utils::SmallString name;
Storage::Version version;
@@ -295,6 +452,20 @@ public:
, exportedTypeNameId{exportedTypeNameId}
{}
+ template<typename String>
+ friend void convertToString(String &string, const ExportedTypeView &exportedType)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", exportedType.name),
+ keyValue("module id", exportedType.moduleId),
+ keyValue("type id", exportedType.typeId),
+ keyValue("version", exportedType.version),
+ keyValue("version", exportedType.exportedTypeNameId));
+
+ convertToString(string, dict);
+ }
+
public:
::Utils::SmallStringView name;
Storage::Version version;
@@ -305,6 +476,43 @@ public:
using ImportedTypeName = std::variant<ImportedType, QualifiedImportedType>;
+template<typename String>
+void convertToString(String &string, const ImportedTypeName &typeName)
+{
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+
+ struct Dispatcher
+ {
+ static const QmlDesigner::Storage::Import &nullImport()
+ {
+ static QmlDesigner::Storage::Import import;
+
+ return import;
+ }
+
+ void operator()(const QmlDesigner::Storage::Synchronization::ImportedType &importedType) const
+ {
+ auto dict = dictonary(keyValue("name", importedType.name));
+
+ convertToString(string, dict);
+ }
+
+ void operator()(
+ const QmlDesigner::Storage::Synchronization::QualifiedImportedType &qualifiedImportedType) const
+ {
+ auto dict = dictonary(keyValue("name", qualifiedImportedType.name),
+ keyValue("import", qualifiedImportedType.import));
+
+ convertToString(string, dict);
+ }
+
+ String &string;
+ };
+
+ std::visit(Dispatcher{string}, typeName);
+}
+
class EnumeratorDeclaration
{
public:
@@ -325,6 +533,18 @@ public:
&& first.hasValue == second.hasValue;
}
+ template<typename String>
+ friend void convertToString(String &string, const EnumeratorDeclaration &enumeratorDeclaration)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", enumeratorDeclaration.name),
+ keyValue("value", enumeratorDeclaration.value),
+ keyValue("has value", enumeratorDeclaration.hasValue));
+
+ convertToString(string, dict);
+ }
+
public:
::Utils::SmallString name;
long long value = 0;
@@ -349,6 +569,18 @@ public:
&& first.enumeratorDeclarations == second.enumeratorDeclarations;
}
+ template<typename String>
+ friend void convertToString(String &string, const EnumerationDeclaration &enumerationDeclaration)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", enumerationDeclaration.name),
+ keyValue("enumerator declarations",
+ enumerationDeclaration.enumeratorDeclarations));
+
+ convertToString(string, dict);
+ }
+
public:
TypeNameString name;
EnumeratorDeclarations enumeratorDeclarations;
@@ -368,6 +600,20 @@ public:
, id{id}
{}
+ template<typename String>
+ friend void convertToString(String &string,
+ const EnumerationDeclarationView &enumerationDeclaration)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", enumerationDeclaration.name),
+ keyValue("enumerator declarations",
+ enumerationDeclaration.enumeratorDeclarations),
+ keyValue("id", enumerationDeclaration.id));
+
+ convertToString(string, dict);
+ }
+
public:
::Utils::SmallStringView name;
::Utils::SmallStringView enumeratorDeclarations;
@@ -392,6 +638,18 @@ public:
&& first.traits == second.traits;
}
+ template<typename String>
+ friend void convertToString(String &string, const ParameterDeclaration &parameterDeclaration)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", parameterDeclaration.name),
+ keyValue("type name", parameterDeclaration.typeName),
+ keyValue("traits", parameterDeclaration.traits));
+
+ convertToString(string, dict);
+ }
+
public:
::Utils::SmallString name;
TypeNameString typeName;
@@ -418,6 +676,17 @@ public:
return first.name == second.name && first.parameters == second.parameters;
}
+ template<typename String>
+ friend void convertToString(String &string, const SignalDeclaration &signalDeclaration)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", signalDeclaration.name),
+ keyValue("parameters", signalDeclaration.parameters));
+
+ convertToString(string, dict);
+ }
+
public:
::Utils::SmallString name;
ParameterDeclarations parameters;
@@ -437,6 +706,18 @@ public:
, id{id}
{}
+ template<typename String>
+ friend void convertToString(String &string, const SignalDeclarationView &signalDeclaration)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", signalDeclaration.name),
+ keyValue("signature", signalDeclaration.signature),
+ keyValue("id", signalDeclaration.id));
+
+ convertToString(string, dict);
+ }
+
public:
::Utils::SmallStringView name;
::Utils::SmallStringView signature;
@@ -467,6 +748,18 @@ public:
&& first.parameters == second.parameters;
}
+ template<typename String>
+ friend void convertToString(String &string, const FunctionDeclaration &functionDeclaration)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", functionDeclaration.name),
+ keyValue("return type name", functionDeclaration.returnTypeName),
+ keyValue("parameters", functionDeclaration.parameters));
+
+ convertToString(string, dict);
+ }
+
public:
::Utils::SmallString name;
TypeNameString returnTypeName;
@@ -489,6 +782,19 @@ public:
, id{id}
{}
+ template<typename String>
+ friend void convertToString(String &string, const FunctionDeclarationView &functionDeclaration)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", functionDeclaration.name),
+ keyValue("return type name", functionDeclaration.returnTypeName),
+ keyValue("signature", functionDeclaration.signature),
+ keyValue("id", functionDeclaration.id));
+
+ convertToString(string, dict);
+ }
+
public:
::Utils::SmallStringView name;
::Utils::SmallStringView returnTypeName;
@@ -498,6 +804,19 @@ public:
enum class PropertyKind { Property, Alias };
+template<typename String>
+void convertToString(String &string, const PropertyKind &kind)
+{
+ switch (kind) {
+ case PropertyKind::Property:
+ convertToString(string, "Property");
+ break;
+ case PropertyKind::Alias:
+ convertToString(string, "Alias");
+ break;
+ }
+}
+
class PropertyDeclaration
{
public:
@@ -567,6 +886,24 @@ public:
&& first.traits == second.traits && first.kind == second.kind;
}
+ template<typename String>
+ friend void convertToString(String &string, const PropertyDeclaration &propertyDeclaration)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", propertyDeclaration.name),
+ keyValue("type name", propertyDeclaration.typeName),
+ keyValue("alias property name", propertyDeclaration.aliasPropertyName),
+ keyValue("alias property name tail",
+ propertyDeclaration.aliasPropertyNameTail),
+ keyValue("traits", propertyDeclaration.traits),
+ keyValue("type id", propertyDeclaration.typeId),
+ keyValue("property type id", propertyDeclaration.propertyTypeId),
+ keyValue("kind", propertyDeclaration.kind));
+
+ convertToString(string, dict);
+ }
+
public:
::Utils::SmallString name;
ImportedTypeName typeName;
@@ -597,6 +934,21 @@ public:
, aliasId{aliasId}
{}
+ template<typename String>
+ friend void convertToString(String &string, const PropertyDeclarationView &propertyDeclaration)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("name", propertyDeclaration.name),
+ keyValue("traits", propertyDeclaration.traits),
+ keyValue("type id", propertyDeclaration.typeId),
+ keyValue("type name id", propertyDeclaration.typeNameId),
+ keyValue("id", propertyDeclaration.id),
+ keyValue("alias id", propertyDeclaration.aliasId));
+
+ convertToString(string, dict);
+ }
+
public:
::Utils::SmallStringView name;
PropertyDeclarationTraits traits = {};
@@ -608,6 +960,22 @@ public:
enum class ChangeLevel : char { Full, Minimal, ExcludeExportedTypes };
+template<typename String>
+void convertToString(String &string, const ChangeLevel &changeLevel)
+{
+ switch (changeLevel) {
+ case ChangeLevel::Full:
+ convertToString(string, "Full");
+ break;
+ case ChangeLevel::Minimal:
+ convertToString(string, "Minimal");
+ break;
+ case ChangeLevel::ExcludeExportedTypes:
+ convertToString(string, "ExcludeExportedTypes");
+ break;
+ }
+}
+
class Type
{
public:
@@ -717,6 +1085,27 @@ public:
&& first.sourceId == second.sourceId;
}
+ template<typename String>
+ friend void convertToString(String &string, const Type &type)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("type name", type.typeName),
+ keyValue("prototype", type.prototype),
+ keyValue("extension", type.extension),
+ keyValue("exported types", type.exportedTypes),
+ keyValue("property declarations", type.propertyDeclarations),
+ keyValue("function declarations", type.functionDeclarations),
+ keyValue("signal declarations", type.signalDeclarations),
+ keyValue("enumeration declarations", type.enumerationDeclarations),
+ keyValue("traits", type.traits),
+ keyValue("source id", type.sourceId),
+ keyValue("change level", type.changeLevel),
+ keyValue("default property name", type.defaultPropertyName));
+
+ convertToString(string, dict);
+ }
+
public:
TypeNameString typeName;
::Utils::SmallString defaultPropertyName;
@@ -747,6 +1136,20 @@ public:
, moduleId{moduleId}
{}
+ template<typename String>
+ friend void convertToString(String &string, const PropertyEditorQmlPath &propertyEditorQmlPath)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("type name", propertyEditorQmlPath.typeName),
+ keyValue("type id", propertyEditorQmlPath.typeId),
+ keyValue("path id", propertyEditorQmlPath.pathId),
+ keyValue("directory id", propertyEditorQmlPath.directoryId),
+ keyValue("module id", propertyEditorQmlPath.moduleId));
+
+ convertToString(string, dict);
+ }
+
public:
TypeNameString typeName;
TypeId typeId;
@@ -774,6 +1177,19 @@ public:
&& first.fileType == second.fileType;
}
+ template<typename String>
+ friend void convertToString(String &string, const ProjectData &projectData)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("project source id", projectData.projectSourceId),
+ keyValue("source id", projectData.sourceId),
+ keyValue("module id", projectData.moduleId),
+ keyValue("file type", projectData.fileType));
+
+ convertToString(string, dict);
+ }
+
public:
SourceId projectSourceId;
SourceId sourceId;
@@ -786,10 +1202,13 @@ using ProjectDatas = std::vector<ProjectData>;
class TypeAnnotation
{
public:
- TypeAnnotation(SourceId sourceId)
+ TypeAnnotation(SourceId sourceId, SourceId directorySourceId)
: sourceId{sourceId}
+ , directorySourceId{directorySourceId}
{}
+
TypeAnnotation(SourceId sourceId,
+ SourceId directorySourceId,
Utils::SmallStringView typeName,
ModuleId moduleId,
Utils::SmallStringView iconPath,
@@ -803,8 +1222,26 @@ public:
, sourceId{sourceId}
, moduleId{moduleId}
, traits{traits}
+ , directorySourceId{directorySourceId}
{}
+ template<typename String>
+ friend void convertToString(String &string, const TypeAnnotation &typeAnnotation)
+ {
+ using NanotraceHR::dictonary;
+ using NanotraceHR::keyValue;
+ auto dict = dictonary(keyValue("type name", typeAnnotation.typeName),
+ keyValue("icon path", typeAnnotation.iconPath),
+ keyValue("item library json", typeAnnotation.itemLibraryJson),
+ keyValue("hints json", typeAnnotation.hintsJson),
+ keyValue("type id", typeAnnotation.typeId),
+ keyValue("source id", typeAnnotation.sourceId),
+ keyValue("module id", typeAnnotation.moduleId),
+ keyValue("traits", typeAnnotation.traits));
+
+ convertToString(string, dict);
+ }
+
public:
TypeNameString typeName;
Utils::PathString iconPath;
@@ -814,6 +1251,7 @@ public:
SourceId sourceId;
ModuleId moduleId;
TypeTraits traits;
+ SourceId directorySourceId;
};
using TypeAnnotations = std::vector<TypeAnnotation>;
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp
index 62fcf310f6..761d6371ef 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp
@@ -11,6 +11,9 @@
#include "qmltypesparserinterface.h"
#include "sourcepath.h"
#include "sourcepathcache.h"
+#include "typeannotationreader.h"
+
+#include <tracing/qmldesignertracing.h>
#include <sqlitedatabase.h>
@@ -21,6 +24,26 @@
#include <functional>
namespace QmlDesigner {
+constexpr auto category = ProjectStorageTracing::projectStorageUpdaterCategory;
+using NanotraceHR::keyValue;
+using Tracer = ProjectStorageTracing::Category::TracerType;
+
+template<typename String>
+void convertToString(String &string, const ProjectStorageUpdater::FileState &state)
+{
+ switch (state) {
+ case ProjectStorageUpdater::FileState::Changed:
+ convertToString(string, "Changed");
+ break;
+ case ProjectStorageUpdater::FileState::NotChanged:
+ convertToString(string, "NotChanged");
+ break;
+ case ProjectStorageUpdater::FileState::NotExists:
+ convertToString(string, "NotExists");
+ break;
+ }
+}
+
namespace {
QStringList filterMultipleEntries(QStringList qmlTypes)
@@ -110,10 +133,15 @@ SourceIds filterNotUpdatedSourceIds(SourceIds updatedSourceIds, SourceIds notUpd
return filteredUpdatedSourceIds;
}
-void addSourceIds(SourceIds &sourceIds, const Storage::Synchronization::ProjectDatas &projectDatas)
+void addSourceIds(SourceIds &sourceIds,
+ const Storage::Synchronization::ProjectDatas &projectDatas,
+ TracerLiteral message,
+ Tracer &tracer)
{
- for (const auto &projectData : projectDatas)
+ for (const auto &projectData : projectDatas) {
+ tracer.tick(message, keyValue("source id", projectData.sourceId));
sourceIds.push_back(projectData.sourceId);
+ }
}
Storage::Version convertVersion(LanguageUtils::ComponentVersion version)
@@ -131,34 +159,71 @@ Storage::Synchronization::IsAutoVersion convertToIsAutoVersion(QmlDirParser::Imp
void addDependencies(Storage::Imports &dependencies,
SourceId sourceId,
const QList<QmlDirParser::Import> &qmldirDependencies,
- ProjectStorageInterface &projectStorage)
+ ProjectStorageInterface &projectStorage,
+ TracerLiteral message,
+ Tracer &tracer)
{
for (const QmlDirParser::Import &qmldirDependency : qmldirDependencies) {
ModuleId moduleId = projectStorage.moduleId(Utils::PathString{qmldirDependency.module}
+ "-cppnative");
- dependencies.emplace_back(moduleId, Storage::Version{}, sourceId);
+ auto &import = dependencies.emplace_back(moduleId, Storage::Version{}, sourceId);
+ tracer.tick(message, keyValue("import", import));
}
}
+void addModuleExportedImport(Storage::Synchronization::ModuleExportedImports &imports,
+ ModuleId moduleId,
+ ModuleId exportedModuleId,
+ Storage::Version version,
+ Storage::Synchronization::IsAutoVersion isAutoVersion,
+ std::string_view moduleName,
+ std::string_view exportedModuleName)
+{
+ NanotraceHR::Tracer tracer{"add module exported imports"_t,
+ category(),
+ keyValue("module id", moduleId),
+ keyValue("exported module id", exportedModuleId),
+ keyValue("version", version),
+ keyValue("is auto version", isAutoVersion),
+ keyValue("module name", moduleName),
+ keyValue("exported module name", exportedModuleName)};
+
+ imports.emplace_back(moduleId, exportedModuleId, version, isAutoVersion);
+}
+
void addModuleExportedImports(Storage::Synchronization::ModuleExportedImports &imports,
ModuleId moduleId,
ModuleId cppModuleId,
+ std::string_view moduleName,
+ std::string_view cppModuleName,
const QList<QmlDirParser::Import> &qmldirImports,
ProjectStorageInterface &projectStorage)
{
- for (const QmlDirParser::Import &qmldirImport : qmldirImports) {
- ModuleId exportedModuleId = projectStorage.moduleId(Utils::PathString{qmldirImport.module});
- imports.emplace_back(moduleId,
- exportedModuleId,
- convertVersion(qmldirImport.version),
- convertToIsAutoVersion(qmldirImport.flags));
+ NanotraceHR::Tracer tracer{"add module exported imports"_t,
+ category(),
+ keyValue("cpp module id", cppModuleId),
+ keyValue("module id", moduleId)};
- ModuleId exportedCppModuleId = projectStorage.moduleId(
- Utils::PathString{qmldirImport.module} + "-cppnative");
- imports.emplace_back(cppModuleId,
- exportedCppModuleId,
- Storage::Version{},
- Storage::Synchronization::IsAutoVersion::No);
+ for (const QmlDirParser::Import &qmldirImport : qmldirImports) {
+ Utils::PathString exportedModuleName{qmldirImport.module};
+ ModuleId exportedModuleId = projectStorage.moduleId(exportedModuleName);
+ addModuleExportedImport(imports,
+ moduleId,
+ exportedModuleId,
+ convertVersion(qmldirImport.version),
+ convertToIsAutoVersion(qmldirImport.flags),
+ moduleName,
+ exportedModuleName);
+
+ exportedModuleName += "-cppnative";
+ ModuleId exportedCppModuleId = projectStorage.moduleId(exportedModuleName);
+ addModuleExportedImport(imports,
+ cppModuleId,
+ exportedCppModuleId,
+ Storage::Version{},
+ Storage::Synchronization::IsAutoVersion::No,
+ cppModuleName,
+ exportedModuleName);
}
}
@@ -182,8 +247,14 @@ std::vector<IdPaths> createIdPaths(ProjectStorageUpdater::WatchedSourceIdsIds wa
void ProjectStorageUpdater::update(QStringList directories,
QStringList qmlTypesPaths,
- const QString &propertyEditorResourcesPath)
+ const QString &propertyEditorResourcesPath,
+ const QStringList &typeAnnotationPaths)
{
+ NanotraceHR::Tracer tracer{"update"_t,
+ category(),
+ keyValue("directories", directories),
+ keyValue("qml types paths", qmlTypesPaths)};
+
Storage::Synchronization::SynchronizationPackage package;
WatchedSourceIdsIds watchedSourceIds{Utils::span{directories}.size()};
NotUpdatedSourceIds notUpdatedSourceIds{Utils::span{directories}.size()};
@@ -191,6 +262,7 @@ void ProjectStorageUpdater::update(QStringList directories,
updateDirectories(directories, package, notUpdatedSourceIds, watchedSourceIds);
updateQmlTypes(qmlTypesPaths, package, notUpdatedSourceIds, watchedSourceIds);
updatePropertyEditorPaths(propertyEditorResourcesPath, package, notUpdatedSourceIds);
+ updateTypeAnnotations(typeAnnotationPaths, package, notUpdatedSourceIds);
package.updatedSourceIds = filterNotUpdatedSourceIds(std::move(package.updatedSourceIds),
std::move(notUpdatedSourceIds.sourceIds));
@@ -198,7 +270,11 @@ void ProjectStorageUpdater::update(QStringList directories,
std::move(package.updatedFileStatusSourceIds),
std::move(notUpdatedSourceIds.fileStatusSourceIds));
- m_projectStorage.synchronize(std::move(package));
+ try {
+ m_projectStorage.synchronize(std::move(package));
+ } catch (...) {
+ qWarning() << "Project storage could not been updated!";
+ }
m_pathWatcher.updateIdPaths(createIdPaths(watchedSourceIds, m_projectPartId));
}
@@ -211,11 +287,16 @@ void ProjectStorageUpdater::updateQmlTypes(const QStringList &qmlTypesPaths,
if (qmlTypesPaths.empty())
return;
+ NanotraceHR::Tracer tracer{"update qmltypes file"_t, category()};
+
ModuleId moduleId = m_projectStorage.moduleId("QML-cppnative");
for (const QString &qmlTypesPath : qmlTypesPaths) {
SourceId sourceId = m_pathCache.sourceId(SourcePath{qmlTypesPath});
watchedSourceIdsIds.qmltypesSourceIds.push_back(sourceId);
+ tracer.tick("append watched qml types source id"_t,
+ keyValue("source id", sourceId),
+ keyValue("qml types path", qmlTypesPath));
Storage::Synchronization::ProjectData projectData{sourceId,
sourceId,
@@ -228,7 +309,9 @@ void ProjectStorageUpdater::updateQmlTypes(const QStringList &qmlTypesPaths,
notUpdatedSourceIds);
if (state == FileState::Changed) {
+ tracer.tick("append project data"_t, keyValue("project data", projectData));
package.projectDatas.push_back(std::move(projectData));
+ tracer.tick("append updated project source ids"_t, keyValue("source id", sourceId));
package.updatedProjectSourceIds.push_back(sourceId);
}
}
@@ -246,13 +329,86 @@ ProjectStorageUpdater::FileState combineState(FileStates... fileStates)
return ProjectStorageUpdater::FileState::NotExists;
}
+
} // namespace
+void ProjectStorageUpdater::updateDirectoryChanged(std::string_view directoryPath,
+ FileState qmldirState,
+ SourcePath qmldirSourcePath,
+ SourceId qmldirSourceId,
+ SourceId directorySourceId,
+ SourceContextId directoryId,
+ Storage::Synchronization::SynchronizationPackage &package,
+ NotUpdatedSourceIds &notUpdatedSourceIds,
+ WatchedSourceIdsIds &watchedSourceIdsIds,
+ Tracer &tracer)
+{
+ QmlDirParser parser;
+ if (qmldirState != FileState::NotExists)
+ parser.parse(m_fileSystem.contentAsQString(QString{qmldirSourcePath}));
+
+ if (qmldirState != FileState::NotChanged) {
+ tracer.tick("append updated source id"_t, keyValue("module id", qmldirSourceId));
+ package.updatedSourceIds.push_back(qmldirSourceId);
+ }
+
+ Utils::PathString moduleName{parser.typeNamespace()};
+ ModuleId moduleId = m_projectStorage.moduleId(moduleName);
+ Utils::PathString cppModuleName = moduleName + "-cppnative";
+ ModuleId cppModuleId = m_projectStorage.moduleId(cppModuleName);
+ ModuleId pathModuleId = m_projectStorage.moduleId(directoryPath);
+
+ auto imports = filterMultipleEntries(parser.imports());
+
+ addModuleExportedImports(package.moduleExportedImports,
+ moduleId,
+ cppModuleId,
+ moduleName,
+ cppModuleName,
+ imports,
+ m_projectStorage);
+ tracer.tick("append updated module id"_t, keyValue("module id", moduleId));
+ package.updatedModuleIds.push_back(moduleId);
+
+ const auto qmlProjectDatas = m_projectStorage.fetchProjectDatas(directorySourceId);
+ addSourceIds(package.updatedSourceIds, qmlProjectDatas, "append updated source id"_t, tracer);
+ addSourceIds(package.updatedFileStatusSourceIds,
+ qmlProjectDatas,
+ "append updated file status source id"_t,
+ tracer);
+
+ auto qmlTypes = filterMultipleEntries(parser.typeInfos());
+
+ if (!qmlTypes.isEmpty()) {
+ parseTypeInfos(qmlTypes,
+ filterMultipleEntries(parser.dependencies()),
+ imports,
+ directorySourceId,
+ directoryPath,
+ cppModuleId,
+ package,
+ notUpdatedSourceIds,
+ watchedSourceIdsIds);
+ }
+ parseQmlComponents(
+ createComponents(parser.components(), moduleId, pathModuleId, m_fileSystem, directoryPath),
+ directorySourceId,
+ directoryId,
+ package,
+ notUpdatedSourceIds,
+ watchedSourceIdsIds,
+ qmldirState);
+ tracer.tick("append updated project source id"_t, keyValue("module id", moduleId));
+ package.updatedProjectSourceIds.push_back(directorySourceId);
+}
+
void ProjectStorageUpdater::updateDirectories(const QStringList &directories,
Storage::Synchronization::SynchronizationPackage &package,
NotUpdatedSourceIds &notUpdatedSourceIds,
WatchedSourceIdsIds &watchedSourceIdsIds)
{
+ NanotraceHR::Tracer tracer{"update directories"_t, category()};
+
for (const QString &directory : directories)
updateDirectory({directory}, package, notUpdatedSourceIds, watchedSourceIdsIds);
}
@@ -262,8 +418,10 @@ void ProjectStorageUpdater::updateDirectory(const Utils::PathString &directoryPa
NotUpdatedSourceIds &notUpdatedSourceIds,
WatchedSourceIdsIds &watchedSourceIdsIds)
{
+ NanotraceHR::Tracer tracer{"update directory"_t, category(), keyValue("directory", directoryPath)};
+
SourcePath qmldirSourcePath{directoryPath + "/qmldir"};
- auto [directoryId, qmlDirSourceId] = m_pathCache.sourceContextAndSourceId(qmldirSourcePath);
+ auto [directoryId, qmldirSourceId] = m_pathCache.sourceContextAndSourceId(qmldirSourcePath);
SourcePath directorySourcePath{directoryPath + "/."};
auto directorySourceId = m_pathCache.sourceId(directorySourcePath);
@@ -271,62 +429,28 @@ void ProjectStorageUpdater::updateDirectory(const Utils::PathString &directoryPa
if (directoryState != FileState::NotExists)
watchedSourceIdsIds.directorySourceIds.push_back(directorySourceId);
- auto qmldirState = fileState(qmlDirSourceId, package, notUpdatedSourceIds);
+ auto qmldirState = fileState(qmldirSourceId, package, notUpdatedSourceIds);
if (qmldirState != FileState::NotExists)
- watchedSourceIdsIds.qmldirSourceIds.push_back(qmlDirSourceId);
+ watchedSourceIdsIds.qmldirSourceIds.push_back(qmldirSourceId);
switch (combineState(directoryState, qmldirState)) {
case FileState::Changed: {
- QmlDirParser parser;
- if (qmldirState != FileState::NotExists)
- parser.parse(m_fileSystem.contentAsQString(QString{qmldirSourcePath}));
-
- if (qmldirState != FileState::NotChanged)
- package.updatedSourceIds.push_back(qmlDirSourceId);
-
- Utils::PathString moduleName{parser.typeNamespace()};
- ModuleId moduleId = m_projectStorage.moduleId(moduleName);
- ModuleId cppModuleId = m_projectStorage.moduleId(moduleName + "-cppnative");
- ModuleId pathModuleId = m_projectStorage.moduleId(directoryPath);
-
- auto imports = filterMultipleEntries(parser.imports());
-
- addModuleExportedImports(package.moduleExportedImports,
- moduleId,
- cppModuleId,
- imports,
- m_projectStorage);
- package.updatedModuleIds.push_back(moduleId);
-
- const auto qmlProjectDatas = m_projectStorage.fetchProjectDatas(directorySourceId);
- addSourceIds(package.updatedSourceIds, qmlProjectDatas);
- addSourceIds(package.updatedFileStatusSourceIds, qmlProjectDatas);
-
- auto qmlTypes = filterMultipleEntries(parser.typeInfos());
-
- if (!qmlTypes.isEmpty()) {
- parseTypeInfos(qmlTypes,
- filterMultipleEntries(parser.dependencies()),
- imports,
- directorySourceId,
- directoryPath,
- cppModuleId,
- package,
- notUpdatedSourceIds,
- watchedSourceIdsIds);
- }
- parseQmlComponents(
- createComponents(parser.components(), moduleId, pathModuleId, m_fileSystem, directoryPath),
- directorySourceId,
- directoryId,
- package,
- notUpdatedSourceIds,
- watchedSourceIdsIds,
- qmldirState);
- package.updatedProjectSourceIds.push_back(directorySourceId);
+ tracer.tick("update directory changed"_t);
+ updateDirectoryChanged(directoryPath,
+ qmldirState,
+ qmldirSourcePath,
+ qmldirSourceId,
+ directorySourceId,
+ directoryId,
+ package,
+ notUpdatedSourceIds,
+ watchedSourceIdsIds,
+ tracer);
break;
}
case FileState::NotChanged: {
+ tracer.tick("update directory not changed"_t);
+
parseProjectDatas(m_projectStorage.fetchProjectDatas(directorySourceId),
package,
notUpdatedSourceIds,
@@ -334,19 +458,32 @@ void ProjectStorageUpdater::updateDirectory(const Utils::PathString &directoryPa
break;
}
case FileState::NotExists: {
+ tracer.tick("update directory don't exits"_t);
+
package.updatedFileStatusSourceIds.push_back(directorySourceId);
- package.updatedFileStatusSourceIds.push_back(qmlDirSourceId);
+ package.updatedFileStatusSourceIds.push_back(qmldirSourceId);
package.updatedProjectSourceIds.push_back(directorySourceId);
- package.updatedSourceIds.push_back(qmlDirSourceId);
+ package.updatedSourceIds.push_back(qmldirSourceId);
auto qmlProjectDatas = m_projectStorage.fetchProjectDatas(directorySourceId);
for (const Storage::Synchronization::ProjectData &projectData : qmlProjectDatas) {
+ tracer.tick("append updated source id"_t, keyValue("source id", projectData.sourceId));
package.updatedSourceIds.push_back(projectData.sourceId);
+ tracer.tick("append updated file status source id"_t,
+ keyValue("source id", projectData.sourceId));
package.updatedFileStatusSourceIds.push_back(projectData.sourceId);
}
break;
}
}
+
+ tracer.end(keyValue("qmldir source path", qmldirSourcePath),
+ keyValue("directory source path", directorySourcePath),
+ keyValue("directory id", directoryId),
+ keyValue("qmldir source id", qmldirSourceId),
+ keyValue("directory source source id", directorySourceId),
+ keyValue("qmldir state", qmldirState),
+ keyValue("directory state", directoryState));
}
void ProjectStorageUpdater::updatePropertyEditorPaths(
@@ -354,6 +491,10 @@ void ProjectStorageUpdater::updatePropertyEditorPaths(
Storage::Synchronization::SynchronizationPackage &package,
NotUpdatedSourceIds &notUpdatedSourceIds)
{
+ NanotraceHR::Tracer tracer{"update property editor paths"_t,
+ category(),
+ keyValue("property editor resources path", propertyEditorResourcesPath)};
+
if (propertyEditorResourcesPath.isEmpty())
return;
@@ -373,12 +514,134 @@ void ProjectStorageUpdater::updatePropertyEditorPaths(
}
}
+namespace {
+
+template<typename SourceIds1, typename SourceIds2>
+SmallSourceIds<16> mergedSourceIds(const SourceIds1 &sourceIds1, const SourceIds2 &sourceIds2)
+{
+ SmallSourceIds<16> mergedSourceIds;
+
+ std::set_union(sourceIds1.begin(),
+ sourceIds1.end(),
+ sourceIds2.begin(),
+ sourceIds2.end(),
+ std::back_inserter(mergedSourceIds));
+
+ return mergedSourceIds;
+}
+} // namespace
+
+void ProjectStorageUpdater::updateTypeAnnotations(const QStringList &directoryPaths,
+ Storage::Synchronization::SynchronizationPackage &package,
+ NotUpdatedSourceIds &notUpdatedSourceIds)
+{
+ NanotraceHR::Tracer tracer("update type annotations"_t, category());
+
+ std::map<SourceId, SmallSourceIds<16>> updatedSourceIdsDictonary;
+
+ for (SourceId directoryId : m_projectStorage.typeAnnotationDirectorySourceIds())
+ updatedSourceIdsDictonary[directoryId] = {};
+
+ for (const auto &directoryPath : directoryPaths)
+ updateTypeAnnotations(directoryPath, package, notUpdatedSourceIds, updatedSourceIdsDictonary);
+
+ updateTypeAnnotationDirectories(package, notUpdatedSourceIds, updatedSourceIdsDictonary);
+}
+
void ProjectStorageUpdater::updateTypeAnnotations(
- const QString & /*propertyEditorResourcesPath*/,
- Storage::Synchronization::SynchronizationPackage & /*package*/,
- NotUpdatedSourceIds & /*notUpdatedSourceIds*/)
+ const QString &rootDirectoryPath,
+ Storage::Synchronization::SynchronizationPackage &package,
+ NotUpdatedSourceIds &notUpdatedSourceIds,
+ std::map<SourceId, SmallSourceIds<16>> &updatedSourceIdsDictonary)
+{
+ NanotraceHR::Tracer tracer("update type annotation directory"_t,
+ category(),
+ keyValue("path", rootDirectoryPath));
+
+ if (rootDirectoryPath.isEmpty())
+ return;
+
+ QDirIterator directoryIterator{rootDirectoryPath,
+ {"*.metainfo"},
+ QDir::NoDotAndDotDot | QDir::Files,
+ QDirIterator::Subdirectories};
+
+ while (directoryIterator.hasNext()) {
+ auto fileInfo = directoryIterator.nextFileInfo();
+ auto filePath = fileInfo.filePath();
+ SourceId sourceId = m_pathCache.sourceId(SourcePath{filePath});
+
+ auto directoryPath = fileInfo.canonicalPath();
+
+ SourceId directorySourceId = m_pathCache.sourceId(SourcePath{directoryPath + "/."});
+
+ auto state = fileState(sourceId, package, notUpdatedSourceIds);
+ if (state == FileState::Changed)
+ updateTypeAnnotation(directoryPath, fileInfo.filePath(), sourceId, directorySourceId, package);
+
+ if (state != FileState::NotChanged)
+ updatedSourceIdsDictonary[directorySourceId].push_back(sourceId);
+ }
+}
+
+void ProjectStorageUpdater::updateTypeAnnotationDirectories(
+ Storage::Synchronization::SynchronizationPackage &package,
+ NotUpdatedSourceIds &notUpdatedSourceIds,
+ std::map<SourceId, SmallSourceIds<16>> &updatedSourceIdsDictonary)
+{
+ for (auto &[directorySourceId, updatedSourceIds] : updatedSourceIdsDictonary) {
+ auto directoryState = fileState(directorySourceId, package, notUpdatedSourceIds);
+
+ if (directoryState != FileState::NotChanged) {
+ auto existingTypeAnnotationSourceIds = m_projectStorage.typeAnnotationSourceIds(
+ directorySourceId);
+
+ std::sort(updatedSourceIds.begin(), updatedSourceIds.end());
+
+ auto changedSourceIds = mergedSourceIds(existingTypeAnnotationSourceIds, updatedSourceIds);
+ package.updatedTypeAnnotationSourceIds.insert(package.updatedTypeAnnotationSourceIds.end(),
+ changedSourceIds.begin(),
+ changedSourceIds.end());
+ } else {
+ package.updatedTypeAnnotationSourceIds.insert(package.updatedTypeAnnotationSourceIds.end(),
+ updatedSourceIds.begin(),
+ updatedSourceIds.end());
+ }
+ }
+}
+
+namespace {
+QString contentFromFile(const QString &path)
+{
+ QFile file{path};
+ if (file.open(QIODevice::ReadOnly))
+ return QString::fromUtf8(file.readAll());
+
+ return {};
+}
+} // namespace
+
+void ProjectStorageUpdater::updateTypeAnnotation(const QString &directoryPath,
+ const QString &filePath,
+ SourceId sourceId,
+ SourceId directorySourceId,
+ Storage::Synchronization::SynchronizationPackage &package)
{
- // const auto typeAnnotations = dir.entryInfoList({"*.metainfo"}, QDir::Files);
+ NanotraceHR::Tracer tracer{"update type annotation path"_t,
+ category(),
+ keyValue("path", filePath),
+ keyValue("directory path", directoryPath)};
+
+ Storage::TypeAnnotationReader reader{m_projectStorage};
+
+ auto annotations = reader.parseTypeAnnotation(contentFromFile(filePath),
+ directoryPath,
+ sourceId,
+ directorySourceId);
+ auto &typeAnnotations = package.typeAnnotations;
+ package.typeAnnotations.insert(typeAnnotations.end(),
+ std::make_move_iterator(annotations.begin()),
+ std::make_move_iterator(annotations.end()));
}
void ProjectStorageUpdater::updatePropertyEditorPath(
@@ -386,6 +649,13 @@ void ProjectStorageUpdater::updatePropertyEditorPath(
Storage::Synchronization::SynchronizationPackage &package,
SourceId directorySourceId)
{
+ NanotraceHR::Tracer tracer{"update property editor path"_t,
+ category(),
+ keyValue("directory path", directoryPath),
+ keyValue("directory source id", directorySourceId)};
+
+ tracer.tick("append updated property editor qml path source id"_t,
+ keyValue("source id", directorySourceId));
package.updatedPropertyEditorQmlPathSourceIds.push_back(directorySourceId);
auto dir = QDir{directoryPath};
const auto fileInfos = dir.entryInfoList({"*Pane.qml", "*Specifics.qml"}, QDir::Files);
@@ -398,6 +668,11 @@ void ProjectStorageUpdater::updatePropertyEditorFilePath(
Storage::Synchronization::SynchronizationPackage &package,
SourceId directorySourceId)
{
+ NanotraceHR::Tracer tracer{"update property editor file path"_t,
+ category(),
+ keyValue("directory path", path),
+ keyValue("directory source id", directorySourceId)};
+
QRegularExpression regex{R"xo(.+\/(\w+)\/(\w+)(Specifics|Pane).qml)xo"};
auto match = regex.match(path);
QString oldModuleName;
@@ -410,7 +685,12 @@ void ProjectStorageUpdater::updatePropertyEditorFilePath(
}
Storage::TypeNameString typeName{match.capturedView(2)};
SourceId pathId = m_pathCache.sourceId(SourcePath{path});
- package.propertyEditorQmlPaths.emplace_back(moduleId, typeName, pathId, directorySourceId);
+ const auto &paths = package.propertyEditorQmlPaths.emplace_back(moduleId,
+ typeName,
+ pathId,
+ directorySourceId);
+ tracer.tick("append property editor qml paths"_t,
+ keyValue("property editor qml paths", paths));
}
}
@@ -447,6 +727,10 @@ bool contains(const Container &container, Id id)
void ProjectStorageUpdater::pathsWithIdsChanged(const std::vector<IdPaths> &changedIdPaths)
{
+ NanotraceHR::Tracer tracer{"paths with ids changed"_t,
+ category(),
+ keyValue("id paths", changedIdPaths)};
+
m_changedIdPaths.insert(m_changedIdPaths.end(), changedIdPaths.begin(), changedIdPaths.end());
Storage::Synchronization::SynchronizationPackage package;
@@ -539,21 +823,35 @@ void ProjectStorageUpdater::parseTypeInfos(const QStringList &typeInfos,
NotUpdatedSourceIds &notUpdatedSourceIds,
WatchedSourceIdsIds &watchedSourceIds)
{
+ NanotraceHR::Tracer tracer{"parse type infos"_t,
+ category(),
+ keyValue("directory source id", directorySourceId),
+ keyValue("directory path", directoryPath),
+ keyValue("module id", moduleId)};
+
for (const QString &typeInfo : typeInfos) {
+ NanotraceHR::Tracer tracer{"parse type info"_t, category(), keyValue("type info", typeInfo)};
+
Utils::PathString qmltypesPath = Utils::PathString::join(
{directoryPath, "/", Utils::SmallString{typeInfo}});
SourceId sourceId = m_pathCache.sourceId(SourcePathView{qmltypesPath});
+ tracer.tick("append qmltypes source id"_t, keyValue("source id", sourceId));
watchedSourceIds.qmltypesSourceIds.push_back(sourceId);
addDependencies(package.moduleDependencies,
sourceId,
joinImports(qmldirDependencies, qmldirImports),
- m_projectStorage);
+ m_projectStorage,
+ "append module dependency"_t,
+ tracer);
+
+ tracer.tick("append module dependenct source source id"_t, keyValue("source id", sourceId));
package.updatedModuleDependencySourceIds.push_back(sourceId);
auto projectData = package.projectDatas.emplace_back(
directorySourceId, sourceId, moduleId, Storage::Synchronization::FileType::QmlTypes);
+ tracer.tick("append project data"_t, keyValue("source id", sourceId));
parseTypeInfo(projectData, qmltypesPath, package, notUpdatedSourceIds);
}
@@ -564,6 +862,8 @@ void ProjectStorageUpdater::parseProjectDatas(const Storage::Synchronization::Pr
NotUpdatedSourceIds &notUpdatedSourceIds,
WatchedSourceIdsIds &watchedSourceIds)
{
+ NanotraceHR::Tracer tracer{"parse project datas"_t, category()};
+
for (const Storage::Synchronization::ProjectData &projectData : projectDatas) {
switch (projectData.fileType) {
case Storage::Synchronization::FileType::QmlTypes: {
@@ -577,6 +877,7 @@ void ProjectStorageUpdater::parseProjectDatas(const Storage::Synchronization::Pr
watchedSourceIds.qmlSourceIds.push_back(projectData.sourceId);
parseQmlComponent(projectData.sourceId, package, notUpdatedSourceIds);
+ break;
}
}
}
@@ -587,9 +888,14 @@ auto ProjectStorageUpdater::parseTypeInfo(const Storage::Synchronization::Projec
Storage::Synchronization::SynchronizationPackage &package,
NotUpdatedSourceIds &notUpdatedSourceIds) -> FileState
{
+ NanotraceHR::Tracer tracer{"parse type info"_t,
+ category(),
+ keyValue("qmltypes path", qmltypesPath)};
+
auto state = fileState(projectData.sourceId, package, notUpdatedSourceIds);
switch (state) {
case FileState::Changed: {
+ tracer.tick("append updated source ids"_t, keyValue("source id", projectData.sourceId));
package.updatedSourceIds.push_back(projectData.sourceId);
const auto content = m_fileSystem.contentAsQString(QString{qmltypesPath});
@@ -597,14 +903,16 @@ auto ProjectStorageUpdater::parseTypeInfo(const Storage::Synchronization::Projec
break;
}
case FileState::NotChanged: {
+ tracer.tick("append not updated source ids"_t, keyValue("source id", projectData.sourceId));
notUpdatedSourceIds.sourceIds.push_back(projectData.sourceId);
break;
}
case FileState::NotExists:
throw CannotParseQmlTypesFile{};
- break;
}
+ tracer.end(keyValue("state", state));
+
return state;
}
@@ -617,6 +925,14 @@ void ProjectStorageUpdater::parseQmlComponent(Utils::SmallStringView relativeFil
WatchedSourceIdsIds &watchedSourceIds,
FileState qmldirState)
{
+ NanotraceHR::Tracer tracer{"parse qml component"_t,
+ category(),
+ keyValue("relative file path", relativeFilePath),
+ keyValue("directory path", directoryPath),
+ keyValue("exported types", exportedTypes),
+ keyValue("directory source id", directorySourceId),
+ keyValue("qmldir state", qmldirState)};
+
if (std::find(relativeFilePath.begin(), relativeFilePath.end(), '+') != relativeFilePath.end())
return;
@@ -626,16 +942,18 @@ void ProjectStorageUpdater::parseQmlComponent(Utils::SmallStringView relativeFil
Storage::Synchronization::Type type;
auto state = fileState(sourceId, package, notUpdatedSourceIds);
+ tracer.tick("append watched qml source id"_t, keyValue("source id", sourceId));
watchedSourceIds.qmlSourceIds.push_back(sourceId);
switch (state) {
case FileState::NotChanged:
if (qmldirState == FileState::NotExists) {
+ tracer.tick("append not updated source id"_t, keyValue("source id", sourceId));
notUpdatedSourceIds.sourceIds.emplace_back(sourceId);
- package.projectDatas.emplace_back(directorySourceId,
- sourceId,
- ModuleId{},
- Storage::Synchronization::FileType::QmlDocument);
+
+ const auto &projectData = package.projectDatas.emplace_back(
+ directorySourceId, sourceId, ModuleId{}, Storage::Synchronization::FileType::QmlDocument);
+ tracer.tick("append project data"_t, keyValue("project data", projectData));
return;
}
@@ -649,11 +967,11 @@ void ProjectStorageUpdater::parseQmlComponent(Utils::SmallStringView relativeFil
break;
}
- package.projectDatas.emplace_back(directorySourceId,
- sourceId,
- ModuleId{},
- Storage::Synchronization::FileType::QmlDocument);
+ const auto &projectData = package.projectDatas.emplace_back(
+ directorySourceId, sourceId, ModuleId{}, Storage::Synchronization::FileType::QmlDocument);
+ tracer.tick("append project data"_t, keyValue("project data", projectData));
+ tracer.tick("append updated source id"_t, keyValue("source id", sourceId));
package.updatedSourceIds.push_back(sourceId);
type.typeName = SourcePath{qmlFilePath}.name();
@@ -661,6 +979,8 @@ void ProjectStorageUpdater::parseQmlComponent(Utils::SmallStringView relativeFil
type.sourceId = sourceId;
type.exportedTypes = std::move(exportedTypes);
+ tracer.end(keyValue("type", type));
+
package.types.push_back(std::move(type));
}
@@ -668,10 +988,13 @@ void ProjectStorageUpdater::parseQmlComponent(SourceId sourceId,
Storage::Synchronization::SynchronizationPackage &package,
NotUpdatedSourceIds &notUpdatedSourceIds)
{
+ NanotraceHR::Tracer tracer{"parse qml component"_t, category(), keyValue("source id", sourceId)};
+
auto state = fileState(sourceId, package, notUpdatedSourceIds);
if (state == FileState::NotChanged)
return;
+ tracer.tick("append updated source id"_t, keyValue("source id", sourceId));
package.updatedSourceIds.push_back(sourceId);
if (state == FileState::NotExists)
@@ -687,6 +1010,8 @@ void ProjectStorageUpdater::parseQmlComponent(SourceId sourceId,
type.sourceId = sourceId;
type.changeLevel = Storage::Synchronization::ChangeLevel::ExcludeExportedTypes;
+ tracer.end(keyValue("type", type));
+
package.types.push_back(std::move(type));
}
@@ -733,6 +1058,12 @@ void ProjectStorageUpdater::parseQmlComponents(Components components,
WatchedSourceIdsIds &watchedSourceIdsIds,
FileState qmldirState)
{
+ NanotraceHR::Tracer tracer{"parse qml components"_t,
+ category(),
+ keyValue("directory source id", directorySourceId),
+ keyValue("directory id", directoryId),
+ keyValue("qmldir state", qmldirState)};
+
std::sort(components.begin(), components.end(), [](auto &&first, auto &&second) {
return first.fileName < second.fileName;
});
@@ -760,22 +1091,37 @@ ProjectStorageUpdater::FileState ProjectStorageUpdater::fileState(
Storage::Synchronization::SynchronizationPackage &package,
NotUpdatedSourceIds &notUpdatedSourceIds) const
{
+ NanotraceHR::Tracer tracer{"update property editor paths"_t,
+ category(),
+ keyValue("source id", sourceId)};
+
auto currentFileStatus = m_fileStatusCache.find(sourceId);
if (!currentFileStatus.isValid()) {
+ tracer.tick("append updated file status source id"_t, keyValue("source id", sourceId));
package.updatedFileStatusSourceIds.push_back(sourceId);
+
+ tracer.end(keyValue("state", FileState::NotExists));
return FileState::NotExists;
}
auto projectStorageFileStatus = m_projectStorage.fetchFileStatus(sourceId);
if (!projectStorageFileStatus.isValid() || projectStorageFileStatus != currentFileStatus) {
+ tracer.tick("append file status"_t, keyValue("file status", sourceId));
package.fileStatuses.push_back(currentFileStatus);
+
+ tracer.tick("append updated file status source id"_t, keyValue("source id", sourceId));
package.updatedFileStatusSourceIds.push_back(sourceId);
+
+ tracer.end(keyValue("state", FileState::Changed));
return FileState::Changed;
}
+ tracer.tick("append not updated file status source id"_t, keyValue("source id", sourceId));
notUpdatedSourceIds.fileStatusSourceIds.push_back(sourceId);
+
+ tracer.end(keyValue("state", FileState::NotChanged));
return FileState::NotChanged;
}
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h
index 187a2219d0..640969fe99 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h
@@ -11,10 +11,15 @@
#include "projectstoragetypes.h"
#include "sourcepath.h"
+#include <modelfwd.h>
+
+#include <tracing/qmldesignertracing.h>
+
#include <qmljs/parser/qmldirparser_p.h>
#include <QStringList>
+#include <map>
#include <vector>
namespace Sqlite {
@@ -27,7 +32,6 @@ class ProjectStorageInterface;
template<typename ProjectStorage, typename Mutex>
class SourcePathCache;
class FileStatusCache;
-template<typename Database>
class ProjectStorage;
class QmlDocumentParserInterface;
class QmlTypesParserInterface;
@@ -35,10 +39,10 @@ class QmlTypesParserInterface;
class ProjectStorageUpdater final : public ProjectStoragePathWatcherNotifierInterface
{
public:
- using PathCache = SourcePathCache<ProjectStorage<Sqlite::Database>, NonLockingMutex>;
+ using PathCache = SourcePathCache<ProjectStorage, NonLockingMutex>;
ProjectStorageUpdater(FileSystemInterface &fileSystem,
- ProjectStorageInterface &projectStorage,
+ ProjectStorageType &projectStorage,
FileStatusCache &fileStatusCache,
PathCache &pathCache,
QmlDocumentParserInterface &qmlDocumentParser,
@@ -57,7 +61,8 @@ public:
void update(QStringList directories,
QStringList qmlTypesPaths,
- const QString &propertyEditorResourcesPath);
+ const QString &propertyEditorResourcesPath,
+ const QStringList &typeAnnotationPaths);
void pathsWithIdsChanged(const std::vector<IdPaths> &idPaths) override;
void pathsChanged(const SourceIds &filePathIds) override;
@@ -141,13 +146,35 @@ private:
Storage::Synchronization::SynchronizationPackage &package,
NotUpdatedSourceIds &notUpdatedSourceIds,
WatchedSourceIdsIds &watchedSourceIdsIds);
+ void updateDirectoryChanged(std::string_view directoryPath,
+ FileState qmldirState,
+ SourcePath qmldirSourcePath,
+ SourceId qmldirSourceId,
+ SourceId directorySourceId,
+ SourceContextId directoryId,
+ Storage::Synchronization::SynchronizationPackage &package,
+ NotUpdatedSourceIds &notUpdatedSourceIds,
+ WatchedSourceIdsIds &watchedSourceIdsIds,
+ ProjectStorageTracing::Category::TracerType &tracer);
void updatePropertyEditorPaths(const QString &propertyEditorResourcesPath,
Storage::Synchronization::SynchronizationPackage &package,
NotUpdatedSourceIds &notUpdatedSourceIds);
- void updateTypeAnnotations(const QString &propertyEditorResourcesPath,
+ void updateTypeAnnotations(const QString &directoryPath,
+ Storage::Synchronization::SynchronizationPackage &package,
+ NotUpdatedSourceIds &notUpdatedSourceIds,
+ std::map<SourceId, SmallSourceIds<16>> &updatedSourceIdsDictonary);
+ void updateTypeAnnotationDirectories(Storage::Synchronization::SynchronizationPackage &package,
+ NotUpdatedSourceIds &notUpdatedSourceIds,
+ std::map<SourceId, SmallSourceIds<16>> &updatedSourceIdsDictonary);
+ void updateTypeAnnotations(const QStringList &directoryPath,
Storage::Synchronization::SynchronizationPackage &package,
NotUpdatedSourceIds &notUpdatedSourceIds);
+ void updateTypeAnnotation(const QString &directoryPath,
+ const QString &filePath,
+ SourceId sourceId,
+ SourceId directorySourceId,
+ Storage::Synchronization::SynchronizationPackage &package);
void updatePropertyEditorPath(const QString &path,
Storage::Synchronization::SynchronizationPackage &package,
SourceId directorySourceId);
@@ -197,7 +224,7 @@ private:
private:
std::vector<IdPaths> m_changedIdPaths;
FileSystemInterface &m_fileSystem;
- ProjectStorageInterface &m_projectStorage;
+ ProjectStorageType &m_projectStorage;
FileStatusCache &m_fileStatusCache;
PathCache &m_pathCache;
QmlDocumentParserInterface &m_qmlDocumentParser;
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.cpp b/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.cpp
index f9eb8080f7..27efa8d530 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.cpp
+++ b/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.cpp
@@ -10,6 +10,8 @@
#include <sqlitedatabase.h>
+#include <tracing/qmldesignertracing.h>
+
#ifdef QDS_BUILD_QMLPARSER
#include <private/qqmldomtop_p.h>
#endif
@@ -21,6 +23,10 @@ namespace QmlDesigner {
#ifdef QDS_BUILD_QMLPARSER
+constexpr auto category = ProjectStorageTracing::projectStorageUpdaterCategory;
+using NanotraceHR::keyValue;
+using Tracer = ProjectStorageTracing::Category::TracerType;
+
namespace QmlDom = QQmlJS::Dom;
namespace Synchronization = Storage::Synchronization;
@@ -84,6 +90,11 @@ QualifiedImports createQualifiedImports(const QList<QmlDom::Import> &qmlImports,
Utils::SmallStringView directoryPath,
QmlDocumentParser::ProjectStorage &storage)
{
+ NanotraceHR::Tracer tracer{"create qualified imports"_t,
+ category(),
+ keyValue("sourceId", sourceId),
+ keyValue("directoryPath", directoryPath)};
+
QualifiedImports qualifiedImports;
for (const QmlDom::Import &qmlImport : qmlImports) {
@@ -92,6 +103,8 @@ QualifiedImports createQualifiedImports(const QList<QmlDom::Import> &qmlImports,
createImport(qmlImport, sourceId, directoryPath, storage));
}
+ tracer.end(keyValue("qualified imports", qualifiedImports));
+
return qualifiedImports;
}
@@ -280,6 +293,11 @@ Storage::Synchronization::Type QmlDocumentParser::parse(const QString &sourceCon
SourceId sourceId,
Utils::SmallStringView directoryPath)
{
+ NanotraceHR::Tracer tracer{"qml document parser parse"_t,
+ category(),
+ keyValue("sourceId", sourceId),
+ keyValue("directoryPath", directoryPath)};
+
Storage::Synchronization::Type type;
using Option = QmlDom::DomEnvironment::Option;
@@ -335,7 +353,7 @@ Storage::Synchronization::Type QmlDocumentParser::parse(const QString &sourceCon
m_storage);
type.prototype = createImportedTypeName(qmlObject.name(), qualifiedImports);
-
+ type.defaultPropertyName = qmlObject.localDefaultPropertyName();
addImports(imports, qmlFile->imports(), sourceId, directoryPath, m_storage);
addPropertyDeclarations(type, qmlObject, qualifiedImports, file);
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h b/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h
index b8ab4ec4b1..1b494a2f69 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/qmldocumentparser.h
@@ -15,7 +15,7 @@ class SourcePathCache;
class QmlDocumentParser final : public QmlDocumentParserInterface
{
public:
- using ProjectStorage = QmlDesigner::ProjectStorage<Sqlite::Database>;
+ using ProjectStorage = QmlDesigner::ProjectStorage;
using PathCache = QmlDesigner::SourcePathCache<ProjectStorage, NonLockingMutex>;
#ifdef QDS_BUILD_QMLPARSER
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.cpp b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.cpp
index 3768535299..104338e514 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.cpp
+++ b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.cpp
@@ -5,8 +5,12 @@
#include "projectstorage.h"
+#include <tracing/qmldesignertracing.h>
+
#include <sqlitedatabase.h>
+#include <utils/span.h>
+
#ifdef QDS_BUILD_QMLPARSER
#include <private/qqmldomtop_p.h>
#include <private/qqmljstypedescriptionreader_p.h>
@@ -21,6 +25,10 @@ namespace QmlDesigner {
#ifdef QDS_BUILD_QMLPARSER
+constexpr auto category = ProjectStorageTracing::projectStorageUpdaterCategory;
+using NanotraceHR::keyValue;
+using Tracer = ProjectStorageTracing::Category::TracerType;
+
namespace QmlDom = QQmlJS::Dom;
namespace {
@@ -31,6 +39,8 @@ using Storage::TypeNameString;
ComponentWithoutNamespaces createComponentNameWithoutNamespaces(const QList<QQmlJSExportedScope> &objects)
{
+ NanotraceHR::Tracer tracer{"parse qmltypes file"_t, category()};
+
ComponentWithoutNamespaces componentWithoutNamespaces;
for (const auto &object : objects) {
@@ -46,13 +56,15 @@ ComponentWithoutNamespaces createComponentNameWithoutNamespaces(const QList<QQml
name);
}
+ tracer.end(keyValue("components without namespace", componentWithoutNamespaces));
+
return componentWithoutNamespaces;
}
-void appendImports(Storage::Imports &imports,
- const QString &dependency,
- SourceId sourceId,
- QmlTypesParser::ProjectStorage &storage)
+const Storage::Import &appendImports(Storage::Imports &imports,
+ const QString &dependency,
+ SourceId sourceId,
+ QmlTypesParser::ProjectStorage &storage)
{
auto spaceFound = std::find_if(dependency.begin(), dependency.end(), [](QChar c) {
return c.isSpace();
@@ -62,7 +74,7 @@ void appendImports(Storage::Imports &imports,
moduleName.append("-cppnative");
ModuleId cppModuleId = storage.moduleId(moduleName);
- imports.emplace_back(cppModuleId, Storage::Version{}, sourceId);
+ return imports.emplace_back(cppModuleId, Storage::Version{}, sourceId);
}
void addImports(Storage::Imports &imports,
@@ -71,13 +83,25 @@ void addImports(Storage::Imports &imports,
QmlTypesParser::ProjectStorage &storage,
ModuleId cppModuleId)
{
- for (const QString &dependency : dependencies)
- appendImports(imports, dependency, sourceId, storage);
+ NanotraceHR::Tracer tracer{
+ "add imports"_t,
+ category(),
+ keyValue("source id", sourceId),
+ keyValue("module id", cppModuleId),
+ };
+
+ for (const QString &dependency : dependencies) {
+ const auto &import = appendImports(imports, dependency, sourceId, storage);
+ tracer.tick("append import"_t, keyValue("import", import), keyValue("dependency", dependency));
+ }
- imports.emplace_back(cppModuleId, Storage::Version{}, sourceId);
+ const auto &import = imports.emplace_back(cppModuleId, Storage::Version{}, sourceId);
+ tracer.tick("append import"_t, keyValue("import", import));
- if (ModuleId qmlCppModuleId = storage.moduleId("QML-cppnative"); cppModuleId != qmlCppModuleId)
- imports.emplace_back(qmlCppModuleId, Storage::Version{}, sourceId);
+ if (ModuleId qmlCppModuleId = storage.moduleId("QML-cppnative"); cppModuleId != qmlCppModuleId) {
+ const auto &import = imports.emplace_back(qmlCppModuleId, Storage::Version{}, sourceId);
+ tracer.tick("append import"_t, keyValue("import", import));
+ }
}
Storage::TypeTraits createAccessTypeTraits(QQmlJSScope::AccessSemantics accessSematics)
@@ -412,6 +436,11 @@ void addType(Storage::Synchronization::Types &types,
QmlTypesParser::ProjectStorage &storage,
const ComponentWithoutNamespaces &componentNameWithoutNamespace)
{
+ NanotraceHR::Tracer tracer{"add type"_t,
+ category(),
+ keyValue("source id", sourceId),
+ keyValue("module id", cppModuleId)};
+
const auto &component = *exportScope.scope;
auto [functionsDeclarations, signalDeclarations] = createFunctionAndSignals(
@@ -421,7 +450,7 @@ void addType(Storage::Synchronization::Types &types,
auto exports = exportScope.exports;
auto enumerationTypes = addEnumerationTypes(types, typeName, sourceId, cppModuleId, enumerations);
- types.emplace_back(
+ const auto &type = types.emplace_back(
Utils::SmallStringView{typeName},
Storage::Synchronization::ImportedType{TypeNameString{component.baseTypeName()}},
Storage::Synchronization::ImportedType{TypeNameString{component.extensionTypeName()}},
@@ -431,7 +460,37 @@ void addType(Storage::Synchronization::Types &types,
createProperties(component.ownProperties(), enumerationTypes, componentNameWithoutNamespace),
std::move(functionsDeclarations),
std::move(signalDeclarations),
- createEnumeration(enumerations));
+ createEnumeration(enumerations),
+ Storage::Synchronization::ChangeLevel::Full,
+ Utils::SmallString{component.ownDefaultPropertyName()});
+ tracer.end(keyValue("type", type));
+}
+
+using namespace Qt::StringLiterals;
+
+constexpr auto skipLists = std::make_tuple(
+ std::pair{"QtQuick.Templates-cppnative"sv, std::array{"QQuickItem"_L1}});
+
+Utils::span<const QLatin1StringView> getSkipList(std::string_view moduleName)
+{
+ static constexpr Utils::span<const QLatin1StringView> emptySkipList;
+ auto currentSkipList = emptySkipList;
+
+ std::apply(
+ [&](const auto &entry) {
+ if (entry.first == moduleName)
+ currentSkipList = entry.second;
+ },
+ skipLists);
+
+ return currentSkipList;
+}
+
+bool skipType(const QQmlJSExportedScope &object, Utils::span<const QLatin1StringView> skipList)
+{
+ return std::any_of(skipList.begin(), skipList.end(), [&](const QLatin1StringView skip) {
+ return object.scope->internalName() == skip;
+ });
}
void addTypes(Storage::Synchronization::Types &types,
@@ -440,15 +499,22 @@ void addTypes(Storage::Synchronization::Types &types,
QmlTypesParser::ProjectStorage &storage,
const ComponentWithoutNamespaces &componentNameWithoutNamespaces)
{
+ NanotraceHR::Tracer tracer{"add types"_t, category()};
types.reserve(Utils::usize(objects) + types.size());
- for (const auto &object : objects)
+ const auto skipList = getSkipList(storage.moduleName(projectData.moduleId));
+
+ for (const auto &object : objects) {
+ if (skipType(object, skipList))
+ continue;
+
addType(types,
projectData.sourceId,
projectData.moduleId,
object,
storage,
componentNameWithoutNamespaces);
+ }
}
} // namespace
@@ -458,6 +524,8 @@ void QmlTypesParser::parse(const QString &sourceContent,
Storage::Synchronization::Types &types,
const Storage::Synchronization::ProjectData &projectData)
{
+ NanotraceHR::Tracer tracer{"qmltypes parser parse"_t, category()};
+
QQmlJSTypeDescriptionReader reader({}, sourceContent);
QList<QQmlJSExportedScope> components;
QStringList dependencies;
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h
index 7c41925f30..4a6427501b 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/qmltypesparser.h
@@ -4,6 +4,7 @@
#pragma once
#include "nonlockingmutex.h"
+#include "projectstoragefwd.h"
#include "qmltypesparserinterface.h"
namespace Sqlite {
@@ -12,17 +13,13 @@ class Database;
namespace QmlDesigner {
-template<typename Database>
-class ProjectStorage;
-
template<typename ProjectStorage, typename Mutex>
class SourcePathCache;
class QmlTypesParser final : public QmlTypesParserInterface
{
public:
- using ProjectStorage = QmlDesigner::ProjectStorage<Sqlite::Database>;
-
+ using ProjectStorage = QmlDesigner::ProjectStorage;
#ifdef QDS_BUILD_QMLPARSER
QmlTypesParser(ProjectStorage &storage)
: m_storage{storage}
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/sourcepath.h b/src/plugins/qmldesigner/designercore/projectstorage/sourcepath.h
index 837e58d48a..b655c5cc34 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/sourcepath.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/sourcepath.h
@@ -117,6 +117,12 @@ public:
std::ptrdiff_t slashIndex() const { return m_slashIndex; }
+ template<typename String>
+ friend void convertToString(String &string, const SourcePath &path)
+ {
+ convertToString(string, path.toStringView());
+ }
+
private:
std::ptrdiff_t m_slashIndex = -1;
};
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/sourcepathcachetypes.h b/src/plugins/qmldesigner/designercore/projectstorage/sourcepathcachetypes.h
index 5feaf30d00..1ef8ba7f21 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/sourcepathcachetypes.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/sourcepathcachetypes.h
@@ -125,4 +125,6 @@ public:
SourceContextId sourceContextId;
};
+using SourceNameAndSourceContextIds = std::vector<SourceNameAndSourceContextId>;
+
} // namespace QmlDesigner::Cache
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/typeannotationreader.cpp b/src/plugins/qmldesigner/designercore/projectstorage/typeannotationreader.cpp
index b829e9db36..67a63542bc 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/typeannotationreader.cpp
+++ b/src/plugins/qmldesigner/designercore/projectstorage/typeannotationreader.cpp
@@ -27,11 +27,11 @@ constexpr auto propertyElementName = "Property"_L1;
constexpr auto extraFileElementName = "ExtraFile"_L1;
} // namespace
-Synchronization::TypeAnnotations TypeAnnotationReader::parseTypeAnnotation(const QString &content,
- const QString &directoryPath,
- SourceId sourceId)
+Synchronization::TypeAnnotations TypeAnnotationReader::parseTypeAnnotation(
+ const QString &content, const QString &directoryPath, SourceId sourceId, SourceId directorySourceId)
{
m_sourceId = sourceId;
+ m_directorySourceId = directorySourceId;
m_directoryPath = directoryPath;
m_parserState = ParsingDocument;
if (!SimpleAbstractStreamReader::readFromSource(content)) {
@@ -178,7 +178,7 @@ TypeAnnotationReader::ParserSate TypeAnnotationReader::readDocument(const QStrin
TypeAnnotationReader::ParserSate TypeAnnotationReader::readMetaInfoRootElement(const QString &name)
{
if (name == typeElementName) {
- m_typeAnnotations.emplace_back(m_sourceId);
+ m_typeAnnotations.emplace_back(m_sourceId, m_directorySourceId);
m_itemLibraryEntries = json::array();
return ParsingType;
} else {
@@ -277,7 +277,7 @@ void TypeAnnotationReader::readItemLibraryEntryProperty(QStringView name, const
} else if (name == "category"_L1) {
m_itemLibraryEntries.back()["category"] = value;
} else if (name == "libraryIcon"_L1) {
- m_itemLibraryEntries.back()["iconPath"] = value;
+ m_itemLibraryEntries.back()["iconPath"] = absoluteFilePathForDocument(variant.toString());
} else if (name == "version"_L1) {
// setVersion(value.toString());
} else if (name == "requiredImport"_L1) {
@@ -427,8 +427,8 @@ void TypeAnnotationReader::setVersion(const QString &versionNumber)
int minor = 0;
if (!versionNumber.isEmpty()) {
- int val;
- bool ok;
+ int val = -1;
+ bool ok = false;
if (versionNumber.contains('.'_L1)) {
val = versionNumber.split('.'_L1).constFirst().toInt(&ok);
major = ok ? val : major;
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/typeannotationreader.h b/src/plugins/qmldesigner/designercore/projectstorage/typeannotationreader.h
index 9332d5bed9..a320493ee2 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/typeannotationreader.h
+++ b/src/plugins/qmldesigner/designercore/projectstorage/typeannotationreader.h
@@ -49,7 +49,8 @@ public:
Synchronization::TypeAnnotations parseTypeAnnotation(const QString &content,
const QString &directoryPath,
- SourceId sourceId);
+ SourceId sourceId,
+ SourceId directorySourceId);
QStringList errors();
@@ -124,6 +125,7 @@ private:
json m_itemLibraryEntries;
Property m_currentProperty;
SourceId m_sourceId;
+ SourceId m_directorySourceId;
};
} // namespace QmlDesigner::Storage
diff --git a/src/plugins/qmldesigner/designercore/tracing/qmldesignertracing.cpp b/src/plugins/qmldesigner/designercore/tracing/qmldesignertracing.cpp
index d49c6156a6..b5798b713d 100644
--- a/src/plugins/qmldesigner/designercore/tracing/qmldesignertracing.cpp
+++ b/src/plugins/qmldesigner/designercore/tracing/qmldesignertracing.cpp
@@ -3,40 +3,48 @@
#include "qmldesignertracing.h"
+#include <sqlitebasestatement.h>
+
namespace QmlDesigner {
+
+using namespace NanotraceHR::Literals;
+
namespace Tracing {
namespace {
using TraceFile = NanotraceHR::TraceFile<tracingStatus()>;
-TraceFile &traceFile()
+auto &traceFile()
{
- static TraceFile traceFile{"qml_designer.json"};
- return traceFile;
+ if constexpr (std::is_same_v<Sqlite::TraceFile, TraceFile>) {
+ return Sqlite::traceFile();
+ } else {
+ static TraceFile traceFile{"tracing.json"};
+ return traceFile;
+ }
}
} // namespace
EventQueue &eventQueue()
{
- thread_local NanotraceHR::EventQueueData<NanotraceHR::StringViewTraceEvent, 10000, tracingStatus()>
- stringViewEventQueueData(traceFile());
+ thread_local NanotraceHR::EventQueue<NanotraceHR::StringViewTraceEvent, tracingStatus()>
+ stringViewEventQueue(traceFile());
- return stringViewEventQueueData;
+ return stringViewEventQueue;
}
EventQueueWithStringArguments &eventQueueWithStringArguments()
{
- thread_local NanotraceHR::
- EventQueueData<NanotraceHR::StringViewWithStringArgumentsTraceEvent, 1000, tracingStatus()>
- stringViewWithStringArgumentsEventQueueData(traceFile());
+ thread_local NanotraceHR::EventQueue<NanotraceHR::StringViewWithStringArgumentsTraceEvent, tracingStatus()>
+ stringViewWithStringArgumentsEventQueue(traceFile());
- return stringViewWithStringArgumentsEventQueueData;
+ return stringViewWithStringArgumentsEventQueue;
}
StringEventQueue &stringEventQueue()
{
- thread_local NanotraceHR::EventQueueData<NanotraceHR::StringTraceEvent, 1000, tracingStatus()> eventQueue(
+ thread_local NanotraceHR::EventQueue<NanotraceHR::StringTraceEvent, tracingStatus()> eventQueue(
traceFile());
return eventQueue;
@@ -46,7 +54,6 @@ StringEventQueue &stringEventQueue()
namespace ModelTracing {
namespace {
-using namespace NanotraceHR::Literals;
thread_local Category category_{"model"_t, Tracing::stringEventQueue(), category};
@@ -58,4 +65,27 @@ Category &category()
}
} // namespace ModelTracing
+
+namespace ProjectStorageTracing {
+
+Category &projectStorageCategory()
+{
+ thread_local Category category{"project storage"_t,
+ Tracing::eventQueueWithStringArguments(),
+ projectStorageCategory};
+
+ return category;
+}
+
+Category &projectStorageUpdaterCategory()
+{
+ thread_local Category category{"project storage updater"_t,
+ Tracing::eventQueueWithStringArguments(),
+ projectStorageCategory};
+
+ return category;
+}
+
+} // namespace ProjectStorageTracing
+
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/tracing/qmldesignertracing.h b/src/plugins/qmldesigner/designercore/tracing/qmldesignertracing.h
index 31058260d6..3a33834c70 100644
--- a/src/plugins/qmldesigner/designercore/tracing/qmldesignertracing.h
+++ b/src/plugins/qmldesigner/designercore/tracing/qmldesignertracing.h
@@ -44,4 +44,22 @@ using AsynchronousToken = Category::AsynchronousTokenType;
[[gnu::pure]] QMLDESIGNERCORE_EXPORT Category &category();
} // namespace ModelTracing
+
+namespace ProjectStorageTracing {
+constexpr NanotraceHR::Tracing projectStorageTracingStatus()
+{
+#ifdef ENABLE_PROJECT_STORAGE_TRACING
+ return NanotraceHR::Tracing::IsEnabled;
+#else
+ return NanotraceHR::Tracing::IsDisabled;
+#endif
+}
+
+using Category = NanotraceHR::StringViewWithStringArgumentsCategory<projectStorageTracingStatus()>;
+
+[[gnu::pure]] Category &projectStorageCategory();
+
+[[gnu::pure]] Category &projectStorageUpdaterCategory();
+
+} // namespace ProjectStorageTracing
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/documentmanager.cpp b/src/plugins/qmldesigner/documentmanager.cpp
index fcaac762ba..92d80680a9 100644
--- a/src/plugins/qmldesigner/documentmanager.cpp
+++ b/src/plugins/qmldesigner/documentmanager.cpp
@@ -130,7 +130,7 @@ static void openComponentSourcePropertyOfLoader(const ModelNode &modelNode)
}
Core::EditorManager::openEditor(FilePath::fromString(
- componentModelNode.metaInfo().componentFileName()),
+ ModelUtils::componentFilePath(componentModelNode)),
Utils::Id(),
Core::EditorManager::DoNotMakeVisible);
}
@@ -230,7 +230,9 @@ void DocumentManager::setCurrentDesignDocument(Core::IEditor *editor)
auto found = m_designDocuments.find(editor);
if (found == m_designDocuments.end()) {
auto &inserted = m_designDocuments[editor] = std::make_unique<DesignDocument>(
- m_projectManager.projectStorageDependencies(), m_externalDependencies);
+ editor->document()->filePath().toString(),
+ m_projectManager.projectStorageDependencies(),
+ m_externalDependencies);
m_currentDesignDocument = inserted.get();
m_currentDesignDocument->setEditor(editor);
} else {
@@ -266,6 +268,11 @@ void DocumentManager::resetPossibleImports()
}
}
+const GeneratedComponentUtils &DocumentManager::generatedComponentUtils() const
+{
+ return m_generatedComponentUtils;
+}
+
bool DocumentManager::goIntoComponent(const ModelNode &modelNode)
{
QImage image = QmlDesignerPlugin::instance()->viewManager().takeFormEditorScreenshot();
@@ -537,6 +544,13 @@ Utils::FilePath DocumentManager::currentResourcePath()
if (contentFilePath.exists())
return contentFilePath;
+ const auto project = ProjectManager::startupProject();
+ const QString baseName = project->rootProjectDirectory().baseName() + "Content";
+
+ contentFilePath = resourcePath.pathAppended(baseName);
+ if (contentFilePath.exists())
+ return contentFilePath;
+
return resourcePath;
}
diff --git a/src/plugins/qmldesigner/documentmanager.h b/src/plugins/qmldesigner/documentmanager.h
index 090630e5fe..6447694339 100644
--- a/src/plugins/qmldesigner/documentmanager.h
+++ b/src/plugins/qmldesigner/documentmanager.h
@@ -5,6 +5,8 @@
#include "qmldesigner_global.h"
+#include <generatedcomponentutils.h>
+
#include <QObject>
#include <QList>
#include <QLoggingCategory>
@@ -31,6 +33,7 @@ public:
ExternalDependenciesInterface &externalDependencies)
: m_projectManager{projectManager}
, m_externalDependencies{externalDependencies}
+ , m_generatedComponentUtils(externalDependencies)
{}
void setCurrentDesignDocument(Core::IEditor *editor);
@@ -41,6 +44,8 @@ public:
void resetPossibleImports();
+ const GeneratedComponentUtils &generatedComponentUtils() const;
+
static bool goIntoComponent(const ModelNode &modelNode);
static void goIntoComponent(const QString &fileName);
@@ -64,6 +69,7 @@ private:
QPointer<DesignDocument> m_currentDesignDocument;
QmlDesignerProjectManager &m_projectManager;
ExternalDependenciesInterface &m_externalDependencies;
+ GeneratedComponentUtils m_generatedComponentUtils;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/documentwarningwidget.cpp b/src/plugins/qmldesigner/documentwarningwidget.cpp
index 9fb2b87635..e1b8346a66 100644
--- a/src/plugins/qmldesigner/documentwarningwidget.cpp
+++ b/src/plugins/qmldesigner/documentwarningwidget.cpp
@@ -39,8 +39,7 @@ DocumentWarningWidget::DocumentWarningWidget(QWidget *parent)
m_messageLabel->setWordWrap(true);
m_messageLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
- m_ignoreWarningsCheckBox->setText(tr("Always ignore these warnings about features "
- "not supported by Qt Quick Designer."));
+ m_ignoreWarningsCheckBox->setText(tr("Turn off warnings about unsupported Qt Design Studio features."));
connect(m_navigateLabel, &QLabel::linkActivated, this, [this](const QString &link) {
if (link == QLatin1String("goToCode")) {
@@ -93,7 +92,7 @@ void DocumentWarningWidget::refreshContent()
m_ignoreWarningsCheckBox->hide();
m_continueButton->setText(tr("OK"));
} else {
- m_headerLabel->setText(tr("This QML file contains features which are not supported by Qt Quick Designer at:"));
+ m_headerLabel->setText(tr("This QML file contains features which are not supported by Qt Design Studio at:"));
{
QSignalBlocker blocker(m_ignoreWarningsCheckBox);
m_ignoreWarningsCheckBox->setChecked(!warningsEnabled());
diff --git a/src/plugins/qmldesigner/puppetenvironmentbuilder.cpp b/src/plugins/qmldesigner/puppetenvironmentbuilder.cpp
index 6e8a2b6024..7819c6b49d 100644
--- a/src/plugins/qmldesigner/puppetenvironmentbuilder.cpp
+++ b/src/plugins/qmldesigner/puppetenvironmentbuilder.cpp
@@ -126,7 +126,7 @@ void PuppetEnvironmentBuilder::addRendering() const
{
m_environment.set("QML_BAD_GUI_RENDER_LOOP", "true");
m_environment.set("QML_PUPPET_MODE", "true");
- m_environment.set("QML_DISABLE_DISK_CACHE", "true");
+ //m_environment.set("QML_DISABLE_DISK_CACHE", "true");
m_environment.set("QMLPUPPET_RENDER_EFFECTS", "true");
if (!m_environment.hasKey("QT_SCREEN_SCALE_FACTORS") && !m_environment.hasKey("QT_SCALE_FACTOR"))
m_environment.set("QT_AUTO_SCREEN_SCALE_FACTOR", "1");
diff --git a/src/plugins/qmldesigner/qmldesignerconstants.h b/src/plugins/qmldesigner/qmldesignerconstants.h
index db63d894fe..fb691097f7 100644
--- a/src/plugins/qmldesigner/qmldesignerconstants.h
+++ b/src/plugins/qmldesigner/qmldesignerconstants.h
@@ -78,15 +78,19 @@ inline constexpr char EDIT3D_SNAP_CONFIG[] = "QmlDesigner.Editor3D.SnapConfig";
inline constexpr char EDIT3D_CAMERA_SPEED_CONFIG[] = "QmlDesigner.Editor3D.CameraSpeedConfig";
inline constexpr char QML_DESIGNER_SUBFOLDER[] = "/designer/";
-inline constexpr char COMPONENT_BUNDLES_FOLDER[] = "/ComponentBundles";
+inline constexpr char COMPONENT_BUNDLES_TYPE[] = "ComponentBundles";
+inline constexpr char GENERATED_COMPONENTS_FOLDER[] = "GeneratedComponents";
inline constexpr char COMPONENT_BUNDLES_ASSET_REF_FILE[] = "_asset_ref.json";
-inline constexpr char QUICK_3D_ASSETS_FOLDER[] = "/Quick3DAssets";
+inline constexpr char OLD_QUICK_3D_ASSETS_FOLDER[] = "Quick3DAssets";
+inline constexpr char QUICK_3D_COMPONENTS_FOLDER[] = "QtQuick3D";
inline constexpr char QUICK_3D_ASSET_LIBRARY_ICON_SUFFIX[] = "_libicon";
inline constexpr char QUICK_3D_ASSET_IMPORT_DATA_NAME[] = "_importdata.json";
inline constexpr char QUICK_3D_ASSET_IMPORT_DATA_OPTIONS_KEY[] = "import_options";
inline constexpr char QUICK_3D_ASSET_IMPORT_DATA_SOURCE_KEY[] = "source_scene";
-inline constexpr char DEFAULT_ASSET_IMPORT_FOLDER[] = "/asset_imports";
-inline constexpr char DEFAULT_EFFECTS_IMPORT_FOLDER[] = "/asset_imports/Effects";
+inline constexpr char OLD_ASSET_IMPORT_FOLDER[] = "asset_imports";
+inline constexpr char OLD_EFFECTS_IMPORT_FOLDER[] = "/asset_imports/Effects";
+inline constexpr char OLD_EFFECTS_FOLDER[] = "Effects";
+inline constexpr char COMPOSED_EFFECTS_TYPE[] = "ComposedEffects";
inline constexpr char MATERIAL_LIB_ID[] = "__materialLibrary__";
inline constexpr char MIME_TYPE_ITEM_LIBRARY_INFO[]
diff --git a/src/plugins/qmldesigner/qmldesignerprojectmanager.cpp b/src/plugins/qmldesigner/qmldesignerprojectmanager.cpp
index 7e28849fbb..9602bf050f 100644
--- a/src/plugins/qmldesigner/qmldesignerprojectmanager.cpp
+++ b/src/plugins/qmldesigner/qmldesignerprojectmanager.cpp
@@ -41,6 +41,7 @@
#include <QDirIterator>
#include <QFileSystemWatcher>
+#include <QLibraryInfo>
#include <QQmlEngine>
using namespace std::chrono;
@@ -180,7 +181,7 @@ public:
pathCache.sourceId(SourcePath{project->projectDirectory().toString() + "/."}).internalId())}
{}
Sqlite::Database database;
- ProjectStorage<Sqlite::Database> storage{database, database.isInitialized()};
+ ProjectStorage storage{database, database.isInitialized()};
PathCacheType pathCache{storage};
FileSystem fileSystem{pathCache};
FileStatusCache fileStatusCache{fileSystem};
@@ -281,7 +282,7 @@ AsynchronousImageCache &QmlDesignerProjectManager::asynchronousImageCache()
}
namespace {
-[[maybe_unused]] ProjectStorage<Sqlite::Database> *dummyProjectStorage()
+[[maybe_unused]] ProjectStorage *dummyProjectStorage()
{
return nullptr;
}
@@ -374,6 +375,10 @@ void collectQmldirPaths(const QString &path, QStringList &qmldirPaths)
{
QDirIterator dirIterator{path, QDir::Dirs | QDir::NoDotAndDotDot, QDirIterator::Subdirectories};
+ QString rootQmldirPath = path + "/qmldir";
+ if (!skipPath(path) && QFileInfo::exists(rootQmldirPath))
+ qmldirPaths.push_back(path);
+
while (dirIterator.hasNext()) {
auto directoryPath = dirIterator.next();
@@ -401,17 +406,16 @@ void collectQmldirPaths(const QString &path, QStringList &qmldirPaths)
collectQmldirPaths(qmlPath(target).toString(), qmldirPaths);
}
-[[maybe_unused]] void qtQmldirPathsForLiteDesigner(::ProjectExplorer::Target *target,
- QStringList &qmldirPaths)
+[[maybe_unused]] void qtQmldirPathsForLiteDesigner(QStringList &qmldirPaths)
{
if constexpr (useProjectStorage()) {
- auto qmlRootPath = qmlPath(target).toString();
+ auto qmlRootPath = QLibraryInfo::path(QLibraryInfo::QmlImportsPath);
collectQmldirPaths(qmlRootPath + "/QtQml", qmldirPaths);
collectQmldirPaths(qmlRootPath + "/QtQuick", qmldirPaths);
}
}
-QStringList directories(::ProjectExplorer::Target *target)
+[[maybe_unused]] QStringList directories(::ProjectExplorer::Target *target)
{
if (!target)
return {};
@@ -419,12 +423,8 @@ QStringList directories(::ProjectExplorer::Target *target)
QStringList qmldirPaths;
qmldirPaths.reserve(100);
- if constexpr (isUsingQmlDesignerLite()) {
- qtQmldirPathsForLiteDesigner(target, qmldirPaths);
- } else {
- qtQmldirPaths(target, qmldirPaths);
- projectQmldirPaths(target, qmldirPaths);
- }
+ qtQmldirPaths(target, qmldirPaths);
+ projectQmldirPaths(target, qmldirPaths);
std::sort(qmldirPaths.begin(), qmldirPaths.end());
qmldirPaths.erase(std::unique(qmldirPaths.begin(), qmldirPaths.end()), qmldirPaths.end());
@@ -432,7 +432,20 @@ QStringList directories(::ProjectExplorer::Target *target)
return qmldirPaths;
}
-QStringList qmlTypes(::ProjectExplorer::Target *target)
+[[maybe_unused]] QStringList directoriesForLiteDesigner()
+{
+ QStringList qmldirPaths;
+ qmldirPaths.reserve(100);
+
+ qtQmldirPathsForLiteDesigner(qmldirPaths);
+
+ std::sort(qmldirPaths.begin(), qmldirPaths.end());
+ qmldirPaths.erase(std::unique(qmldirPaths.begin(), qmldirPaths.end()), qmldirPaths.end());
+
+ return qmldirPaths;
+}
+
+[[maybe_unused]] QStringList qmlTypes(::ProjectExplorer::Target *target)
{
if (!target)
return {};
@@ -440,10 +453,26 @@ QStringList qmlTypes(::ProjectExplorer::Target *target)
QStringList qmldirPaths;
qmldirPaths.reserve(2);
- const QString installDirectory = qmlPath(target).toString();
+ const QString qmlRootPath = qmlPath(target).toString();
- qmldirPaths.append(installDirectory + "/builtins.qmltypes");
- qmldirPaths.append(installDirectory + "/jsroot.qmltypes");
+ qmldirPaths.append(qmlRootPath + "/builtins.qmltypes");
+ qmldirPaths.append(qmlRootPath + "/jsroot.qmltypes");
+
+ qmldirPaths.append(
+ Core::ICore::resourcePath("qmldesigner/projectstorage/fake.qmltypes").toString());
+
+ return qmldirPaths;
+}
+
+[[maybe_unused]] QStringList qmlTypesForLiteDesigner()
+{
+ QStringList qmldirPaths;
+ qmldirPaths.reserve(2);
+
+ const auto qmlRootPath = QLibraryInfo::path(QLibraryInfo::QmlImportsPath);
+
+ qmldirPaths.append(qmlRootPath + "/builtins.qmltypes");
+ qmldirPaths.append(qmlRootPath + "/jsroot.qmltypes");
qmldirPaths.append(
Core::ICore::resourcePath("qmldesigner/projectstorage/fake.qmltypes").toString());
@@ -461,6 +490,11 @@ QString propertyEditorResourcesPath()
return Core::ICore::resourcePath("qmldesigner/propertyEditorQmlSources").toString();
}
+QString qtCreatorItemLibraryPath()
+{
+ return Core::ICore::resourcePath("qmldesigner/itemLibrary").toString();
+}
+
} // namespace
void QmlDesignerProjectManager::projectAdded(::ProjectExplorer::Project *project)
@@ -594,9 +628,17 @@ void QmlDesignerProjectManager::update()
if (!m_projectData || !m_projectData->projectStorageData)
return;
- m_projectData->projectStorageData->updater.update(directories(m_projectData->activeTarget),
- qmlTypes(m_projectData->activeTarget),
- propertyEditorResourcesPath());
+ if constexpr (isUsingQmlDesignerLite()) {
+ m_projectData->projectStorageData->updater.update(directoriesForLiteDesigner(),
+ qmlTypesForLiteDesigner(),
+ propertyEditorResourcesPath(),
+ {qtCreatorItemLibraryPath()});
+ } else {
+ m_projectData->projectStorageData->updater.update(directories(m_projectData->activeTarget),
+ qmlTypes(m_projectData->activeTarget),
+ propertyEditorResourcesPath(),
+ {qtCreatorItemLibraryPath()});
+ }
}
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/qtquickplugin/quick.metainfo b/src/plugins/qmldesigner/qtquickplugin/quick.metainfo
index 3f3cdb7910..46cb42b60d 100644
--- a/src/plugins/qmldesigner/qtquickplugin/quick.metainfo
+++ b/src/plugins/qmldesigner/qtquickplugin/quick.metainfo
@@ -374,7 +374,6 @@ MetaInfo {
name: "Keyframe"
category: "none"
version: "1.0"
- requiredImport: "none"
}
}
@@ -386,7 +385,6 @@ MetaInfo {
name: "KeyframeGroup"
category: "none"
version: "1.0"
- requiredImport: "none"
}
}
diff --git a/src/plugins/qmldesigner/settingspage.cpp b/src/plugins/qmldesigner/settingspage.cpp
index 344e2700d9..17c75a0285 100644
--- a/src/plugins/qmldesigner/settingspage.cpp
+++ b/src/plugins/qmldesigner/settingspage.cpp
@@ -135,7 +135,7 @@ SettingsPageWidget::SettingsPageWidget(ExternalDependencies &externalDependencie
m_useDefaultPuppetRadioButton = new QRadioButton(tr("Use fallback QML emulation layer"));
m_useDefaultPuppetRadioButton->setToolTip(
- tr("If you select this radio button, Qt Quick Designer always uses the "
+ tr("If you select this radio button, Qt Design Studio always uses the "
"QML emulation layer (QML Puppet) located at the following path."));
m_useDefaultPuppetRadioButton->setChecked(true);
@@ -167,7 +167,7 @@ SettingsPageWidget::SettingsPageWidget(ExternalDependencies &externalDependencie
m_designerWarningsCheckBox = new QCheckBox(
tr("Warn about unsupported features in .ui.qml files"));
m_designerWarningsCheckBox->setToolTip(
- tr("Warns about QML features that are not properly supported by the Qt Quick Designer."));
+ tr("Warns about QML features that are not properly supported by the Qt Design Studio."));
m_designerWarningsUiQmlfiles = new QCheckBox(
tr("Warn about using .qml files instead of .ui.qml files"));
diff --git a/src/plugins/qmldesigner/utils/asset.cpp b/src/plugins/qmldesigner/utils/asset.cpp
index 2984a4d890..ec1e4312e4 100644
--- a/src/plugins/qmldesigner/utils/asset.cpp
+++ b/src/plugins/qmldesigner/utils/asset.cpp
@@ -1,15 +1,19 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-#include <QImageReader>
-
#include "asset.h"
+#include "hdrimage.h"
+
+#include <QImageReader>
+#include <QPixmap>
+
namespace QmlDesigner {
Asset::Asset(const QString &filePath)
: m_filePath(filePath)
{
+ m_fileName = filePath.split('/').last();
const QStringList split = filePath.split('.');
if (split.size() > 1)
m_suffix = "*." + split.last().toLower();
@@ -105,6 +109,19 @@ bool Asset::isSupported(const QString &path)
return supportedSuffixes().contains(path);
}
+QPixmap Asset::pixmap(const QSize &size) const
+{
+ if (!isImage() && !isHdrFile())
+ return {};
+
+ QPixmap icon = isHdrFile() ? HdrImage{m_filePath}.toPixmap() : QPixmap{m_filePath};
+
+ if (size.isValid())
+ icon = icon.scaled(size, Qt::KeepAspectRatio);
+
+ return icon;
+}
+
Asset::Type Asset::type() const
{
return m_type;
@@ -175,6 +192,11 @@ const QString Asset::id() const
return m_filePath;
}
+const QString Asset::fileName() const
+{
+ return m_fileName;
+}
+
bool Asset::isSupported() const
{
return m_type != Asset::Type::Unknown;
diff --git a/src/plugins/qmldesigner/utils/asset.h b/src/plugins/qmldesigner/utils/asset.h
index cb09f3a5ee..a5c5899f34 100644
--- a/src/plugins/qmldesigner/utils/asset.h
+++ b/src/plugins/qmldesigner/utils/asset.h
@@ -3,8 +3,11 @@
#pragma once
+#include <QSize>
#include <QString>
+QT_FORWARD_DECLARE_CLASS(QPixmap)
+
namespace QmlDesigner {
class Asset
@@ -37,7 +40,9 @@ public:
const QString suffix() const;
const QString id() const;
+ const QString fileName() const;
bool hasSuffix() const;
+ QPixmap pixmap(const QSize &size = {}) const;
Type type() const;
bool isImage() const;
@@ -58,6 +63,7 @@ private:
void resolveType();
QString m_filePath;
+ QString m_fileName;
QString m_suffix;
Type m_type = Unknown;
};
diff --git a/src/plugins/qmldesigner/utils/imageutils.cpp b/src/plugins/qmldesigner/utils/imageutils.cpp
index 8fa3131cd3..42df6184b9 100644
--- a/src/plugins/qmldesigner/utils/imageutils.cpp
+++ b/src/plugins/qmldesigner/utils/imageutils.cpp
@@ -11,7 +11,7 @@
namespace QmlDesigner {
-QString ImageUtils::imageInfo(const QSize &dimensions, qint64 sizeInBytes)
+QString ImageUtils::imageInfoString(const QSize &dimensions, qint64 sizeInBytes)
{
return QLatin1String("%1 x %2\n%3")
.arg(QString::number(dimensions.width()),
@@ -20,7 +20,7 @@ QString ImageUtils::imageInfo(const QSize &dimensions, qint64 sizeInBytes)
sizeInBytes, 2, QLocale::DataSizeTraditionalFormat));
}
-QString QmlDesigner::ImageUtils::imageInfo(const QString &path)
+QPair<QSize, qint64> QmlDesigner::ImageUtils::imageInfo(const QString &path)
{
QFileInfo info(path);
if (!info.exists())
@@ -52,7 +52,13 @@ QString QmlDesigner::ImageUtils::imageInfo(const QString &path)
if (width <= 0 || height <= 0)
return {};
- return imageInfo(QSize(width, height), info.size());
+ return {QSize(width, height), info.size()};
+}
+
+QString ImageUtils::imageInfoString(const QString &path)
+{
+ QPair<QSize, qint64> info = imageInfo(path);
+ return imageInfoString(info.first, info.second);
}
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/utils/imageutils.h b/src/plugins/qmldesigner/utils/imageutils.h
index a4036614a3..dae64423bb 100644
--- a/src/plugins/qmldesigner/utils/imageutils.h
+++ b/src/plugins/qmldesigner/utils/imageutils.h
@@ -12,8 +12,9 @@ class ImageUtils
public:
ImageUtils();
- static QString imageInfo(const QSize &dimensions, qint64 sizeInBytes);
- static QString imageInfo(const QString &path);
+ static QPair<QSize, qint64> imageInfo(const QString &path);
+ static QString imageInfoString(const QString &path);
+ static QString imageInfoString(const QSize &dimensions, qint64 sizeInBytes);
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesignerbase/utils/designerpaths.cpp b/src/plugins/qmldesignerbase/utils/designerpaths.cpp
index da4ce8ce08..f938c58e04 100644
--- a/src/plugins/qmldesignerbase/utils/designerpaths.cpp
+++ b/src/plugins/qmldesignerbase/utils/designerpaths.cpp
@@ -20,9 +20,7 @@ Utils::FilePath defaultExamplesPath()
Utils::FilePath defaultBundlesPath()
{
- QStandardPaths::StandardLocation location = Utils::HostOsInfo::isMacHost()
- ? QStandardPaths::HomeLocation
- : QStandardPaths::DocumentsLocation;
+ QStandardPaths::StandardLocation location = QStandardPaths::DocumentsLocation;
return Utils::FilePath::fromString(QStandardPaths::writableLocation(location))
.pathAppended("QtDesignStudio/bundles");
diff --git a/src/plugins/qmlpreview/CMakeLists.txt b/src/plugins/qmlpreview/CMakeLists.txt
index 4c1889143a..440b407b70 100644
--- a/src/plugins/qmlpreview/CMakeLists.txt
+++ b/src/plugins/qmlpreview/CMakeLists.txt
@@ -4,7 +4,7 @@ add_qtc_plugin(QmlPreview
DEPENDS QmlJS Qt::QmlPrivate
PLUGIN_DEPENDS
Core ProjectExplorer QmlJSTools QtSupport
- ResourceEditor QmlProjectManager
+ ResourceEditor QmlProjectManager TextEditor
SOURCES
qmlpreviewclient.cpp qmlpreviewclient.h
qmlpreviewconnectionmanager.cpp qmlpreviewconnectionmanager.h
diff --git a/src/plugins/qmlpreview/qmlpreviewplugin.cpp b/src/plugins/qmlpreview/qmlpreviewplugin.cpp
index 31638f7662..70f905448e 100644
--- a/src/plugins/qmlpreview/qmlpreviewplugin.cpp
+++ b/src/plugins/qmlpreview/qmlpreviewplugin.cpp
@@ -166,12 +166,8 @@ QmlPreviewPluginPrivate::QmlPreviewPluginPrivate(QmlPreviewPlugin *parent)
runPreviewAction->setEnabled(ProjectManager::startupProject() != nullptr);
connect(ProjectManager::instance(), &ProjectManager::startupProjectChanged, runPreviewAction,
&QAction::setEnabled);
- connect(runPreviewAction, &QAction::triggered, this, [runPreviewAction, this] {
+ connect(runPreviewAction, &QAction::triggered, this, [&, runPreviewAction] {
runPreviewAction->setEnabled(false);
- attachToEditorManager();
- setDirty();
- onEditorChanged(Core::EditorManager::currentEditor());
-
if (auto multiLanguageAspect = QmlProjectManager::QmlMultiLanguageAspect::current())
m_localeIsoCode = multiLanguageAspect->currentLocale();
bool skipDeploy = false;
@@ -425,7 +421,7 @@ void QmlPreviewPluginPrivate::onEditorAboutToClose(Core::IEditor *editor)
void QmlPreviewPluginPrivate::setDirty()
{
m_dirty = true;
- QTimer::singleShot(1000, this, [this](){
+ QTimer::singleShot(1000, this, [&](){
if (m_dirty && m_lastEditor) {
m_dirty = false;
checkEditor();
@@ -435,6 +431,10 @@ void QmlPreviewPluginPrivate::setDirty()
void QmlPreviewPlugin::addPreview(RunControl *preview)
{
+ d->attachToEditorManager();
+ d->setDirty();
+ d->onEditorChanged(Core::EditorManager::currentEditor());
+
d->m_runningPreviews.append(preview);
emit runningPreviewsChanged(d->m_runningPreviews);
}
diff --git a/src/plugins/qmlprojectmanager/CMakeLists.txt b/src/plugins/qmlprojectmanager/CMakeLists.txt
index ab96a5f7df..68bb545011 100644
--- a/src/plugins/qmlprojectmanager/CMakeLists.txt
+++ b/src/plugins/qmlprojectmanager/CMakeLists.txt
@@ -42,14 +42,10 @@ extend_qtc_plugin(QmlProjectManager
PUBLIC_INCLUDES ${CMAKE_CURRENT_LIST_DIR}/cmakegen
SOURCES_PREFIX ${CMAKE_CURRENT_LIST_DIR}/cmakegen
SOURCES
- checkablefiletreeitem.cpp checkablefiletreeitem.h
- cmakegeneratordialog.cpp cmakegeneratordialog.h
- cmakegeneratordialogtreemodel.cpp cmakegeneratordialogtreemodel.h
- cmakeprojectconverter.cpp cmakeprojectconverter.h
- cmakeprojectconverterdialog.cpp cmakeprojectconverterdialog.h
- generatecmakelists.cpp generatecmakelists.h
- generatecmakelistsconstants.h
cmakegenerator.cpp cmakegenerator.h
+ cmakewriter.cpp cmakewriter.h
+ cmakewriterv0.cpp cmakewriterv0.h
+ cmakewriterv1.cpp cmakewriterv1.h
boilerplate.qrc
)
diff --git a/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.cpp b/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.cpp
index a0b8263900..00e501d6f8 100644
--- a/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.cpp
+++ b/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.cpp
@@ -93,6 +93,7 @@ QmlBuildSystem::QmlBuildSystem(Target *target)
connect(target->project(), &Project::projectFileIsDirty, this, [this] {
refresh(RefreshOptions::Project);
m_cmakeGen->initialize(qmlProject());
+ m_cmakeGen->updateMenuAction();
updateMcuBuildStep(project()->activeTarget(), qtForMCUs());
});
@@ -501,6 +502,17 @@ void QmlBuildSystem::setPrimaryLanguage(QString language)
m_projectItem->setPrimaryLanguage(language);
}
+bool QmlBuildSystem::enableCMakeGeneration() const
+{
+ return m_projectItem->enableCMakeGeneration();
+}
+
+void QmlBuildSystem::setEnableCMakeGeneration(bool enable)
+{
+ if (enable != enableCMakeGeneration())
+ m_projectItem->setEnableCMakeGeneration(enable);
+}
+
void QmlBuildSystem::refreshFiles(const QSet<QString> & /*added*/, const QSet<QString> &removed)
{
if (m_blockFilesUpdate) {
diff --git a/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.h b/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.h
index 524af5cd1b..e3f9b99adb 100644
--- a/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.h
+++ b/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.h
@@ -83,6 +83,9 @@ public:
QString primaryLanguage() const;
void setPrimaryLanguage(QString language);
+ bool enableCMakeGeneration() const;
+ void setEnableCMakeGeneration(bool enable);
+
bool forceFreeType() const;
bool widgetApp() const;
diff --git a/src/plugins/qmlprojectmanager/cmakegen/boilerplate.qrc b/src/plugins/qmlprojectmanager/cmakegen/boilerplate.qrc
index 10fab59838..4960324ab7 100644
--- a/src/plugins/qmlprojectmanager/cmakegen/boilerplate.qrc
+++ b/src/plugins/qmlprojectmanager/cmakegen/boilerplate.qrc
@@ -1,15 +1,15 @@
<RCC>
- <qresource prefix="/boilerplatetemplates">
- <file>gencmakeroot.tpl</file>
- <file>gencmakemodule.tpl</file>
- <file>gencmakeheadercomponents.tpl</file>
- <file>qmlprojectmaincpp.tpl</file>
- <file>qmlprojectmaincppheader.tpl</file>
- <file>qmlprojectenvheader.tpl</file>
- <file>qmlprojectmodules.tpl</file>
- <file>qmlprojectmaincmakelists.tpl</file>
- <file>qmlprojectmodulecmakelists.tpl</file>
- <file>qmlprojectmainqml.tpl</file>
- <file>qmlprojectappmainqml.tpl</file>
+ <qresource prefix="/templates">
+ <file alias="cmakeroot_v0">templates/cmakeroot_v0.tpl</file>
+ <file alias="cmakeroot_v1">templates/cmakeroot_v1.tpl</file>
+ <file alias="main_cpp_v0">templates/main_cpp_v0.tpl</file>
+ <file alias="main_cpp_v1">templates/main_cpp_v1.tpl</file>
+ <file alias="cmakemodule_v1">templates/cmakemodule_v1.tpl</file>
+ <file alias="insight">templates/insight.tpl</file>
+ <file alias="qmlcomponents">templates/qmlcomponents.tpl</file>
+ <file alias="environment_h">templates/environment_h.tpl</file>
+ <file alias="import_qml_components_h">templates/import_qml_components_h.tpl</file>
+ <file alias="qtquickcontrols_conf">templates/qtquickcontrols2_conf.tpl</file>
+ <file alias="cmake_shared">templates/cmakelists_txt_shared.tpl</file>
</qresource>
</RCC>
diff --git a/src/plugins/qmlprojectmanager/cmakegen/checkablefiletreeitem.cpp b/src/plugins/qmlprojectmanager/cmakegen/checkablefiletreeitem.cpp
deleted file mode 100644
index 9eb45d9150..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/checkablefiletreeitem.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#include "checkablefiletreeitem.h"
-
-using namespace Utils;
-
-namespace QmlProjectManager {
-
-CheckableFileTreeItem::CheckableFileTreeItem(const FilePath &filePath)
- :QStandardItem(filePath.toString())
-{
- Qt::ItemFlags itemFlags = flags();
- if (!isDir())
- itemFlags |= Qt::ItemIsUserCheckable;
- itemFlags &= ~(Qt::ItemIsEditable | Qt::ItemIsSelectable);
- setFlags(itemFlags);
-}
-
-const FilePath CheckableFileTreeItem::toFilePath() const
-{
- return FilePath::fromString(text());
-}
-
-bool CheckableFileTreeItem::isFile() const
-{
- return FilePath::fromString(text()).isFile();
-}
-
-bool CheckableFileTreeItem::isDir() const
-{
- return FilePath::fromString(text()).isDir();
-}
-
-void CheckableFileTreeItem::setChecked(bool checked)
-{
- this->checked = checked;
-}
-
-bool CheckableFileTreeItem::isChecked() const
-{
- return this->checked;
-}
-
-} //QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/cmakegen/checkablefiletreeitem.h b/src/plugins/qmlprojectmanager/cmakegen/checkablefiletreeitem.h
deleted file mode 100644
index c3c5145301..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/checkablefiletreeitem.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#ifndef CHECKABLEFILETREEITEM_H
-#define CHECKABLEFILETREEITEM_H
-
-#include <utils/fileutils.h>
-
-#include <QStandardItem>
-
-namespace QmlProjectManager {
-
-class CheckableFileTreeItem : public QStandardItem
-{
-public:
- explicit CheckableFileTreeItem(const Utils::FilePath &text = Utils::FilePath());
-
- const Utils::FilePath toFilePath() const;
- bool isFile() const;
- bool isDir() const;
-
- bool isChecked() const;
- void setChecked(bool checked);
-
-private:
- bool checked;
-};
-
-} //QmlProjectManager
-
-#endif // CHECKABLEFILETREEITEM_H
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakegenerator.cpp b/src/plugins/qmlprojectmanager/cmakegen/cmakegenerator.cpp
index 736ac04ec6..659c544ebd 100644
--- a/src/plugins/qmlprojectmanager/cmakegen/cmakegenerator.cpp
+++ b/src/plugins/qmlprojectmanager/cmakegen/cmakegenerator.cpp
@@ -2,13 +2,23 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "cmakegenerator.h"
-#include "generatecmakelistsconstants.h"
+
+#include "qmlprojectmanager/qmlproject.h"
+#include "qmlprojectmanager/qmlprojectconstants.h"
+#include "qmlprojectmanager/qmlprojectmanagertr.h"
#include "projectexplorer/projectmanager.h"
#include "projectexplorer/projectnodes.h"
-#include "qmlprojectmanager/qmlproject.h"
+#include "projectexplorer/taskhub.h"
+#include "utils/filenamevalidatinglineedit.h"
+
+#include "coreplugin/actionmanager/actionmanager.h"
+#include "coreplugin/actionmanager/actioncontainer.h"
+
+#include <QDirIterator>
#include <QRegularExpression>
+#include <QMenu>
#include <set>
@@ -16,30 +26,64 @@ namespace QmlProjectManager {
namespace GenerateCmake {
-const char TEMPLATE_CMAKELISTS_ROOT[] = ":/boilerplatetemplates/gencmakeroot.tpl";
-const char TEMPLATE_CMAKELISTS_MODULE[] = ":/boilerplatetemplates/gencmakemodule.tpl";
+void CMakeGenerator::createMenuAction(QObject *parent)
+{
+ Core::ActionContainer *fileMenu = Core::ActionManager::actionContainer(
+ Core::Constants::M_FILE);
+ Core::ActionContainer *exportMenu = Core::ActionManager::createMenu(
+ QmlProjectManager::Constants::EXPORT_MENU);
+
+ exportMenu->menu()->setTitle(Tr::tr("Export Project"));
+ exportMenu->appendGroup(QmlProjectManager::Constants::G_EXPORT_GENERATE);
+ fileMenu->addMenu(exportMenu, Core::Constants::G_FILE_EXPORT);
+
+ auto action = new QAction(Tr::tr("Enable Automatic CMake Generation"), parent);
+ action->setEnabled(false);
+ action->setCheckable(true);
+
+ Core::Command *cmd = Core::ActionManager::registerAction(action, "QmlProject.EnableCMakeGeneration");
+ exportMenu->addAction(cmd, QmlProjectManager::Constants::G_EXPORT_GENERATE);
+
+ QObject::connect(
+ ProjectExplorer::ProjectManager::instance(),
+ &ProjectExplorer::ProjectManager::startupProjectChanged,
+ [action]() {
+ if (auto buildSystem = QmlBuildSystem::getStartupBuildSystem()) {
+ action->setEnabled(!buildSystem->qtForMCUs());
+ action->setChecked(buildSystem->enableCMakeGeneration());
+ }
+ }
+ );
+
+ QObject::connect(action, &QAction::toggled, [](bool checked) {
+ if (auto buildSystem = QmlBuildSystem::getStartupBuildSystem())
+ buildSystem->setEnableCMakeGeneration(checked);
+ });
+}
+
+void CMakeGenerator::logIssue(ProjectExplorer::Task::TaskType type, const QString &text, const Utils::FilePath &file)
+{
+ ProjectExplorer::BuildSystemTask task(type, text, file);
+ ProjectExplorer::TaskHub::addTask(task);
+ ProjectExplorer::TaskHub::requestPopup();
+}
-const char TEMPLATE_SOURCE_MAIN[] = ":/boilerplatetemplates/qmlprojectmaincpp.tpl";
-const char TEMPLATE_HEADER_IMPORT_COMPS[] = ":/boilerplatetemplates/gencmakeheadercomponents.tpl";
-const char TEMPLATE_HEADER_IMPORT_PLUGINS[] = ":/boilerplatetemplates/qmlprojectmaincppheader.tpl";
-const char TEMPLATE_HEADER_ENVIRONMENT[] = ":/boilerplatetemplates/qmlprojectenvheader.tpl";
+void CMakeGenerator::updateMenuAction()
+{
+ QTC_ASSERT(buildSystem(), return);
-const char DO_NOT_EDIT_FILE_COMMENT[]
- = "### This file is automatically generated by Qt Design Studio.\n"
- "### Do not change\n\n";
+ Core::Command *cmd = Core::ActionManager::command("QmlProject.EnableCMakeGeneration");
+ if (!cmd)
+ return;
-const char TEMPLATE_BIG_RESOURCES[] = R"(
-qt6_add_resources(%1 %2
- BIG_RESOURCES
- PREFIX "%3"
- VERSION 1.0
- FILES %4
-))";
+ QAction *action = cmd->action();
+ if (!action)
+ return;
-const char TEMPLATE_LINK_LIBRARIES[] = R"(
-target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE
-%3
-))";
+ bool enabled = buildSystem()->enableCMakeGeneration();
+ if (enabled != action->isChecked())
+ action->setChecked(enabled);
+}
CMakeGenerator::CMakeGenerator(QmlBuildSystem *bs, QObject *parent)
: QObject(parent)
@@ -47,6 +91,44 @@ CMakeGenerator::CMakeGenerator(QmlBuildSystem *bs, QObject *parent)
, m_buildSystem(bs)
{}
+const QmlProject *CMakeGenerator::qmlProject() const
+{
+ if (m_buildSystem)
+ return m_buildSystem->qmlProject();
+ return nullptr;
+}
+
+const QmlBuildSystem *CMakeGenerator::buildSystem() const
+{
+ return m_buildSystem;
+}
+
+bool CMakeGenerator::findFile(const Utils::FilePath& file) const
+{
+ return findFile(m_root, file);
+}
+
+bool CMakeGenerator::isRootNode(const NodePtr &node) const
+{
+ return node->name == "Main";
+}
+
+bool CMakeGenerator::hasChildModule(const NodePtr &node) const
+{
+ for (const NodePtr &child : node->subdirs) {
+ if (child->type == Node::Type::Module)
+ return true;
+ if (hasChildModule(child))
+ return true;
+ }
+ return false;
+}
+
+QString CMakeGenerator::projectName() const
+{
+ return m_projectName;
+}
+
void CMakeGenerator::setEnabled(bool enabled)
{
m_enabled = enabled;
@@ -57,11 +139,11 @@ void CMakeGenerator::initialize(QmlProject *project)
if (!m_enabled)
return;
- m_srcs.clear();
m_moduleNames.clear();
+ m_writer = CMakeWriter::create(this);
m_root = std::make_shared<Node>();
- m_root->module = true;
+ m_root->type = Node::Type::App;
m_root->uri = QString("Main");
m_root->name = QString("Main");
m_root->dir = project->rootProjectDirectory();
@@ -73,7 +155,9 @@ void CMakeGenerator::initialize(QmlProject *project)
parseSourceTree();
createCMakeFiles(m_root);
- createEntryPoints(m_root);
+ createSourceFiles();
+
+ compareWithFileSystem(m_root);
}
void CMakeGenerator::update(const QSet<QString> &added, const QSet<QString> &removed)
@@ -81,304 +165,96 @@ void CMakeGenerator::update(const QSet<QString> &added, const QSet<QString> &rem
if (!m_enabled)
return;
+ QTC_ASSERT(m_writer, return);
+
std::set<NodePtr> dirtyModules;
for (const QString &add : added) {
const Utils::FilePath path = Utils::FilePath::fromString(add);
- if (auto node = findOrCreateNode(m_root, path)) {
+ if (auto node = findOrCreateNode(m_root, path.parentDir())) {
insertFile(node, path);
if (auto module = findModuleFor(node))
dirtyModules.insert(module);
} else {
- qDebug() << "CmakeGen: Failed to find Folder node " << path;
+ QString text("Failed to find Folder for file");
+ logIssue(ProjectExplorer::Task::Error, text, path);
}
}
for (const QString &remove : removed) {
const Utils::FilePath path = Utils::FilePath::fromString(remove);
- if (auto node = findNode(m_root, path)) {
+ if (auto node = findNode(m_root, path.parentDir())) {
removeFile(node, path);
if (auto module = findModuleFor(node))
dirtyModules.insert(module);
}
}
- for (auto module : dirtyModules)
- createModuleCMakeFile(module);
-}
-
-std::vector<Utils::FilePath> CMakeGenerator::files(const NodePtr &node,
- const FileGetter &getter) const
-{
- std::vector<Utils::FilePath> out = getter(node);
- for (const CMakeGenerator::NodePtr &child : node->subdirs) {
- if (child->module)
- continue;
-
- auto childFiles = files(child, getter);
- out.insert(out.end(), childFiles.begin(), childFiles.end());
- }
- return out;
-}
-
-std::vector<Utils::FilePath> CMakeGenerator::qmlFiles(const NodePtr &node) const
-{
- return files(node, [](const NodePtr &n) { return n->files; });
+ createCMakeFiles(m_root);
+ createSourceFiles();
}
-std::vector<Utils::FilePath> CMakeGenerator::singletons(const NodePtr &node) const
+bool CMakeGenerator::isQml(const Utils::FilePath &path) const
{
- return files(node, [](const NodePtr &n) { return n->singletons; });
+ const QString suffix = path.suffix();
+ return suffix == "qml" || suffix == "ui.qml";
}
-std::vector<Utils::FilePath> CMakeGenerator::resources(const NodePtr &node) const
+bool CMakeGenerator::isResource(const Utils::FilePath &path) const
{
- return files(node, [](const NodePtr &n) { return n->resources; });
+ static const QStringList suffixes = {
+ "json", "mesh", "dae", "qad", "hints", "png", "hdr", "ttf", "jpg",
+ "jpeg", "js", "qsb", "frag", "frag.qsb", "vert", "vert.qsb", "svg",
+ "ktx", "bmp", "gif", "webp", "tiff"};
+ return suffixes.contains(path.suffix(), Qt::CaseInsensitive);
}
-std::vector<Utils::FilePath> CMakeGenerator::sources(const NodePtr &node) const
+bool CMakeGenerator::ignoreFile(const Utils::FilePath &path) const
{
- return files(node, [](const NodePtr &n) { return n->sources; });
+ static const QStringList suffixes = { "hints" };
+ return suffixes.contains(path.suffix(), Qt::CaseInsensitive);
}
void CMakeGenerator::createCMakeFiles(const NodePtr &node) const
{
+ QTC_ASSERT(m_writer, return);
+
if (isRootNode(node))
- createMainCMakeFile(node);
+ m_writer->writeRootCMakeFile(node);
- if (node->module || hasChildModule(node))
- createModuleCMakeFile(node);
+ if (node->type == Node::Type::Module || (hasChildModule(node)))
+ m_writer->writeModuleCMakeFile(node, m_root);
for (const NodePtr &n : node->subdirs)
createCMakeFiles(n);
}
-void CMakeGenerator::createMainCMakeFile(const NodePtr &node) const
-{
- const QString appName = m_projectName + "App";
-
- const QString qtcontrolsConfFile = makeEnvironmentVariable(Constants::ENV_VARIABLE_CONTROLCONF);
-
- QString fileSection = "";
- if (!qtcontrolsConfFile.isEmpty())
- fileSection = QString(" FILES\n %1").arg(qtcontrolsConfFile);
-
- const QString fileTemplate = readTemplate(TEMPLATE_CMAKELISTS_ROOT);
- const QString fileContent = fileTemplate.arg(appName, m_srcs.join(" "), fileSection);
-
- const Utils::FilePath file = node->dir.pathAppended("CMakeLists.txt");
- writeFile(file, fileContent);
-}
-
-void CMakeGenerator::createModuleCMakeFile(const NodePtr &node) const
+void CMakeGenerator::createSourceFiles() const
{
- Utils::FilePath writeToFile = node->dir.pathAppended("CMakeLists.txt");
+ QTC_ASSERT(m_writer, return);
- if (!node->module && hasChildModule(node)) {
- QString content(DO_NOT_EDIT_FILE_COMMENT);
- content.append(makeSubdirectoriesBlock(node));
- writeFile(writeToFile, content);
- return;
- }
-
- QString templatePrefix;
- templatePrefix.append(makeSubdirectoriesBlock(node));
- templatePrefix.append(makeSingletonBlock(node));
-
- auto [resources, bigResources] = makeResourcesBlocks(node);
- QString moduleContent;
- moduleContent.append(makeQmlFilesBlock(node));
- moduleContent.append(resources);
-
- QString templatePostfix;
- templatePostfix.append(bigResources);
-
- if (isRootNode(node)) {
- writeToFile = node->dir.pathAppended("qmlModules");
- QString pluginNames;
- for (const QString &moduleName : m_moduleNames)
- pluginNames.append(" " + moduleName + "plugin\n");
-
- templatePostfix += QString::fromUtf8(TEMPLATE_LINK_LIBRARIES, -1).arg(pluginNames);
+ NodePtr sourceNode = {};
+ for (const NodePtr &child : m_root->subdirs) {
+ if (child->name == m_writer->sourceDirName())
+ sourceNode = child;
}
- const QString fileTemplate = readTemplate(TEMPLATE_CMAKELISTS_MODULE);
- const QString fileContent
- = fileTemplate.arg(node->name, node->uri, templatePrefix, moduleContent, templatePostfix);
-
- writeFile(writeToFile, fileContent);
-}
-
-void CMakeGenerator::createEntryPoints(const NodePtr &node) const
-{
- createMainCppFile(node);
-}
-
-void CMakeGenerator::createMainCppFile(const NodePtr &node) const
-{
- const Utils::FilePath srcDir = node->dir.pathAppended(Constants::DIRNAME_CPP);
- if (!srcDir.exists()) {
- srcDir.createDir();
-
- const Utils::FilePath componentsHeaderPath = srcDir.pathAppended(
- "import_qml_components_plugins.h");
-
- const QString componentsHeaderContent = readTemplate(TEMPLATE_HEADER_IMPORT_COMPS);
- writeFile(componentsHeaderPath, componentsHeaderContent);
-
- const Utils::FilePath cppFilePath = srcDir.pathAppended("main.cpp");
- const QString cppContent = readTemplate(TEMPLATE_SOURCE_MAIN);
- writeFile(cppFilePath, cppContent);
-
- const Utils::FilePath envHeaderPath = srcDir.pathAppended("app_environment.h");
- if (m_buildSystem) {
- QString environment;
- const QString qtcontrolsConfFile = makeEnvironmentVariable(
- Constants::ENV_VARIABLE_CONTROLCONF);
- for (Utils::EnvironmentItem &envItem : m_buildSystem->environment()) {
- QString key = envItem.name;
- QString value = envItem.value;
- if (value == qtcontrolsConfFile)
- value.prepend(":/");
- environment.append(QString(" qputenv(\"%1\", \"%2\");\n").arg(key).arg(value));
- }
- const QString envHeaderContent
- = readTemplate(TEMPLATE_HEADER_ENVIRONMENT).arg(environment);
- writeFile(envHeaderPath, envHeaderContent);
- }
- }
-
- QString moduleContent;
- for (const QString &module : m_moduleNames)
- moduleContent.append(QString("Q_IMPORT_QML_PLUGIN(%1)\n").arg(module + "Plugin"));
-
- const QString headerContent = readTemplate(TEMPLATE_HEADER_IMPORT_PLUGINS).arg(moduleContent);
- const Utils::FilePath headerFilePath = srcDir.pathAppended("import_qml_plugins.h");
- writeFile(headerFilePath, headerContent);
-}
-
-void CMakeGenerator::writeFile(const Utils::FilePath &path, const QString &content) const
-{
- QFile fileHandle(path.toString());
- fileHandle.open(QIODevice::WriteOnly);
- QTextStream stream(&fileHandle);
- stream << content;
- fileHandle.close();
-}
-
-QString CMakeGenerator::makeRelative(const NodePtr &node, const Utils::FilePath &path) const
-{
- const QString dir = node->dir.toString();
- return "\"" + Utils::FilePath::calcRelativePath(path.toString(), dir) + "\"";
-}
-
-QString CMakeGenerator::makeEnvironmentVariable(const QString &key) const
-{
- QString value;
- if (m_buildSystem) {
- auto envItems = m_buildSystem->environment();
- auto confEnv = std::find_if(envItems.begin(),
- envItems.end(),
- [key](Utils::EnvironmentItem &item) { return item.name == key; });
- if (confEnv != envItems.end())
- value = confEnv->value;
- }
- return value;
-}
-
-QString CMakeGenerator::makeSingletonBlock(const NodePtr &node) const
-{
- const QString setProperties(
- "set_source_files_properties(%1\n PROPERTIES\n %2 %3\n)\n\n");
-
- QString str;
- for (const Utils::FilePath &path : node->singletons)
- str.append(setProperties.arg(path.fileName()).arg("QT_QML_SINGLETON_TYPE").arg("true"));
- return str;
-}
-
-QString CMakeGenerator::makeSubdirectoriesBlock(const NodePtr &node) const
-{
- QString str;
- for (const NodePtr &n : node->subdirs) {
- if (n->module || hasChildModule(n))
- str.append(QString("add_subdirectory(%1)\n").arg(n->dir.fileName()));
- }
- return str;
-}
-
-QString CMakeGenerator::makeQmlFilesBlock(const NodePtr &node) const
-{
- QString qmlFileContent;
- for (const Utils::FilePath &path : qmlFiles(node))
- qmlFileContent.append(QString(" %1\n").arg(makeRelative(node, path)));
-
- if (isRootNode(node) && qmlFileContent.isEmpty())
- qmlFileContent.append(QString(" %1\n").arg("\"main.qml\""));
-
- QString str;
- if (!qmlFileContent.isEmpty())
- str.append(QString(" QML_FILES\n%1").arg(qmlFileContent));
-
- return str;
-}
-
-std::tuple<QString, QString> CMakeGenerator::makeResourcesBlocks(const NodePtr &node) const
-{
- QString resourcesOut;
- QString bigResourcesOut;
-
- QString resourceFiles;
- std::vector<QString> bigResources;
- for (const Utils::FilePath &path : resources(node)) {
- if (path.fileSize() > 5000000) {
- bigResources.push_back(makeRelative(node, path));
- continue;
- }
- resourceFiles.append(QString(" %1\n").arg(makeRelative(node, path)));
- }
-
- if (!resourceFiles.isEmpty())
- resourcesOut.append(QString(" RESOURCES\n%1").arg(resourceFiles));
-
- QString templatePostfix;
- if (!bigResources.empty()) {
- QString resourceContent;
- for (const QString &res : bigResources)
- resourceContent.append(QString("\n %1").arg(res));
-
- const QString prefixPath = QString(node->uri).replace('.', '/');
- const QString prefix = "/qt/qml/" + prefixPath;
- const QString resourceName = node->name + "BigResource";
-
- bigResourcesOut = QString::fromUtf8(TEMPLATE_BIG_RESOURCES, -1)
- .arg(node->name, resourceName, prefix, resourceContent);
- }
-
- return {resourcesOut, bigResourcesOut};
-}
-
-QString CMakeGenerator::readTemplate(const QString &templatePath) const
-{
- QFile templatefile(templatePath);
- templatefile.open(QIODevice::ReadOnly);
- QTextStream stream(&templatefile);
- QString content = stream.readAll();
- templatefile.close();
- return content;
+ if (sourceNode)
+ m_writer->writeSourceFiles(sourceNode, m_root);
}
void CMakeGenerator::readQmlDir(const Utils::FilePath &filePath, NodePtr &node) const
{
- node->module = true;
+ node->type = Node::Type::Module;
QFile f(filePath.toString());
f.open(QIODevice::ReadOnly);
QTextStream stream(&f);
Utils::FilePath dir = filePath.parentDir();
+ static const QRegularExpression whitespaceRegex("\\s+");
while (!stream.atEnd()) {
const QString line = stream.readLine();
- const QStringList tokenizedLine = line.split(QRegularExpression("\\s+"));
+ const QStringList tokenizedLine = line.split(whitespaceRegex);
const QString maybeFileName = tokenizedLine.last();
if (tokenizedLine.first().compare("module", Qt::CaseInsensitive) == 0) {
node->uri = tokenizedLine.last();
@@ -392,11 +268,11 @@ void CMakeGenerator::readQmlDir(const Utils::FilePath &filePath, NodePtr &node)
f.close();
}
-CMakeGenerator::NodePtr CMakeGenerator::findModuleFor(const NodePtr &node) const
+NodePtr CMakeGenerator::findModuleFor(const NodePtr &node) const
{
NodePtr current = node;
while (current->parent) {
- if (current->module)
+ if (current->type == Node::Type::Module)
return current;
current = current->parent;
@@ -404,11 +280,10 @@ CMakeGenerator::NodePtr CMakeGenerator::findModuleFor(const NodePtr &node) const
return nullptr;
}
-CMakeGenerator::NodePtr CMakeGenerator::findNode(NodePtr &node, const Utils::FilePath &path) const
+NodePtr CMakeGenerator::findNode(NodePtr &node, const Utils::FilePath &path) const
{
- const Utils::FilePath parentDir = path.parentDir();
for (NodePtr &child : node->subdirs) {
- if (child->dir == parentDir)
+ if (child->dir == path)
return child;
if (path.isChildOf(child->dir))
return findNode(child, path);
@@ -416,8 +291,7 @@ CMakeGenerator::NodePtr CMakeGenerator::findNode(NodePtr &node, const Utils::Fil
return nullptr;
}
-CMakeGenerator::NodePtr CMakeGenerator::findOrCreateNode(NodePtr &node,
- const Utils::FilePath &path) const
+NodePtr CMakeGenerator::findOrCreateNode(NodePtr &node, const Utils::FilePath &path) const
{
if (auto found = findNode(node, path))
return found;
@@ -425,31 +299,74 @@ CMakeGenerator::NodePtr CMakeGenerator::findOrCreateNode(NodePtr &node,
if (!path.isChildOf(node->dir))
return nullptr;
- const Utils::FilePath parentDir = path.parentDir();
- const Utils::FilePath relative = parentDir.relativeChildPath(node->dir);
+ auto findSubDir = [](NodePtr &node, const Utils::FilePath &path) -> NodePtr {
+ for (NodePtr child : node->subdirs) {
+ if (child->dir == path)
+ return child;
+ }
+ return nullptr;
+ };
+
+ const Utils::FilePath relative = path.relativeChildPath(node->dir);
const QChar separator = relative.pathComponentSeparator();
const QList<QStringView> components = relative.pathView().split(separator);
- NodePtr last = node;
+ NodePtr lastNode = node;
for (const auto &comp : components) {
+
+ Utils::FilePath subPath = lastNode->dir.pathAppended(comp.toString());
+ if (NodePtr sub = findSubDir(lastNode, subPath)) {
+ lastNode = sub;
+ continue;
+ }
NodePtr newNode = std::make_shared<Node>();
- newNode->parent = last;
+ newNode->parent = lastNode;
newNode->name = comp.toString();
- newNode->dir = last->dir.pathAppended(comp.toString());
- last->subdirs.push_back(newNode);
- last = newNode;
+ newNode->dir = subPath;
+ lastNode->subdirs.push_back(newNode);
+ lastNode = newNode;
}
- return last;
+ return lastNode;
+}
+
+bool findFileWithGetter(const Utils::FilePath &file, const NodePtr &node, const FileGetter &getter)
+{
+ for (const auto &f : getter(node)) {
+ if (f == file)
+ return true;
+ }
+ for (const auto &subdir : node->subdirs) {
+ if (findFileWithGetter(file, subdir, getter))
+ return true;
+ }
+ return false;
+}
+
+bool CMakeGenerator::findFile(const NodePtr &node, const Utils::FilePath &file) const
+{
+ if (isResource(file)) {
+ return findFileWithGetter(file, node, [](const NodePtr &n) { return n->resources; });
+ } else if (isQml(file)) {
+ if (findFileWithGetter(file, node, [](const NodePtr &n) { return n->files; }))
+ return true;
+ else if (findFileWithGetter(file, node, [](const NodePtr &n) { return n->singletons; }))
+ return true;
+ }
+ return false;
}
void CMakeGenerator::insertFile(NodePtr &node, const Utils::FilePath &path) const
{
+ QString error;
+ if (!Utils::FileNameValidatingLineEdit::validateFileName(path.fileName(), false, &error))
+ logIssue(ProjectExplorer::Task::Error, error, path);
+
if (path.fileName() == "qmldir") {
readQmlDir(path, node);
- } else if (path.suffix() == "qml" || path.suffix() == "ui.qml") {
- node->files.push_back(path);
} else if (path.suffix() == "cpp") {
node->sources.push_back(path);
+ } else if (isQml(path)) {
+ node->files.push_back(path);
} else if (isResource(path)) {
node->resources.push_back(path);
}
@@ -458,12 +375,12 @@ void CMakeGenerator::insertFile(NodePtr &node, const Utils::FilePath &path) cons
void CMakeGenerator::removeFile(NodePtr &node, const Utils::FilePath &path) const
{
if (path.fileName() == "qmldir") {
- node->module = false;
+ node->type = Node::Type::Folder;
node->singletons.clear();
node->uri = "";
node->name = path.parentDir().fileName();
- } else if (path.suffix() == "qml") {
+ } else if (isQml(path)) {
auto iter = std::find(node->files.begin(), node->files.end(), path);
if (iter != node->files.end())
node->files.erase(iter);
@@ -474,33 +391,9 @@ void CMakeGenerator::removeFile(NodePtr &node, const Utils::FilePath &path) cons
}
}
-bool CMakeGenerator::isRootNode(const NodePtr &node) const
-{
- return node->name == "Main";
-}
-
-bool CMakeGenerator::hasChildModule(const NodePtr &node) const
-{
- for (const NodePtr &child : node->subdirs) {
- if (child->module)
- return true;
- if (hasChildModule(child))
- return true;
- }
- return false;
-}
-
-bool CMakeGenerator::isResource(const Utils::FilePath &path) const
-{
- static const QStringList suffixes = {
- "json", "mesh", "dae", "qad", "hints", "png", "hdr", "ttf", "jpg", "JPG",
- "js", "qsb", "frag", "frag.qsb", "vert", "vert.qsb", "svg", "ktx"};
- return suffixes.contains(path.suffix());
-}
-
void CMakeGenerator::printModules(const NodePtr &node) const
{
- if (node->module)
+ if (node->type == Node::Type::Module)
qDebug() << "Module: " << node->name;
for (const auto &child : node->subdirs)
@@ -516,7 +409,27 @@ void CMakeGenerator::printNodeTree(const NodePtr &generatorNode, size_t indent)
return str;
};
+ QString typeString;
+ switch (generatorNode->type)
+ {
+ case Node::Type::App:
+ typeString = "Node::Type::App";
+ break;
+ case Node::Type::Folder:
+ typeString = "Node::Type::Folder";
+ break;
+ case Node::Type::Module:
+ typeString = "Node::Type::Module";
+ break;
+ case Node::Type::Library:
+ typeString = "Node::Type::Library";
+ break;
+ default:
+ typeString = "Node::Type::Undefined";
+ }
+
qDebug() << addIndent(indent) << "GeneratorNode: " << generatorNode->name;
+ qDebug() << addIndent(indent) << "type: " << typeString;
qDebug() << addIndent(indent) << "directory: " << generatorNode->dir;
qDebug() << addIndent(indent) << "files: " << generatorNode->files;
qDebug() << addIndent(indent) << "singletons: " << generatorNode->singletons;
@@ -532,7 +445,7 @@ void CMakeGenerator::parseNodeTree(NodePtr &generatorNode,
{
for (const auto *childNode : folderNode->nodes()) {
if (const auto *subFolderNode = childNode->asFolderNode()) {
- CMakeGenerator::NodePtr childGeneratorNode = std::make_shared<Node>();
+ NodePtr childGeneratorNode = std::make_shared<Node>();
childGeneratorNode->parent = generatorNode;
childGeneratorNode->dir = subFolderNode->filePath();
childGeneratorNode->name = subFolderNode->displayName();
@@ -544,25 +457,55 @@ void CMakeGenerator::parseNodeTree(NodePtr &generatorNode,
}
}
- if (generatorNode->name == "content")
- generatorNode->module = true;
+ if (m_writer)
+ m_writer->transformNode(generatorNode);
- if (generatorNode->module)
+ if (generatorNode->type == Node::Type::Module)
m_moduleNames.push_back(generatorNode->name);
}
void CMakeGenerator::parseSourceTree()
{
- m_srcs.clear();
- const QString srcDir = m_root->dir.pathAppended(Constants::DIRNAME_CPP).path();
- QDirIterator it(srcDir, QStringList({"*.cpp"}), QDir::Files, QDirIterator::Subdirectories);
+ QTC_ASSERT(m_writer, return);
+
+ const Utils::FilePath srcDir = m_root->dir.pathAppended(m_writer->sourceDirName());
+ QDirIterator it(srcDir.path(), {"*.cpp"}, QDir::Files, QDirIterator::Subdirectories);
+
+ NodePtr srcNode = std::make_shared<Node>();
+ srcNode->parent = m_root;
+ srcNode->type = Node::Type::App;
+ srcNode->dir = srcDir;
+ srcNode->uri = srcDir.baseName();
+ srcNode->name = srcNode->uri;
+
while (it.hasNext()) {
- QString relative = Utils::FilePath::calcRelativePath(it.next(), m_root->dir.path());
- m_srcs.push_back(relative);
+ auto next = it.next();
+ srcNode->sources.push_back(Utils::FilePath::fromString(next));
+ }
+
+ if (srcNode->sources.empty())
+ srcNode->sources.push_back(srcDir.pathAppended("main.cpp"));
+
+ if (m_writer)
+ m_writer->transformNode(srcNode);
+
+ m_root->subdirs.push_back(srcNode);
+}
+
+void CMakeGenerator::compareWithFileSystem(const NodePtr &node) const
+{
+ std::vector<Utils::FilePath> files;
+ QDirIterator iter(node->dir.path(), QDir::Files, QDirIterator::Subdirectories);
+
+ while (iter.hasNext()) {
+ auto next = Utils::FilePath::fromString(iter.next());
+ if (isResource(next) && !findFile(next) && !ignoreFile(next))
+ files.push_back(next);
}
- if (m_srcs.empty())
- m_srcs.push_back("src/main.cpp");
+ const QString text("File is not part of the project");
+ for (const auto &file : files)
+ logIssue(ProjectExplorer::Task::Warning, text, file);
}
} // namespace GenerateCmake
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakegenerator.h b/src/plugins/qmlprojectmanager/cmakegen/cmakegenerator.h
index f89257ac5d..6077166d5b 100644
--- a/src/plugins/qmlprojectmanager/cmakegen/cmakegenerator.h
+++ b/src/plugins/qmlprojectmanager/cmakegen/cmakegenerator.h
@@ -2,7 +2,10 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#pragma once
+#include "cmakewriter.h"
+
#include "utils/filepath.h"
+#include "projectexplorer/task.h"
#include <QObject>
@@ -22,80 +25,56 @@ class CMakeGenerator : public QObject
Q_OBJECT
public:
+ static void createMenuAction(QObject *parent);
+ static void logIssue(ProjectExplorer::Task::TaskType type, const QString &text, const Utils::FilePath &file);
+
CMakeGenerator(QmlBuildSystem *bs, QObject *parent = nullptr);
- void setEnabled(bool enabled);
+ QString projectName() const;
- void initialize(QmlProject *project);
+ const QmlProject *qmlProject() const;
+ const QmlBuildSystem *buildSystem() const;
+
+ bool findFile(const Utils::FilePath &file) const;
+ bool isRootNode(const NodePtr &node) const;
+ bool hasChildModule(const NodePtr &node) const;
+ void setEnabled(bool enabled);
+ void initialize(QmlProject *project);
void update(const QSet<QString> &added, const QSet<QString> &removed);
+ void updateMenuAction();
private:
- struct Node
- {
- std::shared_ptr<Node> parent = nullptr;
- bool module = false;
-
- QString uri;
- QString name;
- Utils::FilePath dir;
-
- std::vector<std::shared_ptr<Node>> subdirs;
- std::vector<Utils::FilePath> files;
- std::vector<Utils::FilePath> singletons;
- std::vector<Utils::FilePath> resources;
- std::vector<Utils::FilePath> sources;
- };
-
- using NodePtr = std::shared_ptr<Node>;
- using FileGetter = std::function<std::vector<Utils::FilePath>(const NodePtr &)>;
-
- std::vector<Utils::FilePath> files(const NodePtr &node, const FileGetter &getter) const;
- std::vector<Utils::FilePath> qmlFiles(const NodePtr &node) const;
- std::vector<Utils::FilePath> singletons(const NodePtr &node) const;
- std::vector<Utils::FilePath> resources(const NodePtr &node) const;
- std::vector<Utils::FilePath> sources(const NodePtr &node) const;
+ bool isQml(const Utils::FilePath &path) const;
+ bool isResource(const Utils::FilePath &path) const;
+ bool ignoreFile(const Utils::FilePath &path) const;
void createCMakeFiles(const NodePtr &node) const;
- void createMainCMakeFile(const NodePtr &node) const;
- void createModuleCMakeFile(const NodePtr &node) const;
+ void createSourceFiles() const;
- void createEntryPoints(const NodePtr &node) const;
- void createMainCppFile(const NodePtr &node) const;
- void writeFile(const Utils::FilePath &path, const QString &content) const;
-
- QString makeRelative(const NodePtr &node, const Utils::FilePath &path) const;
- QString makeEnvironmentVariable(const QString &key) const;
- QString makeSingletonBlock(const NodePtr &node) const;
- QString makeSubdirectoriesBlock(const NodePtr &node) const;
- QString makeQmlFilesBlock(const NodePtr &node) const;
- std::tuple<QString, QString> makeResourcesBlocks(const NodePtr &node) const;
-
- QString readTemplate(const QString &templatePath) const;
void readQmlDir(const Utils::FilePath &filePath, NodePtr &node) const;
-
NodePtr findModuleFor(const NodePtr &node) const;
NodePtr findNode(NodePtr &node, const Utils::FilePath &path) const;
NodePtr findOrCreateNode(NodePtr &node, const Utils::FilePath &path) const;
+ bool findFile(const NodePtr &node, const Utils::FilePath &file) const;
void insertFile(NodePtr &node, const Utils::FilePath &path) const;
void removeFile(NodePtr &node, const Utils::FilePath &path) const;
- bool isRootNode(const NodePtr &node) const;
- bool hasChildModule(const NodePtr &node) const;
- bool isResource(const Utils::FilePath &path) const;
-
void printModules(const NodePtr &generatorNode) const;
void printNodeTree(const NodePtr &generatorNode, size_t indent = 0) const;
void parseNodeTree(NodePtr &generatorNode, const ProjectExplorer::FolderNode *folderNode);
void parseSourceTree();
+ void compareWithFileSystem(const NodePtr &node) const;
+
bool m_enabled = false;
+ CMakeWriter::Ptr m_writer = {};
+
QString m_projectName = {};
NodePtr m_root = {};
- QStringList m_srcs = {};
- std::vector<QString> m_moduleNames = {};
+ QStringList m_moduleNames = {};
QmlBuildSystem *m_buildSystem = nullptr;
};
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialog.cpp b/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialog.cpp
deleted file mode 100644
index aa733b68af..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialog.cpp
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#include "cmakegeneratordialog.h"
-#include "../qmlprojectmanagertr.h"
-#include "cmakegeneratordialogtreemodel.h"
-
-#include <utils/utilsicons.h>
-#include <utils/detailswidget.h>
-
-#include <QDialogButtonBox>
-#include <QPushButton>
-#include <QLayout>
-#include <QLabel>
-
-#include <QSplitter>
-
-using namespace Utils;
-
-namespace QmlProjectManager {
-namespace GenerateCmake {
-
-CmakeGeneratorDialog::CmakeGeneratorDialog(const FilePath &rootDir,
- const FilePaths &files,
- const FilePaths invalidFiles)
- : QDialog(), m_rootDir(rootDir), m_files(files), m_invalidFiles(invalidFiles)
-{
- setWindowTitle(Tr::tr("Select Files to Generate"));
-
- QLabel *mainLabel = new QLabel(Tr::tr("Start CMakeFiles.txt generation"), this);
- mainLabel->setMargin(30);
-
- QVBoxLayout *dialogLayout = new QVBoxLayout(this);
- dialogLayout->addWidget(mainLabel);
- dialogLayout->addWidget(createDetailsWidget());
- dialogLayout->addWidget(createButtons());
- setLayout(dialogLayout);
-
- setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
- setMaximumHeight(layout()->totalSizeHint().height());
-
- refreshNotificationText();
-}
-
-QTreeView* CmakeGeneratorDialog::createFileTree()
-{
- m_model = new CMakeGeneratorDialogTreeModel(m_rootDir, m_files, this);
-
- QTreeView *tree = new QTreeView(this);
- tree->setModel(m_model);
- tree->expandAll();
- tree->setHeaderHidden(true);
-
- return tree;
-}
-
-QWidget* CmakeGeneratorDialog::createDetailsWidget()
-{
- QTreeView* tree = createFileTree();
-
- m_notifications = new QTextEdit(this);
- m_warningIcon = Utils::Icons::WARNING.pixmap();
-
- QSplitter *advancedInnerWidget = new QSplitter(this);
- advancedInnerWidget->addWidget(tree);
- advancedInnerWidget->addWidget(m_notifications);
- advancedInnerWidget->setStretchFactor(0, 2);
- advancedInnerWidget->setStretchFactor(1, 1);
- advancedInnerWidget->setOrientation(Qt::Vertical);
- advancedInnerWidget->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::MinimumExpanding);
-
- DetailsWidget *advancedWidget = new DetailsWidget(this);
- advancedWidget->setMinimumWidth(600);
- advancedWidget->setWidget(advancedInnerWidget);
- advancedWidget->setSummaryText(Tr::tr("Advanced Options"));
- connect(advancedWidget, &DetailsWidget::expanded, this, &CmakeGeneratorDialog::advancedVisibilityChanged);
-
- return advancedWidget;
-}
-
-QWidget* CmakeGeneratorDialog::createButtons()
-{
- QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
- auto *okButton = buttons->button(QDialogButtonBox::Ok);
- okButton->setDefault(true);
-
- connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
- connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
- connect(m_model, &CMakeGeneratorDialogTreeModel::checkedStateChanged, this, &CmakeGeneratorDialog::refreshNotificationText);
-
- return buttons;
-}
-
-FilePaths CmakeGeneratorDialog::getFilePaths()
-{
- FilePaths paths;
-
- QList<CheckableFileTreeItem*> items = m_model->checkedItems();
- for (CheckableFileTreeItem *item: items) {
- paths.append(FilePath::fromString(item->text()));
- }
-
- return paths;
-}
-
-const QString FILE_CREATE_NOTIFICATION = Tr::tr("File %1 will be created.\n");
-const QString FILE_OVERWRITE_NOTIFICATION = Tr::tr("File %1 will be overwritten.\n");
-const QString FILE_INVALID_NOTIFICATION = Tr::tr(
- "File %1 contains invalid characters and will be skipped.\n");
-
-void CmakeGeneratorDialog::refreshNotificationText()
-{
- QTextDocument *document = m_notifications->document();
- document->clear();
- document->addResource(QTextDocument::ImageResource, QUrl("cmakegendialog://warningicon"), m_warningIcon);
-
- QTextCursor cursor = m_notifications->textCursor();
- QTextImageFormat iformat;
- iformat.setName("cmakegendialog://warningicon");
-
- QList<CheckableFileTreeItem*> nodes = m_model->items();
-
- for (const auto &file : m_invalidFiles) {
- cursor.insertImage(iformat);
- cursor.insertText(QString(FILE_INVALID_NOTIFICATION).arg(file.displayName()));
- }
-
- for (CheckableFileTreeItem *node : nodes) {
- if (!m_files.contains(node->toFilePath()))
- continue;
-
- if (!node->toFilePath().exists() && node->isChecked()) {
- QString relativePath = QString(node->toFilePath().toString()).remove(m_rootDir.toString()+'/');
- cursor.insertText(QString(FILE_CREATE_NOTIFICATION).arg(relativePath));
- }
- }
-
- if (!document->toPlainText().isEmpty())
- cursor.insertBlock();
-
- for (CheckableFileTreeItem *node : nodes) {
- if (!m_files.contains(node->toFilePath()))
- continue;
-
- if (node->toFilePath().exists() && node->isChecked()) {
- QString relativePath = node->toFilePath().relativePathFrom(m_rootDir).toString();
- cursor.insertImage(iformat);
- cursor.insertText(QString(FILE_OVERWRITE_NOTIFICATION).arg(relativePath));
- }
- }
-}
-
-void CmakeGeneratorDialog::advancedVisibilityChanged(bool visible)
-{
- if (visible) {
- setMaximumHeight(QWIDGETSIZE_MAX);
- setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
- }
- else {
- setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
- int height = layout()->totalSizeHint().height();
- setMaximumHeight(height);
- resize(width(), height);
- }
-}
-
-} //GenerateCmake
-} //QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialog.h b/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialog.h
deleted file mode 100644
index fb15ec4de7..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialog.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-
-#ifndef CMAKEGENERATORDIALOG_H
-#define CMAKEGENERATORDIALOG_H
-
-#include "cmakegeneratordialogtreemodel.h"
-
-#include <utils/fileutils.h>
-
-#include <QDialog>
-#include <QTextEdit>
-#include <QTreeView>
-#include <QLabel>
-
-namespace QmlProjectManager {
-namespace GenerateCmake {
-
-class CmakeGeneratorDialog : public QDialog
-{
- Q_OBJECT
-
-public:
- CmakeGeneratorDialog(const Utils::FilePath &rootDir,
- const Utils::FilePaths &files,
- const Utils::FilePaths invalidFiles);
- Utils::FilePaths getFilePaths();
-
-public slots:
- void refreshNotificationText();
- void advancedVisibilityChanged(bool visible);
-
-private:
- QTreeView* createFileTree();
- QWidget* createDetailsWidget();
- QWidget* createButtons();
-
-private:
- CMakeGeneratorDialogTreeModel *m_model;
- QTextEdit *m_notifications;
- QVariant m_warningIcon;
- Utils::FilePath m_rootDir;
- Utils::FilePaths m_files;
- Utils::FilePaths m_invalidFiles;
-};
-
-} //GenerateCmake
-} //QmlProjectManager
-
-#endif // CMAKEGENERATORDIALOG_H
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialogtreemodel.cpp b/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialogtreemodel.cpp
deleted file mode 100644
index 525230bdfd..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialogtreemodel.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
-// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#include "cmakegeneratordialogtreemodel.h"
-#include "generatecmakelistsconstants.h"
-#include "checkablefiletreeitem.h"
-#include "../qmlprojectmanagertr.h"
-
-#include <utils/utilsicons.h>
-
-using namespace Utils;
-
-namespace QmlProjectManager {
-namespace GenerateCmake {
-
-CMakeGeneratorDialogTreeModel::CMakeGeneratorDialogTreeModel(const FilePath &rootDir,
- const FilePaths &files, QObject *parent)
- :QStandardItemModel(parent),
- rootDir(rootDir),
- m_icons(new QFileIconProvider())
-{
- createNodes(files, invisibleRootItem());
-}
-
-CMakeGeneratorDialogTreeModel::~CMakeGeneratorDialogTreeModel()
-{
- delete m_icons;
-}
-
-QVariant CMakeGeneratorDialogTreeModel::data(const QModelIndex &index, int role) const
-{
- if (index.isValid()) {
- const CheckableFileTreeItem *node = constNodeForIndex(index);
- if (role == Qt::CheckStateRole) {
- if (!node->isDir())
- return node->isChecked() ? Qt::Checked : Qt::Unchecked;
- return {};
- }
- else if (role == Qt::DisplayRole) {
- FilePath fullPath = node->toFilePath();
- return QVariant(fullPath.fileName());
- }
- else if (role == Qt::DecorationRole) {
- if (node->isFile())
- return Utils::Icons::WARNING.icon();
- if (node->isDir())
- return m_icons->icon(QFileIconProvider::Folder);
- else
- return Utils::Icons::NEWFILE.icon();
- }
- else if (role == Qt::ToolTipRole) {
- if (node->isFile())
- return Tr::tr("This file already exists and will be overwritten.");
- if (!node->toFilePath().exists())
- return Tr::tr("This file or folder will be created.");
- }
- }
-
- return QStandardItemModel::data(index, role);
-}
-
-bool CMakeGeneratorDialogTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
-{
- if (index.isValid()) {
- CheckableFileTreeItem *node = nodeForIndex(index);
- if (role == Qt::CheckStateRole) {
- node->setChecked(value.value<bool>());
- emit checkedStateChanged(node);
- return true;
- }
- }
-
- return QStandardItemModel::setData(index, value, role);;
-}
-
-const QList<CheckableFileTreeItem*> CMakeGeneratorDialogTreeModel::items() const
-{
- QList<QStandardItem*> standardItems = findItems(".*", Qt::MatchRegularExpression | Qt::MatchRecursive);
- QList<CheckableFileTreeItem*> checkableItems;
- for (QStandardItem *item : standardItems)
- checkableItems.append(static_cast<CheckableFileTreeItem*>(item));
-
- return checkableItems;
-}
-
-const QList<CheckableFileTreeItem*> CMakeGeneratorDialogTreeModel::checkedItems() const
-{
- QList<CheckableFileTreeItem*> allItems = items();
-
- QList<CheckableFileTreeItem*> checkedItems;
- for (CheckableFileTreeItem *item : allItems) {
- if (item->isChecked())
- checkedItems.append(item);
- }
-
- return checkedItems;
-}
-
-bool CMakeGeneratorDialogTreeModel::checkedByDefault(const Utils::FilePath &file) const
-{
- if (file.exists()) {
- QString relativePath = file.relativeChildPath(rootDir).toString();
- if (relativePath.compare(QmlProjectManager::GenerateCmake::Constants::FILENAME_CMAKELISTS) == 0)
- return false;
- if (relativePath.endsWith(QmlProjectManager::GenerateCmake::Constants::FILENAME_CMAKELISTS)
- && relativePath.length() > QString(QmlProjectManager::GenerateCmake::Constants::FILENAME_CMAKELISTS).length())
- return true;
- if (relativePath.compare(QmlProjectManager::GenerateCmake::Constants::FILENAME_MODULES) == 0)
- return true;
- if (relativePath.compare(
- FilePath::fromString(QmlProjectManager::GenerateCmake::Constants::DIRNAME_CPP)
- .pathAppended(QmlProjectManager::GenerateCmake::Constants::FILENAME_MAINCPP_HEADER)
- .toString())
- == 0)
- return true;
- }
-
- return !file.exists();
-}
-
-void CMakeGeneratorDialogTreeModel::createNodes(const FilePaths &candidates, QStandardItem *parent)
-{
- if (!parent)
- return;
-
- CheckableFileTreeItem *checkParent = dynamic_cast<CheckableFileTreeItem*>(parent);
- FilePath thisDir = (parent == invisibleRootItem()) ? rootDir : checkParent->toFilePath();
-
- for (const FilePath &file : candidates) {
- if (file.parentDir() == thisDir) {
- CheckableFileTreeItem *fileNode = new CheckableFileTreeItem(file);
- fileNode->setChecked(checkedByDefault(file));
- if (!file.exists())
- fileNode->setChecked(true);
- parent->appendRow(fileNode);
- }
- }
-
- FilePaths directSubDirs;
- for (const FilePath &file : candidates) {
- FilePath dir = file.parentDir();
- if (dir.parentDir() == thisDir && !directSubDirs.contains(dir))
- directSubDirs.append(dir);
- }
-
- for (const FilePath &subDir : directSubDirs) {
- CheckableFileTreeItem *dirNode = new CheckableFileTreeItem(subDir);
- parent->appendRow(dirNode);
-
- FilePaths subDirCandidates;
- for (const FilePath &file : candidates)
- if (file.isChildOf(subDir))
- subDirCandidates.append(file);
-
- createNodes(subDirCandidates, dirNode);
- }
-}
-
-const CheckableFileTreeItem* CMakeGeneratorDialogTreeModel::constNodeForIndex(const QModelIndex &index) const
-{
- const QStandardItem *parent = static_cast<const QStandardItem*>(index.internalPointer());
- const QStandardItem *item = parent->child(index.row(), index.column());
- return static_cast<const CheckableFileTreeItem*>(item);
-}
-
-CheckableFileTreeItem* CMakeGeneratorDialogTreeModel::nodeForIndex(const QModelIndex &index)
-{
- QStandardItem *parent = static_cast<QStandardItem*>(index.internalPointer());
- QStandardItem *item = parent->child(index.row(), index.column());
- return static_cast<CheckableFileTreeItem*>(item);
-}
-
-} //GenerateCmake
-} //QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialogtreemodel.h b/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialogtreemodel.h
deleted file mode 100644
index 3fb79c2b96..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/cmakegeneratordialogtreemodel.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#ifndef CMAKEGENERATORDIALOGTREEMODEL_H
-#define CMAKEGENERATORDIALOGTREEMODEL_H
-
-#include "checkablefiletreeitem.h"
-
-#include <QFileIconProvider>
-#include <QStandardItemModel>
-
-#include <utils/fileutils.h>
-
-namespace QmlProjectManager {
-namespace GenerateCmake {
-
-class CMakeGeneratorDialogTreeModel : public QStandardItemModel
-{
- Q_OBJECT
-
-public:
- CMakeGeneratorDialogTreeModel(const Utils::FilePath &rootDir,
- const Utils::FilePaths &files, QObject *parent = nullptr);
- ~CMakeGeneratorDialogTreeModel();
-
- QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
- bool setData(const QModelIndex &index, const QVariant &value, int role);
-
- const QList<CheckableFileTreeItem*> items() const;
- const QList<CheckableFileTreeItem*> checkedItems() const;
- const CheckableFileTreeItem* constNodeForIndex(const QModelIndex &index) const;
- CheckableFileTreeItem* nodeForIndex(const QModelIndex &index);
-
-signals:
- void checkedStateChanged(CheckableFileTreeItem *item);
-
-protected:
- bool checkedByDefault(const Utils::FilePath &file) const;
- Utils::FilePath rootDir;
-
-private:
- void createNodes(const Utils::FilePaths &candidates, QStandardItem *parent);
-
- QFileIconProvider* m_icons;
-};
-
-} //GenerateCmake
-} //QmlProjectManager
-
-
-#endif // CMAKEGENERATORDIALOGTREEMODEL_H
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverter.cpp b/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverter.cpp
deleted file mode 100644
index f6bf1a4975..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverter.cpp
+++ /dev/null
@@ -1,422 +0,0 @@
-// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#include "cmakeprojectconverter.h"
-#include "cmakeprojectconverterdialog.h"
-#include "generatecmakelists.h"
-#include "generatecmakelistsconstants.h"
-#include "../qmlprojectmanagertr.h"
-
-#include <coreplugin/actionmanager/actionmanager.h>
-#include <coreplugin/actionmanager/actioncontainer.h>
-#include <coreplugin/icore.h>
-
-#include <projectexplorer/projectexplorer.h>
-#include <projectexplorer/projectmanager.h>
-#include <projectexplorer/target.h>
-
-#include <qmlprojectmanager/qmlprojectconstants.h>
-
-#include <QAction>
-#include <QMessageBox>
-#include <QRegularExpression>
-
-using namespace Utils;
-using namespace QmlProjectManager::GenerateCmake::Constants;
-
-namespace QmlProjectManager {
-namespace GenerateCmake {
-
-const QString MENU_ITEM_CONVERT = Tr::tr("Export as Latest Project Format...");
-const QString ERROR_TITLE = Tr::tr("Creating Project");
-const QString SUCCESS_TITLE = Tr::tr("Creating Project");
-const QString ERROR_TEXT = Tr::tr("Creating project failed.\n%1");
-const QString SUCCESS_TEXT = Tr::tr("Creating project succeeded.");
-
-void CmakeProjectConverter::generateMenuEntry(QObject *parent)
-{
- Core::ActionContainer *exportMenu = Core::ActionManager::actionContainer(
- QmlProjectManager::Constants::EXPORT_MENU);
- auto action = new QAction(MENU_ITEM_CONVERT, parent);
- QObject::connect(action, &QAction::triggered, CmakeProjectConverter::onConvertProject);
- Core::Command *cmd = Core::ActionManager::registerAction(action, "QmlProject.ConvertToCmakeProject");
- exportMenu->addAction(cmd, QmlProjectManager::Constants::G_EXPORT_CONVERT);
-
- action->setEnabled(isProjectConvertable(ProjectExplorer::ProjectManager::startupProject()));
- QObject::connect(ProjectExplorer::ProjectManager::instance(),
- &ProjectExplorer::ProjectManager::startupProjectChanged,
- [action]() {
- auto currentBuildSystem = QmlBuildSystem::getStartupBuildSystem();
- bool isMCU = currentBuildSystem ? currentBuildSystem->qtForMCUs() : false;
-
- action->setEnabled(isMCU
- && isProjectConvertable(
- ProjectExplorer::ProjectManager::startupProject()));
- });
-}
-
-bool CmakeProjectConverter::isProjectConvertable(const ProjectExplorer::Project *project)
-{
- if (!project)
- return false;
-
- return !isProjectCurrentFormat(project);
-}
-
-const QStringList sanityCheckFiles({FILENAME_CMAKELISTS,
- FILENAME_MODULES,
- FILENAME_MAINQML,
- QString(DIRNAME_CONTENT)+'/'+FILENAME_CMAKELISTS,
- QString(DIRNAME_IMPORT)+'/'+FILENAME_CMAKELISTS,
- QString(DIRNAME_CPP)+'/'+FILENAME_MAINCPP,
- QString(DIRNAME_CPP)+'/'+FILENAME_ENV_HEADER,
- QString(DIRNAME_CPP)+'/'+FILENAME_MAINCPP_HEADER
- });
-
-bool CmakeProjectConverter::isProjectCurrentFormat(const ProjectExplorer::Project *project)
-{
- const QmlProjectManager::QmlProject *qmlprj = qobject_cast<const QmlProjectManager::QmlProject*>(project);
-
- if (!qmlprj)
- return false;
-
- FilePath rootDir = qmlprj->rootProjectDirectory();
- for (const QString &file : sanityCheckFiles)
- if (!rootDir.pathAppended(file).exists())
- return false;
-
- return true;
-}
-
-void CmakeProjectConverter::onConvertProject()
-{
- ProjectExplorer::Project *project = ProjectExplorer::ProjectManager::startupProject();
- const QmlProjectManager::QmlProject *qmlProject =
- qobject_cast<const QmlProjectManager::QmlProject*>(project);
- if (qmlProject) {
- CmakeProjectConverterDialog dialog(qmlProject);
- if (dialog.exec()) {
- FilePath newProjectPath = dialog.newPath();
- CmakeProjectConverter converter;
- converter.convertProject(qmlProject, newProjectPath);
- }
- }
-}
-
-bool CmakeProjectConverter::convertProject(const QmlProjectManager::QmlProject *project,
- const FilePath &targetDir)
-{
- m_converterObjects.clear();
- m_projectDir = project->projectDirectory();
- m_newProjectDir = targetDir;
- m_project = project;
-
- m_rootDirFiles = QStringList(FILENAME_FILTER_QMLPROJECT);
- const QString confFile = GenerateCmake::projectEnvironmentVariable(ENV_VARIABLE_CONTROLCONF);
- if (!confFile.isEmpty())
- m_rootDirFiles.append(confFile);
-
- bool retVal = prepareAndExecute();
-
- if (retVal) {
- QMessageBox::information(Core::ICore::dialogParent(), SUCCESS_TITLE, SUCCESS_TEXT);
- ProjectExplorer::OpenProjectResult result
- = ProjectExplorer::ProjectExplorerPlugin::openProject(newProjectFile());
- if (!result)
- ProjectExplorer::ProjectExplorerPlugin::showOpenProjectError(result);
- }
- else {
- QMessageBox::critical(Core::ICore::dialogParent(), ERROR_TITLE, ERROR_TEXT.arg(m_errorText));
- }
-
- return retVal;
-}
-
-bool CmakeProjectConverter::prepareAndExecute()
-{
- GenerateCmake::CmakeFileGenerator cmakeGenerator;
-
- if (!performSanityCheck())
- return false;
- if (!prepareBaseDirectoryStructure())
- return false;
- if (!prepareCopy())
- return false;
- if (!createPreparedProject())
- return false;
- if (!cmakeGenerator.prepare(m_newProjectDir, false))
- return false;
- if (!cmakeGenerator.execute())
- return false;
- if (!modifyNewFiles())
- return false;
-
- return true;
-}
-
-bool CmakeProjectConverter::isFileBlacklisted(const Utils::FilePath &file) const
-{
- if (!file.fileName().compare(FILENAME_CMAKELISTS))
- return true;
- if (!file.suffix().compare(FILENAME_SUFFIX_QMLPROJECT))
- return true;
- if (!file.suffix().compare(FILENAME_SUFFIX_USER))
- return true;
- if (m_rootDirFiles.contains(file.fileName()))
- return true;
-
- return false;
-}
-
-bool CmakeProjectConverter::isDirBlacklisted(const Utils::FilePath &dir) const
-{
- if (!dir.isDir())
- return true;
-
- return false;
-}
-
-const QString ERROR_CANNOT_WRITE_DIR = Tr::tr("Unable to write to directory\n%1.");
-
-bool CmakeProjectConverter::performSanityCheck()
-{
- if (!m_newProjectDir.parentDir().isWritableDir()) {
- m_errorText = ERROR_CANNOT_WRITE_DIR.arg(m_newProjectDir.parentDir().toString());
- return false;
- }
-
- return true;
-}
-
-bool CmakeProjectConverter::prepareBaseDirectoryStructure()
-{
- addDirectory(m_newProjectDir);
- addDirectory(contentDir());
- addDirectory(sourceDir());
- addDirectory(importDir());
- addDirectory(assetDir());
- addDirectory(assetImportDir());
- addFile(contentDir().pathAppended(FILENAME_APPMAINQML));
-
- return true;
-}
-
-bool CmakeProjectConverter::prepareCopy()
-{
- FilePaths rootFiles = m_projectDir.dirEntries({m_rootDirFiles, QDir::Files});
- for (const FilePath &file : rootFiles) {
- addFile(file, m_newProjectDir.pathAppended(file.fileName()));
- }
-
- prepareCopyDirFiles(m_projectDir, contentDir());
-
- FilePaths subDirs = m_projectDir.dirEntries(QDir::Dirs|QDir::NoDotAndDotDot);
- for (FilePath &subDir : subDirs) {
- if (subDir.fileName() == DIRNAME_IMPORT) {
- prepareCopyDirTree(subDir, importDir());
- }
- else if (subDir.fileName() == DIRNAME_CPP) {
- prepareCopyDirTree(subDir, sourceDir());
- }
- else if (subDir.fileName() == DIRNAME_ASSET) {
- prepareCopyDirTree(subDir, assetDir());
- }
- else if (subDir.fileName() == DIRNAME_ASSETIMPORT) {
- prepareCopyDirTree(subDir, assetImportDir());
- }
- else {
- prepareCopyDirTree(subDir, contentDir().pathAppended(subDir.fileName()));
- }
- }
-
- return true;
-}
-
-bool CmakeProjectConverter::prepareCopyDirFiles(const FilePath &dir, const FilePath &targetDir)
-{
- FilePaths dirFiles = dir.dirEntries(QDir::Files);
- for (FilePath file : dirFiles) {
- if (!isFileBlacklisted(file))
- addFile(file, targetDir.pathAppended(file.fileName()));
- }
-
- return true;
-}
-
-bool CmakeProjectConverter::prepareCopyDirTree(const FilePath &dir, const FilePath &targetDir)
-{
- prepareCopyDirFiles(dir, targetDir);
- FilePaths subDirs = dir.dirEntries(QDir::Dirs|QDir::NoDotAndDotDot);
- for (FilePath &subDir : subDirs) {
- if (isDirBlacklisted(subDir))
- continue;
- addDirectory(targetDir.pathAppended(subDir.fileName()));
- prepareCopyDirFiles(subDir, targetDir.pathAppended(subDir.fileName()));
- prepareCopyDirTree(subDir, targetDir.pathAppended(subDir.fileName()));
- }
-
- return true;
-}
-
-bool CmakeProjectConverter::addDirectory(const Utils::FilePath &target)
-{
- return addObject(ProjectConverterObjectType::Directory, FilePath(), target);
-}
-
-bool CmakeProjectConverter::addFile(const Utils::FilePath &target)
-{
- return addFile(FilePath(), target);
-}
-
-bool CmakeProjectConverter::addFile(const Utils::FilePath &original, const Utils::FilePath &target)
-{
- addDirectory(target.parentDir());
- return addObject(ProjectConverterObjectType::File, original, target);
-}
-
-bool CmakeProjectConverter::addObject(ProjectConverterObjectType type,
- const Utils::FilePath &original, const Utils::FilePath &target)
-{
- if (target.isChildOf(m_projectDir))
- return false;
-
- if (!target.isChildOf(m_newProjectDir) &&
- ((type == ProjectConverterObjectType::Directory) && (target != m_newProjectDir))) {
- return false;
- }
-
- for (ProjectConverterObject &o : m_converterObjects) {
- if (o.target == target)
- return false;
- }
-
- ProjectConverterObject object;
- object.type = type;
- object.target = target;
- object.original = original;
-
- m_converterObjects.append(object);
-
- return true;
-}
-
-bool CmakeProjectConverter::createPreparedProject()
-{
- for (ProjectConverterObject &pco : m_converterObjects) {
- if (pco.type == ProjectConverterObjectType::Directory) {
- pco.target.createDir();
- }
- else if (pco.type == ProjectConverterObjectType::File) {
- if (pco.original.isEmpty()) {
- QFile newFile(pco.target.toString());
- newFile.open(QIODevice::WriteOnly);
- newFile.close();
- }
- else {
- pco.original.copyFile(pco.target);
- }
- }
- }
-
- return true;
-}
-
-const FilePath CmakeProjectConverter::contentDir() const
-{
- return m_newProjectDir.pathAppended(DIRNAME_CONTENT);
-}
-
-const FilePath CmakeProjectConverter::sourceDir() const
-{
- return m_newProjectDir.pathAppended(DIRNAME_CPP);
-}
-
-const FilePath CmakeProjectConverter::importDir() const
-{
- return m_newProjectDir.pathAppended(DIRNAME_IMPORT);
-}
-
-const FilePath CmakeProjectConverter::assetDir() const
-{
- return contentDir().pathAppended(DIRNAME_ASSET);
-}
-
-const FilePath CmakeProjectConverter::assetImportDir() const
-{
- return m_newProjectDir.pathAppended(DIRNAME_ASSETIMPORT);
-}
-
-const FilePath CmakeProjectConverter::newProjectFile() const
-{
- return m_newProjectDir.pathAppended(m_project->projectFilePath().fileName());
-}
-
-const FilePath CmakeProjectConverter::projectMainFile() const
-{
- auto *target = m_project->activeTarget();
- if (target && target->buildSystem()) {
- auto buildSystem = qobject_cast<QmlProjectManager::QmlBuildSystem *>(target->buildSystem());
- if (buildSystem) {
- return buildSystem->mainFilePath();
- }
- }
- return {};
-}
-
-const QString CmakeProjectConverter::projectMainClass() const
-{
- return projectMainFile().baseName();
-}
-
-bool CmakeProjectConverter::modifyNewFiles()
-{
- return modifyAppMainQml() && modifyProjectFile();
-}
-
-const char APPMAIN_QMLFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectappmainqml.tpl";
-
-bool CmakeProjectConverter::modifyAppMainQml()
-{
- QString appMainQmlPath = contentDir().pathAppended(FILENAME_APPMAINQML).toString();
- QFile appMainQml(appMainQmlPath);
- appMainQml.open(QIODevice::ReadWrite);
- if (!appMainQml.isOpen())
- return false;
-
- QString templateContent = GenerateCmake::readTemplate(APPMAIN_QMLFILE_TEMPLATE_PATH);
- QString appMainQmlContent = templateContent.arg(projectMainClass());
-
- appMainQml.reset();
- appMainQml.write(appMainQmlContent.toUtf8());
- appMainQml.close();
-
- return true;
-}
-
-bool CmakeProjectConverter::modifyProjectFile()
-{
- QString projectFileName = m_project->projectFilePath().fileName();
- FilePath projectFilePath = m_newProjectDir.pathAppended(projectFileName);
- QFile projectFile(projectFilePath.toString());
- projectFile.open(QIODevice::ReadOnly);
- if (!projectFile.isOpen())
- return false;
- QString projectFileContent = QString::fromUtf8(projectFile.readAll());
- projectFile.close();
-
- const QRegularExpression mainFilePattern("^\\s*mainFile:\\s*\".*\"", QRegularExpression::MultilineOption);
- const QString mainFileString(" mainFile: \"content/App.qml\"");
-
- projectFileContent.replace(mainFilePattern, mainFileString);
-
- projectFile.open(QIODevice::WriteOnly|QIODevice::Truncate);
- if (!projectFile.isOpen())
- return false;
- projectFile.write(projectFileContent.toUtf8());
- projectFile.close();
-
- return true;
-}
-
-} //GenerateCmake
-} //QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverter.h b/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverter.h
deleted file mode 100644
index 415123db70..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverter.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#ifndef CMAKEPROJECTCONVERTER_H
-#define CMAKEPROJECTCONVERTER_H
-
-#include <utils/fileutils.h>
-#include <qmlprojectmanager/qmlproject.h>
-
-namespace QmlProjectManager {
-
-namespace GenerateCmake {
-
-enum ProjectConverterObjectType {
- File,
- Directory
-};
-
-struct ProjectConverterObject {
- ProjectConverterObjectType type;
- Utils::FilePath target;
- Utils::FilePath original;
-};
-
-class CmakeProjectConverter {
-
-public:
- bool convertProject(const QmlProjectManager::QmlProject *project,
- const Utils::FilePath &targetDir);
- static void generateMenuEntry(QObject *parent);
- static void onConvertProject();
- static bool isProjectConvertable(const ProjectExplorer::Project *project);
- static bool isProjectCurrentFormat(const ProjectExplorer::Project *project);
-
-private:
- bool prepareAndExecute();
- bool isFileBlacklisted(const Utils::FilePath &file) const;
- bool isDirBlacklisted(const Utils::FilePath &dir) const;
- bool performSanityCheck();
- bool prepareBaseDirectoryStructure();
- bool prepareCopyDirFiles(const Utils::FilePath &dir, const Utils::FilePath &targetDir);
- bool prepareCopyDirTree(const Utils::FilePath &dir, const Utils::FilePath &targetDir);
- bool prepareCopy();
- bool addDirectory(const Utils::FilePath &target);
- bool addFile(const Utils::FilePath &target);
- bool addFile(const Utils::FilePath &original, const Utils::FilePath &target);
- bool addObject(ProjectConverterObjectType type,
- const Utils::FilePath &original, const Utils::FilePath &target);
- bool createPreparedProject();
-
- const Utils::FilePath contentDir() const;
- const Utils::FilePath sourceDir() const;
- const Utils::FilePath importDir() const;
- const Utils::FilePath assetDir() const;
- const Utils::FilePath assetImportDir() const;
- const Utils::FilePath newProjectFile() const;
-
- const QString environmentVariable(const QString &key) const;
- const Utils::FilePath projectMainFile() const;
- const QString projectMainClass() const;
- bool modifyNewFiles();
- bool modifyAppMainQml();
- bool modifyProjectFile();
-
-private:
- QList<ProjectConverterObject> m_converterObjects;
- QStringList m_rootDirFiles;
- Utils::FilePath m_projectDir;
- Utils::FilePath m_newProjectDir;
- const QmlProjectManager::QmlProject *m_project;
- QString m_errorText;
-};
-
-} //GenerateCmake
-} //QmlProjectManager
-
-#endif // CMAKEPROJECTCONVERTER_H
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverterdialog.cpp b/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverterdialog.cpp
deleted file mode 100644
index 1d67a92b39..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverterdialog.cpp
+++ /dev/null
@@ -1,180 +0,0 @@
-// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#include "cmakeprojectconverterdialog.h"
-#include "../qmlprojectmanagertr.h"
-
-#include <coreplugin/documentmanager.h>
-
-#include <QDialog>
-#include <QDialogButtonBox>
-#include <QFormLayout>
-#include <QGroupBox>
-#include <QLabel>
-#include <QPushButton>
-#include <QRegularExpression>
-
-using namespace Utils;
-
-namespace QmlProjectManager {
-namespace GenerateCmake {
-
-const QRegularExpression projectNameRegexp("^(?!(import))(?!(QtQml))(?!(QtQuick))(?:[A-Z][a-zA-Z0-9-_]*)$");
-
-static bool projectNameValidationFunction(FancyLineEdit *editor, QString *)
-{
- return editor->text().count(projectNameRegexp);
-}
-
-static bool dirValidationFunction(FancyLineEdit *editor, QString *)
-{
- return FilePath::fromString(editor->text()).isWritableDir();
-}
-
-const QString EXPLANATION_TEXT = Tr::tr("This process creates a copy of the existing project. The new project's folder structure is adjusted for CMake build process and necessary related new files are generated.\n\nThe new project can be opened in Qt Creator using the main CMakeLists.txt file.");
-const QString PROJECT_NAME_LABEL = Tr::tr("Name:");
-const QString PARENT_DIR_LABEL = Tr::tr("Create in:");
-
-CmakeProjectConverterDialog::CmakeProjectConverterDialog(const QmlProjectManager::QmlProject *oldProject)
- : QDialog()
-{
- const FilePath defaultDir = Core::DocumentManager::projectsDirectory();
- const QString defaultName = uniqueProjectName(defaultDir, oldProject->displayName());
-
- QLabel *mainLabel = new QLabel(EXPLANATION_TEXT, this);
- mainLabel->setWordWrap(true);
-
- mainLabel->setMargin(20);
- mainLabel->setMinimumWidth(600);
-
- m_errorLabel = new InfoLabel();
- m_errorLabel->setType(InfoLabel::InfoType::None);
-
- m_nameEditor = new FancyLineEdit();
- m_nameEditor->setValidationFunction(projectNameValidationFunction);
- m_nameEditor->setText(defaultName);
-
- m_dirSelector = new PathChooser();
- m_dirSelector->setExpectedKind(PathChooser::Directory);
- m_dirSelector->setValidationFunction(dirValidationFunction);
- m_dirSelector->setFilePath(defaultDir);
-
- QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
- m_okButton = buttons->button(QDialogButtonBox::Ok);
- m_okButton->setDefault(true);
-
- connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
- connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
- connect(m_nameEditor, &FancyLineEdit::textChanged, this, &CmakeProjectConverterDialog::pathValidChanged);
- connect(m_dirSelector->lineEdit(), &FancyLineEdit::textChanged, this, &CmakeProjectConverterDialog::pathValidChanged);
-
- QGroupBox *form = new QGroupBox();
- QFormLayout *formLayout = new QFormLayout(form);
- formLayout->addRow(PROJECT_NAME_LABEL, m_nameEditor);
- formLayout->addRow(PARENT_DIR_LABEL, m_dirSelector);
-
- QVBoxLayout *dialogLayout = new QVBoxLayout(this);
- dialogLayout->addWidget(mainLabel);
- dialogLayout->addWidget(form);
- dialogLayout->addWidget(m_errorLabel);
- dialogLayout->addWidget(buttons);
-
- pathValidChanged();
-}
-
-void CmakeProjectConverterDialog::pathValidChanged()
-{
- bool valid = isValid();
-
- if (valid)
- m_newProjectDir = m_dirSelector->filePath().pathAppended(m_nameEditor->text());
- else
- m_newProjectDir = FilePath();
-
- const QString error = errorText();
- m_errorLabel->setType(error.isEmpty() ? InfoLabel::None : InfoLabel::Warning);
- m_errorLabel->setText(error);
- m_okButton->setEnabled(valid);
-}
-
-const FilePath CmakeProjectConverterDialog::newPath() const
-{
- return m_newProjectDir;
-}
-
-const QStringList blackListedStarts = {"import","QtQml","QtQuick"};
-
-const QString CmakeProjectConverterDialog::startsWithBlacklisted(const QString &text) const
-{
- for (const QString &badWord : blackListedStarts) {
- if (text.startsWith(badWord))
- return badWord;
- }
-
- return {};
-}
-
-const QString ERROR_TEXT_NAME_EMPTY = Tr::tr("Name is empty.");
-const QString ERROR_TEXT_NAME_BAD_START = Tr::tr("Name must not start with \"%1\".");
-const QString ERROR_TEXT_NAME_LOWERCASE_START = Tr::tr("Name must begin with a capital letter");
-const QString ERROR_TEXT_NAME_BAD_CHARACTERS = Tr::tr("Name must contain only letters, numbers or characters - _.");
-
-const QString ERROR_DIR_NOT_DIR = Tr::tr("Target is not a directory.");
-const QString ERROR_DIR_NOT_WRITABLE = Tr::tr("Cannot write to target directory.");
-const QString ERROR_DIR_EXISTS = Tr::tr("Project directory already exists.");
-
-const QString CmakeProjectConverterDialog::errorText() const
-{
- QString text;
-
- if (!m_nameEditor->isValid()) {
- QString name = m_nameEditor->text();
-
- if (name.isEmpty())
- return ERROR_TEXT_NAME_EMPTY;
-
- const QString badStart = startsWithBlacklisted(text);
- if (!badStart.isEmpty())
- return ERROR_TEXT_NAME_BAD_START.arg(badStart);
-
- if (name[0].isLower())
- return ERROR_TEXT_NAME_LOWERCASE_START;
-
- return ERROR_TEXT_NAME_BAD_CHARACTERS;
-
- }
-
- if (!m_dirSelector->isValid()) {
- FilePath path = m_dirSelector->filePath();
- if (!path.isDir())
- return ERROR_DIR_NOT_DIR;
- if (!path.isWritableDir())
- return ERROR_DIR_NOT_WRITABLE;
- }
-
- if (m_dirSelector->filePath().pathAppended(m_nameEditor->text()).exists())
- return ERROR_DIR_EXISTS;
-
- return text;
-}
-
-const QString CmakeProjectConverterDialog::uniqueProjectName(const FilePath &dir, const QString &oldName) const
-{
- for (unsigned i = 0; ; ++i) {
- QString name = oldName;
- if (i)
- name += QString::number(i);
- if (!dir.pathAppended(name).exists())
- return name;
- }
- return oldName;
-}
-
-bool CmakeProjectConverterDialog::isValid()
-{
- FilePath newPath = m_dirSelector->filePath().pathAppended(m_nameEditor->text());
- return m_dirSelector->isValid() && m_nameEditor->isValid() && !newPath.exists();
-}
-
-} //GenerateCmake
-} //QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverterdialog.h b/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverterdialog.h
deleted file mode 100644
index 071eec481a..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/cmakeprojectconverterdialog.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-
-#ifndef CMAKEPROJECTCONVERTERDIALOG_H
-#define CMAKEPROJECTCONVERTERDIALOG_H
-
-#include <qmlprojectmanager/qmlproject.h>
-#include <utils/fancylineedit.h>
-#include <utils/filepath.h>
-#include <utils/infolabel.h>
-#include <utils/pathchooser.h>
-
-#include <QDialog>
-
-namespace QmlProjectManager {
-namespace GenerateCmake {
-
-class CmakeProjectConverterDialog : public QDialog
-{
- Q_OBJECT
-
-public:
- CmakeProjectConverterDialog(const QmlProjectManager::QmlProject *oldProject);
- const Utils::FilePath newPath() const;
-
-public slots:
- void pathValidChanged();
-
-private:
- const QString startsWithBlacklisted(const QString &text) const;
- const QString errorText() const;
- const QString uniqueProjectName(const Utils::FilePath &dir, const QString &oldName) const;
- bool isValid();
-
-private:
- Utils::FilePath m_newProjectDir;
- Utils::FancyLineEdit *m_nameEditor;
- Utils::PathChooser *m_dirSelector;
- Utils::InfoLabel *m_errorLabel;
- QPushButton *m_okButton;
-};
-
-} //GenerateCmake
-} //QmlProjectManager
-
-#endif // CMAKEPROJECTCONVERTERDIALOG_H
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakewriter.cpp b/src/plugins/qmlprojectmanager/cmakegen/cmakewriter.cpp
new file mode 100644
index 0000000000..0b1d0c4c60
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/cmakegen/cmakewriter.cpp
@@ -0,0 +1,258 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+#include "cmakewriter.h"
+#include "cmakegenerator.h"
+#include "cmakewriterv0.h"
+#include "cmakewriterv1.h"
+
+#include "qmlprojectmanager/qmlproject.h"
+#include "qmlprojectmanager/buildsystem/qmlbuildsystem.h"
+
+#include "utils/namevalueitem.h"
+
+#include <QFile>
+#include <QTextStream>
+
+namespace QmlProjectManager {
+
+namespace GenerateCmake {
+
+const char TEMPLATE_BIG_RESOURCES[] = R"(
+qt6_add_resources(%1 %2
+ BIG_RESOURCES
+ PREFIX "%3"
+ VERSION 1.0
+ FILES %4
+))";
+
+CMakeWriter::Ptr CMakeWriter::create(CMakeGenerator *parent)
+{
+ const QmlProject *project = parent->qmlProject();
+ QTC_ASSERT(project, return {});
+
+ const QmlBuildSystem *buildSystem = parent->buildSystem();
+ QTC_ASSERT(buildSystem, return {});
+
+ const QString versionString = buildSystem->versionDesignStudio();
+ bool ok = false;
+ if (float version = versionString.toFloat(&ok); ok && version > 4.4)
+ return std::make_unique<CMakeWriterV1>(parent);
+
+ return std::make_unique<CMakeWriterV0>(parent);
+}
+
+QString CMakeWriter::readTemplate(const QString &templatePath)
+{
+ QFile templatefile(templatePath);
+ templatefile.open(QIODevice::ReadOnly);
+ QTextStream stream(&templatefile);
+ QString content = stream.readAll();
+ templatefile.close();
+ return content;
+}
+
+CMakeWriter::CMakeWriter(CMakeGenerator *parent)
+ : m_parent(parent)
+{}
+
+const CMakeGenerator *CMakeWriter::parent() const
+{
+ return m_parent;
+}
+
+bool CMakeWriter::isPlugin(const NodePtr &node) const
+{
+ if (node->type == Node::Type::Module)
+ return true;
+ return false;
+}
+
+QString CMakeWriter::sourceDirName() const
+{
+ return "src";
+}
+
+void CMakeWriter::transformNode(NodePtr &) const
+{}
+
+std::vector<Utils::FilePath> CMakeWriter::files(const NodePtr &node, const FileGetter &getter) const
+{
+ std::vector<Utils::FilePath> out = getter(node);
+ for (const NodePtr &child : node->subdirs) {
+ if (child->type == Node::Type::Module)
+ continue;
+
+ auto childFiles = files(child, getter);
+ out.insert(out.end(), childFiles.begin(), childFiles.end());
+ }
+ return out;
+}
+
+std::vector<Utils::FilePath> CMakeWriter::qmlFiles(const NodePtr &node) const
+{
+ return files(node, [](const NodePtr &n) { return n->files; });
+}
+
+std::vector<Utils::FilePath> CMakeWriter::singletons(const NodePtr &node) const
+{
+ return files(node, [](const NodePtr &n) { return n->singletons; });
+}
+
+std::vector<Utils::FilePath> CMakeWriter::resources(const NodePtr &node) const
+{
+ return files(node, [](const NodePtr &n) { return n->resources; });
+}
+
+std::vector<Utils::FilePath> CMakeWriter::sources(const NodePtr &node) const
+{
+ return files(node, [](const NodePtr &n) { return n->sources; });
+}
+
+std::vector<QString> CMakeWriter::plugins(const NodePtr &node) const
+{
+ QTC_ASSERT(parent(), return {});
+ std::vector<QString> out;
+ collectPlugins(node, out);
+ return out;
+}
+
+QString CMakeWriter::getEnvironmentVariable(const QString &key) const
+{
+ QTC_ASSERT(parent(), return {});
+
+ QString value;
+ if (m_parent->buildSystem()) {
+ auto envItems = m_parent->buildSystem()->environment();
+ auto confEnv = std::find_if(
+ envItems.begin(), envItems.end(), [key](const Utils::EnvironmentItem &item) {
+ return item.name == key;
+ });
+ if (confEnv != envItems.end())
+ value = confEnv->value;
+ }
+ return value;
+}
+
+QString CMakeWriter::makeRelative(const NodePtr &node, const Utils::FilePath &path) const
+{
+ const QString dir = node->dir.toString();
+ return "\"" + Utils::FilePath::calcRelativePath(path.toString(), dir) + "\"";
+}
+
+QString CMakeWriter::makeQmlFilesBlock(const NodePtr &node) const
+{
+ QTC_ASSERT(parent(), return {});
+
+ QString qmlFileContent;
+ for (const Utils::FilePath &path : qmlFiles(node))
+ qmlFileContent.append(QString("\t\t%1\n").arg(makeRelative(node, path)));
+
+ QString str;
+ if (!qmlFileContent.isEmpty())
+ str.append(QString("\tQML_FILES\n%1").arg(qmlFileContent));
+
+ return str;
+}
+
+QString CMakeWriter::makeSingletonBlock(const NodePtr &node) const
+{
+ QString str;
+ const QString setProperties("set_source_files_properties(%1\n\tPROPERTIES\n\t\t%2 %3\n)\n\n");
+ for (const Utils::FilePath &path : node->singletons)
+ str.append(setProperties.arg(path.fileName()).arg("QT_QML_SINGLETON_TYPE").arg("true"));
+ return str;
+}
+
+QString CMakeWriter::makeSubdirectoriesBlock(const NodePtr &node) const
+{
+ QTC_ASSERT(parent(), return {});
+
+ QString str;
+ for (const NodePtr &n : node->subdirs) {
+ if (n->type == Node::Type::Module || n->type == Node::Type::Library
+ || n->type == Node::Type::App || parent()->hasChildModule(n))
+ str.append(QString("add_subdirectory(%1)\n").arg(n->dir.fileName()));
+ }
+ return str;
+}
+
+QString CMakeWriter::makeSetEnvironmentFn() const
+{
+ QTC_ASSERT(parent(), return {});
+ QTC_ASSERT(parent()->buildSystem(), return {});
+
+ const QmlBuildSystem *buildSystem = parent()->buildSystem();
+ const QString configFile = getEnvironmentVariable(ENV_VARIABLE_CONTROLCONF);
+
+ QString out("inline void set_qt_environment() {\n");
+ for (Utils::EnvironmentItem &envItem : buildSystem->environment()) {
+ QString key = envItem.name;
+ QString value = envItem.value;
+ if (value == configFile)
+ value.prepend(":/");
+ out.append(QString("\tqputenv(\"%1\", \"%2\");\n").arg(key).arg(value));
+ }
+ out.append("}");
+
+ return out;
+}
+
+std::tuple<QString, QString> CMakeWriter::makeResourcesBlocks(const NodePtr &node) const
+{
+ QString resourcesOut;
+ QString bigResourcesOut;
+
+ QString resourceFiles;
+ std::vector<QString> bigResources;
+ for (const Utils::FilePath &path : resources(node)) {
+ if (path.fileSize() > 5000000) {
+ bigResources.push_back(makeRelative(node, path));
+ continue;
+ }
+ resourceFiles.append(QString("\t\t%1\n").arg(makeRelative(node, path)));
+ }
+
+ if (!resourceFiles.isEmpty())
+ resourcesOut.append(QString("\tRESOURCES\n%1").arg(resourceFiles));
+
+ QString templatePostfix;
+ if (!bigResources.empty()) {
+ QString resourceContent;
+ for (const QString &res : bigResources)
+ resourceContent.append(QString("\n %1").arg(res));
+
+ const QString prefixPath = QString(node->uri).replace('.', '/');
+ const QString prefix = "/qt/qml/" + prefixPath;
+ const QString resourceName = node->name + "BigResource";
+
+ bigResourcesOut = QString::fromUtf8(TEMPLATE_BIG_RESOURCES, -1)
+ .arg(node->name, resourceName, prefix, resourceContent);
+ }
+
+ return {resourcesOut, bigResourcesOut};
+}
+
+void CMakeWriter::writeFile(const Utils::FilePath &path, const QString &content) const
+{
+ QFile fileHandle(path.toString());
+ if (fileHandle.open(QIODevice::WriteOnly)) {
+ QTextStream stream(&fileHandle);
+ stream << content;
+ } else {
+ QString text("Failed to write");
+ CMakeGenerator::logIssue(ProjectExplorer::Task::Error, text, path);
+ }
+ fileHandle.close();
+}
+
+void CMakeWriter::collectPlugins(const NodePtr &node, std::vector<QString> &out) const
+{
+ if (isPlugin(node))
+ out.push_back(node->name);
+ for (const auto &child : node->subdirs)
+ collectPlugins(child, out);
+}
+
+} // End namespace GenerateCmake.
+
+} // End namespace QmlProjectManager.
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakewriter.h b/src/plugins/qmlprojectmanager/cmakegen/cmakewriter.h
new file mode 100644
index 0000000000..8766df0dcd
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/cmakegen/cmakewriter.h
@@ -0,0 +1,101 @@
+// 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 once
+
+#include "utils/filepath.h"
+
+#include <QString>
+
+namespace QmlProjectManager {
+
+class QmlProject;
+class QmlBuildSystem;
+
+namespace GenerateCmake {
+
+struct Node
+{
+ enum class Type {
+ App,
+ Module,
+ Library,
+ Folder,
+ };
+
+ std::shared_ptr<Node> parent = nullptr;
+ Type type = Type::Folder;
+
+ QString uri;
+ QString name;
+ Utils::FilePath dir;
+
+ std::vector<std::shared_ptr<Node>> subdirs;
+ std::vector<Utils::FilePath> files;
+ std::vector<Utils::FilePath> singletons;
+ std::vector<Utils::FilePath> resources;
+ std::vector<Utils::FilePath> sources;
+};
+
+using NodePtr = std::shared_ptr<Node>;
+using FileGetter = std::function<std::vector<Utils::FilePath>(const NodePtr &)>;
+
+class CMakeGenerator;
+
+const char ENV_VARIABLE_CONTROLCONF[] =
+ "QT_QUICK_CONTROLS_CONF";
+
+const char DO_NOT_EDIT_FILE[] =
+ "### This file is automatically generated by Qt Design Studio.\n"
+ "### Do not change\n\n";
+
+const char TEMPLATE_LINK_LIBRARIES[] =
+ "target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE\n"
+ "%3"
+ ")";
+
+class CMakeWriter
+{
+public:
+ using Ptr = std::shared_ptr<CMakeWriter>;
+
+ static Ptr create(CMakeGenerator *parent);
+ static QString readTemplate(const QString &templatePath);
+
+ CMakeWriter(CMakeGenerator *parent);
+ const CMakeGenerator *parent() const;
+
+ virtual bool isPlugin(const NodePtr &node) const;
+ virtual QString sourceDirName() const;
+ virtual void transformNode(NodePtr &) const;
+
+ virtual void writeRootCMakeFile(const NodePtr &node) const = 0;
+ virtual void writeModuleCMakeFile(const NodePtr &node, const NodePtr &root) const = 0;
+ virtual void writeSourceFiles(const NodePtr &node, const NodePtr &root) const = 0;
+
+protected:
+ std::vector<Utils::FilePath> files(const NodePtr &node, const FileGetter &getter) const;
+ std::vector<Utils::FilePath> qmlFiles(const NodePtr &node) const;
+ std::vector<Utils::FilePath> singletons(const NodePtr &node) const;
+ std::vector<Utils::FilePath> resources(const NodePtr &node) const;
+ std::vector<Utils::FilePath> sources(const NodePtr &node) const;
+ std::vector<QString> plugins(const NodePtr &node) const;
+
+ QString getEnvironmentVariable(const QString &key) const;
+
+ QString makeRelative(const NodePtr &node, const Utils::FilePath &path) const;
+ QString makeQmlFilesBlock(const NodePtr &node) const;
+ QString makeSingletonBlock(const NodePtr &node) const;
+ QString makeSubdirectoriesBlock(const NodePtr &node) const;
+ QString makeSetEnvironmentFn() const;
+ std::tuple<QString, QString> makeResourcesBlocks(const NodePtr &node) const;
+
+ void writeFile(const Utils::FilePath &path, const QString &content) const;
+
+private:
+ void collectPlugins(const NodePtr &node, std::vector<QString> &out) const;
+ const CMakeGenerator *m_parent = nullptr;
+};
+
+} // End namespace GenerateCmake.
+
+} // End namespace QmlProjectManager.
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakewriterv0.cpp b/src/plugins/qmlprojectmanager/cmakegen/cmakewriterv0.cpp
new file mode 100644
index 0000000000..5cb17d1e1b
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/cmakegen/cmakewriterv0.cpp
@@ -0,0 +1,180 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+#include "cmakewriterv0.h"
+#include "cmakegenerator.h"
+
+namespace QmlProjectManager {
+
+namespace GenerateCmake {
+
+const char TEMPLATE_ADD_QML_MODULE[] = R"(
+qt6_add_qml_module(%1
+ URI "%2"
+ VERSION 1.0
+ RESOURCE_PREFIX "/qt/qml"
+%3))";
+
+CMakeWriterV0::CMakeWriterV0(CMakeGenerator *parent)
+ : CMakeWriter(parent)
+{}
+
+bool CMakeWriterV0::isPlugin(const NodePtr &node) const
+{
+ if (node->type == Node::Type::App)
+ return !node->files.empty() || !node->singletons.empty() || !node->resources.empty();
+
+ return CMakeWriter::isPlugin(node);
+}
+
+void CMakeWriterV0::transformNode(NodePtr &node) const
+{
+ QTC_ASSERT(parent(), return);
+
+ if (node->name == "src") {
+ node->type = Node::Type::Folder;
+ } else if (node->name == "content") {
+ node->type = Node::Type::Module;
+ } else if (node->type == Node::Type::App) {
+ Utils::FilePath path = node->dir.pathAppended("main.qml");
+ if (!path.exists()) {
+ QString text("Expected File not found.");
+ CMakeGenerator::logIssue(ProjectExplorer::Task::Error, text, path);
+ return;
+ }
+ if (!parent()->findFile(path))
+ node->files.push_back(path);
+ }
+}
+
+void CMakeWriterV0::writeRootCMakeFile(const NodePtr &node) const
+{
+ QTC_ASSERT(parent(), return);
+
+ const Utils::FilePath quickControlsPath = node->dir.pathAppended("qtquickcontrols2.conf");
+ if (!quickControlsPath.exists()) {
+ const QString quickControlsTemplate = readTemplate(":/templates/qtquickcontrols_conf");
+ writeFile(quickControlsPath, quickControlsTemplate);
+ }
+
+ const Utils::FilePath insightPath = node->dir.pathAppended("insight");
+ if (!insightPath.exists()) {
+ const QString insightTemplate = readTemplate(":/templates/insight");
+ writeFile(insightPath, insightTemplate);
+ }
+
+ const Utils::FilePath componentPath = node->dir.pathAppended("qmlcomponents");
+ if (!componentPath.exists()) {
+ const QString compTemplate = readTemplate(":/templates/qmlcomponents");
+ writeFile(componentPath, compTemplate);
+ }
+
+ const QString appName = parent()->projectName() + "App";
+ const QString qtcontrolsConfFile = getEnvironmentVariable(ENV_VARIABLE_CONTROLCONF);
+
+ QString fileSection = "";
+ if (!qtcontrolsConfFile.isEmpty())
+ fileSection = QString("\tFILES\n\t\t%1").arg(qtcontrolsConfFile);
+
+ QStringList srcs;
+ for (const Utils::FilePath &path : sources(node))
+ srcs.push_back(makeRelative(node, path));
+
+ const QString fileTemplate = readTemplate(":/templates/cmakeroot_v0");
+ const QString fileContent = fileTemplate.arg(appName, srcs.join(" "), fileSection);
+
+ const Utils::FilePath cmakeFile = node->dir.pathAppended("CMakeLists.txt");
+ writeFile(cmakeFile, fileContent);
+}
+
+void CMakeWriterV0::writeModuleCMakeFile(const NodePtr &node, const NodePtr &root) const
+{
+ QTC_ASSERT(parent(), return);
+
+ Utils::FilePath writeToFile = node->dir.pathAppended("CMakeLists.txt");
+
+ QString content(DO_NOT_EDIT_FILE);
+ if (node->type == Node::Type::Folder && parent()->hasChildModule(node)) {
+ content.append(makeSubdirectoriesBlock(node));
+ writeFile(writeToFile, content);
+ return;
+ }
+
+ content.append(makeSubdirectoriesBlock(node));
+ content.append("\n");
+ content.append(makeSingletonBlock(node));
+
+ QString qmlModulesContent;
+ qmlModulesContent.append(makeQmlFilesBlock(node));
+
+ auto [resources, bigResources] = makeResourcesBlocks(node);
+ qmlModulesContent.append(resources);
+
+ if (!qmlModulesContent.isEmpty()) {
+ const QString addLibraryTemplate("qt_add_library(%1 STATIC)");
+ const QString addModuleTemplate(TEMPLATE_ADD_QML_MODULE);
+
+ content.append(addLibraryTemplate.arg(node->name));
+ content.append(addModuleTemplate.arg(node->name, node->uri, qmlModulesContent));
+ content.append("\n\n");
+ }
+
+ content.append(bigResources);
+
+ if (node->type == Node::Type::App) {
+ writeToFile = node->dir.pathAppended("qmlModules");
+ QString pluginNames;
+ for (const QString &moduleName : plugins(root))
+ pluginNames.append("\t" + moduleName + "plugin\n");
+
+ if (!pluginNames.isEmpty())
+ content += QString::fromUtf8(TEMPLATE_LINK_LIBRARIES, -1).arg(pluginNames);
+ }
+
+ writeFile(writeToFile, content);
+}
+
+void CMakeWriterV0::writeSourceFiles(const NodePtr &node, const NodePtr &root) const
+{
+ QTC_ASSERT(parent(), return);
+
+ const Utils::FilePath srcDir = node->dir;
+ if (!srcDir.exists()) {
+ srcDir.createDir();
+
+ const Utils::FilePath componentsHeaderPath = srcDir.pathAppended(
+ "import_qml_components_plugins.h");
+ const QString componentsHeaderContent = readTemplate(
+ ":/templates/import_qml_components_h");
+ writeFile(componentsHeaderPath, componentsHeaderContent);
+
+ const Utils::FilePath cppFilePath = srcDir.pathAppended("main.cpp");
+ const QString cppContent = readTemplate(":/templates/main_cpp_v0");
+ writeFile(cppFilePath, cppContent);
+ }
+
+ QString fileHeader(
+ "/*\n"
+ " * This file is automatically generated by Qt Design Studio.\n"
+ " * Do not change\n"
+ "*/\n\n");
+
+ const Utils::FilePath envHeaderPath = srcDir.pathAppended("app_environment.h");
+ QString envHeaderContent(fileHeader);
+ envHeaderContent.append("#include <QGuiApplication>\n\n");
+ envHeaderContent.append(makeSetEnvironmentFn());
+ writeFile(envHeaderPath, envHeaderContent);
+
+ QString importPluginsContent;
+ for (const QString &module : plugins(root))
+ importPluginsContent.append(QString("Q_IMPORT_QML_PLUGIN(%1)\n").arg(module + "Plugin"));
+
+ QString importPluginsHeader(fileHeader);
+ importPluginsHeader.append("#include <QtQml/qqmlextensionplugin.h>\n\n");
+ importPluginsHeader.append(importPluginsContent);
+
+ const Utils::FilePath headerFilePath = srcDir.pathAppended("import_qml_plugins.h");
+ writeFile(headerFilePath, importPluginsHeader);
+}
+
+} // namespace GenerateCmake
+} // namespace QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakewriterv0.h b/src/plugins/qmlprojectmanager/cmakegen/cmakewriterv0.h
new file mode 100644
index 0000000000..a1cd16d0fc
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/cmakegen/cmakewriterv0.h
@@ -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
+#pragma once
+
+#include "cmakewriter.h"
+
+namespace QmlProjectManager {
+
+namespace GenerateCmake {
+
+class CMakeWriterV0 final : public CMakeWriter
+{
+public:
+ CMakeWriterV0(CMakeGenerator *parent);
+
+ bool isPlugin(const NodePtr &node) const override;
+ void transformNode(NodePtr &node) const override;
+
+ void writeRootCMakeFile(const NodePtr &node) const override;
+ void writeModuleCMakeFile(const NodePtr &node, const NodePtr &root) const override;
+ void writeSourceFiles(const NodePtr &node, const NodePtr &root) const override;
+};
+
+} // namespace GenerateCmake
+} // namespace QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakewriterv1.cpp b/src/plugins/qmlprojectmanager/cmakegen/cmakewriterv1.cpp
new file mode 100644
index 0000000000..6d2d93a76b
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/cmakegen/cmakewriterv1.cpp
@@ -0,0 +1,185 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+#include "cmakewriterv1.h"
+#include "cmakegenerator.h"
+
+#include "qmlprojectmanager/buildsystem/qmlbuildsystem.h"
+
+namespace QmlProjectManager {
+
+namespace GenerateCmake {
+
+const char TEMPLATE_SRC_CMAKELISTS[] = R"(
+target_sources(${CMAKE_PROJECT_NAME} PUBLIC
+%2)
+
+target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE
+ Qt${QT_VERSION_MAJOR}::Core
+ Qt${QT_VERSION_MAJOR}::Gui
+ Qt${QT_VERSION_MAJOR}::Quick
+ Qt${QT_VERSION_MAJOR}::Qml))";
+
+CMakeWriterV1::CMakeWriterV1(CMakeGenerator *parent)
+ : CMakeWriter(parent)
+{}
+
+QString CMakeWriterV1::sourceDirName() const
+{
+ return "App";
+}
+
+void CMakeWriterV1::transformNode(NodePtr &node) const
+{
+ QTC_ASSERT(parent(), return);
+
+ QString contentDir = parent()->projectName() + "Content";
+ if (node->name == contentDir)
+ node->type = Node::Type::Module;
+}
+
+void CMakeWriterV1::writeRootCMakeFile(const NodePtr &node) const
+{
+ QTC_ASSERT(parent(), return);
+
+ const Utils::FilePath cmakeFolderPath = node->dir.pathAppended("cmake");
+ if (!cmakeFolderPath.exists())
+ cmakeFolderPath.createDir();
+
+ const Utils::FilePath insightPath = cmakeFolderPath.pathAppended("insight.cmake");
+ if (!insightPath.exists()) {
+ const QString insightTemplate = readTemplate(":/templates/insight");
+ writeFile(insightPath, insightTemplate);
+ }
+
+ const Utils::FilePath componentPath = cmakeFolderPath.pathAppended("qmlcomponents.cmake");
+ if (!componentPath.exists()) {
+ const QString compTemplate = readTemplate(":/templates/qmlcomponents");
+ writeFile(componentPath, compTemplate);
+ }
+
+ const Utils::FilePath sharedFile = node->dir.pathAppended("CMakeLists.txt.shared");
+ if (!sharedFile.exists()) {
+ const QString sharedTemplate = readTemplate(":/templates/cmake_shared");
+ writeFile(sharedFile, sharedTemplate);
+ }
+
+ const Utils::FilePath file = node->dir.pathAppended("CMakeLists.txt");
+ if (!file.exists()) {
+ const QString appName = parent()->projectName() + "App";
+
+ QString fileSection = "";
+ const QString configFile = getEnvironmentVariable(ENV_VARIABLE_CONTROLCONF);
+ if (!configFile.isEmpty())
+ fileSection = QString("\t\t%1").arg(configFile);
+
+ const QString fileTemplate = readTemplate(":/templates/cmakeroot_v1");
+ const QString fileContent = fileTemplate.arg(appName, fileSection);
+ writeFile(file, fileContent);
+ }
+}
+
+void CMakeWriterV1::writeModuleCMakeFile(const NodePtr &node, const NodePtr &) const
+{
+ QTC_ASSERT(parent(), return);
+
+ if (node->type == Node::Type::App) {
+ const Utils::FilePath userFile = node->dir.pathAppended("qds.cmake");
+ QString userFileContent(DO_NOT_EDIT_FILE);
+ userFileContent.append(makeSubdirectoriesBlock(node));
+ userFileContent.append("\n");
+
+ QString pluginNames;
+ std::vector<QString> plugs = plugins(node);
+ for (size_t i = 0; i < plugs.size(); ++i) {
+ pluginNames.append("\t" + plugs[i] + "plugin");
+ if (i != plugs.size() - 1)
+ pluginNames.append("\n");
+ }
+
+ QString linkLibrariesTemplate(
+ "target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE\n"
+ "%1)");
+
+ userFileContent.append(linkLibrariesTemplate.arg(pluginNames));
+ writeFile(userFile, userFileContent);
+ return;
+ }
+
+ Utils::FilePath writeToFile = node->dir.pathAppended("CMakeLists.txt");
+ if (node->type == Node::Type::Folder && parent()->hasChildModule(node)) {
+ QString content(DO_NOT_EDIT_FILE);
+ content.append(makeSubdirectoriesBlock(node));
+ writeFile(writeToFile, content);
+ return;
+ }
+
+ QString prefix;
+ prefix.append(makeSubdirectoriesBlock(node));
+ prefix.append(makeSingletonBlock(node));
+
+ auto [resources, bigResources] = makeResourcesBlocks(node);
+ QString moduleContent;
+ moduleContent.append(makeQmlFilesBlock(node));
+ moduleContent.append(resources);
+
+ QString postfix;
+ postfix.append(bigResources);
+
+ const QString fileTemplate = readTemplate(":/templates/cmakemodule_v1");
+ const QString fileContent = fileTemplate
+ .arg(node->name, node->uri, prefix, moduleContent, postfix);
+ writeFile(writeToFile, fileContent);
+}
+
+void CMakeWriterV1::writeSourceFiles(const NodePtr &node, const NodePtr &root) const
+{
+ QTC_ASSERT(parent(), return);
+ QTC_ASSERT(parent()->buildSystem(), return);
+
+ const QmlBuildSystem *buildSystem = parent()->buildSystem();
+
+ const Utils::FilePath srcDir = node->dir;
+ if (!srcDir.exists())
+ srcDir.createDir();
+
+ const Utils::FilePath autogenDir = srcDir.pathAppended("autogen");
+ if (!autogenDir.exists())
+ autogenDir.createDir();
+
+ const Utils::FilePath mainCppPath = srcDir.pathAppended("main.cpp");
+ if (!mainCppPath.exists()) {
+ const QString cppContent = readTemplate(":/templates/main_cpp_v1");
+ writeFile(mainCppPath, cppContent);
+ }
+
+ const Utils::FilePath cmakePath = srcDir.pathAppended("CMakeLists.txt");
+ if (!cmakePath.exists()) {
+ std::vector<Utils::FilePath> sourcePaths = sources(node);
+ if (sourcePaths.empty())
+ sourcePaths.push_back(mainCppPath);
+
+ QString srcs = {};
+ for (const Utils::FilePath &src : sourcePaths)
+ srcs.append("\t" + makeRelative(node, src) + "\n");
+
+ QString fileTemplate = QString::fromUtf8(TEMPLATE_SRC_CMAKELISTS, -1).arg(srcs);
+ writeFile(cmakePath, fileTemplate);
+ }
+
+ const Utils::FilePath headerPath = autogenDir.pathAppended("environment.h");
+
+ QString environmentPrefix;
+ for (const QString &module : plugins(root))
+ environmentPrefix.append(QString("Q_IMPORT_QML_PLUGIN(%1)\n").arg(module + "Plugin"));
+
+ const QString mainFile("const char mainQmlFile[] = \"qrc:/qt/qml/%1\";");
+ environmentPrefix.append("\n");
+ environmentPrefix.append(mainFile.arg(buildSystem->mainFile()));
+
+ const QString environmentPostfix = makeSetEnvironmentFn();
+ const QString headerTemplate = readTemplate(":/templates/environment_h");
+ writeFile(headerPath, headerTemplate.arg(environmentPrefix, environmentPostfix));
+}
+
+} // namespace GenerateCmake
+} // namespace QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/cmakegen/cmakewriterv1.h b/src/plugins/qmlprojectmanager/cmakegen/cmakewriterv1.h
new file mode 100644
index 0000000000..2a6a05b07b
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/cmakegen/cmakewriterv1.h
@@ -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
+#pragma once
+
+#include "cmakewriter.h"
+
+namespace QmlProjectManager {
+
+namespace GenerateCmake {
+
+class CMakeWriterV1 final : public CMakeWriter
+{
+public:
+ CMakeWriterV1(CMakeGenerator *parent);
+
+ QString sourceDirName() const override;
+ void transformNode(NodePtr &node) const override;
+
+ void writeRootCMakeFile(const NodePtr &node) const override;
+ void writeModuleCMakeFile(const NodePtr &node, const NodePtr &root) const override;
+ void writeSourceFiles(const NodePtr &node, const NodePtr &root) const override;
+};
+
+} // namespace GenerateCmake
+} // namespace QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.cpp b/src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.cpp
deleted file mode 100644
index f46b508c8c..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.cpp
+++ /dev/null
@@ -1,668 +0,0 @@
-// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#include "generatecmakelists.h"
-
-#include "generatecmakelistsconstants.h"
-#include "cmakegeneratordialog.h"
-#include "../qmlprojectmanagertr.h"
-
-#include <coreplugin/actionmanager/actionmanager.h>
-#include <coreplugin/actionmanager/actioncontainer.h>
-
-#include <projectexplorer/buildsystem.h>
-#include <projectexplorer/project.h>
-#include <projectexplorer/projectexplorerconstants.h>
-#include <projectexplorer/projectmanager.h>
-#include <projectexplorer/target.h>
-
-#include <qmlprojectmanager/buildsystem/qmlbuildsystem.h>
-#include <qmlprojectmanager/qmlmainfileaspect.h>
-#include <qmlprojectmanager/qmlproject.h>
-#include <qmlprojectmanager/qmlprojectconstants.h>
-
-#include <extensionsystem/iplugin.h>
-#include <extensionsystem/pluginmanager.h>
-#include <extensionsystem/pluginspec.h>
-
-#include <utils/fileutils.h>
-
-#include <QAction>
-#include <QMenu>
-#include <QMessageBox>
-#include <QRegularExpression>
-#include <QStringList>
-#include <QTextStream>
-#include <QtConcurrent>
-
-using namespace Utils;
-using namespace QmlProjectManager::GenerateCmake::Constants;
-
-namespace QmlProjectManager {
-
-namespace GenerateCmake {
-
-static bool isQmlDesigner(const ExtensionSystem::PluginSpec *spec)
-{
- if (!spec)
- return false;
-
- return spec->name().contains("QmlDesigner");
-}
-
-static void trackUsage(const QString &id)
-{
- const auto plugins = ExtensionSystem::PluginManager::plugins();
- const auto it = std::find_if(plugins.begin(), plugins.end(), &isQmlDesigner);
- if (it != plugins.end()) {
- QObject *qmlDesignerPlugin = (*it)->plugin();
- QMetaObject::invokeMethod(qmlDesignerPlugin,
- "usageStatisticsNotifier",
- Qt::DirectConnection,
- Q_ARG(QString, id));
- }
-}
-
-bool operator==(const GeneratableFile &left, const GeneratableFile &right)
-{
- return (left.filePath == right.filePath && left.content == right.content);
-}
-
-enum ProjectDirectoryError {
- NoError = 0,
- MissingContentDir = 1<<1,
- MissingImportDir = 1<<2,
- MissingAssetDir = 1<<3,
- MissingAssetImportDir = 1<<4,
- MissingCppDir = 1<<5,
- MissingMainCMake = 1<<6,
- MissingMainQml = 1<<7,
- MissingAppMainQml = 1<<8,
- MissingQmlModules = 1<<9,
- MissingMainCpp = 1<<10,
- MissingMainCppHeader = 1<<11,
- MissingEnvHeader = 1<<12
-};
-
-const QString MENU_ITEM_GENERATE = Tr::tr("Generate CMake Build Files...");
-
-void generateMenuEntry(QObject *parent)
-{
- Core::ActionContainer *menu = Core::ActionManager::actionContainer(Core::Constants::M_FILE);
-
- Core::ActionContainer *exportMenu = Core::ActionManager::createMenu(
- QmlProjectManager::Constants::EXPORT_MENU);
-
- exportMenu->menu()->setTitle(Tr::tr("Export Project"));
- menu->addMenu(exportMenu, Core::Constants::G_FILE_EXPORT);
-
- exportMenu->appendGroup(QmlProjectManager::Constants::G_EXPORT_GENERATE);
- exportMenu->appendGroup(QmlProjectManager::Constants::G_EXPORT_CONVERT);
- exportMenu->addSeparator(QmlProjectManager::Constants::G_EXPORT_CONVERT);
-
- auto action = new QAction(MENU_ITEM_GENERATE, parent);
- QObject::connect(action, &QAction::triggered, GenerateCmake::onGenerateCmakeLists);
- Core::Command *cmd = Core::ActionManager::registerAction(action, "QmlProject.CreateCMakeLists");
- exportMenu->addAction(cmd, QmlProjectManager::Constants::G_EXPORT_GENERATE);
-
- action->setEnabled(false);
- QObject::connect(ProjectExplorer::ProjectManager::instance(),
- &ProjectExplorer::ProjectManager::startupProjectChanged,
- [action]() {
- if (auto buildSystem = QmlBuildSystem::getStartupBuildSystem())
- action->setEnabled(!buildSystem->qtForMCUs());
- });
-}
-
-void onGenerateCmakeLists()
-{
- trackUsage("generateCMakeProjectDialogOpened");
- FilePath rootDir = ProjectExplorer::ProjectManager::startupProject()->projectDirectory();
-
- int projectDirErrors = isProjectCorrectlyFormed(rootDir);
- if (projectDirErrors != NoError) {
- showProjectDirErrorDialog(projectDirErrors);
- if (isErrorFatal(projectDirErrors))
- return;
- }
-
- CmakeFileGenerator cmakeGen;
- cmakeGen.prepare(rootDir);
-
- FilePaths allFiles;
- for (const GeneratableFile &file: cmakeGen.fileQueue().queuedFiles())
- allFiles.append(file.filePath);
-
- CmakeGeneratorDialog dialog(rootDir, allFiles, cmakeGen.invalidFileNames());
- if (dialog.exec()) {
- FilePaths confirmedFiles = dialog.getFilePaths();
- cmakeGen.filterFileQueue(confirmedFiles);
- cmakeGen.execute();
- }
-
- trackUsage("generateCMakeProjectExecuted");
-}
-
-bool isErrorFatal(int error)
-{
- if (error & MissingContentDir ||
- error & MissingImportDir ||
- error & MissingCppDir ||
- error & MissingAppMainQml)
- return true;
-
- return false;
-}
-
-int isProjectCorrectlyFormed(const FilePath &rootDir)
-{
- int errors = NoError;
-
- if (!rootDir.pathAppended(DIRNAME_CONTENT).exists())
- errors |= MissingContentDir;
- if (!rootDir.pathAppended(DIRNAME_CONTENT).pathAppended(FILENAME_APPMAINQML).exists())
- errors |= MissingAppMainQml;
-
- if (!rootDir.pathAppended(DIRNAME_IMPORT).exists())
- errors |= MissingImportDir;
- if (!rootDir.pathAppended(DIRNAME_ASSETIMPORT).exists())
- errors |= MissingAssetImportDir;
-
- if (!rootDir.pathAppended(DIRNAME_CPP).exists())
- errors |= MissingCppDir;
- if (!rootDir.pathAppended(DIRNAME_CPP).pathAppended(FILENAME_MAINCPP).exists())
- errors |= MissingMainCpp;
- if (!rootDir.pathAppended(DIRNAME_CPP).pathAppended(FILENAME_MAINCPP_HEADER).exists())
- errors |= MissingMainCppHeader;
- if (!rootDir.pathAppended(DIRNAME_CPP).pathAppended(FILENAME_ENV_HEADER).exists())
- errors |= MissingEnvHeader;
-
- if (!rootDir.pathAppended(FILENAME_CMAKELISTS).exists())
- errors |= MissingMainCMake;
- if (!rootDir.pathAppended(FILENAME_MODULES).exists())
- errors |= MissingQmlModules;
- if (!rootDir.pathAppended(FILENAME_MAINQML).exists())
- errors |= MissingMainQml;
-
- return errors;
-}
-
-const QString WARNING_MISSING_STRUCTURE_FATAL = Tr::tr("The project is not properly structured for automatically generating CMake files.\n\nAborting process.\n\nThe following files or directories are missing:\n\n%1");
-//const QString WARNING_MISSING_STRUCTURE_NONFATAL = Tr::tr("The project is not properly structured for automatically generating CMake files.\n\nThe following files or directories are missing and may be created:\n\n%1");
-const QString WARNING_TITLE_FATAL = Tr::tr("Cannot Generate CMake Files");
-//const QString WARNING_TITLE_NONFATAL = Tr::tr("Problems with Generating CMake Files");
-
-void showProjectDirErrorDialog(int error)
-{
- bool isFatal = isErrorFatal(error);
-
- if (isFatal) {
- QString fatalList;
-
- if (error & MissingContentDir)
- fatalList.append(QString(DIRNAME_CONTENT) + "\n");
- if (error & MissingAppMainQml)
- fatalList.append(QString(DIRNAME_CONTENT)
- + QDir::separator()
- + QString(FILENAME_APPMAINQML)
- + "\n");
- if (error & MissingCppDir)
- fatalList.append(QString(DIRNAME_CPP) + "\n");
- if (error & MissingImportDir)
- fatalList.append(QString(DIRNAME_IMPORT) + "\n");
-
- QMessageBox::critical(nullptr,
- WARNING_TITLE_FATAL,
- WARNING_MISSING_STRUCTURE_FATAL.arg(fatalList));
- }
-}
-
-bool FileQueue::queueFile(const FilePath &filePath, const QString &fileContent)
-{
- GeneratableFile file;
- file.filePath = filePath;
- file.content = fileContent;
- file.fileExists = filePath.exists();
- m_queuedFiles.append(file);
-
- return true;
-}
-
-const QVector<GeneratableFile> FileQueue::queuedFiles() const
-{
- return m_queuedFiles;
-}
-
-bool FileQueue::writeQueuedFiles()
-{
- for (GeneratableFile &file: m_queuedFiles)
- if (!writeFile(file))
- return false;
-
- return true;
-}
-
-bool FileQueue::writeFile(const GeneratableFile &file)
-{
- QFile fileHandle(file.filePath.toString());
- fileHandle.open(QIODevice::WriteOnly);
- QTextStream stream(&fileHandle);
- stream << file.content;
- fileHandle.close();
-
- return true;
-}
-
-void FileQueue::filterFiles(const Utils::FilePaths keepFiles)
-{
- QtConcurrent::blockingFilter(m_queuedFiles, [keepFiles](const GeneratableFile &qf) {
- return keepFiles.contains(qf.filePath);
- });
-}
-
-QString readTemplate(const QString &templatePath)
-{
- QFile templatefile(templatePath);
- templatefile.open(QIODevice::ReadOnly);
- QTextStream stream(&templatefile);
- QString content = stream.readAll();
- templatefile.close();
-
- return content;
-}
-
-const QString projectEnvironmentVariable(const QString &key)
-{
- QString value = {};
-
- if (auto buildSystem = QmlBuildSystem::getStartupBuildSystem()) {
- auto envItems = buildSystem->environment();
- auto confEnv = std::find_if(envItems.begin(), envItems.end(), [key](EnvironmentItem &item) {
- return item.name == key;
- });
- if (confEnv != envItems.end())
- value = confEnv->value;
- }
-
- return value;
-}
-
-const QDir::Filters FILES_ONLY = QDir::Files;
-const QDir::Filters DIRS_ONLY = QDir::Dirs|QDir::Readable|QDir::NoDotAndDotDot;
-
-const char MAIN_CMAKEFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmaincmakelists.tpl";
-const char QMLMODULES_FILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmodules.tpl";
-
-bool CmakeFileGenerator::prepare(const FilePath &rootDir, bool checkFileBelongs)
-{
- m_checkFileIsInProject = checkFileBelongs;
-
- FilePath contentDir = rootDir.pathAppended(DIRNAME_CONTENT);
- FilePath importDir = rootDir.pathAppended(DIRNAME_IMPORT);
- FilePath assetImportDir = rootDir.pathAppended(DIRNAME_ASSETIMPORT);
-
- generateModuleCmake(contentDir);
- generateImportCmake(importDir);
- generateImportCmake(assetImportDir);
- generateMainCmake(rootDir);
- generateEntryPointFiles(rootDir);
-
- return true;
-}
-
-const FileQueue CmakeFileGenerator::fileQueue() const
-{
- return m_fileQueue;
-}
-
-void CmakeFileGenerator::filterFileQueue(const Utils::FilePaths &keepFiles)
-{
- m_fileQueue.filterFiles(keepFiles);
-}
-
-bool CmakeFileGenerator::execute()
-{
- return m_fileQueue.writeQueuedFiles();
-}
-
-FilePaths CmakeFileGenerator::invalidFileNames() const
-{
- return m_invalidFileNames;
-}
-
-const char DO_NOT_EDIT_FILE_COMMENT[] = "### This file is automatically generated by Qt Design Studio.\n### Do not change\n\n";
-const char ADD_SUBDIR[] = "add_subdirectory(%1)\n";
-
-void CmakeFileGenerator::generateMainCmake(const FilePath &rootDir)
-{
- //TODO startupProject() may be a terrible way to try to get "current project". It's not necessarily the same thing at all.
- QString projectName = ProjectExplorer::ProjectManager::startupProject()->displayName();
- QString appName = projectName + "App";
-
- QString fileSection = "";
- const QString qtcontrolsConfFile = GenerateCmake::projectEnvironmentVariable(ENV_VARIABLE_CONTROLCONF);
- if (!qtcontrolsConfFile.isEmpty())
- fileSection = QString(" FILES\n %1").arg(qtcontrolsConfFile);
-
- QString cmakeFileContent = GenerateCmake::readTemplate(MAIN_CMAKEFILE_TEMPLATE_PATH)
- .arg(appName)
- .arg(fileSection);
-
- queueCmakeFile(rootDir, cmakeFileContent);
-
- QString subdirIncludes;
- subdirIncludes.append(QString(ADD_SUBDIR).arg(DIRNAME_CONTENT));
- subdirIncludes.append(QString(ADD_SUBDIR).arg(DIRNAME_IMPORT));
- if (rootDir.pathAppended(DIRNAME_ASSETIMPORT).exists())
- subdirIncludes.append(QString(ADD_SUBDIR).arg(DIRNAME_ASSETIMPORT));
-
- QString modulesAsPlugins;
- for (const QString &moduleName : m_moduleNames)
- modulesAsPlugins.append(" " + moduleName + "plugin\n");
-
- QString moduleFileContent = GenerateCmake::readTemplate(QMLMODULES_FILE_TEMPLATE_PATH)
- .arg(appName)
- .arg(subdirIncludes)
- .arg(modulesAsPlugins);
-
- m_fileQueue.queueFile(rootDir.pathAppended(FILENAME_MODULES), moduleFileContent);
-}
-
-void CmakeFileGenerator::generateImportCmake(const FilePath &dir, const QString &modulePrefix)
-{
- if (!dir.exists())
- return;
-
- QString fileContent;
-
- fileContent.append(DO_NOT_EDIT_FILE_COMMENT);
- FilePaths subDirs = dir.dirEntries(DIRS_ONLY);
- for (FilePath &subDir : subDirs) {
- if (isDirBlacklisted(subDir))
- continue;
- if (getDirectoryTreeQmls(subDir).isEmpty() && getDirectoryTreeResources(subDir).isEmpty())
- continue;
- fileContent.append(QString(ADD_SUBDIR).arg(subDir.fileName()));
- QString prefix = modulePrefix.isEmpty() ?
- QString(modulePrefix % subDir.fileName()) :
- QString(QString(modulePrefix + '.') + subDir.fileName());
- if (getDirectoryQmls(subDir).isEmpty()) {
- generateImportCmake(subDir, prefix);
- } else {
- generateModuleCmake(subDir, prefix);
- }
- }
-
- queueCmakeFile(dir, fileContent);
-}
-
-const char MODULEFILE_PROPERTY_SINGLETON[] = "QT_QML_SINGLETON_TYPE";
-const char MODULEFILE_PROPERTY_SET[] = "set_source_files_properties(%1\n PROPERTIES\n %2 %3\n)\n\n";
-const char MODULEFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmodulecmakelists.tpl";
-
-void CmakeFileGenerator::generateModuleCmake(const FilePath &dir, const QString &uri)
-{
- QString fileTemplate = GenerateCmake::readTemplate(MODULEFILE_TEMPLATE_PATH);
-
- QString singletonContent;
- FilePaths qmldirFileList = dir.dirEntries({QStringList(FILENAME_QMLDIR), FILES_ONLY});
- if (!qmldirFileList.isEmpty()) {
- QStringList singletons = getSingletonsFromQmldirFile(qmldirFileList.first());
- for (QString &singleton : singletons) {
- singletonContent.append(QString(MODULEFILE_PROPERTY_SET).arg(singleton).arg(MODULEFILE_PROPERTY_SINGLETON).arg("true"));
- }
- }
-
- QStringList qmlFileList = getDirectoryTreeQmls(dir);
- QString qmlFiles;
- for (QString &qmlFile : qmlFileList)
- qmlFiles.append(QString(" %1\n").arg(qmlFile));
-
- QStringList resourceFileList = getDirectoryTreeResources(dir);
- QString resourceFiles;
- for (QString &resourceFile : resourceFileList)
- resourceFiles.append(QString(" %1\n").arg(resourceFile));
-
- QString moduleContent;
- if (!qmlFiles.isEmpty()) {
- moduleContent.append(QString(" QML_FILES\n%1").arg(qmlFiles));
- }
- if (!resourceFiles.isEmpty()) {
- moduleContent.append(QString(" RESOURCES\n%1").arg(resourceFiles));
- }
-
- QString moduleUri = uri.isEmpty() ?
- dir.fileName() :
- uri;
-
- QString moduleName = QString(moduleUri).replace('.', '_');
- m_moduleNames.append(moduleName);
-
- QString fileContent;
- fileContent.append(fileTemplate.arg(singletonContent, moduleName, moduleUri, moduleContent));
- queueCmakeFile(dir, fileContent);
-}
-
-QStringList CmakeFileGenerator::getSingletonsFromQmldirFile(const FilePath &filePath)
-{
- QStringList singletons;
- QFile f(filePath.toString());
- f.open(QIODevice::ReadOnly);
- QTextStream stream(&f);
-
- while (!stream.atEnd()) {
- QString line = stream.readLine();
- if (line.startsWith("singleton", Qt::CaseInsensitive)) {
- QStringList tokenizedLine = line.split(QRegularExpression("\\s+"));
- QString fileName = tokenizedLine.last();
- if (fileName.endsWith(".qml", Qt::CaseInsensitive)) {
- singletons.append(fileName);
- }
- }
- }
-
- f.close();
-
- return singletons;
-}
-
-QStringList CmakeFileGenerator::getDirectoryQmls(const FilePath &dir)
-{
- QStringList moduleFiles;
-
- const QStringList qmlFilesOnly(FILENAME_FILTER_QML);
- FilePaths allFiles = dir.dirEntries({qmlFilesOnly, FILES_ONLY});
- for (FilePath &file : allFiles) {
- if (includeFile(file)) {
- moduleFiles.append(file.fileName());
- }
- }
-
- return moduleFiles;
-}
-
-QStringList CmakeFileGenerator::getDirectoryResources(const FilePath &dir)
-{
- QStringList moduleFiles;
-
- FilePaths allFiles = dir.dirEntries(FILES_ONLY);
- for (FilePath &file : allFiles) {
- if (!file.fileName().endsWith(".qml", Qt::CaseInsensitive) && includeFile(file)) {
- moduleFiles.append(file.fileName());
- }
- }
-
- return moduleFiles;
-}
-
-QStringList CmakeFileGenerator::getDirectoryTreeQmls(const FilePath &dir)
-{
- QStringList qmlFileList;
-
- qmlFileList.append(getDirectoryQmls(dir));
-
- FilePaths subDirsList = dir.dirEntries(DIRS_ONLY);
- for (FilePath &subDir : subDirsList) {
- if (isDirBlacklisted(subDir))
- continue;
- QStringList subDirQmlFiles = getDirectoryTreeQmls(subDir);
- for (QString &qmlFile : subDirQmlFiles) {
- qmlFileList.append(subDir.fileName().append('/').append(qmlFile));
- }
- }
-
- return qmlFileList;
-}
-
-static void appendWidthQuotes(QStringList &list, const QString &string)
-{
- if (string.contains(' '))
- list.append("\"" + string + "\"");
- else
- list.append(string);
-}
-
-QStringList CmakeFileGenerator::getDirectoryTreeResources(const FilePath &dir)
-{
- QStringList resourceFileList;
-
- //for (const auto &string : getDirectoryResources(dir))
- // appendWidthQuotes(resourceFileList, string);
- resourceFileList.append(getDirectoryResources(dir));
-
- FilePaths subDirsList = dir.dirEntries(DIRS_ONLY);
- for (FilePath &subDir : subDirsList) {
- if (isDirBlacklisted(subDir))
- continue;
- QStringList subDirResources = getDirectoryTreeResources(subDir);
- for (QString &resource : subDirResources) {
- appendWidthQuotes(resourceFileList, subDir.fileName().append('/').append(resource));
- }
- }
-
- return resourceFileList;
-}
-
-void CmakeFileGenerator::queueCmakeFile(const FilePath &dir, const QString &content)
-{
- FilePath filePath = dir.pathAppended(FILENAME_CMAKELISTS);
- m_fileQueue.queueFile(filePath, content);
-}
-
-bool CmakeFileGenerator::isFileBlacklisted(const QString &fileName)
-{
- return (!fileName.compare(FILENAME_QMLDIR) ||
- !fileName.compare(FILENAME_CMAKELISTS));
-}
-
-bool CmakeFileGenerator::isDirBlacklisted(const FilePath &dir)
-{
- return (!dir.fileName().compare(DIRNAME_DESIGNER));
-}
-
-bool CmakeFileGenerator::validFileName(const Utils::FilePath &filePath)
-{
- QStringList invalidChars = {"!", "\"", "£", "$", "%", "!", "^", "&", "*", "(", ")", "=", "+",
- "'", ",", ";", ":", "#", "~", "{", "{", "[", "]", "<", ">", "?"};
- const QString baseName = filePath.baseName();
- for (const auto &c : invalidChars) {
- if (baseName.contains(c))
- return false;
- }
- return true;
-}
-
-bool CmakeFileGenerator::includeFile(const FilePath &filePath)
-{
- if (m_checkFileIsInProject) {
- ProjectExplorer::Project *project = ProjectExplorer::ProjectManager::startupProject();
- if (!project->isKnownFile(filePath))
- return false;
- }
-
- if (validFileName(filePath))
- return !isFileBlacklisted(filePath.fileName());
- else
- m_invalidFileNames.append(filePath);
-
- return false;
-}
-
-bool CmakeFileGenerator::generateEntryPointFiles(const FilePath &dir)
-{
- const QString qtcontrolsConf = GenerateCmake::projectEnvironmentVariable(ENV_VARIABLE_CONTROLCONF);
- if (!qtcontrolsConf.isEmpty())
- m_resourceFileLocations.append(qtcontrolsConf);
-
- bool cppOk = generateMainCpp(dir);
- bool qmlOk = generateMainQml(dir);
-
- return cppOk && qmlOk;
-}
-
-const char MAIN_CPPFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmaincpp.tpl";
-const char MAIN_CPPFILE_HEADER_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmaincppheader.tpl";
-const char MAIN_CPPFILE_HEADER_PLUGIN_LINE[] = "Q_IMPORT_QML_PLUGIN(%1)\n";
-const char ENV_HEADER_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectenvheader.tpl";
-const char ENV_HEADER_VARIABLE_LINE[] = " qputenv(\"%1\", \"%2\");\n";
-
-bool CmakeFileGenerator::generateMainCpp(const FilePath &dir)
-{
- FilePath srcDir = dir.pathAppended(DIRNAME_CPP);
-
- QString cppContent = GenerateCmake::readTemplate(MAIN_CPPFILE_TEMPLATE_PATH);
- FilePath cppFilePath = srcDir.pathAppended(FILENAME_MAINCPP);
- bool cppOk = m_fileQueue.queueFile(cppFilePath, cppContent);
-
- QString modulesAsPlugins;
- for (const QString &moduleName : m_moduleNames)
- modulesAsPlugins.append(
- QString(MAIN_CPPFILE_HEADER_PLUGIN_LINE).arg(moduleName + "Plugin"));
-
- QString headerContent = GenerateCmake::readTemplate(MAIN_CPPFILE_HEADER_TEMPLATE_PATH)
- .arg(modulesAsPlugins);
- FilePath headerFilePath = srcDir.pathAppended(FILENAME_MAINCPP_HEADER);
- bool pluginHeaderOk = m_fileQueue.queueFile(headerFilePath, headerContent);
-
- bool envHeaderOk = true;
- QString environment;
-
- if (auto buildSystem = QmlBuildSystem::getStartupBuildSystem()) {
- for (EnvironmentItem &envItem : buildSystem->environment()) {
- QString key = envItem.name;
- QString value = envItem.value;
- if (isFileResource(value))
- value.prepend(":/");
- environment.append(QString(ENV_HEADER_VARIABLE_LINE).arg(key).arg(value));
- }
- QString envHeaderContent = GenerateCmake::readTemplate(ENV_HEADER_TEMPLATE_PATH)
- .arg(environment);
- FilePath envHeaderPath = srcDir.pathAppended(FILENAME_ENV_HEADER);
- envHeaderOk = m_fileQueue.queueFile(envHeaderPath, envHeaderContent);
- }
-
- return cppOk && pluginHeaderOk && envHeaderOk;
-}
-
-const char MAIN_QMLFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmainqml.tpl";
-
-bool CmakeFileGenerator::generateMainQml(const FilePath &dir)
-{
- QString content = GenerateCmake::readTemplate(MAIN_QMLFILE_TEMPLATE_PATH);
- FilePath filePath = dir.pathAppended(FILENAME_MAINQML);
- return m_fileQueue.queueFile(filePath, content);
-}
-
-bool CmakeFileGenerator::isFileResource(const QString &relativeFilePath)
-{
- if (m_resourceFileLocations.contains(relativeFilePath))
- return true;
-
- return false;
-}
-
-
-
-} //GenerateCmake
-} //QmlProjectManager
-
diff --git a/src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.h b/src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.h
deleted file mode 100644
index db025daa27..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.h
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#pragma once
-
-#include <projectexplorer/project.h>
-
-#include <utils/fileutils.h>
-
-namespace QmlProjectManager {
-namespace GenerateCmake {
-struct GeneratableFile {
- Utils::FilePath filePath;
- QString content;
- bool fileExists;
-};
-
-bool operator==(const GeneratableFile &left, const GeneratableFile &right);
-
-void generateMenuEntry(QObject *parent);
-void onGenerateCmakeLists();
-bool isErrorFatal(int error);
-int isProjectCorrectlyFormed(const Utils::FilePath &rootDir);
-void showProjectDirErrorDialog(int error);
-QString readTemplate(const QString &templatePath);
-const QString projectEnvironmentVariable(const QString &key);
-
-class FileQueue {
-public:
- bool queueFile(const Utils::FilePath &filePath, const QString &fileContent);
- const QVector<GeneratableFile> queuedFiles() const;
- bool writeQueuedFiles();
- void filterFiles(const Utils::FilePaths keepFiles);
-
-private:
- bool writeFile(const GeneratableFile &file);
-
-private:
- QVector<GeneratableFile> m_queuedFiles;
-};
-
-class CmakeFileGenerator {
-public:
- bool prepare(const Utils::FilePath &rootDir, bool check = true);
- const FileQueue fileQueue() const;
- void filterFileQueue(const Utils::FilePaths &keepFiles);
- bool execute();
- Utils::FilePaths invalidFileNames() const;
-
-private:
- void generateMainCmake(const Utils::FilePath &rootDir);
- void generateImportCmake(const Utils::FilePath &dir, const QString &modulePrefix = QString());
- void generateModuleCmake(const Utils::FilePath &dir, const QString &moduleUri = QString());
- bool generateEntryPointFiles(const Utils::FilePath &dir);
- bool generateMainCpp(const Utils::FilePath &dir);
- bool generateMainQml(const Utils::FilePath &dir);
- QStringList getDirectoryQmls(const Utils::FilePath &dir);
- QStringList getDirectoryResources(const Utils::FilePath &dir);
- QStringList getSingletonsFromQmldirFile(const Utils::FilePath &filePath);
- QStringList getDirectoryTreeQmls(const Utils::FilePath &dir);
- QStringList getDirectoryTreeResources(const Utils::FilePath &dir);
- void queueCmakeFile(const Utils::FilePath &filePath, const QString &content);
- bool isFileResource(const QString &relativeFilePath);
- bool isFileBlacklisted(const QString &fileName);
- bool isDirBlacklisted(const Utils::FilePath &dir);
- bool includeFile(const Utils::FilePath &filePath);
- bool validFileName(const Utils::FilePath &filePath);
-
-private:
- FileQueue m_fileQueue;
- QStringList m_resourceFileLocations;
- QStringList m_moduleNames;
- bool m_checkFileIsInProject;
-
- Utils::FilePaths m_invalidFileNames;
-};
-
-} //GenerateCmake
-
-} //QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/cmakegen/generatecmakelistsconstants.h b/src/plugins/qmlprojectmanager/cmakegen/generatecmakelistsconstants.h
deleted file mode 100644
index b983ce7fec..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/generatecmakelistsconstants.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#ifndef GENERATECMAKELISTSCONSTANTS_H
-#define GENERATECMAKELISTSCONSTANTS_H
-
-#pragma once
-
-namespace QmlProjectManager {
-namespace GenerateCmake {
-namespace Constants {
-
-const char DIRNAME_CONTENT[] = "content";
-const char DIRNAME_IMPORT[] = "imports";
-const char DIRNAME_ASSET[] = "assets";
-const char DIRNAME_ASSETIMPORT[] = "asset_imports";
-const char DIRNAME_CPP[] = "src";
-const char DIRNAME_DESIGNER[] = "designer";
-
-const char FILENAME_CMAKELISTS[] = "CMakeLists.txt";
-const char FILENAME_APPMAINQML[] = "App.qml";
-const char FILENAME_MAINQML[] = "main.qml";
-const char FILENAME_MAINCPP[] = "main.cpp";
-const char FILENAME_MAINCPP_HEADER[] = "import_qml_plugins.h";
-const char FILENAME_MODULES[] = "qmlmodules";
-const char FILENAME_QMLDIR[] = "qmldir";
-const char FILENAME_ENV_HEADER[] = "app_environment.h";
-
-const char FILENAME_SUFFIX_QMLPROJECT[] = "qmlproject";
-const char FILENAME_SUFFIX_QML[] = "qml";
-const char FILENAME_SUFFIX_USER[] = "user";
-
-const char FILENAME_FILTER_QMLPROJECT[] = "*.qmlproject";
-const char FILENAME_FILTER_QML[] = "*.qml";
-
-const char ENV_VARIABLE_CONTROLCONF[] = "QT_QUICK_CONTROLS_CONF";
-
-} //Constants
-} //GenerateCmake
-} //QmlProjectManager
-
-#endif // GENERATECMAKELISTSCONSTANTS_H
diff --git a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectappmainqml.tpl b/src/plugins/qmlprojectmanager/cmakegen/qmlprojectappmainqml.tpl
deleted file mode 100644
index 35f8218dc6..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectappmainqml.tpl
+++ /dev/null
@@ -1,14 +0,0 @@
-import QtQuick
-import QtQuick.Window
-
-Window {
- visible: true
- title: "%1"
- width: mainScreen.width
- height: mainScreen.height
-
- %1 {
- id: mainScreen
- }
-
-}
diff --git a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectenvheader.tpl b/src/plugins/qmlprojectmanager/cmakegen/qmlprojectenvheader.tpl
deleted file mode 100644
index bf60adb4ac..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectenvheader.tpl
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * This file is automatically generated by Qt Design Studio.
- * Do not change.
-*/
-
-#include <QGuiApplication>
-
-void set_qt_environment()
-{
-%1
-}
diff --git a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmaincppheader.tpl b/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmaincppheader.tpl
deleted file mode 100644
index 60cef09a82..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmaincppheader.tpl
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
- * This file is automatically generated by Qt Design Studio.
- * Do not change.
-*/
-
-#include <QtQml/qqmlextensionplugin.h>
-
-%1
diff --git a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmainqml.tpl b/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmainqml.tpl
deleted file mode 100644
index fa8f6d1cc1..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmainqml.tpl
+++ /dev/null
@@ -1,6 +0,0 @@
-import QtQuick
-import content
-
-App {
-}
-
diff --git a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmodulecmakelists.tpl b/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmodulecmakelists.tpl
deleted file mode 100644
index 93573a1ed7..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmodulecmakelists.tpl
+++ /dev/null
@@ -1,12 +0,0 @@
-### This file is automatically generated by Qt Design Studio.
-### Do not change
-
-%1
-
-qt_add_library(%2 STATIC)
-qt6_add_qml_module(%2
- URI "%3"
- VERSION 1.0
- RESOURCE_PREFIX "/qt/qml"
-%4
-)
diff --git a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmodules.tpl b/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmodules.tpl
deleted file mode 100644
index 2b74c49af3..0000000000
--- a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmodules.tpl
+++ /dev/null
@@ -1,16 +0,0 @@
-### This file is automatically generated by Qt Design Studio.
-### Do not change
-
-qt6_add_qml_module(%1
- URI "Main"
- VERSION 1.0
- RESOURCE_PREFIX "/qt/qml"
- NO_PLUGIN
- QML_FILES main.qml
-)
-
-%2
-
-target_link_libraries(%1 PRIVATE
-%3
-)
diff --git a/src/plugins/qmlprojectmanager/cmakegen/templates/cmakelists_txt_shared.tpl b/src/plugins/qmlprojectmanager/cmakegen/templates/cmakelists_txt_shared.tpl
new file mode 100644
index 0000000000..3db7152bff
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/cmakegen/templates/cmakelists_txt_shared.tpl
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE QtCreatorProject>
+<qtcreator>
+ <data>
+ <variable>ProjectExplorer.Project.PluginSettings</variable>
+ <valuemap type="QVariantMap">
+ <valuelist type="QVariantList" key="ProjectExplorer.Project.Environment">
+ <value type="QString">QTC_DEFAULT_BUILD_DIRECTORY_TEMPLATE=../%{Asciify:%{Project:Name}-%{BuildConfig:Name}}</value>
+ </valuelist>
+ </valuemap>
+</data>
+<data>
+ <variable>Version</variable>
+ <value type="int">22</value>
+</data>
+</qtcreator>
diff --git a/src/plugins/qmlprojectmanager/cmakegen/gencmakemodule.tpl b/src/plugins/qmlprojectmanager/cmakegen/templates/cmakemodule_v1.tpl
index b81d253c90..25d894b347 100644
--- a/src/plugins/qmlprojectmanager/cmakegen/gencmakemodule.tpl
+++ b/src/plugins/qmlprojectmanager/cmakegen/templates/cmakemodule_v1.tpl
@@ -8,7 +8,6 @@ qt6_add_qml_module(%1
URI "%2"
VERSION 1.0
RESOURCE_PREFIX "/qt/qml"
-%4
-)
+%4)
%5
diff --git a/src/plugins/qmlprojectmanager/cmakegen/gencmakeroot.tpl b/src/plugins/qmlprojectmanager/cmakegen/templates/cmakeroot_v0.tpl
index a23a311c1a..a23a311c1a 100644
--- a/src/plugins/qmlprojectmanager/cmakegen/gencmakeroot.tpl
+++ b/src/plugins/qmlprojectmanager/cmakegen/templates/cmakeroot_v0.tpl
diff --git a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmaincmakelists.tpl b/src/plugins/qmlprojectmanager/cmakegen/templates/cmakeroot_v1.tpl
index 9ca0ace63b..a5d5e2bd02 100644
--- a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmaincmakelists.tpl
+++ b/src/plugins/qmlprojectmanager/cmakegen/templates/cmakeroot_v1.tpl
@@ -1,3 +1,4 @@
+
cmake_minimum_required(VERSION 3.21.1)
option(LINK_INSIGHT "Link Qt Insight Tracker library" ON)
@@ -5,6 +6,8 @@ option(BUILD_QDS_COMPONENTS "Build design studio components" ON)
project(%1 LANGUAGES CXX)
+list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
+
set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(QT_QML_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/qml)
@@ -19,34 +22,25 @@ if (Qt6_VERSION VERSION_GREATER_EQUAL 6.3)
qt_standard_project_setup()
endif()
-qt_add_executable(%1 src/main.cpp)
-
-qt_add_resources(%1 "configuration"
+qt_add_executable(${CMAKE_PROJECT_NAME})
+qt_add_resources(${CMAKE_PROJECT_NAME} "configuration"
PREFIX "/"
-%2
-)
+ FILES
+%2)
-target_link_libraries(%1 PRIVATE
- Qt${QT_VERSION_MAJOR}::Core
- Qt${QT_VERSION_MAJOR}::Gui
- Qt${QT_VERSION_MAJOR}::Quick
- Qt${QT_VERSION_MAJOR}::Qml
-)
+include(qds)
if (BUILD_QDS_COMPONENTS)
- include(${CMAKE_CURRENT_SOURCE_DIR}/qmlcomponents)
+ include(qmlcomponents OPTIONAL)
endif()
-include(${CMAKE_CURRENT_SOURCE_DIR}/qmlmodules)
-
if (LINK_INSIGHT)
- include(${CMAKE_CURRENT_SOURCE_DIR}/insight)
+ include(insight OPTIONAL)
endif ()
include(GNUInstallDirs)
-install(TARGETS %1
+install(TARGETS ${CMAKE_PROJECT_NAME}
BUNDLE DESTINATION .
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
-
diff --git a/share/qtcreator/qmldesigner/studio_templates/projects/common/import_qml_components_plugins.h.tpl b/src/plugins/qmlprojectmanager/cmakegen/templates/environment_h.tpl
index 167481d7c7..d835c942f6 100644
--- a/share/qtcreator/qmldesigner/studio_templates/projects/common/import_qml_components_plugins.h.tpl
+++ b/src/plugins/qmlprojectmanager/cmakegen/templates/environment_h.tpl
@@ -3,8 +3,11 @@
* Do not change.
*/
+#include <QGuiApplication>
#include "qqmlextensionplugin.h"
+%1
+
#ifdef BUILD_QDS_COMPONENTS
Q_IMPORT_QML_PLUGIN(QtQuick_Studio_ComponentsPlugin)
@@ -17,3 +20,5 @@ Q_IMPORT_QML_PLUGIN(QtQuick_Studio_EventSimulatorPlugin)
Q_IMPORT_QML_PLUGIN(QtQuick_Studio_EventSystemPlugin)
#endif
+
+%2
diff --git a/src/plugins/qmlprojectmanager/cmakegen/gencmakeheadercomponents.tpl b/src/plugins/qmlprojectmanager/cmakegen/templates/import_qml_components_h.tpl
index 167481d7c7..84d3c1c777 100644
--- a/src/plugins/qmlprojectmanager/cmakegen/gencmakeheadercomponents.tpl
+++ b/src/plugins/qmlprojectmanager/cmakegen/templates/import_qml_components_h.tpl
@@ -17,3 +17,4 @@ Q_IMPORT_QML_PLUGIN(QtQuick_Studio_EventSimulatorPlugin)
Q_IMPORT_QML_PLUGIN(QtQuick_Studio_EventSystemPlugin)
#endif
+
diff --git a/share/qtcreator/qmldesigner/studio_templates/projects/common/insight.tpl b/src/plugins/qmlprojectmanager/cmakegen/templates/insight.tpl
index 8245e31f0d..8245e31f0d 100644
--- a/share/qtcreator/qmldesigner/studio_templates/projects/common/insight.tpl
+++ b/src/plugins/qmlprojectmanager/cmakegen/templates/insight.tpl
diff --git a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmaincpp.tpl b/src/plugins/qmlprojectmanager/cmakegen/templates/main_cpp_v0.tpl
index 0ff9201d91..0ff9201d91 100644
--- a/src/plugins/qmlprojectmanager/cmakegen/qmlprojectmaincpp.tpl
+++ b/src/plugins/qmlprojectmanager/cmakegen/templates/main_cpp_v0.tpl
diff --git a/src/plugins/qmlprojectmanager/cmakegen/templates/main_cpp_v1.tpl b/src/plugins/qmlprojectmanager/cmakegen/templates/main_cpp_v1.tpl
new file mode 100644
index 0000000000..4d2a526d76
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/cmakegen/templates/main_cpp_v1.tpl
@@ -0,0 +1,31 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QGuiApplication>
+#include <QQmlApplicationEngine>
+
+#include "autogen/environment.h"
+
+int main(int argc, char *argv[])
+{
+ set_qt_environment();
+ QGuiApplication app(argc, argv);
+
+ QQmlApplicationEngine engine;
+ const QUrl url(mainQmlFile);
+ QObject::connect(
+ &engine, &QQmlApplicationEngine::objectCreated, &app,
+ [url](QObject *obj, const QUrl &objUrl) {
+ if (!obj && url == objUrl)
+ QCoreApplication::exit(-1);
+ }, Qt::QueuedConnection);
+
+ engine.addImportPath(QCoreApplication::applicationDirPath() + "/qml");
+ engine.addImportPath(":/");
+ engine.load(url);
+
+ if (engine.rootObjects().isEmpty())
+ return -1;
+
+ return app.exec();
+}
diff --git a/share/qtcreator/qmldesigner/studio_templates/projects/common/qmlcomponents.tpl b/src/plugins/qmlprojectmanager/cmakegen/templates/qmlcomponents.tpl
index 2e940be032..a9f20243a6 100644
--- a/share/qtcreator/qmldesigner/studio_templates/projects/common/qmlcomponents.tpl
+++ b/src/plugins/qmlprojectmanager/cmakegen/templates/qmlcomponents.tpl
@@ -8,7 +8,7 @@ set(QT_QML_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/qml")
include(FetchContent)
FetchContent_Declare(
ds
- GIT_TAG qds-4.4
+ GIT_TAG qds-4.5
GIT_REPOSITORY https://code.qt.io/qt-labs/qtquickdesigner-components.git
)
diff --git a/src/plugins/qmlprojectmanager/cmakegen/templates/qtquickcontrols2_conf.tpl b/src/plugins/qmlprojectmanager/cmakegen/templates/qtquickcontrols2_conf.tpl
new file mode 100644
index 0000000000..eb1f825a38
--- /dev/null
+++ b/src/plugins/qmlprojectmanager/cmakegen/templates/qtquickcontrols2_conf.tpl
@@ -0,0 +1,7 @@
+; This file can be edited to change the style of the application
+; Read "Qt Quick Controls 2 Configuration File" for details:
+; http://doc.qt.io/qt-5/qtquickcontrols2-configuration.html
+
+[Controls]
+Style=Basic
+
diff --git a/src/plugins/qmlprojectmanager/qmlprojectgen/qmlprojectgenerator.cpp b/src/plugins/qmlprojectmanager/qmlprojectgen/qmlprojectgenerator.cpp
index 32506183fa..0270a290fd 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectgen/qmlprojectgenerator.cpp
+++ b/src/plugins/qmlprojectmanager/qmlprojectgen/qmlprojectgenerator.cpp
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "qmlprojectgenerator.h"
-#include "../cmakegen/generatecmakelists.h"
+#include "../cmakegen/cmakewriter.h"
#include "../qmlprojectmanagertr.h"
#include <coreplugin/documentmanager.h>
@@ -61,7 +61,7 @@ bool QmlProjectFileGenerator::execute()
importDirs.removeAll("content");
const QString importPaths = createDirArrayEntry("importPaths", importDirs);
- const QString fileContent = GenerateCmake::readTemplate(QMLPROJECT_FILE_TEMPLATE_PATH)
+ const QString fileContent = GenerateCmake::CMakeWriter::readTemplate(QMLPROJECT_FILE_TEMPLATE_PATH)
.arg(contentEntry, imageEntry, jsEntry, assetEntry, importPaths);
QFile file(m_targetFile.toString());
diff --git a/src/plugins/qmlprojectmanager/qmlprojectmanager.qbs b/src/plugins/qmlprojectmanager/qmlprojectmanager.qbs
index 76fcd70157..0fa49b5102 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectmanager.qbs
+++ b/src/plugins/qmlprojectmanager/qmlprojectmanager.qbs
@@ -47,14 +47,10 @@ QtcPlugin {
name: "CMake Generator"
prefix: "cmakegen/"
files: [
- "generatecmakelists.cpp", "generatecmakelists.h",
- "generatecmakelistsconstants.h",
- "checkablefiletreeitem.cpp", "checkablefiletreeitem.h",
"cmakegenerator.cpp", "cmakegenerator.h",
- "cmakegeneratordialogtreemodel.cpp", "cmakegeneratordialogtreemodel.h",
- "cmakegeneratordialog.cpp", "cmakegeneratordialog.h",
- "cmakeprojectconverter.cpp", "cmakeprojectconverter.h",
- "cmakeprojectconverterdialog.cpp", "cmakeprojectconverterdialog.h",
+ "cmakewriter.cpp", "cmakewriter.h",
+ "cmakewriterv0.cpp", "cmakewriterv0.h",
+ "cmakewriterv1.cpp", "cmakewriterv1.h"
]
}
diff --git a/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp b/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp
index 62abce5fe9..9cd1bae9c6 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp
+++ b/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp
@@ -9,8 +9,7 @@
#include "qmlprojectmanagertr.h"
#include "qmlprojectrunconfiguration.h"
#include "projectfilecontenttools.h"
-#include "cmakegen/cmakeprojectconverter.h"
-#include "cmakegen/generatecmakelists.h"
+#include "cmakegen/cmakegenerator.h"
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
@@ -386,11 +385,9 @@ void QmlProjectPlugin::initialize()
mainUifileAction->setEnabled(buildSystem->mainUiFilePath()
!= fileNode->filePath());
});
- }
- GenerateCmake::generateMenuEntry(this);
- if (ICore::isQtDesignStudio())
- GenerateCmake::CmakeProjectConverter::generateMenuEntry(this);
+ GenerateCmake::CMakeGenerator::createMenuAction(this);
+ }
}
void QmlProjectPlugin::displayQmlLandingPage()
diff --git a/src/plugins/remotelinux/linuxdevicetester.cpp b/src/plugins/remotelinux/linuxdevicetester.cpp
index 4dea30c3d0..d6ab3a9745 100644
--- a/src/plugins/remotelinux/linuxdevicetester.cpp
+++ b/src/plugins/remotelinux/linuxdevicetester.cpp
@@ -5,6 +5,7 @@
#include "linuxdevice.h"
#include "remotelinuxtr.h"
+#include "utils/async.h"
#include <extensionsystem/pluginmanager.h>
diff --git a/src/plugins/studiowelcome/studiowelcomeplugin.cpp b/src/plugins/studiowelcome/studiowelcomeplugin.cpp
index 9e93384cfa..d526a9c436 100644
--- a/src/plugins/studiowelcome/studiowelcomeplugin.cpp
+++ b/src/plugins/studiowelcome/studiowelcomeplugin.cpp
@@ -333,6 +333,37 @@ public:
Core::EditorManager::openEditor(qmlFile);
}
+ Q_INVOKABLE bool exampleVersionOk(const QString &exampleVersion)
+ {
+ if (exampleVersion.isEmpty())
+ return true;
+
+ const QStringList exampleVersionParts = exampleVersion.split('.');
+ const QStringList qdsVersionParts = QCoreApplication::applicationVersion().split('.');
+
+ QList<int> exampleVerInts;
+ QList<int> qdsVerInts;
+ for (const QString &part : exampleVersionParts)
+ exampleVerInts.append(part.toInt());
+
+ for (const QString &part : qdsVersionParts)
+ qdsVerInts.append(part.toInt());
+
+ // pad zeros so both lists are same size
+ while (qdsVerInts.size() < exampleVerInts.size())
+ qdsVerInts.append(0);
+
+ while (exampleVerInts.size() < qdsVerInts.size())
+ exampleVerInts.append(0);
+
+ for (int i = 0; i < qdsVerInts.size(); ++i) {
+ if (exampleVerInts[i] < qdsVerInts[i])
+ return false;
+ }
+
+ return true;
+ }
+
public slots:
void resetProjects();
void delayedResetProjects();
diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp
index 749e7bf2f7..7a8fa1edbc 100644
--- a/src/plugins/texteditor/texteditor.cpp
+++ b/src/plugins/texteditor/texteditor.cpp
@@ -4975,7 +4975,7 @@ static QColor calcBlendColor(const QColor &baseColor, int level, int count)
if (level == count - 1)
return color90;
- const int blendFactor = level * (256 / (count - 2));
+ const int blendFactor = level * (256 / (count - 1));
return blendColors(color80, color90, blendFactor);
}
@@ -7471,8 +7471,7 @@ void TextEditorWidgetPrivate::handleBackspaceKey()
}
}
} else if (typingSettings.m_smartBackspaceBehavior == TypingSettings::BackspaceUnindents) {
- const QChar previousChar = q->document()->characterAt(pos - 1);
- if (!(previousChar == QLatin1Char(' ') || previousChar == QLatin1Char('\t'))) {
+ if (c.positionInBlock() > TabSettings::firstNonSpace(c.block().text())) {
if (cursorWithinSnippet)
c.beginEditBlock();
c.deletePreviousChar();
diff --git a/src/tools/qml2puppet/editor3d_qt6.qrc b/src/tools/qml2puppet/editor3d_qt6.qrc
index 2913fbe15e..d76b1941b9 100644
--- a/src/tools/qml2puppet/editor3d_qt6.qrc
+++ b/src/tools/qml2puppet/editor3d_qt6.qrc
@@ -8,6 +8,8 @@
<file>mockfiles/images/editor_camera@2x.png</file>
<file>mockfiles/images/editor_particlesystem.png</file>
<file>mockfiles/images/editor_particlesystem@2x.png</file>
+ <file>mockfiles/images/crosshair.png</file>
+ <file>mockfiles/images/crosshair@2x.png</file>
<file>mockfiles/images/directional.png</file>
<file>mockfiles/images/directional@2x.png</file>
<file>mockfiles/images/point.png</file>
diff --git a/src/tools/qml2puppet/mockfiles/images/crosshair.png b/src/tools/qml2puppet/mockfiles/images/crosshair.png
new file mode 100644
index 0000000000..6c30263513
--- /dev/null
+++ b/src/tools/qml2puppet/mockfiles/images/crosshair.png
Binary files differ
diff --git a/src/tools/qml2puppet/mockfiles/images/crosshair@2x.png b/src/tools/qml2puppet/mockfiles/images/crosshair@2x.png
new file mode 100644
index 0000000000..5340bf0846
--- /dev/null
+++ b/src/tools/qml2puppet/mockfiles/images/crosshair@2x.png
Binary files differ
diff --git a/src/tools/qml2puppet/mockfiles/qt6/EditCameraController.qml b/src/tools/qml2puppet/mockfiles/qt6/EditCameraController.qml
index 446d575683..255d93e529 100644
--- a/src/tools/qml2puppet/mockfiles/qt6/EditCameraController.qml
+++ b/src/tools/qml2puppet/mockfiles/qt6/EditCameraController.qml
@@ -102,6 +102,23 @@ Item {
storeCameraState(0);
}
+ function approachObject()
+ {
+ if (!camera)
+ return;
+
+ var pickResult = _generalHelper.pickViewAt(view3d, width / 2, height / 2);
+ var resolvedResult = _generalHelper.resolvePick(pickResult.objectHit);
+
+ if (resolvedResult) {
+ var newLookAtAndZoom = _generalHelper.approachNode(camera, _defaultCameraLookAtDistance,
+ resolvedResult, view3D);
+ _lookAtPoint = newLookAtAndZoom.toVector3d();
+ _zoomFactor = newLookAtAndZoom.w;
+ storeCameraState(0);
+ }
+ }
+
function jumpToRotation(rotation)
{
let distance = camera.scenePosition.minus(_lookAtPoint).length()
@@ -138,7 +155,10 @@ Item {
else
nodes = targetNodes
- _lookAtPoint = _generalHelper.alignView(camera, nodes, _lookAtPoint);
+ var newLookAtAndZoom = _generalHelper.alignView(camera, nodes, _lookAtPoint,
+ _defaultCameraLookAtDistance);
+ _lookAtPoint = newLookAtAndZoom.toVector3d();
+ _zoomFactor = newLookAtAndZoom.w;
storeCameraState(0);
}
@@ -158,8 +178,7 @@ Item {
function moveCamera(moveVec)
{
- cameraCtrl._lookAtPoint = _generalHelper.moveCamera(camera, _lookAtPoint, _zoomFactor,
- moveVec);
+ cameraCtrl._lookAtPoint = _generalHelper.moveCamera(camera, _lookAtPoint, moveVec);
}
function getMoveVectorForKey(key) {
@@ -238,6 +257,13 @@ Item {
}
}
+ Image {
+ anchors.centerIn: parent
+ source: "qrc:///qtquickplugin/mockfiles/images/crosshair.png"
+ visible: cameraCtrl.flyMode && viewRoot.activeSplit === cameraCtrl.splitId
+ opacity: 0.7
+ }
+
MouseArea {
id: mouseHandler
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
@@ -302,7 +328,10 @@ Item {
Keys.onPressed: (event) => {
event.accepted = true;
- _generalHelper.startCameraMove(cameraCtrl.camera, cameraCtrl.getMoveVectorForKey(event.key));
+ if (cameraCtrl.flyMode && event.key === Qt.Key_Space)
+ approachObject();
+ else
+ _generalHelper.startCameraMove(cameraCtrl.camera, cameraCtrl.getMoveVectorForKey(event.key));
}
Keys.onReleased: (event) => {
diff --git a/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.cpp b/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.cpp
index 6886f7e41c..dadd817633 100644
--- a/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.cpp
+++ b/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.cpp
@@ -157,7 +157,7 @@ QVector3D GeneralHelper::panCamera(QQuick3DCamera *camera, const QMatrix4x4 star
// Moves camera in 3D space and returns new look-at point
QVector3D GeneralHelper::moveCamera(QQuick3DCamera *camera, const QVector3D &startLookAt,
- float zoomFactor, const QVector3D &moveVector)
+ const QVector3D &moveVector)
{
if (moveVector.length() < 0.001f)
@@ -171,7 +171,8 @@ QVector3D GeneralHelper::moveCamera(QQuick3DCamera *camera, const QVector3D &sta
const QVector3D xDelta = xAxis * moveVector.x();
const QVector3D yDelta = yAxis * moveVector.y();
const QVector3D zDelta = zAxis * moveVector.z();
- const QVector3D delta = (yDelta - xDelta - zDelta) * zoomFactor;
+ // Delta multiplier for nice default speed in default scene
+ const QVector3D delta = (yDelta - xDelta - zDelta) * .5f;
camera->setPosition(camera->position() + delta);
@@ -187,8 +188,14 @@ QVector3D GeneralHelper::rotateCamera(QQuick3DCamera *camera, const QPointF &ang
if (qAbs(angles.y()) > 0.001f)
camera->rotate(angles.y(), QVector3D(1.f, 0.f, 0.f), QQuick3DNode::LocalSpace);
// Rotation around Y-axis is done in scene space to keep horizon level
- if (qAbs(angles.x()) > 0.001f)
- camera->rotate(angles.x(), QVector3D(0.f, 1.f, 0.f), QQuick3DNode::SceneSpace);
+ if (qAbs(angles.x()) > 0.001f) {
+ // Since we are rotating in scene space, adjust direction according to camera up-vector
+ float angle = angles.x();
+ if (camera->up().y() <= 0)
+ angle = -angle;
+
+ camera->rotate(angle, QVector3D(0.f, 1.f, 0.f), QQuick3DNode::SceneSpace);
+ }
QMatrix4x4 m = camera->sceneTransform();
const float *dataPtr(m.data());
@@ -391,6 +398,55 @@ QVector4D GeneralHelper::focusNodesToCamera(QQuick3DCamera *camera, float defaul
return QVector4D(lookAt, cameraZoomFactor);
}
+// Approaches the specified node without changing camera orientation
+QVector4D GeneralHelper::approachNode(
+ QQuick3DCamera *camera, float defaultLookAtDistance, QObject *node,
+ QQuick3DViewport *viewPort)
+{
+ auto node3d = qobject_cast<QQuick3DNode *>(node);
+ if (!camera || !node3d)
+ return QVector4D(0.f, 0.f, 0.f, 1.f);
+
+ QVector3D minBounds = maxVec;
+ QVector3D maxBounds = minVec;
+
+ getBounds(viewPort, node3d, minBounds, maxBounds); // Bounds are in node3d local coordinates
+
+ QVector3D extents = maxBounds - minBounds;
+ QVector3D focusLookAt = minBounds + (extents / 2.f);
+
+ if (node3d->parentNode()) {
+ QMatrix4x4 m = node3d->parentNode()->sceneTransform();
+ focusLookAt = m.map(focusLookAt);
+ }
+
+ float maxExtent = qSqrt(qreal(extents.x()) * qreal(extents.x())
+ + qreal(extents.y()) * qreal(extents.y())
+ + qreal(extents.z()) * qreal(extents.z()));
+
+ // Reset camera position to default zoom
+ QMatrix4x4 m = camera->sceneTransform();
+ const float *dataPtr(m.data());
+ QVector3D newLookVector(dataPtr[8], dataPtr[9], dataPtr[10]);
+ newLookVector.normalize();
+
+ // We don't want to change camera orientation, so calculate projection point on current
+ // camera look vector
+ QVector3D focusLookAtVector = focusLookAt - camera->position();
+ float dot = QVector3D::dotProduct(newLookVector, focusLookAtVector);
+ QVector3D newLookAt = camera->position() + dot * newLookVector;
+
+ newLookVector *= defaultLookAtDistance;
+ camera->setPosition(newLookAt + newLookVector);
+
+ float divisor = 1050.f;
+ float newZoomFactor = qBound(.01f, maxExtent / divisor, 100.f);
+ float cameraZoomFactor = zoomCamera(viewPort, camera, 0, defaultLookAtDistance, newLookAt,
+ newZoomFactor, false);
+
+ return QVector4D(newLookAt, cameraZoomFactor);
+}
+
// This function can be used to synchronously focus camera on a node, which doesn't have to be
// a selection box for bound calculations to work. This is used to focus the view for
// various preview image generations, where doing things asynchronously is not good
@@ -487,12 +543,10 @@ void GeneralHelper::alignCameras(QQuick3DCamera *camera, const QVariant &nodes)
// Aligns the camera to the first camera in nodes list.
// Aligning means taking the position and XY rotation from the source camera. Rest of the properties
// remain the same, as this is used to align edit cameras, which have fixed Z-rot, fov, and clips.
-// The new lookAt is set at same distance away as it was previously and scale isn't adjusted, so
-// the zoom factor of the edit camera stays the same.
-QVector3D GeneralHelper::alignView(QQuick3DCamera *camera, const QVariant &nodes,
- const QVector3D &lookAtPoint)
+// The camera zoom is reset to default.
+QVector4D GeneralHelper::alignView(QQuick3DCamera *camera, const QVariant &nodes,
+ const QVector3D &lookAtPoint, float defaultLookAtDistance)
{
- float lastDistance = (lookAtPoint - camera->position()).length();
const QVariantList varNodes = nodes.value<QVariantList>();
QQuick3DCamera *cameraNode = nullptr;
for (const auto &varNode : varNodes) {
@@ -502,15 +556,24 @@ QVector3D GeneralHelper::alignView(QQuick3DCamera *camera, const QVariant &nodes
}
if (cameraNode) {
+ if (auto orthoCamera = qobject_cast<QQuick3DOrthographicCamera *>(camera)) {
+ orthoCamera->setHorizontalMagnification(1.f);
+ orthoCamera->setVerticalMagnification(1.f);
+ // Force update on transform just in case position and rotation didn't change
+ float x = orthoCamera->x();
+ orthoCamera->setX(x + 1.f);
+ orthoCamera->setX(x);
+ }
camera->setPosition(cameraNode->scenePosition());
QVector3D newRotation = cameraNode->sceneRotation().toEulerAngles();
newRotation.setZ(0.f);
camera->setEulerRotation(newRotation);
+
}
- QVector3D lookAt = camera->position() + camera->forward() * lastDistance;
+ QVector3D lookAt = camera->position() + camera->forward() * defaultLookAtDistance;
- return lookAt;
+ return QVector4D(lookAt, 1.f);
}
bool GeneralHelper::fuzzyCompare(double a, double b)
diff --git a/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.h b/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.h
index 3ba6f8b1d9..62a95d86a6 100644
--- a/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.h
+++ b/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.h
@@ -55,7 +55,7 @@ public:
const QVector3D &pressPos, const QVector3D &currentPos,
float zoomFactor);
Q_INVOKABLE QVector3D moveCamera(QQuick3DCamera *camera,const QVector3D &startLookAt,
- float zoomFactor, const QVector3D &moveVector);
+ const QVector3D &moveVector);
Q_INVOKABLE QVector3D rotateCamera(QQuick3DCamera *camera, const QPointF &angles,
const QVector3D &lookAtPoint);
@@ -70,12 +70,14 @@ public:
const QVariant &nodes, QQuick3DViewport *viewPort,
float oldZoom, bool updateZoom = true,
bool closeUp = false);
+ Q_INVOKABLE QVector4D approachNode(QQuick3DCamera *camera, float defaultLookAtDistance,
+ QObject *node, QQuick3DViewport *viewPort);
Q_INVOKABLE void calculateNodeBoundsAndFocusCamera(QQuick3DCamera *camera, QQuick3DNode *node,
QQuick3DViewport *viewPort,
float defaultLookAtDistance, bool closeUp);
Q_INVOKABLE void alignCameras(QQuick3DCamera *camera, const QVariant &nodes);
- Q_INVOKABLE QVector3D alignView(QQuick3DCamera *camera, const QVariant &nodes,
- const QVector3D &lookAtPoint);
+ Q_INVOKABLE QVector4D alignView(QQuick3DCamera *camera, const QVariant &nodes,
+ const QVector3D &lookAtPoint, float defaultLookAtDistance);
Q_INVOKABLE bool fuzzyCompare(double a, double b);
Q_INVOKABLE void delayedPropertySet(QObject *obj, int delay, const QString &property,
const QVariant& value);
diff --git a/src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceserver.cpp b/src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceserver.cpp
index fca884e94b..765b52321b 100644
--- a/src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceserver.cpp
+++ b/src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceserver.cpp
@@ -436,10 +436,18 @@ QQuickItem *Qt5NodeInstanceServer::parentEffectItem(QQuickItem *item)
return nullptr;
}
-static bool isEffectItem(QQuickItem *item, QQuickShaderEffectSource *sourceItem)
+static bool isEffectItem(QQuickItem *item, QQuickShaderEffectSource *sourceItem, QQuickItem *target)
{
QQuickItemPrivate *pItem = QQuickItemPrivate::get(sourceItem);
+ if (item) {
+ QQmlProperty prop(item, "__effect");
+ if (prop.read().toBool()) {
+ prop = QQmlProperty(item, "source");
+ return prop.read().value<QQuickItem *>() == target;
+ }
+ }
+
if (!pItem || !pItem->layer())
return false;
@@ -477,7 +485,7 @@ QImage Qt5NodeInstanceServer::grabItem([[maybe_unused]] QQuickItem *item)
if (auto parent = item->parentItem()) {
const auto siblings = parent->childItems();
for (auto sibling : siblings) {
- if (isEffectItem(sibling, pItem->layer()->effectSource()))
+ if (isEffectItem(sibling, pItem->layer()->effectSource(), item))
return grabItem(sibling);
}
}
diff --git a/src/tools/qml2puppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp b/src/tools/qml2puppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp
index f9191950fd..53af00ab09 100644
--- a/src/tools/qml2puppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp
+++ b/src/tools/qml2puppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp
@@ -146,7 +146,9 @@ void Qt5RenderNodeInstanceServer::collectItemChangesAndSendChangeCommands()
&& !changedPropertyList().isEmpty()
&& nodeInstanceClient()->bytesToWrite() < 10000) {
- Internal::QuickItemNodeInstance::updateDirtyNode(rootNodeInstance().contentItem());
+ QQuickItem *rootItem = rootNodeInstance().contentItem();
+ QQuickDesignerSupport::addDirty(rootItem, QQuickDesignerSupport::Content);
+ QQuickDesignerSupport::updateDirtyNode(rootItem);
nodeInstanceClient()->pixmapChanged(createPixmapChangedCommand({rootNodeInstance()}));
}
@@ -239,6 +241,24 @@ void Qt5RenderNodeInstanceServer::changePropertyValues(const ChangeValuesCommand
if (instance.hasParent() && instance.propertyNames().contains("_isEffectItem"))
makeDirtyRecursive(instance.parent());
+ } else if (container.isDynamic() && hasInstanceForId(container.instanceId())) {
+ // Changes to dynamic properties are not always noticed by normal signal spy mechanism
+ addChangedProperty(InstancePropertyPair(instanceForId(container.instanceId()),
+ container.name()));
+ }
+ }
+}
+
+void Qt5RenderNodeInstanceServer::changePropertyBindings(const ChangeBindingsCommand &command)
+{
+ Qt5NodeInstanceServer::changePropertyBindings(command);
+
+ const QVector<PropertyBindingContainer> changes = command.bindingChanges;
+ for (const PropertyBindingContainer &container : changes) {
+ if (container.isDynamic() && hasInstanceForId(container.instanceId())) {
+ // Changes to dynamic properties are not always noticed by normal signal spy mechanism
+ addChangedProperty(InstancePropertyPair(instanceForId(container.instanceId()),
+ container.name()));
}
}
}
diff --git a/src/tools/qml2puppet/qml2puppet/instances/qt5rendernodeinstanceserver.h b/src/tools/qml2puppet/qml2puppet/instances/qt5rendernodeinstanceserver.h
index 738aa47b18..1e0f885da1 100644
--- a/src/tools/qml2puppet/qml2puppet/instances/qt5rendernodeinstanceserver.h
+++ b/src/tools/qml2puppet/qml2puppet/instances/qt5rendernodeinstanceserver.h
@@ -18,6 +18,7 @@ public:
void completeComponent(const CompleteComponentCommand &command) override;
void removeSharedMemory(const RemoveSharedMemoryCommand &command) override;
void changePropertyValues(const ChangeValuesCommand &command) override;
+ void changePropertyBindings(const ChangeBindingsCommand &command) override;
protected:
void collectItemChangesAndSendChangeCommands() override;
diff --git a/src/tools/qml2puppet/qml2puppet/instances/quickitemnodeinstance.cpp b/src/tools/qml2puppet/qml2puppet/instances/quickitemnodeinstance.cpp
index 9d432fe047..a9c49b9661 100644
--- a/src/tools/qml2puppet/qml2puppet/instances/quickitemnodeinstance.cpp
+++ b/src/tools/qml2puppet/qml2puppet/instances/quickitemnodeinstance.cpp
@@ -277,13 +277,27 @@ static bool layerEnabledAndEffect(QQuickItem *item)
return false;
}
+static QRectF getBoundingRectForEffect(QQuickItem *item)
+{
+ const auto siblings = item->parentItem()->childItems();
+ for (auto sibling : siblings) {
+ QQmlProperty prop(sibling, "__effect");
+ if (prop.read().toBool()) {
+ prop = QQmlProperty(sibling, "source");
+ if (prop.read().value<QQuickItem *>() == item)
+ return ServerNodeInstance::effectAdjustedBoundingRect(sibling);
+ }
+ }
+ return ServerNodeInstance::effectAdjustedBoundingRect(item);
+}
+
QRectF QuickItemNodeInstance::boundingRect() const
{
if (quickItem()) {
- if (quickItem()->clip()) {
+ if (layerEnabledAndEffect(quickItem()) && quickItem()->parentItem()) {
+ return getBoundingRectForEffect(quickItem());
+ } else if (quickItem()->clip()) {
return quickItem()->boundingRect();
- } else if (layerEnabledAndEffect(quickItem())) {
- return ServerNodeInstance::effectAdjustedBoundingRect(quickItem());
} else {
QSize maximumSize(4000, 4000);
auto isValidSize = [maximumSize] (const QRectF& rect) {
diff --git a/src/tools/qml2puppet/qml2puppet/instances/servernodeinstance.cpp b/src/tools/qml2puppet/qml2puppet/instances/servernodeinstance.cpp
index 758e18df35..aa91b8ffaa 100644
--- a/src/tools/qml2puppet/qml2puppet/instances/servernodeinstance.cpp
+++ b/src/tools/qml2puppet/qml2puppet/instances/servernodeinstance.cpp
@@ -26,6 +26,8 @@
#include <qmlprivategate.h>
+#include <QtQuick/private/qquickitem_p.h>
+
#include <QHash>
#include <QSet>
#include <QDebug>
@@ -116,8 +118,23 @@ bool ServerNodeInstance::isSubclassOf(QObject *object, const QByteArray &superTy
QRectF ServerNodeInstance::effectAdjustedBoundingRect(QQuickItem *item)
{
- if (item)
- return item->boundingRect().adjusted(-40, -40, 40, 40);
+ if (item) {
+ QQuickItemPrivate *pItem = QQuickItemPrivate::get(item);
+
+ QQmlProperty prop(item, "__effect");
+
+ if (pItem && pItem->layer() && pItem->layer()->sourceRect().isValid()) {
+ return pItem->layer()->sourceRect();
+ } else if (prop.read().toBool()) {
+ prop = QQmlProperty(item, "effectBoundingBox");
+ QRectF rect = prop.read().toRectF().adjusted(-40, -40, 40, 40);
+ if (rect.isValid())
+ return rect;
+ return item->boundingRect();
+ } else {
+ return item->boundingRect();
+ }
+ }
return {};
}
diff --git a/src/tools/qml2puppet/qmlprivategate/qmlprivategate.cpp b/src/tools/qml2puppet/qmlprivategate/qmlprivategate.cpp
index 123d4aee2d..096ac36244 100644
--- a/src/tools/qml2puppet/qmlprivategate/qmlprivategate.cpp
+++ b/src/tools/qml2puppet/qmlprivategate/qmlprivategate.cpp
@@ -10,6 +10,7 @@
#include <QQmlComponent>
#include <QFileInfo>
#include <QProcessEnvironment>
+#include <QJsonValue>
#include <private/qabstractfileengine_p.h>
#include <private/qfsfileengine_p.h>
@@ -35,16 +36,484 @@
#include <private/qquickanimation_p.h>
#include <private/qqmlmetatype_p.h>
#include <private/qqmltimer_p.h>
+#include <private/qqmlanybinding_p.h>
#ifdef QUICK3D_MODULE
#include <private/qquick3dobject_p.h>
#include <private/qquick3drepeater_p.h>
#endif
+
+
namespace QmlDesigner {
namespace Internal {
+static void addToPropertyNameListIfNotBlackListed(QQuickDesignerSupport::PropertyNameList *propertyNameList,
+ const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ if (!QQuickDesignerSupportProperties::isPropertyBlackListed(propertyName))
+ propertyNameList->append(propertyName);
+}
+
+static QQuickDesignerSupport::PropertyNameList propertyNameListForWritablePropertiesInternal(QObject *object,
+ const QQuickDesignerSupport::PropertyName &baseName,
+ QObjectList *inspectedObjects,
+ int depth = 0)
+{
+ QQuickDesignerSupport::PropertyNameList propertyNameList;
+
+ if (depth > 2)
+ return propertyNameList;
+
+ if (!inspectedObjects->contains(object))
+ inspectedObjects->append(object);
+
+ const QMetaObject *metaObject = object->metaObject();
+ for (int index = 0; index < metaObject->propertyCount(); ++index) {
+ QMetaProperty metaProperty = metaObject->property(index);
+ QQmlProperty declarativeProperty(object, QString::fromUtf8(metaProperty.name()));
+ if (declarativeProperty.isValid() && !declarativeProperty.isWritable() && declarativeProperty.propertyTypeCategory() == QQmlProperty::Object) {
+ if (declarativeProperty.name() != QLatin1String("parent")) {
+ QObject *childObject = QQmlMetaType::toQObject(declarativeProperty.read());
+ if (childObject)
+ propertyNameList.append(propertyNameListForWritablePropertiesInternal(childObject,
+ baseName + QQuickDesignerSupport::PropertyName(metaProperty.name())
+ + '.', inspectedObjects,
+ depth + 1));
+ }
+ } else if (QQmlGadgetPtrWrapper *valueType
+ = QQmlGadgetPtrWrapper::instance(qmlEngine(object), metaProperty.metaType())) {
+
+
+ const QVariant value = metaProperty.read(object);
+ QMetaType jsType = QMetaType::fromType<QJSValue>();
+ int userType = value.userType();
+
+ //qDebug() << jsType << jsType.id();
+ //qDebug() << "tp" << value.typeName();
+ //qDebug() << "ut" << userType;
+
+ if (userType == jsType.id()) {
+ qDebug() << "js value found";
+ //QJSValue jsValue = value.value<QJSValue>(); //crashes
+ //qDebug() << jsValue.isObject();
+ //qDebug() << jsValue.isQObject();
+ } else {
+
+
+
+ valueType->setValue(value);
+ propertyNameList.append(propertyNameListForWritablePropertiesInternal(valueType,
+ baseName + QQuickDesignerSupport::PropertyName(metaProperty.name())
+ + '.', inspectedObjects,
+ depth + 1));
+ }
+
+ }
+
+ if (metaProperty.isReadable() && metaProperty.isWritable()) {
+ addToPropertyNameListIfNotBlackListed(&propertyNameList,
+ baseName + QQuickDesignerSupport::PropertyName(metaProperty.name()));
+ }
+ }
+
+ return propertyNameList;
+}
+
+static QQuickDesignerSupport::PropertyNameList propertyNameListForWritablePropertiesFork(QObject *object)
+{
+ QObjectList localObjectList;
+ return propertyNameListForWritablePropertiesInternal(object, {}, &localObjectList);
+}
+
+static QQuickDesignerSupport::PropertyNameList allPropertyNamesFork(QObject *object,
+ const QQuickDesignerSupport::PropertyName &baseName = QQuickDesignerSupport::PropertyName(),
+ QObjectList *inspectedObjects = nullptr,
+ int depth = 0)
+{
+ QQuickDesignerSupport::PropertyNameList propertyNameList;
+
+ QObjectList localObjectList;
+
+ if (inspectedObjects == nullptr)
+ inspectedObjects = &localObjectList;
+
+ if (depth > 2)
+ return propertyNameList;
+
+ if (!inspectedObjects->contains(object))
+ inspectedObjects->append(object);
+
+ const QMetaObject *metaObject = object->metaObject();
+
+ QStringList deferredPropertyNames;
+ const int namesIndex = metaObject->indexOfClassInfo("DeferredPropertyNames");
+ if (namesIndex != -1) {
+ QMetaClassInfo classInfo = metaObject->classInfo(namesIndex);
+ deferredPropertyNames = QString::fromUtf8(classInfo.value()).split(QLatin1Char(','));
+ }
+
+ for (int index = 0; index < metaObject->propertyCount(); ++index) {
+ QMetaProperty metaProperty = metaObject->property(index);
+ QQmlProperty declarativeProperty(object, QString::fromUtf8(metaProperty.name()));
+ if (declarativeProperty.isValid() && declarativeProperty.propertyTypeCategory() == QQmlProperty::Object) {
+ if (declarativeProperty.name() != QLatin1String("parent")
+ && !deferredPropertyNames.contains(declarativeProperty.name())) {
+ QObject *childObject = QQmlMetaType::toQObject(declarativeProperty.read());
+ if (childObject)
+ propertyNameList.append(allPropertyNamesFork(childObject,
+ baseName
+ + QQuickDesignerSupport::PropertyName(metaProperty.name())
+ + '.', inspectedObjects,
+ depth + 1));
+ }
+ } else if (QQmlGadgetPtrWrapper *valueType
+ = QQmlGadgetPtrWrapper::instance(qmlEngine(object), metaProperty.metaType())) {
+
+ const QVariant value = metaProperty.read(object);
+ propertyNameList.append(baseName + QQuickDesignerSupport::PropertyName(metaProperty.name()));
+ const QJsonValue jsonValue = value.toJsonValue();
+
+ if (!jsonValue.isNull()) {
+ qDebug() << "llokhere";
+ qDebug() << "name" << metaProperty.name();
+ qDebug() << "value" << value;
+ qDebug() << jsonValue;
+ }
+
+ if (value.isValid() && jsonValue.isNull()) {
+ //qDebug() << "llokhere crash";
+ //qDebug() << "name" << metaProperty.name();
+ //qDebug() << "value" << value;
+ //qDebug() << jsonValue;
+
+
+ QMetaType jsType = QMetaType::fromType<QJSValue>();
+
+ int userType = value.userType();
+
+ //qDebug() << jsType << jsType.id();
+ //qDebug() << "tp" << value.typeName();
+ //qDebug() << "ut" << userType;
+
+ if (userType == jsType.id()) {
+ qDebug() << "js value found";
+ //QJSValue jsValue = value.value<QJSValue>(); //crashes
+ //qDebug() << jsValue.isObject();
+ //qDebug() << jsValue.isQObject();
+ } else {
+
+
+ valueType->setValue(value);
+ propertyNameList.append(allPropertyNamesFork(valueType,
+ baseName
+ + QQuickDesignerSupport::PropertyName(metaProperty.name())
+ + '.', inspectedObjects,
+ depth + 1));
+ }
+
+
+ }
+ } else {
+ addToPropertyNameListIfNotBlackListed(&propertyNameList,
+ baseName + QQuickDesignerSupport::PropertyName(metaProperty.name()));
+ }
+ }
+
+ return propertyNameList;
+}
+
+class DesignerCustomObjectDataFork
+{
+public:
+ static void registerData(QObject *object);
+ static DesignerCustomObjectDataFork *get(QObject *object);
+ static QVariant getResetValue(QObject *object, const QQuickDesignerSupport::PropertyName &propertyName);
+ static void doResetProperty(QObject *object, QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName);
+ static bool hasValidResetBinding(QObject *object, const QQuickDesignerSupport::PropertyName &propertyName);
+ static bool hasBindingForProperty(QObject *object,
+ QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ bool *hasChanged);
+ static void setPropertyBinding(QObject *object,
+ QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ const QString &expression);
+ static void keepBindingFromGettingDeleted(QObject *object,
+ QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName);
+ void handleDestroyed();
+
+private:
+ DesignerCustomObjectDataFork(QObject *object);
+ void populateResetHashes();
+ QObject *object() const;
+ QVariant getResetValue(const QQuickDesignerSupport::PropertyName &propertyName) const;
+ void doResetProperty(QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName);
+ bool hasValidResetBinding(const QQuickDesignerSupport::PropertyName &propertyName) const;
+ QQmlAnyBinding getResetBinding(const QQuickDesignerSupport::PropertyName &propertyName) const;
+ bool hasBindingForProperty(QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName, bool *hasChanged) const;
+ void setPropertyBinding(QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName, const QString &expression);
+ void keepBindingFromGettingDeleted(QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName);
+
+ QObject *m_object;
+ QHash<QQuickDesignerSupport::PropertyName, QVariant> m_resetValueHash;
+ QHash<QQuickDesignerSupport::PropertyName, QQmlAnyBinding> m_resetBindingHash;
+ mutable QHash<QQuickDesignerSupport::PropertyName, bool> m_hasBindingHash;
+};
+
+typedef QHash<QObject*, DesignerCustomObjectDataFork*> CustomObjectDataHash;
+Q_GLOBAL_STATIC(CustomObjectDataHash, s_designerObjectToDataHash)
+
+struct HandleDestroyedFunctor {
+ DesignerCustomObjectDataFork *data;
+ void operator()() { data->handleDestroyed(); }
+};
+
+using namespace Qt::StringLiterals;
+
+DesignerCustomObjectDataFork::DesignerCustomObjectDataFork(QObject *object)
+ : m_object(object)
+{
+ if (object) {
+ populateResetHashes();
+ s_designerObjectToDataHash()->insert(object, this);
+
+ HandleDestroyedFunctor functor;
+ functor.data = this;
+ QObject::connect(object, &QObject::destroyed, functor);
+ }
+}
+
+void DesignerCustomObjectDataFork::registerData(QObject *object)
+{
+ new DesignerCustomObjectDataFork(object);
+}
+
+DesignerCustomObjectDataFork *DesignerCustomObjectDataFork::get(QObject *object)
+{
+ return s_designerObjectToDataHash()->value(object);
+}
+
+QVariant DesignerCustomObjectDataFork::getResetValue(QObject *object, const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ DesignerCustomObjectDataFork* data = get(object);
+
+ if (data)
+ return data->getResetValue(propertyName);
+
+ return QVariant();
+}
+
+void DesignerCustomObjectDataFork::doResetProperty(QObject *object, QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ DesignerCustomObjectDataFork* data = get(object);
+
+ if (data)
+ data->doResetProperty(context, propertyName);
+}
+
+bool DesignerCustomObjectDataFork::hasValidResetBinding(QObject *object, const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ DesignerCustomObjectDataFork* data = get(object);
+
+ if (data)
+ return data->hasValidResetBinding(propertyName);
+
+ return false;
+}
+
+bool DesignerCustomObjectDataFork::hasBindingForProperty(QObject *object,
+ QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ bool *hasChanged)
+{
+ DesignerCustomObjectDataFork* data = get(object);
+
+ if (data)
+ return data->hasBindingForProperty(context, propertyName, hasChanged);
+
+ return false;
+}
+
+void DesignerCustomObjectDataFork::setPropertyBinding(QObject *object,
+ QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ const QString &expression)
+{
+ DesignerCustomObjectDataFork* data = get(object);
+
+ if (data)
+ data->setPropertyBinding(context, propertyName, expression);
+}
+
+void DesignerCustomObjectDataFork::keepBindingFromGettingDeleted(QObject *object,
+ QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ DesignerCustomObjectDataFork* data = get(object);
+
+ if (data)
+ data->keepBindingFromGettingDeleted(context, propertyName);
+}
+
+void DesignerCustomObjectDataFork::populateResetHashes()
+{
+ const QQuickDesignerSupport::PropertyNameList propertyNameList =
+ propertyNameListForWritablePropertiesFork(object());
+
+ const QMetaObject *mo = object()->metaObject();
+ QByteArrayList deferredPropertyNames;
+ const int namesIndex = mo->indexOfClassInfo("DeferredPropertyNames");
+ if (namesIndex != -1) {
+ QMetaClassInfo classInfo = mo->classInfo(namesIndex);
+ deferredPropertyNames = QByteArray(classInfo.value()).split(',');
+ }
+
+ for (const QQuickDesignerSupport::PropertyName &propertyName : propertyNameList) {
+
+ if (deferredPropertyNames.contains(propertyName))
+ continue;
+
+ QQmlProperty property(object(), QString::fromUtf8(propertyName), QQmlEngine::contextForObject(object()));
+
+ auto binding = QQmlAnyBinding::ofProperty(property);
+
+ if (binding) {
+ m_resetBindingHash.insert(propertyName, binding);
+ } else if (property.isWritable()) {
+ m_resetValueHash.insert(propertyName, property.read());
+ }
+ }
+}
+
+QObject *DesignerCustomObjectDataFork::object() const
+{
+ return m_object;
+}
+
+QVariant DesignerCustomObjectDataFork::getResetValue(const QQuickDesignerSupport::PropertyName &propertyName) const
+{
+ return m_resetValueHash.value(propertyName);
+}
+
+void DesignerCustomObjectDataFork::doResetProperty(QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ QQmlProperty property(object(), QString::fromUtf8(propertyName), context);
+
+ if (!property.isValid())
+ return;
+
+ // remove existing binding
+ QQmlAnyBinding::takeFrom(property);
+
+
+ if (hasValidResetBinding(propertyName)) {
+ QQmlAnyBinding binding = getResetBinding(propertyName);
+ binding.installOn(property);
+
+ if (binding.isAbstractPropertyBinding()) {
+ // for new style properties, we will evaluate during setBinding anyway
+ static_cast<QQmlBinding *>(binding.asAbstractBinding())->update();
+ }
+
+ } else if (property.isResettable()) {
+ property.reset();
+ } else if (property.propertyTypeCategory() == QQmlProperty::List) {
+ QQmlListReference list = qvariant_cast<QQmlListReference>(property.read());
+
+ if (!QQuickDesignerSupportProperties::hasFullImplementedListInterface(list)) {
+ qWarning() << "Property list interface not fully implemented for Class " << property.property().typeName() << " in property " << property.name() << "!";
+ return;
+ }
+
+ list.clear();
+ } else if (property.isWritable()) {
+ if (property.read() == getResetValue(propertyName))
+ return;
+
+ property.write(getResetValue(propertyName));
+ }
+}
+
+bool DesignerCustomObjectDataFork::hasValidResetBinding(const QQuickDesignerSupport::PropertyName &propertyName) const
+{
+ return m_resetBindingHash.contains(propertyName) && m_resetBindingHash.value(propertyName);
+}
+
+QQmlAnyBinding DesignerCustomObjectDataFork::getResetBinding(const QQuickDesignerSupport::PropertyName &propertyName) const
+{
+ return m_resetBindingHash.value(propertyName);
+}
+
+bool DesignerCustomObjectDataFork::hasBindingForProperty(QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ bool *hasChanged) const
+{
+ if (QQuickDesignerSupportProperties::isPropertyBlackListed(propertyName))
+ return false;
+
+ QQmlProperty property(object(), QString::fromUtf8(propertyName), context);
+
+ bool hasBinding = QQmlAnyBinding::ofProperty(property);
+
+ if (hasChanged) {
+ *hasChanged = hasBinding != m_hasBindingHash.value(propertyName, false);
+ if (*hasChanged)
+ m_hasBindingHash.insert(propertyName, hasBinding);
+ }
+
+ return hasBinding;
+}
+
+void DesignerCustomObjectDataFork::setPropertyBinding(QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName,
+ const QString &expression)
+{
+ QQmlProperty property(object(), QString::fromUtf8(propertyName), context);
+
+ if (!property.isValid())
+ return;
+
+ if (property.isProperty()) {
+ QString url = u"@designer"_s;
+ int lineNumber = 0;
+ QQmlAnyBinding binding = QQmlAnyBinding::createFromCodeString(property,
+ expression, object(), QQmlContextData::get(context), url, lineNumber);
+
+ binding.installOn(property);
+ if (binding.isAbstractPropertyBinding()) {
+ // for new style properties, we will evaluate during setBinding anyway
+ static_cast<QQmlBinding *>(binding.asAbstractBinding())->update();
+ }
+
+ if (binding.hasError()) {
+ if (property.property().userType() == QMetaType::QString)
+ property.write(QVariant(QLatin1Char('#') + expression + QLatin1Char('#')));
+ }
+
+ } else {
+ qWarning() << Q_FUNC_INFO << ": Cannot set binding for property" << propertyName << ": property is unknown for type";
+ }
+}
+
+void DesignerCustomObjectDataFork::keepBindingFromGettingDeleted(QQmlContext *context,
+ const QQuickDesignerSupport::PropertyName &propertyName)
+{
+ //Refcounting is taking care
+ Q_UNUSED(context);
+ Q_UNUSED(propertyName);
+}
+
+void DesignerCustomObjectDataFork::handleDestroyed()
+{
+ s_designerObjectToDataHash()->remove(m_object);
+ delete this;
+}
+
+
+
namespace QmlPrivateGate {
bool isPropertyBlackListed(const QmlDesigner::PropertyName &propertyName)
@@ -54,12 +523,14 @@ bool isPropertyBlackListed(const QmlDesigner::PropertyName &propertyName)
PropertyNameList allPropertyNames(QObject *object)
{
- return QQuickDesignerSupportProperties::allPropertyNames(object);
+ return allPropertyNamesFork(object);
+ //return QQuickDesignerSupportProperties::allPropertyNames(object);
}
PropertyNameList propertyNameListForWritableProperties(QObject *object)
{
- return QQuickDesignerSupportProperties::propertyNameListForWritableProperties(object);
+ return propertyNameListForWritablePropertiesFork(object);
+ //return QQuickDesignerSupportProperties::propertyNameListForWritableProperties(object);
}
void tweakObjects(QObject *object)
@@ -69,7 +540,9 @@ void tweakObjects(QObject *object)
void createNewDynamicProperty(QObject *object, QQmlEngine *engine, const QString &name)
{
- QQuickDesignerSupportProperties::createNewDynamicProperty(object, engine, name);
+ QQmlProperty qmlProp(object, name, engine->contextForObject(object));
+ if (!qmlProp.isValid())
+ QQuickDesignerSupportProperties::createNewDynamicProperty(object, engine, name);
}
void registerNodeInstanceMetaObject(QObject *object, QQmlEngine *engine)
@@ -187,7 +660,8 @@ bool hasFullImplementedListInterface(const QQmlListReference &list)
void registerCustomData(QObject *object)
{
- QQuickDesignerSupportProperties::registerCustomData(object);
+ DesignerCustomObjectDataFork::registerData(object);
+ //QQuickDesignerSupportProperties::registerCustomData(object);
}
QVariant getResetValue(QObject *object, const PropertyName &propertyName)
@@ -201,7 +675,8 @@ QVariant getResetValue(QObject *object, const PropertyName &propertyName)
else if (propertyName == "Layout.fillWidth")
return false;
else
- return QQuickDesignerSupportProperties::getResetValue(object, propertyName);
+ return DesignerCustomObjectDataFork::getResetValue(object, propertyName);
+ //return QQuickDesignerSupportProperties::getResetValue(object, propertyName);
}
static void setProperty(QObject *object, QQmlContext *context, const PropertyName &propertyName, const QVariant &value)
@@ -221,7 +696,9 @@ void doResetProperty(QObject *object, QQmlContext *context, const PropertyName &
else if (propertyName == "Layout.fillWidth")
setProperty(object, context, propertyName, getResetValue(object, propertyName));
else
- QQuickDesignerSupportProperties::doResetProperty(object, context, propertyName);
+ DesignerCustomObjectDataFork::doResetProperty(object, context, propertyName);
+
+ //QQuickDesignerSupportProperties::doResetProperty(object, context, propertyName);
}
bool hasValidResetBinding(QObject *object, const PropertyName &propertyName)
@@ -234,17 +711,22 @@ bool hasValidResetBinding(QObject *object, const PropertyName &propertyName)
return true;
else if (propertyName == "Layout.fillWidth")
return true;
- return QQuickDesignerSupportProperties::hasValidResetBinding(object, propertyName);
+ return
+ DesignerCustomObjectDataFork::hasValidResetBinding(object, propertyName);
+ //QQuickDesignerSupportProperties::hasValidResetBinding(object, propertyName);
}
bool hasBindingForProperty(QObject *object, QQmlContext *context, const PropertyName &propertyName, bool *hasChanged)
{
- return QQuickDesignerSupportProperties::hasBindingForProperty(object, context, propertyName, hasChanged);
+ return DesignerCustomObjectDataFork::hasBindingForProperty(object, context, propertyName, hasChanged);
+ //return QQuickDesignerSupportProperties::hasBindingForProperty(object, context, propertyName, hasChanged);
}
void setPropertyBinding(QObject *object, QQmlContext *context, const PropertyName &propertyName, const QString &expression)
{
- QQuickDesignerSupportProperties::setPropertyBinding(object, context, propertyName, expression);
+ DesignerCustomObjectDataFork::setPropertyBinding(object, context, propertyName, expression);
+
+ //QQuickDesignerSupportProperties::setPropertyBinding(object, context, propertyName, expression);
}
void emitComponentComplete(QObject *item)
@@ -317,7 +799,8 @@ void doComponentCompleteRecursive(QObject *object, NodeInstanceServer *nodeInsta
void keepBindingFromGettingDeleted(QObject *object, QQmlContext *context, const PropertyName &propertyName)
{
- QQuickDesignerSupportProperties::keepBindingFromGettingDeleted(object, context, propertyName);
+ DesignerCustomObjectDataFork::keepBindingFromGettingDeleted(object, context, propertyName);
+ //QQuickDesignerSupportProperties::keepBindingFromGettingDeleted(object, context, propertyName);
}
bool objectWasDeleted(QObject *object)
diff --git a/tests/system/objects.map b/tests/system/objects.map
index 66681c6b05..6ad38f5831 100644
--- a/tests/system/objects.map
+++ b/tests/system/objects.map
@@ -12,7 +12,7 @@
:*Qt Creator.findEdit_Utils::FilterLineEdit {name='findEdit' type='Utils::FancyLineEdit' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:*Qt Creator_Core::Internal::FancyToolButton {name='KitSelector.Button' type='Core::Internal::FancyToolButton' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:*Qt Creator_Utils::FilterLineEdit {type='Utils::FancyLineEdit' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
-:*Qt Creator_Utils::IconButton {occurrence='5' type='Utils::FancyIconButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
+:*Qt Creator_Utils::IconButton {toolTip='Clear text' type='Utils::FancyIconButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:About Qt Creator_Core::Internal::VersionDialog {type='Core::Internal::VersionDialog' unnamed='1' visible='1' windowTitle='About Qt Creator'}
:Activate completion:_QComboBox {buddy=':Behavior.Activate completion:_QLabel' type='QComboBox' unnamed='1' visible='1'}
:Add Bookmark.ExpandBookmarksList_QToolButton {text='+' type='QToolButton' unnamed='1' visible='1' window=':Add Bookmark_BookmarkDialog'}
@@ -92,7 +92,6 @@
:JsonWizard_ProjectExplorer::JsonFieldPage {type='ProjectExplorer::JsonFieldPage' unnamed='1' visible='1' window=':New_ProjectExplorer::JsonWizard'}
:Kits_QtVersion_QComboBox {container=':qt_tabwidget_stackedwidget_QWidget' leftWidget=':QtVersionLabel_KitPage' type='QComboBox' unnamed='1' visible='1'}
:Locals and Expressions_Debugger::Internal::WatchTreeView {container=':Debugger.Docks.LocalsAndWatchersDockWidget.Inspector_QFrame' name='WatchWindow' type='Debugger::Internal::WatchTreeView' visible='1'}
-:New Text File.Add to project:_QLabel {name='projectLabel' text='Add to project:' type='QLabel' visible='1' window=':New_ProjectExplorer::JsonWizard'}
:New Text File.nameLineEdit_Utils::FileNameValidatingLineEdit {name='nameLineEdit' type='Utils::FileNameValidatingLineEdit' visible='1' window=':New_ProjectExplorer::JsonWizard'}
:New.comboBox_QComboBox {type='QComboBox' unnamed='1' visible='1' window=':New_Core::Internal::NewDialog'}
:New.templateCategoryView_QTreeView {name='templateCategoryView' type='QTreeView' visible='1' window=':New_Core::Internal::NewDialog'}
@@ -141,11 +140,11 @@
:Qt Creator.WelcomeScreenStackedWidget {name='WelcomeScreenStackedWidget' type='QStackedWidget' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:Qt Creator.replaceEdit_Utils::FilterLineEdit {name='replaceEdit' type='Utils::FancyLineEdit' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:Qt Creator.splitter_QSplitter {name='splitter' type='QSplitter' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
-:Qt Creator_AppOutput_Core::Internal::OutputPaneToggleButton {occurrence='3' type='Core::Internal::OutputPaneToggleButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
+:Qt Creator_AppOutput_Core::Internal::OutputPaneToggleButton {toolTip?='*Application Output*' type='Core::Internal::OutputPaneToggleButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:Qt Creator_BinEditor::BinEditorWidget {type='BinEditor::Internal::BinEditorWidget' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:Qt Creator_Bookmarks_TreeView {type='TreeView' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:Qt Creator_CloseButton {type='CloseButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
-:Qt Creator_CompileOutput_Core::Internal::OutputPaneToggleButton {occurrence='4' type='Core::Internal::OutputPaneToggleButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
+:Qt Creator_CompileOutput_Core::Internal::OutputPaneToggleButton {toolTip?='*Compile Output*' type='Core::Internal::OutputPaneToggleButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:Qt Creator_Core::Internal::CommandComboBox {type='Core::Internal::CommandComboBox' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:Qt Creator_Core::Internal::MainWindow {type='Utils::AppMainWindow' visible='1' windowTitle?='*Qt Creator'}
:Qt Creator_Core::Internal::NavComboBox {type='Core::Internal::NavComboBox' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
@@ -153,17 +152,17 @@
:Qt Creator_Core::OutputWindow {type='Core::OutputWindow' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:Qt Creator_CppEditor::Internal::CPPEditorWidget {type='CppEditor::CppEditorWidget' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:Qt Creator_DiffEditor::Internal::DescriptionEditorWidget {type='DiffEditor::Internal::DescriptionEditorWidget' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
-:Qt Creator_DiffEditor::SideDiffEditorWidget {type='DiffEditor::Internal::SideDiffEditorWidget' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
-:Qt Creator_DiffEditor::SideDiffEditorWidget2 {occurrence='2' type='DiffEditor::Internal::SideDiffEditorWidget' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
+:Qt Creator_DiffEditor::SideDiffEditorWidgetChanged {type='DiffEditor::Internal::SideDiffEditorWidget' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow' x~='[1-9][0-9]*'}
+:Qt Creator_DiffEditor::SideDiffEditorWidgetOriginal {type='DiffEditor::Internal::SideDiffEditorWidget' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow' x='0'}
:Qt Creator_FilenameQComboBox {leftWidget=':Qt Creator.DragDoc_QToolButton' type='QComboBox' unnamed='1' visible='1'}
:Qt Creator_Find::Internal::SearchResultTreeView {type='Core::Internal::SearchResultTreeView' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:Qt Creator_Git::Internal::GitEditor {type='Git::Internal::GitEditorWidget' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:Qt Creator_HelpSelector_QComboBox {occurrence='3' type='QComboBox' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
-:Qt Creator_Issues_Core::Internal::OutputPaneToggleButton {occurrence='1' type='Core::Internal::OutputPaneToggleButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
+:Qt Creator_Issues_Core::Internal::OutputPaneToggleButton {toolTip?='*Issues*' type='Core::Internal::OutputPaneToggleButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:Qt Creator_QHelpContentWidget {name='helpContentWidget' type='QTreeView' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:Qt Creator_QmlJSEditor::Internal::QmlJSOutlineTreeView {type='QmlJSEditor::Internal::QmlJSOutlineTreeView' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:Qt Creator_QmlJSEditor::QmlJSTextEditorWidget {type='QmlJSEditor::QmlJSEditorWidget' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
-:Qt Creator_SearchResult_Core::Internal::OutputPaneToggleButton {occurrence='2' type='Core::Internal::OutputPaneToggleButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
+:Qt Creator_SearchResult_Core::Internal::OutputPaneToggleButton {toolTip?='*Search Results*' type='Core::Internal::OutputPaneToggleButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:Qt Creator_TextEditor::TextEditorWidget {type='TextEditor::TextEditorWidget' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:Qt Creator_Utils::BuildDirectoryLineEdit {name='LineEdit' type='Utils::FancyLineEdit' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:Qt Creator_Utils::NavigationTreeView {name='projectTreeView' type='QTreeView' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
@@ -205,8 +204,7 @@
:headerFileLineEdit_Utils::FileNameValidatingLineEdit {name='HdrFileName' type='Utils::FancyLineEdit' visible='1' window=':New_ProjectExplorer::JsonWizard'}
:popupFrame_Proposal_QListView {container=':popupFrame_TextEditor::GenericProposalWidget' type='QListView' unnamed='1' visible='1'}
:popupFrame_TextEditor::GenericProposalWidget {name='m_popupFrame' type='TextEditor::GenericProposalWidget' visible='1'}
-:projectComboBox_QComboBox {buddy=':New Text File.Add to project:_QLabel' name='projectComboBox' type='QComboBox' visible='1'}
-:projectComboBox_Utils::TreeViewComboBox {buddy=':New Text File.Add to project:_QLabel' name='projectComboBox' type='QComboBox' visible='1'}
+:projectComboBox_QComboBox {name='projectComboBox' type='QComboBox' visible='1'}
:qdesigner_internal::WidgetBoxCategoryListView {container=':Widget Box_qdesigner_internal::WidgetBoxTreeWidget' occurrence='3' type='qdesigner_internal::WidgetBoxCategoryListView' unnamed='1' visible='1'}
:qt_tabwidget_stackedwidget.QtSupport__Internal__QtVersionManager_QtSupport::Internal::QtOptionsPageWidget {container=':Options.qt_tabwidget_stackedwidget_QStackedWidget' type='QScrollArea' unnamed='1' visible='1'}
:qt_tabwidget_stackedwidget_QScrollArea {container=':Options.qt_tabwidget_stackedwidget_QStackedWidget' type='QScrollArea' unnamed='1' visible='1'}
diff --git a/tests/system/settings/windows/QtProject/qtcreator/debuggers.xml b/tests/system/settings/windows/QtProject/qtcreator/debuggers.xml
index b8d5b705e1..64016440ae 100644
--- a/tests/system/settings/windows/QtProject/qtcreator/debuggers.xml
+++ b/tests/system/settings/windows/QtProject/qtcreator/debuggers.xml
@@ -6,23 +6,6 @@
<variable>DebuggerItem.0</variable>
<valuemap type="QVariantMap">
<valuelist type="QVariantList" key="Abis">
- <value type="QString">x86-windows-msvc2015-pe-SQUISH_DEBUGGER_BITNESSbit</value>
- </valuelist>
- <value type="bool" key="AutoDetected">true</value>
- <value type="QString" key="AutoDetectionSource"></value>
- <value type="QString" key="Binary">C:/Program Files (x86)/Windows Kits/10/Debuggers/SQUISH_DEBUGGER_ARCHITECTURE/cdb.exe</value>
- <value type="QString" key="DisplayName">Auto-detected CDB at C:\Program Files (x86)\Windows Kits\10\Debuggers\SQUISH_DEBUGGER_ARCHITECTURE\cdb.exe</value>
- <value type="int" key="EngineType">4</value>
- <value type="QString" key="Id">{1b25f20a-d584-4fb7-85b3-74dd15b82f6f}</value>
- <value type="QDateTime" key="LastModified"></value>
- <value type="QString" key="Version"></value>
- <value type="QString" key="WorkingDirectory"></value>
- </valuemap>
- </data>
- <data>
- <variable>DebuggerItem.1</variable>
- <valuemap type="QVariantMap">
- <valuelist type="QVariantList" key="Abis">
<value type="QString">x86-windows-msys-pe-unknown</value>
</valuelist>
<value type="bool" key="AutoDetected">false</value>
@@ -36,7 +19,7 @@
</data>
<data>
<variable>DebuggerItem.Count</variable>
- <value type="int">2</value>
+ <value type="int">1</value>
</data>
<data>
<variable>Version</variable>
diff --git a/tests/system/settings/windows/QtProject/qtcreator/profiles.xml b/tests/system/settings/windows/QtProject/qtcreator/profiles.xml
index 1a46caa099..ecb22a0459 100644
--- a/tests/system/settings/windows/QtProject/qtcreator/profiles.xml
+++ b/tests/system/settings/windows/QtProject/qtcreator/profiles.xml
@@ -37,7 +37,6 @@
<value type="QString" key="PE.Profile.AutoDetectionSource"></value>
<valuemap type="QVariantMap" key="PE.Profile.Data">
<value type="QString" key="Android.GdbServer.Information"></value>
- <value type="QString" key="Debugger.Information">{1b25f20a-d584-4fb7-85b3-74dd15b82f6f}</value>
<value type="QString" key="PE.Profile.Device">Desktop Device</value>
<value type="QByteArray" key="PE.Profile.DeviceType">Desktop</value>
<valuelist type="QVariantList" key="PE.Profile.Environment"/>
@@ -65,7 +64,6 @@
<valuemap type="QVariantMap" key="PE.Profile.Data">
<value type="QString"></value>
<value type="QString" key="Android.GdbServer.Information"></value>
- <value type="QString" key="Debugger.Information">{1b25f20a-d584-4fb7-85b3-74dd15b82f6f}</value>
<value type="QString" key="PE.Profile.Device">Desktop Device</value>
<value type="QByteArray" key="PE.Profile.DeviceType">Desktop</value>
<valuelist type="QVariantList" key="PE.Profile.Environment">
@@ -94,7 +92,6 @@
<value type="bool" key="PE.Profile.AutoDetected">false</value>
<value type="QString" key="PE.Profile.AutoDetectionSource"></value>
<valuemap type="QVariantMap" key="PE.Profile.Data">
- <value type="QString" key="Debugger.Information">{1b25f20a-d584-4fb7-85b3-74dd15b82f6f}</value>
<value type="QString" key="PE.Profile.Device">Desktop Device</value>
<value type="QString" key="PE.Profile.DeviceType">Desktop</value>
<valuemap type="QVariantMap" key="PE.Profile.ToolChainsV3">
diff --git a/tests/system/shared/project.py b/tests/system/shared/project.py
index 2ff44dc373..cdf5290d89 100644
--- a/tests/system/shared/project.py
+++ b/tests/system/shared/project.py
@@ -662,7 +662,7 @@ def addCPlusPlusFile(name, template, projectName, forceOverwrite=False, addToVCS
test.compare(str(waitForObject("{name='HdrFileName' type='QLineEdit' visible='1'}").text),
expectedHeaderName)
clickButton(waitForObject(":Next_QPushButton"))
- projectComboBox = waitForObjectExists(":projectComboBox_Utils::TreeViewComboBox")
+ projectComboBox = waitForObjectExists(":projectComboBox_QComboBox")
test.compare(projectComboBox.enabled, projectName != None,
"Project combo box must be enabled when a project is open")
projectNameToDisplay = "<None>"
diff --git a/tests/system/shared/qtcreator.py b/tests/system/shared/qtcreator.py
index f1d4078fb5..12d6fc364b 100644
--- a/tests/system/shared/qtcreator.py
+++ b/tests/system/shared/qtcreator.py
@@ -201,31 +201,6 @@ def substituteDefaultCompiler(settingsDir):
__substitute__(qtversion, "SQUISH_DEFAULT_COMPILER", compiler)
test.log("Injected default compiler '%s' to qtversion.xml..." % compiler)
-def substituteCdb(settingsDir):
- def canUse64bitCdb():
- try:
- serverIni = readFile(os.path.join(os.getenv("APPDATA"), "froglogic",
- "Squish", "ver1", "server.ini"))
- autLine = next(iter(filter(lambda line: "AUT/qtcreator" in line,
- serverIni.splitlines())))
- autPath = autLine.split("\"")[1]
- return os.path.exists(os.path.join(autPath, "..", "lib", "qtcreatorcdbext64"))
- except:
- test.fatal("Something went wrong when determining debugger bitness",
- "Did Squish's file structure change? Guessing 32-bit cdb can be used...")
- return True
-
- if canUse64bitCdb():
- architecture = "x64"
- bitness = "64"
- else:
- architecture = "x86"
- bitness = "32"
- debuggers = os.path.join(settingsDir, "QtProject", 'qtcreator', 'debuggers.xml')
- __substitute__(debuggers, "SQUISH_DEBUGGER_ARCHITECTURE", architecture)
- __substitute__(debuggers, "SQUISH_DEBUGGER_BITNESS", bitness)
- test.log("Injected architecture '%s' and bitness '%s' in cdb path..." % (architecture, bitness))
-
def substituteMsvcPaths(settingsDir, version, targetBitness=64):
if not version in ['2017', '2019']:
@@ -298,7 +273,6 @@ def copySettingsToTmpDir(destination=None, omitFiles=[]):
substituteTildeWithinQtVersion(tmpSettingsDir)
substituteDefaultCompiler(tmpSettingsDir)
elif platform.system() in ('Windows', 'Microsoft'):
- substituteCdb(tmpSettingsDir)
substituteMsvcPaths(tmpSettingsDir, '2017', 64)
substituteMsvcPaths(tmpSettingsDir, '2017', 32)
substituteMsvcPaths(tmpSettingsDir, '2019', 64)
diff --git a/tests/system/suite_debugger/tst_debug_empty_main/test.py b/tests/system/suite_debugger/tst_debug_empty_main/test.py
index 019b55e5f0..d62f76cdeb 100644
--- a/tests/system/suite_debugger/tst_debug_empty_main/test.py
+++ b/tests/system/suite_debugger/tst_debug_empty_main/test.py
@@ -14,8 +14,7 @@ def addFileToProject(projectPath, category, fileTemplate, fileName):
projectPath, "Verifying whether path is correct."):
replaceEditorContent(pathLineEdit, projectPath)
clickButton(waitForObject(":Next_QPushButton"))
- projCombo = findObject("{buddy={name='projectLabel' text='Add to project:' type='QLabel' "
- "visible='1'} name='projectComboBox' type='QComboBox' visible='1'}")
+ projCombo = waitForObjectExists(":projectComboBox_QComboBox", 1000)
proFileName = os.path.basename(projectPath) + ".pro"
test.verify(not selectFromCombo(projCombo, proFileName), "Verifying project is selected.")
__createProjectHandleLastPage__()
diff --git a/tests/system/suite_tools/tst_git_first_commit/test.py b/tests/system/suite_tools/tst_git_first_commit/test.py
index 1ef7090602..0ee8f2505b 100644
--- a/tests/system/suite_tools/tst_git_first_commit/test.py
+++ b/tests/system/suite_tools/tst_git_first_commit/test.py
@@ -35,7 +35,7 @@ def main():
test.verify(" files changed, 229938 insertions(+)" in commitDetails,
"Summary in details view?")
clickButton(waitForObject(":Select a Git Commit.Show_QPushButton"))
- changedEdit = waitForObject(":Qt Creator_DiffEditor::SideDiffEditorWidget")
+ changedEdit = waitForObject(":Qt Creator_DiffEditor::SideDiffEditorWidgetChanged")
waitFor("len(str(changedEdit.plainText)) > 0 and "
"str(changedEdit.plainText) != 'Waiting for data...'", 40000)
diffPlainText = str(changedEdit.plainText)
diff --git a/tests/system/suite_tools/tst_git_local/test.py b/tests/system/suite_tools/tst_git_local/test.py
index c74ad6e20c..1c9cd01712 100644
--- a/tests/system/suite_tools/tst_git_local/test.py
+++ b/tests/system/suite_tools/tst_git_local/test.py
@@ -105,8 +105,8 @@ def verifyClickCommit():
for i in range(1, 3):
if not __clickCommit__(i):
continue
- changed = waitForObject(":Qt Creator_DiffEditor::SideDiffEditorWidget")
- original = waitForObject(":Qt Creator_DiffEditor::SideDiffEditorWidget2")
+ changed = waitForObject(":Qt Creator_DiffEditor::SideDiffEditorWidgetChanged")
+ original = waitForObject(":Qt Creator_DiffEditor::SideDiffEditorWidgetOriginal")
waitFor('str(changed.plainText) != "Waiting for data..." '
'and str(original.plainText) != "Waiting for data..."', 5000)
# content of diff editors is merge of modified files
@@ -202,7 +202,7 @@ def main():
type(gitEditor, "<Right>")
rect = gitEditor.cursorRect(gitEditor.textCursor())
mouseClick(gitEditor, rect.x+rect.width/2, rect.y+rect.height/2, 0, Qt.LeftButton)
- changed = waitForObject(":Qt Creator_DiffEditor::SideDiffEditorWidget")
+ changed = waitForObject(":Qt Creator_DiffEditor::SideDiffEditorWidgetChanged")
waitFor('str(changed.plainText) != "Waiting for data..."', 5000)
test.compare(str(changed.plainText), "Retrieving data failed.",
"Showing an invalid commit can't succeed but Creator survived.")
diff --git a/tests/unit/.clang-format b/tests/unit/.clang-format
index d3695ac298..366f82f76f 100644
--- a/tests/unit/.clang-format
+++ b/tests/unit/.clang-format
@@ -2,6 +2,7 @@ Language: Cpp
AccessModifierOffset: -4
AlignEscapedNewlines: DontAlign
AllowShortFunctionsOnASingleLine: Inline
+AlwaysBreakTemplateDeclarations: true # use with clang 19
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
@@ -15,6 +16,7 @@ BreakBeforeBinaryOperators: All
BreakBeforeBraces: Custom
BreakConstructorInitializers: BeforeComma
BreakInheritanceList: AfterComma
+# BreakTemplateDeclarations: Yes # use with clang 19
ColumnLimit: 100
IncludeCategories:
- Regex: 'Q.*'
diff --git a/tests/unit/tests/matchers/projectstorage-matcher.h b/tests/unit/tests/matchers/projectstorage-matcher.h
index 5ce6512c14..02861d7eea 100644
--- a/tests/unit/tests/matchers/projectstorage-matcher.h
+++ b/tests/unit/tests/matchers/projectstorage-matcher.h
@@ -53,3 +53,24 @@ MATCHER_P3(IsItemLibraryProperty,
return property.name == name && property.type == type && property.value == value;
}
+
+template<typename IconPathMatcher, typename TypeTraitsMatcher, typename HintsJsonMatcher, typename ItemLibraryJsonMatcher>
+auto IsTypeAnnotation(QmlDesigner::SourceId sourceId,
+ QmlDesigner::SourceId directorySourceId,
+ Utils::SmallStringView typeName,
+ QmlDesigner::ModuleId moduleId,
+ IconPathMatcher iconPath,
+ TypeTraitsMatcher traits,
+ HintsJsonMatcher hintsJsonMatcher,
+ ItemLibraryJsonMatcher itemLibraryJsonMatcher)
+{
+ using QmlDesigner::Storage::Synchronization::TypeAnnotation;
+ return AllOf(Field("sourceId", &TypeAnnotation::sourceId, sourceId),
+ Field("sourceId", &TypeAnnotation::directorySourceId, directorySourceId),
+ Field("typeName", &TypeAnnotation::typeName, typeName),
+ Field("moduleId", &TypeAnnotation::moduleId, moduleId),
+ Field("iconPath", &TypeAnnotation::iconPath, iconPath),
+ Field("traits", &TypeAnnotation::traits, traits),
+ Field("hintsJson", &TypeAnnotation::hintsJson, hintsJsonMatcher),
+ Field("itemLibraryJson", &TypeAnnotation::itemLibraryJson, itemLibraryJsonMatcher));
+}
diff --git a/tests/unit/tests/matchers/unittest-matchers.h b/tests/unit/tests/matchers/unittest-matchers.h
index 7c52d973b8..faa99a48a2 100644
--- a/tests/unit/tests/matchers/unittest-matchers.h
+++ b/tests/unit/tests/matchers/unittest-matchers.h
@@ -95,6 +95,64 @@ private:
const QString m_suffix;
};
+template<typename StringType>
+class StartsWithMatcher
+{
+public:
+ explicit StartsWithMatcher(const StringType &prefix)
+ : m_prefix(prefix)
+ {}
+
+ template<typename CharType>
+ bool MatchAndExplain(CharType *s, testing::MatchResultListener *listener) const
+ {
+ return s != NULL && MatchAndExplain(StringType(s), listener);
+ }
+
+ template<typename MatcheeStringType>
+ bool MatchAndExplain(const MatcheeStringType &s, testing::MatchResultListener * /* listener */) const
+ {
+ return s.startsWith(m_prefix);
+ }
+
+ void DescribeTo(::std::ostream *os) const { *os << "ends with " << m_prefix; }
+
+ void DescribeNegationTo(::std::ostream *os) const { *os << "doesn't end with " << m_prefix; }
+
+ StartsWithMatcher(const StartsWithMatcher &) = default;
+ StartsWithMatcher &operator=(const StartsWithMatcher &) = delete;
+
+private:
+ const StringType m_prefix;
+};
+
+class QStringStartsWithMatcher
+{
+public:
+ explicit QStringStartsWithMatcher(const QString &prefix)
+ : m_prefix(prefix)
+ {}
+
+ template<typename MatcheeStringType>
+ bool MatchAndExplain(const MatcheeStringType &s, testing::MatchResultListener * /* listener */) const
+ {
+ return s.startsWith(m_prefix);
+ }
+
+ void DescribeTo(::std::ostream *os) const
+ {
+ *os << "ends with " << testing::PrintToString(m_prefix);
+ }
+
+ void DescribeNegationTo(::std::ostream *os) const
+ {
+ *os << "doesn't end with " << testing::PrintToString(m_prefix);
+ }
+
+private:
+ const QString m_prefix;
+};
+
class IsEmptyMatcher
{
public:
@@ -157,6 +215,16 @@ inline auto EndsWith(const QStringView &suffix)
return ::testing::PolymorphicMatcher(Internal::QStringEndsWithMatcher(suffix.toString()));
}
+inline auto StartsWith(const Utils::SmallStringView &prefix)
+{
+ return ::testing::PolymorphicMatcher(Internal::StartsWithMatcher(prefix));
+}
+
+inline auto StartsWith(const QStringView &prefix)
+{
+ return ::testing::PolymorphicMatcher(Internal::QStringStartsWithMatcher(prefix.toString()));
+}
+
inline auto IsEmpty()
{
return ::testing::PolymorphicMatcher(Internal::IsEmptyMatcher());
diff --git a/tests/unit/tests/mocks/mocksqlitestatement.h b/tests/unit/tests/mocks/mocksqlitestatement.h
index f34b13f6d0..1e55d4c74f 100644
--- a/tests/unit/tests/mocks/mocksqlitestatement.h
+++ b/tests/unit/tests/mocks/mocksqlitestatement.h
@@ -50,6 +50,8 @@ public:
SqliteDatabaseMock &database() { return *m_databaseMock; }
+ MOCK_METHOD(std::uintptr_t, handle, (), (const));
+
private:
SqliteDatabaseMock *m_databaseMock = nullptr;
};
diff --git a/tests/unit/tests/mocks/projectstoragemock.cpp b/tests/unit/tests/mocks/projectstoragemock.cpp
index 83ff85fe9a..6d5304879e 100644
--- a/tests/unit/tests/mocks/projectstoragemock.cpp
+++ b/tests/unit/tests/mocks/projectstoragemock.cpp
@@ -51,6 +51,7 @@ ModuleId ProjectStorageMock::createModule(Utils::SmallStringView moduleName)
incrementBasicId(moduleId);
ON_CALL(*this, moduleId(Eq(moduleName))).WillByDefault(Return(moduleId));
+ ON_CALL(*this, moduleName(Eq(moduleId))).WillByDefault(Return(moduleName));
ON_CALL(*this, fetchModuleIdUnguarded(Eq(moduleName))).WillByDefault(Return(moduleId));
return moduleId;
@@ -122,6 +123,14 @@ void ProjectStorageMock::addExportedTypeName(QmlDesigner::TypeId typeId,
exportedTypeName[typeId].emplace_back(moduleId, typeName);
}
+void ProjectStorageMock::addExportedTypeNameBySourceId(QmlDesigner::TypeId typeId,
+ QmlDesigner::ModuleId moduleId,
+ Utils::SmallStringView typeName,
+ QmlDesigner::SourceId sourceId)
+{
+ exportedTypeNameBySourceId[{typeId, sourceId}].emplace_back(moduleId, typeName);
+}
+
void ProjectStorageMock::removeExportedTypeName(QmlDesigner::TypeId typeId,
QmlDesigner::ModuleId moduleId,
Utils::SmallStringView typeName)
@@ -227,7 +236,9 @@ void ProjectStorageMock::setItemLibraryEntries(
}
namespace {
-void addBaseProperties(TypeId typeId, TypeIds baseTypeIds, ProjectStorageMock &storage)
+void addBaseProperties(TypeId typeId,
+ const QmlDesigner::SmallTypeIds<16> &baseTypeIds,
+ ProjectStorageMock &storage)
{
for (TypeId baseTypeId : baseTypeIds) {
for (const auto &propertyId : storage.localPropertyDeclarationIds(baseTypeId)) {
@@ -254,7 +265,7 @@ TypeId ProjectStorageMock::createType(ModuleId moduleId,
PropertyDeclarationTraits defaultPropertyTraits,
TypeId defaultPropertyTypeId,
Storage::TypeTraits typeTraits,
- TypeIds baseTypeIds,
+ const QmlDesigner::SmallTypeIds<16> &baseTypeIds,
SourceId sourceId)
{
if (auto id = typeId(moduleId, typeName)) {
@@ -282,18 +293,19 @@ TypeId ProjectStorageMock::createType(ModuleId moduleId,
defaultPropertyTypeId);
}
- ON_CALL(*this, type(Eq(typeId)))
- .WillByDefault(Return(Storage::Info::Type{defaultPropertyDeclarationId, sourceId, typeTraits}));
+ ON_CALL(*this, type(Eq(typeId))).WillByDefault(Return(Storage::Info::Type{sourceId, typeTraits}));
+
+ ON_CALL(*this, defaultPropertyDeclarationId(Eq(typeId)))
+ .WillByDefault(Return(defaultPropertyDeclarationId));
ON_CALL(*this, isBasedOn(Eq(typeId), Eq(typeId))).WillByDefault(Return(true));
for (TypeId baseTypeId : baseTypeIds)
ON_CALL(*this, isBasedOn(Eq(typeId), Eq(baseTypeId))).WillByDefault(Return(true));
- TypeIds selfAndPrototypes;
- selfAndPrototypes.reserve(baseTypeIds.size() + 1);
+ QmlDesigner::SmallTypeIds<16> selfAndPrototypes;
selfAndPrototypes.push_back(typeId);
- selfAndPrototypes.insert(selfAndPrototypes.end(), baseTypeIds.begin(), baseTypeIds.end());
+ std::copy(baseTypeIds.begin(), baseTypeIds.end(), std::back_inserter(selfAndPrototypes));
ON_CALL(*this, prototypeAndSelfIds(Eq(typeId))).WillByDefault(Return(selfAndPrototypes));
ON_CALL(*this, prototypeIds(Eq(typeId))).WillByDefault(Return(baseTypeIds));
@@ -314,7 +326,7 @@ void ProjectStorageMock::removeType(QmlDesigner::ModuleId moduleId, Utils::Small
QmlDesigner::TypeId ProjectStorageMock::createType(QmlDesigner::ModuleId moduleId,
Utils::SmallStringView typeName,
QmlDesigner::Storage::TypeTraits typeTraits,
- QmlDesigner::TypeIds baseTypeIds,
+ const QmlDesigner::SmallTypeIds<16> &baseTypeIds,
SourceId sourceId)
{
return createType(moduleId, typeName, {}, {}, TypeId{}, typeTraits, baseTypeIds, sourceId);
@@ -325,7 +337,7 @@ TypeId ProjectStorageMock::createObject(ModuleId moduleId,
Utils::SmallStringView defaultPropertyName,
PropertyDeclarationTraits defaultPropertyTraits,
QmlDesigner::TypeId defaultPropertyTypeId,
- TypeIds baseTypeIds,
+ const QmlDesigner::SmallTypeIds<16> &baseTypeIds,
QmlDesigner::SourceId sourceId)
{
return createType(moduleId,
@@ -340,19 +352,20 @@ TypeId ProjectStorageMock::createObject(ModuleId moduleId,
TypeId ProjectStorageMock::createObject(ModuleId moduleId,
Utils::SmallStringView typeName,
- TypeIds baseTypeIds)
+ const QmlDesigner::SmallTypeIds<16> &baseTypeIds)
{
return createType(moduleId, typeName, Storage::TypeTraitsKind::Reference, baseTypeIds);
}
QmlDesigner::TypeId ProjectStorageMock::createValue(QmlDesigner::ModuleId moduleId,
Utils::SmallStringView typeName,
- QmlDesigner::TypeIds baseTypeIds)
+ const QmlDesigner::SmallTypeIds<16> &baseTypeIds)
{
return createType(moduleId, typeName, Storage::TypeTraitsKind::Value, baseTypeIds);
}
-void ProjectStorageMock::setHeirs(QmlDesigner::TypeId typeId, QmlDesigner::TypeIds heirIds)
+void ProjectStorageMock::setHeirs(QmlDesigner::TypeId typeId,
+ const QmlDesigner::SmallTypeIds<64> &heirIds)
{
ON_CALL(*this, heirIds(typeId)).WillByDefault(Return(heirIds));
}
@@ -362,6 +375,10 @@ ProjectStorageMock::ProjectStorageMock()
ON_CALL(*this, exportedTypeNames(_)).WillByDefault([&](TypeId id) {
return exportedTypeName[id];
});
+
+ ON_CALL(*this, exportedTypeNames(_, _)).WillByDefault([&](TypeId typeId, SourceId sourceId) {
+ return exportedTypeNameBySourceId[{typeId, sourceId}];
+ });
}
void ProjectStorageMock::setupQtQuick()
diff --git a/tests/unit/tests/mocks/projectstoragemock.h b/tests/unit/tests/mocks/projectstoragemock.h
index 198e54b370..8aa5979ddb 100644
--- a/tests/unit/tests/mocks/projectstoragemock.h
+++ b/tests/unit/tests/mocks/projectstoragemock.h
@@ -46,6 +46,11 @@ public:
QmlDesigner::ModuleId moduleId,
Utils::SmallStringView typeName);
+ void addExportedTypeNameBySourceId(QmlDesigner::TypeId typeId,
+ QmlDesigner::ModuleId moduleId,
+ Utils::SmallStringView typeName,
+ QmlDesigner::SourceId sourceId);
+
void removeExportedTypeName(QmlDesigner::TypeId typeId,
QmlDesigner::ModuleId moduleId,
Utils::SmallStringView typeName);
@@ -56,7 +61,7 @@ public:
QmlDesigner::Storage::PropertyDeclarationTraits defaultPropertyTraits,
QmlDesigner::TypeId defaultPropertyTypeId,
QmlDesigner::Storage::TypeTraits typeTraits,
- QmlDesigner::TypeIds baseTypeIds = {},
+ const QmlDesigner::SmallTypeIds<16> &baseTypeIds = {},
QmlDesigner::SourceId sourceId = QmlDesigner::SourceId{});
void removeType(QmlDesigner::ModuleId moduleId, Utils::SmallStringView typeName);
@@ -64,27 +69,26 @@ public:
QmlDesigner::TypeId createType(QmlDesigner::ModuleId moduleId,
Utils::SmallStringView typeName,
QmlDesigner::Storage::TypeTraits typeTraits,
- QmlDesigner::TypeIds baseTypeIds = {},
+ const QmlDesigner::SmallTypeIds<16> &baseTypeIds = {},
QmlDesigner::SourceId sourceId = QmlDesigner::SourceId{});
- QmlDesigner::TypeId createObject(
- QmlDesigner::ModuleId moduleId,
- Utils::SmallStringView typeName,
- Utils::SmallStringView defaultPropertyName,
- QmlDesigner::Storage::PropertyDeclarationTraits defaultPropertyTraits,
- QmlDesigner::TypeId defaultPropertyTypeId,
- QmlDesigner::TypeIds baseTypeIds = {},
- QmlDesigner::SourceId sourceId = QmlDesigner::SourceId{});
+ QmlDesigner::TypeId createObject(QmlDesigner::ModuleId moduleId,
+ Utils::SmallStringView typeName,
+ Utils::SmallStringView defaultPropertyName,
+ QmlDesigner::Storage::PropertyDeclarationTraits defaultPropertyTraits,
+ QmlDesigner::TypeId defaultPropertyTypeId,
+ const QmlDesigner::SmallTypeIds<16> &baseTypeIds = {},
+ QmlDesigner::SourceId sourceId = QmlDesigner::SourceId{});
QmlDesigner::TypeId createObject(QmlDesigner::ModuleId moduleId,
Utils::SmallStringView typeName,
- QmlDesigner::TypeIds baseTypeIds = {});
+ const QmlDesigner::SmallTypeIds<16> &baseTypeIds = {});
QmlDesigner::TypeId createValue(QmlDesigner::ModuleId moduleId,
Utils::SmallStringView typeName,
- QmlDesigner::TypeIds baseTypeIds = {});
+ const QmlDesigner::SmallTypeIds<16> &baseTypeIds = {});
- void setHeirs(QmlDesigner::TypeId typeId, QmlDesigner::TypeIds heirIds);
+ void setHeirs(QmlDesigner::TypeId typeId, const QmlDesigner::SmallTypeIds<64> &heirIds);
QmlDesigner::PropertyDeclarationId createProperty(
QmlDesigner::TypeId typeId,
@@ -123,6 +127,7 @@ public:
MOCK_METHOD(void, removeObserver, (QmlDesigner::ProjectStorageObserver *), (override));
MOCK_METHOD(QmlDesigner::ModuleId, moduleId, (::Utils::SmallStringView), (const, override));
+ MOCK_METHOD(Utils::SmallString, moduleName, (QmlDesigner::ModuleId), (const, override));
MOCK_METHOD(std::optional<QmlDesigner::Storage::Info::PropertyDeclaration>,
propertyDeclaration,
@@ -182,10 +187,19 @@ public:
propertyDeclarationId,
(QmlDesigner::TypeId typeId, ::Utils::SmallStringView propertyName),
(const, override));
+ MOCK_METHOD(QmlDesigner::PropertyDeclarationId,
+ defaultPropertyDeclarationId,
+ (QmlDesigner::TypeId typeId),
+ (const, override));
MOCK_METHOD(std::optional<QmlDesigner::Storage::Info::Type>,
type,
(QmlDesigner::TypeId typeId),
(const, override));
+ MOCK_METHOD(QmlDesigner::SmallSourceIds<4>,
+ typeAnnotationSourceIds,
+ (QmlDesigner::SourceId directoryId),
+ (const, override));
+ MOCK_METHOD(QmlDesigner::SmallSourceIds<64>, typeAnnotationDirectorySourceIds, (), (const, override));
MOCK_METHOD(Utils::PathString, typeIconPath, (QmlDesigner::TypeId typeId), (const, override));
MOCK_METHOD(QmlDesigner::Storage::Info::TypeHints,
typeHints,
@@ -215,9 +229,15 @@ public:
propertyName,
(QmlDesigner::PropertyDeclarationId propertyDeclarationId),
(const, override));
- MOCK_METHOD(QmlDesigner::TypeIds, prototypeAndSelfIds, (QmlDesigner::TypeId type), (const, override));
- MOCK_METHOD(QmlDesigner::TypeIds, prototypeIds, (QmlDesigner::TypeId type), (const, override));
- MOCK_METHOD(QmlDesigner::TypeIds, heirIds, (QmlDesigner::TypeId type), (const, override));
+ MOCK_METHOD(QmlDesigner::SmallTypeIds<16>,
+ prototypeAndSelfIds,
+ (QmlDesigner::TypeId type),
+ (const, override));
+ MOCK_METHOD(QmlDesigner::SmallTypeIds<16>,
+ prototypeIds,
+ (QmlDesigner::TypeId type),
+ (const, override));
+ MOCK_METHOD(QmlDesigner::SmallTypeIds<64>, heirIds, (QmlDesigner::TypeId type), (const, override));
MOCK_METHOD(bool, isBasedOn, (QmlDesigner::TypeId typeId, QmlDesigner::TypeId), (const, override));
MOCK_METHOD(bool,
isBasedOn,
@@ -326,6 +346,8 @@ public:
QmlDesigner::Storage::Info::CommonTypeCache<QmlDesigner::ProjectStorageInterface> typeCache{*this};
std::map<QmlDesigner::TypeId, QmlDesigner::Storage::Info::ExportedTypeNames> exportedTypeName;
+ std::map<std::pair<QmlDesigner::TypeId, QmlDesigner::SourceId>, QmlDesigner::Storage::Info::ExportedTypeNames>
+ exportedTypeNameBySourceId;
};
class ProjectStorageMockWithQtQtuick : public ProjectStorageMock
diff --git a/tests/unit/tests/printers/gtest-creator-printing.cpp b/tests/unit/tests/printers/gtest-creator-printing.cpp
index 1bff6df492..6bc78e9936 100644
--- a/tests/unit/tests/printers/gtest-creator-printing.cpp
+++ b/tests/unit/tests/printers/gtest-creator-printing.cpp
@@ -675,7 +675,7 @@ std::ostream &operator<<(std::ostream &out, const PropertyDeclaration &propertyD
std::ostream &operator<<(std::ostream &out, const Type &type)
{
- return out << "(" << type.defaultPropertyId << ")";
+ return out << "(" << type.sourceId << ")";
}
std::ostream &operator<<(std::ostream &out, const ExportedTypeName &name)
@@ -795,7 +795,10 @@ std::ostream &operator<<(std::ostream &out, const SynchronizationPackage &packag
<< ", projectDatas: " << package.projectDatas
<< ", propertyEditorQmlPaths: " << package.propertyEditorQmlPaths
<< ", updatedPropertyEditorQmlPathSourceIds: "
- << package.updatedPropertyEditorQmlPathSourceIds << ")";
+ << package.updatedPropertyEditorQmlPathSourceIds
+ << ", typeAnnotations: " << package.typeAnnotations
+ << ", updatedTypeAnnotationSourceIds: " << package.updatedTypeAnnotationSourceIds
+ << ")";
}
std::ostream &operator<<(std::ostream &out, const ProjectData &data)
diff --git a/tests/unit/tests/stubs/qmldesigner/designercore/include/rewriterview.h b/tests/unit/tests/stubs/qmldesigner/designercore/include/rewriterview.h
index a10da0133c..4c59440b0f 100644
--- a/tests/unit/tests/stubs/qmldesigner/designercore/include/rewriterview.h
+++ b/tests/unit/tests/stubs/qmldesigner/designercore/include/rewriterview.h
@@ -128,8 +128,6 @@ public:
void setCheckSemanticErrors(bool) {}
- QString pathForImport(const Import &) { return {}; }
-
QStringList importDirectories() const { return {}; }
QSet<QPair<QString, QString>> qrcMapping() const { return {}; }
diff --git a/tests/unit/tests/unittests/componentcore/propertyeditorcomponentgenerator-test.cpp b/tests/unit/tests/unittests/componentcore/propertyeditorcomponentgenerator-test.cpp
index 3b9a8bbfe2..d2f2143a73 100644
--- a/tests/unit/tests/unittests/componentcore/propertyeditorcomponentgenerator-test.cpp
+++ b/tests/unit/tests/unittests/componentcore/propertyeditorcomponentgenerator-test.cpp
@@ -18,7 +18,7 @@ class PropertyEditorComponentGenerator : public ::testing::Test
{
protected:
QmlDesigner::NodeMetaInfo createType(Utils::SmallStringView name,
- QmlDesigner::TypeIds baseTypeIds = {})
+ const QmlDesigner::SmallTypeIds<16> &baseTypeIds = {})
{
auto typeId = projectStorageMock.createValue(qtQuickModuleId, name, baseTypeIds);
diff --git a/tests/unit/tests/unittests/imagecache/taskqueue-test.cpp b/tests/unit/tests/unittests/imagecache/taskqueue-test.cpp
index 537f4b3ea3..ea295c5733 100644
--- a/tests/unit/tests/unittests/imagecache/taskqueue-test.cpp
+++ b/tests/unit/tests/unittests/imagecache/taskqueue-test.cpp
@@ -100,4 +100,22 @@ TEST_F(TaskQueue, clean_task_in_queue)
queue.clean();
}
+TEST_F(TaskQueue, sleeping_queue_is_recovering)
+{
+ Queue queue{mockDispatchCallback.AsStdFunction(), mockCleanCallback.AsStdFunction()};
+ EXPECT_CALL(mockDispatchCallback, Call(IsTask(5))).WillRepeatedly([&](Task) {
+ notification.notify();
+ });
+ queue.addTask(5);
+ notification.wait();
+ queue.putThreadToSleep();
+
+ EXPECT_CALL(mockDispatchCallback, Call(IsTask(22))).WillRepeatedly([&](Task) {
+ notification.notify();
+ });
+
+ queue.addTask(22);
+ notification.wait();
+}
+
} // namespace
diff --git a/tests/unit/tests/unittests/model/model-test.cpp b/tests/unit/tests/unittests/model/model-test.cpp
index bda942fec0..bd34a3a6b1 100644
--- a/tests/unit/tests/unittests/model/model-test.cpp
+++ b/tests/unit/tests/unittests/model/model-test.cpp
@@ -116,11 +116,11 @@ protected:
NiceMock<SourcePathCacheMockWithPaths> pathCacheMock{"/path/foo.qml"};
NiceMock<ProjectStorageMockWithQtQtuick> projectStorageMock{pathCacheMock.sourceId};
NiceMock<ModelResourceManagementMock> resourceManagementMock;
+ QmlDesigner::Imports imports = {QmlDesigner::Import::createLibraryImport("QtQuick")};
QmlDesigner::Model model{{projectStorageMock, pathCacheMock},
"Item",
- -1,
- -1,
- nullptr,
+ imports,
+ pathCacheMock.path.toQString(),
std::make_unique<ModelResourceManagementMockWrapper>(
resourceManagementMock)};
NiceMock<AbstractViewMock> viewMock;
@@ -541,7 +541,10 @@ TEST_F(Model, by_default_remove_properties_removes_property)
TEST_F(Model, by_default_remove_model_node_in_factory_method_calls_removes_node)
{
model.detachView(&viewMock);
- auto newModel = QmlDesigner::Model::create({projectStorageMock, pathCacheMock}, "QtQuick.Item");
+ auto newModel = QmlDesigner::Model::create({projectStorageMock, pathCacheMock},
+ "Item",
+ imports,
+ pathCacheMock.path.toQString());
newModel->attachView(&viewMock);
auto node = createNodeWithParent(viewMock.rootModelNode());
@@ -553,7 +556,10 @@ TEST_F(Model, by_default_remove_model_node_in_factory_method_calls_removes_node)
TEST_F(Model, by_default_remove_properties_in_factory_method_calls_remove_property)
{
model.detachView(&viewMock);
- auto newModel = QmlDesigner::Model::create({projectStorageMock, pathCacheMock}, "QtQuick.Item");
+ auto newModel = QmlDesigner::Model::create({projectStorageMock, pathCacheMock},
+ "Item",
+ imports,
+ pathCacheMock.path.toQString());
newModel->attachView(&viewMock);
rootNode = viewMock.rootModelNode();
auto property = createProperty(rootNode, "yi");
diff --git a/tests/unit/tests/unittests/model/modelresourcemanagement-test.cpp b/tests/unit/tests/unittests/model/modelresourcemanagement-test.cpp
index 40b94f872d..fd3d3c70c3 100644
--- a/tests/unit/tests/unittests/model/modelresourcemanagement-test.cpp
+++ b/tests/unit/tests/unittests/model/modelresourcemanagement-test.cpp
@@ -280,7 +280,6 @@ INSTANTIATE_TEST_SUITE_P(
ForTarget,
testing::Values(TargetData{"QtQuick.Item", "QtQuick.PropertyChanges", "target"},
TargetData{"QtQuick.Item", "QtQuick.Timeline.KeyframeGroup", "target"},
- TargetData{"FlowView.FlowTransition", "FlowView.FlowActionArea", "target"},
TargetData{"QtQuick.Item", "QtQuick.PropertyAnimation", "target"},
TargetData{"FlowView.FlowItem", "FlowView.FlowTransition", "to"},
TargetData{"FlowView.FlowItem", "FlowView.FlowTransition", "from"}));
diff --git a/tests/unit/tests/unittests/model/modelutils-test.cpp b/tests/unit/tests/unittests/model/modelutils-test.cpp
index c7a70cfbdb..5a9e63b60d 100644
--- a/tests/unit/tests/unittests/model/modelutils-test.cpp
+++ b/tests/unit/tests/unittests/model/modelutils-test.cpp
@@ -141,7 +141,7 @@ TEST_F(ModelUtils, find_lowest_common_ancestor_when_one_of_the_nodes_is_parent)
ASSERT_THAT(commonAncestor, parentNode);
}
-TEST_F(ModelUtils, lowest_common_ancestor_for_uncle_and_nephew_should_return_the_grandFather)
+TEST_F(ModelUtils, lowest_common_ancestor_for_uncle_and_nephew_should_return_the_grandfather)
{
auto grandFatherNode = model.createModelNode("Item");
auto fatherNode = model.createModelNode("Item");
diff --git a/tests/unit/tests/unittests/model/nodelistproperty-test.cpp b/tests/unit/tests/unittests/model/nodelistproperty-test.cpp
index 6783bde3e7..aac2e729a2 100644
--- a/tests/unit/tests/unittests/model/nodelistproperty-test.cpp
+++ b/tests/unit/tests/unittests/model/nodelistproperty-test.cpp
@@ -61,8 +61,8 @@ protected:
++defaultPropertyIdNumber);
ON_CALL(projectStorageMock, typeId(Eq(moduleId), Eq(typeName), _)).WillByDefault(Return(typeId));
- ON_CALL(projectStorageMock, type(Eq(typeId)))
- .WillByDefault(Return(Info::Type{defaultPropertyId, QmlDesigner::SourceId{}, {}}));
+ ON_CALL(projectStorageMock, defaultPropertyDeclarationId(Eq(typeId)))
+ .WillByDefault(Return(defaultPropertyId));
ON_CALL(projectStorageMock, propertyName(Eq(defaultPropertyId)))
.WillByDefault(Return(defaultPeopertyName));
}
diff --git a/tests/unit/tests/unittests/projectstorage/data/qml/QtQuick/Controls/designer/qtquickcontrols2.metainfo b/tests/unit/tests/unittests/projectstorage/data/qml/QtQuick/Controls/designer/qtquickcontrols2.metainfo
new file mode 100644
index 0000000000..0cd3959cf8
--- /dev/null
+++ b/tests/unit/tests/unittests/projectstorage/data/qml/QtQuick/Controls/designer/qtquickcontrols2.metainfo
@@ -0,0 +1,575 @@
+MetaInfo {
+ Type {
+ name: "QtQuick.Controls.BusyIndicator"
+ icon: "images/busyindicator-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Busy Indicator"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/busyindicator-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("Indicates activity while, for example, content is being loaded.")
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Button"
+ icon: "images/button-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Button"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/button-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A button with text.")
+
+ Property { name: "text"; type: "binding"; value: "qsTr(\"Button\")" }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.CheckBox"
+ icon: "images/checkbox-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Check Box"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/checkbox-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A checkbox with a text label.")
+
+ Property { name: "text"; type: "binding"; value: "qsTr(\"Check Box\")" }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.CheckDelegate"
+ icon: "images/checkbox-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Check Delegate"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/checkbox-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("Presents items from a model as checkboxes.")
+
+ Property { name: "text"; type: "binding"; value: "qsTr(\"Check Delegate\")" }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.ComboBox"
+ icon: "images/combobox-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Combo Box"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/combobox-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("An editable drop-down list.")
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Control"
+ icon: "images/control-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Control"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/control-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("An abstract base type for UI controls.")
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.DelayButton"
+ icon: "images/button-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Delay Button"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/delaybutton-icon.png"
+ version: "2.2"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A button with a delay preventing accidental presses.")
+
+ Property { name: "text"; type: "binding"; value: "qsTr(\"Delay Button\")" }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Dial"
+ icon: "images/dial-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Dial"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/dial-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+
+ toolTip: qsTr("A circular dial that is rotated to set a value.")
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Frame"
+ icon: "images/frame-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Frame"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/frame-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("An untitled container for a group of controls.")
+
+ Property { name: "width"; type: "int"; value: 200 }
+ Property { name: "height"; type: "int"; value: 200 }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.GroupBox"
+ icon: "images/groupbox-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Group Box"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/groupbox-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A titled container for a group of controls.")
+
+ Property { name: "width"; type: "int"; value: 200 }
+ Property { name: "height"; type: "int"; value: 200 }
+ Property { name: "title"; type: "binding"; value: "qsTr(\"Group Box\")" }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.ItemDelegate"
+ icon: "images/itemdelegate-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Item Delegate"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/itemdelegate-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("Presents a standard view item. It can be used as a delegate in various views and controls, such as ListView and ComboBox.")
+
+ Property { name: "text"; type: "binding"; value: "qsTr(\"Item Delegate\")" }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Label"
+ icon: "images/label-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Label"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/label-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A text label.")
+
+ Property { name: "text"; type: "binding"; value: "qsTr(\"Label\")" }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Page"
+ icon: "images/page-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Page"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/page-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A page with header and footer.")
+
+ Property { name: "width"; type: "int"; value: 200 }
+ Property { name: "height"; type: "int"; value: 200 }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.PageIndicator"
+ icon: "images/pageindicator-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Page Indicator"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/pageindicator-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("Indicates the currently active page.")
+
+ Property { name: "count"; type: "int"; value: 3 }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Pane"
+ icon: "images/pane-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Pane"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/pane-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("Provides a background matching the application style and theme.")
+
+ Property { name: "width"; type: "int"; value: 200 }
+ Property { name: "height"; type: "int"; value: 200 }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.ProgressBar"
+ icon: "images/progressbar-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Progress Bar"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/progressbar-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A bar indicating the progress of an operation.")
+
+ Property { name: "value"; type: "real"; value: 0.5 }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.RadioButton"
+ icon: "images/radiobutton-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Radio Button"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/radiobutton-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("An option button that you can toggle on or off.")
+
+ Property { name: "text"; type: "binding"; value: "qsTr(\"Radio Button\")" }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.RadioDelegate"
+ icon: "images/radiobutton-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Radio Delegate"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/radiobutton-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("Presents items from a model as radio buttons.")
+
+ Property { name: "text"; type: "binding"; value: "qsTr(\"Radio Delegate\")" }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.RangeSlider"
+ icon: "images/rangeslider-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Range Slider"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/rangeslider-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A bar with adjustable start and end points.")
+
+ Property { name: "first.value"; type: "real"; value: 0.25 }
+ Property { name: "second.value"; type: "real"; value: 0.75 }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.RoundButton"
+ icon: "images/roundbutton-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Round Button"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/roundbutton-icon.png"
+ version: "2.1"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A round button with text.")
+
+ Property { name: "text"; type: "string"; value: "+" }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Slider"
+ icon: "images/slider-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Slider"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/slider-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("An adjustable slider.")
+
+ Property { name: "value"; type: "real"; value: 0.5 }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.SpinBox"
+ icon: "images/spinbox-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Spin Box"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/spinbox-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A box with an adjustable number.")
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.ScrollView"
+ icon: "images/scrollview-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Scroll View"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/scrollview-icon.png"
+ version: "2.2"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A scrollable area.")
+
+ Property { name: "width"; type: "int"; value: 200 }
+ Property { name: "height"; type: "int"; value: 200 }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.StackView"
+ icon: "images/stackview-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Stack View"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/stackview-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("Provides a stack-based navigation for a set of pages.")
+
+ Property { name: "width"; type: "int"; value: 200 }
+ Property { name: "height"; type: "int"; value: 200 }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.SwipeDelegate"
+ icon: "images/itemdelegate-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Swipe Delegate"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/itemdelegate-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("Presents items from a model as items that you can swipe to expose more options.")
+
+ Property { name: "text"; type: "binding"; value: "qsTr(\"Swipe Delegate\")" }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.SwipeView"
+ icon: "images/swipeview-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Swipe View"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/swipeview-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("Provides a view where you can navigate pages by swiping.")
+
+ Property { name: "width"; type: "int"; value: 200 }
+ Property { name: "height"; type: "int"; value: 200 }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Switch"
+ icon: "images/switch-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Switch"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/switch-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A button that you can toggle on and off.")
+
+ Property { name: "text"; type: "binding"; value: "qsTr(\"Switch\")" }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.SwitchDelegate"
+ icon: "images/switch-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Switch Delegate"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/switch-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("Presents items from a model as toggle switches.")
+
+ Property { name: "text"; type: "binding"; value: "qsTr(\"Switch Delegate\")" }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.TabBar"
+ icon: "images/toolbar-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Tab Bar"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/toolbar-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A tab-based navigation model.")
+
+ Property { name: "width"; type: "int"; value: 240 }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.TabButton"
+ icon: "images/toolbutton-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Tab Button"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/toolbutton-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A button suitable for a tab bar.")
+
+ Property { name: "text"; type: "binding"; value: "qsTr(\"Tab Button\")" }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.TextArea"
+ icon: "images/textarea-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Text Area"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/textarea-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A multi-line text box.")
+
+ Property { name: "placeholderText"; type: "binding"; value: "qsTr(\"Text Area\")" }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.TextField"
+ icon: "images/textfield-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Text Field"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/textfield-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A single-line text box.")
+
+ Property { name: "placeholderText"; type: "binding"; value: "qsTr(\"Text Field\")" }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.ToolBar"
+ icon: "images/toolbar-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Tool Bar"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/toolbar-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A row that can hold actions and buttons.")
+
+ Property { name: "width"; type: "int"; value: 360 }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.ToolButton"
+ icon: "images/toolbutton-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Tool Button"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/toolbutton-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A button suitable for a tool bar.")
+
+ Property { name: "text"; type: "binding"; value: "qsTr(\"Tool Button\")" }
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.ToolSeparator"
+ icon: "images/toolseparator-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Tool Separator"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/toolseparator-icon.png"
+ version: "2.1"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A line to separate sections in a tool bar.")
+ }
+ }
+
+ Type {
+ name: "QtQuick.Controls.Tumbler"
+ icon: "images/tumbler-icon16.png"
+
+ ItemLibraryEntry {
+ name: "Tumbler"
+ category: "Qt Quick - Controls 2"
+ libraryIcon: "images/tumbler-icon.png"
+ version: "2.0"
+ requiredImport: "QtQuick.Controls"
+ toolTip: qsTr("A spinnable wheel of selectable items.")
+
+ Property { name: "model"; type: "int"; value: "10" }
+ }
+ }
+}
diff --git a/tests/unit/tests/unittests/projectstorage/data/qml/QtQuick3D/AssetUtils/designer/assetutils.metainfo b/tests/unit/tests/unittests/projectstorage/data/qml/QtQuick3D/AssetUtils/designer/assetutils.metainfo
new file mode 100644
index 0000000000..47abeea7a3
--- /dev/null
+++ b/tests/unit/tests/unittests/projectstorage/data/qml/QtQuick3D/AssetUtils/designer/assetutils.metainfo
@@ -0,0 +1,21 @@
+MetaInfo {
+ Type {
+ name: "QtQuick3D.AssetUtils.RuntimeLoader"
+ icon: "images/runtimeloader16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Runtime Loader"
+ category: "AssetUtils"
+ libraryIcon: "images/runtimeloader.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.AssetUtils"
+ }
+ }
+}
diff --git a/tests/unit/tests/unittests/projectstorage/data/qml/QtQuick3D/Effects/designer/effectlib.metainfo b/tests/unit/tests/unittests/projectstorage/data/qml/QtQuick3D/Effects/designer/effectlib.metainfo
new file mode 100644
index 0000000000..7ad3357894
--- /dev/null
+++ b/tests/unit/tests/unittests/projectstorage/data/qml/QtQuick3D/Effects/designer/effectlib.metainfo
@@ -0,0 +1,401 @@
+MetaInfo {
+ Type {
+ name: "QtQuick3D.Effects.AdditiveColorGradient"
+ icon: "images/effect16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "Additive Color Gradient"
+ category: "Qt Quick 3D Effects"
+ libraryIcon: "images/effect.png"
+ version: "1.0"
+ requiredImport: "QtQuick3D.Effects"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Effects.Blur"
+ icon: "images/effect16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "Blur"
+ category: "Qt Quick 3D Effects"
+ libraryIcon: "images/effect.png"
+ version: "1.0"
+ requiredImport: "QtQuick3D.Effects"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Effects.BrushStrokes"
+ icon: "images/effect16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "Brush Strokes"
+ category: "Qt Quick 3D Effects"
+ libraryIcon: "images/effect.png"
+ version: "1.0"
+ requiredImport: "QtQuick3D.Effects"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Effects.ChromaticAberration"
+ icon: "images/effect16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "Chromatic Aberration"
+ category: "Qt Quick 3D Effects"
+ libraryIcon: "images/effect.png"
+ version: "1.0"
+ requiredImport: "QtQuick3D.Effects"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Effects.ColorMaster"
+ icon: "images/effect16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "Color Master"
+ category: "Qt Quick 3D Effects"
+ libraryIcon: "images/effect.png"
+ version: "1.0"
+ requiredImport: "QtQuick3D.Effects"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Effects.DepthOfFieldHQBlur"
+ icon: "images/effect16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "Depth of Field HQ Blur"
+ category: "Qt Quick 3D Effects"
+ libraryIcon: "images/effect.png"
+ version: "1.0"
+ requiredImport: "QtQuick3D.Effects"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Effects.Desaturate"
+ icon: "images/effect16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "Desaturate"
+ category: "Qt Quick 3D Effects"
+ libraryIcon: "images/effect.png"
+ version: "1.0"
+ requiredImport: "QtQuick3D.Effects"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Effects.DistortionRipple"
+ icon: "images/effect16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "Distortion Ripple"
+ category: "Qt Quick 3D Effects"
+ libraryIcon: "images/effect.png"
+ version: "1.0"
+ requiredImport: "QtQuick3D.Effects"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Effects.DistortionSphere"
+ icon: "images/effect16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "Distortion Sphere"
+ category: "Qt Quick 3D Effects"
+ libraryIcon: "images/effect.png"
+ version: "1.0"
+ requiredImport: "QtQuick3D.Effects"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Effects.DistortionSpiral"
+ icon: "images/effect16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "Distortion Spiral"
+ category: "Qt Quick 3D Effects"
+ libraryIcon: "images/effect.png"
+ version: "1.0"
+ requiredImport: "QtQuick3D.Effects"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Effects.EdgeDetect"
+ icon: "images/effect16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "Edge Detect"
+ category: "Qt Quick 3D Effects"
+ libraryIcon: "images/effect.png"
+ version: "1.0"
+ requiredImport: "QtQuick3D.Effects"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Effects.Emboss"
+ icon: "images/effect16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "Emboss"
+ category: "Qt Quick 3D Effects"
+ libraryIcon: "images/effect.png"
+ version: "1.0"
+ requiredImport: "QtQuick3D.Effects"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Effects.Flip"
+ icon: "images/effect16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "Flip"
+ category: "Qt Quick 3D Effects"
+ libraryIcon: "images/effect.png"
+ version: "1.0"
+ requiredImport: "QtQuick3D.Effects"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Effects.Fxaa"
+ icon: "images/effect16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "Fxaa"
+ category: "Qt Quick 3D Effects"
+ libraryIcon: "images/effect.png"
+ version: "1.0"
+ requiredImport: "QtQuick3D.Effects"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Effects.GaussianBlur"
+ icon: "images/effect16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "Gaussian Blur"
+ category: "Qt Quick 3D Effects"
+ libraryIcon: "images/effect.png"
+ version: "1.0"
+ requiredImport: "QtQuick3D.Effects"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Effects.HDRBloomTonemap"
+ icon: "images/effect16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "HDR Bloom Tonemap"
+ category: "Qt Quick 3D Effects"
+ libraryIcon: "images/effect.png"
+ version: "1.0"
+ requiredImport: "QtQuick3D.Effects"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Effects.MotionBlur"
+ icon: "images/effect16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "Motion Blur"
+ category: "Qt Quick 3D Effects"
+ libraryIcon: "images/effect.png"
+ version: "1.0"
+ requiredImport: "QtQuick3D.Effects"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Effects.Scatter"
+ icon: "images/effect16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "Scatter"
+ category: "Qt Quick 3D Effects"
+ libraryIcon: "images/effect.png"
+ version: "1.0"
+ requiredImport: "QtQuick3D.Effects"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Effects.SCurveTonemap"
+ icon: "images/effect16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "SCurve Tonemap"
+ category: "Qt Quick 3D Effects"
+ libraryIcon: "images/effect.png"
+ version: "1.0"
+ requiredImport: "QtQuick3D.Effects"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Effects.TiltShift"
+ icon: "images/effect16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "Tilt Shift"
+ category: "Qt Quick 3D Effects"
+ libraryIcon: "images/effect.png"
+ version: "1.0"
+ requiredImport: "QtQuick3D.Effects"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Effects.Vignette"
+ icon: "images/effect16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "Vignette"
+ category: "Qt Quick 3D Effects"
+ libraryIcon: "images/effect.png"
+ version: "1.0"
+ requiredImport: "QtQuick3D.Effects"
+ }
+ }
+}
diff --git a/tests/unit/tests/unittests/projectstorage/data/qml/QtQuick3D/Helpers/designer/helpers.metainfo b/tests/unit/tests/unittests/projectstorage/data/qml/QtQuick3D/Helpers/designer/helpers.metainfo
new file mode 100644
index 0000000000..83492e2c81
--- /dev/null
+++ b/tests/unit/tests/unittests/projectstorage/data/qml/QtQuick3D/Helpers/designer/helpers.metainfo
@@ -0,0 +1,261 @@
+MetaInfo {
+ Type {
+ name: "QtQuick3D.Helpers.LookAtNode"
+ icon: "images/lookatnode16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Look-at Node"
+ category: "Helpers"
+ libraryIcon: "images/lookatnode.png"
+ version: "6.4"
+ requiredImport: "QtQuick3D.Helpers"
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.Helpers.AxisHelper"
+ icon: "images/axishelper16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Axis Helper"
+ category: "Helpers"
+ libraryIcon: "images/axishelper.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D.Helpers"
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.Helpers.DebugView"
+ icon: "images/debugview16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: true
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "Debug View"
+ category: "Helpers"
+ libraryIcon: "images/debugview.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D.Helpers"
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.Helpers.GridGeometry"
+ icon: "images/gridgeometry16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Grid Geometry"
+ category: "Helpers"
+ libraryIcon: "images/gridgeometry.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D.Helpers"
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.Helpers.HeightFieldGeometry"
+ icon: "images/heightfieldgeometry16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Height Field Geometry"
+ category: "Helpers"
+ libraryIcon: "images/heightfieldgeometry.png"
+ version: "6.4"
+ requiredImport: "QtQuick3D.Helpers"
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.Helpers.InstanceModel"
+ icon: "images/instancemodel16.png"
+
+ Hints {
+ visibleInNavigator: false
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "Instance Model"
+ category: "Helpers"
+ libraryIcon: "images/instancemodel.png"
+ version: "6.4"
+ requiredImport: "QtQuick3D.Helpers"
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.Helpers.InstanceRepeater"
+ icon: "images/instancerepeater16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Instance Repeater"
+ category: "Helpers"
+ libraryIcon: "images/instancerepeater.png"
+ version: "6.4"
+ requiredImport: "QtQuick3D.Helpers"
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.Helpers.WasdController"
+ icon: "images/wasdcontroller16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: true
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "Wasd Controller"
+ category: "Helpers"
+ libraryIcon: "images/wasdcontroller.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D.Helpers"
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.Helpers.InfiniteGrid"
+ icon: "images/infinitegrid16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "Infinite Grid"
+ category: "Helpers"
+ libraryIcon: "images/infinitegrid.png"
+ version: "6.5"
+ requiredImport: "QtQuick3D.Helpers"
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.Helpers.OrbitCameraController"
+ icon: "images/orbitcameracontroller16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: true
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "Orbit Camera Controller"
+ category: "Helpers"
+ libraryIcon: "images/orbitcameracontroller.png"
+ version: "6.4"
+ requiredImport: "QtQuick3D.Helpers"
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.Helpers.ProceduralSkyTextureData"
+ icon: "images/proceduralskytexturedata16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "Procedural Sky Texture Data"
+ category: "Helpers"
+ libraryIcon: "images/proceduralskytexturedata.png"
+ version: "6.4"
+ requiredImport: "QtQuick3D.Helpers"
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.Helpers.ExtendedSceneEnvironment"
+ icon: "images/extendedsceneenvironment16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "Extended Scene Environment"
+ category: "Helpers"
+ libraryIcon: "images/extendedsceneenvironment.png"
+ version: "6.5"
+ requiredImport: "QtQuick3D.Helpers"
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.Helpers.LodManager"
+ icon: "images/lodmanager16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Lod Manager"
+ category: "Helpers"
+ libraryIcon: "images/lodmanager.png"
+ version: "6.5"
+ requiredImport: "QtQuick3D.Helpers"
+ }
+ }
+}
diff --git a/tests/unit/tests/unittests/projectstorage/data/qml/QtQuick3D/ParticleEffects/designer/particleeffects.metainfo b/tests/unit/tests/unittests/projectstorage/data/qml/QtQuick3D/ParticleEffects/designer/particleeffects.metainfo
new file mode 100644
index 0000000000..d9bc305b4a
--- /dev/null
+++ b/tests/unit/tests/unittests/projectstorage/data/qml/QtQuick3D/ParticleEffects/designer/particleeffects.metainfo
@@ -0,0 +1,246 @@
+MetaInfo {
+ Type {
+ name: "QtQuick3D.Particle3D.ParticleSystem3D"
+ icon: "images/dummy16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Clouds"
+ category: "Qt Quick 3D Particle Effects"
+ libraryIcon: "images/dummy.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.ParticleEffects"
+ QmlSource { source: "./source/particleeffect_clouds.qml" }
+ ExtraFile { source: "images/smoke_sprite2.png" }
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.Particle3D.ParticleSystem3D"
+ icon: "images/dummy16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Dust"
+ category: "Qt Quick 3D Particle Effects"
+ libraryIcon: "images/dummy.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.ParticleEffects"
+ QmlSource { source: "./source/particleeffect_dust.qml" }
+ ExtraFile { source: "images/sphere.png" }
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.Particle3D.ParticleSystem3D"
+ icon: "images/dummy16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Exhaust"
+ category: "Qt Quick 3D Particle Effects"
+ libraryIcon: "images/dummy.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.ParticleEffects"
+ QmlSource { source: "./source/particleeffect_exhaust.qml" }
+ ExtraFile { source: "images/smoke2.png" }
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.Particle3D.ParticleSystem3D"
+ icon: "images/dummy16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Fire"
+ category: "Qt Quick 3D Particle Effects"
+ libraryIcon: "images/dummy.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.ParticleEffects"
+ QmlSource { source: "./source/particleeffect_fire.qml" }
+ ExtraFile { source: "images/smoke_sprite.png" }
+ ExtraFile { source: "images/sphere.png" }
+ ExtraFile { source: "images/color_table.png" }
+ ExtraFile { source: "images/color_table2.png" }
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.Particle3D.ParticleSystem3D"
+ icon: "images/dummy16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Heavy Rain"
+ category: "Qt Quick 3D Particle Effects"
+ libraryIcon: "images/dummy.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.ParticleEffects"
+ QmlSource { source: "./source/particleeffect_heavyrain.qml" }
+ ExtraFile { source: "images/rain.png" }
+ ExtraFile { source: "images/sphere.png" }
+ ExtraFile { source: "images/ripple.png" }
+ ExtraFile { source: "images/splash7.png" }
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.Particle3D.ParticleSystem3D"
+ icon: "images/dummy16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Heavy Rain - Tire Spray"
+ category: "Qt Quick 3D Particle Effects"
+ libraryIcon: "images/dummy.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.ParticleEffects"
+ QmlSource { source: "./source/particleeffect_heavyrain_tirespray.qml" }
+ ExtraFile { source: "images/smoke2.png" }
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.Particle3D.ParticleSystem3D"
+ icon: "images/dummy16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Light Rain"
+ category: "Qt Quick 3D Particle Effects"
+ libraryIcon: "images/dummy.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.ParticleEffects"
+ QmlSource { source: "./source/particleeffect_lightrain.qml" }
+ ExtraFile { source: "images/rain.png" }
+ ExtraFile { source: "images/splash7.png" }
+ }
+ }
+ Type {
+ name: "QtQuick3D.Particle3D.ParticleSystem3D"
+ icon: "images/dummy16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Light Rain - Tire Spray"
+ category: "Qt Quick 3D Particle Effects"
+ libraryIcon: "images/dummy.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.ParticleEffects"
+ QmlSource { source: "./source/particleeffect_lightrain_tirespray.qml" }
+ ExtraFile { source: "images/smoke2.png" }
+ }
+ }
+ Type {
+ name: "QtQuick3D.Particle3D.ParticleSystem3D"
+ icon: "images/dummy16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Rain Mist"
+ category: "Qt Quick 3D Particle Effects"
+ libraryIcon: "images/dummy.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.ParticleEffects"
+ QmlSource { source: "./source/particleeffect_rainmist.qml" }
+ ExtraFile { source: "images/smoke2.png" }
+ }
+ }
+ Type {
+ name: "QtQuick3D.Particle3D.ParticleSystem3D"
+ icon: "images/dummy16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Snow"
+ category: "Qt Quick 3D Particle Effects"
+ libraryIcon: "images/dummy.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.ParticleEffects"
+ QmlSource { source: "./source/particleeffect_snow.qml" }
+ ExtraFile { source: "images/snowflake.png" }
+ }
+ }
+ Type {
+ name: "QtQuick3D.Particle3D.ParticleSystem3D"
+ icon: "images/dummy16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Steam"
+ category: "Qt Quick 3D Particle Effects"
+ libraryIcon: "images/dummy.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.ParticleEffects"
+ QmlSource { source: "./source/particleeffect_steam.qml" }
+ ExtraFile { source: "images/smoke2.png" }
+ }
+ }
+}
diff --git a/tests/unit/tests/unittests/projectstorage/data/qml/QtQuick3D/Particles3D/designer/particles3d.metainfo b/tests/unit/tests/unittests/projectstorage/data/qml/QtQuick3D/Particles3D/designer/particles3d.metainfo
new file mode 100644
index 0000000000..d2a2999c50
--- /dev/null
+++ b/tests/unit/tests/unittests/projectstorage/data/qml/QtQuick3D/Particles3D/designer/particles3d.metainfo
@@ -0,0 +1,562 @@
+MetaInfo {
+ Type {
+ name: "QtQuick3D.Particles3D.Attractor3D"
+ icon: "images/attractor-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Attractor"
+ category: "Qt Quick 3D Particles 3D"
+ libraryIcon: "images/attractor-24px.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.Particles3D"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Particles3D.DynamicBurst3D"
+ icon: "images/emit-burst-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Dynamic Burst"
+ category: "Qt Quick 3D Particles 3D"
+ libraryIcon: "images/emit-burst-24px.png"
+ version: "6.3"
+ requiredImport: "QtQuick3D.Particles3D"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Particles3D.EmitBurst3D"
+ icon: "images/emit-burst-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Emit Burst"
+ category: "Qt Quick 3D Particles 3D"
+ libraryIcon: "images/emit-burst-24px.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.Particles3D"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Particles3D.ParticleEmitter3D"
+ icon: "images/emitter-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Emitter"
+ category: "Qt Quick 3D Particles 3D"
+ libraryIcon: "images/emitter-24px.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.Particles3D"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Particles3D.Gravity3D"
+ icon: "images/gravity-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Gravity"
+ category: "Qt Quick 3D Particles 3D"
+ libraryIcon: "images/gravity-24px.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.Particles3D"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Particles3D.ModelBlendParticle3D"
+ icon: "images/model-blend-particle-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Model Blend Particle"
+ category: "Qt Quick 3D Particles 3D"
+ libraryIcon: "images/model-blend-particle-24px.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.Particles3D"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Particles3D.ModelParticle3D"
+ icon: "images/model-particle-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Model Particle"
+ category: "Qt Quick 3D Particles 3D"
+ libraryIcon: "images/model-particle-24px.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.Particles3D"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Particles3D.ParticleCustomShape3D"
+ icon: "images/particle-custom-shape-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Custom Shape"
+ category: "Qt Quick 3D Particles 3D"
+ libraryIcon: "images/particle-custom-shape-24px.png"
+ version: "6.3"
+ requiredImport: "QtQuick3D.Particles3D"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Particles3D.ParticleModelShape3D"
+ icon: "images/model-shape-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Model Shape"
+ category: "Qt Quick 3D Particles 3D"
+ libraryIcon: "images/model-shape-24px.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.Particles3D"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Particles3D.PointRotator3D"
+ icon: "images/point-rotator-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Point Rotator"
+ category: "Qt Quick 3D Particles 3D"
+ libraryIcon: "images/point-rotator-24px.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.Particles3D"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Particles3D.ParticleShape3D"
+ icon: "images/particle-shape-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Particle Shape"
+ category: "Qt Quick 3D Particles 3D"
+ libraryIcon: "images/particle-shape-24px.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.Particles3D"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Particles3D.SpriteParticle3D"
+ icon: "images/sprite-particle-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Sprite Particle"
+ category: "Qt Quick 3D Particles 3D"
+ libraryIcon: "images/sprite-particle-24px.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.Particles3D"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Particles3D.SpriteSequence3D"
+ icon: "images/sprite-sequence-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Sprite Sequence"
+ category: "Qt Quick 3D Particles 3D"
+ libraryIcon: "images/sprite-sequence-24px.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.Particles3D"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Particles3D.ParticleSystem3D"
+ icon: "images/particle-system-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Particle System"
+ category: "Qt Quick 3D Particles 3D"
+ libraryIcon: "images/particle-system-24px.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.Particles3D"
+ QmlSource { source: "./source/particlesystem_template.qml" }
+ }
+ }
+ Type {
+ name: "QtQuick3D.Particles3D.TargetDirection3D"
+ icon: "images/target-direction-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Target Direction"
+ category: "Qt Quick 3D Particles 3D"
+ libraryIcon: "images/target-direction-24px.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.Particles3D"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Particles3D.TrailEmitter3D"
+ icon: "images/trail-emitter-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Trail Emitter"
+ category: "Qt Quick 3D Particles 3D"
+ libraryIcon: "images/trail-emitter-24px.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.Particles3D"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Particles3D.VectorDirection3D"
+ icon: "images/vector-direction-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Vector Direction"
+ category: "Qt Quick 3D Particles 3D"
+ libraryIcon: "images/vector-direction-24px.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.Particles3D"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Particles3D.Wander3D"
+ icon: "images/wander-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Wander"
+ category: "Qt Quick 3D Particles 3D"
+ libraryIcon: "images/wander-24px.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.Particles3D"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Particles3D.ParticleSystem3D"
+ icon: "images/particle-system-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Animated Sprite"
+ category: "Qt Quick 3D Particle System Templates"
+ libraryIcon: "images/particle-system-24px.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.Particles3D"
+ QmlSource { source: "./source/particlesystem_animatedsprite_template.qml" }
+ }
+ }
+ Type {
+ name: "QtQuick3D.Particles3D.ParticleSystem3D"
+ icon: "images/particle-system-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Attractor System"
+ category: "Qt Quick 3D Particle System Templates"
+ libraryIcon: "images/particle-system-24px.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.Particles3D"
+ QmlSource { source: "./source/particlesystem_attractor_template.qml" }
+ }
+ }
+ Type {
+ name: "QtQuick3D.Particles3D.ParticleSystem3D"
+ icon: "images/particle-system-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Burst"
+ category: "Qt Quick 3D Particle System Templates"
+ libraryIcon: "images/particle-system-24px.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.Particles3D"
+ QmlSource { source: "./source/particlesystem_burst_template.qml" }
+ }
+ }
+ Type {
+ name: "QtQuick3D.Particles3D.ParticleSystem3D"
+ icon: "images/particle-system-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Model Blend"
+ category: "Qt Quick 3D Particle System Templates"
+ libraryIcon: "images/particle-system-24px.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.Particles3D"
+ QmlSource { source: "./source/particlesystem_modelblend_template.qml" }
+ }
+ }
+ Type {
+ name: "QtQuick3D.Particles3D.ParticleSystem3D"
+ icon: "images/particle-system-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Model Shape"
+ category: "Qt Quick 3D Particle System Templates"
+ libraryIcon: "images/particle-system-24px.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.Particles3D"
+ QmlSource { source: "./source/particlesystem_modelshape_template.qml" }
+ }
+ }
+ Type {
+ name: "QtQuick3D.Particles3D.ParticleSystem3D"
+ icon: "images/particle-system-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Particle Trail"
+ category: "Qt Quick 3D Particle System Templates"
+ libraryIcon: "images/particle-system-24px.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.Particles3D"
+ QmlSource { source: "./source/particlesystem_particletrail_template.qml" }
+ }
+ }
+ Type {
+ name: "QtQuick3D.Particles3D.ParticleSystem3D"
+ icon: "images/particle-system-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Sprite"
+ category: "Qt Quick 3D Particle System Templates"
+ libraryIcon: "images/particle-system-24px.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.Particles3D"
+ QmlSource { source: "./source/particlesystem_sprite_template.qml" }
+ }
+ }
+ Type {
+ name: "QtQuick3D.Particles3D.ParticleSystem3D"
+ icon: "images/particle-system-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Wander"
+ category: "Qt Quick 3D Particle System Templates"
+ libraryIcon: "images/particle-system-24px.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D.Particles3D"
+ QmlSource { source: "./source/particlesystem_wander_template.qml" }
+ }
+ }
+ Type {
+ name: "QtQuick3D.Particles3D.LineParticle3D"
+ icon: "images/line-particle-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Line Particle"
+ category: "Qt Quick 3D Particles 3D"
+ libraryIcon: "images/line-particle-24px.png"
+ version: "6.4"
+ requiredImport: "QtQuick3D.Particles3D"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Particles3D.Repeller3D"
+ icon: "images/repeller-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Repeller"
+ category: "Qt Quick 3D Particles 3D"
+ libraryIcon: "images/repeller-24px.png"
+ version: "6.4"
+ requiredImport: "QtQuick3D.Particles3D"
+ }
+ }
+ Type {
+ name: "QtQuick3D.Particles3D.ScaleAffector3D"
+ icon: "images/scale-affector-16px.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Scale Affector"
+ category: "Qt Quick 3D Particles 3D"
+ libraryIcon: "images/scale-affector-24px.png"
+ version: "6.4"
+ requiredImport: "QtQuick3D.Particles3D"
+ }
+ }
+}
diff --git a/tests/unit/tests/unittests/projectstorage/data/qml/QtQuick3D/Physics/designer/physics.metainfo b/tests/unit/tests/unittests/projectstorage/data/qml/QtQuick3D/Physics/designer/physics.metainfo
new file mode 100644
index 0000000000..874e209dc5
--- /dev/null
+++ b/tests/unit/tests/unittests/projectstorage/data/qml/QtQuick3D/Physics/designer/physics.metainfo
@@ -0,0 +1,261 @@
+MetaInfo {
+ Type {
+ name: "QtQuick3D.Physics.PhysicsWorld"
+ icon: "images/physicsworld16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "Physics World"
+ category: "Components"
+ libraryIcon: "images/physicsworld.png"
+ version: "6.5"
+ requiredImport: "QtQuick3D.Physics"
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.Physics.TriggerBody"
+ icon: "images/triggerbody16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Trigger Body"
+ category: "Collision Bodies"
+ libraryIcon: "images/triggerbody.png"
+ version: "6.5"
+ requiredImport: "QtQuick3D.Physics"
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.Physics.StaticRigidBody"
+ icon: "images/staticrigidbody16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Static Rigid Body"
+ category: "Collision Bodies"
+ libraryIcon: "images/staticrigidbody.png"
+ version: "6.5"
+ requiredImport: "QtQuick3D.Physics"
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.Physics.DynamicRigidBody"
+ icon: "images/dynamicrigidbody16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Dynamic Rigid Body"
+ category: "Collision Bodies"
+ libraryIcon: "images/dynamicrigidbody.png"
+ version: "6.5"
+ requiredImport: "QtQuick3D.Physics"
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.Physics.PhysicsMaterial"
+ icon: "images/physicsmaterial16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "Physics Material"
+ category: "Components"
+ libraryIcon: "images/physicsmaterial.png"
+ version: "6.5"
+ requiredImport: "QtQuick3D.Physics"
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.Physics.BoxShape"
+ icon: "images/boxshape16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Box Shape"
+ category: "Collision Shapes"
+ libraryIcon: "images/boxshape.png"
+ version: "6.5"
+ requiredImport: "QtQuick3D.Physics"
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.Physics.CapsuleShape"
+ icon: "images/capsuleshape16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Capsule Shape"
+ category: "Collision Shapes"
+ libraryIcon: "images/capsuleshape.png"
+ version: "6.5"
+ requiredImport: "QtQuick3D.Physics"
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.Physics.ConvexMeshShape"
+ icon: "images/convexmeshshape16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Convex Mesh Shape"
+ category: "Collision Shapes"
+ libraryIcon: "images/convexmeshshape.png"
+ version: "6.5"
+ requiredImport: "QtQuick3D.Physics"
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.Physics.HeightFieldShape"
+ icon: "images/heightfieldshape16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Height Field Shape"
+ category: "Collision Shapes"
+ libraryIcon: "images/heightfieldshape.png"
+ version: "6.5"
+ requiredImport: "QtQuick3D.Physics"
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.Physics.PlaneShape"
+ icon: "images/planeshape16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Plane Shape"
+ category: "Collision Shapes"
+ libraryIcon: "images/planeshape.png"
+ version: "6.5"
+ requiredImport: "QtQuick3D.Physics"
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.Physics.SphereShape"
+ icon: "images/sphereshape16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Sphere Shape"
+ category: "Collision Shapes"
+ libraryIcon: "images/sphereshape.png"
+ version: "6.5"
+ requiredImport: "QtQuick3D.Physics"
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.Physics.TriangleMeshShape"
+ icon: "images/trianglemeshshape16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Triangle Mesh Shape"
+ category: "Collision Shapes"
+ libraryIcon: "images/trianglemeshshape.png"
+ version: "6.5"
+ requiredImport: "QtQuick3D.Physics"
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.Physics.CharacterController"
+ icon: "images/charactercontroller16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Character Controller"
+ category: "Collision Bodies"
+ libraryIcon: "images/charactercontroller.png"
+ version: "6.5"
+ requiredImport: "QtQuick3D.Physics"
+ }
+ }
+}
diff --git a/tests/unit/tests/unittests/projectstorage/data/qml/QtQuick3D/designer/quick3d.metainfo b/tests/unit/tests/unittests/projectstorage/data/qml/QtQuick3D/designer/quick3d.metainfo
new file mode 100644
index 0000000000..852f908129
--- /dev/null
+++ b/tests/unit/tests/unittests/projectstorage/data/qml/QtQuick3D/designer/quick3d.metainfo
@@ -0,0 +1,861 @@
+MetaInfo {
+ Type {
+ name: "QtQuick3D.PerspectiveCamera"
+ icon: "images/camera16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Perspective Camera"
+ category: "Cameras"
+ libraryIcon: "images/camera.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D"
+ Property { name: "z"; type: "int"; value: 500; }
+ toolTip: qsTr("A camera that uses perspective projection.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.OrthographicCamera"
+ icon: "images/camera16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Orthographic Camera"
+ category: "Cameras"
+ libraryIcon: "images/camera.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D"
+ Property { name: "z"; type: "int"; value: 500; }
+ toolTip: qsTr("A parallel projection Camera, in which an object's perceived scale is unaffected by its distance from the Camera.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.FrustumCamera"
+ icon: "images/camera16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Frustum Camera"
+ category: "Cameras"
+ libraryIcon: "images/camera.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D"
+ Property { name: "z"; type: "int"; value: 500; }
+ toolTip: qsTr("A perspective camera with a custom frustum.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.CustomCamera"
+ icon: "images/camera16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Custom Camera"
+ category: "Cameras"
+ libraryIcon: "images/camera.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D"
+ Property { name: "z"; type: "int"; value: 500; }
+ toolTip: qsTr("A camera with a custom projection matrix.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.CustomMaterial"
+ icon: "images/custommaterial16.png"
+
+ Hints {
+ visibleInNavigator: false
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ }
+
+ ItemLibraryEntry {
+ name: "Custom Material"
+ category: "Materials"
+ libraryIcon: "images/custommaterial.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D"
+ Property { name: "fragmentShader"; type: "QUrl"; value: "custom_material_default_shader.frag"; }
+ ExtraFile { source: "source/custom_material_default_shader.frag" }
+ toolTip: qsTr("A material with customizable vertex and fragment shaders.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.DefaultMaterial"
+ icon: "images/material16.png"
+
+ Hints {
+ visibleInNavigator: false
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ }
+
+ ItemLibraryEntry {
+ name: "Default Material"
+ category: "Materials"
+ libraryIcon: "images/material.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D"
+ Property { name: "diffuseColor"; type: "color"; value: "#4aee45"; }
+ toolTip: qsTr("A material with a specular/glossiness properties.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.PrincipledMaterial"
+ icon: "images/material16.png"
+
+ Hints {
+ visibleInNavigator: false
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ }
+
+ ItemLibraryEntry {
+ name: "Principled Material"
+ category: "Materials"
+ libraryIcon: "images/material.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D"
+ Property { name: "baseColor"; type: "color"; value: "#4aee45"; }
+ toolTip: qsTr("A material with a PBR metal/roughness properties.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.SpecularGlossyMaterial"
+ icon: "images/material16.png"
+
+ Hints {
+ visibleInNavigator: false
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ }
+
+ ItemLibraryEntry {
+ name: "Specular Glossy"
+ category: "Materials"
+ libraryIcon: "images/material.png"
+ version: "6.4"
+ requiredImport: "QtQuick3D"
+ Property { name: "albedoColor"; type: "color"; value: "#4aee45"; }
+ Property { name: "specularColor"; type: "color"; value: "#000000"; }
+ toolTip: qsTr("A material with a PBR specular/glossiness properties.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.Texture"
+ icon: "images/texture16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeContainer: false
+ }
+
+ ItemLibraryEntry {
+ name: "Texture"
+ category: "Textures"
+ libraryIcon: "images/texture.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D"
+ toolTip: qsTr("Defines a texture for 3D objects.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.CubeMapTexture"
+ icon: "images/cubemaptexture16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeContainer: false
+ }
+
+ ItemLibraryEntry {
+ name: "Cube Map Texture"
+ category: "Textures"
+ libraryIcon: "images/cubemaptexture.png"
+ version: "6.4"
+ requiredImport: "QtQuick3D"
+ toolTip: qsTr("Defines a cube map texture for 3D objects.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.DirectionalLight"
+ icon: "images/lightdirectional16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Directional Light"
+ category: "Lights"
+ libraryIcon: "images/lightdirectional.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D"
+ toolTip: qsTr("A light similar to sunlight. It emits light in one direction from an infinitely far away source.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.PointLight"
+ icon: "images/lightpoint16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Point Light"
+ category: "Lights"
+ libraryIcon: "images/lightpoint.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D"
+ toolTip: qsTr("A light similar to a light bulb. It emits light equally in all directions from a central source.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.SpotLight"
+ icon: "images/lightspot16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Spotlight"
+ category: "Lights"
+ libraryIcon: "images/lightspot.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D"
+ toolTip: qsTr("A spotlight emits light in one direction in a cone shape.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.Model"
+ icon: "images/model16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ visibleNonDefaultProperties: "materials"
+ }
+
+ ItemLibraryEntry {
+ name: "Model"
+ category: "Components"
+ libraryIcon: "images/group.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D"
+ toolTip: qsTr("Allows you to load 3D mesh data.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.Model"
+ icon: "images/model16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ visibleNonDefaultProperties: "materials"
+ }
+
+ ItemLibraryEntry {
+ name: "Cube"
+ category: "Primitives"
+ libraryIcon: "images/cube.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D"
+ Property { name: "source"; type: "QUrl"; value: "#Cube"; }
+ toolTip: qsTr("A cube model.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.Model"
+ icon: "images/model16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ visibleNonDefaultProperties: "materials"
+ }
+
+ ItemLibraryEntry {
+ name: "Sphere"
+ category: "Primitives"
+ libraryIcon: "images/sphere.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D"
+ Property { name: "source"; type: "QUrl"; value: "#Sphere"; }
+ toolTip: qsTr("A sphere model.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.Model"
+ icon: "images/model16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ visibleNonDefaultProperties: "materials"
+ }
+
+ ItemLibraryEntry {
+ name: "Cylinder"
+ category: "Primitives"
+ libraryIcon: "images/cylinder.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D"
+ Property { name: "source"; type: "QUrl"; value: "#Cylinder"; }
+ toolTip: qsTr("A cylinder model.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.Model"
+ icon: "images/model16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ visibleNonDefaultProperties: "materials"
+ }
+
+ ItemLibraryEntry {
+ name: "Plane"
+ category: "Primitives"
+ libraryIcon: "images/plane.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D"
+ Property { name: "source"; type: "QUrl"; value: "#Rectangle"; }
+ toolTip: qsTr("A plane model.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.Model"
+ icon: "images/model16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ visibleNonDefaultProperties: "materials"
+ }
+
+ ItemLibraryEntry {
+ name: "Cone"
+ category: "Primitives"
+ libraryIcon: "images/cone.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D"
+ Property { name: "source"; type: "QUrl"; value: "#Cone"; }
+ toolTip: qsTr("A cone model.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.Node"
+ icon: "images/group16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Group"
+ category: "Components"
+ libraryIcon: "images/group.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D"
+ toolTip: qsTr("A container to keep several QtQuick3D components or scenes together.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.SceneEnvironment"
+ icon: "images/scene16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ }
+
+ ItemLibraryEntry {
+ name: "Scene Environment"
+ category: "Components"
+ libraryIcon: "images/scene.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D"
+ toolTip: qsTr("Configures the render settings for a scene.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.View3D"
+ icon: "images/view3D16.png"
+
+ ItemLibraryEntry {
+ name: "View3D"
+ category: "Items"
+ libraryIcon: "images/view3D.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D"
+ QmlSource { source: "./source/view3D_template.qml" }
+ toolTip: qsTr("A 2D surface where a 3D scene can be rendered.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.Shader"
+ icon: "images/shaderutil16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ }
+
+ ItemLibraryEntry {
+ name: "Shader"
+ category: "Custom Shader Utils"
+ libraryIcon: "images/shaderutil.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D"
+ toolTip: qsTr("A container for keeping the vertex or fragment shader codes to be used by post-processing effect.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.TextureInput"
+ icon: "images/shaderutil16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ }
+
+ ItemLibraryEntry {
+ name: "Texture Input"
+ category: "Custom Shader Utils"
+ libraryIcon: "images/shaderutil.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D"
+ toolTip: qsTr("Specifies a texture that gets exposed to the shader.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.Pass"
+ icon: "images/shaderutil16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ }
+
+ ItemLibraryEntry {
+ name: "Pass"
+ category: "Custom Shader Utils"
+ libraryIcon: "images/shaderutil.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D"
+ toolTip: qsTr("Holds a set of actions combining a list of executable render commands, an output buffer, and a list of shaders to use for rendering effects.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.BufferInput"
+ icon: "images/shadercommand16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ }
+
+ ItemLibraryEntry {
+ name: "Buffer Input"
+ category: "Custom Shader Utils"
+ libraryIcon: "images/shadercommand.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D"
+ toolTip: qsTr("A command that gets added to the list of commands in the Pass of an Effect when executed.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.Buffer"
+ icon: "images/shaderutil16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ }
+
+ ItemLibraryEntry {
+ name: "Buffer"
+ category: "Custom Shader Utils"
+ libraryIcon: "images/shaderutil.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D"
+ toolTip: qsTr("Creates or references a color buffer to be used for a pass of an Effect.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.SetUniformValue"
+ icon: "images/shadercommand16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ }
+
+ ItemLibraryEntry {
+ name: "Set Uniform Value"
+ category: "Custom Shader Utils"
+ libraryIcon: "images/shadercommand.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D"
+ toolTip: qsTr("A value that would be set when a single pass actions takes place.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.Effect"
+ icon: "images/effect16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ }
+
+ ItemLibraryEntry {
+ name: "Effect"
+ category: "Components"
+ libraryIcon: "images/effect.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D"
+ QmlSource { source: "./source/effect_template.qml" }
+ ExtraFile { source: "./source/effect_default_shader.frag" }
+ toolTip: qsTr("A method to allow the user to implement their post-processing effects on entire View3D.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.Repeater3D"
+ icon: "images/repeater3d16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "3D Repeater"
+ category: "Components"
+ libraryIcon: "images/repeater3d.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D"
+ toolTip: qsTr("Dynamically creates several copies of the same 3D object.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.Loader3D"
+ icon: "images/loader3d16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Loader3D"
+ category: "Components"
+ libraryIcon: "images/loader3d.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D"
+ toolTip: qsTr("Allows you to load 3D components dynamically.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.Skeleton"
+ icon: "images/skeleton16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ }
+
+ ItemLibraryEntry {
+ name: "Skeleton"
+ category: "Components"
+ libraryIcon: "images/skeleton.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D"
+ toolTip: qsTr("Defines a skeletal animation hierarchy.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.MorphTarget"
+ icon: "images/morphtarget16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ }
+
+ ItemLibraryEntry {
+ name: "Morph Target"
+ category: "Components"
+ libraryIcon: "images/morphtarget.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D"
+ toolTip: qsTr("Defines the properties of a morph target.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.InstanceListEntry"
+ icon: "images/instancelistentry16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ }
+
+ ItemLibraryEntry {
+ name: "Instance List Entry"
+ category: "Components"
+ libraryIcon: "images/instancelistentry.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D"
+ toolTip: qsTr("One instance in an Instance List. The instance includes a set of property specifications.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.InstanceList"
+ icon: "images/instancelist16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ }
+
+ ItemLibraryEntry {
+ name: "Instance List"
+ category: "Components"
+ libraryIcon: "images/instancelist.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D"
+ toolTip: qsTr("Enables 3D model instancing, a lightweight 3D object replication method.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.FileInstancing"
+ icon: "images/fileinstancing16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ }
+
+ ItemLibraryEntry {
+ name: "File Instancing"
+ category: "Components"
+ libraryIcon: "images/fileinstancing.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D"
+ toolTip: qsTr("A method that allows reading instance tables from XML or Qt-specific binary files.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.Joint"
+ icon: "images/joint16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ }
+
+ ItemLibraryEntry {
+ name: "Joint"
+ category: "Components"
+ libraryIcon: "images/joint.png"
+ version: "6.0"
+ requiredImport: "QtQuick3D"
+ toolTip: qsTr("A transformable node that connects different parts in a skeletal animation.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.ReflectionProbe"
+ icon: "images/reflectionProbe16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: true
+ }
+
+ ItemLibraryEntry {
+ name: "Reflection Probe"
+ category: "Components"
+ libraryIcon: "images/reflectionProbe.png"
+ version: "6.3"
+ requiredImport: "QtQuick3D"
+ toolTip: qsTr("Reflects the current scene to the objects.")
+ }
+ }
+ Type {
+ name: "QtQuick3D.Fog"
+ icon: "images/fog16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "Fog"
+ category: "Components"
+ libraryIcon: "images/fog.png"
+ version: "6.5"
+ requiredImport: "QtQuick3D"
+ }
+ }
+ Type {
+ name: "QtQuick3D.DebugSettings"
+ icon: "images/debugsettings16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "Debug Settings"
+ category: "Components"
+ libraryIcon: "images/debugsettings.png"
+ version: "6.5"
+ requiredImport: "QtQuick3D"
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.Lightmapper"
+ icon: "images/lightmapper16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ // Split the name to avoid ellipsis in UI
+ name: "Light Mapper"
+ category: "Components"
+ libraryIcon: "images/lightmapper.png"
+ version: "6.5"
+ requiredImport: "QtQuick3D"
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.Skin"
+ icon: "images/skin16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "Skin"
+ category: "Components"
+ libraryIcon: "images/skin.png"
+ version: "6.5"
+ requiredImport: "QtQuick3D"
+ }
+ }
+
+ Type {
+ name: "QtQuick3D.ResourceLoader"
+ icon: "images/resourceLoader16.png"
+
+ Hints {
+ visibleInNavigator: true
+ canBeDroppedInNavigator: true
+ canBeDroppedInFormEditor: false
+ canBeDroppedInView3D: false
+ }
+
+ ItemLibraryEntry {
+ name: "Resource Loader"
+ category: "Components"
+ libraryIcon: "images/resourceLoader.png"
+ version: "6.2"
+ requiredImport: "QtQuick3D"
+ toolTip: qsTr("Pre-load resources for 3D scene. It makes sure that large resources are available before rendering a frame.")
+ }
+ }
+}
diff --git a/tests/unit/tests/unittests/projectstorage/projectstorage-test.cpp b/tests/unit/tests/unittests/projectstorage/projectstorage-test.cpp
index 4b3f0a1869..4034ae58f9 100644
--- a/tests/unit/tests/unittests/projectstorage/projectstorage-test.cpp
+++ b/tests/unit/tests/unittests/projectstorage/projectstorage-test.cpp
@@ -202,7 +202,7 @@ class HasNameMatcher
public:
using is_gtest_matcher = void;
- HasNameMatcher(const QmlDesigner::ProjectStorage<Sqlite::Database> &storage,
+ HasNameMatcher(const QmlDesigner::ProjectStorage &storage,
Utils::SmallStringView name)
: storage{storage}
, name{name}
@@ -231,7 +231,7 @@ public:
void DescribeNegationTo(std::ostream *os) const { *os << "is not '" << name << "'"; }
private:
- const QmlDesigner::ProjectStorage<Sqlite::Database> &storage;
+ const QmlDesigner::ProjectStorage &storage;
Utils::SmallStringView name;
};
@@ -253,17 +253,15 @@ MATCHER(StringsAreSorted, std::string(negation ? "isn't sorted" : "is sorted"))
});
}
-MATCHER_P3(IsInfoType,
- defaultPropertyId,
+MATCHER_P2(IsInfoType,
sourceId,
traits,
std::string(negation ? "isn't " : "is ")
- + PrintToString(Storage::Info::Type{defaultPropertyId, sourceId, traits}))
+ + PrintToString(Storage::Info::Type{sourceId, traits}))
{
const Storage::Info::Type &type = arg;
- return type.defaultPropertyId == defaultPropertyId && type.sourceId == sourceId
- && type.traits == traits;
+ return type.sourceId == sourceId && type.traits == traits;
}
class ProjectStorage : public testing::Test
@@ -273,7 +271,7 @@ protected:
{
static_database = std::make_unique<Sqlite::Database>(":memory:", Sqlite::JournalMode::Memory);
- static_projectStorage = std::make_unique<QmlDesigner::ProjectStorage<Sqlite::Database>>(
+ static_projectStorage = std::make_unique<QmlDesigner::ProjectStorage>(
*static_database, static_database->isInitialized());
}
@@ -998,10 +996,10 @@ protected:
package.updatedSourceIds = {sourceId1, sourceId2, sourceId3};
- package.propertyEditorQmlPaths.emplace_back(qtQuickModuleId, "QtObject", sourceId1, sourceIdPath);
- package.propertyEditorQmlPaths.emplace_back(qtQuickModuleId, "Item", sourceId2, sourceIdPath);
- package.propertyEditorQmlPaths.emplace_back(qtQuickModuleId, "Item3D", sourceId3, sourceIdPath);
- package.updatedPropertyEditorQmlPathSourceIds.emplace_back(sourceIdPath);
+ package.propertyEditorQmlPaths.emplace_back(qtQuickModuleId, "QtObject", sourceId1, sourceIdPath6);
+ package.propertyEditorQmlPaths.emplace_back(qtQuickModuleId, "Item", sourceId2, sourceIdPath6);
+ package.propertyEditorQmlPaths.emplace_back(qtQuickModuleId, "Item3D", sourceId3, sourceIdPath6);
+ package.updatedPropertyEditorQmlPathSourceIds.emplace_back(sourceIdPath6);
return package;
}
@@ -1015,6 +1013,7 @@ protected:
traits.visibleInLibrary = FlagIs::True;
annotations.emplace_back(sourceId4,
+ sourceIdPath6,
"Object",
qmlModuleId,
"/path/to/icon.png",
@@ -1036,6 +1035,32 @@ protected:
"properties":[["color", "color", "#blue"]]}])xy");
annotations.emplace_back(sourceId5,
+ sourceIdPath6,
+ "Item",
+ qtQuickModuleId,
+ "/path/to/quick.png",
+ traits,
+ R"xy({"canBeContainer": "true", "forceClip": "false"})xy",
+ R"xy([{"name":"Item",
+ "iconPath":"/path/icon3",
+ "category":"Advanced Items",
+ "import":"QtQuick",
+ "toolTip":"Item is an Object",
+ "properties":[["x", "double", 1], ["y", "double", 2]]}])xy");
+
+ return annotations;
+ }
+
+ auto createExtendedTypeAnnotations() const
+ {
+ auto annotations = createTypeAnnotions();
+ annotations.pop_back();
+ TypeTraits traits{TypeTraitsKind::Reference};
+ traits.canBeContainer = FlagIs::True;
+ traits.visibleInLibrary = FlagIs::True;
+
+ annotations.emplace_back(sourceId5,
+ sourceIdPath1,
"Item",
qtQuickModuleId,
"/path/to/quick.png",
@@ -1111,10 +1136,9 @@ protected:
protected:
inline static std::unique_ptr<Sqlite::Database> static_database;
Sqlite::Database &database = *static_database;
- //Sqlite::Database database{"/tmp/aaaaa.db", Sqlite::JournalMode::Wal};
- inline static std::unique_ptr<QmlDesigner::ProjectStorage<Sqlite::Database>> static_projectStorage;
- QmlDesigner::ProjectStorage<Sqlite::Database> &storage = *static_projectStorage;
- QmlDesigner::SourcePathCache<QmlDesigner::ProjectStorage<Sqlite::Database>> sourcePathCache{
+ inline static std::unique_ptr<QmlDesigner::ProjectStorage> static_projectStorage;
+ QmlDesigner::ProjectStorage &storage = *static_projectStorage;
+ QmlDesigner::SourcePathCache<QmlDesigner::ProjectStorage> sourcePathCache{
storage};
QmlDesigner::SourcePathView path1{"/path1/to"};
QmlDesigner::SourcePathView path2{"/path2/to"};
@@ -1122,14 +1146,16 @@ protected:
QmlDesigner::SourcePathView path4{"/path4/to"};
QmlDesigner::SourcePathView path5{"/path5/to"};
QmlDesigner::SourcePathView path6{"/path6/to"};
- QmlDesigner::SourcePathView pathPath{"/path6/."};
+ QmlDesigner::SourcePathView pathPath1{"/path1/."};
+ QmlDesigner::SourcePathView pathPath6{"/path6/."};
SourceId sourceId1{sourcePathCache.sourceId(path1)};
SourceId sourceId2{sourcePathCache.sourceId(path2)};
SourceId sourceId3{sourcePathCache.sourceId(path3)};
SourceId sourceId4{sourcePathCache.sourceId(path4)};
SourceId sourceId5{sourcePathCache.sourceId(path5)};
SourceId sourceId6{sourcePathCache.sourceId(path6)};
- SourceId sourceIdPath{sourcePathCache.sourceId(path6)};
+ SourceId sourceIdPath1{sourcePathCache.sourceId(pathPath1)};
+ SourceId sourceIdPath6{sourcePathCache.sourceId(pathPath6)};
SourceId qmlProjectSourceId{sourcePathCache.sourceId("/path1/qmldir")};
SourceId qtQuickProjectSourceId{sourcePathCache.sourceId("/path2/qmldir")};
ModuleId qmlModuleId{storage.moduleId("Qml")};
@@ -5076,7 +5102,7 @@ TEST_F(ProjectStorage, populate_module_cache)
{
auto id = storage.moduleId("Qml");
- QmlDesigner::ProjectStorage<Sqlite::Database> newStorage{database, database.isInitialized()};
+ QmlDesigner::ProjectStorage newStorage{database, database.isInitialized()};
ASSERT_THAT(newStorage.moduleName(id), Eq("Qml"));
}
@@ -6683,12 +6709,10 @@ TEST_F(ProjectStorage, get_type)
auto package{createSimpleSynchronizationPackage()};
storage.synchronize(package);
auto typeId = fetchTypeId(sourceId1, "QQuickItem");
- auto defaultPropertyName = storage.fetchTypeByTypeId(typeId).defaultPropertyName;
- auto defaultPropertyId = storage.propertyDeclarationId(typeId, defaultPropertyName);
auto type = storage.type(typeId);
- ASSERT_THAT(type, Optional(IsInfoType(defaultPropertyId, sourceId1, TypeTraitsKind::Reference)));
+ ASSERT_THAT(type, Optional(IsInfoType(sourceId1, TypeTraitsKind::Reference)));
}
TEST_F(ProjectStorage, dont_get_type_for_invalid_id)
@@ -6701,6 +6725,58 @@ TEST_F(ProjectStorage, dont_get_type_for_invalid_id)
ASSERT_THAT(type, Eq(std::nullopt));
}
+TEST_F(ProjectStorage, get_default_property_declarartion_id)
+{
+ auto package{createSimpleSynchronizationPackage()};
+ storage.synchronize(package);
+ auto typeId = fetchTypeId(sourceId1, "QQuickItem");
+ auto defaultPropertyName = storage.fetchTypeByTypeId(typeId).defaultPropertyName;
+ auto defaultPropertyId = storage.propertyDeclarationId(typeId, defaultPropertyName);
+
+ auto propertyId = storage.defaultPropertyDeclarationId(typeId);
+
+ ASSERT_THAT(propertyId, defaultPropertyId);
+}
+
+TEST_F(ProjectStorage, get_default_property_declarartion_id_in_base_type)
+{
+ auto package{createSynchronizationPackageWithAliases()};
+ storage.synchronize(package);
+ auto baseTypeId = fetchTypeId(sourceId1, "QQuickItem");
+ auto defaultPropertyName = storage.fetchTypeByTypeId(baseTypeId).defaultPropertyName;
+ auto defaultPropertyId = storage.propertyDeclarationId(baseTypeId, defaultPropertyName);
+ auto typeId = fetchTypeId(sourceId3, "QAliasItem");
+
+ auto propertyId = storage.defaultPropertyDeclarationId(typeId);
+
+ ASSERT_THAT(propertyId, defaultPropertyId);
+}
+
+TEST_F(ProjectStorage, do_not_get_default_property_declarartion_id_wrong_type_in_property_chain)
+{
+ auto package{createSynchronizationPackageWithAliases()};
+ package.types[1].defaultPropertyName = "objects";
+ storage.synchronize(package);
+ auto baseTypeId = fetchTypeId(sourceId1, "QQuickItem");
+ auto defaultPropertyName = storage.fetchTypeByTypeId(baseTypeId).defaultPropertyName;
+ auto defaultPropertyId = storage.propertyDeclarationId(baseTypeId, defaultPropertyName);
+ auto typeId = fetchTypeId(sourceId3, "QAliasItem");
+
+ auto propertyId = storage.defaultPropertyDeclarationId(typeId);
+
+ ASSERT_THAT(propertyId, defaultPropertyId);
+}
+
+TEST_F(ProjectStorage, get_invalid_default_property_declarartion_id_for_invalid_type)
+{
+ auto package{createSimpleSynchronizationPackage()};
+ storage.synchronize(package);
+
+ auto propertyId = storage.defaultPropertyDeclarationId(TypeId());
+
+ ASSERT_FALSE(propertyId);
+}
+
TEST_F(ProjectStorage, get_common_type)
{
auto package{createSimpleSynchronizationPackage()};
@@ -7228,7 +7304,7 @@ TEST_F(ProjectStorage, synchronize_property_editor_adds_path)
auto package{createPropertyEditorPathsSynchronizationPackage()};
package.propertyEditorQmlPaths.pop_back();
storage.synchronize(package);
- package.propertyEditorQmlPaths.emplace_back(qtQuickModuleId, "Item3D", sourceId3, sourceIdPath);
+ package.propertyEditorQmlPaths.emplace_back(qtQuickModuleId, "Item3D", sourceId3, sourceIdPath6);
storage.synchronize(package);
@@ -7240,7 +7316,7 @@ TEST_F(ProjectStorage, synchronize_property_editor_adds_path)
TEST_F(ProjectStorage, synchronize_property_editor_with_non_existing_type_name)
{
auto package{createPropertyEditorPathsSynchronizationPackage()};
- package.propertyEditorQmlPaths.emplace_back(qtQuickModuleId, "Item4D", sourceId4, sourceIdPath);
+ package.propertyEditorQmlPaths.emplace_back(qtQuickModuleId, "Item4D", sourceId4, sourceIdPath6);
storage.synchronize(package);
@@ -7260,6 +7336,21 @@ TEST_F(ProjectStorage, call_remove_type_ids_in_observer_after_synchronization)
storage.synchronize(package);
}
+TEST_F(ProjectStorage, do_not_synchronize_type_annotations_without_type)
+{
+ SynchronizationPackage package;
+ package.typeAnnotations = createTypeAnnotions();
+ package.updatedTypeAnnotationSourceIds = createUpdatedTypeAnnotionSourceIds(
+ package.typeAnnotations);
+ TypeTraits traits{TypeTraitsKind::Reference};
+ traits.canBeContainer = FlagIs::True;
+ traits.visibleInLibrary = FlagIs::True;
+
+ storage.synchronize(package);
+
+ ASSERT_THAT(storage.allItemLibraryEntries(), IsEmpty());
+}
+
TEST_F(ProjectStorage, synchronize_type_annotation_type_traits)
{
auto package{createSimpleSynchronizationPackage()};
@@ -7414,6 +7505,18 @@ TEST_F(ProjectStorage, synchronize_removes_type_hints)
TEST_F(ProjectStorage, return_empty_type_hints_if_no_type_hints_exists)
{
auto package{createSimpleSynchronizationPackage()};
+ package.typeAnnotations = createTypeAnnotions();
+ package.typeAnnotations[0].hintsJson.clear();
+ storage.synchronize(package);
+
+ auto typeHints = storage.typeHints(fetchTypeId(sourceId2, "QObject"));
+
+ ASSERT_THAT(typeHints, IsEmpty());
+}
+
+TEST_F(ProjectStorage, return_empty_type_hints_if_no_type_annotaion_exists)
+{
+ auto package{createSimpleSynchronizationPackage()};
storage.synchronize(package);
auto typeHints = storage.typeHints(fetchTypeId(sourceId2, "QObject"));
@@ -7486,7 +7589,7 @@ TEST_F(ProjectStorage, synchronize_removes_item_library_entries)
ASSERT_THAT(storage.allItemLibraryEntries(), IsEmpty());
}
-TEST_F(ProjectStorage, synchronize_udpates_item_library_entries)
+TEST_F(ProjectStorage, synchronize_updates_item_library_entries)
{
auto package{createSimpleSynchronizationPackage()};
package.typeAnnotations = createTypeAnnotions();
@@ -7512,6 +7615,59 @@ TEST_F(ProjectStorage, synchronize_udpates_item_library_entries)
IsEmpty())));
}
+TEST_F(ProjectStorage, synchronize_updates_item_library_entries_with_empty_entries)
+{
+ auto package{createSimpleSynchronizationPackage()};
+ package.typeAnnotations = createTypeAnnotions();
+ package.updatedTypeAnnotationSourceIds = createUpdatedTypeAnnotionSourceIds(
+ package.typeAnnotations);
+ storage.synchronize(package);
+ package.typeAnnotations[0].itemLibraryJson.clear();
+
+ storage.synchronize(package);
+
+ ASSERT_THAT(storage.itemLibraryEntries(fetchTypeId(sourceId2, "QObject")), IsEmpty());
+}
+
+TEST_F(ProjectStorage, synchronize_type_annotation_directory_source_id)
+{
+ auto package{createSimpleSynchronizationPackage()};
+ package.typeAnnotations = createTypeAnnotions();
+ package.updatedTypeAnnotationSourceIds = createUpdatedTypeAnnotionSourceIds(
+ package.typeAnnotations);
+
+ storage.synchronize(package);
+
+ ASSERT_THAT(storage.typeAnnotationSourceIds(sourceIdPath6),
+ UnorderedElementsAre(sourceId4, sourceId5));
+}
+
+TEST_F(ProjectStorage, get_type_annotation_source_ids)
+{
+ auto package{createSimpleSynchronizationPackage()};
+ package.typeAnnotations = createTypeAnnotions();
+ package.updatedTypeAnnotationSourceIds = createUpdatedTypeAnnotionSourceIds(
+ package.typeAnnotations);
+ storage.synchronize(package);
+
+ auto sourceIds = storage.typeAnnotationSourceIds(sourceIdPath6);
+
+ ASSERT_THAT(sourceIds, UnorderedElementsAre(sourceId4, sourceId5));
+}
+
+TEST_F(ProjectStorage, get_type_annotation_directory_source_ids)
+{
+ auto package{createSimpleSynchronizationPackage()};
+ package.typeAnnotations = createExtendedTypeAnnotations();
+ package.updatedTypeAnnotationSourceIds = createUpdatedTypeAnnotionSourceIds(
+ package.typeAnnotations);
+ storage.synchronize(package);
+
+ auto sourceIds = storage.typeAnnotationDirectorySourceIds();
+
+ ASSERT_THAT(sourceIds, ElementsAre(sourceIdPath1, sourceIdPath6));
+}
+
TEST_F(ProjectStorage, get_all_item_library_entries)
{
auto package{createSimpleSynchronizationPackage()};
@@ -7557,6 +7713,31 @@ TEST_F(ProjectStorage, get_all_item_library_entries)
IsEmpty())));
}
+TEST_F(ProjectStorage, get_all_item_library_entries_handles_no_entries)
+{
+ auto package{createSimpleSynchronizationPackage()};
+ package.typeAnnotations = createTypeAnnotions();
+ package.typeAnnotations[0].itemLibraryJson.clear();
+ package.updatedTypeAnnotationSourceIds = createUpdatedTypeAnnotionSourceIds(
+ package.typeAnnotations);
+ storage.synchronize(package);
+
+ auto entries = storage.allItemLibraryEntries();
+
+ ASSERT_THAT(entries,
+ UnorderedElementsAre(
+ IsItemLibraryEntry(fetchTypeId(sourceId1, "QQuickItem"),
+ "Item",
+ "/path/icon3",
+ "Advanced Items",
+ "QtQuick",
+ "Item is an Object",
+ "",
+ UnorderedElementsAre(IsItemLibraryProperty("x", "double", 1),
+ IsItemLibraryProperty("y", "double", 2)),
+ IsEmpty())));
+}
+
TEST_F(ProjectStorage, get_item_library_entries_by_type_id)
{
auto package{createSimpleSynchronizationPackage()};
@@ -7606,6 +7787,21 @@ TEST_F(ProjectStorage, get_no_item_library_entries_if_type_id_is_invalid)
ASSERT_THAT(entries, IsEmpty());
}
+TEST_F(ProjectStorage, get_no_item_library_entries_by_type_id_for_no_entries)
+{
+ auto package{createSimpleSynchronizationPackage()};
+ package.typeAnnotations = createTypeAnnotions();
+ package.typeAnnotations[0].itemLibraryJson.clear();
+ package.updatedTypeAnnotationSourceIds = createUpdatedTypeAnnotionSourceIds(
+ package.typeAnnotations);
+ storage.synchronize(package);
+ auto typeId = fetchTypeId(sourceId2, "QObject");
+
+ auto entries = storage.itemLibraryEntries(typeId);
+
+ ASSERT_THAT(entries, IsEmpty());
+}
+
TEST_F(ProjectStorage, get_item_library_entries_by_source_id)
{
auto package{createSimpleSynchronizationPackage()};
@@ -7641,6 +7837,20 @@ TEST_F(ProjectStorage, get_item_library_entries_by_source_id)
IsEmpty())));
}
+TEST_F(ProjectStorage, get_no_item_library_entries_by_source_id_for_no_entries)
+{
+ auto package{createSimpleSynchronizationPackage()};
+ package.typeAnnotations = createTypeAnnotions();
+ package.typeAnnotations[0].itemLibraryJson.clear();
+ package.updatedTypeAnnotationSourceIds = createUpdatedTypeAnnotionSourceIds(
+ package.typeAnnotations);
+ storage.synchronize(package);
+
+ auto entries = storage.itemLibraryEntries(sourceId2);
+
+ ASSERT_THAT(entries, IsEmpty());
+}
+
TEST_F(ProjectStorage, return_type_ids_for_module_id)
{
auto package{createBuiltinSynchronizationPackage()};
diff --git a/tests/unit/tests/unittests/projectstorage/projectstoragepathwatcher-test.cpp b/tests/unit/tests/unittests/projectstorage/projectstoragepathwatcher-test.cpp
index d6ed96d0cf..26d5af8af8 100644
--- a/tests/unit/tests/unittests/projectstorage/projectstoragepathwatcher-test.cpp
+++ b/tests/unit/tests/unittests/projectstorage/projectstoragepathwatcher-test.cpp
@@ -16,7 +16,7 @@
#include <utils/smallstring.h>
namespace {
-using SourcePathCache = QmlDesigner::SourcePathCache<QmlDesigner::ProjectStorage<Sqlite::Database>>;
+using SourcePathCache = QmlDesigner::SourcePathCache<QmlDesigner::ProjectStorage>;
using Watcher = QmlDesigner::ProjectStoragePathWatcher<NiceMock<MockQFileSytemWatcher>,
NiceMock<MockTimer>,
SourcePathCache>;
@@ -43,7 +43,7 @@ protected:
{
static_database = std::make_unique<Sqlite::Database>(":memory:", Sqlite::JournalMode::Memory);
- static_projectStorage = std::make_unique<QmlDesigner::ProjectStorage<Sqlite::Database>>(
+ static_projectStorage = std::make_unique<QmlDesigner::ProjectStorage>(
*static_database, static_database->isInitialized());
}
@@ -81,8 +81,8 @@ protected:
NiceMock<FileSystemMock> mockFileSystem;
inline static std::unique_ptr<Sqlite::Database> static_database;
Sqlite::Database &database = *static_database;
- inline static std::unique_ptr<QmlDesigner::ProjectStorage<Sqlite::Database>> static_projectStorage;
- QmlDesigner::ProjectStorage<Sqlite::Database> &storage = *static_projectStorage;
+ inline static std::unique_ptr<QmlDesigner::ProjectStorage> static_projectStorage;
+ QmlDesigner::ProjectStorage &storage = *static_projectStorage;
SourcePathCache pathCache{storage};
Watcher watcher{pathCache, mockFileSystem, &notifier};
NiceMock<MockQFileSytemWatcher> &mockQFileSytemWatcher = watcher.fileSystemWatcher();
diff --git a/tests/unit/tests/unittests/projectstorage/projectstorageupdater-test.cpp b/tests/unit/tests/unittests/projectstorage/projectstorageupdater-test.cpp
index d9578d2f1b..96909857b3 100644
--- a/tests/unit/tests/unittests/projectstorage/projectstorageupdater-test.cpp
+++ b/tests/unit/tests/unittests/projectstorage/projectstorageupdater-test.cpp
@@ -9,6 +9,8 @@
#include "../mocks/qmldocumentparsermock.h"
#include "../mocks/qmltypesparsermock.h"
+#include <projectstorage-matcher.h>
+
#include <projectstorage/filestatuscache.h>
#include <projectstorage/projectstorage.h>
#include <projectstorage/projectstorageupdater.h>
@@ -120,7 +122,8 @@ MATCHER(PackageIsEmpty, std::string(negation ? "isn't empty" : "is empty"))
&& package.moduleDependencies.empty() && package.updatedModuleDependencySourceIds.empty()
&& package.moduleExportedImports.empty() && package.updatedModuleIds.empty()
&& package.propertyEditorQmlPaths.empty()
- && package.updatedPropertyEditorQmlPathSourceIds.empty();
+ && package.updatedPropertyEditorQmlPathSourceIds.empty()
+ && package.typeAnnotations.empty() && package.updatedTypeAnnotationSourceIds.empty();
}
template<typename ModuleIdMatcher, typename TypeNameMatcher, typename SourceIdMatcher>
@@ -141,7 +144,7 @@ public:
{
static_database = std::make_unique<Sqlite::Database>(":memory:", Sqlite::JournalMode::Memory);
- static_projectStorage = std::make_unique<QmlDesigner::ProjectStorage<Sqlite::Database>>(
+ static_projectStorage = std::make_unique<QmlDesigner::ProjectStorage>(
*static_database, static_database->isInitialized());
}
@@ -168,7 +171,8 @@ public:
secondSourceId,
thirdSourceId,
qmltypes1SourceId,
- qmltypes2SourceId});
+ qmltypes2SourceId,
+ itemLibraryPathSourceId});
setFilesAdded({qmldir1SourceId, qmldir2SourceId, qmldir3SourceId});
@@ -298,6 +302,8 @@ public:
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(path))).WillRepeatedly(Return(content));
}
+ auto moduleId(Utils::SmallStringView name) const { return storage.moduleId(name); }
+
protected:
NiceMock<FileSystemMock> fileSystemMock;
NiceMock<ProjectStorageMock> projectStorageMock;
@@ -306,9 +312,9 @@ protected:
QmlDesigner::FileStatusCache fileStatusCache{fileSystemMock};
inline static std::unique_ptr<Sqlite::Database> static_database;
Sqlite::Database &database = *static_database;
- inline static std::unique_ptr<QmlDesigner::ProjectStorage<Sqlite::Database>> static_projectStorage;
- QmlDesigner::ProjectStorage<Sqlite::Database> &storage = *static_projectStorage;
- QmlDesigner::SourcePathCache<QmlDesigner::ProjectStorage<Sqlite::Database>> sourcePathCache{
+ inline static std::unique_ptr<QmlDesigner::ProjectStorage> static_projectStorage;
+ QmlDesigner::ProjectStorage &storage = *static_projectStorage;
+ QmlDesigner::SourcePathCache<QmlDesigner::ProjectStorage> sourcePathCache{
storage};
NiceMock<ProjectStoragePathWatcherMock> patchWatcherMock;
QmlDesigner::ProjectPartId projectPartId = QmlDesigner::ProjectPartId::create(1);
@@ -328,6 +334,13 @@ protected:
SourceId qmlDocumentSourceId1 = sourcePathCache.sourceId("/path/First.qml");
SourceId qmlDocumentSourceId2 = sourcePathCache.sourceId("/path/First2.qml");
SourceId qmlDocumentSourceId3 = sourcePathCache.sourceId("/path/Second.qml");
+ const QString itemLibraryPath = QDir::cleanPath(
+ UNITTEST_DIR "/../../../../share/qtcreator/qmldesigner/itemLibrary/");
+ const QString qmlImportsPath = QDir::cleanPath(UNITTEST_DIR "/projectstorage/data/qml");
+ SourceId itemLibraryPathSourceId = sourcePathCache.sourceId(
+ QmlDesigner::SourcePath{itemLibraryPath + "/."});
+ SourceId qmlImportsPathSourceId = sourcePathCache.sourceId(
+ QmlDesigner::SourcePath{qmlImportsPath + "/."});
ModuleId qmlModuleId{storage.moduleId("Qml")};
ModuleId qmlCppNativeModuleId{storage.moduleId("Qml-cppnative")};
ModuleId exampleModuleId{storage.moduleId("Example")};
@@ -410,7 +423,7 @@ TEST_F(ProjectStorageUpdater, get_content_for_qml_dir_paths_if_file_status_is_di
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/one/qmldir"))));
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/two/qmldir"))));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, request_file_status_from_file_system)
@@ -419,7 +432,7 @@ TEST_F(ProjectStorageUpdater, request_file_status_from_file_system)
EXPECT_CALL(fileSystemMock, fileStatus(Eq(directoryPathSourceId)));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, get_content_for_qml_types)
@@ -431,7 +444,7 @@ TEST_F(ProjectStorageUpdater, get_content_for_qml_types)
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/example.qmltypes"))));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, get_content_for_qml_types_if_project_storage_file_status_is_invalid)
@@ -444,7 +457,7 @@ TEST_F(ProjectStorageUpdater, get_content_for_qml_types_if_project_storage_file_
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/example.qmltypes"))));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, parse_qml_types)
@@ -463,7 +476,7 @@ TEST_F(ProjectStorageUpdater, parse_qml_types)
EXPECT_CALL(qmlTypesParserMock,
parse(qmltypes2, _, _, Field(&ProjectData::moduleId, exampleCppNativeModuleId)));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, synchronize_is_empty_for_no_change)
@@ -472,7 +485,7 @@ TEST_F(ProjectStorageUpdater, synchronize_is_empty_for_no_change)
EXPECT_CALL(projectStorageMock, synchronize(PackageIsEmpty()));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, synchronize_qml_types)
@@ -507,7 +520,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_types)
Field(&SynchronizationPackage::updatedProjectSourceIds,
UnorderedElementsAre(directoryPathSourceId)))));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, synchronize_qml_types_throws_if_qmltpes_does_not_exists)
@@ -515,7 +528,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_types_throws_if_qmltpes_does_not_e
Storage::Import import{qmlModuleId, Storage::Version{2, 3}, qmltypesPathSourceId};
setFilesDontExists({qmltypesPathSourceId});
- ASSERT_THROW(updater.update(directories, {}, {}), QmlDesigner::CannotParseQmlTypesFile);
+ ASSERT_THROW(updater.update(directories, {}, {}, {}), QmlDesigner::CannotParseQmlTypesFile);
}
TEST_F(ProjectStorageUpdater, synchronize_qml_types_are_empty_if_file_does_not_changed)
@@ -528,7 +541,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_types_are_empty_if_file_does_not_c
EXPECT_CALL(projectStorageMock, synchronize(PackageIsEmpty()));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, get_content_for_qml_documents)
@@ -549,7 +562,7 @@ TEST_F(ProjectStorageUpdater, get_content_for_qml_documents)
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/OldSecond.qml"))));
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/Second.qml"))));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, parse_qml_documents)
@@ -570,7 +583,7 @@ TEST_F(ProjectStorageUpdater, parse_qml_documents)
EXPECT_CALL(qmlDocumentParserMock, parse(qmlDocument2, _, _, _));
EXPECT_CALL(qmlDocumentParserMock, parse(qmlDocument3, _, _, _));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, parse_qml_documents_with_non_existing_qml_document_throws)
@@ -579,7 +592,7 @@ TEST_F(ProjectStorageUpdater, parse_qml_documents_with_non_existing_qml_document
NonexitingType 1.0 NonexitingType.qml)"};
setContent(u"/path/qmldir", qmldir);
- ASSERT_THROW(updater.update(directories, {}, {}), QmlDesigner::CannotParseQmlDocumentFile);
+ ASSERT_THROW(updater.update(directories, {}, {}, {}), QmlDesigner::CannotParseQmlDocumentFile);
}
TEST_F(ProjectStorageUpdater, synchronize_qml_documents)
@@ -652,7 +665,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents)
ModuleId{},
FileType::QmlDocument))))));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, synchronize_add_only_qml_document_in_directory)
@@ -708,7 +721,7 @@ TEST_F(ProjectStorageUpdater, synchronize_add_only_qml_document_in_directory)
ModuleId{},
FileType::QmlDocument))))));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, synchronize_removes_qml_document)
@@ -771,7 +784,7 @@ TEST_F(ProjectStorageUpdater, synchronize_removes_qml_document)
ModuleId{},
FileType::QmlDocument))))));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, synchronize_removes_qml_document_in_qmldir_only)
@@ -826,7 +839,7 @@ TEST_F(ProjectStorageUpdater, synchronize_removes_qml_document_in_qmldir_only)
ModuleId{},
FileType::QmlDocument))))));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, synchronize_add_qml_document_to_qmldir)
@@ -884,7 +897,7 @@ TEST_F(ProjectStorageUpdater, synchronize_add_qml_document_to_qmldir)
ModuleId{},
FileType::QmlDocument))))));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, synchronize_remove_qml_document_from_qmldir)
@@ -939,7 +952,7 @@ TEST_F(ProjectStorageUpdater, synchronize_remove_qml_document_from_qmldir)
ModuleId{},
FileType::QmlDocument))))));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, synchronize_qml_documents_dont_update_if_up_to_date)
@@ -1009,7 +1022,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents_dont_update_if_up_to_dat
ModuleId{},
FileType::QmlDocument))))));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, synchroniz_if_qmldir_file_has_not_changed)
@@ -1060,7 +1073,7 @@ TEST_F(ProjectStorageUpdater, synchroniz_if_qmldir_file_has_not_changed)
qmlDocumentSourceId2)),
Field(&SynchronizationPackage::projectDatas, IsEmpty()))));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, synchroniz_if_qmldir_file_has_not_changed_and_some_updated_files)
@@ -1095,7 +1108,7 @@ TEST_F(ProjectStorageUpdater, synchroniz_if_qmldir_file_has_not_changed_and_some
UnorderedElementsAre(qmltypesPathSourceId, qmlDocumentSourceId1)),
Field(&SynchronizationPackage::projectDatas, IsEmpty()))));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, synchroniz_if_qmldir_file_not_changed_and_some_removed_files)
@@ -1110,7 +1123,7 @@ TEST_F(ProjectStorageUpdater, synchroniz_if_qmldir_file_not_changed_and_some_rem
setFilesDontChanged({qmlDirPathSourceId, qmltypes2PathSourceId, qmlDocumentSourceId2});
setFilesRemoved({qmltypesPathSourceId, qmlDocumentSourceId1});
- ASSERT_THROW(updater.update(directories, {}, {}), QmlDesigner::CannotParseQmlTypesFile);
+ ASSERT_THROW(updater.update(directories, {}, {}, {}), QmlDesigner::CannotParseQmlTypesFile);
}
TEST_F(ProjectStorageUpdater, synchroniz_if_qmldir_file_has_changed_and_some_removed_files)
@@ -1162,7 +1175,7 @@ TEST_F(ProjectStorageUpdater, synchroniz_if_qmldir_file_has_changed_and_some_rem
exampleCppNativeModuleId,
FileType::QmlTypes))))));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, update_qml_types_files_is_empty)
@@ -1177,7 +1190,7 @@ TEST_F(ProjectStorageUpdater, update_qml_types_files_is_empty)
Field(&SynchronizationPackage::projectDatas, IsEmpty()),
Field(&SynchronizationPackage::updatedProjectSourceIds, IsEmpty()))));
- updater.update({}, {}, {});
+ updater.update({}, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, update_qml_types_files)
@@ -1205,7 +1218,7 @@ TEST_F(ProjectStorageUpdater, update_qml_types_files)
Field(&SynchronizationPackage::updatedProjectSourceIds,
UnorderedElementsAre(qmltypesPathSourceId, qmltypes2PathSourceId)))));
- updater.update({}, {"/path/example.qmltypes", "/path/example2.qmltypes"}, {});
+ updater.update({}, {"/path/example.qmltypes", "/path/example2.qmltypes"}, {}, {});
}
TEST_F(ProjectStorageUpdater, dont_update_qml_types_files_if_unchanged)
@@ -1230,7 +1243,7 @@ TEST_F(ProjectStorageUpdater, dont_update_qml_types_files_if_unchanged)
Field(&SynchronizationPackage::updatedProjectSourceIds,
UnorderedElementsAre(qmltypesPathSourceId)))));
- updater.update({}, {"/path/example.qmltypes", "/path/example2.qmltypes"}, {});
+ updater.update({}, {"/path/example.qmltypes", "/path/example2.qmltypes"}, {}, {});
}
TEST_F(ProjectStorageUpdater, synchronize_qml_documents_with_different_version_but_same_type_name_and_file_name)
@@ -1273,7 +1286,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents_with_different_version_b
ModuleId{},
FileType::QmlDocument))))));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, synchronize_qml_documents_with_different_type_name_but_same_version_and_file_name)
@@ -1314,7 +1327,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents_with_different_type_name
ModuleId{},
FileType::QmlDocument))))));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, dont_synchronize_selectors)
@@ -1332,7 +1345,7 @@ TEST_F(ProjectStorageUpdater, dont_synchronize_selectors)
Contains(Field(&Storage::Synchronization::Type::exportedTypes,
Contains(IsExportedType(exampleModuleId, "FirstType", 1, 0))))))));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, synchronize_qmldir_dependencies)
@@ -1357,7 +1370,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qmldir_dependencies)
Field(&SynchronizationPackage::updatedModuleDependencySourceIds,
UnorderedElementsAre(qmltypesPathSourceId, qmltypes2PathSourceId)))));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, synchronize_qmldir_dependencies_with_double_entries)
@@ -1383,7 +1396,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qmldir_dependencies_with_double_entrie
Field(&SynchronizationPackage::updatedModuleDependencySourceIds,
UnorderedElementsAre(qmltypesPathSourceId, qmltypes2PathSourceId)))));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, synchronize_qmldir_dependencies_with_colliding_imports)
@@ -1409,7 +1422,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qmldir_dependencies_with_colliding_imp
Field(&SynchronizationPackage::updatedModuleDependencySourceIds,
UnorderedElementsAre(qmltypesPathSourceId, qmltypes2PathSourceId)))));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, synchronize_qmldir_with_no_dependencies)
@@ -1426,7 +1439,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qmldir_with_no_dependencies)
Field(&SynchronizationPackage::updatedModuleDependencySourceIds,
UnorderedElementsAre(qmltypesPathSourceId, qmltypes2PathSourceId)))));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, synchronize_qmldir_imports)
@@ -1468,7 +1481,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qmldir_imports)
Field(&SynchronizationPackage::updatedModuleIds,
ElementsAre(exampleModuleId)))));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, synchronize_qmldir_with_no_imports)
@@ -1482,7 +1495,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qmldir_with_no_imports)
Field(&SynchronizationPackage::updatedModuleIds,
ElementsAre(exampleModuleId)))));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, synchronize_qmldir_imports_with_double_entries)
@@ -1525,7 +1538,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qmldir_imports_with_double_entries)
Field(&SynchronizationPackage::updatedModuleIds,
ElementsAre(exampleModuleId)))));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, synchronize_qmldir_optional_imports)
@@ -1567,7 +1580,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qmldir_optional_imports)
Field(&SynchronizationPackage::updatedModuleIds,
ElementsAre(exampleModuleId)))));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, update_path_watcher_directories)
@@ -1577,7 +1590,7 @@ TEST_F(ProjectStorageUpdater, update_path_watcher_directories)
QmlDesigner::SourceType::Directory,
{path1SourceId, path2SourceId, path3SourceId}})));
- updater.update(directories3, {}, {});
+ updater.update(directories3, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, update_path_watcher_directory_does_not_exists)
@@ -1589,7 +1602,7 @@ TEST_F(ProjectStorageUpdater, update_path_watcher_directory_does_not_exists)
QmlDesigner::SourceType::Directory,
{path1SourceId, path3SourceId}})));
- updater.update(directories3, {}, {});
+ updater.update(directories3, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, update_path_watcher_directory_does_not_changed)
@@ -1601,7 +1614,7 @@ TEST_F(ProjectStorageUpdater, update_path_watcher_directory_does_not_changed)
QmlDesigner::SourceType::Directory,
{path1SourceId, path2SourceId}})));
- updater.update(directories2, {}, {});
+ updater.update(directories2, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, update_path_watcher_directory_removed)
@@ -1612,7 +1625,7 @@ TEST_F(ProjectStorageUpdater, update_path_watcher_directory_removed)
updateIdPaths(Contains(
IdPaths{projectPartId, QmlDesigner::SourceType::Directory, {path2SourceId}})));
- updater.update(directories2, {}, {});
+ updater.update(directories2, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, update_path_watcher_qmldirs)
@@ -1622,7 +1635,7 @@ TEST_F(ProjectStorageUpdater, update_path_watcher_qmldirs)
QmlDesigner::SourceType::QmlDir,
{qmldir1SourceId, qmldir2SourceId, qmldir3SourceId}})));
- updater.update(directories3, {}, {});
+ updater.update(directories3, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, update_path_watcher_qmldir_does_not_exists)
@@ -1634,7 +1647,7 @@ TEST_F(ProjectStorageUpdater, update_path_watcher_qmldir_does_not_exists)
QmlDesigner::SourceType::QmlDir,
{qmldir1SourceId, qmldir3SourceId}})));
- updater.update(directories3, {}, {});
+ updater.update(directories3, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, update_path_watcher_qmldir_does_not_changed)
@@ -1646,7 +1659,7 @@ TEST_F(ProjectStorageUpdater, update_path_watcher_qmldir_does_not_changed)
QmlDesigner::SourceType::QmlDir,
{qmldir1SourceId, qmldir2SourceId}})));
- updater.update(directories2, {}, {});
+ updater.update(directories2, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, update_path_watcher_qmldir_removed)
@@ -1657,7 +1670,7 @@ TEST_F(ProjectStorageUpdater, update_path_watcher_qmldir_removed)
updateIdPaths(Contains(
IdPaths{projectPartId, QmlDesigner::SourceType::QmlDir, {qmldir2SourceId}})));
- updater.update(directories2, {}, {});
+ updater.update(directories2, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, update_path_watcher_qml_files)
@@ -1674,7 +1687,7 @@ TEST_F(ProjectStorageUpdater, update_path_watcher_qml_files)
QmlDesigner::SourceType::Qml,
{firstSourceId, secondSourceId, thirdSourceId}})));
- updater.update(directories2, {}, {});
+ updater.update(directories2, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, update_path_watcher_only_qml_files_dont_changed)
@@ -1692,7 +1705,7 @@ TEST_F(ProjectStorageUpdater, update_path_watcher_only_qml_files_dont_changed)
QmlDesigner::SourceType::Qml,
{firstSourceId, secondSourceId, thirdSourceId}})));
- updater.update(directories2, {}, {});
+ updater.update(directories2, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, update_path_watcher_only_qml_files_changed)
@@ -1710,7 +1723,7 @@ TEST_F(ProjectStorageUpdater, update_path_watcher_only_qml_files_changed)
QmlDesigner::SourceType::Qml,
{firstSourceId, secondSourceId, thirdSourceId}})));
- updater.update(directories2, {}, {});
+ updater.update(directories2, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, update_path_watcher_qml_files_and_directories_dont_changed)
@@ -1733,7 +1746,7 @@ TEST_F(ProjectStorageUpdater, update_path_watcher_qml_files_and_directories_dont
QmlDesigner::SourceType::Qml,
{firstSourceId, secondSourceId, thirdSourceId}})));
- updater.update(directories2, {}, {});
+ updater.update(directories2, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, update_path_watcher_qmltypes_files_in_qmldir)
@@ -1752,7 +1765,7 @@ TEST_F(ProjectStorageUpdater, update_path_watcher_qmltypes_files_in_qmldir)
QmlDesigner::SourceType::QmlTypes,
{qmltypes1SourceId, qmltypes2SourceId}})));
- updater.update(directories2, {}, {});
+ updater.update(directories2, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, update_path_watcher_only_qmltypes_files_in_qmldir_dont_changed)
@@ -1770,7 +1783,7 @@ TEST_F(ProjectStorageUpdater, update_path_watcher_only_qmltypes_files_in_qmldir_
QmlDesigner::SourceType::QmlTypes,
{qmltypes1SourceId, qmltypes2SourceId}})));
- updater.update(directories2, {}, {});
+ updater.update(directories2, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, update_path_watcher_only_qmltypes_files_changed)
@@ -1787,7 +1800,7 @@ TEST_F(ProjectStorageUpdater, update_path_watcher_only_qmltypes_files_changed)
QmlDesigner::SourceType::QmlTypes,
{qmltypes1SourceId, qmltypes2SourceId}})));
- updater.update(directories2, {}, {});
+ updater.update(directories2, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, update_path_watcher_qmltypes_files_and_directories_dont_changed)
@@ -1808,7 +1821,7 @@ TEST_F(ProjectStorageUpdater, update_path_watcher_qmltypes_files_and_directories
QmlDesigner::SourceType::QmlTypes,
{qmltypes1SourceId, qmltypes2SourceId}})));
- updater.update(directories2, {}, {});
+ updater.update(directories2, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, update_path_watcher_builtin_qmltypes_files)
@@ -1823,7 +1836,7 @@ TEST_F(ProjectStorageUpdater, update_path_watcher_builtin_qmltypes_files)
QmlDesigner::SourceType::QmlTypes,
{qmltypes1SourceId, qmltypes2SourceId}})));
- updater.update({}, {builtinQmltyplesPath1, builtinQmltyplesPath2}, {});
+ updater.update({}, {builtinQmltyplesPath1, builtinQmltyplesPath2}, {}, {});
}
TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir)
@@ -1890,7 +1903,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir)
ModuleId{},
FileType::QmlDocument))))));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir_throws_if_qml_document_does_not_exists)
@@ -1898,7 +1911,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir_throws_if
setFilesDontExists({qmlDirPathSourceId, qmlDocumentSourceId1});
setFilesAdded({directoryPathSourceId});
- ASSERT_THROW(updater.update(directories, {}, {}), QmlDesigner::CannotParseQmlDocumentFile);
+ ASSERT_THROW(updater.update(directories, {}, {}, {}), QmlDesigner::CannotParseQmlDocumentFile);
}
TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir_throws_if_directory_does_not_exists)
@@ -1928,7 +1941,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir_throws_if
UnorderedElementsAre(directoryPathSourceId)),
Field(&SynchronizationPackage::projectDatas, IsEmpty()))));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir_add_qml_document)
@@ -1977,7 +1990,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir_add_qml_d
ModuleId{},
FileType::QmlDocument))))));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir_removes_qml_document)
@@ -2016,7 +2029,7 @@ TEST_F(ProjectStorageUpdater, synchronize_qml_documents_without_qmldir_removes_q
ModuleId{},
FileType::QmlDocument))))));
- updater.update(directories, {}, {});
+ updater.update(directories, {}, {}, {});
}
TEST_F(ProjectStorageUpdater, watcher_updates_directories)
@@ -3210,7 +3223,8 @@ TEST_F(ProjectStorageUpdater, errors_for_watcher_updates_are_handled)
SecondType 2.2 Second.qml)"};
setContent(u"/path/qmldir", qmldir);
- ON_CALL(projectStorageMock, synchronize(_)).WillByDefault(Throw(QmlDesigner::ProjectStorageError{}));
+ ON_CALL(projectStorageMock, synchronize(_))
+ .WillByDefault(Throw(QmlDesigner::NoSourcePathForInvalidSourceId{}));
ASSERT_NO_THROW(updater.pathsWithIdsChanged({{directoryProjectChunkId, {directoryPathSourceId}}}));
}
@@ -3227,7 +3241,8 @@ TEST_F(ProjectStorageUpdater, input_is_reused_next_call_if_an_error_happens)
{{directoryPathSourceId, qmltypesPathSourceId, exampleModuleId, FileType::QmlTypes},
{directoryPathSourceId, qmltypes2PathSourceId, exampleModuleId, FileType::QmlTypes}});
setFilesDontChanged({directoryPathSourceId, qmlDirPathSourceId});
- ON_CALL(projectStorageMock, synchronize(_)).WillByDefault(Throw(QmlDesigner::ProjectStorageError{}));
+ ON_CALL(projectStorageMock, synchronize(_))
+ .WillByDefault(Throw(QmlDesigner::NoSourcePathForInvalidSourceId{}));
updater.pathsWithIdsChanged(
{{qmltypesProjectChunkId, {qmltypesPathSourceId, qmltypes2PathSourceId}}});
ON_CALL(projectStorageMock, synchronize(_)).WillByDefault(Return());
@@ -3286,7 +3301,8 @@ TEST_F(ProjectStorageUpdater, input_is_reused_next_call_if_an_error_happens_and_
{{directoryPathSourceId, qmltypesPathSourceId, exampleModuleId, FileType::QmlTypes},
{directoryPathSourceId, qmltypes2PathSourceId, exampleModuleId, FileType::QmlTypes}});
setFilesDontChanged({directoryPathSourceId, qmlDirPathSourceId});
- ON_CALL(projectStorageMock, synchronize(_)).WillByDefault(Throw(QmlDesigner::ProjectStorageError{}));
+ ON_CALL(projectStorageMock, synchronize(_))
+ .WillByDefault(Throw(QmlDesigner::NoSourcePathForInvalidSourceId{}));
updater.pathsWithIdsChanged(
{{qmltypesProjectChunkId, {qmltypesPathSourceId, qmltypes2PathSourceId}}});
ON_CALL(projectStorageMock, synchronize(_)).WillByDefault(Return());
@@ -3348,7 +3364,8 @@ TEST_F(ProjectStorageUpdater, input_is_reused_next_call_if_an_error_happens_and_
{directoryPathSourceId, qmlDocumentSourceId1, QmlDesigner::ModuleId{}, FileType::QmlDocument},
{directoryPathSourceId, qmlDocumentSourceId1, QmlDesigner::ModuleId{}, FileType::QmlDocument}});
setFilesDontChanged({directoryPathSourceId, qmlDirPathSourceId});
- ON_CALL(projectStorageMock, synchronize(_)).WillByDefault(Throw(QmlDesigner::ProjectStorageError{}));
+ ON_CALL(projectStorageMock, synchronize(_))
+ .WillByDefault(Throw(QmlDesigner::NoSourcePathForInvalidSourceId{}));
updater.pathsWithIdsChanged(
{{qmlDocumentProjectChunkId, {qmlDocumentSourceId1, qmlDocumentSourceId2}}});
ON_CALL(projectStorageMock, synchronize(_)).WillByDefault(Return());
@@ -3471,7 +3488,7 @@ TEST_F(ProjectStorageUpdater, update_property_editor_panes)
Field(&SynchronizationPackage::updatedPropertyEditorQmlPathSourceIds,
ElementsAre(directoryId)))));
- updater.update({}, {}, propertyEditorQmlPath);
+ updater.update({}, {}, propertyEditorQmlPath, {});
}
TEST_F(ProjectStorageUpdater, update_property_editor_specifics)
@@ -3496,12 +3513,12 @@ TEST_F(ProjectStorageUpdater, update_property_editor_specifics)
Field(&SynchronizationPackage::updatedPropertyEditorQmlPathSourceIds,
ElementsAre(directoryId)))));
- updater.update({}, {}, propertyEditorQmlPath);
+ updater.update({}, {}, propertyEditorQmlPath, {});
}
TEST_F(ProjectStorageUpdater, update_property_editor_panes_is_empty_if_directory_has_not_changed)
{
- updater.update({}, {}, propertyEditorQmlPath);
+ updater.update({}, {}, propertyEditorQmlPath, {});
ON_CALL(fileSystemMock, fileStatus(_)).WillByDefault([](SourceId sourceId) {
return FileStatus{sourceId, 1, 21};
});
@@ -3511,7 +3528,135 @@ TEST_F(ProjectStorageUpdater, update_property_editor_panes_is_empty_if_directory
EXPECT_CALL(projectStorageMock, synchronize(PackageIsEmpty()));
- updater.update({}, {}, propertyEditorQmlPath);
+ updater.update({}, {}, propertyEditorQmlPath, {});
+}
+
+TEST_F(ProjectStorageUpdater, update_type_annotations)
+{
+ auto itemSourceId = sourcePathCache.sourceId(
+ QmlDesigner::SourcePath{itemLibraryPath + "/quick.metainfo"});
+ auto buttonSourceId = sourcePathCache.sourceId(
+ QmlDesigner::SourcePath{itemLibraryPath + "/qtquickcontrols2.metainfo"});
+ setFilesChanged({itemLibraryPathSourceId, itemSourceId, buttonSourceId});
+ auto qtQuickModuleId = moduleId("QtQuick");
+ auto qtQuickControlsModuleId = moduleId("QtQuick.Controls.Basic");
+ QmlDesigner::Storage::TypeTraits itemTraits;
+ itemTraits.canBeContainer = QmlDesigner::FlagIs::True;
+
+ EXPECT_CALL(projectStorageMock,
+ synchronize(AllOf(Field(&SynchronizationPackage::typeAnnotations,
+ IsSupersetOf({IsTypeAnnotation(itemSourceId,
+ itemLibraryPathSourceId,
+ "Item",
+ qtQuickModuleId,
+ StartsWith(itemLibraryPath),
+ _,
+ _,
+ _),
+ IsTypeAnnotation(buttonSourceId,
+ itemLibraryPathSourceId,
+ "Button",
+ qtQuickControlsModuleId,
+ StartsWith(itemLibraryPath),
+ _,
+ _,
+ _)})),
+ Field(&SynchronizationPackage::updatedTypeAnnotationSourceIds,
+ IsSupersetOf({itemSourceId, buttonSourceId})))));
+
+ updater.update({}, {}, {}, {itemLibraryPath});
+}
+
+TEST_F(ProjectStorageUpdater, update_changed_type_annotation)
+{
+ auto itemSourceId = sourcePathCache.sourceId(
+ QmlDesigner::SourcePath{itemLibraryPath + "/quick.metainfo"});
+ auto buttonSourceId = sourcePathCache.sourceId(
+ QmlDesigner::SourcePath{itemLibraryPath + "/qtquickcontrols2.metainfo"});
+ setFilesDontChanged({itemLibraryPathSourceId});
+ setFilesChanged({itemSourceId, buttonSourceId});
+ auto qtQuickModuleId = moduleId("QtQuick");
+ auto qtQuickControlsModuleId = moduleId("QtQuick.Controls.Basic");
+ QmlDesigner::Storage::TypeTraits itemTraits;
+ itemTraits.canBeContainer = QmlDesigner::FlagIs::True;
+
+ EXPECT_CALL(projectStorageMock,
+ synchronize(AllOf(Field(&SynchronizationPackage::typeAnnotations,
+ IsSupersetOf({IsTypeAnnotation(itemSourceId,
+ itemLibraryPathSourceId,
+ "Item",
+ qtQuickModuleId,
+ StartsWith(itemLibraryPath),
+ _,
+ _,
+ _),
+ IsTypeAnnotation(buttonSourceId,
+ itemLibraryPathSourceId,
+ "Button",
+ qtQuickControlsModuleId,
+ StartsWith(itemLibraryPath),
+ _,
+ _,
+ _)})),
+ Field(&SynchronizationPackage::updatedTypeAnnotationSourceIds,
+ IsSupersetOf({itemSourceId, buttonSourceId})))));
+
+ updater.update({}, {}, {}, {itemLibraryPath});
+}
+
+TEST_F(ProjectStorageUpdater, update_type_annotations_removed_meta_info_file)
+{
+ ON_CALL(fileSystemMock, fileStatus(_)).WillByDefault([](SourceId sourceId) {
+ return FileStatus{sourceId, 1, 21};
+ });
+ ON_CALL(projectStorageMock, fetchFileStatus(_)).WillByDefault([](SourceId sourceId) {
+ return FileStatus{sourceId, 1, 21};
+ });
+ auto itemSourceId = sourcePathCache.sourceId(
+ QmlDesigner::SourcePath{itemLibraryPath + "/quick.metainfo"});
+ auto buttonSourceId = sourcePathCache.sourceId(
+ QmlDesigner::SourcePath{itemLibraryPath + "/qtquickcontrols2.metainfo"});
+ ON_CALL(projectStorageMock, typeAnnotationDirectorySourceIds())
+ .WillByDefault(Return(QmlDesigner::SmallSourceIds<64>{itemLibraryPathSourceId}));
+ ON_CALL(projectStorageMock, typeAnnotationSourceIds(itemLibraryPathSourceId))
+ .WillByDefault(Return(QmlDesigner::SmallSourceIds<4>{itemSourceId, buttonSourceId}));
+ setFilesChanged({itemLibraryPathSourceId});
+ setFilesDontChanged({itemSourceId, buttonSourceId});
+
+ EXPECT_CALL(projectStorageMock,
+ synchronize(AllOf(Field(&SynchronizationPackage::typeAnnotations, IsEmpty()),
+ Field(&SynchronizationPackage::updatedTypeAnnotationSourceIds,
+ IsSupersetOf({itemSourceId, buttonSourceId})))));
+
+ updater.update({}, {}, {}, {itemLibraryPath});
+}
+
+TEST_F(ProjectStorageUpdater, update_type_annotations_removed_directory)
+{
+ ON_CALL(fileSystemMock, fileStatus(_)).WillByDefault([](SourceId sourceId) {
+ return FileStatus{sourceId, 1, 21};
+ });
+ ON_CALL(projectStorageMock, fetchFileStatus(_)).WillByDefault([](SourceId sourceId) {
+ return FileStatus{sourceId, 1, 21};
+ });
+ auto itemSourceId = sourcePathCache.sourceId(
+ QmlDesigner::SourcePath{itemLibraryPath + "/quick.metainfo"});
+ auto buttonSourceId = sourcePathCache.sourceId(
+ QmlDesigner::SourcePath{itemLibraryPath + "/qtquickcontrols2.metainfo"});
+ ON_CALL(projectStorageMock, typeAnnotationDirectorySourceIds())
+ .WillByDefault(Return(QmlDesigner::SmallSourceIds<64>{
+ itemLibraryPathSourceId,
+ }));
+ ON_CALL(projectStorageMock, typeAnnotationSourceIds(itemLibraryPathSourceId))
+ .WillByDefault(Return(QmlDesigner::SmallSourceIds<4>{itemSourceId, buttonSourceId}));
+ setFilesDontExists({itemLibraryPathSourceId, buttonSourceId, itemSourceId});
+
+ EXPECT_CALL(projectStorageMock,
+ synchronize(AllOf(Field(&SynchronizationPackage::typeAnnotations, IsEmpty()),
+ Field(&SynchronizationPackage::updatedTypeAnnotationSourceIds,
+ IsSupersetOf({buttonSourceId, itemSourceId})))));
+
+ updater.update({}, {}, {}, {itemLibraryPath});
}
} // namespace
diff --git a/tests/unit/tests/unittests/projectstorage/qmldocumentparser-test.cpp b/tests/unit/tests/unittests/projectstorage/qmldocumentparser-test.cpp
index f39dec121c..513fbf2ec0 100644
--- a/tests/unit/tests/unittests/projectstorage/qmldocumentparser-test.cpp
+++ b/tests/unit/tests/unittests/projectstorage/qmldocumentparser-test.cpp
@@ -143,8 +143,8 @@ class QmlDocumentParser : public ::testing::Test
public:
protected:
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
- QmlDesigner::ProjectStorage<Sqlite::Database> storage{database, database.isInitialized()};
- QmlDesigner::SourcePathCache<QmlDesigner::ProjectStorage<Sqlite::Database>> sourcePathCache{
+ QmlDesigner::ProjectStorage storage{database, database.isInitialized()};
+ QmlDesigner::SourcePathCache<QmlDesigner::ProjectStorage> sourcePathCache{
storage};
QmlDesigner::QmlDocumentParser parser{storage, sourcePathCache};
Storage::Imports imports;
@@ -516,4 +516,16 @@ TEST_F(QmlDocumentParser, qualified_list_property)
Storage::PropertyDeclarationTraits::IsList)));
}
+TEST_F(QmlDocumentParser, default_property)
+{
+ auto type = parser.parse(R"(import Example 2.1 as Example
+ Item{
+ default property list<Example.Foo> foos
+ })",
+ imports,
+ qmlFileSourceId,
+ directoryPath);
+
+ ASSERT_THAT(type.defaultPropertyName, Eq("foos"));
+}
} // namespace
diff --git a/tests/unit/tests/unittests/projectstorage/qmltypesparser-test.cpp b/tests/unit/tests/unittests/projectstorage/qmltypesparser-test.cpp
index 78f8f41d6c..64f3631a68 100644
--- a/tests/unit/tests/unittests/projectstorage/qmltypesparser-test.cpp
+++ b/tests/unit/tests/unittests/projectstorage/qmltypesparser-test.cpp
@@ -168,8 +168,8 @@ class QmlTypesParser : public ::testing::Test
public:
protected:
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
- QmlDesigner::ProjectStorage<Sqlite::Database> storage{database, database.isInitialized()};
- QmlDesigner::SourcePathCache<QmlDesigner::ProjectStorage<Sqlite::Database>> sourcePathCache{
+ QmlDesigner::ProjectStorage storage{database, database.isInitialized()};
+ QmlDesigner::SourcePathCache<QmlDesigner::ProjectStorage> sourcePathCache{
storage};
QmlDesigner::QmlTypesParser parser{storage};
Storage::Imports imports;
@@ -838,4 +838,39 @@ TEST_F(QmlTypesParser, uses_no_custom_parser)
ASSERT_THAT(types, ElementsAre(IsTypeTrait(UsesCustomParser(false))));
}
+TEST_F(QmlTypesParser, default_property)
+{
+ QString source{R"(import QtQuick.tooling 1.2
+ Module{
+ Component { name: "QObject"
+ defaultProperty: "children" }})"};
+
+ parser.parse(source, imports, types, projectData);
+
+ ASSERT_THAT(types,
+ ElementsAre(Field(&Synchronization::Type::defaultPropertyName, Eq("children"))));
+}
+
+TEST_F(QmlTypesParser, skip_template_item)
+{
+ ModuleId moduleId = storage.moduleId("QtQuick.Templates-cppnative");
+ Synchronization::ProjectData projectData{qmltypesFileSourceId,
+ qmltypesFileSourceId,
+ moduleId,
+ Synchronization::FileType::QmlTypes};
+ QString source{R"(import QtQuick.tooling 1.2
+ Module{
+ Component { name: "QQuickItem"}
+ Component { name: "QQmlComponent"}})"};
+
+ parser.parse(source, imports, types, projectData);
+
+ ASSERT_THAT(types,
+ UnorderedElementsAre(IsType("QQmlComponent",
+ Synchronization::ImportedType{},
+ Synchronization::ImportedType{},
+ Storage::TypeTraitsKind::Reference,
+ qmltypesFileSourceId)));
+}
+
} // namespace
diff --git a/tests/unit/tests/unittests/projectstorage/typeannotationreader-test.cpp b/tests/unit/tests/unittests/projectstorage/typeannotationreader-test.cpp
index ed5c1a0778..a614a5c7cf 100644
--- a/tests/unit/tests/unittests/projectstorage/typeannotationreader-test.cpp
+++ b/tests/unit/tests/unittests/projectstorage/typeannotationreader-test.cpp
@@ -3,6 +3,7 @@
#include "../utils/googletest.h"
+#include <projectstorage-matcher.h>
#include <strippedstring-matcher.h>
#include <projectstorage/projectstorage.h>
@@ -11,24 +12,6 @@
namespace {
-template<typename HintsJsonMatcher, typename ItemLibraryJsonMatcher>
-auto IsTypeAnnotation(QmlDesigner::SourceId sourceId,
- Utils::SmallStringView typeName,
- QmlDesigner::ModuleId moduleId,
- Utils::SmallStringView iconPath,
- QmlDesigner::Storage::TypeTraits traits,
- HintsJsonMatcher hintsJsonMatcher,
- ItemLibraryJsonMatcher itemLibraryJsonMatcher)
-{
- using QmlDesigner::Storage::Synchronization::TypeAnnotation;
- return AllOf(Field("sourceId", &TypeAnnotation::sourceId, sourceId),
- Field("typeName", &TypeAnnotation::typeName, typeName),
- Field("moduleId", &TypeAnnotation::moduleId, moduleId),
- Field("iconPath", &TypeAnnotation::iconPath, iconPath),
- Field("traits", &TypeAnnotation::traits, traits),
- Field("hintsJson", &TypeAnnotation::hintsJson, hintsJsonMatcher),
- Field("itemLibraryJson", &TypeAnnotation::itemLibraryJson, itemLibraryJsonMatcher));
-}
class TypeAnnotationReader : public testing::Test
{
@@ -37,7 +20,7 @@ protected:
{
static_database = std::make_unique<Sqlite::Database>(":memory:", Sqlite::JournalMode::Memory);
- static_projectStorage = std::make_unique<QmlDesigner::ProjectStorage<Sqlite::Database>>(
+ static_projectStorage = std::make_unique<QmlDesigner::ProjectStorage>(
*static_database, static_database->isInitialized());
}
@@ -52,10 +35,11 @@ protected:
protected:
inline static std::unique_ptr<Sqlite::Database> static_database;
Sqlite::Database &database = *static_database;
- inline static std::unique_ptr<QmlDesigner::ProjectStorage<Sqlite::Database>> static_projectStorage;
- QmlDesigner::ProjectStorage<Sqlite::Database> &storage = *static_projectStorage;
+ inline static std::unique_ptr<QmlDesigner::ProjectStorage> static_projectStorage;
+ QmlDesigner::ProjectStorage &storage = *static_projectStorage;
QmlDesigner::Storage::TypeAnnotationReader reader{storage};
QmlDesigner::SourceId sourceId = QmlDesigner::SourceId::create(33);
+ QmlDesigner::SourceId directorySourceId = QmlDesigner::SourceId::create(77);
};
TEST_F(TypeAnnotationReader, parse_type)
@@ -73,10 +57,11 @@ TEST_F(TypeAnnotationReader, parse_type)
})xy"};
QmlDesigner::Storage::TypeTraits traits;
- auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId);
+ auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId, directorySourceId);
ASSERT_THAT(annotations,
UnorderedElementsAre(IsTypeAnnotation(sourceId,
+ directorySourceId,
"Frame",
moduleId("QtQuick.Controls"),
"/path/images/frame-icon16.png",
@@ -84,6 +69,7 @@ TEST_F(TypeAnnotationReader, parse_type)
IsEmpty(),
IsEmpty()),
IsTypeAnnotation(sourceId,
+ directorySourceId,
"Item",
moduleId("QtQuick"),
"/path/images/item-icon16.png",
@@ -109,10 +95,11 @@ TEST_F(TypeAnnotationReader, parse_true_canBeContainer)
QmlDesigner::Storage::TypeTraits traits;
traits.canBeContainer = FlagIs::True;
- auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId);
+ auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId, directorySourceId);
ASSERT_THAT(annotations,
ElementsAre(IsTypeAnnotation(sourceId,
+ directorySourceId,
"Frame",
moduleId("QtQuick.Controls"),
"/path/images/frame-icon16.png",
@@ -138,10 +125,11 @@ TEST_F(TypeAnnotationReader, parse_true_forceClip)
QmlDesigner::Storage::TypeTraits traits;
traits.forceClip = FlagIs::True;
- auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId);
+ auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId, directorySourceId);
ASSERT_THAT(annotations,
ElementsAre(IsTypeAnnotation(sourceId,
+ directorySourceId,
"Frame",
moduleId("QtQuick.Controls"),
"/path/images/frame-icon16.png",
@@ -167,10 +155,11 @@ TEST_F(TypeAnnotationReader, parse_true_doesLayoutChildren)
QmlDesigner::Storage::TypeTraits traits;
traits.doesLayoutChildren = FlagIs::True;
- auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId);
+ auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId, directorySourceId);
ASSERT_THAT(annotations,
ElementsAre(IsTypeAnnotation(sourceId,
+ directorySourceId,
"Frame",
moduleId("QtQuick.Controls"),
"/path/images/frame-icon16.png",
@@ -196,10 +185,11 @@ TEST_F(TypeAnnotationReader, parse_true_canBeDroppedInFormEditor)
QmlDesigner::Storage::TypeTraits traits;
traits.canBeDroppedInFormEditor = FlagIs::True;
- auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId);
+ auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId, directorySourceId);
ASSERT_THAT(annotations,
ElementsAre(IsTypeAnnotation(sourceId,
+ directorySourceId,
"Frame",
moduleId("QtQuick.Controls"),
"/path/images/frame-icon16.png",
@@ -225,10 +215,11 @@ TEST_F(TypeAnnotationReader, parse_true_canBeDroppedInNavigator)
QmlDesigner::Storage::TypeTraits traits;
traits.canBeDroppedInNavigator = FlagIs::True;
- auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId);
+ auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId, directorySourceId);
ASSERT_THAT(annotations,
ElementsAre(IsTypeAnnotation(sourceId,
+ directorySourceId,
"Frame",
moduleId("QtQuick.Controls"),
"/path/images/frame-icon16.png",
@@ -254,10 +245,11 @@ TEST_F(TypeAnnotationReader, parse_true_canBeDroppedInView3D)
QmlDesigner::Storage::TypeTraits traits;
traits.canBeDroppedInView3D = FlagIs::True;
- auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId);
+ auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId, directorySourceId);
ASSERT_THAT(annotations,
ElementsAre(IsTypeAnnotation(sourceId,
+ directorySourceId,
"Frame",
moduleId("QtQuick.Controls"),
"/path/images/frame-icon16.png",
@@ -283,10 +275,11 @@ TEST_F(TypeAnnotationReader, parse_true_isMovable)
QmlDesigner::Storage::TypeTraits traits;
traits.isMovable = FlagIs::True;
- auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId);
+ auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId, directorySourceId);
ASSERT_THAT(annotations,
ElementsAre(IsTypeAnnotation(sourceId,
+ directorySourceId,
"Frame",
moduleId("QtQuick.Controls"),
"/path/images/frame-icon16.png",
@@ -312,10 +305,11 @@ TEST_F(TypeAnnotationReader, parse_true_isResizable)
QmlDesigner::Storage::TypeTraits traits;
traits.isResizable = FlagIs::True;
- auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId);
+ auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId, directorySourceId);
ASSERT_THAT(annotations,
ElementsAre(IsTypeAnnotation(sourceId,
+ directorySourceId,
"Frame",
moduleId("QtQuick.Controls"),
"/path/images/frame-icon16.png",
@@ -341,10 +335,11 @@ TEST_F(TypeAnnotationReader, parse_true_hasFormEditorItem)
QmlDesigner::Storage::TypeTraits traits;
traits.hasFormEditorItem = FlagIs::True;
- auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId);
+ auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId, directorySourceId);
ASSERT_THAT(annotations,
ElementsAre(IsTypeAnnotation(sourceId,
+ directorySourceId,
"Frame",
moduleId("QtQuick.Controls"),
"/path/images/frame-icon16.png",
@@ -370,10 +365,11 @@ TEST_F(TypeAnnotationReader, parse_true_isStackedContainer)
QmlDesigner::Storage::TypeTraits traits;
traits.isStackedContainer = FlagIs::True;
- auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId);
+ auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId, directorySourceId);
ASSERT_THAT(annotations,
ElementsAre(IsTypeAnnotation(sourceId,
+ directorySourceId,
"Frame",
moduleId("QtQuick.Controls"),
"/path/images/frame-icon16.png",
@@ -399,10 +395,11 @@ TEST_F(TypeAnnotationReader, parse_true_takesOverRenderingOfChildren)
QmlDesigner::Storage::TypeTraits traits;
traits.takesOverRenderingOfChildren = FlagIs::True;
- auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId);
+ auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId, directorySourceId);
ASSERT_THAT(annotations,
ElementsAre(IsTypeAnnotation(sourceId,
+ directorySourceId,
"Frame",
moduleId("QtQuick.Controls"),
"/path/images/frame-icon16.png",
@@ -428,10 +425,11 @@ TEST_F(TypeAnnotationReader, parse_true_visibleInNavigator)
QmlDesigner::Storage::TypeTraits traits;
traits.visibleInNavigator = FlagIs::True;
- auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId);
+ auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId, directorySourceId);
ASSERT_THAT(annotations,
ElementsAre(IsTypeAnnotation(sourceId,
+ directorySourceId,
"Frame",
moduleId("QtQuick.Controls"),
"/path/images/frame-icon16.png",
@@ -457,10 +455,11 @@ TEST_F(TypeAnnotationReader, parse_true_visibleInLibrary)
QmlDesigner::Storage::TypeTraits traits;
traits.visibleInLibrary = FlagIs::True;
- auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId);
+ auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId, directorySourceId);
ASSERT_THAT(annotations,
ElementsAre(IsTypeAnnotation(sourceId,
+ directorySourceId,
"Frame",
moduleId("QtQuick.Controls"),
"/path/images/frame-icon16.png",
@@ -485,10 +484,11 @@ TEST_F(TypeAnnotationReader, parse_false)
})xy"};
QmlDesigner::Storage::TypeTraits traits;
- auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId);
+ auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId, directorySourceId);
ASSERT_THAT(annotations,
ElementsAre(IsTypeAnnotation(sourceId,
+ directorySourceId,
"Frame",
moduleId("QtQuick.Controls"),
"/path/images/frame-icon16.png",
@@ -526,10 +526,11 @@ TEST_F(TypeAnnotationReader, parse_complex_expression)
QmlDesigner::Storage::TypeTraits itemTraits;
itemTraits.canBeContainer = QmlDesigner::FlagIs::True;
- auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId);
+ auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId, directorySourceId);
ASSERT_THAT(annotations,
UnorderedElementsAre(IsTypeAnnotation(sourceId,
+ directorySourceId,
"Frame",
moduleId("QtQuick.Controls"),
"/path/images/frame-icon16.png",
@@ -538,6 +539,7 @@ TEST_F(TypeAnnotationReader, parse_complex_expression)
"visibleNonDefaultProperties":"layer.effect"})xy"),
IsEmpty()),
IsTypeAnnotation(sourceId,
+ directorySourceId,
"Item",
moduleId("QtQuick"),
"/path/images/item-icon16.png",
@@ -573,10 +575,11 @@ TEST_F(TypeAnnotationReader, parse_item_library_entry)
})xy"};
QmlDesigner::Storage::TypeTraits traits;
- auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId);
+ auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId, directorySourceId);
ASSERT_THAT(annotations,
ElementsAre(IsTypeAnnotation(sourceId,
+ directorySourceId,
"Frame",
moduleId("QtQuick.Controls"),
"/path/images/frame-icon16.png",
@@ -584,12 +587,12 @@ TEST_F(TypeAnnotationReader, parse_item_library_entry)
IsEmpty(),
StrippedStringEq(R"xy([
{"category":"Qt Quick - Controls 2",
- "iconPath":"images/frame-icon.png",
+ "iconPath":"/path/images/frame-icon.png",
"import":"QtQuick.Controls",
"name":"Frame",
"toolTip":"qsTr(\"An untitled container for a group of controls.\")"},
{"category":"Qt Quick - Controls 2",
- "iconPath":"images/frame-icon.png",
+ "iconPath":"/path/images/frame-icon.png",
"import":"QtQuick.Controls",
"name":"Large Frame",
"toolTip":"qsTr(\"An large container for a group of controls.\")"}]
@@ -629,10 +632,11 @@ TEST_F(TypeAnnotationReader, parse_item_library_entry_with_properties)
})xy"};
QmlDesigner::Storage::TypeTraits traits;
- auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId);
+ auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId, directorySourceId);
ASSERT_THAT(annotations,
ElementsAre(IsTypeAnnotation(sourceId,
+ directorySourceId,
"Frame",
moduleId("QtQuick.Controls"),
"/path/images/frame-icon16.png",
@@ -640,13 +644,13 @@ TEST_F(TypeAnnotationReader, parse_item_library_entry_with_properties)
IsEmpty(),
StrippedStringEq(R"xy([
{"category":"Qt Quick - Controls 2",
- "iconPath":"images/frame-icon.png",
+ "iconPath":"/path/images/frame-icon.png",
"import":"QtQuick.Controls",
"name":"Frame",
"properties":[["width","int",200.0],["height","int",100.0]],
"toolTip":"qsTr(\"An untitled container for a group of controls.\")"},
{"category":"Qt Quick - Controls 2",
- "iconPath":"images/frame-icon.png",
+ "iconPath":"/path/images/frame-icon.png",
"import":"QtQuick.Controls",
"name":"Large Frame",
"properties":[["width","int",2000.0],["height","int",1000.0]],
@@ -679,13 +683,14 @@ TEST_F(TypeAnnotationReader, parse_item_library_entry_template_path)
})xy"};
QmlDesigner::Storage::TypeTraits traits;
- auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId);
+ auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId, directorySourceId);
ASSERT_THAT(annotations,
ElementsAre(IsTypeAnnotation(sourceId,
+ directorySourceId,
"Frame",
moduleId("QtQuick.Controls"),
- {},
+ Utils::SmallStringView{},
traits,
IsEmpty(),
StrippedStringEq(R"xy([
@@ -693,9 +698,10 @@ TEST_F(TypeAnnotationReader, parse_item_library_entry_template_path)
"templatePath":"/path/templates/frame.qml"}]
)xy")),
IsTypeAnnotation(sourceId,
+ directorySourceId,
"Item",
moduleId("QtQuick"),
- {},
+ Utils::SmallStringView{},
traits,
IsEmpty(),
StrippedStringEq(R"xy([
@@ -730,13 +736,14 @@ TEST_F(TypeAnnotationReader, parse_item_library_entry_extra_file_paths)
})xy"};
QmlDesigner::Storage::TypeTraits traits;
- auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId);
+ auto annotations = reader.parseTypeAnnotation(content, "/path", sourceId, directorySourceId);
ASSERT_THAT(annotations,
ElementsAre(IsTypeAnnotation(sourceId,
+ directorySourceId,
"Frame",
moduleId("QtQuick.Controls"),
- {},
+ Utils::SmallStringView{},
traits,
IsEmpty(),
StrippedStringEq(R"xy([
@@ -744,9 +751,10 @@ TEST_F(TypeAnnotationReader, parse_item_library_entry_extra_file_paths)
"name":"Frame"}]
)xy")),
IsTypeAnnotation(sourceId,
+ directorySourceId,
"Item",
moduleId("QtQuick"),
- {},
+ Utils::SmallStringView{},
traits,
IsEmpty(),
StrippedStringEq(R"xy([
diff --git a/tests/unit/tests/unittests/sqlite/sqliteindex-test.cpp b/tests/unit/tests/unittests/sqlite/sqliteindex-test.cpp
index 9d3fca88ff..b065c0ab9a 100644
--- a/tests/unit/tests/unittests/sqlite/sqliteindex-test.cpp
+++ b/tests/unit/tests/unittests/sqlite/sqliteindex-test.cpp
@@ -17,7 +17,9 @@ TEST(Index, one_column)
auto sqlStatement = index.sqlStatement();
- ASSERT_THAT(sqlStatement, Eq("CREATE INDEX IF NOT EXISTS index_tableName_column1 ON tableName(column1)"));
+ ASSERT_THAT(
+ sqlStatement,
+ Eq("CREATE INDEX IF NOT EXISTS index_normal_tableName_column1 ON tableName(column1)"));
}
TEST(Index, two_column)
@@ -26,7 +28,9 @@ TEST(Index, two_column)
auto sqlStatement = index.sqlStatement();
- ASSERT_THAT(sqlStatement, Eq("CREATE INDEX IF NOT EXISTS index_tableName_column1_column2 ON tableName(column1, column2)"));
+ ASSERT_THAT(sqlStatement,
+ Eq("CREATE INDEX IF NOT EXISTS index_normal_tableName_column1_column2 ON "
+ "tableName(column1, column2)"));
}
TEST(Index, empty_table_name)
@@ -49,7 +53,8 @@ TEST(Index, unique_index)
auto sqlStatement = index.sqlStatement();
- ASSERT_THAT(sqlStatement, Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_tableName_column1 ON tableName(column1)"));
+ ASSERT_THAT(
+ sqlStatement, Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_unique_tableName_column1 ON tableName(column1)"));
}
TEST(Index, condition)
@@ -58,8 +63,20 @@ TEST(Index, condition)
auto sqlStatement = index.sqlStatement();
+ ASSERT_THAT(
+ sqlStatement,
+ Eq("CREATE INDEX IF NOT EXISTS index_partial_tableName_column1 ON tableName(column1) WHERE "
+ "column1 IS NOT NULL"));
+}
+
+TEST(Index, unique_index_with_condition)
+{
+ Index index{"tableName", {"column1"}, IndexType::Unique, "column1 IS NOT NULL"};
+
+ auto sqlStatement = index.sqlStatement();
+
ASSERT_THAT(sqlStatement,
- Eq("CREATE INDEX IF NOT EXISTS index_tableName_column1 ON tableName(column1) WHERE "
- "column1 IS NOT NULL"));
+ Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_unique_partial_tableName_column1 ON "
+ "tableName(column1) WHERE column1 IS NOT NULL"));
}
}
diff --git a/tests/unit/tests/unittests/sqlite/sqlitetable-test.cpp b/tests/unit/tests/unittests/sqlite/sqlitetable-test.cpp
index 7b8189b51e..e1b0427f3c 100644
--- a/tests/unit/tests/unittests/sqlite/sqlitetable-test.cpp
+++ b/tests/unit/tests/unittests/sqlite/sqlitetable-test.cpp
@@ -60,9 +60,9 @@ TEST_F(SqliteTable, add_index)
auto index = table.addIndex({column, column2});
- ASSERT_THAT(
- Utils::SmallStringView(index.sqlStatement()),
- Eq("CREATE INDEX IF NOT EXISTS index_testTable_name_value ON testTable(name, value)"));
+ ASSERT_THAT(Utils::SmallStringView(index.sqlStatement()),
+ Eq("CREATE INDEX IF NOT EXISTS index_normal_testTable_name_value ON "
+ "testTable(name, value)"));
}
TEST_F(SqliteTable, initialize_table)
@@ -92,10 +92,11 @@ TEST_F(SqliteTable, initialize_table_with_index)
EXPECT_CALL(databaseMock, execute(Eq("CREATE TABLE testTable(name, value)")));
EXPECT_CALL(databaseMock,
- execute(Eq("CREATE INDEX IF NOT EXISTS index_testTable_name ON testTable(name)")));
+ execute(Eq(
+ "CREATE INDEX IF NOT EXISTS index_normal_testTable_name ON testTable(name)")));
EXPECT_CALL(databaseMock,
- execute(Eq("CREATE INDEX IF NOT EXISTS index_testTable_value ON testTable(value) "
- "WHERE value IS NOT NULL")));
+ execute(Eq("CREATE INDEX IF NOT EXISTS index_partial_testTable_value ON "
+ "testTable(value) WHERE value IS NOT NULL")));
table.initialize(databaseMock);
}
@@ -110,13 +111,13 @@ TEST_F(SqliteTable, initialize_table_with_unique_index)
table.addUniqueIndex({column2}, "value IS NOT NULL");
EXPECT_CALL(databaseMock, execute(Eq("CREATE TABLE testTable(name, value)")));
+ EXPECT_CALL(
+ databaseMock,
+ execute(Eq(
+ "CREATE UNIQUE INDEX IF NOT EXISTS index_unique_testTable_name ON testTable(name)")));
EXPECT_CALL(databaseMock,
- execute(Eq(
- "CREATE UNIQUE INDEX IF NOT EXISTS index_testTable_name ON testTable(name)")));
- EXPECT_CALL(databaseMock,
- execute(Eq(
- "CREATE UNIQUE INDEX IF NOT EXISTS index_testTable_value ON testTable(value) "
- "WHERE value IS NOT NULL")));
+ execute(Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_unique_partial_testTable_value "
+ "ON testTable(value) WHERE value IS NOT NULL")));
table.initialize(databaseMock);
}
@@ -351,8 +352,8 @@ TEST_F(StrictSqliteTable, add_index)
auto index = table.addIndex({column, column2});
ASSERT_THAT(Utils::SmallStringView(index.sqlStatement()),
- Eq("CREATE INDEX IF NOT EXISTS index_testTable_name_value ON testTable(name, "
- "value)"));
+ Eq("CREATE INDEX IF NOT EXISTS index_normal_testTable_name_value ON "
+ "testTable(name, value)"));
}
TEST_F(StrictSqliteTable, initialize_table)
@@ -382,10 +383,11 @@ TEST_F(StrictSqliteTable, initialize_table_with_index)
EXPECT_CALL(databaseMock, execute(Eq("CREATE TABLE testTable(name ANY, value ANY) STRICT")));
EXPECT_CALL(databaseMock,
- execute(Eq("CREATE INDEX IF NOT EXISTS index_testTable_name ON testTable(name)")));
+ execute(Eq(
+ "CREATE INDEX IF NOT EXISTS index_normal_testTable_name ON testTable(name)")));
EXPECT_CALL(databaseMock,
- execute(Eq("CREATE INDEX IF NOT EXISTS index_testTable_value ON testTable(value) "
- "WHERE value IS NOT NULL")));
+ execute(Eq("CREATE INDEX IF NOT EXISTS index_partial_testTable_value ON "
+ "testTable(value) WHERE value IS NOT NULL")));
table.initialize(databaseMock);
}
@@ -400,13 +402,13 @@ TEST_F(StrictSqliteTable, initialize_table_with_unique_index)
table.addUniqueIndex({column2}, "value IS NOT NULL");
EXPECT_CALL(databaseMock, execute(Eq("CREATE TABLE testTable(name ANY, value ANY) STRICT")));
+ EXPECT_CALL(
+ databaseMock,
+ execute(Eq(
+ "CREATE UNIQUE INDEX IF NOT EXISTS index_unique_testTable_name ON testTable(name)")));
EXPECT_CALL(databaseMock,
- execute(Eq(
- "CREATE UNIQUE INDEX IF NOT EXISTS index_testTable_name ON testTable(name)")));
- EXPECT_CALL(databaseMock,
- execute(Eq(
- "CREATE UNIQUE INDEX IF NOT EXISTS index_testTable_value ON testTable(value) "
- "WHERE value IS NOT NULL")));
+ execute(Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_unique_partial_testTable_value "
+ "ON testTable(value) WHERE value IS NOT NULL")));
table.initialize(databaseMock);
}
diff --git a/tests/unit/tests/unittests/utils/smallstring-test.cpp b/tests/unit/tests/unittests/utils/smallstring-test.cpp
index bdcdb44019..71090f8760 100644
--- a/tests/unit/tests/unittests/utils/smallstring-test.cpp
+++ b/tests/unit/tests/unittests/utils/smallstring-test.cpp
@@ -941,6 +941,33 @@ TEST(SmallString, append_empty_initializer_list)
ASSERT_THAT(text, Eq("some text"));
}
+TEST(SmallString, append_int)
+{
+ SmallString text("some text");
+
+ text += 123;
+
+ ASSERT_THAT(text, Eq("some text123"));
+}
+
+TEST(SmallString, append_float)
+{
+ SmallString text("some text");
+
+ text += 123.456;
+
+ ASSERT_THAT(text, Eq("some text123.456"));
+}
+
+TEST(SmallString, append_character)
+{
+ SmallString text("some text");
+
+ text += 'x';
+
+ ASSERT_THAT(text, Eq("some textx"));
+}
+
TEST(SmallString, to_byte_array)
{
SmallString text("some text");
@@ -1299,6 +1326,19 @@ TEST(SmallString, starts_with_string_view)
ASSERT_FALSE(text.startsWith('@'));
}
+TEST(SmallString, starts_with_qstringview)
+{
+ using namespace Qt::StringLiterals;
+ SmallString text("$column");
+
+ ASSERT_FALSE(text.startsWith(u"$columnxxx"_s));
+ ASSERT_TRUE(text.startsWith(u"$column"_s));
+ ASSERT_TRUE(text.startsWith(u"$col"_s));
+ ASSERT_FALSE(text.startsWith(u"col"_s));
+ ASSERT_TRUE(text.startsWith(u"$"_s));
+ ASSERT_FALSE(text.startsWith(u"@"_s));
+}
+
TEST(SmallString, ends_with)
{
SmallString text("/my/path");
@@ -1839,6 +1879,8 @@ TEST(SmallString, number_to_string)
ASSERT_THAT(SmallString::number(std::numeric_limits<long long int>::min()), "-9223372036854775808");
ASSERT_THAT(SmallString::number(1.2), "1.2");
ASSERT_THAT(SmallString::number(-1.2), "-1.2");
+ ASSERT_THAT(SmallString::number(1.2f), "1.2");
+ ASSERT_THAT(SmallString::number(-1.2f), "-1.2");
}
TEST(SmallString, string_view_plus_operator)