diff --git a/cmake/Utils.cmake b/cmake/Utils.cmake
index eca19a7dd0b..64473a926c2 100644
--- a/cmake/Utils.cmake
+++ b/cmake/Utils.cmake
@@ -61,7 +61,7 @@ function(setup_dependencies_component)
endfunction()
function(configure_qml_designer Qt6_VERSION)
- set(QMLDESIGNER_QT6_REQUIRED_VERSION 6.5.4)
+ set(QMLDESIGNER_QT6_REQUIRED_VERSION 6.7.3)
set(QMLDESIGNER_GCC_REQUIRED_VERSION 10.0)
set(QMLDESIGNER_CLANG_REQUIRED_VERSION 13.0)
set(QMLDESIGNER_APPLECLANG_REQUIRED_VERSION 15.0)
diff --git a/dist/branding/qtdesignstudio/QtCreatorIDEBranding.cmake b/dist/branding/qtdesignstudio/QtCreatorIDEBranding.cmake
index eb676b209fc..2e889d88be1 100644
--- a/dist/branding/qtdesignstudio/QtCreatorIDEBranding.cmake
+++ b/dist/branding/qtdesignstudio/QtCreatorIDEBranding.cmake
@@ -32,6 +32,7 @@ set(DESIGNSTUDIO_PLUGINS
DiffEditor
EffectComposer
FakeVim
+ Git
Help
Insight
LanguageClient
diff --git a/doc/qtcreator/src/external-resources/external-resources-qds.qdoc b/doc/qtcreator/src/external-resources/external-resources-qds.qdoc
index c46066168e8..1cd90ae903f 100644
--- a/doc/qtcreator/src/external-resources/external-resources-qds.qdoc
+++ b/doc/qtcreator/src/external-resources/external-resources-qds.qdoc
@@ -105,6 +105,10 @@
\externalpage https://doc.qt.io/qt/linguist-id-based-i18n.html
\title Text ID based translations
*/
+/*!
+ \externalpage https://www.qt.io/blog/qt-design-studio-4.6-released
+ \title Qt Design Studio 4.6 released
+*/
/*!
\externalpage https://www.qt.io/blog/qt-design-studio-4.5.1-released
\title Qt Design Studio 4.5.1 released
diff --git a/doc/qtdesignstudio/config/style/qt5-sidebar.html b/doc/qtdesignstudio/config/style/qt5-sidebar.html
index 7ca7d5b1e65..f1e2fc4af57 100644
--- a/doc/qtdesignstudio/config/style/qt5-sidebar.html
+++ b/doc/qtdesignstudio/config/style/qt5-sidebar.html
@@ -12,103 +12,444 @@
Getting Started
-
+
-
-
-
Prototyping
+ Key Concepts
-
-
-
-
-
Implementing Applications
-
-
-
-
-
-
Advanced Designer Topics
-
-
-
-
+
-
Help
+ Working with
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Best Practices
+
+
+
+
+
+
+
+
+
+
+
+
+
Reference
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/doc/qtdesignstudio/images/edit-list-model-model-editor.webp b/doc/qtdesignstudio/images/edit-list-model-model-editor.webp
deleted file mode 100644
index e7f47c6402c..00000000000
Binary files a/doc/qtdesignstudio/images/edit-list-model-model-editor.webp and /dev/null differ
diff --git a/doc/qtdesignstudio/images/model-editor-new-model.webp b/doc/qtdesignstudio/images/model-editor-new-model.webp
deleted file mode 100644
index 6ea705a047b..00000000000
Binary files a/doc/qtdesignstudio/images/model-editor-new-model.webp and /dev/null differ
diff --git a/doc/qtdesignstudio/images/repeater3d-model-editor.webp b/doc/qtdesignstudio/images/repeater3d-model-editor.webp
deleted file mode 100644
index e0e60873668..00000000000
Binary files a/doc/qtdesignstudio/images/repeater3d-model-editor.webp and /dev/null differ
diff --git a/doc/qtdesignstudio/images/studio-edit-list-model.webp b/doc/qtdesignstudio/images/studio-edit-list-model.webp
new file mode 100644
index 00000000000..ce740ec6d26
Binary files /dev/null and b/doc/qtdesignstudio/images/studio-edit-list-model.webp differ
diff --git a/doc/qtdesignstudio/images/studio-feedback-popup-material.png b/doc/qtdesignstudio/images/studio-feedback-popup-material.png
new file mode 100644
index 00000000000..2d935349bf1
Binary files /dev/null and b/doc/qtdesignstudio/images/studio-feedback-popup-material.png differ
diff --git a/doc/qtdesignstudio/images/studio-feedback-popup.png b/doc/qtdesignstudio/images/studio-feedback-popup.png
deleted file mode 100644
index 5a6d38bc050..00000000000
Binary files a/doc/qtdesignstudio/images/studio-feedback-popup.png and /dev/null differ
diff --git a/doc/qtdesignstudio/src/components/qtquick-components.qdoc b/doc/qtdesignstudio/src/components/qtquick-components.qdoc
index f512b8f67d4..a0ab80b2570 100644
--- a/doc/qtdesignstudio/src/components/qtquick-components.qdoc
+++ b/doc/qtdesignstudio/src/components/qtquick-components.qdoc
@@ -1,9 +1,9 @@
-// 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.html
- \previouspage studio-flow-external-events.html
+ \previouspage quick-uis.html
\nextpage quick-preset-components.html
\title Using Components
diff --git a/doc/qtdesignstudio/src/components/qtquick-data-models.qdoc b/doc/qtdesignstudio/src/components/qtquick-data-models.qdoc
index b93b745bc2c..2aa89a744dd 100644
--- a/doc/qtdesignstudio/src/components/qtquick-data-models.qdoc
+++ b/doc/qtdesignstudio/src/components/qtquick-data-models.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
/*!
@@ -147,12 +147,12 @@
\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 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
+ \uicontrol {Edit List Model} in the context-menu to open
+ the list model editor.
+ \image studio-edit-list-model.webp "List view in the list 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
list item.
\endlist
diff --git a/doc/qtdesignstudio/src/developers/studio-designer-developer-workflow.qdoc b/doc/qtdesignstudio/src/developers/studio-designer-developer-workflow.qdoc
index 5b59d665971..78e90404542 100644
--- a/doc/qtdesignstudio/src/developers/studio-designer-developer-workflow.qdoc
+++ b/doc/qtdesignstudio/src/developers/studio-designer-developer-workflow.qdoc
@@ -39,6 +39,9 @@
\list
\li Qt Creator 13.0 or above.
\li \QDS 4.5 or above.
+ \li Git.
+
+ \note Learn more about getting Git \l {https://wiki.qt.io/Git_Installation} {here}.
\endlist
\list 1
diff --git a/doc/qtdesignstudio/src/overviews/qtquick-animation-overview.qdoc b/doc/qtdesignstudio/src/overviews/qtquick-animation-overview.qdoc
index 86132b5ce1a..e6ae0295788 100644
--- a/doc/qtdesignstudio/src/overviews/qtquick-animation-overview.qdoc
+++ b/doc/qtdesignstudio/src/overviews/qtquick-animation-overview.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
/*!
@@ -15,7 +15,7 @@
\list
\li Common motion design techniques for 2D and 3D
- \li Screen-to-screen or state-to-state animations
+ \li State-to-state animations
\li Data-driven UI logic animations
\endlist
@@ -70,7 +70,7 @@
\section2 Animation Curves
While easing curves work well for most simple UI animations, more complex
- 3D animations require several keyframes so it becomes necessary to visualize
+ 3D animations require several keyframes, so it becomes necessary to visualize
the value and the interpolation of a keyframe simultaneously. The
\l {Curves} view visualizes the whole animation of a property at once and
shows the effective values of a keyframe together with the interpolation
@@ -78,36 +78,11 @@
simultaneously so that you can see the animation for the x position
and the animation for the y position side-by-side.
- \section1 Screen-to-Screen or State-to-State Animations
+ \section1 State-to-State Animations
- The following table summarizes techniques used for navigating between
- screens and UI states.
-
- \table
- \header
- \li Technique
- \li Use Case
- \row
- \li \l{Designing Application Flows}{Application flows}
- \li An interactive prototype that can be clicked through to simulate
- the user experience of the application.
- \row
- \li \l{Transitions}{Transitions between states}
- \li Transitions between different states of the UI using a transition
- timeline that is based on keyframes. You can apply easing curves
- to the keyframes.
- \endtable
-
- \section2 Application Flows
-
- You can design an application in the form of a \e {schematic diagram}
- that shows all the significant components of the application UI and their
- interconnections by means of symbols. This results in an interactive
- prototype that can be clicked through to simulate the user experience of
- the application. Code is created in the background and can be used
- as the base of the production version of the application.
-
- For more information, see \l{Designing Application Flows}.
+ To navigate between UI states, use transitions between different states of the UI
+ using a transition timeline that is based on keyframes. You can apply easing
+ curves to the keyframes.
\section2 Transitions Between States
diff --git a/doc/qtdesignstudio/src/overviews/qtquick-motion-design.qdoc b/doc/qtdesignstudio/src/overviews/qtquick-motion-design.qdoc
index 382c2f5fea8..80e0a844507 100644
--- a/doc/qtdesignstudio/src/overviews/qtquick-motion-design.qdoc
+++ b/doc/qtdesignstudio/src/overviews/qtquick-motion-design.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
/*!
@@ -14,8 +14,8 @@
\li You can use different animation techniques for different
purposes. \QDS supports common motion design techniques,
such as timeline and keyframe based animation and easing
- curves, as well as screen-to-screen or state-to-state
- application flows and data-driven UI logic animation.
+ curves, as well as state-to-state application flows and
+ data-driven UI logic animation.
\endtable
\list
diff --git a/doc/qtdesignstudio/src/overviews/qtquick-uis.qdoc b/doc/qtdesignstudio/src/overviews/qtquick-uis.qdoc
index 2f0aa723b8f..74063602795 100644
--- a/doc/qtdesignstudio/src/overviews/qtquick-uis.qdoc
+++ b/doc/qtdesignstudio/src/overviews/qtquick-uis.qdoc
@@ -1,10 +1,10 @@
-// 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-uis.html
\previouspage {Examples}
- \nextpage studio-app-flows.html
+ \nextpage quick-components.html
\title Wireframing
@@ -38,15 +38,6 @@
the developer documentation by pressing \key F1.
\list
-
- \li \l {Designing Application Flows}
-
- You can design an application in the form of a \e {schematic diagram}
- that shows all significant components of an application UI and their
- interconnections by means of symbols. This results in an
- interactive prototype that can be clicked through to simulate
- the user experience of the application.
-
\li \l {Using Components}
\QDS comes with \e {preset components} that you can use in
diff --git a/doc/qtdesignstudio/src/overviews/studio-user-feedback.qdoc b/doc/qtdesignstudio/src/overviews/studio-user-feedback.qdoc
index db7d24cdba6..5feddcd2c97 100644
--- a/doc/qtdesignstudio/src/overviews/studio-user-feedback.qdoc
+++ b/doc/qtdesignstudio/src/overviews/studio-user-feedback.qdoc
@@ -16,7 +16,7 @@
\uicontrol Skip or \uicontrol Submit, the pop-up survey will not appear for
the same feature again.
- \image studio-feedback-popup.png "User feedback pop-up survey for Flow Editor"
+ \image studio-feedback-popup-material.png "User feedback pop-up survey for Material Browser"
For the pop-up survey to appear, you must enable collecting statistics, and
also allow collecting \uicontrol {4 - Detailed usage statistics} in
diff --git a/doc/qtdesignstudio/src/qtdesignstudio-app-flows.qdoc b/doc/qtdesignstudio/src/qtdesignstudio-app-flows.qdoc
deleted file mode 100644
index 1be7f143117..00000000000
--- a/doc/qtdesignstudio/src/qtdesignstudio-app-flows.qdoc
+++ /dev/null
@@ -1,707 +0,0 @@
-// Copyright (C) 2024 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
-
-/*!
- \page studio-app-flows.html
- \previouspage quick-uis.html
- \nextpage studio-flow-view.html
-
- \title Designing Application Flows
-
- \image studio-flow-view.webp "Application flow in the 2D view"
-
- In \QDS, a \e {flow view} represents a schematic diagram. It consists of
- \e {flow items} that represent the screens in the UI and \e {transition
- lines} that connect them, thus illustrating the possible user pathways
- through the UI. \e {Action areas} are clickable starting points for transition
- lines. Attach effects to transition lines, such as fade or push,
- to determine what users see when one flow item changes into another.
-
- Use \e {flow decisions} to set up alternative pathways between flow items in the UI. For
- example, if user input determines which flow item should open next, test the different
- scenarios in the prototype with the decision dialog where you can select which flow item to
- show next.
-
- Especially on mobile and embedded platforms, the application might need to
- react to external events from the platform, such as notifications or other
- applications requiring the users' attention. Use \e {flow wildcards}
- to determine the priority of flow items by adding them to allow and
- block lists.
-
- To design application flows:
-
- \image studio-flow-steps.png "Designing application flows"
-
- \list 1
- \li Use a project wizard template to add a \uicontrol {Flow View}
- component, as described in \l{Adding Flow Views}.
- \li Use a project wizard template to add a \uicontrol {Flow Item}
- component for each screen in the UI, as described in
- \l{Adding Flow Items}.
- \li Use context menu commands to add action areas and transitions,
- as described in \l{Adding Action Areas and Transitions}.
- \endlist
-
- Additionally, to create a more advanced application flow:
-
- \list
- \li Use context menu commands to apply effects to transitions,
- as described in \l{Applying Effects to Transitions}.
- \li Use the event list simulator to replace transition lines with connections to real
- signals from UI controls, as described in \l{Simulating Events}.
- \li Use \uicontrol {Flow Decision} components from \uicontrol Components > \uicontrol {Flow
- View} to set up alternative pathways between flow items, as described in
- \l{Simulating Conditions}.
- \li Use \l{Working with States}{states} in flows to modify the appearance
- of components on screens in response to user interaction, as
- described in \l{Applying States in Flows}.
- \li Use \uicontrol {Flow Wildcard} components from
- \uicontrol Components > \uicontrol {Flow View} to prioritize events
- from other applications and to stop some screens from appearing on
- others, as described in \l{Reacting to External Events}.
- \endlist
-*/
-
-/*!
- \page studio-flow-view.html
- \previouspage studio-app-flows.html
- \nextpage studio-flow-item.html
-
- \title Adding Flow Views
-
- 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} >
- \uicontrol {Qt Quick Files} > \uicontrol {Flow View}
- and follow the instructions of the wizard.
-
- \image studio-flow-view-create.png "Create Flow View wizard template"
-
- 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. For more information, see \l {Simulating Events}.
-
- 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
-
- You can specify basic properties for a \uicontrol {Flow View} component
- in the \l {Type}{Component}, \l {2D Geometry}{Geometry - 2D}, and
- \l Visibility sections in the \l Properties view. Specify flow view
- properties in the \uicontrol {Flow View} section.
-
- \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.
-
- Use the \l{Picking Colors}{color picker} to set colors for:
-
- \list
- \li Transition lines
- \li Area outlines
- \li Area fills
- \li Block items
- \endlist
-
- You can set some additional global properties for drawing transition lines:
-
- \image studio-flow-view-properties-transition.png "Flow View transition properties"
-
- \list
- \li In the \uicontrol {Type} field, select \uicontrol Bezier to draw
- transition lines as bezier curves.
- \li In the \uicontrol {Radius} field, specify the corner radius for
- default curves.
- \li In the \uicontrol {Bezier factor} field, specify the factor that
- modifies the positions of the control points used for bezier curves.
- \endlist
-
- For more information about changing the appearance of a particular action
- area or transition line, see \l{Flow Action Area Properties} and
- \l{Flow Transition Properties}.
-
- In the \uicontrol Advanced section, you can manage the more
- \l{Specifying Developer Properties}{advanced properties}
- of components.
-*/
-
-/*!
- \page studio-flow-item.html
- \previouspage studio-flow-view.html
- \nextpage studio-flow-action-area.html
-
- \title Adding Flow Items
-
- 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 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, 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.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 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:
-
- \list 1
- \li Select \uicontrol File > \uicontrol {New File} >
- \uicontrol {Qt Quick Files} >
- \uicontrol {Flow Item} and follow the instructions of the wizard
- 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 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
- the \uicontrol {2D} view or \uicontrol Navigator.
- \endlist
- \li In \l Properties, edit the properties of each flow item.
- \endlist
-
- 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
-
- You can specify basic properties for a \uicontrol {Flow Item} component
- in the \l {Type}{Component}, \l {2D Geometry}{Geometry - 2D}, and
- \l Visibility sections in the \uicontrol Properties view. Specify flow item
- properties in the \uicontrol {Flow Item} section.
-
- \image studio-flow-item-properties.png "Flow Item properties"
-
- The \uicontrol {State change target} and \uicontrol {Target state}
- properties are used to \l{Applying States in Flows}{apply states}
- in flows.
-
- 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} checkbox.
-
- 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} checkbox in the \uicontrol {Transition Lines}
- section.
-
- In the \uicontrol Advanced section, you can manage the more
- \l{Specifying Developer Properties}{advanced properties} of components.
-*/
-
-/*!
- \page studio-flow-action-area.html
- \previouspage studio-flow-item.html
- \nextpage studio-flow-effects.html
-
- \title Adding Action Areas and Transitions
-
- \e {Action areas} are clickable areas that initiate transitions between flow items or
- \l{Connecting and Releasing Signals}{create connections} to any signal from any component in a
- \l{Adding Flow Items}{flow item}. For example, you could connect an
- action to the \c onPressed signal of a button in your flow item to
- determine what should happen when users press the button.
-
- \image studio-flow-action-area.webp "Flow Action Area in the 2D view"
-
- Select the type of the mouse or touch input to use for triggering
- events, such as click, double-click, flick, pinch, or long press.
-
- Typically, a flow item is connected to several other flow items in the
- flow with two-way connections. To avoid clutter, set an action area
- as \e {go back} instead of adding explicit transition lines to and from
- every potentially connected flow item. When the \uicontrol {Go back} option
- is enabled, the transition will always take the user back to the previous
- flow item.
-
- You can specify the appearance of each action area or transition line,
- including the color, line thickness, dotted or solid lines, and even
- the curve of the transition lines. You can change some of these properties
- globally, as instructed in \l{Flow View Properties}.
-
- To create action areas:
-
- \list 1
- \li Select the flow item in the \l {2D} view, then right-click it, and select
- \uicontrol {Flow} > \uicontrol {Create Flow Action} in
- the context menu.
- \li Drag the action area to the UI control that you want to connect
- to the other flow item. For example, to a button that opens another
- flow item when clicked.
- \li Double-click the action area and drag the transition line to the flow item you want to
- connect to. Alternatively, select the action area, right-click it to open the
- context-menu, and then select \uicontrol Connect and the flow item from the list.
- \li In \l Properties, modify the properties of the action area
- and transition line.
- \endlist
-
- To preview the flow, select the
- \uicontrol {Live Preview} button on the top toolbar or press \key Alt +
- \key P.
-
- \section1 Common Properties
-
- Specify basic properties for \uicontrol {Flow Action Area}
- and \uicontrol {Flow Transition} components in the \l {Type}{Component},
- \l {2D Geometry}{Geometry - 2D}, and \l Visibility sections in the
- \uicontrol Properties view.
-
- Use \l{Setting Anchors and Margins}{anchors} in the \uicontrol Layout tab to position
- the component.
-
- Manage the more \l{Specifying Developer Properties}{advanced properties} of components
- in the \uicontrol Advanced section.
-
- \section1 Flow Action Area Properties
-
- Use the \l{Picking Colors}{color picker} in the \uicontrol {Flow Action Area} section
- to set line and fill color.
-
- \image studio-flow-action-area-properties.webp "Flow Action Area properties"
-
- Specify additional properties for action areas in the \uicontrol {Flow Action} and
- \uicontrol {Action Area} sections:
-
- \list
- \li Select the \uicontrol {Go back} checkbox to specify that the
- transition will always take the user back to the previous flow item.
- \li In the \uicontrol {Event IDs} field, specify the IDs of the
- events to connect to, such as mouse, touch or keyboard events.
- \li In the \uicontrol {Action type} field, select the type of the
- mouse or touch input to use for triggering events.
- \li In the \uicontrol {Line width} field, set the width of the
- action area outline.
- \li Select the \uicontrol {Dashed line} checkbox to draw a dashed
- action area outline.
- \li Select the \uicontrol Enabled checkbox to enable interaction
- with the action area during preview.
- \endlist
-
- \section1 Flow Transition Properties
-
- Specify additional properties for transitions between \l{Adding Flow Items}{flow items}
- in the \uicontrol Transition section:
-
- \image studio-flow-transition-properties.webp "Flow Transition properties"
-
- \list
- \li Select the \uicontrol Condition checkbox to activate the
- transition. Select \inlineimage icons/action-icon.png
- to \l{Adding Bindings Between Properties}{bind} a condition
- to the transition.
- \li In the \uicontrol Question field, enter the text that will appear
- next to the transition line. If the transition represents the
- connection to a \uicontrol {Flow Decision} component, the
- text will also be visible in the selection dialog that opens when
- the \l{Simulating Conditions}{condition} is triggered.
- \li In the \uicontrol {Event IDs} field, specify the IDs of the
- events to connect to, such as mouse, touch or keyboard events.
- \li In the \uicontrol From and \uicontrol To fields, select the
- flow item where the transition starts and the one where it
- ends.
- \endlist
-
- Specify the following properties to change the appearance of transition lines in
- the \uicontrol {2D} view:
-
- \image studio-flow-transition-line-properties.webp "Flow Transition Line properties"
-
- \list
- \li In the \uicontrol {Line width} field, set the width of the
- transition line.
- \li In the \uicontrol {Offset} and \uicontrol {Break offset} fields, set
- the start point (\uicontrol Out) or end point (\uicontrol In) of a
- transition line or a break to the specified offset. This enables
- you to move them up and down or left and right.
- \li Select the \uicontrol {Dashed line} checkbox to draw a dashed line.
- \li In the \uicontrol Type field, select \uicontrol Bezier to draw
- transition lines as bezier curves.
- \li In the \uicontrol Radius field, specify the corner radius for
- default curves.
- \li In the \uicontrol {Bezier factor} field, specify the factor that
- modifies the positions of the control points used for a bezier
- curve.
- \li In the \uicontrol {Label position} field, set the position of
- the value of the \uicontrol Question field in respect to the
- transition start point.
- \li Select the \uicontrol {Label flip side} checkbox to move the
- \uicontrol Question value to the opposite side of the transition
- line.
- \endlist
-
- \section1 Connecting and Releasing Signals
-
- To connect components to \l{Connecting Components to Signals}{signals}, export the
- components first as \l{Adding Property Aliases}{aliases} in \l Navigator. To create
- and release connections, select \uicontrol {Open Signal Dialog} in the context menu.
- The \uicontrol {Signal List} dialog displays the signals for all components.
-
- \image studio-flow-signal-list.webp "Signal List dialog"
-
- To connect a component to a signal, select \uicontrol Connect next to one
- in the list. To release a connected signal, select \uicontrol Release.
-*/
-
-/*!
- \page studio-flow-effects.html
- \previouspage studio-flow-action-area.html
- \nextpage studio-flow-events.html
-
- \title Applying Effects to Transitions
-
- You can apply effects, such as fade, move, or push, to
- \l{Adding Action Areas and Transitions}{transitions} between
- \l{Adding Flow Items}{flow items}. A fade effect makes the first
- flow item appear to fade out, while the next flow item fades in.
- A move effect makes the second flow item appear to move in over the
- first flow item. The push effect makes a flow item appear to push out the previous one.
- You can also use your own custom effects that you have created with some other tool.
-
- The transition direction determines the direction the new flow item appears
- from: left, right, top, bottom. You can set the duration of the effect and
- \l{Editing Easing Curves}{attach an easing curve} to the effect.
-
- To add effects:
-
- \list 1
- \li Select a transition line in the \l {2D} view.
- \li Right-click the transition line to open the context menu, select \uicontrol {Flow} >
- \uicontrol {Flow Effects}, and then select the effect to apply.
- \li In \l Properties, modify the properties of the effect.
- \endlist
-
- To edit effect properties later, select a transition, open the context menu, and then select
- \uicontrol {Flow} > \uicontrol {Select Effect}.
-
- To use your own custom effects, select a transition, open the context menu, and then select
- \uicontrol {Flow} > \uicontrol {Flow Effects} > \uicontrol {Assign Custom FlowEffect}.
- Then specify the path to your custom effect file.
-
- To remove the current effect from a transition, select a transition, open the context menu,
- and then select \uicontrol {Flow} > \uicontrol {Flow Effects} >
- \uicontrol {Assign FlowEffect None}.
-
- \section1 Flow Effect Properties
-
- Specify basic properties for a \uicontrol {Flow Effect} component in the \l Type and
- \l ID fields in the \uicontrol Component section in the \uicontrol Properties view.
-
- \image studio-flow-effect-properties.png "Flow Effect properties"
-
- Set the duration and easing curve of flow effects in the \uicontrol {Transition Effect}
- section:
-
- \list
- \li In the \uicontrol Duration field, specify the duration of the
- effect.
- \li Select the \inlineimage icons/curve_editor.png
- button to open \uicontrol {Easing Curve Editor} to attach an
- \l{Editing Easing Curves}{easing curve} to the effect.
- \endlist
-
- Set some additional properties for a move or push effect in the \uicontrol {Push Effect}
- or \uicontrol {Move Effect} section:
-
- \image studio-flow-effect-push-properties.png "Flow Push Effect properties"
-
- \list
- \li In the \uicontrol Direction field, specify the direction that
- the target \uicontrol {Flow Item} appears from: left, right, top,
- or bottom.
- \li In the \uicontrol Scale field, set scaling for the effect.
- \li In the \uicontrol {Incoming opacity} and
- \uicontrol {Outgoing opacity} fields, specify the opacity of
- the effect as a number between 0 and 1.
- \li Select the \uicontrol Reveal checkbox to reveal the
- \uicontrol {Flow Item} where the transition starts.
- \endlist
-*/
-
-/*!
- \page studio-flow-events.html
- \previouspage studio-flow-effects.html
- \nextpage studio-flow-conditions.html
-
- \title Simulating Events
-
- While \l{Adding Action Areas and Transitions}{transition lines}
- are useful for prototyping, in production you need to use the real
- \l{Connecting and Releasing Signals}{signals} from UI
- \l{glossary-component}{components} to control the flow of the application.
- For this purpose, you can use action areas in a more advanced way, by
- having them listen to signals from flow items or the controls in them and
- by connecting these to the \l{Adding Flow Views}{flow view}. You can use
- keyboard shortcuts to simulate these events when you preview the UI.
-
- When you use the wizard to create a \uicontrol {Flow View} component, select
- the \uicontrol {Use event simulator} checkbox to add an event simulator to
- the flow view.
-
- You can create an event list where you assign keyboard shortcuts to events,
- and then use context-menu commands to attach the events to action areas or
- transition lines.
-
- \section1 Creating Event Lists
-
- To create an event list:
-
- \list 1
- \li Right-click in the \uicontrol 2D or \uicontrol Navigator view and select
- \uicontrol {Event List} > \uicontrol {Show Event List}.
- \li In the \uicontrol {Event List} dialog, select \inlineimage icons/plus.png
- to add a keyboard shortcut for triggering an event to the list.
- \image studio-flow-event-list.png "Event List dialog"
- \li In the \uicontrol {Event ID} field, enter an identifier for the event. To search
- for existing events, enter search criteria in the \uicontrol Filter field.
- \li In the \uicontrol Description field, describe the keyboard shortcut.
- \li In the \uicontrol Shortcut field, press the keyboard key that will
- trigger the event, and then select \uicontrol R to record the
- keyboard shortcut. The key identifier appears in the field.
- \endlist
-
- You can now assign the events to action areas and transitions.
-
- \section1 Assigning Events to Actions
-
- To assign events to actions:
-
- \list 1
- \li Select \uicontrol eventListSimulator in \uicontrol Navigator, and in
- \uicontrol Properties > \uicontrol {Exposed Custom Properties}, select the
- \uicontrol active checkbox. If \uicontrol eventListSimulator is not visible
- in the \uicontrol Navigator, select \inlineimage icons/visibilityon.png.
- \li In \uicontrol Navigator, select an action area or transition line.
- \li In the context menu, select \uicontrol {Event List} >
- \uicontrol {Assign Events to Actions}.
- \image studio-flow-events-assign.webp "Assign Events to Actions dialog"
- \li To connect an event, select \uicontrol Connect next to an event in
- the list. To release a connected event, select \uicontrol Release.
- \li Press \key {Alt+P} to preview the UI.
- \li Select action areas in the preview, double-click events in the
- event list, or use the keyboard shortcuts to trigger events.
- \image studio-flow-events-event-list.webp "Event list in Live Preview"
- \endlist
-
-*/
-
-/*!
- \page studio-flow-conditions.html
- \previouspage studio-flow-events.html
- \nextpage studio-flow-states.html
-
- \title Simulating Conditions
-
- Part of any complex UI is the conditional logic it uses to present its
- state to users or to collect and process data from various sources. Data
- can be produced by user interaction from a variety of inputs, such as
- buttons and controls, sensor readings from arrays of equipment, or general
- values received from backend or service APIs.
-
- The \uicontrol {Flow Decision} component simulates conditions by displaying a
- list of options you can choose from when you preview the flow. This enables
- you to prototype complex interactions before you have access to the physical
- controls, backend, or sensor data that will be required for the production
- version.
-
- \image studio-flow-decision.webp "Flow Decision in the 2D view"
-
- To simulate conditions:
-
- \list 1
- \li Drag a \uicontrol {Flow Decision} component from
- \uicontrol Components > \uicontrol {Flow View} to a
- \l{Adding Flow Views}{flow view} in the \l Navigator or \l {2D} view.
- \li Select the flow item where you want the application to start in
- the \uicontrol Navigator or \uicontrol {2D} view. Then right-click the component
- to open the context menu, and select \uicontrol Flow > \uicontrol {Set Flow Start}.
- \li Create an \l{Adding Action Areas and Transitions}{action area} for
- the component that will trigger the condition and connect it to the
- flow decision.
- \li Select the flow decision, and then select \uicontrol Connect in the
- context menu to create connections to the flow items that will open
- depending on whether the condition is met.
- \li In the \l Properties view, \uicontrol {Dialog title} field, enter a
- title for the selection dialog that opens when the condition is
- triggered.
- \li Select a transition line in the \uicontrol Navigator or
- \uicontrol {2D} view, and add a descriptive text in the
- \uicontrol {Question} field in \uicontrol Properties to represent
- a choice in the selection dialog.
- \image studio-flow-transition-properties-question.webp "Flow Transition properties"
- \li Press \key {Alt+P} to preview the UI.
- \li Select action areas in the preview, double-click events in the
- event list, or use the keyboard shortcuts to trigger events.
- \endlist
-
- Flow decisions are listed in a dialog where you can select which condition
- is met to see the results.
-
- \image studio-flow-decision-preview.webp "Selection dialog for flow decision"
-
- \section1 Flow Decision Properties
-
- Specify basic properties for a \uicontrol {Flow Decision} component
- in the \l Type and \l ID fields in the \uicontrol Component section in the
- \uicontrol Properties view. Specify properties for flow decisions in the
- \uicontrol {Flow Decision} section.
-
- \image studio-flow-decision-properties.webp "Flow Decision properties"
-
- In the \uicontrol {Dialog title} field, enter a title for the selection
- dialog that opens when the condition is triggered.
-
- Specify the following properties to change the appearance of the
- flow decision icon \inlineimage icons/flow-decision-icon.png
- :
-
- \list
- \li Select \inlineimage icons/visibility-off.png
- to display the ID of the \uicontrol {Flow Decision}
- component in the \l {2D} view.
- \li In the \uicontrol {Label position} field, select the corner of
- the flow decision icon to place the label in.
- \li Use the \l{Picking Colors}{color picker} to set \uicontrol {Outline color} and
- \uicontrol {Fill color} of the flow decision icon.
- \li In the \uicontrol Size field, specify the size of the flow
- decision icon.
- \li In the \uicontrol Radius field, specify the radius of the flow
- decision icon corners.
- \endlist
-
-*/
-
-/*!
- \page studio-flow-states.html
- \previouspage studio-flow-conditions.html
- \nextpage studio-flow-external-events.html
-
- \title Applying States in Flows
-
- Use \l{Working with States}{states} in flows to modify how the \l{glossary-component}
- {component} properties change in flow items. For this purpose, use the \uicontrol {Flow Item}
- component available in \uicontrol Components > \uicontrol {Flow View}.
-
- To apply states in flows:
-
- \list 1
- \li Select \uicontrol File > \uicontrol {New File} >
- \uicontrol {Qt Quick Files} >
- \uicontrol {Flow Item} to create a flow item.
- \li In the \l States view, add states to the flow item.
- \li In the \l Projects view, open the .ui.qml file that contains the \l{Adding Flow Views}
- {flow view}, and drag the flow item from \uicontrol Components >
- \uicontrol {My Components} to the flow view in the \l Navigator or \l 2D view.
- \li From \uicontrol Components > \uicontrol {Flow View}, drag an empty
- \uicontrol {Flow Item} component (1) to the flow view for each state that you added.
- \image studio-flow-item-component.webp "Flow Item in the Components view."
- \li In the \uicontrol Navigator or \uicontrol 2D view, select an empty
- \uicontrol {Flow Item} to open the \l Properties view.
- \li In the \uicontrol {State change target} field, select the flow item that you created
- using the wizard.
- \li In the \uicontrol {Target state} field, select the state to apply to the flow item.
- \image studio-flow-states-item-properties.webp "Flow Item properties"
- \endlist
-
- To apply the different states to your application flow, add
- \l{Adding Action Areas and Transitions}{action areas} and
- \l{Simulating Conditions}{flow decisions} to the flow items.
-*/
-
-/*!
- \page studio-flow-external-events.html
- \previouspage studio-flow-states.html
- \nextpage quick-components.html
-
- \title Reacting to External Events
-
- On mobile and embedded platforms, applications are usually integrated into
- the platform and therefore screens might pop-up from anywhere or at any
- time, based on a conditional event. For example, push notifications
- appear on mobile devices and incoming call screens on a car's HMI.
-
- Use the \uicontrol {Flow Wildcard} component to model this type of
- screens in your \l{Adding Flow Views}{flow view} using real or simulated events.
- Add \l{Adding Flow Items}{flow items} to an \uicontrol {Allow
- list} to prioritize them or to a \uicontrol {Block list} to stop some screens from
- appearing on others. For example, you could block the incoming call screen
- from appearing on a warning screen for the engine if you consider the
- warning more important.
-
- To use wildcards:
-
- \list 1
- \li Drag a \uicontrol {Flow Wildcard} component from
- \uicontrol Components > \uicontrol {Flow View} to the \l {2D} view.
- \li To connect the wildcard to a flow item with a \l{Adding Action Areas and Transitions}
- {transition line}, double-click the wildcard and drag the transition line to the flow
- item.
- \li To add logic to the \uicontrol {Flow Wildcard} component, use
- \l{Simulating Events}{events}, \l{Simulating Conditions}{Flow Decision} components,
- or \l{Connecting and Releasing Signals}{signals}.
- \li To manage the priority of your flow items, add flow items to
- \uicontrol {Allow list} or \uicontrol {Block list} in \l Properties.
- \image studio-flow-wildcard.webp "The wildcard component in 2D view."
- \endlist
-
- \section1 Flow Wildcard Properties
-
- Specify basic properties for a \uicontrol {Flow Wildcard} component
- in the \l Type and \l ID fields in the \uicontrol Component section in the
- \uicontrol Properties view. Specify properties for flow wildcards in the
- \uicontrol {Flow Wildcard} section.
-
- \image studio-flow-wildcard-properties.webp "Flow Wildcard properties"
-
- In the \uicontrol {Event IDs} field, specify the IDs of the events to
- connect to, such as mouse, touch or keyboard events.
-
- Select the \uicontrol {Global wildcard} checkbox to enable triggering
- the wildcard from several flows.
-
- To give flow items high priority, select them in the
- \uicontrol {Allow list} field. To block flow items,
- select them in the \uicontrol {Block list} field.
-
- Specify the following properties to change the appearance of the
- wildcard icon \inlineimage icons/flow-wildcard-icon.png:
-
- \list
- \li To set the outline and fill color of the wildcard icon, use the
- \l{Picking Colors}{color picker}.
- \li In the \uicontrol Size field, specify the size of the wildcard icon.
- \li In the \uicontrol Radius field, specify the radius of the wildcard
- icon corners.
- \endlist
-
-*/
diff --git a/doc/qtdesignstudio/src/qtdesignstudio-projects.qdoc b/doc/qtdesignstudio/src/qtdesignstudio-projects.qdoc
index 02a82d02031..c65469d8cd0 100644
--- a/doc/qtdesignstudio/src/qtdesignstudio-projects.qdoc
+++ b/doc/qtdesignstudio/src/qtdesignstudio-projects.qdoc
@@ -247,11 +247,7 @@
\li Wizard Template
\li Purpose
\row
- \li {1,5} Qt Quick Files
- \li Flow Item and Flow View
- \li Generate components that you can use to design the
- \l{Designing Application Flows}{application flow}.
- \row
+ \li {1,4} Qt Quick Files
\li Qt Quick File
\li Generates a component with one of the following default components
or \l{Using Positioners}{positioners} as the root component:
diff --git a/doc/qtdesignstudio/src/qtdesignstudio-toc.qdoc b/doc/qtdesignstudio/src/qtdesignstudio-toc.qdoc
index 9000fbb2f5a..8cf7f393684 100644
--- a/doc/qtdesignstudio/src/qtdesignstudio-toc.qdoc
+++ b/doc/qtdesignstudio/src/qtdesignstudio-toc.qdoc
@@ -29,7 +29,6 @@
\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{Projects}
@@ -53,17 +52,6 @@
\endlist
\li \l{Wireframing}
\list
- \li \l{Designing Application Flows}
- \list
- \li \l{Adding Flow Views}
- \li \l{Adding Flow Items}
- \li \l{Adding Action Areas and Transitions}
- \li \l{Applying Effects to Transitions}
- \li \l{Simulating Events}
- \li \l{Simulating Conditions}
- \li \l{Applying States in Flows}
- \li \l{Reacting to External Events}
- \endlist
\li \l {Using Components}
\list
\li \l{Preset Components}
@@ -134,7 +122,6 @@
\li\l{Connecting Components to Signals}
\li\l{Adding Bindings Between Properties}
\li\l{Specifying Custom Properties}
- \li\l{Connecting Properties to JSON Data Source}
\endlist
\li \l{Working with States}
\endlist
diff --git a/doc/qtdesignstudio/src/qtdesignstudio.qdoc b/doc/qtdesignstudio/src/qtdesignstudio.qdoc
index e90e733c631..cedc8b80460 100644
--- a/doc/qtdesignstudio/src/qtdesignstudio.qdoc
+++ b/doc/qtdesignstudio/src/qtdesignstudio.qdoc
@@ -48,8 +48,8 @@
click-through mockup. Test, preview, and fine-tune your designs to pixel-perfection,
live on target devices.
- A single unified framework, one common language, fewer feedback loops, and faster iterations,
- \QDS closes the gap between designers and developers.
+ With a single unified framework, one common language, fewer feedback loops, and faster
+ iterations, \QDS closes the gap between designers and developers.
\b {LEARN MORE}
@@ -87,11 +87,11 @@
\endlist
\li Online Courses
\list
- \li \l{https://qurious.qt.io/enrollments/197683855/details}{Getting Started}
- \li \l{https://qurious.qt.io/catalog/courses/3910783}{Creating Your First App}
- \li \l{https://qurious.qt.io/enrollments/154647839/details}{Introduction to 2D UI Design}
- \li \l{https://qurious.qt.io/enrollments/167005403/details}{Introduction to 3D Design}
- \li \l{https://qurious.qt.io/catalog/courses/3910791}{Using Qt Bridge for Figma}
+ \li \l{https://www.qt.io/academy/course-catalog#getting-started-with-qt-design-studio}{Getting Started}
+ \li \l{https://www.qt.io/academy/course-catalog#creating-your-first-app-with-qt-design-studio}{Creating Your First App}
+ \li \l{https://www.qt.io/academy/course-catalog#2d-with-qt-design-studio}{2D with Qt Design Studio}
+ \li \l{https://www.qt.io/academy/course-catalog#3d-with-qt-design-studio}{3D with Qt Design Studio}
+ \li \l{https://www.qt.io/academy/course-catalog#qt-design-studio:-blur-effect}{Creating a Blur Effect}
\endlist
\endtable
\enddiv
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 5cf2370cc98..56a2a803705 100644
--- a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-repeater-3d.qdoc
+++ b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-repeater-3d.qdoc
@@ -96,44 +96,75 @@
\endlist
\image repeater3d-numeric-model.webp
- \section1 Adding a Repeater3D Component with a Model
+ \section1 Adding a Repeater3D Component with a List Model
This section explains how to add a \uicontrol Repeater3D component with
- a model to your \QDS project:
+ a list 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 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
-
-
- name (String) |
- radius (Real) |
-
-
- Mars |
- 3.39 |
-
-
- Earth |
- 6.37 |
-
-
- Venus |
- 6.05 |
-
-
- \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}.
+ \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.
\endlist
+ \code qml
+ Repeater3D {
+ id: repeater3D
+ model: planetModel
+ }
+ \endcode
+
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, you are using a \uicontrol Sphere.
@@ -147,7 +178,7 @@
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 model for each of the sphere
+ scale to the radius value defined in the list model for each of the sphere
instances.
\image repeater3d-radius-binding.png
\li Select \uicontrol OK.
@@ -170,6 +201,6 @@
result. You need to zoom out to see all the spheres.
\endlist
- \image repeater3d-list-model.webp
+ \image repeater3d-list-model.webp "Spheres in Repeater3D with a ListModel"
*/
diff --git a/doc/qtdesignstudio/src/views/qtquick-connection-editor-json.qdoc b/doc/qtdesignstudio/src/views/qtquick-connection-editor-json.qdoc
deleted file mode 100644
index 8b7451b3aa3..00000000000
--- a/doc/qtdesignstudio/src/views/qtquick-connection-editor-json.qdoc
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (C) 2024 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
-
-/*!
- \page quick-json-data-properties.html
- \previouspage quick-dynamic-properties.html
- \nextpage quick-states.html
-
- \title Connecting Properties to JSON Data Source
-
- Connect properties to data from a JSON file. You need two files in your project to do this:
-
- \table
- \row
- \li \c {data.json}
- \li A data file.
- \row
- \li \c {JsonData.qml}
- \li A singleton that reads data from \c {data.json}.
- \endtable
-
- To create these files, you need to create a new data model:
-
- \list 1
- \li In \uicontrol {Model Editor}, select \inlineimage {icons/zoomIn.png}.
- \li Select \uicontrol{Create}.
- \endlist
-
- The files are created in the \e {/imports//} folder of the project.
-
- \section1 Connecting a Text Property to a Data Source
-
- To connect a text property to a corresponding field in a JSON file:
-
- \list 1
- \li In the \uicontrol Navigator or \uicontrol 2D view, select a component
- that has a text property, for example, a text field.
- \li In the \uicontrol Connections view, go to the \uicontrol Bindings
- tab.
- \li Select \inlineimage {icons/plus.png}.
- \li In the first \uicontrol From field, select \uicontrol {DataStore}, and in the second field,
- select the JSON entry you want to use. In this example, \uicontrol {backend.name} is
- selected. This corresponds to the \e name entry in \c {data.json}.
- \li In the \uicontrol To field, ensure that \uicontrol text is selected.
- \image json-text-binding.webp
- \endlist
-
- Now, the text field is populated with data from the JSON file.
-
- \section1 Adding Data Fields to the JSON File
-
- If you add data fields to the JSON file, you need to manually do the same
- updates to \c {JsonData.qml}.
-
- \list 1
- \li Go to the \uicontrol Projects view and open \c {JsonData.qml}.
- \image project-jasondata.webp
- \li In the \uicontrol Properties view, create a new local custom property.
- \image json-new-property.webp
- \li Ensure that the name of the property matches the data entry in the JSON file.
- \endlist
-
-*/
diff --git a/doc/qtdesignstudio/src/views/qtquick-connection-editor.qdoc b/doc/qtdesignstudio/src/views/qtquick-connection-editor.qdoc
index 586098ffca8..bd976fbfd54 100644
--- a/doc/qtdesignstudio/src/views/qtquick-connection-editor.qdoc
+++ b/doc/qtdesignstudio/src/views/qtquick-connection-editor.qdoc
@@ -32,11 +32,6 @@
can specify values for. You can add custom properties that would
not otherwise exist for a particular \l{Component Types}
{component type} or your custom components.
-
- \li \l{Connecting Properties to JSON Data Source}
-
- You can add bindings between properties and data from a JSON file.
-
\endlist
For an example of using properties, bindings, and connections to create a
diff --git a/doc/qtdesignstudio/src/views/studio-model-editor.qdoc b/doc/qtdesignstudio/src/views/studio-model-editor.qdoc
deleted file mode 100644
index 0caebcfb493..00000000000
--- a/doc/qtdesignstudio/src/views/studio-model-editor.qdoc
+++ /dev/null
@@ -1,62 +0,0 @@
-// 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 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/whats new/qds-releases.qdoc b/doc/qtdesignstudio/src/whats new/qds-releases.qdoc
index ee792775f82..c21baef03ba 100644
--- a/doc/qtdesignstudio/src/whats new/qds-releases.qdoc
+++ b/doc/qtdesignstudio/src/whats new/qds-releases.qdoc
@@ -14,6 +14,7 @@
\section2 \QDS 4
\list
+ \li \l{Qt Design Studio 4.6 released}
\li \l{Qt Design Studio 4.5.1 released}
\li \l{Qt Design Studio 4.5 released}
\li \l{Qt Design Studio 4.4 released}
diff --git a/share/qtcreator/qmldesigner/assetsLibraryQmlSources/Assets.qml b/share/qtcreator/qmldesigner/assetsLibraryQmlSources/Assets.qml
index 0514f3dfaef..60beacfe6e2 100644
--- a/share/qtcreator/qmldesigner/assetsLibraryQmlSources/Assets.qml
+++ b/share/qtcreator/qmldesigner/assetsLibraryQmlSources/Assets.qml
@@ -101,7 +101,7 @@ Item {
anchors.fill: parent
acceptedButtons: Qt.RightButton
onClicked: {
- if (assetsModel.hasFiles) {
+ if (!assetsModel.isEmpty) {
function onFolderCreated(path) {
assetsView.addCreatedFolder(path)
}
@@ -189,13 +189,13 @@ Item {
leftPadding: 10
color: StudioTheme.Values.themeTextColor
font.pixelSize: StudioTheme.Values.baseFont
- visible: !assetsModel.hasFiles && !root.__searchBoxEmpty
+ visible: assetsModel.isEmpty && !root.__searchBoxEmpty
}
Item { // placeholder when the assets library is empty
width: parent.width
height: parent.height - toolbar.height - column.spacing
- visible: !assetsModel.hasFiles && root.__searchBoxEmpty
+ visible: assetsModel.isEmpty && 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 40cdac85bbb..08f6c0a990f 100644
--- a/share/qtcreator/qmldesigner/assetsLibraryQmlSources/AssetsContextMenu.qml
+++ b/share/qtcreator/qmldesigner/assetsLibraryQmlSources/AssetsContextMenu.qml
@@ -192,7 +192,7 @@ StudioControls.Menu {
StudioControls.MenuItem {
text: qsTr("New Folder")
- visible: root.assetsModel.hasFiles
+ visible: !root.assetsModel.isEmpty
height: visible ? implicitHeight : 0
NewFolderDialog {
diff --git a/share/qtcreator/qmldesigner/assetsLibraryQmlSources/AssetsView.qml b/share/qtcreator/qmldesigner/assetsLibraryQmlSources/AssetsView.qml
index 307d3637521..df45bc32487 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.hasFiles ||
- root.rows <= root.rootPathRow + 1 && assetsModel.hasFiles) {
- assetsModel.syncHasFiles()
+ if (root.rows > root.rootPathRow + 1 && assetsModel.isEmpty ||
+ root.rows <= root.rootPathRow + 1 && !assetsModel.isEmpty) {
+ assetsModel.syncIsEmpty()
}
root.updateRows()
@@ -328,7 +328,7 @@ TreeView {
function moveSelection(amount)
{
- if (!assetsModel.hasFiles || !amount)
+ if (assetsModel.isEmpty || !amount)
return
let index = root.currentFilePath ? assetsModel.indexForPath(root.currentFilePath)
diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterialsView.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterialsView.qml
index c7b2f5a0822..8cfabf06d22 100644
--- a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterialsView.qml
+++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterialsView.qml
@@ -133,6 +133,8 @@ HelperWidgets.ScrollView {
topPadding: 10
leftPadding: 10
visible: root.materialsModel.isEmpty
+ wrapMode: Text.WordWrap
+ width: root.width - x
}
}
}
diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTabBar.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTabBar.qml
index ca8fb64eccf..a0942bc64a6 100644
--- a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTabBar.qml
+++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTabBar.qml
@@ -2,11 +2,12 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
+import QtQuick.Layouts
import HelperWidgets 2.0 as HelperWidgets
import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme
-Row {
+RowLayout {
id: root
property int currIndex: 0
@@ -24,6 +25,7 @@ Row {
icon: modelData.icon
selected: root.currIndex === index
onClicked: root.currIndex = index
+ Layout.fillWidth: true
}
}
}
diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTabButton.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTabButton.qml
index 587f846a10b..cc8efbf7168 100644
--- a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTabButton.qml
+++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTabButton.qml
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
+import QtQuick.Controls
import HelperWidgets 2.0 as HelperWidgets
import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme
@@ -16,7 +17,6 @@ Rectangle {
property bool selected: false
height: button.height
- width: button.width + label.width + contentRow.spacing + 6
color: StudioTheme.Values.themeToolbarBackground
radius: StudioTheme.Values.smallRadius
@@ -43,9 +43,9 @@ Rectangle {
color: StudioTheme.Values.themeTextColor
text: qsTr("Materials")
font.pixelSize: StudioTheme.Values.baseFontSize
- horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
+ width: root.width - x
}
}
@@ -56,6 +56,12 @@ Rectangle {
onClicked: root.clicked()
}
+ StudioControls.ToolTip {
+ visible: mouseArea.containsMouse
+ text: label.text
+ delay: 1000
+ }
+
states: [
State {
name: "default"
diff --git a/share/qtcreator/qmldesigner/designericons.json b/share/qtcreator/qmldesigner/designericons.json
index 005494b4715..f4f60b7412c 100644
--- a/share/qtcreator/qmldesigner/designericons.json
+++ b/share/qtcreator/qmldesigner/designericons.json
@@ -241,6 +241,9 @@
"LocalOrientIcon": {
"iconName": "localOrient_medium"
},
+ "LiveUpdateIcon": {
+ "iconName": "restartParticles_medium"
+ },
"MoveToolIcon": {
"iconName": "move_medium"
},
@@ -276,6 +279,9 @@
"SplitViewIcon": {
"iconName": "splitScreen_medium"
},
+ "SyncIcon": {
+ "iconName": "updateContent_medium"
+ },
"ToggleGroupIcon": {
"Off": {
"iconName": "selectOutline_medium"
diff --git a/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectComposer.qml b/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectComposer.qml
index 16525678be8..81c01d5f54e 100644
--- a/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectComposer.qml
+++ b/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectComposer.qml
@@ -195,6 +195,10 @@ Item {
onAssignToSelectedClicked: {
root.backendModel.assignToSelected()
}
+
+ onOpenShadersCodeEditor: {
+ root.backendModel.openMainShadersCodeEditor()
+ }
}
SplitView {
@@ -366,6 +370,8 @@ Item {
expanded = wasExpanded
dragAnimation.enabled = true
}
+
+ onOpenShadersCodeEditor: (idx) => root.backendModel.openShadersCodeEditor(idx)
}
} // Repeater
} // Column
diff --git a/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectComposerTopBar.qml b/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectComposerTopBar.qml
index 799dbeeddc3..c6e8abe11a3 100644
--- a/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectComposerTopBar.qml
+++ b/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectComposerTopBar.qml
@@ -19,6 +19,7 @@ Rectangle {
signal saveClicked
signal saveAsClicked
signal assignToSelectedClicked
+ signal openShadersCodeEditor
Row {
spacing: 5
@@ -48,12 +49,24 @@ 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.currentComposition !== ""
+ enabled: root.backendModel ? root.backendModel.isEnabled
+ && root.backendModel.currentComposition !== ""
: false
onClicked: root.saveAsClicked()
}
+ HelperWidgets.AbstractButton {
+ style: StudioTheme.Values.viewBarButtonStyle
+ buttonIcon: StudioTheme.Constants.codeEditor_medium
+ tooltip: qsTr("Open Code")
+ enabled: root.backendModel ? root.backendModel.isEnabled
+ && root.backendModel.currentComposition !== ""
+ : false
+
+ onClicked: root.openShadersCodeEditor()
+ }
+
HelperWidgets.AbstractButton {
style: StudioTheme.Values.viewBarButtonStyle
buttonIcon: StudioTheme.Constants.assignTo_medium
diff --git a/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectCompositionNode.qml b/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectCompositionNode.qml
index a606461b5c5..ef59468ed60 100644
--- a/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectCompositionNode.qml
+++ b/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectCompositionNode.qml
@@ -30,10 +30,34 @@ HelperWidgets.Section {
eyeEnabled: nodeEnabled
eyeButtonToolTip: qsTr("Enable/Disable Node")
+ signal openShadersCodeEditor(index: int)
+
onEyeButtonClicked: {
nodeEnabled = root.eyeEnabled
}
+ icons: HelperWidgets.IconButton {
+ icon: StudioTheme.Constants.codeEditor_medium
+ transparentBg: true
+ buttonSize: 21
+ iconSize: StudioTheme.Values.smallIconFontSize
+ iconColor: StudioTheme.Values.themeTextColor
+ iconScale: containsMouse ? 1.2 : 1
+ implicitWidth: width
+ onClicked: root.openShadersCodeEditor(index)
+ }
+
+ content: Label {
+ text: root.caption
+ color: root.labelColor
+ elide: Text.ElideRight
+ font.pixelSize: root.sectionFontSize
+ font.capitalization: root.labelCapitalization
+ anchors.verticalCenter: parent?.verticalCenter
+ textFormat: Text.RichText
+ leftPadding: StudioTheme.Values.toolbarSpacing
+ }
+
Column {
spacing: 10
diff --git a/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectNode.qml b/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectNode.qml
index dd361b08d73..130208253c6 100644
--- a/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectNode.qml
+++ b/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectNode.qml
@@ -3,6 +3,7 @@
import QtQuick
import QtQuick.Controls
+import QtQuick.Controls.impl
import HelperWidgets
import StudioControls as StudioControls
import StudioTheme as StudioTheme
diff --git a/share/qtcreator/qmldesigner/effectComposerQmlSources/PreviewImagesComboBox.qml b/share/qtcreator/qmldesigner/effectComposerQmlSources/PreviewImagesComboBox.qml
index 201fab9699d..b75a04001e8 100644
--- a/share/qtcreator/qmldesigner/effectComposerQmlSources/PreviewImagesComboBox.qml
+++ b/share/qtcreator/qmldesigner/effectComposerQmlSources/PreviewImagesComboBox.qml
@@ -22,12 +22,17 @@ StudioControls.ComboBox {
required property Item mainRoot
- property var images: ["images/preview0.png",
- "images/preview1.png",
- "images/preview2.png",
- "images/preview3.png",
- "images/preview4.png"]
- property string selectedImage: images[0]
+ property var images: [Qt.url(""),
+ Qt.url("images/preview0.png"),
+ Qt.url("images/preview1.png"),
+ Qt.url("images/preview2.png"),
+ Qt.url("images/preview3.png"),
+ Qt.url("images/preview4.png")]
+ property url selectedImage: EffectComposerBackend.effectComposerModel.currentPreviewImage != Qt.url("")
+ ? EffectComposerBackend.effectComposerModel.currentPreviewImage
+ : images[1]
+
+ Component.onCompleted: EffectComposerBackend.effectComposerModel.currentPreviewImage = images[1]
readonly property int popupHeight: Math.min(800, col.height + 2)
@@ -122,45 +127,80 @@ StudioControls.ComboBox {
border.width: 1
focus: true
- HelperWidgets.ScrollView {
+ Column {
anchors.fill: parent
- anchors.margins: 1
- clip: true
- Column {
- id: col
+ Item {
+ id: setCustomItem
+ width: parent.width
+ height: 50
- padding: 10
- spacing: 10
+ HelperWidgets.Button {
+ anchors.fill: parent
+ anchors.bottomMargin: 2
+ anchors.topMargin: col.padding
+ anchors.leftMargin: col.padding
+ anchors.rightMargin: col.padding
+ text: qsTr("Set Custom Image")
+ onClicked: {
+ EffectComposerBackend.effectComposerModel.chooseCustomPreviewImage()
+ root.popup.close()
+ }
+ }
+ }
- Repeater {
- model: root.images
- Rectangle {
- required property int index
- required property var modelData
+ HelperWidgets.ScrollView {
+ width: parent.width - 2
+ height: parent.height - setCustomItem.height
- color: "transparent"
- border.color: root.selectedImage === modelData ? StudioTheme.Values.themeInteraction
- : "transparent"
+ clip: true
- width: 200
- height: 200
+ Column {
+ id: col
- Image {
- source: modelData
- anchors.fill: parent
- fillMode: Image.PreserveAspectFit
- smooth: true
- anchors.margins: 1
- }
+ padding: 10
+ spacing: 10
- MouseArea {
- anchors.fill: parent
+ Repeater {
+ model: root.images
- onClicked: {
- root.selectedImage = root.images[index]
- root.popup.close()
+ Rectangle {
+ required property int index
+ required property var modelData
+
+ color: "transparent"
+ border.color: root.selectedImage === modelData ? StudioTheme.Values.themeInteraction
+ : "transparent"
+
+ width: 200
+ height: 200
+ visible: index > 0
+ || EffectComposerBackend.effectComposerModel.customPreviewImage !== Qt.url("")
+
+ Image {
+ source: index > 0
+ ? parent.modelData
+ : EffectComposerBackend.effectComposerModel.customPreviewImage
+ anchors.fill: parent
+ fillMode: Image.PreserveAspectFit
+ smooth: true
+ anchors.margins: 1
+ }
+
+ MouseArea {
+ anchors.fill: parent
+
+ onClicked: {
+ if (parent.index > 0) {
+ EffectComposerBackend.effectComposerModel.currentPreviewImage
+ = root.images[index]
+ } else {
+ EffectComposerBackend.effectComposerModel.currentPreviewImage
+ = EffectComposerBackend.effectComposerModel.customPreviewImage
+ }
+ root.popup.close()
+ }
}
}
}
diff --git a/share/qtcreator/qmldesigner/newprojectdialog/imports/NewProjectDialog/Details.qml b/share/qtcreator/qmldesigner/newprojectdialog/imports/NewProjectDialog/Details.qml
index f905191eff9..ccad08f738a 100644
--- a/share/qtcreator/qmldesigner/newprojectdialog/imports/NewProjectDialog/Details.qml
+++ b/share/qtcreator/qmldesigner/newprojectdialog/imports/NewProjectDialog/Details.qml
@@ -391,6 +391,21 @@ Item {
visible: BackendApi.haveVirtualKeyboard
}
+ StudioControls.CheckBox {
+ id: enableCMakeGeneration
+ actionIndicatorVisible: false
+ text: qsTr("Enable Cmake Generation")
+ font.pixelSize: DialogValues.defaultPixelSize
+ checked: BackendApi.enableCMakeGeneration
+ visible: BackendApi.hasCMakeGeneration
+ }
+
+ Binding {
+ target: BackendApi
+ property: "enableCMakeGeneration"
+ value: enableCMakeGeneration.checked
+ }
+
RowLayout { // Target Qt Version
width: parent.width
visible: BackendApi.haveTargetQtVersion
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml
index 245b8506a28..232574a2207 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml
@@ -39,6 +39,8 @@ Item {
textFormat: Text.RichText
}
+ property Item icons
+
property int leftPadding: StudioTheme.Values.sectionLeftPadding
property int rightPadding: 0
property int topPadding: StudioTheme.Values.sectionHeadSpacerHeight
@@ -214,6 +216,13 @@ Item {
}
}
+ Item {
+ id: iconsContent
+ height: header.height
+ children: [ section.icons ]
+ Layout.preferredWidth: childrenRect.width
+ }
+
IconButton {
id: arrow
icon: StudioTheme.Constants.sectionToggle
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 afb00fa253c..ae3dfe5a4ab 100644
--- a/share/qtcreator/qmldesigner/studio_templates/projects/application-3d/wizard.json
+++ b/share/qtcreator/qmldesigner/studio_templates/projects/application-3d/wizard.json
@@ -32,6 +32,7 @@
{ "key": "ScreenWidth", "value": "%{JS: value('UseStandardResolution') === 'true' ? %{ScreenFactor}.ScreenWidth : value('CustomScreenWidth')}" },
{ "key": "ScreenHeight", "value": "%{JS: value('UseStandardResolution') === 'true' ? %{ScreenFactor}.ScreenHeight : value('CustomScreenHeight')}" },
{ "key": "UseVirtualKeyboardDefault", "value": "%{JS: false}" },
+ { "key": "EnableCMakeGenerationDefault", "value": "%{JS: true}" },
{ "key": "QtQuick3DVersion", "value": "%{JS: %{TargetQtVersion}.TargetQuick3DVersion}" }
],
@@ -208,6 +209,15 @@
"checked": "%{UseVirtualKeyboardDefault}"
}
},
+ {
+ "name": "EnableCMakeGeneration",
+ "trDisplayName": "Enable CMake Genertion",
+ "type": "CheckBox",
+ "data":
+ {
+ "checked": "%{EnableCMakeGenerationDefault}"
+ }
+ },
{
"name": "CustomScreenWidth",
"trDisplayName": "Custom screen width:",
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 ccfcd01a983..a0cccc15915 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
@@ -32,6 +32,7 @@
{ "key": "ScreenWidth", "value": "%{JS: value('UseStandardResolution') === 'true' ? %{ScreenFactor}.ScreenWidth : value('CustomScreenWidth')}" },
{ "key": "ScreenHeight", "value": "%{JS: value('UseStandardResolution') === 'true' ? %{ScreenFactor}.ScreenHeight : value('CustomScreenHeight')}" },
{ "key": "UseVirtualKeyboardDefault", "value": "%{JS: false}" },
+ { "key": "EnableCMakeGenerationDefault", "value": "%{JS: true}" },
{ "key": "QtQuick3DVersion", "value": "%{JS: %{TargetQtVersion}.TargetQuick3DVersion}" }
],
@@ -208,6 +209,15 @@
"checked": "%{UseVirtualKeyboardDefault}"
}
},
+ {
+ "name": "EnableCMakeGeneration",
+ "trDisplayName": "Enable CMake Genertion",
+ "type": "CheckBox",
+ "data":
+ {
+ "checked": "%{EnableCMakeGenerationDefault}"
+ }
+ },
{
"name": "CustomScreenWidth",
"trDisplayName": "Custom screen width:",
diff --git a/share/qtcreator/qmldesigner/studio_templates/projects/application/wizard.json b/share/qtcreator/qmldesigner/studio_templates/projects/application/wizard.json
index 0aab9b601f3..a7eb00ae0f5 100644
--- a/share/qtcreator/qmldesigner/studio_templates/projects/application/wizard.json
+++ b/share/qtcreator/qmldesigner/studio_templates/projects/application/wizard.json
@@ -31,6 +31,7 @@
{ "key": "ScreenWidth", "value": "%{JS: value('UseStandardResolution') === 'true' ? %{ScreenFactor}.ScreenWidth : value('CustomScreenWidth')}" },
{ "key": "ScreenHeight", "value": "%{JS: value('UseStandardResolution') === 'true' ? %{ScreenFactor}.ScreenHeight : value('CustomScreenHeight')}" },
{ "key": "UseVirtualKeyboardDefault", "value": "%{JS: false}" },
+ { "key": "EnableCMakeGenerationDefault", "value": "%{JS: true}" },
{ "key": "DefaultStyle", "value": "Basic" }
],
@@ -207,6 +208,15 @@
"checked": "%{UseVirtualKeyboardDefault}"
}
},
+ {
+ "name": "EnableCMakeGeneration",
+ "trDisplayName": "Enable CMake Genertion",
+ "type": "CheckBox",
+ "data":
+ {
+ "checked": "%{EnableCMakeGenerationDefault}"
+ }
+ },
{
"name": "CustomScreenWidth",
"trDisplayName": "Custom screen width:",
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 58afba69c34..615cc8d2348 100644
--- a/share/qtcreator/qmldesigner/studio_templates/projects/common/app.qmlproject.tpl
+++ b/share/qtcreator/qmldesigner/studio_templates/projects/common/app.qmlproject.tpl
@@ -22,7 +22,7 @@ Project {
}
JavaScriptFiles {
- directory: "%{ProjectName}"
+ directory: "%{ContentDir}"
}
ImageFiles {
@@ -103,6 +103,10 @@ Project {
/* Required for deployment */
targetDirectory: "/opt/%{ProjectName}"
+@if %{EnableCMakeGeneration}
+ enableCMakeGeneration: true
+@endif
+
qdsVersion: "4.6"
quickVersion: "%{QtQuickVersion}"
diff --git a/share/qtcreator/qmldesigner/welcomepage/BrandBar.qml b/share/qtcreator/qmldesigner/welcomepage/BrandBar.qml
index 721e2b06dd9..d57d35ecb20 100644
--- a/share/qtcreator/qmldesigner/welcomepage/BrandBar.qml
+++ b/share/qtcreator/qmldesigner/welcomepage/BrandBar.qml
@@ -32,6 +32,7 @@ Item {
}
Text {
+ visible: !Constants.projectModel.liteDesignerEnabled
id: brandLabel
color: Constants.currentBrand
text: qsTr("Qt Design Studio")
@@ -44,6 +45,20 @@ Item {
}
Text {
+ visible: Constants.projectModel.liteDesignerEnabled
+ id: brandLabelLite
+ color: Constants.currentBrand
+ text: qsTr("Lite QML Designer")
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.left: welcomeTo.right
+ anchors.leftMargin: 8
+ verticalAlignment: Text.AlignVCenter
+ font.pixelSize: 36
+ font.family: "titillium web"
+ }
+
+ Text {
+ visible: !Constants.projectModel.liteDesignerEnabled
width: 291
height: 55
color: Constants.currentGlobalText
diff --git a/src/plugins/coreplugin/dialogs/settingsdialog.cpp b/src/plugins/coreplugin/dialogs/settingsdialog.cpp
index 828f396433e..6ca8b7d8f06 100644
--- a/src/plugins/coreplugin/dialogs/settingsdialog.cpp
+++ b/src/plugins/coreplugin/dialogs/settingsdialog.cpp
@@ -56,6 +56,8 @@ using namespace Utils;
namespace Core {
namespace Internal {
+namespace {
+
bool optionsPageLessThan(const IOptionsPage *p1, const IOptionsPage *p2)
{
if (p1->category() != p2->category())
@@ -127,7 +129,7 @@ CategoryModel::~CategoryModel()
int CategoryModel::rowCount(const QModelIndex &parent) const
{
- return parent.isValid() ? 0 : m_categories.size();
+ return parent.isValid() ? 0 : static_cast(m_categories.size());
}
QVariant CategoryModel::data(const QModelIndex &index, int role) const
@@ -249,7 +251,7 @@ protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
};
-static bool categoryVisible(const Id &id)
+static bool categoryVisible([[maybe_unused]] const Id &id)
{
#ifdef QT_NO_DEBUG
@@ -806,6 +808,8 @@ bool SettingsDialog::execDialog()
return m_applied;
}
+} // namespace
+
bool executeSettingsDialog(QWidget *parent, Id initialPage)
{
if (!ExtensionSystem::PluginManager::isInitializationDone()) {
diff --git a/src/plugins/effectcomposer/CMakeLists.txt b/src/plugins/effectcomposer/CMakeLists.txt
index 71805ea1be2..4e3e7283b3b 100644
--- a/src/plugins/effectcomposer/CMakeLists.txt
+++ b/src/plugins/effectcomposer/CMakeLists.txt
@@ -6,12 +6,14 @@ add_qtc_plugin(EffectComposer
Qt::Core Qt::CorePrivate Qt::Widgets Qt::Qml Qt::QmlPrivate Qt::Quick
QtCreator::Utils
SOURCES
+ effectcodeeditorwidget.cpp effectcodeeditorwidget.h
effectcomposerplugin.cpp
effectcomposerwidget.cpp effectcomposerwidget.h
effectcomposerview.cpp effectcomposerview.h
effectcomposermodel.cpp effectcomposermodel.h
effectcomposernodesmodel.cpp effectcomposernodesmodel.h
effectcomposeruniformsmodel.cpp effectcomposeruniformsmodel.h
+ effectshaderscodeeditor.cpp effectshaderscodeeditor.h
effectnode.cpp effectnode.h
effectnodescategory.cpp effectnodescategory.h
compositionnode.cpp compositionnode.h
diff --git a/src/plugins/effectcomposer/compositionnode.cpp b/src/plugins/effectcomposer/compositionnode.cpp
index a69cd00e075..5426d55f2cb 100644
--- a/src/plugins/effectcomposer/compositionnode.cpp
+++ b/src/plugins/effectcomposer/compositionnode.cpp
@@ -3,8 +3,9 @@
#include "compositionnode.h"
-#include "effectutils.h"
#include "effectcomposeruniformsmodel.h"
+#include "effectshaderscodeeditor.h"
+#include "effectutils.h"
#include "propertyhandler.h"
#include "uniform.h"
@@ -44,6 +45,8 @@ CompositionNode::CompositionNode(const QString &effectName, const QString &qenPa
}
}
+CompositionNode::~CompositionNode() = default;
+
QString CompositionNode::fragmentCode() const
{
return m_fragmentCode;
@@ -110,8 +113,8 @@ void CompositionNode::parse(const QString &effectName, const QString &qenPath, c
m_name = json.value("name").toString();
m_description = json.value("description").toString();
- m_fragmentCode = EffectUtils::codeFromJsonArray(json.value("fragmentCode").toArray());
- m_vertexCode = EffectUtils::codeFromJsonArray(json.value("vertexCode").toArray());
+ setFragmentCode(EffectUtils::codeFromJsonArray(json.value("fragmentCode").toArray()));
+ setVertexCode(EffectUtils::codeFromJsonArray(json.value("vertexCode").toArray()));
if (json.contains("extraMargin"))
m_extraMargin = json.value("extraMargin").toInt();
@@ -154,6 +157,36 @@ void CompositionNode::parse(const QString &effectName, const QString &qenPath, c
}
}
+void CompositionNode::ensureShadersCodeEditor()
+{
+ if (m_shadersCodeEditor)
+ return;
+
+ m_shadersCodeEditor = Utils::makeUniqueObjectLatePtr(name());
+ m_shadersCodeEditor->setFragmentValue(fragmentCode());
+ m_shadersCodeEditor->setVertexValue(vertexCode());
+
+ connect(m_shadersCodeEditor.get(), &EffectShadersCodeEditor::vertexValueChanged, this, [this] {
+ setVertexCode(m_shadersCodeEditor->vertexValue());
+ });
+
+ connect(m_shadersCodeEditor.get(), &EffectShadersCodeEditor::fragmentValueChanged, this, [this] {
+ setFragmentCode(m_shadersCodeEditor->fragmentValue());
+ });
+
+ connect(
+ m_shadersCodeEditor.get(),
+ &EffectShadersCodeEditor::rebakeRequested,
+ this,
+ &CompositionNode::rebakeRequested);
+}
+
+void CompositionNode::requestRebakeIfLiveUpdateMode()
+{
+ if (m_shadersCodeEditor && m_shadersCodeEditor->liveUpdate())
+ emit rebakeRequested();
+}
+
QList CompositionNode::uniforms() const
{
return m_uniforms;
@@ -189,6 +222,34 @@ void CompositionNode::setRefCount(int count)
emit isDepencyChanged();
}
+void CompositionNode::setFragmentCode(const QString &fragmentCode)
+{
+ if (m_fragmentCode == fragmentCode)
+ return;
+
+ m_fragmentCode = fragmentCode;
+ emit fragmentCodeChanged();
+
+ requestRebakeIfLiveUpdateMode();
+}
+
+void CompositionNode::setVertexCode(const QString &vertexCode)
+{
+ if (m_vertexCode == vertexCode)
+ return;
+
+ m_vertexCode = vertexCode;
+ emit vertexCodeChanged();
+
+ requestRebakeIfLiveUpdateMode();
+}
+
+void CompositionNode::openShadersCodeEditor()
+{
+ ensureShadersCodeEditor();
+ m_shadersCodeEditor->showWidget();
+}
+
QString CompositionNode::name() const
{
return m_name;
diff --git a/src/plugins/effectcomposer/compositionnode.h b/src/plugins/effectcomposer/compositionnode.h
index 433468688a2..dcd66072afa 100644
--- a/src/plugins/effectcomposer/compositionnode.h
+++ b/src/plugins/effectcomposer/compositionnode.h
@@ -5,11 +5,15 @@
#include "effectcomposeruniformsmodel.h"
+#include
+
#include
#include
namespace EffectComposer {
+class EffectShadersCodeEditor;
+
class CompositionNode : public QObject
{
Q_OBJECT
@@ -18,6 +22,12 @@ class CompositionNode : public QObject
Q_PROPERTY(bool nodeEnabled READ isEnabled WRITE setIsEnabled NOTIFY isEnabledChanged)
Q_PROPERTY(bool isDependency READ isDependency NOTIFY isDepencyChanged)
Q_PROPERTY(QObject *nodeUniformsModel READ uniformsModel NOTIFY uniformsModelChanged)
+ Q_PROPERTY(
+ QString fragmentCode
+ READ fragmentCode
+ WRITE setFragmentCode
+ NOTIFY fragmentCodeChanged)
+ Q_PROPERTY(QString vertexCode READ vertexCode WRITE setVertexCode NOTIFY vertexCodeChanged)
public:
enum NodeType {
@@ -27,6 +37,7 @@ public:
};
CompositionNode(const QString &effectName, const QString &qenPath, const QJsonObject &json = {});
+ virtual ~CompositionNode();
QString fragmentCode() const;
QString vertexCode() const;
@@ -54,14 +65,23 @@ public:
int extraMargin() const { return m_extraMargin; }
+ void setFragmentCode(const QString &fragmentCode);
+ void setVertexCode(const QString &vertexCode);
+
+ void openShadersCodeEditor();
+
signals:
void uniformsModelChanged();
void isEnabledChanged();
void isDepencyChanged();
void rebakeRequested();
+ void fragmentCodeChanged();
+ void vertexCodeChanged();
private:
void parse(const QString &effectName, const QString &qenPath, const QJsonObject &json);
+ void ensureShadersCodeEditor();
+ void requestRebakeIfLiveUpdateMode();
QString m_name;
NodeType m_type = CustomNode;
@@ -77,6 +97,7 @@ private:
QList m_uniforms;
EffectComposerUniformsModel m_unifomrsModel;
+ Utils::UniqueObjectLatePtr m_shadersCodeEditor;
};
} // namespace EffectComposer
diff --git a/src/plugins/effectcomposer/effectcodeeditorwidget.cpp b/src/plugins/effectcomposer/effectcodeeditorwidget.cpp
new file mode 100644
index 00000000000..c6fcf7c952e
--- /dev/null
+++ b/src/plugins/effectcomposer/effectcodeeditorwidget.cpp
@@ -0,0 +1,142 @@
+// 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 "effectcodeeditorwidget.h"
+
+#include
+
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+
+#include
+
+namespace EffectComposer {
+
+constexpr char EFFECTEDITOR_CONTEXT_ID[] = "EffectEditor.EffectEditorContext";
+
+EffectCodeEditorWidget::EffectCodeEditorWidget()
+ : m_context(new Core::IContext(this))
+{
+ Core::Context context(EFFECTEDITOR_CONTEXT_ID, ProjectExplorer::Constants::QMLJS_LANGUAGE_ID);
+
+ m_context->setWidget(this);
+ m_context->setContext(context);
+ Core::ICore::addContextObject(m_context);
+
+ Utils::TransientScrollAreaSupport::support(this);
+
+ /*
+ * We have to register our own active auto completion shortcut, because the original shortcut will
+ * use the cursor position of the original editor in the editor manager.
+ */
+ m_completionAction = new QAction(tr("Trigger Completion"), this);
+
+ Core::Command *command = Core::ActionManager::registerAction(
+ m_completionAction, TextEditor::Constants::COMPLETE_THIS, context);
+ command->setDefaultKeySequence(QKeySequence(
+ Core::useMacShortcuts
+ ? tr("Meta+Space")
+ : tr("Ctrl+Space")));
+
+ connect(m_completionAction, &QAction::triggered, this, [this] {
+ invokeAssist(TextEditor::Completion);
+ });
+}
+
+EffectCodeEditorWidget::~EffectCodeEditorWidget()
+{
+ unregisterAutoCompletion();
+}
+
+void EffectCodeEditorWidget::unregisterAutoCompletion()
+{
+ if (m_completionAction) {
+ Core::ActionManager::unregisterAction(m_completionAction, TextEditor::Constants::COMPLETE_THIS);
+ delete m_completionAction;
+ m_completionAction = nullptr;
+ }
+}
+
+void EffectCodeEditorWidget::setEditorTextWithIndentation(const QString &text)
+{
+ auto *doc = document();
+ doc->setPlainText(text);
+
+ // We don't need to indent an empty text but is also needed for safer text.length()-1 below
+ if (text.isEmpty())
+ return;
+
+ auto modifier = std::make_unique(doc, QTextCursor{doc});
+ modifier->indent(0, text.length()-1);
+}
+
+EffectDocument::EffectDocument()
+ : QmlJSEditor::QmlJSEditorDocument(EFFECTEDITOR_CONTEXT_ID)
+ , m_semanticHighlighter(new QmlJSEditor::SemanticHighlighter(this))
+{}
+
+EffectDocument::~EffectDocument()
+{
+ delete m_semanticHighlighter;
+}
+
+void EffectDocument::applyFontSettings()
+{
+ TextDocument::applyFontSettings();
+ m_semanticHighlighter->updateFontSettings(fontSettings());
+ if (!isSemanticInfoOutdated() && semanticInfo().isValid())
+ m_semanticHighlighter->rerun(semanticInfo());
+}
+
+void EffectDocument::triggerPendingUpdates()
+{
+ TextDocument::triggerPendingUpdates(); // Calls applyFontSettings if necessary
+ if (!isSemanticInfoOutdated() && semanticInfo().isValid())
+ m_semanticHighlighter->rerun(semanticInfo());
+}
+
+EffectCodeEditorFactory::EffectCodeEditorFactory()
+{
+ setId(EFFECTEDITOR_CONTEXT_ID);
+ setDisplayName(::Core::Tr::tr("Effect Code Editor"));
+ addMimeType(EFFECTEDITOR_CONTEXT_ID);
+ addMimeType(Utils::Constants::QML_MIMETYPE);
+ addMimeType(Utils::Constants::QMLTYPES_MIMETYPE);
+ addMimeType(Utils::Constants::JS_MIMETYPE);
+
+ setDocumentCreator([]() { return new EffectDocument; });
+ setEditorWidgetCreator([]() { return new EffectCodeEditorWidget; });
+ setEditorCreator([]() { return new QmlJSEditor::QmlJSEditor; });
+ setAutoCompleterCreator([]() { return new QmlJSEditor::AutoCompleter; });
+ setCommentDefinition(Utils::CommentDefinition::CppStyle);
+ setParenthesesMatchingEnabled(true);
+ setCodeFoldingSupported(true);
+
+ addHoverHandler(new QmlJSEditor::QmlJSHoverHandler);
+ setCompletionAssistProvider(new QmlJSEditor::QmlJSCompletionAssistProvider);
+}
+
+void EffectCodeEditorFactory::decorateEditor(TextEditor::TextEditorWidget *editor)
+{
+ editor->textDocument()->resetSyntaxHighlighter(
+ [] { return new QmlJSEditor::QmlJSHighlighter(); });
+ editor->textDocument()->setIndenter(QmlJSEditor::createQmlJsIndenter(
+ editor->textDocument()->document()));
+ editor->setAutoCompleter(new QmlJSEditor::AutoCompleter);
+}
+
+} // namespace EffectComposer
diff --git a/src/plugins/effectcomposer/effectcodeeditorwidget.h b/src/plugins/effectcomposer/effectcodeeditorwidget.h
new file mode 100644
index 00000000000..1ea043dc68e
--- /dev/null
+++ b/src/plugins/effectcomposer/effectcodeeditorwidget.h
@@ -0,0 +1,63 @@
+// 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
+#include
+
+QT_FORWARD_DECLARE_CLASS(QAction)
+
+namespace QmlJSEditor {
+class SemanticHighlighter;
+}
+
+namespace Core {
+class IContext;
+}
+
+namespace EffectComposer {
+
+class EffectCodeEditorWidget : public QmlJSEditor::QmlJSEditorWidget
+{
+ Q_OBJECT
+
+public:
+ EffectCodeEditorWidget();
+ ~EffectCodeEditorWidget() override;
+
+ void unregisterAutoCompletion();
+ void setEditorTextWithIndentation(const QString &text);
+
+signals:
+ void returnKeyClicked();
+
+public:
+ Core::IContext *m_context = nullptr;
+ QAction *m_completionAction = nullptr;
+ bool m_isMultiline = true;
+};
+
+class EffectDocument : public QmlJSEditor::QmlJSEditorDocument
+{
+public:
+ EffectDocument();
+ ~EffectDocument();
+
+protected:
+ void applyFontSettings() final;
+ void triggerPendingUpdates() final;
+
+private:
+ QmlJSEditor::SemanticHighlighter *m_semanticHighlighter = nullptr;
+};
+
+class EffectCodeEditorFactory : public TextEditor::TextEditorFactory
+{
+public:
+ EffectCodeEditorFactory();
+
+ static void decorateEditor(TextEditor::TextEditorWidget *editor);
+};
+
+} // namespace EffectComposer
diff --git a/src/plugins/effectcomposer/effectcomposercontextobject.cpp b/src/plugins/effectcomposer/effectcomposercontextobject.cpp
index 95ebe7a3670..68053055b30 100644
--- a/src/plugins/effectcomposer/effectcomposercontextobject.cpp
+++ b/src/plugins/effectcomposer/effectcomposercontextobject.cpp
@@ -168,11 +168,11 @@ int EffectComposerContextObject::devicePixelRatio()
QStringList EffectComposerContextObject::allStatesForId(const QString &id)
{
- if (m_model && m_model->rewriterView()) {
- const QmlDesigner::QmlObjectNode node = m_model->rewriterView()->modelNodeForId(id);
- if (node.isValid())
- return node.allStateNames();
- }
+ if (m_model) {
+ const QmlDesigner::QmlObjectNode node = m_model->modelNodeForId(id);
+ if (node.isValid())
+ return node.allStateNames();
+ }
return {};
}
diff --git a/src/plugins/effectcomposer/effectcomposermodel.cpp b/src/plugins/effectcomposer/effectcomposermodel.cpp
index 3561f46a3f0..6f7a2612c98 100644
--- a/src/plugins/effectcomposer/effectcomposermodel.cpp
+++ b/src/plugins/effectcomposer/effectcomposermodel.cpp
@@ -4,27 +4,36 @@
#include "effectcomposermodel.h"
#include "compositionnode.h"
+#include "effectshaderscodeeditor.h"
#include "effectutils.h"
#include "propertyhandler.h"
#include "syntaxhighlighterdata.h"
#include "uniform.h"
+#include
+#include
+#include
+#include
+#include
+
+#include
+
#include
#include
#include
-#include
#include
#include
-#include
-
#include
+#include
#include
#include
#include
+using namespace Qt::StringLiterals;
+
namespace EffectComposer {
enum class FileType
@@ -58,11 +67,12 @@ EffectComposerModel::EffectComposerModel(QObject *parent)
QHash EffectComposerModel::roleNames() const
{
- QHash roles;
- roles[NameRole] = "nodeName";
- roles[EnabledRole] = "nodeEnabled";
- roles[UniformsRole] = "nodeUniformsModel";
- roles[Dependency] = "isDependency";
+ static const QHash roles = {
+ {NameRole, "nodeName"},
+ {EnabledRole, "nodeEnabled"},
+ {UniformsRole, "nodeUniformsModel"},
+ {Dependency, "isDependency"},
+ };
return roles;
}
@@ -206,6 +216,8 @@ void EffectComposerModel::clear(bool clearName)
if (clearName) {
setCurrentComposition("");
setCompositionPath("");
+ resetRootFragmentShader();
+ resetRootVertexShader();
}
setHasUnsavedChanges(!m_currentComposition.isEmpty());
@@ -241,6 +253,47 @@ bool EffectComposerModel::nameExists(const QString &name) const
return QFile::exists(path.arg(name));
}
+void EffectComposerModel::chooseCustomPreviewImage()
+{
+ QTimer::singleShot(0, this, [&]() {
+ using Utils::FilePath;
+ static FilePath lastDir;
+ const QStringList &suffixes = QmlDesigner::Asset::supportedImageSuffixes();
+ QmlDesigner::DesignDocument *document = QmlDesigner::QmlDesignerPlugin::instance()->currentDesignDocument();
+ const FilePath currentDir = lastDir.isEmpty() ? document->fileName().parentDir()
+ : lastDir;
+ const QStringList fileNames = QFileDialog::getOpenFileNames(Core::ICore::dialogParent(),
+ tr("Select custom effect background image"),
+ currentDir.toFSPathString(),
+ tr("Image Files (%1)").arg(suffixes.join(" ")));
+
+ if (!fileNames.isEmpty()) {
+ FilePath imageFile = FilePath::fromString(fileNames.first());
+ lastDir = imageFile.absolutePath();
+ if (imageFile.exists()) {
+ FilePath projDir = QmlDesigner::QmlDesignerPlugin::instance()->documentManager()
+ .currentProjectDirPath();
+ if (!imageFile.isChildOf(projDir)) {
+ FilePath imagesDir = QmlDesigner::ModelNodeOperations::getImagesDefaultDirectory();
+ FilePath targetFile = imagesDir.pathAppended(imageFile.fileName());
+ if (!targetFile.exists())
+ imageFile.copyFile(targetFile);
+ if (targetFile.exists())
+ imageFile = targetFile;
+ }
+
+ m_customPreviewImage = QUrl::fromLocalFile(imageFile.toFSPathString());
+ m_currentPreviewImage = m_customPreviewImage;
+
+ setHasUnsavedChanges(true);
+
+ emit currentPreviewImageChanged();
+ emit customPreviewImageChanged();
+ }
+ }
+ });
+}
+
QString EffectComposerModel::fragmentShader() const
{
return m_fragmentShader;
@@ -267,6 +320,40 @@ void EffectComposerModel::setVertexShader(const QString &newVertexShader)
m_vertexShader = newVertexShader;
}
+void EffectComposerModel::setRootFragmentShader(const QString &shader)
+{
+ m_rootFragmentShader = shader;
+}
+
+void EffectComposerModel::resetRootFragmentShader()
+{
+ static const QString defaultRootFragmentShader = {
+ "void main() {\n"
+ " fragColor = texture(iSource, texCoord);\n"
+ " @nodes\n"
+ " fragColor = fragColor * qt_Opacity;\n"
+ "}\n"};
+ setRootFragmentShader(defaultRootFragmentShader);
+}
+
+void EffectComposerModel::setRootVertexShader(const QString &shader)
+{
+ m_rootVertexShader = shader;
+}
+
+void EffectComposerModel::resetRootVertexShader()
+{
+ static const QString defaultRootVertexShader = {
+ "void main() {\n"
+ " texCoord = qt_MultiTexCoord0;\n"
+ " fragCoord = qt_Vertex.xy;\n"
+ " vec2 vertCoord = qt_Vertex.xy;\n"
+ " @nodes\n"
+ " gl_Position = qt_Matrix * vec4(vertCoord, 0.0, 1.0);\n"
+ "}\n"};
+ setRootVertexShader(defaultRootVertexShader);
+}
+
QString EffectComposerModel::qmlComponentString() const
{
return m_qmlComponentString;
@@ -960,11 +1047,26 @@ void EffectComposerModel::saveComposition(const QString &name)
return;
}
+ const Utils::FilePath compositionPath = Utils::FilePath::fromString(path);
+ const Utils::FilePath compositionDir = compositionPath.absolutePath();
+
updateExtraMargin();
QJsonObject json;
// File format version
json.insert("version", 1);
+ json.insert("tool", "EffectComposer");
+
+ Utils::FilePath customPreviewPath = Utils::FilePath::fromUrl(m_customPreviewImage);
+ if (m_customPreviewImage.isLocalFile())
+ customPreviewPath = customPreviewPath.relativePathFrom(compositionDir);
+ json.insert("customPreviewImage", customPreviewPath.toUrl().toString());
+
+ QUrl previewUrl = m_currentPreviewImage;
+ if (m_currentPreviewImage == m_customPreviewImage)
+ previewUrl = customPreviewPath.toUrl();
+
+ json.insert("previewImage", previewUrl.toString());
// Add nodes
QJsonArray nodesArray;
@@ -973,9 +1075,18 @@ void EffectComposerModel::saveComposition(const QString &name)
nodesArray.append(nodeObject);
}
+ auto toJsonArray = [](const QString &code) -> QJsonArray {
+ if (code.isEmpty())
+ return {};
+ return QJsonArray::fromStringList(code.split('\n'));
+ };
+
if (!nodesArray.isEmpty())
json.insert("nodes", nodesArray);
+ json.insert("vertexCode", toJsonArray(m_rootVertexShader));
+ json.insert("fragmentCode", toJsonArray(m_rootFragmentShader));
+
QJsonObject rootJson;
rootJson.insert("QEP", json);
QJsonDocument jsonDoc(rootJson);
@@ -984,20 +1095,60 @@ void EffectComposerModel::saveComposition(const QString &name)
saveFile.close();
setCurrentComposition(name);
- setCompositionPath(Utils::FilePath::fromString(path));
+ setCompositionPath(compositionPath);
saveResources(name);
setHasUnsavedChanges(false);
}
+void EffectComposerModel::openShadersCodeEditor(int idx)
+{
+ if (m_nodes.size() < idx || idx < 0)
+ return;
+
+ CompositionNode *node = m_nodes.at(idx);
+ node->openShadersCodeEditor();
+}
+
+void EffectComposerModel::openMainShadersCodeEditor()
+{
+ if (!m_shadersCodeEditor) {
+ m_shadersCodeEditor = Utils::makeUniqueObjectLatePtr(
+ currentComposition());
+ m_shadersCodeEditor->setFragmentValue(m_rootFragmentShader);
+ m_shadersCodeEditor->setVertexValue(m_rootVertexShader);
+
+ connect(m_shadersCodeEditor.get(), &EffectShadersCodeEditor::vertexValueChanged, this, [this] {
+ setRootVertexShader(m_shadersCodeEditor->vertexValue());
+ setHasUnsavedChanges(true);
+ rebakeIfLiveUpdateMode();
+ });
+
+ connect(
+ m_shadersCodeEditor.get(), &EffectShadersCodeEditor::fragmentValueChanged, this, [this] {
+ setRootFragmentShader(m_shadersCodeEditor->fragmentValue());
+ setHasUnsavedChanges(true);
+ rebakeIfLiveUpdateMode();
+ });
+
+ connect(
+ m_shadersCodeEditor.get(),
+ &EffectShadersCodeEditor::rebakeRequested,
+ this,
+ &EffectComposerModel::startRebakeTimer);
+ }
+ m_shadersCodeEditor->showWidget();
+}
+
void EffectComposerModel::openComposition(const QString &path)
{
clear(true);
- const QString effectName = QFileInfo(path).baseName();
+ Utils::FilePath effectPath = Utils::FilePath::fromString(path);
+ const QString effectName = effectPath.baseName();
setCurrentComposition(effectName);
- setCompositionPath(Utils::FilePath::fromString(path));
+ setCompositionPath(effectPath);
QFile compFile(path);
if (!compFile.open(QIODevice::ReadOnly)) {
@@ -1030,6 +1181,18 @@ void EffectComposerModel::openComposition(const QString &path)
QJsonObject json = rootJson["QEP"].toObject();
+ const QString toolName = json.contains("tool") ? json["tool"].toString()
+ : json.contains("QQEM") ? "QQEM"_L1
+ : ""_L1;
+
+ if (!toolName.isEmpty() && toolName != "EffectComposer") {
+ const QString error
+ = tr("Error: '%1' effects are not compatible with 'Effect Composer'").arg(toolName);
+ qWarning() << error;
+ setEffectError(error);
+ return;
+ }
+
int version = -1;
if (json.contains("version"))
version = json["version"].toInt(-1);
@@ -1041,6 +1204,63 @@ void EffectComposerModel::openComposition(const QString &path)
return;
}
+ auto toCodeBlock = [](const QJsonValue &jsonValue) -> QString {
+ if (!jsonValue.isArray())
+ return {};
+
+ QString code;
+ const QJsonArray array = jsonValue.toArray();
+ for (const QJsonValue &lineValue : array) {
+ if (lineValue.isString())
+ code += lineValue.toString() + '\n';
+ }
+
+ return code;
+ };
+
+ if (json.contains("vertexCode"))
+ setRootVertexShader(toCodeBlock(json["vertexCode"]));
+ else
+ resetRootVertexShader();
+
+ if (json.contains("fragmentCode"))
+ setRootFragmentShader(toCodeBlock(json["fragmentCode"]));
+ else
+ resetRootFragmentShader();
+
+ m_currentPreviewImage.clear();
+ if (json.contains("previewImage")) {
+ const QString imageStr = json["previewImage"].toString();
+ if (!imageStr.isEmpty()) {
+ const QUrl imageUrl{imageStr};
+ Utils::FilePath imagePath = Utils::FilePath::fromUrl(imageUrl);
+ if (imageStr.startsWith("images/preview")) { // built-in preview image
+ m_currentPreviewImage = imageUrl;
+ } else if (imagePath.isAbsolutePath()) {
+ if (imagePath.exists())
+ m_currentPreviewImage = imageUrl;
+ } else {
+ imagePath = effectPath.absolutePath().resolvePath(imagePath);
+ if (imagePath.exists())
+ m_currentPreviewImage = imagePath.toUrl();
+ }
+ }
+ }
+
+ m_customPreviewImage.clear();
+ if (json.contains("customPreviewImage")) {
+ QUrl imageUrl{json["customPreviewImage"].toString()};
+ Utils::FilePath imagePath = Utils::FilePath::fromUrl(imageUrl);
+ if (imagePath.isAbsolutePath()) {
+ if (imagePath.exists())
+ m_customPreviewImage = imageUrl;
+ } else {
+ imagePath = effectPath.absolutePath().resolvePath(imagePath);
+ if (imagePath.exists())
+ m_customPreviewImage = imagePath.toUrl();
+ }
+ }
+
if (json.contains("nodes") && json["nodes"].isArray()) {
beginResetModel();
QHash refCounts;
@@ -1069,6 +1289,8 @@ void EffectComposerModel::openComposition(const QString &path)
setHasUnsavedChanges(false);
emit nodesChanged();
+ emit currentPreviewImageChanged();
+ emit customPreviewImageChanged();
}
void EffectComposerModel::saveResources(const QString &name)
@@ -1354,8 +1576,6 @@ QString EffectComposerModel::valueAsVariable(const Uniform &uniform)
// Return name for the image property Image element
QString EffectComposerModel::getImageElementName(const Uniform &uniform, bool localFiles)
{
- if (localFiles && uniform.value().toString().isEmpty())
- return QStringLiteral("null");
QString simplifiedName = uniform.name().simplified();
simplifiedName = simplifiedName.remove(' ');
return QStringLiteral("imageItem") + simplifiedName;
@@ -1439,32 +1659,6 @@ QString EffectComposerModel::processFragmentRootLine(const QString &line)
return output;
}
-QStringList EffectComposerModel::getDefaultRootVertexShader()
-{
- if (m_defaultRootVertexShader.isEmpty()) {
- m_defaultRootVertexShader << "void main() {";
- m_defaultRootVertexShader << " texCoord = qt_MultiTexCoord0;";
- m_defaultRootVertexShader << " fragCoord = qt_Vertex.xy;";
- m_defaultRootVertexShader << " vec2 vertCoord = qt_Vertex.xy;";
- m_defaultRootVertexShader << " @nodes";
- m_defaultRootVertexShader << " gl_Position = qt_Matrix * vec4(vertCoord, 0.0, 1.0);";
- m_defaultRootVertexShader << "}";
- }
- return m_defaultRootVertexShader;
-}
-
-QStringList EffectComposerModel::getDefaultRootFragmentShader()
-{
- if (m_defaultRootFragmentShader.isEmpty()) {
- m_defaultRootFragmentShader << "void main() {";
- m_defaultRootFragmentShader << " fragColor = texture(iSource, texCoord);";
- m_defaultRootFragmentShader << " @nodes";
- m_defaultRootFragmentShader << " fragColor = fragColor * qt_Opacity;";
- m_defaultRootFragmentShader << "}";
- }
- return m_defaultRootFragmentShader;
-}
-
// Remove all post-processing tags ("@tag") from the code.
// Except "@nodes" tag as that is handled later.
QStringList EffectComposerModel::removeTagsFromCode(const QStringList &codeLines)
@@ -1527,7 +1721,7 @@ QString EffectComposerModel::generateVertexShader(bool includeUniforms)
// split to root and main parts
QString s_root;
QString s_main;
- QStringList s_sourceCode;
+ QStringList s_sourceCode = m_rootVertexShader.split('\n');
m_shaderVaryingVariables.clear();
for (const CompositionNode *n : std::as_const(m_nodes)) {
if (!n->vertexCode().isEmpty() && n->isEnabled()) {
@@ -1544,11 +1738,6 @@ QString EffectComposerModel::generateVertexShader(bool includeUniforms)
}
}
- if (s_sourceCode.isEmpty()) {
- // If source nodes doesn't contain any code, use default one
- s_sourceCode << getDefaultRootVertexShader();
- }
-
if (removeTags) {
s_sourceCode = removeTagsFromCode(s_sourceCode);
s_root = removeTagsFromCode(s_root);
@@ -1583,7 +1772,7 @@ QString EffectComposerModel::generateFragmentShader(bool includeUniforms)
// split to root and main parts
QString s_root;
QString s_main;
- QStringList s_sourceCode;
+ QStringList s_sourceCode = m_rootFragmentShader.split('\n');
for (const CompositionNode *n : std::as_const(m_nodes)) {
if (!n->fragmentCode().isEmpty() && n->isEnabled()) {
const QStringList fragmentCode = n->fragmentCode().split('\n');
@@ -1599,11 +1788,6 @@ QString EffectComposerModel::generateFragmentShader(bool includeUniforms)
}
}
- if (s_sourceCode.isEmpty()) {
- // If source nodes doesn't contain any code, use default one
- s_sourceCode << getDefaultRootFragmentShader();
- }
-
if (removeTags) {
s_sourceCode = removeTagsFromCode(s_sourceCode);
s_root = removeTagsFromCode(s_root);
@@ -1828,7 +2012,6 @@ void EffectComposerModel::bakeShaders()
runQsb(qsbPath, outPaths, false);
runQsb(qsbPrevPath, outPrevPaths, true);
-
}
bool EffectComposerModel::shadersUpToDate() const
@@ -1877,11 +2060,7 @@ QString EffectComposerModel::getQmlImagesString(bool localFiles)
for (Uniform *uniform : uniforms) {
if (uniform->type() == Uniform::Type::Sampler) {
QString imagePath = uniform->value().toString();
- // For preview, generate image element even if path is empty, as changing uniform values
- // will not trigger qml code regeneration
if (localFiles) {
- if (imagePath.isEmpty())
- continue;
QFileInfo fi(imagePath);
imagePath = fi.fileName();
imagesString += QString(" property url %1Url: \"%2\"\n")
@@ -2003,14 +2182,16 @@ QString EffectComposerModel::getQmlComponentString(bool localFiles)
void EffectComposerModel::connectCompositionNode(CompositionNode *node)
{
- connect(qobject_cast(node->uniformsModel()),
- &EffectComposerUniformsModel::dataChanged, this, [this] {
- setHasUnsavedChanges(true);
- });
- connect(node, &CompositionNode::rebakeRequested, this, [this] {
- // This can come multiple times in a row in response to property changes, so let's buffer it
- m_rebakeTimer.start(200);
- });
+ auto setUnsaved = std::bind(&EffectComposerModel::setHasUnsavedChanges, this, true);
+ connect(
+ qobject_cast(node->uniformsModel()),
+ &EffectComposerUniformsModel::dataChanged,
+ this,
+ setUnsaved);
+
+ connect(node, &CompositionNode::rebakeRequested, this, &EffectComposerModel::startRebakeTimer);
+ connect(node, &CompositionNode::fragmentCodeChanged, this, setUnsaved);
+ connect(node, &CompositionNode::vertexCodeChanged, this, setUnsaved);
}
void EffectComposerModel::updateExtraMargin()
@@ -2020,6 +2201,18 @@ void EffectComposerModel::updateExtraMargin()
m_extraMargin = qMax(node->extraMargin(), m_extraMargin);
}
+void EffectComposerModel::startRebakeTimer()
+{
+ // This can come multiple times in a row in response to property changes, so let's buffer it
+ m_rebakeTimer.start(200);
+}
+
+void EffectComposerModel::rebakeIfLiveUpdateMode()
+{
+ if (m_shadersCodeEditor && m_shadersCodeEditor->liveUpdate())
+ startRebakeTimer();
+}
+
QSet EffectComposerModel::getExposedProperties(const QByteArray &qmlContent)
{
QSet returnSet;
@@ -2051,6 +2244,30 @@ void EffectComposerModel::setCurrentComposition(const QString &newCurrentComposi
m_currentComposition = newCurrentComposition;
emit currentCompositionChanged();
+
+ m_shadersCodeEditor.reset();
+}
+
+QUrl EffectComposerModel::customPreviewImage() const
+{
+ return m_customPreviewImage;
+}
+
+QUrl EffectComposerModel::currentPreviewImage() const
+{
+ return m_currentPreviewImage;
+}
+
+void EffectComposerModel::setCurrentPreviewImage(const QUrl &path)
+{
+ if (m_currentPreviewImage == path)
+ return;
+
+ if (!m_nodes.isEmpty())
+ setHasUnsavedChanges(true);
+
+ m_currentPreviewImage = path;
+ emit currentPreviewImageChanged();
}
Utils::FilePath EffectComposerModel::compositionPath() const
diff --git a/src/plugins/effectcomposer/effectcomposermodel.h b/src/plugins/effectcomposer/effectcomposermodel.h
index 098cc730069..09aeb724532 100644
--- a/src/plugins/effectcomposer/effectcomposermodel.h
+++ b/src/plugins/effectcomposer/effectcomposermodel.h
@@ -6,6 +6,7 @@
#include "shaderfeatures.h"
#include
+#include
#include
#include
@@ -14,6 +15,7 @@
#include
#include
#include
+#include
namespace ProjectExplorer {
class Target;
@@ -26,6 +28,7 @@ class Process;
namespace EffectComposer {
class CompositionNode;
+class EffectShadersCodeEditor;
class Uniform;
struct EffectError {
@@ -51,6 +54,8 @@ class EffectComposerModel : public QAbstractListModel
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)
+ Q_PROPERTY(QUrl currentPreviewImage READ currentPreviewImage WRITE setCurrentPreviewImage NOTIFY currentPreviewImageChanged)
+ Q_PROPERTY(QUrl customPreviewImage READ customPreviewImage NOTIFY customPreviewImageChanged)
public:
EffectComposerModel(QObject *parent = nullptr);
@@ -75,6 +80,7 @@ public:
Q_INVOKABLE void assignToSelected();
Q_INVOKABLE QString getUniqueEffectName() const;
Q_INVOKABLE bool nameExists(const QString &name) const;
+ Q_INVOKABLE void chooseCustomPreviewImage();
bool shadersUpToDate() const;
void setShadersUpToDate(bool newShadersUpToDate);
@@ -91,6 +97,12 @@ public:
QString vertexShader() const;
void setVertexShader(const QString &newVertexShader);
+ void setRootFragmentShader(const QString &shader);
+ void resetRootFragmentShader();
+
+ void setRootVertexShader(const QString &shader);
+ void resetRootVertexShader();
+
Q_INVOKABLE QString qmlComponentString() const;
Q_INVOKABLE void updateQmlComponent();
@@ -100,11 +112,18 @@ public:
Q_INVOKABLE void saveComposition(const QString &name);
+ Q_INVOKABLE void openShadersCodeEditor(int idx);
+ Q_INVOKABLE void openMainShadersCodeEditor();
+
void openComposition(const QString &path);
QString currentComposition() const;
void setCurrentComposition(const QString &newCurrentComposition);
+ QUrl customPreviewImage() const;
+ QUrl currentPreviewImage() const;
+ void setCurrentPreviewImage(const QUrl &path);
+
Utils::FilePath compositionPath() const;
void setCompositionPath(const Utils::FilePath &newCompositionPath);
@@ -129,6 +148,8 @@ signals:
void hasUnsavedChangesChanged();
void assignToSelectedTriggered(const QString &effectPath);
void removePropertiesFromScene(QSet props, const QString &typeName);
+ void currentPreviewImageChanged();
+ void customPreviewImageChanged();
private:
enum Roles {
@@ -167,8 +188,6 @@ private:
int getTagIndex(const QStringList &code, const QString &tag);
QString processVertexRootLine(const QString &line);
QString processFragmentRootLine(const QString &line);
- QStringList getDefaultRootVertexShader();
- QStringList getDefaultRootFragmentShader();
QStringList removeTagsFromCode(const QStringList &codeLines);
QString removeTagsFromCode(const QString &code);
QString getCustomShaderVaryings(bool outState);
@@ -190,6 +209,8 @@ private:
void connectCompositionNode(CompositionNode *node);
void updateExtraMargin();
+ void startRebakeTimer();
+ void rebakeIfLiveUpdateMode();
QSet getExposedProperties(const QByteArray &qmlContent);
QList m_nodes;
@@ -205,8 +226,8 @@ private:
QStringList m_shaderVaryingVariables;
QString m_fragmentShader;
QString m_vertexShader;
- QStringList m_defaultRootVertexShader;
- QStringList m_defaultRootFragmentShader;
+ QString m_rootVertexShader;
+ QString m_rootFragmentShader;
// Temp files to store shaders sources and binary data
QTemporaryDir m_shaderDir;
QString m_fragmentSourceFilename;
@@ -230,6 +251,9 @@ private:
int m_extraMargin = 0;
QString m_effectTypePrefix;
Utils::FilePath m_compositionPath;
+ Utils::UniqueObjectLatePtr m_shadersCodeEditor;
+ QUrl m_currentPreviewImage;
+ QUrl m_customPreviewImage;
const QRegularExpression m_spaceReg = QRegularExpression("\\s+");
};
diff --git a/src/plugins/effectcomposer/effectcomposerview.cpp b/src/plugins/effectcomposer/effectcomposerview.cpp
index d8077502bcb..08fad0150d9 100644
--- a/src/plugins/effectcomposer/effectcomposerview.cpp
+++ b/src/plugins/effectcomposer/effectcomposerview.cpp
@@ -6,6 +6,7 @@
#include "effectcomposermodel.h"
#include "effectcomposernodesmodel.h"
#include "effectcomposerwidget.h"
+#include "studioquickwidget.h"
#include
#include
@@ -218,4 +219,27 @@ void EffectComposerView::removeUnusedEffectImports()
}
}
+void EffectComposerView::highlightSupportedProperties(bool highlight, const QString &suffix)
+{
+ QQmlContext *ctxObj = m_widget->quickWidget()->rootContext();
+ ctxObj->setContextProperty("activeDragSuffix", suffix);
+ ctxObj->setContextProperty("hasActiveDrag", highlight);
+}
+
+void EffectComposerView::dragStarted(QMimeData *mimeData)
+{
+ if (mimeData->hasFormat(QmlDesigner::Constants::MIME_TYPE_ASSETS)) {
+ QString format = mimeData->formats()[0];
+ const QString assetPath = QString::fromUtf8(mimeData->data(format)).split(',')[0];
+ const QString suffix = "*." + assetPath.split('.').last().toLower();
+
+ highlightSupportedProperties(true, suffix);
+ }
+}
+
+void EffectComposerView::dragEnded()
+{
+ highlightSupportedProperties(false);
+}
+
} // namespace EffectComposer
diff --git a/src/plugins/effectcomposer/effectcomposerview.h b/src/plugins/effectcomposer/effectcomposerview.h
index aed51146805..347409172ea 100644
--- a/src/plugins/effectcomposer/effectcomposerview.h
+++ b/src/plugins/effectcomposer/effectcomposerview.h
@@ -31,6 +31,11 @@ public:
const QList &lastSelectedNodeList) override;
void nodeAboutToBeRemoved(const QmlDesigner::ModelNode &removedNode) override;
+ void dragStarted(QMimeData *mimeData) override;
+ void dragEnded() override;
+
+ void highlightSupportedProperties(bool highlight, const QString &suffix = {});
+
private:
void customNotification(const AbstractView *view, const QString &identifier,
const QList &nodeList, const QList &data) override;
diff --git a/src/plugins/effectcomposer/effectshaderscodeeditor.cpp b/src/plugins/effectcomposer/effectshaderscodeeditor.cpp
new file mode 100644
index 00000000000..95fe30a54e6
--- /dev/null
+++ b/src/plugins/effectcomposer/effectshaderscodeeditor.cpp
@@ -0,0 +1,226 @@
+// 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 "effectshaderscodeeditor.h"
+#include "effectcodeeditorwidget.h"
+
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+namespace {
+
+using IconId = QmlDesigner::DesignerIcons::IconId;
+
+inline constexpr char EFFECTCOMPOSER_LIVE_UPDATE_KEY[] = "EffectComposer/CodeEditor/LiveUpdate";
+
+QIcon toolbarIcon(IconId iconId)
+{
+ return QmlDesigner::DesignerActionManager::instance().toolbarIcon(iconId);
+};
+
+} // namespace
+
+namespace EffectComposer {
+
+EffectShadersCodeEditor::EffectShadersCodeEditor(const QString &title, QWidget *parent)
+ : QWidget(parent)
+ , m_settings(new QSettings(qApp->organizationName(), qApp->applicationName(), this))
+{
+ setWindowFlag(Qt::Tool, true);
+ setWindowTitle(title);
+
+ m_fragmentEditor = createJSEditor();
+ m_vertexEditor = createJSEditor();
+
+ connect(
+ m_fragmentEditor,
+ &QPlainTextEdit::textChanged,
+ this,
+ &EffectShadersCodeEditor::fragmentValueChanged);
+ connect(
+ m_vertexEditor,
+ &QPlainTextEdit::textChanged,
+ this,
+ &EffectShadersCodeEditor::vertexValueChanged);
+
+ setupUIComponents();
+}
+
+EffectShadersCodeEditor::~EffectShadersCodeEditor()
+{
+ m_fragmentEditor->deleteLater();
+ m_vertexEditor->deleteLater();
+}
+
+void EffectShadersCodeEditor::showWidget()
+{
+ readAndApplyLiveUpdateSettings();
+ show();
+ raise();
+ m_vertexEditor->setFocus();
+}
+
+void EffectShadersCodeEditor::showWidget(int x, int y)
+{
+ showWidget();
+ move(QPoint(x, y));
+}
+
+QString EffectShadersCodeEditor::fragmentValue() const
+{
+ if (!m_fragmentEditor)
+ return {};
+
+ return m_fragmentEditor->document()->toPlainText();
+}
+
+void EffectShadersCodeEditor::setFragmentValue(const QString &text)
+{
+ if (m_fragmentEditor)
+ m_fragmentEditor->setEditorTextWithIndentation(text);
+}
+
+QString EffectShadersCodeEditor::vertexValue() const
+{
+ if (!m_vertexEditor)
+ return {};
+
+ return m_vertexEditor->document()->toPlainText();
+}
+
+void EffectShadersCodeEditor::setVertexValue(const QString &text)
+{
+ if (m_vertexEditor)
+ m_vertexEditor->setEditorTextWithIndentation(text);
+}
+
+bool EffectShadersCodeEditor::liveUpdate() const
+{
+ return m_liveUpdate;
+}
+
+void EffectShadersCodeEditor::setLiveUpdate(bool liveUpdate)
+{
+ if (m_liveUpdate == liveUpdate)
+ return;
+
+ m_liveUpdate = liveUpdate;
+ writeLiveUpdateSettings();
+
+ emit liveUpdateChanged(m_liveUpdate);
+
+ if (m_liveUpdate)
+ emit rebakeRequested();
+}
+
+EffectCodeEditorWidget *EffectShadersCodeEditor::createJSEditor()
+{
+ static EffectCodeEditorFactory f;
+ TextEditor::BaseTextEditor *editor = qobject_cast(
+ f.createEditor());
+ Q_ASSERT(editor);
+
+ editor->setParent(this);
+
+ EffectCodeEditorWidget *editorWidget = qobject_cast(
+ editor->editorWidget());
+ Q_ASSERT(editorWidget);
+
+ editorWidget->setLineNumbersVisible(false);
+ editorWidget->setMarksVisible(false);
+ editorWidget->setCodeFoldingSupported(false);
+ editorWidget->setTabChangesFocus(true);
+ editorWidget->unregisterAutoCompletion();
+ editorWidget->setParent(this);
+ editorWidget->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
+
+ return editorWidget;
+}
+
+void EffectShadersCodeEditor::setupUIComponents()
+{
+ QVBoxLayout *verticalLayout = new QVBoxLayout(this);
+ QTabWidget *tabWidget = new QTabWidget(this);
+
+ tabWidget->addTab(m_fragmentEditor, tr("Fragment Shader"));
+ tabWidget->addTab(m_vertexEditor, tr("Vertex Shader"));
+
+ verticalLayout->setContentsMargins(0, 0, 0, 0);
+ verticalLayout->addWidget(createToolbar());
+ verticalLayout->addWidget(tabWidget);
+
+ this->resize(660, 240);
+}
+
+void EffectShadersCodeEditor::closeEvent(QCloseEvent *event)
+{
+ QWidget::closeEvent(event);
+
+ if (!liveUpdate())
+ emit rebakeRequested();
+}
+
+void EffectShadersCodeEditor::writeLiveUpdateSettings()
+{
+ m_settings->setValue(EFFECTCOMPOSER_LIVE_UPDATE_KEY, m_liveUpdate);
+}
+
+void EffectShadersCodeEditor::readAndApplyLiveUpdateSettings()
+{
+ bool liveUpdateStatus = m_settings->value(EFFECTCOMPOSER_LIVE_UPDATE_KEY, false).toBool();
+
+ setLiveUpdate(liveUpdateStatus);
+}
+
+QToolBar *EffectShadersCodeEditor::createToolbar()
+{
+ using QmlDesigner::Theme;
+
+ QToolBar *toolbar = new QToolBar(this);
+
+ toolbar->setFixedHeight(Theme::toolbarSize());
+ toolbar->setFloatable(false);
+ toolbar->setContentsMargins(0, 0, 0, 0);
+
+ toolbar->setStyleSheet(Theme::replaceCssColors(
+ QString::fromUtf8(Utils::FileReader::fetchQrc(":/qmldesigner/stylesheet.css"))));
+
+ QAction *liveUpdateButton
+ = toolbar->addAction(toolbarIcon(IconId::LiveUpdateIcon), tr("Live Update"));
+ liveUpdateButton->setCheckable(true);
+ connect(liveUpdateButton, &QAction::toggled, this, &EffectShadersCodeEditor::setLiveUpdate);
+
+ QAction *applyAction = toolbar->addAction(toolbarIcon(IconId::SyncIcon), tr("Apply"));
+ connect(applyAction, &QAction::triggered, this, &EffectShadersCodeEditor::rebakeRequested);
+
+ auto syncLive = [liveUpdateButton, applyAction](bool liveState) {
+ liveUpdateButton->setChecked(liveState);
+ applyAction->setDisabled(liveState);
+ };
+
+ connect(this, &EffectShadersCodeEditor::liveUpdateChanged, this, syncLive);
+ syncLive(liveUpdate());
+
+ toolbar->addAction(liveUpdateButton);
+ toolbar->addAction(applyAction);
+
+ return toolbar;
+}
+
+} // namespace EffectComposer
diff --git a/src/plugins/effectcomposer/effectshaderscodeeditor.h b/src/plugins/effectcomposer/effectshaderscodeeditor.h
new file mode 100644
index 00000000000..f797315f4a6
--- /dev/null
+++ b/src/plugins/effectcomposer/effectshaderscodeeditor.h
@@ -0,0 +1,61 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#pragma once
+
+#include
+
+QT_FORWARD_DECLARE_CLASS(QSettings)
+QT_FORWARD_DECLARE_CLASS(QToolBar)
+
+namespace EffectComposer {
+
+class EffectCodeEditorWidget;
+
+class EffectShadersCodeEditor : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(bool liveUpdate READ liveUpdate WRITE setLiveUpdate NOTIFY liveUpdateChanged)
+
+public:
+ EffectShadersCodeEditor(const QString &title = tr("Untitled Editor"), QWidget *parent = nullptr);
+ ~EffectShadersCodeEditor() override;
+
+ void showWidget();
+ void showWidget(int x, int y);
+
+ QString fragmentValue() const;
+ void setFragmentValue(const QString &text);
+
+ QString vertexValue() const;
+ void setVertexValue(const QString &text);
+
+ bool liveUpdate() const;
+ void setLiveUpdate(bool liveUpdate);
+
+signals:
+ void liveUpdateChanged(bool);
+ void fragmentValueChanged();
+ void vertexValueChanged();
+ void rebakeRequested();
+
+protected:
+ using QWidget::show;
+ EffectCodeEditorWidget *createJSEditor();
+ void setupUIComponents();
+
+ void closeEvent(QCloseEvent *event) override;
+
+private:
+ void writeLiveUpdateSettings();
+ void readAndApplyLiveUpdateSettings();
+ QToolBar *createToolbar();
+
+ QSettings *m_settings = nullptr;
+ QPointer m_fragmentEditor;
+ QPointer m_vertexEditor;
+
+ bool m_liveUpdate = false;
+};
+
+} // namespace EffectComposer
diff --git a/src/plugins/effectcomposer/uniform.cpp b/src/plugins/effectcomposer/uniform.cpp
index 590b38b423b..c42f11063d6 100644
--- a/src/plugins/effectcomposer/uniform.cpp
+++ b/src/plugins/effectcomposer/uniform.cpp
@@ -57,6 +57,14 @@ Uniform::Uniform(const QString &effectName, const QJsonObject &propObj, const QS
m_backendValue = new QmlDesigner::PropertyEditorValue(this);
m_backendValue->setValue(value);
+
+ connect(m_backendValue, &QmlDesigner::PropertyEditorValue::dropCommitted,
+ this, [this](const QString &dropData) {
+ m_backendValue->setValue(dropData);
+ auto *model = QmlDesigner::QmlDesignerPlugin::instance()
+ ->currentDesignDocument()->currentModel();
+ model->endDrag();
+ });
}
Uniform::Type Uniform::type() const
diff --git a/src/plugins/insight/insightmodel.cpp b/src/plugins/insight/insightmodel.cpp
index 50474ffecff..3a4d03124ce 100644
--- a/src/plugins/insight/insightmodel.cpp
+++ b/src/plugins/insight/insightmodel.cpp
@@ -7,9 +7,10 @@
#include
#include
#include
+#include
+#include
#include
#include
-#include
#include
#include
@@ -192,7 +193,9 @@ Qt::CheckState checkState(const std::vector &a, const std::vectorsetCheckLinkErrors(false);
rewriter->setTextModifier(modifier.get());
+#ifdef QDS_USE_PROJECTSTORAGE
+ model = QmlDesigner::Model::create(projectStorageDependencies,
+ "Item",
+ {Import::createLibraryImport("QtQuick")},
+ filePath);
+#else
model = QmlDesigner::Model::create("QtQuick.Item", 2, 1);
+#endif
model->setRewriterView(rewriter.get());
}
@@ -221,9 +231,12 @@ struct ModelBuilder
} // namespace
-InsightModel::InsightModel(InsightView *view, ExternalDependenciesInterface &externalDependencies)
+InsightModel::InsightModel(InsightView *view,
+ ExternalDependenciesInterface &externalDependencies,
+ QmlDesignerProjectManager &projectManager)
: m_insightView(view)
, m_externalDependencies(externalDependencies)
+ , m_projectManager(projectManager)
, m_fileSystemWatcher(new Utils::FileSystemWatcher(this))
{
QObject::connect(ProjectExplorer::ProjectManager::instance(),
@@ -446,7 +459,9 @@ void InsightModel::setEnabled(bool value)
return;
}
- ModelBuilder builder(m_mainQmlInfo.absoluteFilePath(), m_externalDependencies);
+ ModelBuilder builder(m_mainQmlInfo.absoluteFilePath(),
+ m_externalDependencies,
+ m_projectManager.projectStorageDependencies());
if (!builder.model) {
qWarning() << "Could not create model" << m_mainQmlInfo.absoluteFilePath();
@@ -613,7 +628,9 @@ int InsightModel::devicePixelRatio()
void InsightModel::parseMainQml()
{
- ModelBuilder builder(m_mainQmlInfo.absoluteFilePath(), m_externalDependencies);
+ ModelBuilder builder(m_mainQmlInfo.absoluteFilePath(),
+ m_externalDependencies,
+ m_projectManager.projectStorageDependencies());
if (!builder.model)
return;
diff --git a/src/plugins/insight/insightmodel.h b/src/plugins/insight/insightmodel.h
index b21d7e36205..302d79e25b4 100644
--- a/src/plugins/insight/insightmodel.h
+++ b/src/plugins/insight/insightmodel.h
@@ -39,7 +39,9 @@ class InsightModel : public QAbstractListModel
};
public:
- InsightModel(InsightView *view, class ExternalDependenciesInterface &externalDependencies);
+ InsightModel(InsightView *view,
+ class ExternalDependenciesInterface &externalDependencies,
+ class QmlDesignerProjectManager &projectManager);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
@@ -109,6 +111,7 @@ private:
private:
QPointer m_insightView;
ExternalDependenciesInterface &m_externalDependencies;
+ QmlDesignerProjectManager &m_projectManager;
Utils::FileSystemWatcher *m_fileSystemWatcher;
diff --git a/src/plugins/insight/insightplugin.cpp b/src/plugins/insight/insightplugin.cpp
index f3bbcf5fa5c..a7172d807cf 100644
--- a/src/plugins/insight/insightplugin.cpp
+++ b/src/plugins/insight/insightplugin.cpp
@@ -20,7 +20,8 @@ class InsightPlugin final : public ExtensionSystem::IPlugin
auto *designerPlugin = QmlDesignerPlugin::instance();
auto &viewManager = designerPlugin->viewManager();
viewManager.registerView(std::make_unique(
- QmlDesignerPlugin::externalDependenciesForPluginInitializationOnly()));
+ QmlDesignerPlugin::externalDependenciesForPluginInitializationOnly(),
+ QmlDesignerPlugin::projectManagerForPluginInitializationOnly()));
return true;
}
diff --git a/src/plugins/insight/insightview.cpp b/src/plugins/insight/insightview.cpp
index 28101dc94e3..8a4dd5d19ec 100644
--- a/src/plugins/insight/insightview.cpp
+++ b/src/plugins/insight/insightview.cpp
@@ -14,9 +14,10 @@
namespace QmlDesigner {
-InsightView::InsightView(ExternalDependenciesInterface &externalDependencies)
+InsightView::InsightView(ExternalDependenciesInterface &externalDependencies,
+ QmlDesignerProjectManager &projectManager)
: AbstractView(externalDependencies)
- , m_insightModel(std::make_unique(this, externalDependencies))
+ , m_insightModel(std::make_unique(this, externalDependencies, projectManager))
{
Q_ASSERT(m_insightModel);
}
diff --git a/src/plugins/insight/insightview.h b/src/plugins/insight/insightview.h
index e39f34239c2..00f2877d234 100644
--- a/src/plugins/insight/insightview.h
+++ b/src/plugins/insight/insightview.h
@@ -15,13 +15,15 @@ namespace QmlDesigner {
class InsightModel;
class InsightWidget;
+class QmlDesignerProjectManager;
class InsightView : public AbstractView
{
Q_OBJECT
public:
- explicit InsightView(ExternalDependenciesInterface &externalDependencies);
+ explicit InsightView(ExternalDependenciesInterface &externalDependencies,
+ QmlDesignerProjectManager &projectManager);
~InsightView() override;
// AbstractView
diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt
index eb498302fbd..f97e3b4a169 100644
--- a/src/plugins/qmldesigner/CMakeLists.txt
+++ b/src/plugins/qmldesigner/CMakeLists.txt
@@ -52,13 +52,14 @@ add_qtc_plugin(QmlDesigner
QmlJS LanguageUtils QmlEditorWidgets AdvancedDockingSystem
Qt::QuickWidgets Qt::CorePrivate Qt::Xml Qt::Svg Sqlite Zip Qt::GuiPrivate
PUBLIC_DEPENDS
- QmlDesignerUtils QmlPuppetCommunication QmlDesignerCore
+ QmlDesignerUtils QmlPuppetCommunication QmlDesignerCore DesignSystem
DEFINES
IDE_LIBRARY_BASENAME=\"${IDE_LIBRARY_BASE_PATH}\"
SHARE_QML_PATH="${CMAKE_CURRENT_SOURCE_DIR}/../../../share/qtcreator/qmldesigner"
- $<$:QDS_USE_PROJECTSTORAGE>
$<$:QTC_USE_QML_DESIGNER_LITE>
$<$:DETACH_DISABLED_VIEWS>
+ PUBLIC_DEFINES
+ $<$:QDS_USE_PROJECTSTORAGE>
INCLUDES
${CMAKE_CURRENT_LIST_DIR}/libs
${CMAKE_CURRENT_LIST_DIR}/components
@@ -725,14 +726,6 @@ extend_qtc_plugin(QmlDesigner
messagemodel.h
)
-extend_qtc_plugin(QmlDesigner
- SOURCES_PREFIX components/designsystem
- SOURCES
- dsconstants.h
- dsthememanager.h dsthememanager.cpp
- dsthemegroup.cpp dsthemegroup.h
-)
-
add_qtc_plugin(assetexporterplugin
PLUGIN_CLASS AssetExporterPlugin
CONDITION TARGET QmlDesigner
diff --git a/src/plugins/qmldesigner/assetexporterplugin/assetexporter.cpp b/src/plugins/qmldesigner/assetexporterplugin/assetexporter.cpp
index 5fd0c5e0fa7..62f0522fafc 100644
--- a/src/plugins/qmldesigner/assetexporterplugin/assetexporter.cpp
+++ b/src/plugins/qmldesigner/assetexporterplugin/assetexporter.cpp
@@ -85,13 +85,13 @@ private:
std::atomic m_quitDumper;
};
-
-
-AssetExporter::AssetExporter(AssetExporterView *view, ProjectExplorer::Project *project, QObject *parent) :
- QObject(parent),
- m_currentState(*this),
- m_project(project),
- m_view(view)
+AssetExporter::AssetExporter(AssetExporterView *view,
+ ProjectExplorer::Project *project,
+ ProjectStorageDependencies projectStorageDependencies)
+ : m_currentState(*this)
+ , m_project(project)
+ , m_view(view)
+ , m_projectStorageDependencies{projectStorageDependencies}
{
connect(m_view, &AssetExporterView::loadingFinished, this, &AssetExporter::onQmlFileLoaded);
connect(m_view, &AssetExporterView::loadingError, this, &AssetExporter::notifyLoadError);
@@ -260,7 +260,14 @@ void AssetExporter::preprocessQmlFile(const Utils::FilePath &path)
{
// Load the QML file and assign UUIDs to items having none.
// Meanwhile cache the Component UUIDs as well
- ModelPointer model(Model::create("Item", 2, 7));
+#ifdef QDS_USE_PROJECTSTORAGE
+ ModelPointer model = Model::create(m_projectStorageDependencies,
+ "Item",
+ {Import::createLibraryImport("QtQuick")},
+ path.path());
+#else
+ ModelPointer model = Model::create("Item", 2, 7);
+#endif
Utils::FileReader reader;
if (!reader.fetch(path)) {
ExportNotification::addError(tr("Cannot preprocess file: %1. Error %2")
diff --git a/src/plugins/qmldesigner/assetexporterplugin/assetexporter.h b/src/plugins/qmldesigner/assetexporterplugin/assetexporter.h
index f356d56a0d0..36e7d29136b 100644
--- a/src/plugins/qmldesigner/assetexporterplugin/assetexporter.h
+++ b/src/plugins/qmldesigner/assetexporterplugin/assetexporter.h
@@ -32,8 +32,9 @@ public:
ExportingDone
};
- AssetExporter(AssetExporterView *view, ProjectExplorer::Project *project,
- QObject *parent = nullptr);
+ AssetExporter(AssetExporterView *view,
+ ProjectExplorer::Project *project,
+ ProjectStorageDependencies projectStorageDependencies);
~AssetExporter();
void exportQml(const Utils::FilePaths &qmlFiles, const Utils::FilePath &exportPath,
@@ -89,6 +90,7 @@ private:
QHash m_componentUuidCache;
QSet m_usedHashes;
QHash m_assets;
+ ProjectStorageDependencies m_projectStorageDependencies;
std::unique_ptr m_assetDumper;
bool m_cancelled = false;
};
diff --git a/src/plugins/qmldesigner/assetexporterplugin/assetexporterplugin.cpp b/src/plugins/qmldesigner/assetexporterplugin/assetexporterplugin.cpp
index ea0899d07c6..6246e0ed36f 100644
--- a/src/plugins/qmldesigner/assetexporterplugin/assetexporterplugin.cpp
+++ b/src/plugins/qmldesigner/assetexporterplugin/assetexporterplugin.cpp
@@ -3,12 +3,13 @@
#include "assetexporterplugin.h"
-#include "assetexportpluginconstants.h"
#include "assetexportdialog.h"
#include "assetexporter.h"
#include "assetexporterview.h"
-#include "filepathmodel.h"
+#include "assetexportpluginconstants.h"
#include "componentexporter.h"
+#include "filepathmodel.h"
+#include
#include "dumpers/itemnodedumper.h"
#include "dumpers/textnodedumper.h"
@@ -37,6 +38,7 @@
namespace QmlDesigner {
AssetExporterPlugin::AssetExporterPlugin()
+ : m_projectManager{QmlDesigner::QmlDesignerPlugin::projectManagerForPluginInitializationOnly()}
{
ProjectExplorer::TaskHub::addCategory({Constants::TASK_CATEGORY_ASSET_EXPORT,
tr("Asset Export"),
@@ -44,6 +46,7 @@ AssetExporterPlugin::AssetExporterPlugin()
false});
auto *designerPlugin = QmlDesigner::QmlDesignerPlugin::instance();
+
auto &viewManager = designerPlugin->viewManager();
m_view = viewManager.registerView(std::make_unique(
designerPlugin->externalDependenciesForPluginInitializationOnly()));
@@ -79,7 +82,7 @@ void AssetExporterPlugin::onExport()
if (!exportDir.parentDir().isEmpty())
exportDir = exportDir.parentDir();
exportDir = exportDir.pathAppended(startupProject->displayName() + "_export");
- AssetExporter assetExporter(m_view, startupProject);
+ AssetExporter assetExporter(m_view, startupProject, m_projectManager.projectStorageDependencies());
AssetExportDialog assetExporterDialog(exportDir, assetExporter, model);
assetExporterDialog.exec();
}
diff --git a/src/plugins/qmldesigner/assetexporterplugin/assetexporterplugin.h b/src/plugins/qmldesigner/assetexporterplugin/assetexporterplugin.h
index 9261b4601f8..1c2b779138e 100644
--- a/src/plugins/qmldesigner/assetexporterplugin/assetexporterplugin.h
+++ b/src/plugins/qmldesigner/assetexporterplugin/assetexporterplugin.h
@@ -29,6 +29,7 @@ private:
void updateActions();
AssetExporterView *m_view = nullptr;
+ class QmlDesignerProjectManager &m_projectManager;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/assetexporterplugin/componentexporter.cpp b/src/plugins/qmldesigner/assetexporterplugin/componentexporter.cpp
index 701e9fdd244..5979ea2f657 100644
--- a/src/plugins/qmldesigner/assetexporterplugin/componentexporter.cpp
+++ b/src/plugins/qmldesigner/assetexporterplugin/componentexporter.cpp
@@ -21,19 +21,6 @@
namespace {
Q_LOGGING_CATEGORY(loggerInfo, "qtc.designer.assetExportPlugin.modelExporter", QtInfoMsg)
-
-static QByteArrayList populateLineage(const QmlDesigner::ModelNode &node)
-{
- QByteArrayList lineage;
- if (!node.isValid() || node.type().isEmpty())
- return {};
-
- for (auto &info : node.metaInfo().prototypes())
- lineage.append(info.typeName());
-
- return lineage;
-}
-
}
namespace QmlDesigner {
@@ -78,10 +65,9 @@ const QString &Component::name() const
NodeDumper *Component::createNodeDumper(const ModelNode &node) const
{
- QByteArrayList lineage = populateLineage(node);
std::unique_ptr reader;
for (auto &dumperCreator: m_readers) {
- std::unique_ptr r(dumperCreator->instance(lineage, node));
+ std::unique_ptr r(dumperCreator->instance(node));
if (r->isExportable()) {
if (reader) {
if (reader->priority() < r->priority())
diff --git a/src/plugins/qmldesigner/assetexporterplugin/componentexporter.h b/src/plugins/qmldesigner/assetexporterplugin/componentexporter.h
index cf816c748c9..59ee8a2e677 100644
--- a/src/plugins/qmldesigner/assetexporterplugin/componentexporter.h
+++ b/src/plugins/qmldesigner/assetexporterplugin/componentexporter.h
@@ -27,7 +27,7 @@ class NodeDumperCreatorBase
public:
virtual ~NodeDumperCreatorBase() {}
protected:
- virtual NodeDumper *instance(const QByteArrayList &, const ModelNode &) const = 0;
+ virtual NodeDumper *instance(const ModelNode &) const = 0;
friend Component;
};
@@ -39,9 +39,7 @@ public:
~NodeDumperCreator() = default;
protected:
- NodeDumper *instance(const QByteArrayList &lineage, const ModelNode &node) const {
- return new T(lineage, node);
- }
+ NodeDumper *instance(const ModelNode &node) const { return new T(node); }
};
} //Internal
diff --git a/src/plugins/qmldesigner/assetexporterplugin/dumpers/assetnodedumper.cpp b/src/plugins/qmldesigner/assetexporterplugin/dumpers/assetnodedumper.cpp
index fea0f19c801..3fd6cbb333f 100644
--- a/src/plugins/qmldesigner/assetexporterplugin/dumpers/assetnodedumper.cpp
+++ b/src/plugins/qmldesigner/assetexporterplugin/dumpers/assetnodedumper.cpp
@@ -14,18 +14,18 @@
namespace QmlDesigner {
using namespace Constants;
-AssetNodeDumper::AssetNodeDumper(const QByteArrayList &lineage, const ModelNode &node) :
- ItemNodeDumper(lineage, node)
+
+AssetNodeDumper::AssetNodeDumper(const ModelNode &node)
+ : ItemNodeDumper(node)
{
}
bool AssetNodeDumper::isExportable() const
{
- auto hasType = [this](const QByteArray &type) {
- return lineage().contains(type);
- };
- return hasType("QtQuick.Image") || hasType("QtQuick.Rectangle");
+ auto qtQuickImageMetaInfo = model()->qtQuickImageMetaInfo();
+ auto qtQuickRectangleMetaInfo = model()->qtQuickRectangleMetaInfo();
+ return metaInfo().isBasedOn(qtQuickImageMetaInfo, qtQuickRectangleMetaInfo);
}
QJsonObject AssetNodeDumper::json(Component &component) const
diff --git a/src/plugins/qmldesigner/assetexporterplugin/dumpers/assetnodedumper.h b/src/plugins/qmldesigner/assetexporterplugin/dumpers/assetnodedumper.h
index c7bba0b3720..1a5449efafc 100644
--- a/src/plugins/qmldesigner/assetexporterplugin/dumpers/assetnodedumper.h
+++ b/src/plugins/qmldesigner/assetexporterplugin/dumpers/assetnodedumper.h
@@ -10,7 +10,7 @@ class Component;
class AssetNodeDumper : public ItemNodeDumper
{
public:
- AssetNodeDumper(const QByteArrayList &lineage, const ModelNode &node);
+ AssetNodeDumper(const ModelNode &node);
~AssetNodeDumper() override = default;
bool isExportable() const override;
diff --git a/src/plugins/qmldesigner/assetexporterplugin/dumpers/itemnodedumper.cpp b/src/plugins/qmldesigner/assetexporterplugin/dumpers/itemnodedumper.cpp
index 3f5fc4a50c8..e7159d76626 100644
--- a/src/plugins/qmldesigner/assetexporterplugin/dumpers/itemnodedumper.cpp
+++ b/src/plugins/qmldesigner/assetexporterplugin/dumpers/itemnodedumper.cpp
@@ -22,16 +22,16 @@ static QString capitalize(const QString &str)
namespace QmlDesigner {
using namespace Constants;
-ItemNodeDumper::ItemNodeDumper(const QByteArrayList &lineage,
- const ModelNode &node) :
- NodeDumper(lineage, node)
+
+ItemNodeDumper::ItemNodeDumper(const ModelNode &node)
+ : NodeDumper(node)
{
}
bool QmlDesigner::ItemNodeDumper::isExportable() const
{
- return lineage().contains("QtQuick.Item");
+ return metaInfo().isQtQuickItem();
}
QJsonObject QmlDesigner::ItemNodeDumper::json([[maybe_unused]] QmlDesigner::Component &component) const
diff --git a/src/plugins/qmldesigner/assetexporterplugin/dumpers/itemnodedumper.h b/src/plugins/qmldesigner/assetexporterplugin/dumpers/itemnodedumper.h
index 25576bb4067..9752d37caef 100644
--- a/src/plugins/qmldesigner/assetexporterplugin/dumpers/itemnodedumper.h
+++ b/src/plugins/qmldesigner/assetexporterplugin/dumpers/itemnodedumper.h
@@ -11,7 +11,7 @@ class Component;
class ItemNodeDumper : public NodeDumper
{
public:
- ItemNodeDumper(const QByteArrayList &lineage, const ModelNode &node);
+ ItemNodeDumper(const ModelNode &node);
~ItemNodeDumper() override = default;
diff --git a/src/plugins/qmldesigner/assetexporterplugin/dumpers/nodedumper.cpp b/src/plugins/qmldesigner/assetexporterplugin/dumpers/nodedumper.cpp
index 390b0684c8c..521180f2f28 100644
--- a/src/plugins/qmldesigner/assetexporterplugin/dumpers/nodedumper.cpp
+++ b/src/plugins/qmldesigner/assetexporterplugin/dumpers/nodedumper.cpp
@@ -6,10 +6,11 @@
#include
namespace QmlDesigner {
-NodeDumper::NodeDumper(const QByteArrayList &lineage, const ModelNode &node) :
- m_node(node),
- m_objectNode(node),
- m_lineage(lineage)
+NodeDumper::NodeDumper(const ModelNode &node)
+ : m_node(node)
+ , m_objectNode(node)
+ , m_metaInfo(node.metaInfo())
+ , m_model{node.model()}
{
}
diff --git a/src/plugins/qmldesigner/assetexporterplugin/dumpers/nodedumper.h b/src/plugins/qmldesigner/assetexporterplugin/dumpers/nodedumper.h
index f735884e5d0..17bace9ad61 100644
--- a/src/plugins/qmldesigner/assetexporterplugin/dumpers/nodedumper.h
+++ b/src/plugins/qmldesigner/assetexporterplugin/dumpers/nodedumper.h
@@ -14,7 +14,7 @@ class ModelNode;
class NodeDumper
{
public:
- NodeDumper(const QByteArrayList &lineage, const ModelNode &node);
+ NodeDumper(const ModelNode &node);
virtual ~NodeDumper() = default;
@@ -22,16 +22,19 @@ public:
virtual bool isExportable() const = 0;
virtual QJsonObject json(Component& component) const = 0;
- const QByteArrayList& lineage() const { return m_lineage; }
+ const NodeMetaInfo &metaInfo() const { return m_metaInfo; }
const QmlObjectNode& objectNode() const { return m_objectNode; }
QVariant propertyValue(const PropertyName &name) const;
QString uuid() const;
+ Model *model() const { return m_model; }
+
protected:
const ModelNode &m_node;
private:
QmlObjectNode m_objectNode;
- QByteArrayList m_lineage;
+ NodeMetaInfo m_metaInfo;
+ Model *m_model = nullptr;
};
}
diff --git a/src/plugins/qmldesigner/assetexporterplugin/dumpers/textnodedumper.cpp b/src/plugins/qmldesigner/assetexporterplugin/dumpers/textnodedumper.cpp
index aaf87af73ba..5f96d3e2175 100644
--- a/src/plugins/qmldesigner/assetexporterplugin/dumpers/textnodedumper.cpp
+++ b/src/plugins/qmldesigner/assetexporterplugin/dumpers/textnodedumper.cpp
@@ -4,6 +4,8 @@
#include "textnodedumper.h"
#include "assetexportpluginconstants.h"
+#include
+
#include
#include
#include
@@ -35,18 +37,18 @@ QString toJsonAlignEnum(QString value) {
namespace QmlDesigner {
using namespace Constants;
-TextNodeDumper::TextNodeDumper(const QByteArrayList &lineage, const ModelNode &node) :
- ItemNodeDumper(lineage, node)
+
+TextNodeDumper::TextNodeDumper(const ModelNode &node)
+ : ItemNodeDumper(node)
{
}
bool TextNodeDumper::isExportable() const
{
- const QByteArrayList &baseClasses = lineage();
- return std::any_of(baseClasses.cbegin(), baseClasses.cend(), [](const QByteArray &type) {
- return type == "QtQuick.Text" || type == "QtQuick.Controls.Label";
- });
+ auto qtQuickTextMetaInfo = model()->qtQuickTextMetaInfo();
+ auto qtQuickControlsLabelMetaInfo = model()->qtQuickControlsLabelMetaInfo();
+ return metaInfo().isBasedOn(qtQuickTextMetaInfo, qtQuickControlsLabelMetaInfo);
}
QJsonObject TextNodeDumper::json([[maybe_unused]] Component &component) const
diff --git a/src/plugins/qmldesigner/assetexporterplugin/dumpers/textnodedumper.h b/src/plugins/qmldesigner/assetexporterplugin/dumpers/textnodedumper.h
index efd2ea5ca47..b084bdae48c 100644
--- a/src/plugins/qmldesigner/assetexporterplugin/dumpers/textnodedumper.h
+++ b/src/plugins/qmldesigner/assetexporterplugin/dumpers/textnodedumper.h
@@ -10,7 +10,7 @@ class Component;
class TextNodeDumper : public ItemNodeDumper
{
public:
- TextNodeDumper(const QByteArrayList &lineage, const ModelNode &node);
+ TextNodeDumper(const ModelNode &node);
~TextNodeDumper() override = default;
bool isExportable() const override;
diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp
index 3b7524faa00..19c7319d2c0 100644
--- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp
+++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp
@@ -41,7 +41,7 @@ void AssetsLibraryModel::createBackendModel()
QObject::connect(m_sourceFsModel, &QFileSystemModel::directoryLoaded, this,
[this]([[maybe_unused]] const QString &dir) {
- syncHasFiles();
+ syncIsEmpty();
});
m_fileWatcher = new Utils::FileSystemWatcher(parent());
@@ -202,7 +202,7 @@ bool AssetsLibraryModel::isSameOrDescendantPath(const QUrl &source, const QStrin
Utils::FilePath srcPath = Utils::FilePath::fromUrl(source);
Utils::FilePath targetPath = Utils::FilePath::fromString(target);
- return targetPath.isChildOf(srcPath);
+ return srcPath == targetPath || targetPath.isChildOf(srcPath);
}
bool AssetsLibraryModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
@@ -224,41 +224,20 @@ bool AssetsLibraryModel::filterAcceptsRow(int sourceRow, const QModelIndex &sour
}
}
-bool AssetsLibraryModel::checkHasFiles(const QModelIndex &parentIdx) const
+void AssetsLibraryModel::setIsEmpty(bool value)
{
- if (!parentIdx.isValid())
- return false;
-
- const int rowCount = this->rowCount(parentIdx);
- for (int i = 0; i < rowCount; ++i) {
- auto newIdx = this->index(i, 0, parentIdx);
- if (!isDirectory(newIdx))
- return true;
-
- if (checkHasFiles(newIdx))
- return true;
- }
-
- return false;
-}
-
-void AssetsLibraryModel::setHasFiles(bool value)
-{
- if (m_hasFiles != value) {
- m_hasFiles = value;
- emit hasFilesChanged();
+ if (m_isEmpty != value) {
+ m_isEmpty = value;
+ emit isEmptyChanged();
}
}
-bool AssetsLibraryModel::checkHasFiles() const
+void AssetsLibraryModel::syncIsEmpty()
{
- auto rootIdx = indexForPath(m_rootPath);
- return checkHasFiles(rootIdx);
-}
+ QModelIndex rootIdx = indexForPath(m_rootPath);
-void AssetsLibraryModel::syncHasFiles()
-{
- setHasFiles(checkHasFiles());
+ bool hasContent = rowCount(rootIdx);
+ setIsEmpty(!hasContent);
}
void AssetsLibraryModel::setRootPath(const QString &newPath)
diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h
index 27b5eb77f27..5b5525a01bf 100644
--- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h
+++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h
@@ -23,7 +23,7 @@ public:
void setRootPath(const QString &newPath);
void setSearchText(const QString &searchText);
- Q_PROPERTY(bool hasFiles READ hasFiles NOTIFY hasFilesChanged)
+ Q_PROPERTY(bool isEmpty READ isEmpty NOTIFY isEmptyChanged)
Q_INVOKABLE QString rootPath() const;
Q_INVOKABLE QString filePath(const QModelIndex &index) const;
@@ -36,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 syncHasFiles();
+ Q_INVOKABLE void syncIsEmpty();
Q_INVOKABLE QList parentIndices(const QModelIndex &index) const;
Q_INVOKABLE bool indexIsValid(const QModelIndex &index) const;
@@ -58,29 +58,27 @@ public:
return std::min(result, 1);
}
- bool hasFiles() const { return m_hasFiles; }
+ bool isEmpty() const { return m_isEmpty; }
signals:
void directoryLoaded(const QString &path);
void rootPathChanged();
- void hasFilesChanged();
+ void isEmptyChanged();
void fileChanged(const QString &path);
void effectsDeleted(const QStringList &effectNames);
private:
- void setHasFiles(bool value);
+ void setIsEmpty(bool value);
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
void resetModel();
void createBackendModel();
void destroyBackendModel();
- bool checkHasFiles(const QModelIndex &parentIdx) const;
- bool checkHasFiles() const;
QString m_searchText;
QString m_rootPath;
QFileSystemModel *m_sourceFsModel = nullptr;
- bool m_hasFiles = false;
+ bool m_isEmpty = true;
Utils::FileSystemWatcher *m_fileWatcher = nullptr;
};
diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp
index 1d5f68970d3..7d182b99c42 100644
--- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp
+++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp
@@ -7,6 +7,7 @@
#include "assetslibrarymodel.h"
#include "assetslibraryview.h"
+#include
#include
#include
#include
@@ -102,7 +103,6 @@ AssetsLibraryWidget::AssetsLibraryWidget(AsynchronousImageCache &asynchronousFon
, m_assetsIconProvider{new AssetsLibraryIconProvider(synchronousFontImageCache)}
, m_assetsModel{new AssetsLibraryModel(this)}
, m_assetsView{view}
- , m_createTextures{view}
, m_assetsWidget{Utils::makeUniqueObjectPtr(this)}
{
setWindowTitle(tr("Assets Library", "Title of assets library widget"));
@@ -237,18 +237,20 @@ int AssetsLibraryWidget::qtVersion() const
void AssetsLibraryWidget::addTextures(const QStringList &filePaths)
{
m_assetsView->executeInTransaction(__FUNCTION__, [&] {
- m_createTextures.execute(filePaths,
- AddTextureMode::Texture,
- Utils3D::active3DSceneId(m_assetsView->model()));
+ CreateTexture(m_assetsView)
+ .execute(filePaths,
+ AddTextureMode::Texture,
+ Utils3D::active3DSceneId(m_assetsView->model()));
});
}
void AssetsLibraryWidget::addLightProbe(const QString &filePath)
{
m_assetsView->executeInTransaction(__FUNCTION__, [&] {
- m_createTextures.execute({filePath},
- AddTextureMode::LightProbe,
- Utils3D::active3DSceneId(m_assetsView->model()));
+ CreateTexture(m_assetsView)
+ .execute(filePath,
+ AddTextureMode::LightProbe,
+ Utils3D::active3DSceneId(m_assetsView->model()));
});
}
@@ -257,8 +259,9 @@ void AssetsLibraryWidget::updateContextMenuActionsEnableState()
setHasMaterialLibrary(Utils3D::materialLibraryNode(m_assetsView).isValid()
&& m_assetsView->model()->hasImport("QtQuick3D"));
- ModelNode activeSceneEnv = m_createTextures.resolveSceneEnv(
- Utils3D::active3DSceneId(m_assetsView->model()));
+ ModelNode activeSceneEnv = Utils3D::resolveSceneEnv(m_assetsView,
+ Utils3D::active3DSceneId(
+ m_assetsView->model()));
setHasSceneEnv(activeSceneEnv.isValid());
}
@@ -394,11 +397,11 @@ void AssetsLibraryWidget::handleAssetsDrop(const QList &urls, const QStrin
if (destDir.isFile())
destDir = destDir.parentDir();
- QMessageBox mb;
- mb.setInformativeText("What would you like to do with the existing asset?");
- mb.addButton("Keep Both", QMessageBox::AcceptRole);
- mb.addButton("Replace", QMessageBox::ResetRole);
- mb.addButton("Cancel", QMessageBox::RejectRole);
+ QMessageBox msgBox;
+ msgBox.setInformativeText("What would you like to do with the existing asset?");
+ msgBox.addButton("Keep Both", QMessageBox::AcceptRole);
+ msgBox.addButton("Replace", QMessageBox::ResetRole);
+ msgBox.addButton("Cancel", QMessageBox::RejectRole);
for (const QUrl &url : urls) {
Utils::FilePath src = Utils::FilePath::fromUrl(url);
@@ -408,9 +411,9 @@ void AssetsLibraryWidget::handleAssetsDrop(const QList &urls, const QStrin
continue;
if (dest.exists()) {
- mb.setText("An asset named " + dest.fileName() + " already exists.");
- mb.exec();
- int userAction = mb.buttonRole(mb.clickedButton());
+ msgBox.setText("An asset named " + dest.fileName() + " already exists.");
+ msgBox.exec();
+ int userAction = msgBox.buttonRole(msgBox.clickedButton());
if (userAction == QMessageBox::AcceptRole) { // "Keep Both"
dest = Utils::FilePath::fromString(UniqueName::generatePath(dest.toString()));
@@ -424,8 +427,13 @@ void AssetsLibraryWidget::handleAssetsDrop(const QList &urls, const QStrin
}
}
- if (!src.renameFile(dest))
- qWarning() << __FUNCTION__ << "Failed to move asset from" << src << "to" << dest;
+ if (!src.renameFile(dest) && src.isDir()) {
+ QMessageBox errBox;
+ QString message = QString("Failed to move folder \"%1\".\nThe folder might contain subfolders or one of its files is in use.")
+ .arg(src.fileName());
+ errBox.setInformativeText(message);
+ errBox.exec();
+ }
}
if (m_assetsView->model())
@@ -439,7 +447,7 @@ QList AssetsLibraryWidget::createToolBarWidgets()
void AssetsLibraryWidget::handleSearchFilterChanged(const QString &filterText)
{
- if (filterText == m_filterText || (!m_assetsModel->hasFiles()
+ if (filterText == m_filterText || (m_assetsModel->isEmpty()
&& filterText.contains(m_filterText, Qt::CaseInsensitive)))
return;
diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.h b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.h
index 79deeb9efd3..5456fb139b4 100644
--- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.h
+++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.h
@@ -3,7 +3,6 @@
#pragma once
-#include "createtexture.h"
#include "previewtooltipbackend.h"
#include
@@ -135,7 +134,6 @@ private:
AssetsLibraryIconProvider *m_assetsIconProvider = nullptr;
AssetsLibraryModel *m_assetsModel = nullptr;
AssetsLibraryView *m_assetsView = nullptr;
- CreateTextures m_createTextures = nullptr;
Utils::UniqueObjectPtr m_assetsWidget;
std::unique_ptr m_fontPreviewTooltipBackend;
diff --git a/src/plugins/qmldesigner/components/bindingeditor/bindingeditorwidget.cpp b/src/plugins/qmldesigner/components/bindingeditor/bindingeditorwidget.cpp
index 91660e90908..b7b454ffc55 100644
--- a/src/plugins/qmldesigner/components/bindingeditor/bindingeditorwidget.cpp
+++ b/src/plugins/qmldesigner/components/bindingeditor/bindingeditorwidget.cpp
@@ -20,7 +20,6 @@
#include
-#include
#include
#include
diff --git a/src/plugins/qmldesigner/components/componentcore/bundlehelper.cpp b/src/plugins/qmldesigner/components/componentcore/bundlehelper.cpp
index 5d097aaef3b..3d803111516 100644
--- a/src/plugins/qmldesigner/components/componentcore/bundlehelper.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/bundlehelper.cpp
@@ -77,6 +77,7 @@ void BundleHelper::createImporter()
newNode.simplifiedTypeName(), "node"));
m_view->clearSelectedModelNodes();
m_view->selectModelNode(newNode);
+ m_view->resetPuppet();
});
}
});
@@ -104,6 +105,7 @@ void BundleHelper::createImporter()
newNode.simplifiedTypeName(), "node"));
m_view->clearSelectedModelNodes();
m_view->selectModelNode(newNode);
+ m_view->resetPuppet();
});
}
});
@@ -135,8 +137,16 @@ void BundleHelper::importBundleToProject()
" of Qt Design Studio"));
return;
}
+
QString bundleId = importedJsonObj.value("id").toString();
+ bool hasQuick3DImport = m_view->model()->hasImport("QtQuick3D");
+
+ if (!hasQuick3DImport) {
+ Import import = Import::createLibraryImport("QtQuick3D");
+ m_view->model()->changeImports({import}, {});
+ }
+
QTemporaryDir tempDir;
QTC_ASSERT(tempDir.isValid(), return);
auto bundlePath = Utils::FilePath::fromString(tempDir.path());
diff --git a/src/plugins/qmldesigner/components/componentcore/createtexture.cpp b/src/plugins/qmldesigner/components/componentcore/createtexture.cpp
index f595e0e47e7..cd8ea6cfd78 100644
--- a/src/plugins/qmldesigner/components/componentcore/createtexture.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/createtexture.cpp
@@ -114,10 +114,10 @@ ModelNode CreateTexture::execute(const QString &filePath, AddTextureMode mode, i
return {};
if (mode == AddTextureMode::LightProbe && sceneId != -1)
- assignTextureAsLightProbe(texture, sceneId);
+ Utils3D::assignTextureAsLightProbe(m_view, texture, sceneId);
- QTimer::singleShot(0, m_view, [this, texture]() {
- if (m_view->model() && texture.isValid()) {
+ QTimer::singleShot(0, m_view, [view = m_view, texture]() {
+ if (view && view->model() && texture.isValid()) {
QmlDesignerPlugin::instance()->mainWidget()->showDockWidget("MaterialBrowser");
Utils3D::selectTexture(texture);
}
@@ -210,6 +210,12 @@ ModelNode CreateTexture::execute(const ModelNode &texture)
return duplicateTextureNode;
}
+void CreateTexture::execute(const QStringList &filePaths, AddTextureMode mode, int sceneId)
+{
+ for (const QString &path : filePaths)
+ execute(path, mode, sceneId);
+}
+
bool CreateTexture::addFileToProject(const QString &filePath)
{
AddFilesResult result = ModelNodeOperations::addImageToProject(
@@ -260,48 +266,4 @@ ModelNode CreateTexture::createTextureFromImage(const Utils::FilePath &assetPat
return newTexNode;
}
-void CreateTexture::assignTextureAsLightProbe(const ModelNode &texture, int sceneId)
-{
- ModelNode sceneEnvNode = resolveSceneEnv(sceneId);
- QmlObjectNode sceneEnv = sceneEnvNode;
- if (sceneEnv.isValid()) {
- sceneEnv.setBindingProperty("lightProbe", texture.id());
- sceneEnv.setVariantProperty("backgroundMode",
- QVariant::fromValue(Enumeration("SceneEnvironment",
- "SkyBox")));
- }
-}
-
-ModelNode CreateTexture::resolveSceneEnv(int sceneId)
-{
- ModelNode activeSceneEnv;
- ModelNode selectedNode = m_view->firstSelectedModelNode();
-
- if (selectedNode.metaInfo().isQtQuick3DSceneEnvironment()) {
- activeSceneEnv = selectedNode;
- } else if (sceneId != -1) {
- ModelNode activeScene = Utils3D::active3DSceneNode(m_view);
- if (activeScene.isValid()) {
- QmlObjectNode view3D;
- if (activeScene.metaInfo().isQtQuick3DView3D()) {
- view3D = activeScene;
- } else {
- ModelNode sceneParent = activeScene.parentProperty().parentModelNode();
- if (sceneParent.metaInfo().isQtQuick3DView3D())
- view3D = sceneParent;
- }
- if (view3D.isValid())
- activeSceneEnv = m_view->modelNodeForId(view3D.expression("environment"));
- }
- }
-
- return activeSceneEnv;
-}
-
-void CreateTextures::execute(const QStringList &filePaths, AddTextureMode mode, int sceneId)
-{
- for (const QString &path : filePaths)
- CreateTexture::execute(path, mode, sceneId);
-}
-
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/componentcore/createtexture.h b/src/plugins/qmldesigner/components/componentcore/createtexture.h
index 450a7f7a0db..57ef9893cc0 100644
--- a/src/plugins/qmldesigner/components/componentcore/createtexture.h
+++ b/src/plugins/qmldesigner/components/componentcore/createtexture.h
@@ -3,7 +3,7 @@
#pragma once
-#include
+#include
namespace Utils {
class FilePath;
@@ -16,10 +16,8 @@ class ModelNode;
enum class AddTextureMode { Image, Texture, LightProbe };
-class CreateTexture : public QObject
+class CreateTexture
{
- Q_OBJECT
-
public:
CreateTexture(AbstractView *view);
@@ -28,8 +26,7 @@ public:
AddTextureMode mode = AddTextureMode::Texture,
int sceneId = -1);
ModelNode execute(const ModelNode &texture);
- ModelNode resolveSceneEnv(int sceneId);
- void assignTextureAsLightProbe(const ModelNode &texture, int sceneId);
+ void execute(const QStringList &filePaths, AddTextureMode mode, int sceneId = -1);
private:
bool addFileToProject(const QString &filePath);
@@ -38,11 +35,4 @@ private:
AbstractView *m_view = nullptr;
};
-class CreateTextures : public CreateTexture
-{
-public:
- using CreateTexture::CreateTexture;
- void execute(const QStringList &filePaths, AddTextureMode mode, int sceneId = -1);
-};
-
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/componentcore/designericons.h b/src/plugins/qmldesigner/components/componentcore/designericons.h
index 1bce6581bdb..98edfac0b59 100644
--- a/src/plugins/qmldesigner/components/componentcore/designericons.h
+++ b/src/plugins/qmldesigner/components/componentcore/designericons.h
@@ -80,6 +80,7 @@ public:
LightDirectionalIcon,
LightPointIcon,
LightSpotIcon,
+ LiveUpdateIcon,
LocalOrientIcon,
MakeComponentIcon,
MaterialIcon,
@@ -107,6 +108,7 @@ public:
SnappingIcon,
SnappingConfIcon,
SplitViewIcon,
+ SyncIcon,
TimelineIcon,
ToggleGroupIcon,
VisibilityIcon
diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
index db23abc4697..950575888e6 100644
--- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
@@ -6,6 +6,7 @@
#include "addimagesdialog.h"
#include "addsignalhandlerdialog.h"
#include "componentcore_constants.h"
+#include "createtexture.h"
#include "findimplementation.h"
#include "layoutingridlayout.h"
#include "modelnodecontextmenu_helper.h"
@@ -87,11 +88,14 @@ Utils::SmallString auxPropertyString(Utils::SmallStringView name)
{
return auxDataString + name;
}
-} // namespace
-inline static void reparentTo(const ModelNode &node, const QmlItemNode &parent)
+QString relativePathToQmlFile(const QString &absolutePath)
{
+ return DocumentManager::currentFilePath().toFileInfo().dir().relativeFilePath(absolutePath);
+}
+inline void reparentTo(const ModelNode &node, const QmlItemNode &parent)
+{
if (parent.isValid() && node.isValid()) {
NodeAbstractProperty parentProperty;
@@ -104,7 +108,7 @@ inline static void reparentTo(const ModelNode &node, const QmlItemNode &parent)
}
}
-inline static QPointF getUpperLeftPosition(const QList &modelNodeList)
+inline QPointF getUpperLeftPosition(const QList &modelNodeList)
{
QPointF postion(std::numeric_limits::max(), std::numeric_limits::max());
for (const ModelNode &modelNode : modelNodeList) {
@@ -120,13 +124,15 @@ inline static QPointF getUpperLeftPosition(const QList &modelNodeList
return postion;
}
-static void setUpperLeftPostionToNode(const ModelNode &layoutNode, const QList &modelNodeList)
+void setUpperLeftPostionToNode(const ModelNode &layoutNode, const QList &modelNodeList)
{
QPointF upperLeftPosition = getUpperLeftPosition(modelNodeList);
layoutNode.variantProperty("x").setValue(qRound(upperLeftPosition.x()));
layoutNode.variantProperty("y") .setValue(qRound(upperLeftPosition.y()));
}
+} // namespace
+
namespace ModelNodeOperations {
bool goIntoComponent(const ModelNode &modelNode)
@@ -1753,13 +1759,10 @@ void editInEffectComposer(const SelectionContext &selectionContext)
bool isEffectComposerActivated()
{
- const ExtensionSystem::PluginSpecs specs = ExtensionSystem::PluginManager::plugins();
- return std::ranges::find_if(specs,
- [](ExtensionSystem::PluginSpec *spec) {
- return spec->name() == "EffectComposer"
- && spec->isEffectivelyEnabled();
- })
- != specs.end();
+ using namespace ExtensionSystem;
+ return Utils::anyOf(PluginManager::plugins(), [](PluginSpec *spec) {
+ return spec->name() == "EffectComposer" && spec->isEffectivelyEnabled();
+ });
}
void openEffectComposer(const QString &filePath)
@@ -1905,41 +1908,15 @@ static bool moveNodeToParent(const NodeAbstractProperty &targetProperty, const M
return false;
}
-ModelNode createTextureNode(const NodeAbstractProperty &targetProp, const QString &imagePath)
+ModelNode createTextureNode(AbstractView *view, const QString &imagePath)
{
- AbstractView *view = targetProp.view();
QTC_ASSERT(view, return {});
- if (targetProp.isValid()) {
- // create a texture item lib
- ItemLibraryEntry itemLibraryEntry;
- itemLibraryEntry.setName("Texture");
- itemLibraryEntry.setType("QtQuick3D.Texture", 1, 0);
-
- // set texture source
- PropertyName prop = "source";
- QString type = "QUrl";
- QVariant val = imagePath;
- itemLibraryEntry.addProperty(prop, type, val);
-
- // create a texture
- ModelNode newModelNode = QmlItemNode::createQmlObjectNode(view,
- itemLibraryEntry,
- {},
- targetProp,
- false);
-
- // Rename the node based on source image
- QFileInfo fi(imagePath);
- newModelNode.setIdWithoutRefactoring(
- view->model()->generateNewId(fi.baseName(), "textureImage"));
- return newModelNode;
- }
- return {};
+ CreateTexture textureCreator(view);
+ return textureCreator.execute(imagePath, AddTextureMode::Texture);
}
bool dropAsImage3dTexture(const ModelNode &targetNode,
- const NodeAbstractProperty &targetProp,
const QString &imagePath,
ModelNode &newNode,
bool &outMoveNodesAfter)
@@ -1949,16 +1926,11 @@ bool dropAsImage3dTexture(const ModelNode &targetNode,
auto bindToProperty = [&](const PropertyName &propName) {
view->executeInTransaction("NavigatorTreeModel::dropAsImage3dTexture", [&] {
- newNode = createTextureNode(targetProp, imagePath);
+ newNode = createTextureNode(view, imagePath);
if (newNode.isValid()) {
BindingProperty bindProp = targetNode.bindingProperty(propName);
bindProp.setExpression(newNode.validId());
- ModelNode matLib = Utils3D::materialLibraryNode(view);
- if (matLib.isValid()) {
- NodeAbstractProperty matLibProp = matLib.defaultNodeAbstractProperty();
- matLibProp.reparentHere(newNode);
- outMoveNodesAfter = false;
- }
+ outMoveNodesAfter = false;
}
});
};
@@ -1979,7 +1951,7 @@ bool dropAsImage3dTexture(const ModelNode &targetNode,
if (dialog->result() == QDialog::Accepted) {
view->executeInTransaction("NavigatorTreeModel::dropAsImage3dTexture", [&] {
- newNode = createTextureNode(targetProp, imagePath);
+ newNode = createTextureNode(view, imagePath);
if (newNode.isValid()) // Automatically set the texture to selected property
targetNode.bindingProperty(dialog->selectedProperty())
.setExpression(newNode.validId());
@@ -1999,10 +1971,11 @@ bool dropAsImage3dTexture(const ModelNode &targetNode,
return newNode.isValid();
} else if (targetNode.metaInfo().isQtQuick3DTexture()) {
// if dropping an image on an existing texture, set the source
- targetNode.variantProperty("source").setValue(imagePath);
+ targetNode.variantProperty("source").setValue(relativePathToQmlFile(imagePath));
return true;
} else if (targetNode.metaInfo().isQtQuick3DModel()) {
- QTimer::singleShot(0, view, [targetNode, imagePath, view]() {
+ const QString relImagePath = relativePathToQmlFile(imagePath);
+ QTimer::singleShot(0, view, [targetNode, relImagePath, view]() {
if (view && targetNode.isValid()) {
// To MaterialBrowserView. Done async to avoid custom notification in transaction
QmlDesignerPlugin::instance()->mainWidget()->showDockWidget("MaterialBrowser");
@@ -2010,7 +1983,7 @@ bool dropAsImage3dTexture(const ModelNode &targetNode,
{targetNode},
{DocumentManager::currentFilePath()
.absolutePath()
- .pathAppended(imagePath)
+ .pathAppended(relImagePath)
.cleanPath()
.toString()});
}
@@ -2102,20 +2075,12 @@ ModelNode handleItemLibraryImageDrop(const QString &imagePath,
AbstractView *view = targetNode.view();
QTC_ASSERT(view, return {});
- const QString imagePathRelative
- = DocumentManager::currentFilePath().toFileInfo().dir().relativeFilePath(
- imagePath); // relative to .ui.qml file
-
ModelNode newModelNode;
- if (!dropAsImage3dTexture(targetNode,
- targetProperty,
- imagePathRelative,
- newModelNode,
- outMoveNodesAfter)) {
+ if (!dropAsImage3dTexture(targetNode, imagePath, newModelNode, outMoveNodesAfter)) {
if (targetNode.metaInfo().isQtQuickImage() || targetNode.metaInfo().isQtQuickBorderImage()) {
// if dropping an image on an existing image, set the source
- targetNode.variantProperty("source").setValue(imagePathRelative);
+ targetNode.variantProperty("source").setValue(relativePathToQmlFile(imagePath));
} else {
// create an image
QmlItemNode newItemNode = QmlItemNode::createQmlItemNodeFromImage(view,
@@ -2176,8 +2141,7 @@ ModelNode handleItemLibraryShaderDrop(const QString &shaderPath,
ModelNode newModelNode;
- const QString relPath = DocumentManager::currentFilePath().toFileInfo().dir().relativeFilePath(
- shaderPath);
+ const QString relPath = relativePathToQmlFile(shaderPath);
if (targetNode.metaInfo().isQtQuick3DShader()) {
// if dropping into an existing Shader, update
@@ -2233,8 +2197,7 @@ ModelNode handleItemLibrarySoundDrop(const QString &soundPath,
ModelNode newModelNode;
- const QString relPath = DocumentManager::currentFilePath().toFileInfo().dir().relativeFilePath(
- soundPath);
+ const QString relPath = relativePathToQmlFile(soundPath);
if (targetNode.metaInfo().isQtMultimediaSoundEffect()) {
// if dropping into on an existing SoundEffect, update
@@ -2268,7 +2231,6 @@ ModelNode handleItemLibrarySoundDrop(const QString &soundPath,
}
ModelNode handleItemLibraryTexture3dDrop(const QString &tex3DPath,
- NodeAbstractProperty targetProperty,
const ModelNode &targetNode,
bool &outMoveNodesAfter)
{
@@ -2279,24 +2241,9 @@ ModelNode handleItemLibraryTexture3dDrop(const QString &tex3DPath,
if (!view->model()->hasImport(import, true, true))
return {};
- const QString imagePath = DocumentManager::currentFilePath().toFileInfo().dir().relativeFilePath(
- tex3DPath); // relative to qml file
-
ModelNode newModelNode;
- if (!dropAsImage3dTexture(targetNode,
- targetProperty,
- imagePath,
- newModelNode,
- outMoveNodesAfter)) {
- view->executeInTransaction("NavigatorTreeModel::handleItemLibraryTexture3dDrop", [&] {
- // create a standalone Texture3D at drop location
- newModelNode = createTextureNode(targetProperty, imagePath);
- if (!NodeHints::fromModelNode(targetProperty.parentModelNode())
- .canBeContainerFor(newModelNode))
- newModelNode.destroy();
- });
- }
+ dropAsImage3dTexture(targetNode, tex3DPath, newModelNode, outMoveNodesAfter);
return newModelNode;
}
diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h
index 7538452848f..116ea90d1c7 100644
--- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h
+++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h
@@ -137,7 +137,7 @@ bool useLayerEffect();
bool validateEffect(const QString &effectPath);
bool isEffectComposerActivated();
-Utils::FilePath getImagesDefaultDirectory();
+QMLDESIGNERCOMPONENTS_EXPORT Utils::FilePath getImagesDefaultDirectory();
//Item Library and Assets related drop operations
QMLDESIGNERCOMPONENTS_EXPORT ModelNode handleItemLibraryEffectDrop(const QString &effectPath,
@@ -160,7 +160,6 @@ ModelNode handleItemLibrarySoundDrop(const QString &soundPath,
NodeAbstractProperty targetProperty,
const ModelNode &targetNode);
ModelNode handleItemLibraryTexture3dDrop(const QString &tex3DPath,
- NodeAbstractProperty targetProperty,
const ModelNode &targetNode,
bool &outMoveNodesAfter);
diff --git a/src/plugins/qmldesigner/components/componentcore/utils3d.cpp b/src/plugins/qmldesigner/components/componentcore/utils3d.cpp
index 7ddd0997cdf..e38fd544084 100644
--- a/src/plugins/qmldesigner/components/componentcore/utils3d.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/utils3d.cpp
@@ -252,6 +252,43 @@ void applyMaterialToModels(AbstractView *view, const ModelNode &material,
});
}
+ModelNode resolveSceneEnv(AbstractView *view, int sceneId)
+{
+ ModelNode activeSceneEnv;
+ ModelNode selectedNode = view->firstSelectedModelNode();
+
+ if (selectedNode.metaInfo().isQtQuick3DSceneEnvironment()) {
+ activeSceneEnv = selectedNode;
+ } else if (sceneId != -1) {
+ ModelNode activeScene = Utils3D::active3DSceneNode(view);
+ if (activeScene.isValid()) {
+ QmlObjectNode view3D;
+ if (activeScene.metaInfo().isQtQuick3DView3D()) {
+ view3D = activeScene;
+ } else {
+ ModelNode sceneParent = activeScene.parentProperty().parentModelNode();
+ if (sceneParent.metaInfo().isQtQuick3DView3D())
+ view3D = sceneParent;
+ }
+ if (view3D.isValid())
+ activeSceneEnv = view->modelNodeForId(view3D.expression("environment"));
+ }
+ }
+
+ return activeSceneEnv;
+}
+
+void assignTextureAsLightProbe(AbstractView *view, const ModelNode &texture, int sceneId)
+{
+ ModelNode sceneEnvNode = resolveSceneEnv(view, sceneId);
+ QmlObjectNode sceneEnv = sceneEnvNode;
+ if (sceneEnv.isValid()) {
+ sceneEnv.setBindingProperty("lightProbe", texture.id());
+ sceneEnv.setVariantProperty("backgroundMode",
+ QVariant::fromValue(Enumeration("SceneEnvironment", "SkyBox")));
+ }
+}
+
// This method should be executed within a transaction as it performs multiple modifications to the model
#ifdef QDS_USE_PROJECTSTORAGE
ModelNode createMaterial(AbstractView *view, const TypeName &typeName)
diff --git a/src/plugins/qmldesigner/components/componentcore/utils3d.h b/src/plugins/qmldesigner/components/componentcore/utils3d.h
index 546c90f8e70..6a7899589c3 100644
--- a/src/plugins/qmldesigner/components/componentcore/utils3d.h
+++ b/src/plugins/qmldesigner/components/componentcore/utils3d.h
@@ -40,10 +40,14 @@ void selectTexture(const ModelNode &texture);
ModelNode selectedMaterial(AbstractView *view);
ModelNode selectedTexture(AbstractView *view);
+ModelNode resolveSceneEnv(AbstractView *view, int sceneId);
+
QList getSelectedModels(AbstractView *view);
void applyMaterialToModels(AbstractView *view, const ModelNode &material,
const QList &models, bool add = false);
+void assignTextureAsLightProbe(AbstractView *view, const ModelNode &texture, int sceneId);
+
#ifdef QDS_USE_PROJECTSTORAGE
ModelNode createMaterial(AbstractView *view, const TypeName &typeName);
#else
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp
index 5151d89534e..e1f74075c2c 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp
@@ -57,7 +57,6 @@ ContentLibraryView::ContentLibraryView(AsynchronousImageCache &imageCache,
ExternalDependenciesInterface &externalDependencies)
: AbstractView(externalDependencies)
, m_imageCache(imageCache)
- , m_createTexture(this)
{}
ContentLibraryView::~ContentLibraryView()
@@ -88,15 +87,17 @@ WidgetInfo ContentLibraryView::widgetInfo()
m_draggedBundleItem = item;
});
- connect(m_widget, &ContentLibraryWidget::addTextureRequested, this,
- [&] (const QString &texPath, AddTextureMode mode) {
- executeInTransaction("ContentLibraryView::widgetInfo", [&]() {
- m_createTexture.execute(texPath, mode, m_sceneId);
- });
- });
+ connect(m_widget,
+ &ContentLibraryWidget::addTextureRequested,
+ this,
+ [&](const QString &texPath, AddTextureMode mode) {
+ executeInTransaction("ContentLibraryView::widgetInfo", [&]() {
+ CreateTexture(this).execute(texPath, mode, m_sceneId);
+ });
+ });
connect(m_widget, &ContentLibraryWidget::updateSceneEnvStateRequested, this, [this] {
- ModelNode activeSceneEnv = m_createTexture.resolveSceneEnv(m_sceneId);
+ ModelNode activeSceneEnv = Utils3D::resolveSceneEnv(this, m_sceneId);
const bool sceneEnvExists = activeSceneEnv.isValid();
m_widget->texturesModel()->setHasSceneEnv(sceneEnvExists);
m_widget->environmentsModel()->setHasSceneEnv(sceneEnvExists);
diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h
index deba7b93a61..f42423fd7d2 100644
--- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h
+++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h
@@ -90,7 +90,6 @@ private:
bool m_bundleMaterialAddToSelected = false;
bool m_hasQuick3DImport = false;
qint32 m_sceneId = -1;
- CreateTexture m_createTexture;
Utils::FilePath m_iconSavePath;
QString m_generatedFolderName;
QString m_bundleId;
diff --git a/src/plugins/qmldesigner/components/formeditor/movemanipulator.cpp b/src/plugins/qmldesigner/components/formeditor/movemanipulator.cpp
index 167282ea90f..516e7a3c609 100644
--- a/src/plugins/qmldesigner/components/formeditor/movemanipulator.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/movemanipulator.cpp
@@ -101,8 +101,9 @@ bool MoveManipulator::itemsCanReparented() const
void MoveManipulator::setDirectUpdateInNodeInstances(bool directUpdate)
{
- for (FormEditorItem* item : std::as_const(m_itemList)) {
- if (item && item->qmlItemNode().isValid())
+ const auto allFormEditorItems = m_view->scene()->allFormEditorItems();
+ for (FormEditorItem *item : std::as_const(m_itemList)) {
+ if (item && allFormEditorItems.contains(item) && item->qmlItemNode().isValid())
item->qmlItemNode().nodeInstance().setDirectUpdate(directUpdate);
}
}
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp
index 1d9bbf5cd34..0997d06853e 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp
@@ -376,10 +376,11 @@ void ItemLibraryModel::update(Model *model)
for (const ItemLibraryEntry &entry : itemLibEntries) {
NodeMetaInfo metaInfo;
- if constexpr (useProjectStorage())
- metaInfo = NodeMetaInfo{entry.typeId(), model->projectStorage()};
- else
- metaInfo = model->metaInfo(entry.typeName());
+#ifdef QDS_USE_PROJECTSTORAGE
+ metaInfo = NodeMetaInfo{entry.typeId(), model->projectStorage()};
+#else
+ metaInfo = model->metaInfo(entry.typeName());
+#endif
#ifdef QDS_USE_PROJECTSTORAGE
bool valid = metaInfo.isValid();
diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp
index 1d689e88a64..a6344fbb552 100644
--- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp
+++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp
@@ -209,7 +209,7 @@ WidgetInfo MaterialBrowserView::widgetInfo()
});
connect(texturesModel, &MaterialBrowserTexturesModel::updateSceneEnvStateRequested, this, [this] {
- ModelNode activeSceneEnv = CreateTexture(this).resolveSceneEnv(m_sceneId);
+ ModelNode activeSceneEnv = Utils3D::resolveSceneEnv(this, m_sceneId);
const bool sceneEnvExists = activeSceneEnv.isValid();
m_widget->materialBrowserTexturesModel()->setHasSceneEnv(sceneEnvExists);
});
@@ -222,12 +222,14 @@ WidgetInfo MaterialBrowserView::widgetInfo()
m_widget->materialBrowserTexturesModel()->setHasSingleModelSelection(hasModel);
});
- connect(texturesModel, &MaterialBrowserTexturesModel::applyAsLightProbeRequested, this,
- [&] (const ModelNode &texture) {
- executeInTransaction(__FUNCTION__, [&] {
- CreateTexture(this).assignTextureAsLightProbe(texture, m_sceneId);
- });
- });
+ connect(texturesModel,
+ &MaterialBrowserTexturesModel::applyAsLightProbeRequested,
+ this,
+ [&](const ModelNode &texture) {
+ executeInTransaction(__FUNCTION__, [&] {
+ Utils3D::assignTextureAsLightProbe(this, texture, m_sceneId);
+ });
+ });
}
return createWidgetInfo(m_widget.data(),
@@ -239,13 +241,9 @@ WidgetInfo MaterialBrowserView::widgetInfo()
void MaterialBrowserView::createTextures(const QStringList &assetPaths)
{
- auto *create = new CreateTextures(this);
-
executeInTransaction("MaterialBrowserView::createTextures", [&]() {
- create->execute(assetPaths, AddTextureMode::Texture, m_sceneId);
+ CreateTexture(this).execute(assetPaths, AddTextureMode::Texture, m_sceneId);
});
-
- create->deleteLater();
}
void MaterialBrowserView::modelAttached(Model *model)
@@ -740,11 +738,10 @@ void MaterialBrowserView::applyTextureToProperty(const QString &matId, const QSt
{
executeInTransaction(__FUNCTION__, [&] {
if (m_appliedTextureId.isEmpty() && !m_appliedTexturePath.isEmpty()) {
- auto texCreator = new CreateTexture(this);
- ModelNode tex = texCreator->execute(m_appliedTexturePath, AddTextureMode::Texture);
+ CreateTexture texCreator(this);
+ ModelNode tex = texCreator.execute(m_appliedTexturePath, AddTextureMode::Texture);
m_appliedTextureId = tex.id();
m_appliedTexturePath.clear();
- texCreator->deleteLater();
}
QTC_ASSERT(!m_appliedTextureId.isEmpty(), return);
diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp
index 7573c7c4288..40e7652e66a 100644
--- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp
+++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp
@@ -307,10 +307,8 @@ void MaterialBrowserWidget::acceptBundleTextureDropOnMaterial(int matIndex, cons
ModelNode mat = m_materialBrowserModel->materialAt(matIndex);
QTC_ASSERT(mat.isValid(), return);
- auto *creator = new CreateTexture(m_materialBrowserView);
-
m_materialBrowserView->executeInTransaction(__FUNCTION__, [&] {
- ModelNode tex = creator->execute(bundleTexPath.toLocalFile());
+ ModelNode tex = CreateTexture(m_materialBrowserView).execute(bundleTexPath.toLocalFile());
QTC_ASSERT(tex.isValid(), return);
m_materialBrowserModel->selectMaterial(matIndex);
@@ -319,8 +317,6 @@ void MaterialBrowserWidget::acceptBundleTextureDropOnMaterial(int matIndex, cons
if (m_materialBrowserView->model())
m_materialBrowserView->model()->endDrag();
-
- creator->deleteLater();
}
void MaterialBrowserWidget::acceptAssetsDrop(const QList &urls)
@@ -336,14 +332,12 @@ void MaterialBrowserWidget::acceptAssetsDropOnMaterial(int matIndex, const QList
ModelNode mat = m_materialBrowserModel->materialAt(matIndex);
QTC_ASSERT(mat.isValid(), return);
- auto *creator = new CreateTexture(m_materialBrowserView);
-
- QString imageSrc = Utils::findOrDefault(urls, [] (const QUrl &url) {
- return Asset(url.toLocalFile()).isValidTextureSource();
- }).toLocalFile();
+ QString imageSrc = Utils::findOrDefault(urls, [](const QUrl &url) {
+ return Asset(url.toLocalFile()).isValidTextureSource();
+ }).toLocalFile();
m_materialBrowserView->executeInTransaction(__FUNCTION__, [&] {
- ModelNode tex = creator->execute(imageSrc);
+ ModelNode tex = CreateTexture(m_materialBrowserView).execute(imageSrc);
QTC_ASSERT(tex.isValid(), return);
m_materialBrowserModel->selectMaterial(matIndex);
@@ -352,8 +346,6 @@ void MaterialBrowserWidget::acceptAssetsDropOnMaterial(int matIndex, const QList
if (m_materialBrowserView->model())
m_materialBrowserView->model()->endDrag();
-
- creator->deleteLater();
}
void MaterialBrowserWidget::acceptTextureDropOnMaterial(int matIndex, const QString &texId)
diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
index 341f3694857..2c6a02002d4 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
+++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
@@ -177,8 +177,8 @@ static void reparentModelNodeToNodeProperty(NodeAbstractProperty &parentProperty
}
}
-NavigatorTreeModel::NavigatorTreeModel(QObject *parent) : QAbstractItemModel(parent)
- , m_createTextures(Utils::makeUniqueObjectPtr(m_view))
+NavigatorTreeModel::NavigatorTreeModel(QObject *parent)
+ : QAbstractItemModel(parent)
{
m_actionManager = &QmlDesignerPlugin::instance()->viewManager().designerActionManager();
}
@@ -324,7 +324,10 @@ QList NavigatorTreeModel::filteredList(const NodeListProperty &proper
if (filter) {
list.append(::Utils::filtered(nameFilteredList, [](const ModelNode &arg) {
- const bool value = (QmlItemNode::isValidQmlItemNode(arg) || NodeHints::fromModelNode(arg).visibleInNavigator())
+ const bool visibleInNavigator = NodeHints::fromModelNode(arg).visibleInNavigator();
+ const bool hideInNavigator = NodeHints::fromModelNode(arg).hideInNavigator();
+ const bool value = ((QmlItemNode::isValidQmlItemNode(arg) && !hideInNavigator)
+ || visibleInNavigator)
&& arg.id() != Constants::MATERIAL_LIB_ID;
return value;
}));
@@ -583,17 +586,10 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
bool moveNodesAfter = false;
m_view->executeInTransaction(__FUNCTION__, [&] {
- m_createTextures->execute(QStringList{texturePath},
- AddTextureMode::Image,
- Utils3D::active3DSceneId(m_view->model()));
- QString textureName = Utils::FilePath::fromString(texturePath).fileName();
- QString textureAbsolutePath = DocumentManager::currentResourcePath()
- .pathAppended("images/" + textureName).toString();
- ModelNodeOperations::handleItemLibraryImageDrop(textureAbsolutePath,
- targetProperty,
- modelNodeForIndex(
- rowModelIndex),
- moveNodesAfter);
+ ModelNodeOperations::handleItemLibraryTexture3dDrop(texturePath,
+ modelNodeForIndex(
+ rowModelIndex),
+ moveNodesAfter);
});
}
}
@@ -664,7 +660,6 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
} else if (assetType == Constants::MIME_TYPE_ASSET_TEXTURE3D) {
currNode = ModelNodeOperations::handleItemLibraryTexture3dDrop(
assetPath,
- targetProperty,
modelNodeForIndex(rowModelIndex),
moveNodesAfter);
} else if (assetType == Constants::MIME_TYPE_ASSET_EFFECT) {
@@ -853,34 +848,6 @@ bool QmlDesigner::NavigatorTreeModel::moveNodeToParent(const NodeAbstractPropert
return false;
}
-ModelNode NavigatorTreeModel::createTextureNode(const NodeAbstractProperty &targetProp,
- const QString &imagePath)
-{
- if (targetProp.isValid()) {
- // create a texture item lib
- ItemLibraryEntry itemLibraryEntry;
- itemLibraryEntry.setName("Texture");
- itemLibraryEntry.setType("QtQuick3D.Texture", 1, 0);
-
- // set texture source
- PropertyName prop = "source";
- QString type = "QUrl";
- QVariant val = imagePath;
- itemLibraryEntry.addProperty(prop, type, val);
-
- // create a texture
- ModelNode newModelNode = QmlItemNode::createQmlObjectNode(m_view, itemLibraryEntry, {},
- targetProp, false);
-
- // Rename the node based on source image
- QFileInfo fi(imagePath);
- newModelNode.setIdWithoutRefactoring(
- m_view->model()->generateNewId(fi.baseName(), "textureImage"));
- return newModelNode;
- }
- return {};
-}
-
namespace {
NodeMetaInfo propertyType(const NodeAbstractProperty &property)
{
diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h
index 7e6df8b2ec1..350b72dd608 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h
+++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.h
@@ -17,7 +17,6 @@ QT_FORWARD_DECLARE_CLASS(QPixmap)
namespace QmlDesigner {
-class CreateTextures;
class DesignerActionManager;
class Model;
class ModelNode;
@@ -88,7 +87,7 @@ public:
void updateToolTipPixmap(const ModelNode &node, const QPixmap &pixmap);
signals:
- void toolTipPixmapUpdated(const QString &id, const QPixmap &pixmap) const;
+ void toolTipPixmapUpdated(const QString &id, const QPixmap &pixmap);
private:
void moveNodesInteractive(NodeAbstractProperty &parentProperty, const QList &modelNodes,
@@ -96,16 +95,17 @@ private:
void handleInternalDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex);
void handleItemLibraryItemDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex);
- bool dropAsImage3dTexture(const ModelNode &targetNode, const NodeAbstractProperty &targetProp,
- const QString &imagePath, ModelNode &newNode, bool &outMoveNodesAfter);
- ModelNode createTextureNode(const NodeAbstractProperty &targetProp, const QString &imagePath);
+ bool dropAsImage3dTexture(const ModelNode &targetNode,
+ const NodeAbstractProperty &targetProp,
+ const QString &imagePath,
+ ModelNode &newNode,
+ bool &outMoveNodesAfter);
QList nodesToPersistentIndex(const QList &modelNodes);
void addImport(const QString &importName);
QList filteredList(const NodeListProperty &property, bool filter, bool reverseOrder) const;
bool moveNodeToParent(const NodeAbstractProperty &targetProperty, const ModelNode &newModelNode);
QPointer m_view;
- Utils::UniqueObjectPtr m_createTextures;
mutable QHash m_nodeIndexHash;
mutable QHash > m_rowCache;
bool m_showOnlyVisibleItems = true;
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp
index 77b98786e01..b4e7f9a6eac 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp
@@ -521,9 +521,8 @@ void PropertyEditorValue::commitDrop(const QString &dropData)
m_modelNode.view()->executeInTransaction(__FUNCTION__, [&] {
ModelNode texture = m_modelNode.view()->modelNodeForInternalId(dropData.toInt());
if (!texture || !texture.metaInfo().isQtQuick3DTexture()) {
- auto texCreator = new CreateTexture(m_modelNode.view());
- texture = texCreator->execute(dropData, AddTextureMode::Texture);
- texCreator->deleteLater();
+ CreateTexture texCreator(m_modelNode.view());
+ texture = texCreator.execute(dropData, AddTextureMode::Texture);
}
// assign the texture to the property
@@ -531,7 +530,12 @@ void PropertyEditorValue::commitDrop(const QString &dropData)
});
}
- m_modelNode.view()->model()->endDrag();
+ emit dropCommitted(dropData);
+
+ if (!m_modelNode.model())
+ return;
+
+ m_modelNode.model()->endDrag();
}
void PropertyEditorValue::openMaterialEditor(int idx)
diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.h b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.h
index 997640d377e..d8cee333cbb 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.h
+++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.h
@@ -200,6 +200,7 @@ signals:
void isValidChanged();
void isExplicitChanged();
void hasActiveDragChanged();
+ void dropCommitted(QString dropData);
private:
QStringList generateStringList(const QString &string) const;
diff --git a/src/plugins/qmldesigner/components/texteditor/texteditorwidget.cpp b/src/plugins/qmldesigner/components/texteditor/texteditorwidget.cpp
index 6a4d2eb5a6c..642e16055d5 100644
--- a/src/plugins/qmldesigner/components/texteditor/texteditorwidget.cpp
+++ b/src/plugins/qmldesigner/components/texteditor/texteditorwidget.cpp
@@ -339,7 +339,6 @@ void TextEditorWidget::dropEvent(QDropEvent *dropEvent)
targetNode);
} else if (assetType == Constants::MIME_TYPE_ASSET_TEXTURE3D) {
newModelNode = ModelNodeOperations::handleItemLibraryTexture3dDrop(assetPath,
- targetProperty,
targetNode,
moveNodesAfter);
} else if (assetType == Constants::MIME_TYPE_ASSET_EFFECT) {
diff --git a/src/plugins/qmldesigner/components/textureeditor/textureeditorview.cpp b/src/plugins/qmldesigner/components/textureeditor/textureeditorview.cpp
index 2c73685c196..9d10644e89f 100644
--- a/src/plugins/qmldesigner/components/textureeditor/textureeditorview.cpp
+++ b/src/plugins/qmldesigner/components/textureeditor/textureeditorview.cpp
@@ -58,7 +58,6 @@ TextureEditorView::TextureEditorView(AsynchronousImageCache &imageCache,
: AbstractView{externalDependencies}
, m_imageCache(imageCache)
, m_stackedWidget(new QStackedWidget)
- , m_createTexture(new CreateTexture(this))
, m_dynamicPropertiesModel(new DynamicPropertiesModel(true, this))
{
m_updateShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_F12), m_stackedWidget);
@@ -399,7 +398,7 @@ void TextureEditorView::handleToolBarAction(int action)
case TextureEditorContextObject::AddNewTexture: {
if (!model())
break;
- m_createTexture->execute();
+ CreateTexture(this).execute();
break;
}
@@ -845,7 +844,7 @@ void TextureEditorView::importsChanged([[maybe_unused]] const Imports &addedImpo
void TextureEditorView::duplicateTexture(const ModelNode &texture)
{
QTC_ASSERT(texture.isValid(), return);
- m_createTexture->execute(texture);
+ CreateTexture(this).execute(texture);
}
void TextureEditorView::customNotification([[maybe_unused]] const AbstractView *view,
diff --git a/src/plugins/qmldesigner/components/textureeditor/textureeditorview.h b/src/plugins/qmldesigner/components/textureeditor/textureeditorview.h
index 5611cf3ab6b..00336998b6c 100644
--- a/src/plugins/qmldesigner/components/textureeditor/textureeditorview.h
+++ b/src/plugins/qmldesigner/components/textureeditor/textureeditorview.h
@@ -18,7 +18,6 @@ QT_END_NAMESPACE
namespace QmlDesigner {
-class CreateTexture;
class DynamicPropertiesModel;
class ModelNode;
class QmlObjectNode;
@@ -126,7 +125,6 @@ private:
bool m_selectedTextureChanged = false;
QPointer m_colorDialog;
- QPointer m_createTexture;
DynamicPropertiesModel *m_dynamicPropertiesModel = nullptr;
};
diff --git a/src/plugins/qmldesigner/libs/CMakeLists.txt b/src/plugins/qmldesigner/libs/CMakeLists.txt
index 7cac0a93a3d..be2d12733cb 100644
--- a/src/plugins/qmldesigner/libs/CMakeLists.txt
+++ b/src/plugins/qmldesigner/libs/CMakeLists.txt
@@ -1,2 +1,3 @@
add_subdirectory(designercore)
add_subdirectory(qmldesignerutils)
+add_subdirectory(designsystem)
diff --git a/src/plugins/qmldesigner/libs/designercore/CMakeLists.txt b/src/plugins/qmldesigner/libs/designercore/CMakeLists.txt
index 977bced8f23..1ebb8c48322 100644
--- a/src/plugins/qmldesigner/libs/designercore/CMakeLists.txt
+++ b/src/plugins/qmldesigner/libs/designercore/CMakeLists.txt
@@ -375,6 +375,11 @@ extend_qtc_library(QmlDesignerCore
DEFINES QML_DOM_MSVC2019_COMPAT
)
+extend_qtc_library(QmlDesignerCore
+ CONDITION WITH_TESTS
+ PUBLIC_DEFINES QDS_MODEL_USE_PROJECTSTORAGEINTERFACE
+)
+
extend_qtc_library(QmlDesignerCore
SOURCES_PREFIX projectstorage
PUBLIC_INCLUDES projectstorage
diff --git a/src/plugins/qmldesigner/libs/designercore/include/model.h b/src/plugins/qmldesigner/libs/designercore/include/model.h
index 48ec5c7c4c0..d671c8edbba 100644
--- a/src/plugins/qmldesigner/libs/designercore/include/model.h
+++ b/src/plugins/qmldesigner/libs/designercore/include/model.h
@@ -24,13 +24,6 @@
#include
-#ifdef QDS_USE_PROJECTSTORAGE
-# define DEPRECATED_OLD_CREATE_MODELNODE \
- [[deprecated("Use unqualified type names and no versions!")]]
-#else
-# define DEPRECATED_OLD_CREATE_MODELNODE
-#endif
-
QT_BEGIN_NAMESPACE
class QPixmap;
class QUrl;
@@ -91,31 +84,32 @@ public:
Imports imports,
const QUrl &fileUrl,
std::unique_ptr resourceManagement = {});
+#ifndef QDS_USE_PROJECTSTORAGE
Model(const TypeName &typeName,
int major = 1,
int minor = 1,
Model *metaInfoProxyModel = nullptr,
std::unique_ptr resourceManagement = {});
-
+#endif
~Model();
- DEPRECATED_OLD_CREATE_MODELNODE static ModelPointer create(
- const TypeName &typeName,
- int major = 1,
- int minor = 1,
- Model *metaInfoProxyModel = nullptr,
- std::unique_ptr resourceManagement = {})
+#ifndef QDS_USE_PROJECTSTORAGE
+ static ModelPointer create(const TypeName &typeName,
+ int major = 1,
+ int minor = 1,
+ Model *metaInfoProxyModel = nullptr,
+ std::unique_ptr resourceManagement = {})
{
return ModelPointer(
new Model(typeName, major, minor, metaInfoProxyModel, std::move(resourceManagement)));
}
+#endif
- static ModelPointer create(
- ProjectStorageDependencies projectStorageDependencies,
- Utils::SmallStringView typeName,
- Imports imports,
- const QUrl &fileUrl,
- std::unique_ptr resourceManagement = {})
+ static ModelPointer create(ProjectStorageDependencies projectStorageDependencies,
+ Utils::SmallStringView typeName,
+ Imports imports,
+ const QUrl &fileUrl,
+ std::unique_ptr resourceManagement = {})
{
return ModelPointer(new Model(projectStorageDependencies,
typeName,
@@ -124,12 +118,12 @@ public:
std::move(resourceManagement)));
}
- DEPRECATED_OLD_CREATE_MODELNODE static ModelPointer create(
- ProjectStorageDependencies projectStorageDependencies,
- const TypeName &typeName,
- int major = 1,
- int minor = 1,
- std::unique_ptr resourceManagement = {})
+#ifndef QDS_USE_PROJECTSTORAGE
+ static ModelPointer create(ProjectStorageDependencies projectStorageDependencies,
+ const TypeName &typeName,
+ int major = 1,
+ int minor = 1,
+ std::unique_ptr resourceManagement = {})
{
return ModelPointer(new Model(projectStorageDependencies,
typeName,
@@ -138,6 +132,7 @@ public:
nullptr,
std::move(resourceManagement)));
}
+#endif
ModelPointer createModel(const TypeName &typeName,
std::unique_ptr resourceManagement = {});
@@ -188,6 +183,7 @@ public:
NodeMetaInfo qtQuick3DTextureMetaInfo() const;
NodeMetaInfo qtQuick3DTextureInputMetaInfo() const;
NodeMetaInfo qtQuickBorderImageMetaInfo() const;
+ NodeMetaInfo qtQuickControlsLabelMetaInfo() const;
NodeMetaInfo qtQuickControlsTextAreaMetaInfo() const;
NodeMetaInfo qtQuickImageMetaInfo() const;
NodeMetaInfo qtQuickItemMetaInfo() const;
diff --git a/src/plugins/qmldesigner/libs/designercore/include/modelfwd.h b/src/plugins/qmldesigner/libs/designercore/include/modelfwd.h
index 7cbfdba616a..a58e91a838c 100644
--- a/src/plugins/qmldesigner/libs/designercore/include/modelfwd.h
+++ b/src/plugins/qmldesigner/libs/designercore/include/modelfwd.h
@@ -39,6 +39,8 @@ constexpr bool useProjectStorage()
return false;
#endif
}
+class SourcePathStorage;
+using PathCache = SourcePathCache;
#ifdef QDS_MODEL_USE_PROJECTSTORAGEINTERFACE
using ProjectStorageType = ProjectStorageInterface;
@@ -46,7 +48,6 @@ class SourcePathCacheInterface;
using PathCacheType = SourcePathCacheInterface;
#else
using ProjectStorageType = ProjectStorage;
-class SourcePathStorage;
using PathCacheType = SourcePathCache;
#endif
diff --git a/src/plugins/qmldesigner/libs/designercore/include/nodehints.h b/src/plugins/qmldesigner/libs/designercore/include/nodehints.h
index 99470db65f1..5992d7d64a3 100644
--- a/src/plugins/qmldesigner/libs/designercore/include/nodehints.h
+++ b/src/plugins/qmldesigner/libs/designercore/include/nodehints.h
@@ -49,6 +49,7 @@ public:
QStringList visibleNonDefaultProperties() const;
bool takesOverRenderingOfChildren() const;
bool visibleInNavigator() const;
+ bool hideInNavigator() const;
bool visibleInLibrary() const;
QString forceNonDefaultProperty() const;
QPair setParentProperty() const;
diff --git a/src/plugins/qmldesigner/libs/designercore/include/nodemetainfo.h b/src/plugins/qmldesigner/libs/designercore/include/nodemetainfo.h
index fdb29cb10f3..ed2920cac4b 100644
--- a/src/plugins/qmldesigner/libs/designercore/include/nodemetainfo.h
+++ b/src/plugins/qmldesigner/libs/designercore/include/nodemetainfo.h
@@ -23,22 +23,6 @@ QT_BEGIN_NAMESPACE
class QDeclarativeContext;
QT_END_NAMESPACE
-#ifdef QDS_USE_PROJECTSTORAGE
-# define DEPRECATED_TYPENAME [[deprecated("Don't use string based types anymore!")]]
-# 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.")]]
-# define DEPRECATED_IMPORT_DIRECTORY_PATH [[deprecated("Use allExportedTypeNames().")]]
-# define DEPRECATED_REQUIRED_IMPORT_STRING [[deprecated("Use allExportedTypeNames().")]]
-#else
-# define DEPRECATED_TYPENAME
-# define DEPRECATED_VERSION_NUMBER
-# define DEPRECATED_COMPONENT_FILE_NAME
-# define DEPRECATED_IMPORT_DIRECTORY_PATH
-# define DEPRECATED_REQUIRED_IMPORT_STRING
-#endif
-
namespace QmlDesigner {
class MetaInfo;
@@ -54,7 +38,9 @@ class QMLDESIGNERCORE_EXPORT NodeMetaInfo
public:
NodeMetaInfo();
+#ifndef QDS_USE_PROJECTSTORAGE
NodeMetaInfo(Model *model, const TypeName &typeName, int majorVersion, int minorVersion);
+#else
NodeMetaInfo(TypeId typeId, NotNullPointer projectStorage)
: m_typeId{typeId}
, m_projectStorage{projectStorage}
@@ -62,6 +48,7 @@ public:
NodeMetaInfo(NotNullPointer projectStorage)
: m_projectStorage{projectStorage}
{}
+#endif
NodeMetaInfo(const NodeMetaInfo &);
NodeMetaInfo &operator=(const NodeMetaInfo &);
@@ -69,6 +56,7 @@ public:
NodeMetaInfo &operator=(NodeMetaInfo &&);
~NodeMetaInfo();
+#ifdef QDS_USE_PROJECTSTORAGE
static NodeMetaInfo create(NotNullPointer projectStorage, TypeId typeId)
{
return {typeId, projectStorage};
@@ -78,6 +66,7 @@ public:
{
return std::bind_front(&NodeMetaInfo::create, projectStorage);
}
+#endif
bool isValid() const;
explicit operator bool() const { return isValid(); }
@@ -98,6 +87,7 @@ public:
FlagIs isStackedContainer() const;
FlagIs takesOverRenderingOfChildren() const;
FlagIs visibleInNavigator() const;
+ FlagIs hideInNavigator() const;
FlagIs visibleInLibrary() const;
bool hasProperty(::Utils::SmallStringView propertyName) const;
@@ -118,11 +108,12 @@ public:
bool defaultPropertyIsComponent() const;
QString displayName() const;
- DEPRECATED_TYPENAME TypeName typeName() const;
- DEPRECATED_TYPENAME TypeName simplifiedTypeName() const;
- DEPRECATED_VERSION_NUMBER int majorVersion() const;
- DEPRECATED_VERSION_NUMBER int minorVersion() const;
-
+#ifndef QDS_USE_PROJECTSTORAGE
+ TypeName typeName() const;
+ TypeName simplifiedTypeName() const;
+ int majorVersion() const;
+ int minorVersion() const;
+#endif
Storage::Info::ExportedTypeNames allExportedTypeNames() const;
Storage::Info::ExportedTypeNames exportedTypeNamesForSourceId(SourceId sourceId) const;
@@ -131,7 +122,9 @@ public:
Storage::Info::ItemLibraryEntries itemLibrariesEntries() const;
SourceId sourceId() const;
- DEPRECATED_COMPONENT_FILE_NAME QString componentFileName() const;
+#ifndef QDS_USE_PROJECTSTORAGE
+ QString componentFileName() const;
+#endif
bool isBasedOn(const NodeMetaInfo &metaInfo) const;
bool isBasedOn(const NodeMetaInfo &metaInfo1, const NodeMetaInfo &metaInfo2) const;
@@ -214,6 +207,7 @@ public:
bool isQtQuick3DCubeMapTexture() const;
bool isQtQuick3DView3D() const;
bool isQtQuickBorderImage() const;
+ bool isQtQuickControlsLabel() const;
bool isQtQuickControlsSwipeView() const;
bool isQtQuickControlsTabBar() const;
bool isQtQuickExtrasPicture() const;
@@ -226,6 +220,7 @@ public:
bool isQtQuickPositioner() const;
bool isQtQuickPropertyAnimation() const;
bool isQtQuickPropertyChanges() const;
+ bool isQtQuickRectangle() const;
bool isQtQuickRepeater() const;
bool isQtQuickState() const;
bool isQtQuickStateOperation() const;
@@ -251,9 +246,10 @@ public:
bool usesCustomParser() const;
bool isEnumeration() const;
- DEPRECATED_IMPORT_DIRECTORY_PATH QString importDirectoryPath() const;
- DEPRECATED_REQUIRED_IMPORT_STRING QString requiredImportString() const;
-
+#ifndef QDS_USE_PROJECTSTORAGE
+ QString importDirectoryPath() const;
+ QString requiredImportString() const;
+#endif
friend bool operator==(const NodeMetaInfo &first, const NodeMetaInfo &second)
{
if constexpr (useProjectStorage())
diff --git a/src/plugins/qmldesigner/libs/designercore/metainfo/nodehints.cpp b/src/plugins/qmldesigner/libs/designercore/metainfo/nodehints.cpp
index 1f9a3e42bd6..5cbae6861fa 100644
--- a/src/plugins/qmldesigner/libs/designercore/metainfo/nodehints.cpp
+++ b/src/plugins/qmldesigner/libs/designercore/metainfo/nodehints.cpp
@@ -321,6 +321,19 @@ bool NodeHints::visibleInNavigator() const
return evaluateBooleanExpression("visibleInNavigator", false);
}
+bool NodeHints::hideInNavigator() const
+{
+ if (!isValid())
+ return false;
+
+ auto flagIs = m_modelNode.metaInfo().hideInNavigator();
+
+ if (flagIs != FlagIs::Set)
+ return convert(flagIs);
+
+ return evaluateBooleanExpression("hideInNavigator", false);
+}
+
bool NodeHints::visibleInLibrary() const
{
auto flagIs = m_metaInfo.visibleInLibrary();
diff --git a/src/plugins/qmldesigner/libs/designercore/metainfo/nodemetainfo.cpp b/src/plugins/qmldesigner/libs/designercore/metainfo/nodemetainfo.cpp
index e340bc2c357..56836119d06 100644
--- a/src/plugins/qmldesigner/libs/designercore/metainfo/nodemetainfo.cpp
+++ b/src/plugins/qmldesigner/libs/designercore/metainfo/nodemetainfo.cpp
@@ -614,8 +614,9 @@ public:
const TypeName &propertyType(const PropertyName &propertyName) const;
void setupPrototypes();
+#ifndef QDS_USE_PROJECTSTORAGE
QList prototypes() const;
-
+#endif
bool isPropertyWritable(const PropertyName &propertyName) const;
bool isPropertyPointer(const PropertyName &propertyName) const;
bool isPropertyList(const PropertyName &propertyName) const;
@@ -1429,10 +1430,12 @@ void NodeMetaInfoPrivate::setupPrototypes()
}
}
+#ifndef QDS_USE_PROJECTSTORAGE
QList NodeMetaInfoPrivate::prototypes() const
{
return m_prototypes;
}
+#endif
const CppComponentValue *NodeMetaInfoPrivate::getNearestCppComponentValue() const
{
@@ -1478,10 +1481,13 @@ NodeMetaInfo &NodeMetaInfo::operator=(const NodeMetaInfo &) = default;
NodeMetaInfo::NodeMetaInfo(NodeMetaInfo &&) = default;
NodeMetaInfo &NodeMetaInfo::operator=(NodeMetaInfo &&) = default;
+#ifndef QDS_USE_PROJECTSTORAGE
+
NodeMetaInfo::NodeMetaInfo(Model *model, const TypeName &type, int maj, int min)
: m_privateData(NodeMetaInfoPrivate::create(model, type, maj, min))
{
}
+#endif
NodeMetaInfo::~NodeMetaInfo() = default;
@@ -1774,6 +1780,18 @@ FlagIs NodeMetaInfo::visibleInNavigator() const
return FlagIs::Set;
}
+FlagIs NodeMetaInfo::hideInNavigator() const
+{
+ if constexpr (useProjectStorage()) {
+ if (isValid())
+ return typeData().traits.hideInNavigator;
+
+ return FlagIs::False;
+ }
+
+ return FlagIs::Set;
+}
+
FlagIs NodeMetaInfo::visibleInLibrary() const
{
if constexpr (useProjectStorage()) {
@@ -2024,28 +2042,26 @@ std::vector NodeMetaInfo::selfAndPrototypes() const
if (!isValid())
return {};
- if constexpr (useProjectStorage()) {
- using NanotraceHR::keyValue;
- NanotraceHR::Tracer tracer{"get self and prototypes"_t,
- category(),
- keyValue("type id", m_typeId)};
+#ifdef QDS_USE_PROJECTSTORAGE
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get self and prototypes"_t, category(), keyValue("type id", m_typeId)};
- return Utils::transform(m_projectStorage->prototypeAndSelfIds(m_typeId),
- NodeMetaInfo::bind(m_projectStorage));
- } else {
- NodeMetaInfos hierarchy = {*this};
- Model *model = m_privateData->model();
- for (const TypeDescription &type : m_privateData->prototypes()) {
- auto &last = hierarchy.emplace_back(model,
- type.className.toUtf8(),
- type.majorVersion,
- type.minorVersion);
- if (!last.isValid())
- hierarchy.pop_back();
- }
-
- return hierarchy;
+ return Utils::transform(m_projectStorage->prototypeAndSelfIds(m_typeId),
+ NodeMetaInfo::bind(m_projectStorage));
+#else
+ NodeMetaInfos hierarchy = {*this};
+ Model *model = m_privateData->model();
+ for (const TypeDescription &type : m_privateData->prototypes()) {
+ auto &last = hierarchy.emplace_back(model,
+ type.className.toUtf8(),
+ type.majorVersion,
+ type.minorVersion);
+ if (!last.isValid())
+ hierarchy.pop_back();
}
+
+ return hierarchy;
+#endif
}
NodeMetaInfos NodeMetaInfo::prototypes() const
@@ -2053,26 +2069,26 @@ NodeMetaInfos NodeMetaInfo::prototypes() const
if (!isValid())
return {};
- if constexpr (useProjectStorage()) {
- using NanotraceHR::keyValue;
- NanotraceHR::Tracer tracer{"get prototypes"_t, category(), keyValue("type id", m_typeId)};
- return Utils::transform(m_projectStorage->prototypeIds(m_typeId),
- NodeMetaInfo::bind(m_projectStorage));
+#ifdef QDS_USE_PROJECTSTORAGE
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get prototypes"_t, category(), keyValue("type id", m_typeId)};
+ return Utils::transform(m_projectStorage->prototypeIds(m_typeId),
+ NodeMetaInfo::bind(m_projectStorage));
- } else {
- NodeMetaInfos hierarchy;
- Model *model = m_privateData->model();
- for (const TypeDescription &type : m_privateData->prototypes()) {
- auto &last = hierarchy.emplace_back(model,
- type.className.toUtf8(),
- type.majorVersion,
- type.minorVersion);
- if (!last.isValid())
- hierarchy.pop_back();
- }
-
- return hierarchy;
+#else
+ NodeMetaInfos hierarchy;
+ Model *model = m_privateData->model();
+ for (const TypeDescription &type : m_privateData->prototypes()) {
+ auto &last = hierarchy.emplace_back(model,
+ type.className.toUtf8(),
+ type.majorVersion,
+ type.minorVersion);
+ if (!last.isValid())
+ hierarchy.pop_back();
}
+
+ return hierarchy;
+#endif
}
namespace {
@@ -2111,6 +2127,7 @@ QString NodeMetaInfo::displayName() const
return {};
}
+#ifndef QDS_USE_PROJECTSTORAGE
TypeName NodeMetaInfo::typeName() const
{
if (isValid())
@@ -2146,6 +2163,7 @@ int NodeMetaInfo::minorVersion() const
return -1;
}
+#endif
Storage::Info::ExportedTypeNames NodeMetaInfo::allExportedTypeNames() const
{
@@ -2260,6 +2278,7 @@ SourceId NodeMetaInfo::sourceId() const
return SourceId{};
}
+#ifndef QDS_USE_PROJECTSTORAGE
QString NodeMetaInfo::componentFileName() const
{
if constexpr (!useProjectStorage()) {
@@ -2295,6 +2314,7 @@ QString NodeMetaInfo::requiredImportString() const
return {};
}
+#endif
SourceId NodeMetaInfo::propertyEditorPathId() const
{
@@ -2333,13 +2353,17 @@ PropertyDeclarationId NodeMetaInfo::defaultPropertyDeclarationId() const
return *m_defaultPropertyId;
}
-bool NodeMetaInfo::isSubclassOf(const TypeName &type, int majorVersion, int minorVersion) const
+bool NodeMetaInfo::isSubclassOf([[maybe_unused]] const TypeName &type,
+ [[maybe_unused]] int majorVersion,
+ [[maybe_unused]] int minorVersion) const
{
if (!isValid()) {
qWarning() << "NodeMetaInfo is invalid" << type;
return false;
}
+#ifndef QDS_USE_PROJECTSTORAGE
+
if (typeName().isEmpty())
return false;
@@ -2363,6 +2387,7 @@ bool NodeMetaInfo::isSubclassOf(const TypeName &type, int majorVersion, int mino
}
}
m_privateData->prototypeCacheNegatives().insert(stringIdentifier(type, majorVersion, minorVersion));
+#endif
return false;
}
@@ -2402,75 +2427,73 @@ bool NodeMetaInfo::isSuitableForMouseAreaFill() const
bool NodeMetaInfo::isBasedOn(const NodeMetaInfo &metaInfo) const
{
- if constexpr (useProjectStorage()) {
- if (!isValid())
- return false;
+#ifdef QDS_USE_PROJECTSTORAGE
+ if (!isValid())
+ return false;
- using NanotraceHR::keyValue;
- NanotraceHR::Tracer tracer{"is based on"_t,
- category(),
- keyValue("type id", m_typeId),
- keyValue("meta info type id", metaInfo.m_typeId)};
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is based on"_t,
+ category(),
+ keyValue("type id", m_typeId),
+ keyValue("meta info type id", metaInfo.m_typeId)};
- return m_projectStorage->isBasedOn(m_typeId, metaInfo.m_typeId);
- } else {
- if (!isValid())
- return false;
- if (majorVersion() == -1 && minorVersion() == -1)
- return isSubclassOf(metaInfo.typeName());
- return isSubclassOf(metaInfo.typeName(), metaInfo.majorVersion(), metaInfo.minorVersion());
- }
+ return m_projectStorage->isBasedOn(m_typeId, metaInfo.m_typeId);
+#else
+ if (!isValid())
+ return false;
+ if (majorVersion() == -1 && minorVersion() == -1)
+ return isSubclassOf(metaInfo.typeName());
+ return isSubclassOf(metaInfo.typeName(), metaInfo.majorVersion(), metaInfo.minorVersion());
+#endif
}
bool NodeMetaInfo::isBasedOn(const NodeMetaInfo &metaInfo1, const NodeMetaInfo &metaInfo2) const
{
- if constexpr (useProjectStorage()) {
- if (!isValid())
- return false;
+#ifdef QDS_USE_PROJECTSTORAGE
+ if (!isValid())
+ return false;
- using NanotraceHR::keyValue;
- NanotraceHR::Tracer tracer{"is based on"_t, category(), keyValue("type id", m_typeId)};
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is based on"_t, category(), keyValue("type id", m_typeId)};
- return m_projectStorage->isBasedOn(m_typeId, metaInfo1.m_typeId, metaInfo2.m_typeId);
- } else {
- if (!isValid())
- return false;
- if (majorVersion() == -1 && minorVersion() == -1)
- return (isSubclassOf(metaInfo1.typeName()) || isSubclassOf(metaInfo2.typeName()));
+ return m_projectStorage->isBasedOn(m_typeId, metaInfo1.m_typeId, metaInfo2.m_typeId);
+#else
+ if (!isValid())
+ return false;
+ if (majorVersion() == -1 && minorVersion() == -1)
+ return (isSubclassOf(metaInfo1.typeName()) || isSubclassOf(metaInfo2.typeName()));
- return (
- isSubclassOf(metaInfo1.typeName(), metaInfo1.majorVersion(), metaInfo1.minorVersion())
+ return (isSubclassOf(metaInfo1.typeName(), metaInfo1.majorVersion(), metaInfo1.minorVersion())
|| isSubclassOf(metaInfo2.typeName(), metaInfo2.majorVersion(), metaInfo2.minorVersion()));
- }
+#endif
}
bool NodeMetaInfo::isBasedOn(const NodeMetaInfo &metaInfo1,
const NodeMetaInfo &metaInfo2,
const NodeMetaInfo &metaInfo3) const
{
- if constexpr (useProjectStorage()) {
- if (!isValid())
- return false;
+#ifdef QDS_USE_PROJECTSTORAGE
+ if (!isValid())
+ return false;
- using NanotraceHR::keyValue;
- NanotraceHR::Tracer tracer{"is based on"_t, category(), keyValue("type id", m_typeId)};
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is based on"_t, category(), keyValue("type id", m_typeId)};
- return m_projectStorage->isBasedOn(m_typeId,
- metaInfo1.m_typeId,
- metaInfo2.m_typeId,
- metaInfo3.m_typeId);
- } else {
- if (!isValid())
- return false;
- if (majorVersion() == -1 && minorVersion() == -1)
- return (isSubclassOf(metaInfo1.typeName()) || isSubclassOf(metaInfo2.typeName())
- || isSubclassOf(metaInfo3.typeName()));
+ return m_projectStorage->isBasedOn(m_typeId,
+ metaInfo1.m_typeId,
+ metaInfo2.m_typeId,
+ metaInfo3.m_typeId);
+#else
+ if (!isValid())
+ return false;
+ if (majorVersion() == -1 && minorVersion() == -1)
+ return (isSubclassOf(metaInfo1.typeName()) || isSubclassOf(metaInfo2.typeName())
+ || isSubclassOf(metaInfo3.typeName()));
- return (
- isSubclassOf(metaInfo1.typeName(), metaInfo1.majorVersion(), metaInfo1.minorVersion())
+ return (isSubclassOf(metaInfo1.typeName(), metaInfo1.majorVersion(), metaInfo1.minorVersion())
|| isSubclassOf(metaInfo2.typeName(), metaInfo2.majorVersion(), metaInfo2.minorVersion())
|| isSubclassOf(metaInfo3.typeName(), metaInfo3.majorVersion(), metaInfo3.minorVersion()));
- }
+#endif
}
bool NodeMetaInfo::isBasedOn(const NodeMetaInfo &metaInfo1,
@@ -2478,31 +2501,27 @@ bool NodeMetaInfo::isBasedOn(const NodeMetaInfo &metaInfo1,
const NodeMetaInfo &metaInfo3,
const NodeMetaInfo &metaInfo4) const
{
- if constexpr (useProjectStorage()) {
- if (!isValid())
- return false;
+#ifdef QDS_USE_PROJECTSTORAGE
+ if (!isValid())
+ return false;
- using NanotraceHR::keyValue;
- NanotraceHR::Tracer tracer{"is based on"_t, category(), keyValue("type id", m_typeId)};
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is based on"_t, category(), keyValue("type id", m_typeId)};
- return m_projectStorage->isBasedOn(m_typeId,
- metaInfo1.m_typeId,
- metaInfo2.m_typeId,
- metaInfo3.m_typeId,
- metaInfo4.m_typeId);
- } else {
- return isValid()
- && (isSubclassOf(metaInfo1.typeName(), metaInfo1.majorVersion(), metaInfo1.minorVersion())
- || isSubclassOf(metaInfo2.typeName(),
- metaInfo2.majorVersion(),
- metaInfo2.minorVersion())
- || isSubclassOf(metaInfo3.typeName(),
- metaInfo3.majorVersion(),
- metaInfo3.minorVersion())
- || isSubclassOf(metaInfo4.typeName(),
- metaInfo4.majorVersion(),
- metaInfo4.minorVersion()));
- }
+ return m_projectStorage->isBasedOn(m_typeId,
+ metaInfo1.m_typeId,
+ metaInfo2.m_typeId,
+ metaInfo3.m_typeId,
+ metaInfo4.m_typeId);
+#else
+ return isValid()
+ && (isSubclassOf(metaInfo1.typeName(), metaInfo1.majorVersion(), metaInfo1.minorVersion())
+ || isSubclassOf(metaInfo2.typeName(), metaInfo2.majorVersion(), metaInfo2.minorVersion())
+ || isSubclassOf(metaInfo3.typeName(), metaInfo3.majorVersion(), metaInfo3.minorVersion())
+ || isSubclassOf(metaInfo4.typeName(),
+ metaInfo4.majorVersion(),
+ metaInfo4.minorVersion()));
+#endif
}
bool NodeMetaInfo::isBasedOn(const NodeMetaInfo &metaInfo1,
@@ -2511,35 +2530,29 @@ bool NodeMetaInfo::isBasedOn(const NodeMetaInfo &metaInfo1,
const NodeMetaInfo &metaInfo4,
const NodeMetaInfo &metaInfo5) const
{
- if constexpr (useProjectStorage()) {
- if (!isValid())
- return false;
+#ifdef QDS_USE_PROJECTSTORAGE
+ if (!isValid())
+ return false;
- using NanotraceHR::keyValue;
- NanotraceHR::Tracer tracer{"is based on"_t, category(), keyValue("type id", m_typeId)};
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is based on"_t, category(), keyValue("type id", m_typeId)};
- return m_projectStorage->isBasedOn(m_typeId,
- metaInfo1.m_typeId,
- metaInfo2.m_typeId,
- metaInfo3.m_typeId,
- metaInfo4.m_typeId,
- metaInfo5.m_typeId);
- } else {
- return isValid()
- && (isSubclassOf(metaInfo1.typeName(), metaInfo1.majorVersion(), metaInfo1.minorVersion())
- || isSubclassOf(metaInfo2.typeName(),
- metaInfo2.majorVersion(),
- metaInfo2.minorVersion())
- || isSubclassOf(metaInfo3.typeName(),
- metaInfo3.majorVersion(),
- metaInfo3.minorVersion())
- || isSubclassOf(metaInfo4.typeName(),
- metaInfo4.majorVersion(),
- metaInfo4.minorVersion())
- || isSubclassOf(metaInfo5.typeName(),
- metaInfo5.majorVersion(),
- metaInfo5.minorVersion()));
- }
+ return m_projectStorage->isBasedOn(m_typeId,
+ metaInfo1.m_typeId,
+ metaInfo2.m_typeId,
+ metaInfo3.m_typeId,
+ metaInfo4.m_typeId,
+ metaInfo5.m_typeId);
+#else
+ return isValid()
+ && (isSubclassOf(metaInfo1.typeName(), metaInfo1.majorVersion(), metaInfo1.minorVersion())
+ || isSubclassOf(metaInfo2.typeName(), metaInfo2.majorVersion(), metaInfo2.minorVersion())
+ || isSubclassOf(metaInfo3.typeName(), metaInfo3.majorVersion(), metaInfo3.minorVersion())
+ || isSubclassOf(metaInfo4.typeName(), metaInfo4.majorVersion(), metaInfo4.minorVersion())
+ || isSubclassOf(metaInfo5.typeName(),
+ metaInfo5.majorVersion(),
+ metaInfo5.minorVersion()));
+#endif
}
bool NodeMetaInfo::isBasedOn(const NodeMetaInfo &metaInfo1,
@@ -2549,39 +2562,31 @@ bool NodeMetaInfo::isBasedOn(const NodeMetaInfo &metaInfo1,
const NodeMetaInfo &metaInfo5,
const NodeMetaInfo &metaInfo6) const
{
- if constexpr (useProjectStorage()) {
- if (!isValid())
- return false;
+#ifdef QDS_USE_PROJECTSTORAGE
+ if (!isValid())
+ return false;
- using NanotraceHR::keyValue;
- NanotraceHR::Tracer tracer{"is based on"_t, category(), keyValue("type id", m_typeId)};
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is based on"_t, category(), keyValue("type id", m_typeId)};
- return m_projectStorage->isBasedOn(m_typeId,
- metaInfo1.m_typeId,
- metaInfo2.m_typeId,
- metaInfo3.m_typeId,
- metaInfo4.m_typeId,
- metaInfo5.m_typeId,
- metaInfo6.m_typeId);
- } else {
- return isValid()
- && (isSubclassOf(metaInfo1.typeName(), metaInfo1.majorVersion(), metaInfo1.minorVersion())
- || isSubclassOf(metaInfo2.typeName(),
- metaInfo2.majorVersion(),
- metaInfo2.minorVersion())
- || isSubclassOf(metaInfo3.typeName(),
- metaInfo3.majorVersion(),
- metaInfo3.minorVersion())
- || isSubclassOf(metaInfo4.typeName(),
- metaInfo4.majorVersion(),
- metaInfo4.minorVersion())
- || isSubclassOf(metaInfo5.typeName(),
- metaInfo5.majorVersion(),
- metaInfo5.minorVersion())
- || isSubclassOf(metaInfo6.typeName(),
- metaInfo6.majorVersion(),
- metaInfo6.minorVersion()));
- }
+ return m_projectStorage->isBasedOn(m_typeId,
+ metaInfo1.m_typeId,
+ metaInfo2.m_typeId,
+ metaInfo3.m_typeId,
+ metaInfo4.m_typeId,
+ metaInfo5.m_typeId,
+ metaInfo6.m_typeId);
+#else
+ return isValid()
+ && (isSubclassOf(metaInfo1.typeName(), metaInfo1.majorVersion(), metaInfo1.minorVersion())
+ || isSubclassOf(metaInfo2.typeName(), metaInfo2.majorVersion(), metaInfo2.minorVersion())
+ || isSubclassOf(metaInfo3.typeName(), metaInfo3.majorVersion(), metaInfo3.minorVersion())
+ || isSubclassOf(metaInfo4.typeName(), metaInfo4.majorVersion(), metaInfo4.minorVersion())
+ || isSubclassOf(metaInfo5.typeName(), metaInfo5.majorVersion(), metaInfo5.minorVersion())
+ || isSubclassOf(metaInfo6.typeName(),
+ metaInfo6.majorVersion(),
+ metaInfo6.minorVersion()));
+#endif
}
bool NodeMetaInfo::isBasedOn(const NodeMetaInfo &metaInfo1,
@@ -2592,43 +2597,33 @@ bool NodeMetaInfo::isBasedOn(const NodeMetaInfo &metaInfo1,
const NodeMetaInfo &metaInfo6,
const NodeMetaInfo &metaInfo7) const
{
- if constexpr (useProjectStorage()) {
- if (!isValid())
- return false;
+#ifdef QDS_USE_PROJECTSTORAGE
+ if (!isValid())
+ return false;
- using NanotraceHR::keyValue;
- NanotraceHR::Tracer tracer{"is based on"_t, category(), keyValue("type id", m_typeId)};
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is based on"_t, category(), keyValue("type id", m_typeId)};
- return m_projectStorage->isBasedOn(m_typeId,
- metaInfo1.m_typeId,
- metaInfo2.m_typeId,
- metaInfo3.m_typeId,
- metaInfo4.m_typeId,
- metaInfo5.m_typeId,
- metaInfo6.m_typeId,
- metaInfo7.m_typeId);
- } else {
- return isValid()
- && (isSubclassOf(metaInfo1.typeName(), metaInfo1.majorVersion(), metaInfo1.minorVersion())
- || isSubclassOf(metaInfo2.typeName(),
- metaInfo2.majorVersion(),
- metaInfo2.minorVersion())
- || isSubclassOf(metaInfo3.typeName(),
- metaInfo3.majorVersion(),
- metaInfo3.minorVersion())
- || isSubclassOf(metaInfo4.typeName(),
- metaInfo4.majorVersion(),
- metaInfo4.minorVersion())
- || isSubclassOf(metaInfo5.typeName(),
- metaInfo5.majorVersion(),
- metaInfo5.minorVersion())
- || isSubclassOf(metaInfo6.typeName(),
- metaInfo6.majorVersion(),
- metaInfo6.minorVersion())
- || isSubclassOf(metaInfo7.typeName(),
- metaInfo7.majorVersion(),
- metaInfo7.minorVersion()));
- }
+ return m_projectStorage->isBasedOn(m_typeId,
+ metaInfo1.m_typeId,
+ metaInfo2.m_typeId,
+ metaInfo3.m_typeId,
+ metaInfo4.m_typeId,
+ metaInfo5.m_typeId,
+ metaInfo6.m_typeId,
+ metaInfo7.m_typeId);
+#else
+ return isValid()
+ && (isSubclassOf(metaInfo1.typeName(), metaInfo1.majorVersion(), metaInfo1.minorVersion())
+ || isSubclassOf(metaInfo2.typeName(), metaInfo2.majorVersion(), metaInfo2.minorVersion())
+ || isSubclassOf(metaInfo3.typeName(), metaInfo3.majorVersion(), metaInfo3.minorVersion())
+ || isSubclassOf(metaInfo4.typeName(), metaInfo4.majorVersion(), metaInfo4.minorVersion())
+ || isSubclassOf(metaInfo5.typeName(), metaInfo5.majorVersion(), metaInfo5.minorVersion())
+ || isSubclassOf(metaInfo6.typeName(), metaInfo6.majorVersion(), metaInfo6.minorVersion())
+ || isSubclassOf(metaInfo7.typeName(),
+ metaInfo7.majorVersion(),
+ metaInfo7.minorVersion()));
+#endif
}
bool NodeMetaInfo::isGraphicalItem() const
@@ -2673,20 +2668,18 @@ bool NodeMetaInfo::isQtObject() const
bool NodeMetaInfo::isQtQmlConnections() const
{
- if constexpr (useProjectStorage()) {
- if (!isValid())
- return false;
+#ifdef QDS_USE_PROJECTSTORAGE
+ if (!isValid())
+ return false;
- using NanotraceHR::keyValue;
- NanotraceHR::Tracer tracer{"is Qt Qml connections"_t,
- category(),
- keyValue("type id", m_typeId)};
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is Qt Qml connections"_t, category(), keyValue("type id", m_typeId)};
- using namespace Storage::Info;
- return isBasedOnCommonType(m_projectStorage, m_typeId);
- } else {
- return isValid() && simplifiedTypeName() == "Connections";
- }
+ using namespace Storage::Info;
+ return isBasedOnCommonType(m_projectStorage, m_typeId);
+#else
+ return isValid() && simplifiedTypeName() == "Connections";
+#endif
}
bool NodeMetaInfo::isLayoutable() const
@@ -2753,22 +2746,22 @@ bool NodeMetaInfo::isView() const
bool NodeMetaInfo::usesCustomParser() const
{
- if constexpr (useProjectStorage()) {
- if (!isValid())
- return false;
+#ifdef QDS_USE_PROJECTSTORAGE
+ if (!isValid())
+ return false;
- using NanotraceHR::keyValue;
- NanotraceHR::Tracer tracer{"uses custom parser"_t, category(), keyValue("type id", m_typeId)};
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"uses custom parser"_t, category(), keyValue("type id", m_typeId)};
- return typeData().traits.usesCustomParser;
- } else {
- if (!isValid())
- return false;
+ return typeData().traits.usesCustomParser;
+#else
+ if (!isValid())
+ return false;
- auto type = simplifiedTypeName();
- return type == "VisualItemModel" || type == "VisualDataModel" || type == "ListModel"
- || type == "XmlListModel";
- }
+ auto type = simplifiedTypeName();
+ return type == "VisualItemModel" || type == "VisualDataModel" || type == "ListModel"
+ || type == "XmlListModel";
+#endif
}
namespace {
@@ -3123,6 +3116,23 @@ bool NodeMetaInfo::isQtQuickPropertyAnimation() const
}
}
+bool NodeMetaInfo::isQtQuickRectangle() const
+{
+#ifdef QDS_USE_PROJECTSTORAGE
+
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick.Rectange"_t, category(), keyValue("type id", m_typeId)};
+
+ using namespace Storage::Info;
+ return isBasedOnCommonType(m_projectStorage, m_typeId);
+#else
+ return isValid() && isSubclassOf("QtQuick.Rectangle");
+#endif
+}
+
bool NodeMetaInfo::isQtQuickRepeater() const
{
if constexpr (useProjectStorage()) {
@@ -3157,6 +3167,24 @@ bool NodeMetaInfo::isQtQuickControlsTabBar() const
}
}
+bool NodeMetaInfo::isQtQuickControlsLabel() const
+{
+#ifdef QDS_USE_PROJECTSTORAGE
+ if (!isValid())
+ return false;
+
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QtQuick.Controls.SwipeView"_t,
+ category(),
+ keyValue("type id", m_typeId)};
+
+ using namespace Storage::Info;
+ return isBasedOnCommonType(m_projectStorage, m_typeId);
+#else
+ return isValid() && isSubclassOf("QtQuick.Controls.Label");
+#endif
+}
+
bool NodeMetaInfo::isQtQuickControlsSwipeView() const
{
if constexpr (useProjectStorage()) {
@@ -3744,189 +3772,189 @@ bool NodeMetaInfo::isQtQuickStudioUtilsJsonListModel() const
bool NodeMetaInfo::isQmlComponent() const
{
- if constexpr (useProjectStorage()) {
- if (!isValid())
- return false;
+#ifdef QDS_USE_PROJECTSTORAGE
+ if (!isValid())
+ return false;
- using NanotraceHR::keyValue;
- NanotraceHR::Tracer tracer{"is QML.Component"_t, category(), keyValue("type id", m_typeId)};
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is QML.Component"_t, category(), keyValue("type id", m_typeId)};
- using namespace Storage::Info;
- return isBasedOnCommonType(m_projectStorage, m_typeId);
- } else {
- if (!isValid())
- return false;
+ using namespace Storage::Info;
+ return isBasedOnCommonType(m_projectStorage, m_typeId);
+#else
+ if (!isValid())
+ return false;
- auto type = simplifiedTypeName();
+ auto type = simplifiedTypeName();
- return type == "Component" || type == "QQmlComponent";
- }
+ return type == "Component" || type == "QQmlComponent";
+#endif
}
bool NodeMetaInfo::isFont() const
{
- if constexpr (useProjectStorage()) {
- if (!isValid())
- return false;
+#ifdef QDS_USE_PROJECTSTORAGE
+ if (!isValid())
+ return false;
- using NanotraceHR::keyValue;
- NanotraceHR::Tracer tracer{"is font"_t, category(), keyValue("type id", m_typeId)};
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is font"_t, category(), keyValue("type id", m_typeId)};
- using namespace Storage::Info;
- return isValid() && isTypeId(m_typeId, m_projectStorage->commonTypeId());
- } else {
- return isValid() && simplifiedTypeName() == "font";
- }
+ using namespace Storage::Info;
+ return isValid() && isTypeId(m_typeId, m_projectStorage->commonTypeId());
+#else
+ return isValid() && simplifiedTypeName() == "font";
+#endif
}
bool NodeMetaInfo::isColor() const
{
- if constexpr (useProjectStorage()) {
- if (!isValid())
- return false;
+#ifdef QDS_USE_PROJECTSTORAGE
+ if (!isValid())
+ return false;
- using NanotraceHR::keyValue;
- NanotraceHR::Tracer tracer{"is color"_t, category(), keyValue("type id", m_typeId)};
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is color"_t, category(), keyValue("type id", m_typeId)};
- using namespace Storage::Info;
- return isValid() && isTypeId(m_typeId, m_projectStorage->builtinTypeId());
- } else {
- if (!isValid())
- return false;
+ using namespace Storage::Info;
+ return isValid() && isTypeId(m_typeId, m_projectStorage->builtinTypeId());
+#else
+ if (!isValid())
+ return false;
- auto type = simplifiedTypeName();
+ auto type = simplifiedTypeName();
- return type == "QColor" || type == "color" || type == "color";
- }
+ return type == "QColor" || type == "color" || type == "color";
+#endif
}
bool NodeMetaInfo::isBool() const
{
- if constexpr (useProjectStorage()) {
- if (!isValid())
- return false;
+#ifdef QDS_USE_PROJECTSTORAGE
+ if (!isValid())
+ return false;
- using NanotraceHR::keyValue;
- NanotraceHR::Tracer tracer{"is bool"_t, category(), keyValue("type id", m_typeId)};
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is bool"_t, category(), keyValue("type id", m_typeId)};
- using namespace Storage::Info;
- return isValid() && isTypeId(m_typeId, m_projectStorage->builtinTypeId());
- } else {
- if (!isValid())
- return false;
+ using namespace Storage::Info;
+ return isValid() && isTypeId(m_typeId, m_projectStorage->builtinTypeId());
+#else
+ if (!isValid())
+ return false;
- auto type = simplifiedTypeName();
+ auto type = simplifiedTypeName();
- return type == "bool" || type == "boolean";
- }
+ return type == "bool" || type == "boolean";
+#endif
}
bool NodeMetaInfo::isInteger() const
{
- if constexpr (useProjectStorage()) {
- if (!isValid())
- return false;
+#ifdef QDS_USE_PROJECTSTORAGE
+ if (!isValid())
+ return false;
- using NanotraceHR::keyValue;
- NanotraceHR::Tracer tracer{"is integer"_t, category(), keyValue("type id", m_typeId)};
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is integer"_t, category(), keyValue("type id", m_typeId)};
- using namespace Storage::Info;
- return isValid() && isTypeId(m_typeId, m_projectStorage->builtinTypeId());
- } else {
- if (!isValid())
- return false;
+ using namespace Storage::Info;
+ return isValid() && isTypeId(m_typeId, m_projectStorage->builtinTypeId());
+#else
+ if (!isValid())
+ return false;
- auto type = simplifiedTypeName();
+ auto type = simplifiedTypeName();
- return type == "int" || type == "integer" || type == "uint";
- }
+ return type == "int" || type == "integer" || type == "uint";
+#endif
}
bool NodeMetaInfo::isFloat() const
{
- if constexpr (useProjectStorage()) {
- if (!isValid())
- return false;
+#ifdef QDS_USE_PROJECTSTORAGE
+ if (!isValid())
+ return false;
- using NanotraceHR::keyValue;
- NanotraceHR::Tracer tracer{"is float"_t, category(), keyValue("type id", m_typeId)};
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is float"_t, category(), keyValue("type id", m_typeId)};
- using namespace Storage::Info;
- auto floatId = m_projectStorage->builtinTypeId();
- auto doubleId = m_projectStorage->builtinTypeId();
+ using namespace Storage::Info;
+ auto floatId = m_projectStorage->builtinTypeId();
+ auto doubleId = m_projectStorage->builtinTypeId();
- return isTypeId(m_typeId, floatId, doubleId);
- } else {
- if (!isValid())
- return false;
+ return isTypeId(m_typeId, floatId, doubleId);
+#else
+ if (!isValid())
+ return false;
- auto type = simplifiedTypeName();
+ auto type = simplifiedTypeName();
- return type == "qreal" || type == "double" || type == "float" || type == "real";
- }
+ return type == "qreal" || type == "double" || type == "float" || type == "real";
+#endif
}
bool NodeMetaInfo::isVariant() const
{
- if constexpr (useProjectStorage()) {
- if (!isValid())
- return false;
+#ifdef QDS_USE_PROJECTSTORAGE
+ if (!isValid())
+ return false;
- using NanotraceHR::keyValue;
- NanotraceHR::Tracer tracer{"is variant"_t, category(), keyValue("type id", m_typeId)};
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is variant"_t, category(), keyValue("type id", m_typeId)};
- using namespace Storage::Info;
- return isValid() && isTypeId(m_typeId, m_projectStorage->builtinTypeId());
- } else {
- if (!isValid())
- return false;
+ using namespace Storage::Info;
+ return isValid() && isTypeId(m_typeId, m_projectStorage->builtinTypeId());
+#else
+ if (!isValid())
+ return false;
- const auto type = simplifiedTypeName();
+ const auto type = simplifiedTypeName();
- return type == "QVariant" || type == "var" || type == "variant";
- }
+ return type == "QVariant" || type == "var" || type == "variant";
+#endif
}
bool NodeMetaInfo::isString() const
{
- if constexpr (useProjectStorage()) {
- if (!isValid())
- return false;
+#ifdef QDS_USE_PROJECTSTORAGE
+ if (!isValid())
+ return false;
- using NanotraceHR::keyValue;
- NanotraceHR::Tracer tracer{"is string"_t, category(), keyValue("type id", m_typeId)};
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is string"_t, category(), keyValue("type id", m_typeId)};
- using namespace Storage::Info;
- return isValid() && isTypeId(m_typeId, m_projectStorage->builtinTypeId());
- } else {
- if (!isValid())
- return false;
+ using namespace Storage::Info;
+ return isValid() && isTypeId(m_typeId, m_projectStorage->builtinTypeId());
+#else
+ if (!isValid())
+ return false;
- auto type = simplifiedTypeName();
+ auto type = simplifiedTypeName();
- return type == "string" || type == "QString";
- }
+ return type == "string" || type == "QString";
+#endif
}
bool NodeMetaInfo::isUrl() const
{
- if constexpr (useProjectStorage()) {
- if (!isValid())
- return false;
+#ifdef QDS_USE_PROJECTSTORAGE
+ if (!isValid())
+ return false;
- using NanotraceHR::keyValue;
- NanotraceHR::Tracer tracer{"is url"_t, category(), keyValue("type id", m_typeId)};
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"is url"_t, category(), keyValue("type id", m_typeId)};
- using namespace Storage::Info;
- return isValid() && isTypeId(m_typeId, m_projectStorage->builtinTypeId());
- } else {
- if (!isValid())
- return false;
+ using namespace Storage::Info;
+ return isValid() && isTypeId(m_typeId, m_projectStorage->builtinTypeId());
+#else
+ if (!isValid())
+ return false;
- auto type = simplifiedTypeName();
+ auto type = simplifiedTypeName();
- return type == "url" || type == "QUrl";
- }
+ return type == "url" || type == "QUrl";
+#endif
}
bool NodeMetaInfo::isQtQuick3DTexture() const
@@ -4249,40 +4277,40 @@ PropertyMetaInfo::~PropertyMetaInfo() = default;
NodeMetaInfo PropertyMetaInfo::propertyType() const
{
- if constexpr (useProjectStorage()) {
- if (!isValid())
- return {};
+#ifdef QDS_USE_PROJECTSTORAGE
+ if (!isValid())
+ return {};
- using NanotraceHR::keyValue;
- NanotraceHR::Tracer tracer{"get property type"_t,
- category(),
- keyValue("property declaration id", m_id)};
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get property type"_t,
+ category(),
+ keyValue("property declaration id", m_id)};
- return {propertyData().propertyTypeId, m_projectStorage};
- } else {
- if (isValid())
- return NodeMetaInfo{nodeMetaInfoPrivateData()->model(),
- nodeMetaInfoPrivateData()->propertyType(propertyName()),
- -1,
- -1};
- }
+ return {propertyData().propertyTypeId, m_projectStorage};
+#else
+ if (isValid())
+ return NodeMetaInfo{nodeMetaInfoPrivateData()->model(),
+ nodeMetaInfoPrivateData()->propertyType(propertyName()),
+ -1,
+ -1};
+#endif
return {};
}
NodeMetaInfo PropertyMetaInfo::type() const
{
- if constexpr (useProjectStorage()) {
- if (!isValid())
- return {};
+#ifdef QDS_USE_PROJECTSTORAGE
+ if (!isValid())
+ return {};
- using NanotraceHR::keyValue;
- NanotraceHR::Tracer tracer{"get property owner type "_t,
- category(),
- keyValue("property declaration id", m_id)};
+ using NanotraceHR::keyValue;
+ NanotraceHR::Tracer tracer{"get property owner type "_t,
+ category(),
+ keyValue("property declaration id", m_id)};
- return NodeMetaInfo(propertyData().typeId, m_projectStorage);
- }
+ return NodeMetaInfo(propertyData().typeId, m_projectStorage);
+#endif
return {};
}
@@ -4530,7 +4558,11 @@ const Storage::Info::PropertyDeclaration &PropertyMetaInfo::propertyData() const
TypeName PropertyMetaInfo::propertyTypeName() const
{
+#ifndef QDS_USE_PROJECTSTORAGE
return propertyType().typeName();
+#else
+ return {};
+#endif
}
const NodeMetaInfoPrivate *PropertyMetaInfo::nodeMetaInfoPrivateData() const
@@ -4554,37 +4586,36 @@ const PropertyName &PropertyMetaInfo::propertyName() const
NodeMetaInfo NodeMetaInfo::commonBase(const NodeMetaInfo &metaInfo) const
{
- if constexpr (useProjectStorage()) {
- if (isValid() && metaInfo) {
- const auto firstTypeIds = m_projectStorage->prototypeAndSelfIds(m_typeId);
- const auto secondTypeIds = m_projectStorage->prototypeAndSelfIds(metaInfo.m_typeId);
- auto found = std::ranges::find_if(firstTypeIds, [&](TypeId firstTypeId) {
- return std::ranges::find(secondTypeIds, firstTypeId) != secondTypeIds.end();
- });
+#ifdef QDS_USE_PROJECTSTORAGE
+ if (isValid() && metaInfo) {
+ const auto firstTypeIds = m_projectStorage->prototypeAndSelfIds(m_typeId);
+ const auto secondTypeIds = m_projectStorage->prototypeAndSelfIds(metaInfo.m_typeId);
+ auto found = std::ranges::find_if(firstTypeIds, [&](TypeId firstTypeId) {
+ return std::ranges::find(secondTypeIds, firstTypeId) != secondTypeIds.end();
+ });
- if (found != firstTypeIds.end()) {
- return NodeMetaInfo{*found, m_projectStorage};
- }
- }
- } else {
- for (const NodeMetaInfo &info : metaInfo.selfAndPrototypes()) {
- if (isBasedOn(info)) {
- return info;
- }
+ if (found != firstTypeIds.end())
+ return NodeMetaInfo{*found, m_projectStorage};
+ }
+#else
+ for (const NodeMetaInfo &info : metaInfo.selfAndPrototypes()) {
+ if (isBasedOn(info)) {
+ return info;
}
}
+#endif
return {};
}
NodeMetaInfo::NodeMetaInfos NodeMetaInfo::heirs() const
{
- if constexpr (useProjectStorage()) {
- if (isValid()) {
- return Utils::transform(m_projectStorage->heirIds(m_typeId),
- NodeMetaInfo::bind(m_projectStorage));
- }
+#ifdef QDS_USE_PROJECTSTORAGE
+ if (isValid()) {
+ return Utils::transform(m_projectStorage->heirIds(m_typeId),
+ NodeMetaInfo::bind(m_projectStorage));
}
+#endif
return {};
}
diff --git a/src/plugins/qmldesigner/libs/designercore/model/model.cpp b/src/plugins/qmldesigner/libs/designercore/model/model.cpp
index f54ed1758a8..4b7b776b34e 100644
--- a/src/plugins/qmldesigner/libs/designercore/model/model.cpp
+++ b/src/plugins/qmldesigner/libs/designercore/model/model.cpp
@@ -1789,6 +1789,7 @@ Model::Model(ProjectStorageDependencies projectStorageDependencies,
std::move(resourceManagement)))
{}
+#ifndef QDS_USE_PROJECTSTORAGE
Model::Model(const TypeName &typeName,
int major,
int minor,
@@ -1797,6 +1798,7 @@ Model::Model(const TypeName &typeName,
: d(std::make_unique(
this, typeName, major, minor, metaInfoProxyModel, std::move(resourceManagement)))
{}
+#endif
ModelPointer Model::createModel(const TypeName &typeName,
std::unique_ptr resourceManagement)
@@ -1947,6 +1949,9 @@ void Model::startDrag(std::unique_ptr mimeData, const QPixmap &icon,
void Model::endDrag()
{
+ if (!d->drag)
+ return;
+
d->notifyDragEnded();
d->drag.reset();
}
@@ -2481,6 +2486,16 @@ NodeMetaInfo Model::qtQuickTextEditMetaInfo() const
}
}
+NodeMetaInfo Model::qtQuickControlsLabelMetaInfo() const
+{
+#ifdef QDS_USE_PROJECTSTORAGE
+ using namespace Storage::Info;
+ return createNodeMetaInfo();
+#else
+ return metaInfo("QtQuick.Controls.Label");
+#endif
+}
+
NodeMetaInfo Model::qtQuickControlsTextAreaMetaInfo() const
{
if constexpr (useProjectStorage()) {
@@ -2774,24 +2789,26 @@ namespace {
}
} // namespace
-NodeMetaInfo Model::metaInfo(const TypeName &typeName, int majorVersion, int minorVersion) const
+NodeMetaInfo Model::metaInfo(const TypeName &typeName,
+ [[maybe_unused]] int majorVersion,
+ [[maybe_unused]] int minorVersion) const
{
- if constexpr (useProjectStorage()) {
- return NodeMetaInfo(d->projectStorage->typeId(d->importedTypeNameId(typeName)),
- d->projectStorage);
- } else {
- return NodeMetaInfo(metaInfoProxyModel(), typeName, majorVersion, minorVersion);
- }
+#ifdef QDS_USE_PROJECTSTORAGE
+ return NodeMetaInfo(d->projectStorage->typeId(d->importedTypeNameId(typeName)), d->projectStorage);
+#else
+ return NodeMetaInfo(metaInfoProxyModel(), typeName, majorVersion, minorVersion);
+#endif
}
-NodeMetaInfo Model::metaInfo(Module module, Utils::SmallStringView typeName, Storage::Version version) const
+NodeMetaInfo Model::metaInfo([[maybe_unused]] Module module,
+ [[maybe_unused]] Utils::SmallStringView typeName,
+ [[maybe_unused]] Storage::Version version) const
{
- if constexpr (useProjectStorage()) {
- return NodeMetaInfo(d->projectStorage->typeId(module.id(), typeName, version),
- d->projectStorage);
- } else {
- return {};
- }
+#ifdef QDS_USE_PROJECTSTORAGE
+ return NodeMetaInfo(d->projectStorage->typeId(module.id(), typeName, version), d->projectStorage);
+#else
+ return {};
+#endif
}
#ifndef QDS_USE_PROJECTSTORAGE
diff --git a/src/plugins/qmldesigner/libs/designercore/model/modelnode.cpp b/src/plugins/qmldesigner/libs/designercore/model/modelnode.cpp
index 8eba7549bf5..0dc461159fc 100644
--- a/src/plugins/qmldesigner/libs/designercore/model/modelnode.cpp
+++ b/src/plugins/qmldesigner/libs/designercore/model/modelnode.cpp
@@ -687,14 +687,14 @@ NodeMetaInfo ModelNode::metaInfo() const
if (!isValid())
return {};
- if constexpr (useProjectStorage()) {
- return NodeMetaInfo(m_internalNode->typeId, m_model->projectStorage());
- } else {
- return NodeMetaInfo(m_model->metaInfoProxyModel(),
- m_internalNode->typeName,
- m_internalNode->majorVersion,
- m_internalNode->minorVersion);
- }
+#ifdef QDS_USE_PROJECTSTORAGE
+ return NodeMetaInfo(m_internalNode->typeId, m_model->projectStorage());
+#else
+ return NodeMetaInfo(m_model->metaInfoProxyModel(),
+ m_internalNode->typeName,
+ m_internalNode->majorVersion,
+ m_internalNode->minorVersion);
+#endif
}
bool ModelNode::hasMetaInfo() const
diff --git a/src/plugins/qmldesigner/libs/designercore/projectstorage/commontypecache.h b/src/plugins/qmldesigner/libs/designercore/projectstorage/commontypecache.h
index 76305b1fbee..618c9418c18 100644
--- a/src/plugins/qmldesigner/libs/designercore/projectstorage/commontypecache.h
+++ b/src/plugins/qmldesigner/libs/designercore/projectstorage/commontypecache.h
@@ -58,6 +58,7 @@ inline constexpr char Item[] = "Item";
inline constexpr char JsonListModel[] = "JsonListModel";
inline constexpr char KeyframeGroup[] = "KeyframeGroup";
inline constexpr char Keyframe[] = "Keyframe";
+inline constexpr char Label[] = "Label";
inline constexpr char Layout[] = "Layout";
inline constexpr char Light[] = "Light";
inline constexpr char ListElement[] = "ListElement";
@@ -236,6 +237,7 @@ class CommonTypeCache
CacheType,
CacheType,
CacheType,
+ CacheType,
CacheType,
CacheType,
CacheType,
diff --git a/src/plugins/qmldesigner/libs/designercore/projectstorage/filesystem.h b/src/plugins/qmldesigner/libs/designercore/projectstorage/filesystem.h
index 8e83cd2ff04..ae58b229d82 100644
--- a/src/plugins/qmldesigner/libs/designercore/projectstorage/filesystem.h
+++ b/src/plugins/qmldesigner/libs/designercore/projectstorage/filesystem.h
@@ -7,6 +7,8 @@
#include "filesysteminterface.h"
#include "sourcepathstorage/nonlockingmutex.h"
+#include
+
namespace QmlDesigner {
class SourcePathStorage;
@@ -16,10 +18,9 @@ class SourcePathCache;
class QMLDESIGNERCORE_EXPORT FileSystem : public FileSystemInterface
{
- using PathCache = SourcePathCache;
public:
- FileSystem(PathCache &sourcePathCache)
+ FileSystem(PathCacheType &sourcePathCache)
: m_sourcePathCache(sourcePathCache)
{}
@@ -33,7 +34,7 @@ public:
void remove(const SourceIds &sourceIds) override;
private:
- PathCache &m_sourcePathCache;
+ PathCacheType &m_sourcePathCache;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/libs/designercore/projectstorage/projectstorageinfotypes.h b/src/plugins/qmldesigner/libs/designercore/projectstorage/projectstorageinfotypes.h
index 7d1598191d6..8b602ed65a9 100644
--- a/src/plugins/qmldesigner/libs/designercore/projectstorage/projectstorageinfotypes.h
+++ b/src/plugins/qmldesigner/libs/designercore/projectstorage/projectstorageinfotypes.h
@@ -147,6 +147,7 @@ struct TypeTraits
, takesOverRenderingOfChildren{FlagIs::False}
, visibleInNavigator{FlagIs::False}
, visibleInLibrary{FlagIs::False}
+ , hideInNavigator{FlagIs::False}
, dummy2{0U}
{}
@@ -193,7 +194,8 @@ struct TypeTraits
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));
+ keyValue("visible in library", typeTraits.visibleInLibrary),
+ keyValue("hide in navigator", typeTraits.hideInNavigator));
convertToString(string, dict);
}
@@ -228,7 +230,8 @@ struct TypeTraits
FlagIs takesOverRenderingOfChildren : 2;
FlagIs visibleInNavigator : 2;
FlagIs visibleInLibrary : 2;
- unsigned int dummy2 : 6;
+ FlagIs hideInNavigator : 2;
+ unsigned int dummy2 : 4;
};
unsigned int annotation;
diff --git a/src/plugins/qmldesigner/libs/designercore/projectstorage/projectstorageinterface.h b/src/plugins/qmldesigner/libs/designercore/projectstorage/projectstorageinterface.h
index 69674ffc8bf..9cf0daf4e8c 100644
--- a/src/plugins/qmldesigner/libs/designercore/projectstorage/projectstorageinterface.h
+++ b/src/plugins/qmldesigner/libs/designercore/projectstorage/projectstorageinterface.h
@@ -17,7 +17,7 @@ namespace QmlDesigner {
class ProjectStorageInterface
{
- friend Storage::Info::CommonTypeCache;
+ friend Storage::Info::CommonTypeCache;
public:
ProjectStorageInterface(const ProjectStorageInterface &) = delete;
diff --git a/src/plugins/qmldesigner/libs/designercore/projectstorage/projectstorageupdater.h b/src/plugins/qmldesigner/libs/designercore/projectstorage/projectstorageupdater.h
index 344b0543a27..6c3353ff68a 100644
--- a/src/plugins/qmldesigner/libs/designercore/projectstorage/projectstorageupdater.h
+++ b/src/plugins/qmldesigner/libs/designercore/projectstorage/projectstorageupdater.h
@@ -41,12 +41,10 @@ class QMLDESIGNERCORE_EXPORT ProjectStorageUpdater final
: public ProjectStoragePathWatcherNotifierInterface
{
public:
- using PathCache = SourcePathCache;
-
ProjectStorageUpdater(FileSystemInterface &fileSystem,
ProjectStorageType &projectStorage,
FileStatusCache &fileStatusCache,
- PathCache &pathCache,
+ PathCacheType &pathCache,
QmlDocumentParserInterface &qmlDocumentParser,
QmlTypesParserInterface &qmlTypesParser,
class ProjectStoragePathWatcherInterface &pathWatcher,
@@ -243,7 +241,7 @@ private:
FileSystemInterface &m_fileSystem;
ProjectStorageType &m_projectStorage;
FileStatusCache &m_fileStatusCache;
- PathCache &m_pathCache;
+ PathCacheType &m_pathCache;
QmlDocumentParserInterface &m_qmlDocumentParser;
QmlTypesParserInterface &m_qmlTypesParser;
ProjectStoragePathWatcherInterface &m_pathWatcher;
diff --git a/src/plugins/qmldesigner/libs/designercore/projectstorage/qmldocumentparser.cpp b/src/plugins/qmldesigner/libs/designercore/projectstorage/qmldocumentparser.cpp
index b571cebac3d..17aa8ca9617 100644
--- a/src/plugins/qmldesigner/libs/designercore/projectstorage/qmldocumentparser.cpp
+++ b/src/plugins/qmldesigner/libs/designercore/projectstorage/qmldocumentparser.cpp
@@ -66,7 +66,7 @@ Utils::PathString createNormalizedPath(Utils::SmallStringView directoryPath,
Storage::Import createImport(const QmlDom::Import &qmlImport,
SourceId sourceId,
Utils::SmallStringView directoryPath,
- QmlDocumentParser::ProjectStorage &storage)
+ ProjectStorageType &storage)
{
using Storage::ModuleKind;
using QmlUriKind = QQmlJS::Dom::QmlUri::Kind;
@@ -99,7 +99,7 @@ Storage::Import createImport(const QmlDom::Import &qmlImport,
QualifiedImports createQualifiedImports(const QList &qmlImports,
SourceId sourceId,
Utils::SmallStringView directoryPath,
- QmlDocumentParser::ProjectStorage &storage)
+ ProjectStorageType &storage)
{
NanotraceHR::Tracer tracer{"create qualified imports"_t,
category(),
@@ -123,7 +123,7 @@ void addImports(Storage::Imports &imports,
const QList &qmlImports,
SourceId sourceId,
Utils::SmallStringView directoryPath,
- QmlDocumentParser::ProjectStorage &storage)
+ ProjectStorageType &storage)
{
int importCount = 0;
for (const QmlDom::Import &qmlImport : qmlImports) {
diff --git a/src/plugins/qmldesigner/libs/designercore/projectstorage/qmldocumentparser.h b/src/plugins/qmldesigner/libs/designercore/projectstorage/qmldocumentparser.h
index 7b64322ab4f..bdf50aac23e 100644
--- a/src/plugins/qmldesigner/libs/designercore/projectstorage/qmldocumentparser.h
+++ b/src/plugins/qmldesigner/libs/designercore/projectstorage/qmldocumentparser.h
@@ -7,8 +7,8 @@
#include "qmldocumentparserinterface.h"
#include "sourcepathstorage/nonlockingmutex.h"
+#include
#include
-
namespace QmlDesigner {
template
@@ -18,16 +18,14 @@ class SourcePathStorage;
class QMLDESIGNERCORE_EXPORT QmlDocumentParser final : public QmlDocumentParserInterface
{
public:
- using ProjectStorage = QmlDesigner::ProjectStorage;
- using PathCache = QmlDesigner::SourcePathCache;
#ifdef QDS_BUILD_QMLPARSER
- QmlDocumentParser(ProjectStorage &storage, PathCache &pathCache)
+ QmlDocumentParser(ProjectStorageType &storage, PathCacheType &pathCache)
: m_storage{storage}
, m_pathCache{pathCache}
{}
#else
- QmlDocumentParser(ProjectStorage &, PathCache &)
+ QmlDocumentParser(ProjectStorage &, PathCacheType &)
{}
#endif
@@ -39,8 +37,8 @@ public:
private:
// m_pathCache and m_storage are only used when compiled for QDS
#ifdef QDS_BUILD_QMLPARSER
- ProjectStorage &m_storage;
- PathCache &m_pathCache;
+ ProjectStorageType &m_storage;
+ PathCacheType &m_pathCache;
#endif
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/libs/designercore/projectstorage/typeannotationreader.cpp b/src/plugins/qmldesigner/libs/designercore/projectstorage/typeannotationreader.cpp
index 71eba949662..4d604cdf2ea 100644
--- a/src/plugins/qmldesigner/libs/designercore/projectstorage/typeannotationreader.cpp
+++ b/src/plugins/qmldesigner/libs/designercore/projectstorage/typeannotationreader.cpp
@@ -400,6 +400,8 @@ void setTrait(QStringView name, FlagIs flag, Storage::TypeTraits &traits)
traits.visibleInNavigator = flag;
} else if (name == "visibleInLibrary"_L1) {
traits.visibleInLibrary = flag;
+ } else if (name == "hideInNavigator"_L1) {
+ traits.hideInNavigator = flag;
}
}
diff --git a/src/plugins/qmldesigner/libs/designercore/rewriter/texttomodelmerger.cpp b/src/plugins/qmldesigner/libs/designercore/rewriter/texttomodelmerger.cpp
index d41fa2cd7a8..b03e0f3b52e 100644
--- a/src/plugins/qmldesigner/libs/designercore/rewriter/texttomodelmerger.cpp
+++ b/src/plugins/qmldesigner/libs/designercore/rewriter/texttomodelmerger.cpp
@@ -1432,8 +1432,13 @@ QmlDesigner::PropertyName TextToModelMerger::syncScriptBinding(ModelNode &modelN
prefix,
script->qualifiedId,
astValue);
+
+#ifndef QDS_USE_PROJECTSTORAGE
// Can happen if the type was just created and was not fully processed yet
const bool newlyCreatedTypeCase = !modelNode.metaInfo().properties().size();
+#else
+ const bool newlyCreatedTypeCase = false;
+#endif
if (enumValue.isValid()) { // It is a qualified enum:
AbstractProperty modelProperty = modelNode.property(astPropertyName.toUtf8());
@@ -1805,6 +1810,7 @@ void ModelValidator::shouldBeVariantProperty([[maybe_unused]] AbstractProperty &
const QVariant & /*qmlVariantValue*/,
const TypeName & /*dynamicTypeName*/)
{
+ QTC_CHECK(modelProperty.isVariantProperty());
Q_ASSERT(modelProperty.isVariantProperty());
Q_ASSERT(0);
}
@@ -1866,6 +1872,7 @@ void ModelValidator::propertyAbsentFromQml([[maybe_unused]] AbstractProperty &mo
{
Q_ASSERT(!modelProperty.isValid());
Q_ASSERT(0);
+ QTC_CHECK(!modelProperty.isValid());
}
void ModelValidator::idsDiffer([[maybe_unused]] ModelNode &modelNode,
diff --git a/src/plugins/qmldesigner/libs/designsystem/CMakeLists.txt b/src/plugins/qmldesigner/libs/designsystem/CMakeLists.txt
new file mode 100644
index 00000000000..05fde136802
--- /dev/null
+++ b/src/plugins/qmldesigner/libs/designsystem/CMakeLists.txt
@@ -0,0 +1,16 @@
+add_qtc_library(DesignSystem STATIC
+ PUBLIC_INCLUDES ${CMAKE_CURRENT_LIST_DIR}
+ DEPENDS
+ Qt::Core Qt::Widgets QmlDesignerCore
+ SOURCES
+ dsconstants.h
+ dsthemegroup.h dsthemegroup.cpp
+ dsthememanager.h dsthememanager.cpp
+)
+
+extend_qtc_library(DesignSystem
+ CONDITION ENABLE_COMPILE_WARNING_AS_ERROR
+ PROPERTIES COMPILE_WARNING_AS_ERROR ON
+ PUBLIC_COMPILE_OPTIONS
+ $<$:-Wno-error=maybe-uninitialized>
+)
diff --git a/src/plugins/qmldesigner/libs/designsystem/designsystem_global.h b/src/plugins/qmldesigner/libs/designsystem/designsystem_global.h
new file mode 100644
index 00000000000..835c8b0ad3d
--- /dev/null
+++ b/src/plugins/qmldesigner/libs/designsystem/designsystem_global.h
@@ -0,0 +1,14 @@
+// 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
+
+#if defined(DESIGNSYSTEM_LIBRARY)
+# define DESIGNSYSTEM_EXPORT Q_DECL_EXPORT
+#elif defined(DESIGNSYSTEM_STATIC_LIBRARY)
+# define DESIGNSYSTEM_EXPORT
+#else
+# define DESIGNSYSTEM_EXPORT Q_DECL_IMPORT
+#endif
diff --git a/src/plugins/qmldesigner/components/designsystem/dsconstants.h b/src/plugins/qmldesigner/libs/designsystem/dsconstants.h
similarity index 100%
rename from src/plugins/qmldesigner/components/designsystem/dsconstants.h
rename to src/plugins/qmldesigner/libs/designsystem/dsconstants.h
diff --git a/src/plugins/qmldesigner/components/designsystem/dsthemegroup.cpp b/src/plugins/qmldesigner/libs/designsystem/dsthemegroup.cpp
similarity index 100%
rename from src/plugins/qmldesigner/components/designsystem/dsthemegroup.cpp
rename to src/plugins/qmldesigner/libs/designsystem/dsthemegroup.cpp
diff --git a/src/plugins/qmldesigner/components/designsystem/dsthemegroup.h b/src/plugins/qmldesigner/libs/designsystem/dsthemegroup.h
similarity index 94%
rename from src/plugins/qmldesigner/components/designsystem/dsthemegroup.h
rename to src/plugins/qmldesigner/libs/designsystem/dsthemegroup.h
index b76e2f3d504..e61a915623e 100644
--- a/src/plugins/qmldesigner/components/designsystem/dsthemegroup.h
+++ b/src/plugins/qmldesigner/libs/designsystem/dsthemegroup.h
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#pragma once
-#include "qmldesignercomponents_global.h"
+#include "designsystem_global.h"
#include "dsconstants.h"
#include "nodeinstanceglobal.h"
@@ -18,7 +18,7 @@ enum class DECORATION_CONTEXT {
COMPONENT_THEME,
};
-class QMLDESIGNERCOMPONENTS_EXPORT DSThemeGroup
+class DESIGNSYSTEM_EXPORT DSThemeGroup
{
struct PropertyData
{
diff --git a/src/plugins/qmldesigner/components/designsystem/dsthememanager.cpp b/src/plugins/qmldesigner/libs/designsystem/dsthememanager.cpp
similarity index 100%
rename from src/plugins/qmldesigner/components/designsystem/dsthememanager.cpp
rename to src/plugins/qmldesigner/libs/designsystem/dsthememanager.cpp
diff --git a/src/plugins/qmldesigner/components/designsystem/dsthememanager.h b/src/plugins/qmldesigner/libs/designsystem/dsthememanager.h
similarity index 94%
rename from src/plugins/qmldesigner/components/designsystem/dsthememanager.h
rename to src/plugins/qmldesigner/libs/designsystem/dsthememanager.h
index e3ac9e2e4c9..0972dcd7893 100644
--- a/src/plugins/qmldesigner/components/designsystem/dsthememanager.h
+++ b/src/plugins/qmldesigner/libs/designsystem/dsthememanager.h
@@ -3,7 +3,7 @@
#pragma once
-#include "qmldesignercomponents_global.h"
+#include "designsystem_global.h"
#include "dsconstants.h"
#include "dsthemegroup.h"
@@ -15,7 +15,8 @@ namespace QmlDesigner {
using ThemeName = PropertyName;
class DSTheme;
-class QMLDESIGNERCOMPONENTS_EXPORT DSThemeManager
+
+class DESIGNSYSTEM_EXPORT DSThemeManager
{
public:
diff --git a/src/plugins/qmldesigner/qmldesignerconstants.h b/src/plugins/qmldesigner/qmldesignerconstants.h
index 116dc94dcca..8aef417b3bc 100644
--- a/src/plugins/qmldesigner/qmldesignerconstants.h
+++ b/src/plugins/qmldesigner/qmldesignerconstants.h
@@ -140,6 +140,18 @@ inline constexpr char EVENT_TOOLBAR_SET_CURRENT_WORKSPACE[] = "ToolBarSetCurrent
inline constexpr char EVENT_TOOLBAR_EDIT_GLOBAL_ANNOTATION[] = "ToolBarEditGlobalAnnotation";
inline constexpr char EVENT_STATUSBAR_SHOW_ZOOM[] = "StatusBarShowZoomMenu";
inline constexpr char EVENT_STATUSBAR_SET_STYLE[] = "StatusBarSetCurrentStyle";
+inline constexpr char EVENT_DESIGNVIEWER_PROJECT_UPLOADED[] = "DesignViewerProjectUploaded";
+inline constexpr char EVENT_DESIGNVIEWER_PROJECT_DOWNLOADED[] = "DesignViewerProjectDownloaded";
+inline constexpr char EVENT_DESIGNVIEWER_PROJECT_DELETED[] = "DesignViewerProjectDeleted";
+inline constexpr char EVENT_DESIGNVIEWER_PROJECT_SHARED[] = "DesignViewerProjectShared";
+inline constexpr char EVENT_DESIGNVIEWER_PROJECT_UNSHARED[] = "DesignViewerProjectUnshared";
+inline constexpr char EVENT_DESIGNVIEWER_PROJECT_UNSHARED_ALL[] = "DesignViewerProjectUnsharedAll";
+inline constexpr char EVENT_DESIGNVIEWER_PROJECT_THUMBNAIL_UPLOADED[]
+ = "DesignViewerProjectThumbnailUploaded";
+inline constexpr char EVENT_DESIGNVIEWER_PROJECT_THUMBNAIL_DELETED[]
+ = "DesignViewerProjectThumbnailDeleted";
+inline constexpr char EVENT_DESIGNVIEWER_PROJECT_THUMBNAIL_DOWNLOADED[]
+ = "DesignViewerProjectThumbnailDownloaded";
inline constexpr char PROPERTY_EDITOR_CLASSNAME_PROPERTY[] = "__classNamePrivateInternal";
diff --git a/src/plugins/qmldesigner/qmldesignerplugin.cpp b/src/plugins/qmldesigner/qmldesignerplugin.cpp
index 2913a8e6f6d..97621d53936 100644
--- a/src/plugins/qmldesigner/qmldesignerplugin.cpp
+++ b/src/plugins/qmldesigner/qmldesignerplugin.cpp
@@ -702,6 +702,11 @@ Internal::DesignModeWidget *QmlDesignerPlugin::mainWidget() const
return d ? &d->mainWidget : nullptr;
}
+QmlDesignerProjectManager &QmlDesignerPlugin::projectManagerForPluginInitializationOnly()
+{
+ return m_instance->d->projectManager;
+}
+
QWidget *QmlDesignerPlugin::createProjectExplorerWidget(QWidget *parent) const
{
return Internal::DesignModeWidget::createProjectExplorerWidget(parent);
diff --git a/src/plugins/qmldesigner/qmldesignerplugin.h b/src/plugins/qmldesigner/qmldesignerplugin.h
index 8039251b99b..bdb45cc8f42 100644
--- a/src/plugins/qmldesigner/qmldesignerplugin.h
+++ b/src/plugins/qmldesigner/qmldesignerplugin.h
@@ -60,6 +60,8 @@ public:
DesignDocument *currentDesignDocument() const;
Internal::DesignModeWidget *mainWidget() const;
+ static QmlDesignerProjectManager &projectManagerForPluginInitializationOnly();
+
QWidget *createProjectExplorerWidget(QWidget *parent) const;
void switchToTextModeDeferred();
diff --git a/src/plugins/qmldesigner/qmldesignerprojectmanager.cpp b/src/plugins/qmldesigner/qmldesignerprojectmanager.cpp
index 6bba6c12369..9c04f9b1bd3 100644
--- a/src/plugins/qmldesigner/qmldesignerprojectmanager.cpp
+++ b/src/plugins/qmldesigner/qmldesignerprojectmanager.cpp
@@ -202,7 +202,7 @@ public:
FileStatusCache fileStatusCache{fileSystem};
QmlDocumentParser qmlDocumentParser;
QmlTypesParser qmlTypesParser{storage};
- ProjectStoragePathWatcher pathWatcher;
+ ProjectStoragePathWatcher pathWatcher;
ProjectPartId projectPartId;
ProjectStorageUpdater updater;
};
@@ -265,7 +265,7 @@ public:
Sqlite::LockingMode::Normal};
QmlDesigner::SourcePathStorage sourcePathStorage{sourcePathDatabase,
sourcePathDatabase.isInitialized()};
- PathCacheType pathCache{sourcePathStorage};
+ PathCache pathCache{sourcePathStorage};
};
QmlDesignerProjectManager::QmlDesignerProjectManager(ExternalDependenciesInterface &externalDependencies)
@@ -322,12 +322,12 @@ AsynchronousImageCache &QmlDesignerProjectManager::asynchronousImageCache()
}
namespace {
-[[maybe_unused]] ProjectStorage *dummyProjectStorage()
+[[maybe_unused]] ProjectStorageType *dummyProjectStorage()
{
return nullptr;
}
-[[maybe_unused]] ProjectStorageUpdater::PathCache *dummyPathCache()
+[[maybe_unused]] PathCacheType *dummyPathCache()
{
return nullptr;
}
diff --git a/src/plugins/qmldesigner/qmldesignerprojectmanager.h b/src/plugins/qmldesigner/qmldesignerprojectmanager.h
index 10c0bd42618..4947dbcd437 100644
--- a/src/plugins/qmldesigner/qmldesignerprojectmanager.h
+++ b/src/plugins/qmldesigner/qmldesignerprojectmanager.h
@@ -5,6 +5,7 @@
#include "modelfwd.h"
#include
+#include
#include
#include
@@ -28,7 +29,7 @@ namespace QmlDesigner {
class ExternalDependenciesInterface;
-class QmlDesignerProjectManager
+class QMLDESIGNER_EXPORT QmlDesignerProjectManager
{
class QmlDesignerProjectManagerProjectData;
class PreviewImageCacheData;
diff --git a/src/plugins/studiowelcome/CMakeLists.txt b/src/plugins/studiowelcome/CMakeLists.txt
index c4db40db5e9..ead7b757893 100644
--- a/src/plugins/studiowelcome/CMakeLists.txt
+++ b/src/plugins/studiowelcome/CMakeLists.txt
@@ -4,6 +4,7 @@ add_qtc_plugin(StudioWelcome
PLUGIN_DEPENDS Core ProjectExplorer QtSupport QmlDesigner
DEFINES STUDIO_QML_PATH="${CMAKE_CURRENT_SOURCE_DIR}/qml/"
SOURCES
+ fieldhelper.cpp fieldhelper.h
studiowelcomeplugin.cpp studiowelcomeplugin.h
newprojectdialogimageprovider.cpp newprojectdialogimageprovider.h
presetmodel.cpp presetmodel.h
diff --git a/src/plugins/studiowelcome/createproject.cpp b/src/plugins/studiowelcome/createproject.cpp
index 6ed783780cb..5ed59a339e4 100644
--- a/src/plugins/studiowelcome/createproject.cpp
+++ b/src/plugins/studiowelcome/createproject.cpp
@@ -43,6 +43,9 @@ void CreateProject::processFieldPage(ProjectExplorer::JsonFieldPage *page)
if (page->jsonField("UseVirtualKeyboard"))
m_wizard.setUseVirtualKeyboard(m_useVirtualKeyboard);
+ if (page->jsonField("EnableCMakeGeneration"))
+ m_wizard.enableCMakeGeneration(m_enableCMakeGeneration);
+
auto widthField = dynamic_cast(page->jsonField("CustomScreenWidth"));
auto heightField = dynamic_cast(page->jsonField("CustomScreenHeight"));
diff --git a/src/plugins/studiowelcome/createproject.h b/src/plugins/studiowelcome/createproject.h
index e1b0af34205..b9abe2d2edb 100644
--- a/src/plugins/studiowelcome/createproject.h
+++ b/src/plugins/studiowelcome/createproject.h
@@ -28,6 +28,11 @@ public:
CreateProject &withStyle(int styleIndex) { m_styleIndex = styleIndex; return *this; }
CreateProject &useQtVirtualKeyboard(bool value) { m_useVirtualKeyboard = value; return *this; }
+ CreateProject &enableCMakeGeneration(bool value)
+ {
+ m_enableCMakeGeneration = value;
+ return *this;
+ }
CreateProject &saveAsDefaultLocation(bool value) { m_saveAsDefaultLocation = value; return *this; }
CreateProject &withTargetQtVersion(int targetQtVersionIndex)
{ m_targetQtVersionIndex = targetQtVersionIndex; return *this; }
@@ -48,6 +53,7 @@ private:
QString m_customHeight;
int m_styleIndex = -1;
bool m_useVirtualKeyboard = false;
+ bool m_enableCMakeGeneration = false;
bool m_saveAsDefaultLocation = false;
int m_targetQtVersionIndex = -1;
};
diff --git a/src/plugins/studiowelcome/fieldhelper.cpp b/src/plugins/studiowelcome/fieldhelper.cpp
new file mode 100644
index 00000000000..5fdf3532be3
--- /dev/null
+++ b/src/plugins/studiowelcome/fieldhelper.cpp
@@ -0,0 +1,89 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "fieldhelper.h"
+
+#include
+#include
+
+#include
+
+using namespace StudioWelcome::FieldHelper;
+
+CheckBoxHelper::CheckBoxHelper(ProjectExplorer::JsonFieldPage *detailsPage, const QString &fieldName)
+ : m_field(dynamic_cast(detailsPage->jsonField(fieldName)))
+{}
+
+void CheckBoxHelper::setChecked(bool value)
+{
+ QTC_ASSERT(m_field, return);
+
+ m_field->setChecked(value);
+}
+
+ComboBoxHelper::ComboBoxHelper(ProjectExplorer::JsonFieldPage *detailsPage, const QString &fieldName)
+ : m_field(dynamic_cast(detailsPage->jsonField(fieldName)))
+{}
+
+void ComboBoxHelper::selectIndex(int index)
+{
+ QTC_ASSERT(m_field, return);
+
+ m_field->selectRow(index);
+}
+
+QString ComboBoxHelper::text(int index) const
+{
+ QTC_ASSERT(m_field, return {});
+
+ QStandardItemModel *model = m_field->model();
+ if (index < 0 || index >= model->rowCount())
+ return {};
+
+ return model->item(index)->text();
+}
+
+int ComboBoxHelper::indexOf(const QString &text) const
+{
+ QTC_ASSERT(m_field, return -1);
+
+ const QStandardItemModel *model = m_field->model();
+ for (int i = 0; i < model->rowCount(); ++i) {
+ const QStandardItem *item = model->item(i, 0);
+ const QString text = item->text();
+
+ if (text == text)
+ return i;
+ }
+
+ return -1;
+}
+
+int ComboBoxHelper::selectedIndex() const
+{
+ QTC_ASSERT(m_field, return -1);
+
+ return m_field->selectedRow();
+}
+
+QStandardItemModel *ComboBoxHelper::model() const
+{
+ QTC_ASSERT(m_field, return {});
+
+ return m_field->model();
+}
+
+QStringList ComboBoxHelper::allTexts() const
+{
+ QTC_ASSERT(m_field, return {});
+
+ QStandardItemModel *model = m_field->model();
+ const int rows = model->rowCount();
+ QStringList result;
+ result.reserve(rows);
+
+ for (int i = 0; i < rows; ++i)
+ result.append(model->item(i)->text());
+
+ return result;
+}
diff --git a/src/plugins/studiowelcome/fieldhelper.h b/src/plugins/studiowelcome/fieldhelper.h
new file mode 100644
index 00000000000..886e49d0df8
--- /dev/null
+++ b/src/plugins/studiowelcome/fieldhelper.h
@@ -0,0 +1,46 @@
+// 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
+
+QT_FORWARD_DECLARE_CLASS(QStandardItemModel)
+
+namespace ProjectExplorer {
+class JsonFieldPage;
+class CheckBoxField;
+class ComboBoxField;
+}
+
+namespace StudioWelcome::FieldHelper {
+
+class CheckBoxHelper
+{
+public:
+ CheckBoxHelper(ProjectExplorer::JsonFieldPage *detailsPage, const QString &fieldName);
+
+ void setChecked(bool value);
+
+private:
+ ProjectExplorer::CheckBoxField *m_field = nullptr;
+};
+
+class ComboBoxHelper
+{
+public:
+ ComboBoxHelper(ProjectExplorer::JsonFieldPage *detailsPage, const QString &fieldName);
+
+ void selectIndex(int index);
+
+ QString text(int index) const;
+ int indexOf(const QString &text) const;
+ int selectedIndex() const;
+ QStandardItemModel *model() const;
+ QStringList allTexts() const;
+
+private:
+ ProjectExplorer::ComboBoxField *m_field = nullptr;
+};
+
+} // namespace StudioWelcome::FieldHelper
diff --git a/src/plugins/studiowelcome/presetmodel.cpp b/src/plugins/studiowelcome/presetmodel.cpp
index 06e8def612b..e4562872b7a 100644
--- a/src/plugins/studiowelcome/presetmodel.cpp
+++ b/src/plugins/studiowelcome/presetmodel.cpp
@@ -93,6 +93,7 @@ PresetItems PresetData::makeUserPresets(const PresetItems &wizardPresets,
presetItem->qtVersion = userPresetData.qtVersion;
presetItem->styleName = userPresetData.styleName;
presetItem->useQtVirtualKeyboard = userPresetData.useQtVirtualKeyboard;
+ presetItem->enableCMakeGeneration = userPresetData.enableCMakeGeneration;
presetItem->create = foundPreset->create;
presetItem->description = foundPreset->description;
diff --git a/src/plugins/studiowelcome/presetmodel.h b/src/plugins/studiowelcome/presetmodel.h
index f23ec2ea778..94f11fb9aff 100644
--- a/src/plugins/studiowelcome/presetmodel.h
+++ b/src/plugins/studiowelcome/presetmodel.h
@@ -80,6 +80,7 @@ struct UserPresetItem : public PresetItem
public:
QString userName;
bool useQtVirtualKeyboard;
+ bool enableCMakeGeneration;
QString qtVersion;
QString styleName;
};
diff --git a/src/plugins/studiowelcome/qdsnewdialog.cpp b/src/plugins/studiowelcome/qdsnewdialog.cpp
index 1fa82e55034..1032e7fceea 100644
--- a/src/plugins/studiowelcome/qdsnewdialog.cpp
+++ b/src/plugins/studiowelcome/qdsnewdialog.cpp
@@ -133,6 +133,15 @@ void QdsNewDialog::setProjectLocation(const QString &location)
m_wizard.setProjectLocation(m_qmlProjectLocation);
}
+void QdsNewDialog::setHasCMakeGeneration(bool haveCmakeGen)
+{
+ if (m_qmlHasCMakeGeneration == haveCmakeGen)
+ return;
+
+ m_qmlHasCMakeGeneration = haveCmakeGen;
+ emit hasCMakeGenerationChanged();
+}
+
void QdsNewDialog::onStatusMessageChanged(Utils::InfoLabel::InfoType type, const QString &message)
{
switch (type) {
@@ -192,9 +201,16 @@ void QdsNewDialog::onWizardCreated(QStandardItemModel *screenSizeModel, QStandar
auto userPreset = m_currentPreset->asUserPreset();
if (m_qmlDetailsLoaded) {
+ setHasCMakeGeneration(m_wizard.hasCMakeGeneration());
+
+ if (m_currentPreset->isUserPreset()) {
+ if (getHaveVirtualKeyboard())
+ setUseVirtualKeyboard(userPreset->useQtVirtualKeyboard);
+ if (hasCMakeGeneration())
+ setEnableCMakeGeneration(userPreset->enableCMakeGeneration);
+ }
+
m_targetQtVersions.clear();
- if (m_currentPreset->isUserPreset() && m_wizard.haveVirtualKeyboard())
- setUseVirtualKeyboard(userPreset->useQtVirtualKeyboard);
if (m_wizard.haveTargetQtVersion()) {
m_targetQtVersions = m_wizard.targetQtVersionNames();
int index = m_currentPreset->isUserPreset() ? m_wizard.targetQtVersionIndex(userPreset->qtVersion)
@@ -227,6 +243,15 @@ void QdsNewDialog::onWizardCreated(QStandardItemModel *screenSizeModel, QStandar
}
}
+void QdsNewDialog::setEnableCMakeGeneration(bool newQmlEnableCMakeGeneration)
+{
+ if (m_qmlEnableCMakeGeneration == newQmlEnableCMakeGeneration)
+ return;
+
+ m_qmlEnableCMakeGeneration = newQmlEnableCMakeGeneration;
+ emit enableCMakeGenerationChanged();
+}
+
QString QdsNewDialog::currentPresetQmlPath() const
{
if (!m_currentPreset || m_currentPreset->qmlPath.isEmpty())
@@ -385,6 +410,11 @@ bool QdsNewDialog::getHaveTargetQtVersion() const
return m_wizard.haveTargetQtVersion();
}
+bool QdsNewDialog::hasCMakeGeneration() const
+{
+ return m_qmlHasCMakeGeneration;
+}
+
void QdsNewDialog::accept()
{
CreateProject create{m_wizard};
@@ -395,6 +425,7 @@ void QdsNewDialog::accept()
.withScreenSizes(m_qmlScreenSizeIndex, m_qmlCustomWidth, m_qmlCustomHeight)
.withStyle(getStyleIndex())
.useQtVirtualKeyboard(m_qmlUseVirtualKeyboard)
+ .enableCMakeGeneration(m_qmlEnableCMakeGeneration)
.saveAsDefaultLocation(m_qmlSaveAsDefaultLocation)
.withTargetQtVersion(m_qmlTargetQtVersionIndex)
.execute();
@@ -446,6 +477,7 @@ UserPresetData QdsNewDialog::currentUserPresetData(const QString &displayName) c
QString targetQtVersion = "";
QString styleName = "";
bool useVirtualKeyboard = false;
+ bool enableCMakeGeneration = false;
if (m_wizard.haveTargetQtVersion())
targetQtVersion = m_wizard.targetQtVersionName(m_qmlTargetQtVersionIndex);
@@ -456,13 +488,18 @@ UserPresetData QdsNewDialog::currentUserPresetData(const QString &displayName) c
if (m_wizard.haveVirtualKeyboard())
useVirtualKeyboard = m_qmlUseVirtualKeyboard;
- UserPresetData preset = {m_currentPreset->categoryId,
- m_currentPreset->wizardName,
- displayName,
- screenSize,
- useVirtualKeyboard,
- targetQtVersion,
- styleName};
+ if (m_wizard.hasCMakeGeneration())
+ enableCMakeGeneration = m_qmlEnableCMakeGeneration;
+
+ UserPresetData preset{
+ m_currentPreset->categoryId,
+ m_currentPreset->wizardName,
+ displayName,
+ screenSize,
+ useVirtualKeyboard,
+ enableCMakeGeneration,
+ targetQtVersion,
+ styleName};
return preset;
}
diff --git a/src/plugins/studiowelcome/qdsnewdialog.h b/src/plugins/studiowelcome/qdsnewdialog.h
index 95bfa52fe9b..b5aee2ff065 100644
--- a/src/plugins/studiowelcome/qdsnewdialog.h
+++ b/src/plugins/studiowelcome/qdsnewdialog.h
@@ -34,7 +34,13 @@ public:
Q_PROPERTY(QString customHeight MEMBER m_qmlCustomHeight)
Q_PROPERTY(int styleIndex MEMBER m_qmlStyleIndex READ getStyleIndex WRITE setStyleIndex)
Q_PROPERTY(bool useVirtualKeyboard MEMBER m_qmlUseVirtualKeyboard READ getUseVirtualKeyboard WRITE setUseVirtualKeyboard NOTIFY useVirtualKeyboardChanged)
+ Q_PROPERTY(
+ bool enableCMakeGeneration
+ MEMBER m_qmlEnableCMakeGeneration
+ WRITE setEnableCMakeGeneration
+ NOTIFY enableCMakeGenerationChanged)
Q_PROPERTY(bool haveVirtualKeyboard MEMBER m_qmlHaveVirtualKeyboard READ getHaveVirtualKeyboard NOTIFY haveVirtualKeyboardChanged)
+ Q_PROPERTY(bool hasCMakeGeneration READ hasCMakeGeneration NOTIFY hasCMakeGenerationChanged)
Q_PROPERTY(bool haveTargetQtVersion MEMBER m_qmlHaveTargetQtVersion READ getHaveTargetQtVersion NOTIFY haveTargetQtVersionChanged)
Q_PROPERTY(int targetQtVersionIndex MEMBER m_qmlTargetQtVersionIndex READ getTargetQtVersionIndex WRITE setTargetQtVersionIndex NOTIFY targetQtVersionIndexChanged)
Q_PROPERTY(bool saveAsDefaultLocation MEMBER m_qmlSaveAsDefaultLocation WRITE setSaveAsDefaultLocation)
@@ -85,12 +91,15 @@ public:
bool getFieldsValid() const { return m_qmlFieldsValid; }
bool getHaveVirtualKeyboard() const;
bool getHaveTargetQtVersion() const;
+ bool hasCMakeGeneration() const;
void setSaveAsDefaultLocation(bool value) { m_qmlSaveAsDefaultLocation = value; }
QString getStatusMessage() const { return m_qmlStatusMessage; }
QString getStatusType() const { return m_qmlStatusType; }
+ void setEnableCMakeGeneration(bool newQmlEnableCMakeGeneration);
+
public slots:
void accept();
void reject();
@@ -102,7 +111,9 @@ signals:
void projectLocationChanged();
void projectDescriptionChanged();
void useVirtualKeyboardChanged();
+ void enableCMakeGenerationChanged();
void haveVirtualKeyboardChanged();
+ void hasCMakeGenerationChanged();
void haveTargetQtVersionChanged();
void statusMessageChanged();
void statusTypeChanged();
@@ -129,6 +140,8 @@ private:
emit projectDescriptionChanged();
}
+ void setHasCMakeGeneration(bool haveCmakeGen);
+
QString projectDescription() const { return m_qmlProjectDescription; }
void updateScreenSizes();
@@ -156,7 +169,9 @@ private:
// m_qmlStyleIndex is like a cache, so it needs to be updated on get()
mutable int m_qmlStyleIndex = -1;
bool m_qmlUseVirtualKeyboard = false;
+ bool m_qmlEnableCMakeGeneration = false;
bool m_qmlHaveVirtualKeyboard = false;
+ bool m_qmlHasCMakeGeneration = false;
bool m_qmlHaveTargetQtVersion = false;
bool m_qmlSaveAsDefaultLocation = false;
bool m_qmlFieldsValid = false;
diff --git a/src/plugins/studiowelcome/userpresets.cpp b/src/plugins/studiowelcome/userpresets.cpp
index ddc8a406261..cd551f5efe0 100644
--- a/src/plugins/studiowelcome/userpresets.cpp
+++ b/src/plugins/studiowelcome/userpresets.cpp
@@ -67,13 +67,16 @@ void UserPresetsStore::savePresets(const std::vector &presetItem
QJsonArray jsonArray;
for (const auto &preset : presetItems) {
- QJsonObject obj({{"categoryId", preset.categoryId},
- {"wizardName", preset.wizardName},
- {"name", preset.name},
- {"screenSize", preset.screenSize},
- {"useQtVirtualKeyboard", preset.useQtVirtualKeyboard},
- {"qtVersion", preset.qtVersion},
- {"styleName", preset.styleName}});
+ QJsonObject obj{
+ {"categoryId", preset.categoryId},
+ {"wizardName", preset.wizardName},
+ {"name", preset.name},
+ {"screenSize", preset.screenSize},
+ {"useQtVirtualKeyboard", preset.useQtVirtualKeyboard},
+ {"enableCMakeGeneration", preset.enableCMakeGeneration},
+ {"qtVersion", preset.qtVersion},
+ {"styleName", preset.styleName},
+ };
jsonArray.append(QJsonValue{obj});
}
@@ -164,6 +167,7 @@ std::vector