diff --git a/doc/config/macros.qdocconf b/doc/config/macros.qdocconf
index 3b2970724b5..d2e02d06784 100644
--- a/doc/config/macros.qdocconf
+++ b/doc/config/macros.qdocconf
@@ -48,3 +48,17 @@ macro.beginfloatright.HTML = "
"
macro.endfloat.HTML = "
"
macro.clearfloat.HTML = "
"
macro.emptyspan.HTML = ""
+
+# Embed YouTube content by video ID - Example: \youtube dQw4w9WgXcQ
+# Also requires a .jpg thumbnail for offline docs. In .qdocconf, add:
+#
+# HTML.extraimages += images/dQw4w9WgXcQ.jpg
+# qhp.ProjectName.extraFiles += images/dQw4w9WgXcQ.jpg
+#
+macro.youtube.HTML = "\n"
diff --git a/doc/qtcreator/src/qtquick/qtdesignstudio-best-practices.qdoc b/doc/qtcreator/src/qtquick/qtdesignstudio-best-practices.qdoc
index e9507690406..5b3573620c0 100644
--- a/doc/qtcreator/src/qtquick/qtdesignstudio-best-practices.qdoc
+++ b/doc/qtcreator/src/qtquick/qtdesignstudio-best-practices.qdoc
@@ -43,7 +43,7 @@
\if defined(qtdesignstudio)
For guidelines on how to achieve best results when importing assets, see
- \l {Exporting Artwork from Design Tools}.
+ \l {Exporting from Design Tools}.
\endif
\section1 Naming Conventions
diff --git a/doc/qtcreator/src/qtquick/qtquick-connection-editor-properties.qdoc b/doc/qtcreator/src/qtquick/qtquick-connection-editor-properties.qdoc
index 870091441b7..d1de85a6b2a 100644
--- a/doc/qtcreator/src/qtquick/qtquick-connection-editor-properties.qdoc
+++ b/doc/qtcreator/src/qtquick/qtquick-connection-editor-properties.qdoc
@@ -60,7 +60,9 @@
selected item. The item ID is displayed in the \uicontrol Item
column.
\li Double-click the value in the \uicontrol Property column to give a
- name to the property.
+ name to the property. Property names must begin with a lower case
+ letter and can only contain letters, numbers, and underscores.
+ JavaScript \e {reserved words} are not valid property names.
\li Double-click the value in the \uicontrol {Property Type} column to
specify the \l{Supported Property Types}{type of the property}.
\li Double-click the value in the \uicontrol {Property Value} column
diff --git a/doc/qtcreator/src/qtquick/qtquick-uis.qdoc b/doc/qtcreator/src/qtquick/qtquick-uis.qdoc
index 74bc891d718..2461f6468b3 100644
--- a/doc/qtcreator/src/qtquick/qtquick-uis.qdoc
+++ b/doc/qtcreator/src/qtquick/qtquick-uis.qdoc
@@ -42,19 +42,20 @@
for you.
\endif
- Qt Quick enables you to build UIs around the behavior of
- \e components and how they connect with one another. You
- create components using Qt Quick and QML types that are available in
- the Design mode. You can specify values for the \e properties of a
+ Qt Quick enables you to build UIs around the behavior of \e components and
+ how they connect with one another. You create components using Qt Quick and
+ QML types that are available in the \uicontrol Library view in the Design
+ mode. You can specify values for the \e properties of a
component to change its appearance and behavior. All QML types have a
set of predefined properties, some of which control things that are
visible to users, while others are used behind the scene.
While it is useful to learn the basics of Qt Quick, you can also rely on
\QMLD to write the code for you when you drag-and-drop the ready-made
- components to the \uicontrol {Form Editor} view and change them to your
- liking by modifying their properties in the \uicontrol Properties view in
- the Design mode. You can always check up details in the extensive Qt Quick
+ components from the \uicontrol Library view to the \uicontrol {Form Editor}
+ or \uicontrol Navigator view and change them to your liking by modifying
+ their properties in the \uicontrol Properties view.
+ You can always check up details in the extensive Qt Quick
documentation by pressing \key F1.
\list
@@ -62,9 +63,8 @@
\if defined(qtdesignstudio)
\li \l {Designing Application Flows}
- After you export and import your artwork, you can design the
- application flow in the form of a \e {schematic diagram} that
- shows all significant components of an application UI and their
+ 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.
@@ -72,16 +72,15 @@
\li \l {Creating Components}
- In addition to your imported artwork, you can use the Design
- mode to customize ready-made components or design any custom form
- and shape directly as QML types. You can import visual assets in
- various formats, such as PNG, JPG, and SVG for use in the
- components.
+ You can enhance imported designs by customizing ready-made
+ components or design custom forms and shapes directly as
+ QML types. You can import visual assets in various formats,
+ such as PNG, JPG, and SVG for use in the components.
\li \l {Managing Item Hierarchy}
You can manage the items in the current QML file and their
- relationships in the \uicontrol Navigator.
+ relationships in the \uicontrol Navigator view.
\li \l {Specifying Item Properties}
@@ -92,6 +91,13 @@
type. You can specify properties for your components in the
\uicontrol Properties view.
+ \li \l {Positioning Items}
+
+ The position of an item in a UI can be either absolute or relative
+ to other items. While manual positioning is efficient for a static
+ UI, consider the other available method, such as anchors, layouts,
+ positioners, and property bindings, for dynamic UIs.
+
\li \l {Using Custom Fonts}
You can load custom fonts to \QMLD and use them in your designs.
diff --git a/doc/qtcreatordev/src/qtcreator-documentation.qdoc b/doc/qtcreatordev/src/qtcreator-documentation.qdoc
index 3f55589866b..09d17bf0f32 100644
--- a/doc/qtcreatordev/src/qtcreator-documentation.qdoc
+++ b/doc/qtcreatordev/src/qtcreator-documentation.qdoc
@@ -418,6 +418,52 @@
optipng -o 7 -strip all doc/images/
\endcode
+ \section2 Linking to Youtube Videos
+
+ You can use the \c {\youtube} macro to link to a video on Youtube. The HTML
+ docs show a thumbnail of the video with a play button.
+
+ The support for the macro is defined in the
+ \c {qtcreator\doc\config\macros.qdocconf} file. To use the
+ macro, you need to save a thumbnail of the video in
+ \c {qtcreator\doc\qtcreator\images\videoicons} or
+ \c {qtcreator\doc\qtdesignstudio\images\videoicons}.
+
+ You can use the following URL to open the thumbnail image in a browser:
+ \c {https://img.youtube.com/vi//0.jpg}. The \e {} is the ID of
+ the video on Youtube. For example, if the URL to the video is
+ \c {https://www.youtube.com/watch?v=9ihYeC0YJ0M&feature=youtu.be},
+ the ID is \c 9ihYeC0YJ0M. Save the image file as \c {9ihYeC0YJ0M.jpg}.
+
+ You must add the filename of the thumbnail file to
+ \c {\qtcreator\doc\qtcreator\config\qtcreator-project.qdocconf} and
+ \c {\qtcreator\doc\qtdesignstudio\config\qtdesignstudio.qdocconf}
+ to the value of the \c {HTML.extraimages,qhp.qtcreator.extraFiles}
+ or \c {HTML.extraimages,qhp.qtdesignstudio.extraFiles} option.
+
+ If you'll only link to the video from the \QC Manual or the \QDS Manual,
+ you'll only need to add the thumbnail filename to the \c .qdocconf file
+ for that project.
+
+ For example, to enable linking to a video with the thumbnail filename
+ \c 9ihYeC0YJ0M.jpg in the \QDS Manual, the \c {qtdesignstudio.qdocconf}
+ file should contain the following entry:
+
+ \code
+ {HTML.extraimages,qhp.qtdesignstudio.extraFiles} += ../../config/images/commercial.png \
+ ../images/videoicons/9ihYeC0YJ0M.jpg \
+ ../images/videoicons/aV6kFxH3Xws.jpg \
+ ../images/videoicons/ZzbucmQPU44.jpg
+ \endcode
+
+ To add a link to the video in text, you would write:
+
+ \code
+ \youtube 9ihYeC0YJ0M
+ \endcode
+
+ \note Leave out the filename extension when referring to the thumbnail.
+
\section1 Building Documentation
You use QDoc to build the documentation. Build the documentation before
diff --git a/doc/qtdesignstudio/config/qtdesignstudio.qdocconf b/doc/qtdesignstudio/config/qtdesignstudio.qdocconf
index dec1878602a..56c602c2540 100644
--- a/doc/qtdesignstudio/config/qtdesignstudio.qdocconf
+++ b/doc/qtdesignstudio/config/qtdesignstudio.qdocconf
@@ -69,8 +69,12 @@ exampledirs = ../examples/ \
../../qtcreator/examples
examples.fileextensions += *.qml *.svg *.ts *.qm
-HTML.extraimages = ../../config/images/commercial.png
-qhp.QtCreator.extraFiles = ../../config/images/commercial.png
+{HTML.extraimages,qhp.qtdesignstudio.extraFiles} += ../../config/images/commercial.png \
+ ../images/videoicons/SsFWyUeAA_4.jpg \
+ ../images/videoicons/9ihYeC0YJ0M.jpg \
+ ../images/videoicons/aV6kFxH3Xws.jpg \
+ ../images/videoicons/ZzbucmQPU44.jpg
+
depends += qtwidgets \
qtcore \
diff --git a/doc/qtdesignstudio/examples/doc/images/webinardemo-blureffect.png b/doc/qtdesignstudio/examples/doc/images/webinardemo-blureffect.png
index 32a40a8de52..060f6da8246 100644
Binary files a/doc/qtdesignstudio/examples/doc/images/webinardemo-blureffect.png and b/doc/qtdesignstudio/examples/doc/images/webinardemo-blureffect.png differ
diff --git a/doc/qtdesignstudio/examples/doc/images/webinardemo-mainappui.png b/doc/qtdesignstudio/examples/doc/images/webinardemo-mainappui.png
index 29d39c82678..1c2f25fead9 100644
Binary files a/doc/qtdesignstudio/examples/doc/images/webinardemo-mainappui.png and b/doc/qtdesignstudio/examples/doc/images/webinardemo-mainappui.png differ
diff --git a/doc/qtdesignstudio/examples/doc/images/webinardemo-states.png b/doc/qtdesignstudio/examples/doc/images/webinardemo-states.png
index 83755e876a5..6d074c1a157 100644
Binary files a/doc/qtdesignstudio/examples/doc/images/webinardemo-states.png and b/doc/qtdesignstudio/examples/doc/images/webinardemo-states.png differ
diff --git a/doc/qtdesignstudio/examples/doc/images/webinardemo-timeline.png b/doc/qtdesignstudio/examples/doc/images/webinardemo-timeline.png
index c6c0976eeda..71f5eb49fb8 100644
Binary files a/doc/qtdesignstudio/examples/doc/images/webinardemo-timeline.png and b/doc/qtdesignstudio/examples/doc/images/webinardemo-timeline.png differ
diff --git a/doc/qtdesignstudio/examples/doc/webinardemo.qdoc b/doc/qtdesignstudio/examples/doc/webinardemo.qdoc
index 1e13961c917..5ff9fd35ddf 100644
--- a/doc/qtdesignstudio/examples/doc/webinardemo.qdoc
+++ b/doc/qtdesignstudio/examples/doc/webinardemo.qdoc
@@ -42,12 +42,12 @@
\section1 Exporting from Adobe Photoshop
We use Adobe Photoshop to design our application and \QB to export our
- artwork to \QDS as PNG images and custom QML types.
+ design to \QDS as PNG images and custom QML types.
Before we can begin, we must set up \QB as instructed in
\l{Exporting Designs from Adobe Photoshop}.
- We organize our artwork in Photoshop using artboards as instructed in
+ We organize our design in Photoshop using artboards as instructed in
\l{Organizing Assets}.
\QB automatically proposes identifiers for all groups and layers. The ids
@@ -116,10 +116,10 @@
To be able to use the type, we added the statement that imports the
Qt Quick Studio Effects module: \c {QtQuick.Studio.Effects 1.0}.
- We specify that the artwork to which we want to apply the effect is a
+ We specify that the component to which we want to apply the effect is a
child of the effect. We then specify the radius property for the effect,
in the \uicontrol {QML Properties} field. We can modify the property in
- \QDS.
+ the \uicontrol Radius field in the \uicontrol Properties view in \QDS.
\image webinardemo-blureffect.png "FastBlurItem QML item in Design mode"
@@ -142,18 +142,18 @@
We want to animate the contents of the \e largePopup artboard in \QDS, so
we export each group and layer as a child.
- \section2 Exporting Artwork
+ \section2 Exporting Our Design
When we have specified settings for all the artboards and the groups and
layers in them, we select \uicontrol Export to copy the assets and metadata
to the export path we specified.
- \section1 Importing Artwork
+ \section1 Importing Our Design
- After using \QB in Adobe Photoshop to export our artwork, we import it into
+ After using \QB in Adobe Photoshop to export our design, we import it into
a project that we create in \QDS, as instructed in \l{Importing Designs}.
- If we need to make changes in Photoshop later and export our artwork again,
+ If we need to make changes in Photoshop later and export our design again,
\QDS will try to merge our changes during the import, so that none of the
changes we mage in \QDS are lost.
@@ -185,7 +185,7 @@
\image webinardemo-states.png "Popup states in the States view"
- For more information about using states, see \l {Creating Animations}.
+ For more information about using states, see \l {Creating States}.
We then use the \uicontrol Timeline view to add animations that are run
when moving from one state to another.
diff --git a/doc/qtdesignstudio/images/studio-import-metadata.png b/doc/qtdesignstudio/images/studio-import-metadata.png
index 6b2f1716b5f..e7317402f82 100644
Binary files a/doc/qtdesignstudio/images/studio-import-metadata.png and b/doc/qtdesignstudio/images/studio-import-metadata.png differ
diff --git a/doc/qtdesignstudio/images/videoicons/9ihYeC0YJ0M.jpg b/doc/qtdesignstudio/images/videoicons/9ihYeC0YJ0M.jpg
new file mode 100644
index 00000000000..93ffdccbd7f
Binary files /dev/null and b/doc/qtdesignstudio/images/videoicons/9ihYeC0YJ0M.jpg differ
diff --git a/doc/qtdesignstudio/images/videoicons/SsFWyUeAA_4.jpg b/doc/qtdesignstudio/images/videoicons/SsFWyUeAA_4.jpg
new file mode 100644
index 00000000000..49d38474727
Binary files /dev/null and b/doc/qtdesignstudio/images/videoicons/SsFWyUeAA_4.jpg differ
diff --git a/doc/qtdesignstudio/images/videoicons/ZzbucmQPU44.jpg b/doc/qtdesignstudio/images/videoicons/ZzbucmQPU44.jpg
new file mode 100644
index 00000000000..dd25d4cea36
Binary files /dev/null and b/doc/qtdesignstudio/images/videoicons/ZzbucmQPU44.jpg differ
diff --git a/doc/qtdesignstudio/images/videoicons/aV6kFxH3Xws.jpg b/doc/qtdesignstudio/images/videoicons/aV6kFxH3Xws.jpg
new file mode 100644
index 00000000000..94b7e30392a
Binary files /dev/null and b/doc/qtdesignstudio/images/videoicons/aV6kFxH3Xws.jpg differ
diff --git a/doc/qtdesignstudio/src/qtbridge/qtbridge-ai.qdoc b/doc/qtdesignstudio/src/qtbridge/qtbridge-ai.qdoc
index 4d870c84970..e7dddea24fe 100644
--- a/doc/qtdesignstudio/src/qtbridge/qtbridge-ai.qdoc
+++ b/doc/qtdesignstudio/src/qtbridge/qtbridge-ai.qdoc
@@ -31,7 +31,7 @@
\title Exporting Designs from Adobe Illustrator
Even though \QDS does not provide a specific export bridge for Adobe
- Illustrator, you can create artwork in it and export it to \QDS in
+ Illustrator, you can desing UIs in it and export your designs to \QDS in
the following ways:
\list
diff --git a/doc/qtdesignstudio/src/qtbridge/qtbridge-overview.qdoc b/doc/qtdesignstudio/src/qtbridge/qtbridge-overview.qdoc
index 7d3509a0060..27fd037067d 100644
--- a/doc/qtdesignstudio/src/qtbridge/qtbridge-overview.qdoc
+++ b/doc/qtdesignstudio/src/qtbridge/qtbridge-overview.qdoc
@@ -28,7 +28,7 @@
\page qtbridge-overview.html
\nextpage qtbridge-ai.html
- \title Exporting Artwork from Design Tools
+ \title Exporting from Design Tools
You need to use \QB to first export 2D assets from design tools and then to
\l{Importing Designs}{import} them into \QDS.
@@ -56,12 +56,12 @@
\li \l{Exporting Designs from Adobe Photoshop}
You can use the \QBPS export tool in Adobe Photoshop to convert
- artwork into \e {.metadata} format that you can import into
+ designs into \e {.metadata} format that you can import into
projects in \QDS.
\li \l{Exporting Designs from Sketch}
- You can use the \QBSK export tool in Sketch to convert artwork into
+ You can use the \QBSK export tool in Sketch to convert designs into
metadata that you can import into projects in \QDS.
\li \l{Exporting 3D Assets}
diff --git a/doc/qtdesignstudio/src/qtbridge/qtbridge-ps-overview.qdoc b/doc/qtdesignstudio/src/qtbridge/qtbridge-ps-overview.qdoc
index 26eda08a083..aedd017a93b 100644
--- a/doc/qtdesignstudio/src/qtbridge/qtbridge-ps-overview.qdoc
+++ b/doc/qtdesignstudio/src/qtbridge/qtbridge-ps-overview.qdoc
@@ -44,7 +44,7 @@
\li \l{Setting Up Qt Bridge for Adobe Photoshop}
You must install and set up the \QBPS export tool before you can use
- it to export artwork.
+ it to export designs.
\li \l{Using Qt Bridge for Adobe Photoshop}
@@ -52,4 +52,6 @@
Photoshop, you should follow the guidelines for working with
Photoshop and organizing your assets.
\endlist
+
+ \include qtbridge-tutorial-links.qdocinc qtpsbridge videos
*/
diff --git a/doc/qtdesignstudio/src/qtbridge/qtbridge-ps-using.qdoc b/doc/qtdesignstudio/src/qtbridge/qtbridge-ps-using.qdoc
index d9677906fbb..cab3e9b3223 100644
--- a/doc/qtdesignstudio/src/qtbridge/qtbridge-ps-using.qdoc
+++ b/doc/qtdesignstudio/src/qtbridge/qtbridge-ps-using.qdoc
@@ -60,7 +60,7 @@
will be imported as a single QML file that can contain other assets. A child
will be imported as a single image file that you can use within QML files.
- If you plan to use pieces of your artwork as separate images in the UI,
+ If you plan to use pieces of your design as separate images in the UI,
group them on an artboard as separate layers. You can then export the group
as a component and each layer within it as a child. The children are
imported to \QDS as separate PNG files that you can use as image sources.
@@ -249,15 +249,6 @@
In the \QBPS \uicontrol Settings dialog, select \uicontrol {Override JSX Script} to set the
override JSX script.
- For more information, watch a video tutorial and webinar about using \QBPS:
-
- \list
- \li \l{https://resources.qt.io/development-topic-ui-design/qtdesignstudio-clustertutorial-partone}
- {Building an Instrument Cluster for Your Car HMI, Part 1}
- \li \l{https://www.youtube.com/watch?v=ZzbucmQPU44}
- {From Photoshop to Prototype with Qt Design Studio}
- \endlist
-
\section1 Importing Metadata & Assets
\QBPS can import metadata generated from other tools and generate a Photoshop document. A
diff --git a/doc/qtdesignstudio/src/qtbridge/qtbridge-sketch-overview.qdoc b/doc/qtdesignstudio/src/qtbridge/qtbridge-sketch-overview.qdoc
index a85a2473101..4f626c1af0f 100644
--- a/doc/qtdesignstudio/src/qtbridge/qtbridge-sketch-overview.qdoc
+++ b/doc/qtdesignstudio/src/qtbridge/qtbridge-sketch-overview.qdoc
@@ -44,7 +44,7 @@
\li \l{Setting Up Qt Bridge for Sketch}
You must install Sketch and the \QBSK export tool before you can use
- the tool to export artwork.
+ the tool to export designs.
\li \l{Using Qt Bridge for Sketch}
@@ -52,4 +52,6 @@
Sketch, you should follow the guidelines for working with Sketch and
organizing your assets.
\endlist
+
+ \include qtbridge-tutorial-links.qdocinc qtsketchbridge tutorials
*/
diff --git a/doc/qtdesignstudio/src/qtbridge/qtbridge-tutorial-links.qdocinc b/doc/qtdesignstudio/src/qtbridge/qtbridge-tutorial-links.qdocinc
new file mode 100644
index 00000000000..4508b9acc4a
--- /dev/null
+++ b/doc/qtdesignstudio/src/qtbridge/qtbridge-tutorial-links.qdocinc
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Bridge documentation.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+**
+****************************************************************************/
+
+//! [qtpsbridge videos]
+
+ \section1 \QBPS Videos
+
+ For more information, watch a video tutorial and webinar about using \QBPS
+ that are also accessible from the \uicontrol Tutorials tab of the Welcome
+ mode:
+
+ \list
+ \li Building an Instrument Cluster for Your Car HMI, Part 1
+
+ \youtube aV6kFxH3Xws
+
+ You can access the Cluster tutorial source files in the
+ \uicontrol Examples tab.
+
+ \li From Photoshop to Prototype with Qt Design Studio
+
+ \youtube ZzbucmQPU44
+ \endlist
+
+//! [qtpsbridge videos]
+
+
+//! [qtsketchbridge tutorials]
+
+ \section1 \QBSK Tutorials
+
+ For more information, read the tutorials about using \QBSK that are also
+ accessible from the \uicontrol Tutorials tab of the Welcome mode:
+
+ \list
+ \li \l{https://www.qt.io/blog/qt-design-studio-sketch-bridge-tutorial-part-1}
+ {Sketch Bridge Tutorial Part 1}
+ \li \l{https://www.qt.io/blog/qt-design-studio-sketch-bridge-tutorial-part-2}
+ {Sketch Bridge Tutorial Part 2}
+ \endlist
+
+//! [qtsketchbridge tutorials]
diff --git a/doc/qtdesignstudio/src/qtdesignstudio-app-flows.qdoc b/doc/qtdesignstudio/src/qtdesignstudio-app-flows.qdoc
index 19898c24902..9dc01844d2c 100644
--- a/doc/qtdesignstudio/src/qtdesignstudio-app-flows.qdoc
+++ b/doc/qtdesignstudio/src/qtdesignstudio-app-flows.qdoc
@@ -30,10 +30,8 @@
\title Designing Application Flows
- After you \l {Exporting Artwork from Design Tools}{export} your artwork from
- your favorite design tool and \l{Importing Designs}{import} it to \QDS, you
- can design the application flow in the form of a \e {schematic diagram} that
- shows all significant components of an application UI and their
+ You can design the application flow 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. The QML code is created in the background and can be used
diff --git a/doc/qtdesignstudio/src/qtdesignstudio-examples.qdoc b/doc/qtdesignstudio/src/qtdesignstudio-examples.qdoc
index d1fa52b418b..6494ac4d1fd 100644
--- a/doc/qtdesignstudio/src/qtdesignstudio-examples.qdoc
+++ b/doc/qtdesignstudio/src/qtdesignstudio-examples.qdoc
@@ -38,8 +38,8 @@
The \uicontrol Tutorials tab contains links to video tutorials that provide
more information about \QDS.
- You can access the Cluster tutorial source files in the \uicontrol Examples
- tab.
+ \include qtbridge-tutorial-links.qdocinc qtpsbridge videos
+ \include qtbridge-tutorial-links.qdocinc qtsketchbridge tutorials
\section1 Examples
diff --git a/doc/qtdesignstudio/src/qtdesignstudio-getting-started.qdoc b/doc/qtdesignstudio/src/qtdesignstudio-getting-started.qdoc
index e2168288280..dd11d02c7d9 100644
--- a/doc/qtdesignstudio/src/qtdesignstudio-getting-started.qdoc
+++ b/doc/qtdesignstudio/src/qtdesignstudio-getting-started.qdoc
@@ -30,12 +30,12 @@
\title Getting Started
- Typically, you as a designer would create artwork in imaging and design
- tools, such as Adobe Photoshop, Sketch, Blender, or Maya, and then send it
- to a developer for adding it to the application. With the \QB export tool,
+ Typically, you as a designer would design a UI using imaging and design
+ tools, such as Adobe Photoshop, Sketch, Blender, or Maya, and then send your
+ design to a developer for implementation. With the \QB export tool,
you can convert 2D assets into \l {Qt Quick} files. You can use the export
functionality of 3D graphics tools to save your 3D assets in a format
- supported by \QDS. You can import the 2D and 3D assets into \QDS for
+ supported by \QDS. You can import the 2D and 3D assets into \QDS for
editing, before you submit the UI to the developer for adding the
functionality to the application.
@@ -46,8 +46,8 @@
The workflow consists of the following steps:
\list 1
- \li Export your artwork from a design tool.
- \li Create a project in \QDS and import your artwork to it.
+ \li Export your design from a design tool.
+ \li Create a project in \QDS and import your design to it.
\li Create reusable components in the Design mode.
\li Animate your design with the timeline and easing curve editor.
\li Create interactions using states and connections.
@@ -59,16 +59,16 @@
way around \QDS:
\list
- \li \l {Exporting Artwork from Design Tools}
+ \li \l {Exporting from Design Tools}
- Describes how to export 2D and 3D assets into files that
- you can import to projects in \QDS.
+ Describes how to export designs containing 2D and 3D assets into
+ files that you can import to projects in \QDS.
\li \l {User Interface}
Describes the parts and basic features of \QDS.
\li \l{Editing QML Files in Design Mode}
- Describes the parts and basic features of the Design mode.
+ Describes the views and basic features of the Design mode.
This is where you'll do most of your work.
\li \l {Tutorials}
diff --git a/doc/qtdesignstudio/src/qtdesignstudio-importing-2d.qdoc b/doc/qtdesignstudio/src/qtdesignstudio-importing-2d.qdoc
index 8314d6cd660..878d5cc9f81 100644
--- a/doc/qtdesignstudio/src/qtdesignstudio-importing-2d.qdoc
+++ b/doc/qtdesignstudio/src/qtdesignstudio-importing-2d.qdoc
@@ -30,13 +30,13 @@
\title Importing 2D Assets
- \image studio-imported-assets.png "Artwork imported into Qt Design Studio"
+ \image studio-imported-assets.png "UI imported into Qt Design Studio"
\QB enables you to export assets and then import them to a \QDS project
as image and QML files for editing in the \uicontrol {Form Editor}. If you
make changes to your design in the design tool, you can merge the changes
into existing QML files without overwriting the changes you have made in
- \QDS. For more information, see \l {Exporting Artwork from Design Tools}.
+ \QDS. For more information, see \l {Exporting from Design Tools}.
\note Attempting to import assets exported on another system might fail.
@@ -48,8 +48,9 @@
\list 1
\li Select \uicontrol File > \uicontrol {New File or Project} >
- \uicontrol General > \uicontrol Choose, and follow the
- instructions of the wizard to create an empty project.
+ \uicontrol General > \uicontrol {Qt Quick Application - Empty} >
+ \uicontrol Choose, and follow the instructions of the wizard to
+ create an empty project.
\li In \uicontrol Projects, double-click \e Screen01.ui.qml to move to
the Design mode.
\li Select \uicontrol Library > \uicontrol Assets >
@@ -70,6 +71,9 @@
QML files to.
\li In the \uicontrol Assets field, you can change the folder to copy
the image files to.
+ \li Select the \uicontrol {Create sub directory for each metadata}
+ check box to copy the directory structure from the metadata file
+ to \QDS.
\li Deselect the \uicontrol {Import assets} check box if you only want
to create QML files.
\li Deselect the \uicontrol {Generate QML} check box if you only
@@ -100,19 +104,6 @@
\uicontrol {Asset Import} dialog while importing, fix the issues in
design tool and export the assets again.
- \section1 \QB Videos
-
- For more information, see the \QB tutorials that are also accessible from
- the \uicontrol Tutorials tab of the Welcome mode:
-
- \list
- \li \l{https://resources.qt.io/development-topic-ui-design/qtdesignstudio-clustertutorial-partone}
- {Building an Instrument Cluster for Your Car HMI, Part 1} (\QBPS)
- \li \l{https://www.youtube.com/watch?v=ZzbucmQPU44}
- {From Photoshop to Prototype with Qt Design Studio}
- \li \l{https://www.qt.io/blog/qt-design-studio-sketch-bridge-tutorial-part-1}
- {Sketch Bridge Tutorial Part 1}
- \li \l{https://www.qt.io/blog/qt-design-studio-sketch-bridge-tutorial-part-2}
- {Sketch Bridge Tutorial Part 2}
- \endlist
+ \include qtbridge-tutorial-links.qdocinc qtpsbridge videos
+ \include qtbridge-tutorial-links.qdocinc qtsketchbridge tutorials
*/
diff --git a/doc/qtdesignstudio/src/qtdesignstudio-projects.qdoc b/doc/qtdesignstudio/src/qtdesignstudio-projects.qdoc
index 7c8ae924725..0eca243f587 100644
--- a/doc/qtdesignstudio/src/qtdesignstudio-projects.qdoc
+++ b/doc/qtdesignstudio/src/qtdesignstudio-projects.qdoc
@@ -81,6 +81,11 @@
application.
\endlist
+ For an example of creating a \uicontrol {Qt Quick 3D Application} project,
+ watch the following video:
+
+ \youtube 9ihYeC0YJ0M
+
\section1 Using Project Wizards
\list 1
diff --git a/doc/qtdesignstudio/src/qtdesignstudio-toc.qdoc b/doc/qtdesignstudio/src/qtdesignstudio-toc.qdoc
index 52ad03e04d1..c883a14dc1e 100644
--- a/doc/qtdesignstudio/src/qtdesignstudio-toc.qdoc
+++ b/doc/qtdesignstudio/src/qtdesignstudio-toc.qdoc
@@ -31,7 +31,7 @@
\list
\li \l{Getting Started}
\list
- \li \l{Exporting Artwork from Design Tools}
+ \li \l{Exporting from Design Tools}
\list
\li \l{Exporting Designs from Adobe Illustrator}
\li \l{Exporting Designs from Adobe Photoshop}
diff --git a/doc/qtdesignstudio/src/qtdesignstudio.qdoc b/doc/qtdesignstudio/src/qtdesignstudio.qdoc
index 1fa4e2be982..06d140b5b1e 100644
--- a/doc/qtdesignstudio/src/qtdesignstudio.qdoc
+++ b/doc/qtdesignstudio/src/qtdesignstudio.qdoc
@@ -45,7 +45,7 @@
\row
\li \b {\l{Getting Started}}
\list
- \li \l{Exporting Artwork from Design Tools}
+ \li \l{Exporting from Design Tools}
\li \l{User Interface}
\li \l{Editing QML Files in Design Mode}
\li \l{Tutorials}
diff --git a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-editor.qdoc b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-editor.qdoc
index d9b4e33a50c..2bf1ea5da69 100644
--- a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-editor.qdoc
+++ b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-editor.qdoc
@@ -66,6 +66,11 @@
\image studio-3d-editor.png "3D Editor"
+ The following video illustrates navigating in \uicontrol {3D Editor} and
+ using the toolbar:
+
+ \youtube SsFWyUeAA_4
+
\section1 Controlling the 3D Editor Camera
To switch to perspective camera mode, select
diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py
index d0d1244ff1b..b682f4ae002 100644
--- a/share/qtcreator/debugger/dumper.py
+++ b/share/qtcreator/debugger/dumper.py
@@ -555,7 +555,8 @@ class DumperBase():
return 0, size
return size, limit
- def vectorDataHelper(self, vector_data_ptr):
+ def vectorData(self, value):
+ vector_data_ptr = self.extractPointer(value)
# vector_data_ptr is what is e.g. stored in a QVector's d_ptr.
if self.qtVersion() >= 0x050000:
if self.ptrSize() == 4:
@@ -570,6 +571,16 @@ class DumperBase():
self.check(0 <= size and size <= alloc and alloc <= 1000 * 1000 * 1000)
return data, size, alloc
+ def qArrayData(self, value):
+ if self.qtVersion() >= 0x60000:
+ dd, data, size = self.split('ppi', value)
+ if dd:
+ alloc, i, i = self.split('Pii', dd)
+ else: # fromRawData
+ alloc = size
+ return data, size, alloc
+ return self.qArrayDataHelper(self.extractPointer(value))
+
def qArrayDataHelper(self, array_data_ptr):
# array_data_ptr is what is e.g. stored in a QByteArray's d_ptr.
if self.qtVersion() >= 0x050000:
@@ -614,15 +625,14 @@ class DumperBase():
# of inferior calls
if addr == 0:
return 0, ''
- data, size, alloc = self.qArrayDataHelper(addr)
+ data, size, alloc = self.qArrayData(value)
if alloc != 0:
self.check(0 <= size and size <= alloc and alloc <= 100 * 1000 * 1000)
elided, shown = self.computeLimit(size, limit)
return elided, self.readMemory(data, 2 * shown)
def encodeByteArrayHelper(self, value, limit):
- addr = self.extractPointer(value)
- data, size, alloc = self.qArrayDataHelper(addr)
+ data, size, alloc = self.qArrayData(value)
if alloc != 0:
self.check(0 <= size and size <= alloc and alloc <= 100 * 1000 * 1000)
elided, shown = self.computeLimit(size, limit)
@@ -675,9 +685,6 @@ class DumperBase():
elided, data = self.encodeByteArrayHelper(value, limit)
return data
- def qArrayData(self, value):
- return self.qArrayDataHelper(self.extractPointer(value))
-
def putByteArrayValue(self, value):
elided, data = self.encodeByteArrayHelper(value, self.displayStringLimit)
self.putValue(data, 'latin1', elided=elided)
@@ -701,14 +708,6 @@ class DumperBase():
return self.encodedUtf16ToUtf8(self.encodeString(value, limit))
def stringData(self, value): # -> (data, size, alloc)
- if self.qtVersion() >= 0x60000:
- dd, data, size = value.split('ppi')
- if dd:
- alloc, i, i = self.split('Pii', dd)
- else: # fromRawData
- alloc = size
- return data, size, alloc
- else:
return self.qArrayData(value)
def extractTemplateArgument(self, typename, position):
@@ -1442,22 +1441,27 @@ class DumperBase():
intSize = 4
ptrSize = self.ptrSize()
- if self.qtVersion() < 0x050000:
- # Size of QObjectData: 5 pointer + 2 int
- # - vtable
+ if self.qtVersion() >= 0x060000:
+ # Size of QObjectData: 7 pointer + 2 int
+ # - vtable
# - QObject *q_ptr;
# - QObject *parent;
# - QObjectList children;
- # - uint isWidget : 1; etc..
+ # - uint isWidget : 1; etc...
# - int postedEvents;
- # - QMetaObject *metaObject;
+ # - QDynamicMetaObjectData *metaObject;
+ extra = self.extractPointer(dd + 7 * ptrSize + 2 * intSize)
+ if extra == 0:
+ return False
- # Offset of objectName in QObjectPrivate: 5 pointer + 2 int
- # - [QObjectData base]
+ # Offset of objectName in ExtraData: 12 pointer
+ # - QList propertyNames;
+ # - QList propertyValues;
+ # - QVector runningTimers;
+ # - QList > eventFilters;
# - QString objectName
- objectName = self.extractPointer(dd + 5 * ptrSize + 2 * intSize)
-
- else:
+ objectNameAddress = extra + 12 * ptrSize
+ elif self.qtVersion() >= 0x050000:
# Size of QObjectData: 5 pointer + 2 int
# - vtable
# - QObject *q_ptr;
@@ -1477,9 +1481,24 @@ class DumperBase():
# - QVector runningTimers;
# - QList > eventFilters;
# - QString objectName
- objectName = self.extractPointer(extra + 5 * ptrSize)
+ objectNameAddress = extra + 5 * ptrSize
+ else:
+ # Size of QObjectData: 5 pointer + 2 int
+ # - vtable
+ # - QObject *q_ptr;
+ # - QObject *parent;
+ # - QObjectList children;
+ # - uint isWidget : 1; etc..
+ # - int postedEvents;
+ # - QMetaObject *metaObject;
- data, size, alloc = self.qArrayDataHelper(objectName)
+ # Offset of objectName in QObjectPrivate: 5 pointer + 2 int
+ # - [QObjectData base]
+ # - QString objectName
+ objectNameAddress = dd + 5 * ptrSize + 2 * intSize
+
+
+ data, size, alloc = self.qArrayData(objectNameAddress)
# Object names are short, and GDB can crash on to big chunks.
# Since this here is a convenience feature only, limit it.
@@ -1734,9 +1753,8 @@ class DumperBase():
yield self.createValue(data + i * stepSize, innerType)
#yield self.createValue(data + i * stepSize, 'void*')
- def vectorChildrenGenerator(self, addr, innerType):
- base = self.extractPointer(addr)
- data, size, alloc = self.vectorDataHelper(base)
+ def vectorChildrenGenerator(self, value, innerType):
+ data, size, _ = self.vectorData(value)
for i in range(size):
yield self.createValue(data + i * innerType.size(), innerType)
@@ -1766,29 +1784,50 @@ class DumperBase():
def metaString(self, metaObjectPtr, index, revision):
ptrSize = self.ptrSize()
stringdata = self.extractPointer(toInteger(metaObjectPtr) + ptrSize)
- if revision >= 7: # Qt 5.
- byteArrayDataSize = 24 if ptrSize == 8 else 16
- literal = stringdata + toInteger(index) * byteArrayDataSize
- ldata, lsize, lalloc = self.qArrayDataHelper(literal)
+
+ def unpackString(base, size):
try:
- s = struct.unpack_from('%ds' % lsize, self.readRawMemory(ldata, lsize))[0]
+ s = struct.unpack_from('%ds' % size, self.readRawMemory(base, size))[0]
return s if sys.version_info[0] == 2 else s.decode('utf8')
except:
return ''
- else: # Qt 4.
- ldata = stringdata + index
- return self.extractCString(ldata).decode('utf8')
+
+ if revision >= 9: # Qt 6.
+ pos, size = self.split('II', stringdata + 8 * index)
+ return unpackString(stringdata + pos, size)
+
+ if revision >= 7: # Qt 5.
+ byteArrayDataSize = 24 if ptrSize == 8 else 16
+ literal = stringdata + toInteger(index) * byteArrayDataSize
+ base, size, _ = self.qArrayDataHelper(literal)
+ return unpackString(base, size)
+
+ ldata = stringdata + index
+ return self.extractCString(ldata).decode('utf8')
def putSortGroup(self, sortorder):
if not self.isCli:
self.putField('sortgroup', sortorder)
def putQMetaStuff(self, value, origType):
- (metaObjectPtr, handle) = value.split('pI')
+ if self.qtVersion() >= 0x060000:
+ metaObjectPtr, handle = value.split('pp')
+ else:
+ metaObjectPtr, handle = value.split('pI')
if metaObjectPtr != 0:
- dataPtr = self.extractPointer(metaObjectPtr + 2 * self.ptrSize())
- index = self.extractInt(dataPtr + 4 * handle)
- revision = 7 if self.qtVersion() >= 0x050000 else 6
+ if self.qtVersion() >= 0x060000:
+ revision = 9
+ name, alias, flags, keyCount, data = self.split('IIIII', handle)
+ index = name
+ elif self.qtVersion() >= 0x050000:
+ revision = 7
+ dataPtr = self.extractPointer(metaObjectPtr + 2 * self.ptrSize())
+ index = self.extractInt(dataPtr + 4 * handle)
+ else:
+ revision = 6
+ dataPtr = self.extractPointer(metaObjectPtr + 2 * self.ptrSize())
+ index = self.extractInt(dataPtr + 4 * handle)
+ #self.putValue("index: %s rev: %s" % (index, revision))
name = self.metaString(metaObjectPtr, index, revision)
self.putValue(name)
self.putExpandable()
@@ -2142,8 +2181,7 @@ class DumperBase():
with Children(self):
innerType = connections.type[0]
# Should check: innerType == ns::QObjectPrivate::ConnectionList
- base = self.extractPointer(connections)
- data, size, alloc = self.vectorDataHelper(base)
+ data, size, _ = self.vectorData(connections)
connectionType = self.createType('@QObjectPrivate::Connection')
for i in range(size):
first = self.extractPointer(data + i * 2 * ptrSize)
diff --git a/share/qtcreator/debugger/gdbbridge.py b/share/qtcreator/debugger/gdbbridge.py
index f5ee86c3497..eefe6caa764 100644
--- a/share/qtcreator/debugger/gdbbridge.py
+++ b/share/qtcreator/debugger/gdbbridge.py
@@ -1047,9 +1047,9 @@ class Dumper(DumperBase):
def handleNewObjectFile(self, objfile):
name = objfile.filename
if self.isWindowsTarget():
- qtCoreMatch = re.match(r'.*Qt5?Core[^/.]*d?\.dll', name)
+ qtCoreMatch = re.match(r'.*Qt[56]?Core[^/.]*d?\.dll', name)
else:
- qtCoreMatch = re.match(r'.*/libQt5?Core[^/.]*\.so', name)
+ qtCoreMatch = re.match(r'.*/libQt[56]?Core[^/.]*\.so', name)
if qtCoreMatch is not None:
self.addDebugLibs(objfile)
diff --git a/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py
index e6e501a309e..f749fa83281 100644
--- a/share/qtcreator/debugger/qttypes.py
+++ b/share/qtcreator/debugger/qttypes.py
@@ -1620,13 +1620,13 @@ def qdump__QStack(d, value):
def qdump__QPolygonF(d, value):
- data, size, alloc = d.vectorDataHelper(d.extractPointer(value))
+ data, size, _ = d.vectorData(value)
d.putItemCount(size)
d.putPlotData(data, size, d.createType('QPointF'))
def qdump__QPolygon(d, value):
- data, size, alloc = d.vectorDataHelper(d.extractPointer(value))
+ data, size, _ = d.vectorData(value)
d.putItemCount(size)
d.putPlotData(data, size, d.createType('QPoint'))
@@ -1640,7 +1640,7 @@ def qdump__QGraphicsPolygonItem(d, value):
offset = 328 if d.isMsvcTarget() else 320
else:
offset = 308
- data, size, alloc = d.vectorDataHelper(d.extractPointer(dptr + offset))
+ data, size, alloc = d.vectorData(dptr + offset)
d.putItemCount(size)
d.putPlotData(data, size, d.createType('QPointF'))
@@ -2101,7 +2101,7 @@ def qdump__QVariant(d, value):
def qedit__QVector(d, value, data):
values = data.split(',')
d.call('void', value, 'resize', str(len(values)))
- base, vsize, valloc = d.vectorDataHelper(d.extractPointer(value))
+ base, vsize, valloc = d.vectorData(value)
d.setValues(base, value.type[0].name, values)
@@ -2119,8 +2119,7 @@ def qdump__QVector(d, value):
if value.type.name == d.qtNamespace() + "QVector":
d.putBetterType(value.type.name + '<' + value.type.ltarget[0].name + '>')
else:
- dd = d.extractPointer(value)
- data, size, alloc = d.vectorDataHelper(dd)
+ data, size, alloc = d.vectorData(value)
d.check(0 <= size and size <= alloc and alloc <= 1000 * 1000 * 1000)
d.putItemCount(size)
d.putPlotData(data, size, value.type[0])
@@ -2128,8 +2127,7 @@ def qdump__QVector(d, value):
if False:
def qdump__QObjectConnectionList(d, value):
- dd = d.extractPointer(value)
- data, size, alloc = d.vectorDataHelper(dd)
+ data, size, alloc = d.vectorData(value)
d.check(0 <= size and size <= alloc and alloc <= 1000 * 1000 * 1000)
d.putItemCount(size)
d.putPlotData(data, size, d.createType('@QObjectPrivate::ConnectionList'))
@@ -3168,14 +3166,14 @@ def qdump__qfloat16(d, value):
def qdumpHelper_QCbor_string(d, container_ptr, element_index, is_bytes):
- # d.split('i@{QByteArray::size_type}pp', container_ptr) doesn't work with CDB, so be explicit:
- offset = 2 * d.ptrSize() if d.qtVersion() >= 0x060000 else 8
- data_d_ptr, elements_d_ptr = d.split('pp', container_ptr + offset)
- elements_data_ptr, elements_size, _ = d.vectorDataHelper(elements_d_ptr)
+ # d.split('i@{QByteArray::size_type}pp', container_ptr) doesn't work with CDB,
+ # so be explicit:
+ pos = container_ptr + (2 * d.ptrSize() if d.qtVersion() >= 0x060000 else 8)
+ elements_data_ptr, elements_size, _ = d.vectorData(pos + d.ptrSize())
element_at_n_addr = elements_data_ptr + element_index * 16 # sizeof(QtCbor::Element) == 15
element_value, _, element_flags = d.split('qII', element_at_n_addr)
enc = 'latin1' if is_bytes or (element_flags & 8) else 'utf16'
- bytedata, _, _ = d.qArrayDataHelper(data_d_ptr)
+ bytedata, _, _ = d.qArrayData(pos)
bytedata += element_value
if d.qtVersion() >= 0x060000:
bytedata_len = d.extractInt64(bytedata)
@@ -3204,13 +3202,13 @@ def qdumpHelper_QCbor_array(d, container_ptr, is_cbor):
if not container_ptr:
d.putItemCount(0)
return
- # d.split('i@{QByteArray::size_type}pp', container_ptr) doesn't work with CDB, so be explicit:
- offset = 2 * d.ptrSize() if d.qtVersion() >= 0x060000 else 8
- data_d_ptr, elements_d_ptr = d.split('pp', container_ptr + offset)
- elements_data_ptr, elements_size, _ = d.vectorDataHelper(elements_d_ptr)
+ # d.split('i@{QByteArray::size_type}pp', container_ptr) doesn't work with CDB,
+ # so be explicit:
+ pos = container_ptr + (2 * d.ptrSize() if d.qtVersion() >= 0x060000 else 8)
+ elements_data_ptr, elements_size, _ = d.vectorData(pos + d.ptrSize())
d.putItemCount(elements_size)
if d.isExpanded():
- bytedata, _, _ = d.qArrayDataHelper(data_d_ptr)
+ bytedata, _, _ = d.qArrayData(pos)
with Children(d, maxNumChild=1000):
for i in range(elements_size):
d.putSubItem(i, qdumpHelper_QCborArray_valueAt(d, container_ptr, elements_data_ptr, i, bytedata, is_cbor))
@@ -3225,14 +3223,14 @@ def qdumpHelper_QCbor_map(d, container_ptr, is_cbor):
if not container_ptr:
d.putItemCount(0)
return
- # d.split('i@{QByteArray::size_type}pp', container_ptr) doesn't work with CDB, so be explicit:
- offset = 2 * d.ptrSize() if d.qtVersion() >= 0x060000 else 8
- data_d_ptr, elements_d_ptr = d.split('pp', container_ptr + offset)
- elements_data_ptr, elements_size, _ = d.vectorDataHelper(elements_d_ptr)
+ # d.split('i@{QByteArray::size_type}pp', container_ptr) doesn't work with CDB,
+ # so be explicit:
+ pos = container_ptr + (2 * d.ptrSize() if d.qtVersion() >= 0x060000 else 8)
+ elements_data_ptr, elements_size, _ = d.vectorData(pos + d.ptrSize())
elements_size = int(elements_size / 2)
d.putItemCount(elements_size)
if d.isExpanded():
- bytedata, _, _ = d.qArrayDataHelper(data_d_ptr)
+ bytedata, _, _ = d.qArrayDataHelper(pos)
with Children(d, maxNumChild=1000):
for i in range(elements_size):
key = qdumpHelper_QCborArray_valueAt(d, container_ptr, elements_data_ptr, 2 * i, bytedata, is_cbor)
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml
index 002ed7bc04e..be38251e07b 100644
--- a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml
@@ -57,6 +57,10 @@ Item {
property var selectionBoxes: []
property rect viewPortRect: Qt.rect(0, 0, 1000, 1000)
+ property bool shuttingDown: false
+
+ property real fps: 0
+
signal selectionChanged(var selectedNodes)
signal commitObjectProperty(var object, var propName)
signal changeObjectProperty(var object, var propName)
@@ -71,6 +75,11 @@ Item {
onActiveSceneChanged: updateActiveScene()
+ function aboutToShutDown()
+ {
+ shuttingDown = true;
+ }
+
function createEditView()
{
var component = Qt.createComponent("SceneView3D.qml");
@@ -125,8 +134,12 @@ Item {
} else {
// When active scene is deleted, this function gets called by object deletion
// handlers without going through setActiveScene, so make sure sceneId is cleared.
- sceneId = "";
- storeCurrentToolStates();
+ // This is skipped during application shutdown, as calling QQuickText::setText()
+ // during application shutdown can crash the application.
+ if (!shuttingDown) {
+ sceneId = "";
+ storeCurrentToolStates();
+ }
}
notifyActiveSceneChange();
@@ -704,6 +717,10 @@ Item {
Text {
id: gizmoLabelText
text: {
+ // This is skipped during application shutdown, as calling QQuickText::setText()
+ // during application shutdown can crash the application.
+ if (shuttingDown)
+ return text;
var l = Qt.locale();
var targetProperty;
if (viewRoot.selectedNode) {
@@ -738,6 +755,10 @@ Item {
Text {
id: rotateGizmoLabelText
text: {
+ // This is skipped during application shutdown, as calling QQuickText::setText()
+ // during application shutdown can crash the application.
+ if (shuttingDown)
+ return text;
var l = Qt.locale();
if (rotateGizmo.targetNode) {
var degrees = rotateGizmo.currentAngle * (180 / Math.PI);
@@ -796,5 +817,16 @@ Item {
font.pixelSize: 14
color: "white"
}
+
+ Text {
+ id: fpsLabel
+ text: viewRoot.fps
+ anchors.bottom: parent.bottom
+ anchors.left: parent.left
+ anchors.margins: 4
+ font.pixelSize: 12
+ color: "white"
+ visible: viewRoot.fps > 0
+ }
}
}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/ModelNode3DImageView.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/ModelNode3DImageView.qml
index ac5fff1e3e5..324a020d6fa 100644
--- a/share/qtcreator/qml/qmlpuppet/mockfiles/ModelNode3DImageView.qml
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/ModelNode3DImageView.qml
@@ -50,11 +50,8 @@ Item {
view.destroy();
}
- function createViewForObject(obj, w, h)
+ function createViewForObject(obj)
{
- width = w;
- height = h;
-
if (obj instanceof Material)
createViewForMaterial(obj);
else if (obj instanceof Model)
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.cpp
index a54373f9831..d3dc35f2210 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.cpp
@@ -45,6 +45,12 @@
#include
#endif
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+#include
+#include
+#include
+#endif
+
#include
IconRenderer::IconRenderer(int size, const QString &filePath, const QString &source)
@@ -62,23 +68,26 @@ void IconRenderer::setupRender()
DesignerSupport::activateDesignerWindowManager();
#endif
- m_quickView = new QQuickView;
-
+ QQmlEngine *engine = nullptr;
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- QSurfaceFormat surfaceFormat = m_quickView->requestedFormat();
+ auto view = new QQuickView;
+ engine = view->engine();
+ m_window = view;
+ QSurfaceFormat surfaceFormat = view->requestedFormat();
surfaceFormat.setVersion(4, 1);
surfaceFormat.setProfile(QSurfaceFormat::CoreProfile);
- m_quickView->setFormat(surfaceFormat);
-
- DesignerSupport::createOpenGLContext(m_quickView);
+ view->setFormat(surfaceFormat);
+ DesignerSupport::createOpenGLContext(view);
#else
- m_quickView->setDefaultAlphaBuffer(true);
- m_quickView->setColor(Qt::transparent);
- m_ratio = m_quickView->devicePixelRatio();
- m_quickView->installEventFilter(this);
+ engine = new QQmlEngine;
+ m_renderControl = new QQuickRenderControl;
+ m_window = new QQuickWindow(m_renderControl);
+ m_window->setDefaultAlphaBuffer(true);
+ m_window->setColor(Qt::transparent);
+ m_renderControl->initialize();
#endif
- QQmlComponent component(m_quickView->engine());
+ QQmlComponent component(engine);
component.loadUrl(QUrl::fromLocalFile(m_source));
QObject *iconItem = component.create();
@@ -86,13 +95,19 @@ void IconRenderer::setupRender()
#ifdef QUICK3D_MODULE
if (auto scene = qobject_cast(iconItem)) {
qmlRegisterType("SelectionBoxGeometry", 1, 0, "SelectionBoxGeometry");
- QQmlComponent component(m_quickView->engine());
+ QQmlComponent component(engine);
component.loadUrl(QUrl("qrc:/qtquickplugin/mockfiles/IconRenderer3D.qml"));
m_containerItem = qobject_cast(component.create());
- DesignerSupport::setRootItem(m_quickView, m_containerItem);
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ DesignerSupport::setRootItem(view, m_containerItem);
+#else
+ m_window->contentItem()->setSize(m_containerItem->size());
+ m_window->setGeometry(0, 0, m_containerItem->width(), m_containerItem->height());
+ m_containerItem->setParentItem(m_window->contentItem());
+#endif
auto helper = new QmlDesigner::Internal::GeneralHelper();
- m_quickView->engine()->rootContext()->setContextProperty("_generalHelper", helper);
+ engine->rootContext()->setContextProperty("_generalHelper", helper);
m_contentItem = QQmlProperty::read(m_containerItem, "view3D").value();
auto view3D = qobject_cast(m_contentItem);
@@ -104,21 +119,21 @@ void IconRenderer::setupRender()
m_contentItem = scene;
m_containerItem = new QQuickItem();
m_containerItem->setSize(QSizeF(1024, 1024));
- DesignerSupport::setRootItem(m_quickView, m_containerItem);
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ DesignerSupport::setRootItem(view, m_containerItem);
+#else
+ m_window->contentItem()->setSize(m_containerItem->size());
+ m_window->setGeometry(0, 0, m_containerItem->width(), m_containerItem->height());
+ m_containerItem->setParentItem(m_window->contentItem());
+#endif
m_contentItem->setParentItem(m_containerItem);
}
if (m_containerItem && m_contentItem) {
resizeContent(m_size);
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ if (!initRhi())
+ QTimer::singleShot(0, qGuiApp, &QGuiApplication::quit);
QTimer::singleShot(0, this, &IconRenderer::createIcon);
-#else
- m_quickView->show();
- m_quickView->lower();
-
- // Failsafe to exit eventually if window fails to expose
- QTimer::singleShot(10000, qGuiApp, &QGuiApplication::quit);
-#endif
} else {
QTimer::singleShot(0, qGuiApp, &QGuiApplication::quit);
}
@@ -127,25 +142,12 @@ void IconRenderer::setupRender()
}
}
-bool IconRenderer::eventFilter(QObject *watched, QEvent *event)
-{
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
- if (watched == m_quickView && event->type() == QEvent::Expose)
- QTimer::singleShot(0, this, &IconRenderer::createIcon);
-#else
- Q_UNUSED(watched)
- Q_UNUSED(event)
-#endif
- return false;
-}
-
void IconRenderer::createIcon()
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- m_designerSupport.refFromEffectItem(m_quickView->rootObject(), false);
+ m_designerSupport.refFromEffectItem(m_containerItem, false);
#endif
- QQuickDesignerSupportItems::disableNativeTextRendering(m_quickView->rootObject());
-
+ QQuickDesignerSupportItems::disableNativeTextRendering(m_containerItem);
#ifdef QUICK3D_MODULE
if (m_is3D) {
// Render once to make sure scene is up to date before we set up the selection box
@@ -166,6 +168,8 @@ void IconRenderer::createIcon()
// Render @2x image
resizeContent(m_size * 2);
+ if (!initRhi())
+ QTimer::singleShot(1000, qGuiApp, &QGuiApplication::quit);
QString saveFile;
saveFile = fi.absolutePath() + '/' + fi.completeBaseName() + "@2x";
@@ -194,23 +198,39 @@ void IconRenderer::render(const QString &fileName)
item->update();
#endif
};
- updateNodesRecursive(m_quickView->rootObject());
+ updateNodesRecursive(m_containerItem);
QRect rect(QPoint(), m_contentItem->size().toSize());
+ QImage renderImage;
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- QImage renderImage = m_designerSupport.renderImageForItem(m_quickView->rootObject(),
- rect, rect.size());
+ renderImage = m_designerSupport.renderImageForItem(m_containerItem, rect, rect.size());
#else
- QImage renderImage = m_quickView->grabWindow();
+ m_renderControl->polishItems();
+ m_renderControl->beginFrame();
+ m_renderControl->sync();
+ m_renderControl->render();
+
+ bool readCompleted = false;
+ QRhiReadbackResult readResult;
+ readResult.completed = [&] {
+ readCompleted = true;
+ QImage wrapperImage(reinterpret_cast(readResult.data.constData()),
+ readResult.pixelSize.width(), readResult.pixelSize.height(),
+ QImage::Format_RGBA8888_Premultiplied);
+ if (m_rhi->isYUpInFramebuffer())
+ renderImage = wrapperImage.mirrored().copy(0, 0, rect.width(), rect.height());
+ else
+ renderImage = wrapperImage.copy(0, 0, rect.width(), rect.height());
+ };
+ QRhiResourceUpdateBatch *readbackBatch = m_rhi->nextResourceUpdateBatch();
+ readbackBatch->readBackTexture(m_texture, &readResult);
+
+ QQuickRenderControlPrivate *rd = QQuickRenderControlPrivate::get(m_renderControl);
+ rd->cb->resourceUpdate(readbackBatch);
+
+ m_renderControl->endFrame();
#endif
if (!fileName.isEmpty()) {
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
- if (m_ratio != 1.) {
- rect.setWidth(qRound(rect.size().width() * m_ratio));
- rect.setHeight(qRound(rect.size().height() * m_ratio));
- }
- renderImage = renderImage.copy(rect);
-#endif
QFileInfo fi(fileName);
if (fi.suffix().isEmpty())
renderImage.save(fileName, "PNG");
@@ -219,16 +239,60 @@ void IconRenderer::render(const QString &fileName)
}
}
-void IconRenderer::resizeContent(int size)
+void IconRenderer::resizeContent(int dimensions)
{
- int theSize = size;
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
- if (m_ratio != 1.)
- theSize = qRound(qreal(size) / m_quickView->devicePixelRatio());
-#endif
- m_contentItem->setSize(QSizeF(theSize, theSize));
+ QSizeF size(dimensions, dimensions);
+ m_contentItem->setSize(size);
if (m_contentItem->width() > m_containerItem->width())
m_containerItem->setWidth(m_contentItem->width());
if (m_contentItem->height() > m_containerItem->height())
m_containerItem->setHeight(m_contentItem->height());
}
+
+bool IconRenderer::initRhi()
+{
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ if (!m_rhi) {
+ QQuickRenderControlPrivate *rd = QQuickRenderControlPrivate::get(m_renderControl);
+ m_rhi = rd->rhi;
+ if (!m_rhi) {
+ qWarning() << __FUNCTION__ << "Rhi is null";
+ return false;
+ }
+ }
+
+ // Don't bother deleting old ones as iconrender is a single shot executable
+ m_texTarget = nullptr;
+ m_rpDesc = nullptr;
+ m_buffer = nullptr;
+ m_texture = nullptr;
+
+ const QSize size = m_containerItem->size().toSize();
+ m_texture = m_rhi->newTexture(QRhiTexture::RGBA8, size, 1,
+ QRhiTexture::RenderTarget | QRhiTexture::UsedAsTransferSource);
+ if (!m_texture->create()) {
+ qWarning() << __FUNCTION__ << "QRhiTexture creation failed";
+ return false;
+ }
+
+ m_buffer = m_rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, size, 1);
+ if (!m_buffer->create()) {
+ qWarning() << __FUNCTION__ << "Depth/stencil buffer creation failed";
+ return false;
+ }
+
+ QRhiTextureRenderTargetDescription rtDesc {QRhiColorAttachment(m_texture)};
+ rtDesc.setDepthStencilBuffer(m_buffer);
+ m_texTarget = m_rhi->newTextureRenderTarget(rtDesc);
+ m_rpDesc = m_texTarget->newCompatibleRenderPassDescriptor();
+ m_texTarget->setRenderPassDescriptor(m_rpDesc);
+ if (!m_texTarget->create()) {
+ qWarning() << __FUNCTION__ << "Texture render target creation failed";
+ return false;
+ }
+
+ // redirect Qt Quick rendering into our texture
+ m_window->setRenderTarget(QQuickRenderTarget::fromRhiRenderTarget(m_texTarget));
+#endif
+ return true;
+}
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.h
index 64afed6f8ae..6f5e36720d0 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.h
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.h
@@ -31,8 +31,16 @@
#include
QT_BEGIN_NAMESPACE
-class QQuickView;
+class QQuickWindow;
class QQuickItem;
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+class QQuickRenderControl;
+class QRhi;
+class QRhiTexture;
+class QRhiRenderBuffer;
+class QRhiTextureRenderTarget;
+class QRhiRenderPassDescriptor;
+#endif
QT_END_NAMESPACE
class IconRenderer : public QObject
@@ -44,21 +52,26 @@ public:
void setupRender();
-protected:
- bool eventFilter(QObject *watched, QEvent *event) override;
-
private:
void createIcon();
void render(const QString &fileName);
- void resizeContent(int size);
+ void resizeContent(int dimensions);
+ bool initRhi();
int m_size = 16;
- double m_ratio = 1.;
QString m_filePath;
QString m_source;
- QQuickView *m_quickView = nullptr;
+ QQuickWindow *m_window = nullptr;
QQuickItem *m_contentItem = nullptr;
QQuickItem *m_containerItem = nullptr;
DesignerSupport m_designerSupport;
bool m_is3D = false;
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ QQuickRenderControl *m_renderControl = nullptr;
+ QRhi *m_rhi = nullptr;
+ QRhiTexture *m_texture = nullptr;
+ QRhiRenderBuffer *m_buffer = nullptr;
+ QRhiTextureRenderTarget *m_texTarget = nullptr;
+ QRhiRenderPassDescriptor *m_rpDesc = nullptr;
+#endif
};
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp
index 552d3232473..64d790c6a7f 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp
@@ -189,9 +189,14 @@ NodeInstanceServer::NodeInstanceServer(NodeInstanceClientInterface *nodeInstance
Internal::QmlPrivateGate::registerFixResourcePathsForObjectCallBack();
}
+NodeInstanceServer::~NodeInstanceServer()
+{
+ m_objectInstanceHash.clear();
+}
+
QList NodeInstanceServer::createInstances(const QVector &containerVector)
{
- Q_ASSERT(declarativeView() || quickView());
+ Q_ASSERT(declarativeView() || quickWindow());
QList instanceList;
for (const InstanceContainer &instanceContainer : containerVector) {
ServerNodeInstance instance;
@@ -207,7 +212,6 @@ QList NodeInstanceServer::createInstances(const QVectorsetContent(fileUrl(), m_importComponent, m_rootNodeInstance.rootQuickItem());
- resizeCanvasSizeToRootItemSize();
}
foreach (QQmlContext* context, allSubContextsForObject(instance.internalObject()))
@@ -442,7 +446,7 @@ void NodeInstanceServer::removeSharedMemory(const RemoveSharedMemoryCommand &/*c
void NodeInstanceServer::setupImports(const QVector &containerVector)
{
- Q_ASSERT(quickView());
+ Q_ASSERT(quickWindow());
QSet importStatementSet;
QString qtQuickImport;
@@ -497,8 +501,9 @@ void NodeInstanceServer::setupOnlyWorkingImports(const QStringList &workingImpor
QByteArray componentCode = workingImportStatementList.join("\n").toUtf8().append("\n");
m_importCode = componentCode;
- m_importComponent = new QQmlComponent(engine(), quickView());
- quickView()->setContent(fileUrl(), m_importComponent, quickView()->rootObject());
+ m_importComponent = new QQmlComponent(engine(), quickWindow());
+ if (quickView())
+ quickView()->setContent(fileUrl(), m_importComponent, quickView()->rootObject());
m_importComponent->setData(componentCode.append("\nItem {}\n"), fileUrl());
m_importComponentObject = m_importComponent->create();
@@ -942,11 +947,9 @@ void NodeInstanceServer::setInstancePropertyVariant(const PropertyValueContainer
if (hasInstanceForId(valueContainer.instanceId())) {
ServerNodeInstance instance = instanceForId(valueContainer.instanceId());
-
const PropertyName name = valueContainer.name();
const QVariant value = valueContainer.value();
-
if (activeStateInstance().isValid() && !instance.isSubclassOf("QtQuick/PropertyChanges")) {
bool stateValueWasUpdated = activeStateInstance().updateStateVariant(instance, name, value);
if (!stateValueWasUpdated) {
@@ -962,6 +965,9 @@ void NodeInstanceServer::setInstancePropertyVariant(const PropertyValueContainer
if (valueContainer.isDynamic() && valueContainer.instanceId() == 0 && engine())
rootContext()->setContextProperty(QString::fromUtf8(name), Internal::QmlPrivateGate::fixResourcePaths(value));
+
+ if (valueContainer.instanceId() == 0 && (name == "width" || name == "height" || name == "x" || name == "y"))
+ resizeCanvasToRootItem();
}
}
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.h
index 021a2bd6d0d..f44a0047fe0 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.h
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.h
@@ -31,6 +31,7 @@
#include
#include
#include
+#include
#ifdef MULTILANGUAGE_TRANSLATIONPROVIDER
#include
@@ -90,6 +91,7 @@ QT_BEGIN_NAMESPACE
class QFileSystemWatcher;
class QQmlView;
class QQuickView;
+class QQuickWindow;
class QQmlEngine;
class QFileInfo;
class QQmlComponent;
@@ -131,6 +133,7 @@ public:
};
explicit NodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient);
+ ~NodeInstanceServer() override;
void createInstances(const CreateInstancesCommand &command) override;
void changeFileUrl(const ChangeFileUrlCommand &command) override;
@@ -192,6 +195,9 @@ public:
virtual QQmlView *declarativeView() const = 0;
virtual QQuickView *quickView() const = 0;
+ virtual QQuickWindow *quickWindow() const = 0;
+ virtual QQuickItem *rootItem() const = 0;
+ virtual void setRootItem(QQuickItem *item) = 0;
void sendDebugOutput(DebugOutputCommand::Type type, const QString &message, qint32 instanceId = 0);
void sendDebugOutput(DebugOutputCommand::Type type,
@@ -211,6 +217,8 @@ public:
virtual void handleInstanceLocked(const ServerNodeInstance &instance, bool enable, bool checkAncestors);
virtual void handleInstanceHidden(const ServerNodeInstance &instance, bool enable, bool checkAncestors);
+ virtual QImage grabWindow() = 0;
+
public slots:
void refreshLocalFileProperty(const QString &path);
void refreshDummyData(const QString &path);
@@ -288,7 +296,7 @@ protected:
QList allSubContextsForObject(QObject *object);
static QList allSubObjectsForObject(QObject *object);
- virtual void resizeCanvasSizeToRootItemSize() = 0;
+ virtual void resizeCanvasToRootItem() = 0;
void setupState(qint32 stateInstanceId);
private:
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5captureimagenodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5captureimagenodeinstanceserver.cpp
index d24c4e55522..4581bc6ce87 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5captureimagenodeinstanceserver.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5captureimagenodeinstanceserver.cpp
@@ -70,7 +70,7 @@ void Qt5CaptureImageNodeInstanceServer::collectItemChangesAndSendChangeCommands(
auto rooNodeInstance = rootNodeInstance();
rooNodeInstance.rootQuickItem()->setClip(true);
- DesignerSupport::polishItems(quickView());
+ DesignerSupport::polishItems(quickWindow());
QImage image = renderImage(rooNodeInstance);
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5capturepreviewnodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5capturepreviewnodeinstanceserver.cpp
index 7fb87defb09..b9ba3860a35 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5capturepreviewnodeinstanceserver.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5capturepreviewnodeinstanceserver.cpp
@@ -88,7 +88,7 @@ void Qt5CapturePreviewNodeInstanceServer::collectItemChangesAndSendChangeCommand
if (!inFunction) {
inFunction = true;
- DesignerSupport::polishItems(quickView());
+ DesignerSupport::polishItems(quickWindow());
QVector stateDatas;
stateDatas.push_back(collectStateData(rootNodeInstance(), nodeInstances(), 0));
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp
index 576e53c5301..b59ff161cdf 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp
@@ -87,6 +87,10 @@
#include
#include
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+#include
+#endif
+
#ifdef QUICK3D_MODULE
#include
#include
@@ -98,6 +102,14 @@
#endif
#endif
+// Uncomment to display FPS counter on the lower left corner of edit 3D view
+//#define FPS_COUNTER
+#ifdef FPS_COUNTER
+#include
+static QElapsedTimer *_fpsTimer = nullptr;
+static int _frameCount = 0;
+#endif
+
namespace QmlDesigner {
static QVariant objectToVariant(QObject *object)
@@ -135,29 +147,34 @@ static bool isQuick3DMode()
return mode3D;
}
-QQuickView *Qt5InformationNodeInstanceServer::createAuxiliaryQuickView(const QUrl &url,
- QQuickItem *&rootItem)
+void Qt5InformationNodeInstanceServer::createAuxiliaryQuickView(const QUrl &url,
+ RenderViewData &viewData)
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- auto view = new QQuickView(quickView()->engine(), quickView());
- view->setFormat(quickView()->format());
- DesignerSupport::createOpenGLContext(view);
+ viewData.window = new QQuickView(quickView()->engine(), quickView());
+ viewData.window->setFormat(quickView()->format());
+ DesignerSupport::createOpenGLContext(static_cast(viewData.window.data()));
#else
- auto view = new QQuickView(quickView()->engine(), nullptr);
- view->setFormat(quickView()->format());
+ viewData.renderControl = new QQuickRenderControl;
+ viewData.window = new QQuickWindow(viewData.renderControl);
+ viewData.renderControl->initialize();
#endif
QQmlComponent component(engine());
component.loadUrl(url);
- rootItem = qobject_cast(component.create());
+ viewData.rootItem = qobject_cast(component.create());
- if (!rootItem) {
+ if (!viewData.rootItem) {
qWarning() << "Could not create view for: " << url.toString() << component.errors();
- return nullptr;
+ return;
}
- DesignerSupport::setRootItem(view, rootItem);
-
- return view;
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ DesignerSupport::setRootItem(static_cast(viewData.window.data()), viewData.rootItem);
+#else
+ viewData.window->contentItem()->setSize(viewData.rootItem->size());
+ viewData.window->setGeometry(0, 0, viewData.rootItem->width(), viewData.rootItem->height());
+ viewData.rootItem->setParentItem(viewData.window->contentItem());
+#endif
}
void Qt5InformationNodeInstanceServer::updateLockedAndHiddenStates(const QSet &instances)
@@ -177,6 +194,65 @@ void Qt5InformationNodeInstanceServer::updateLockedAndHiddenStates(const QSet= QT_VERSION_CHECK(5, 12, 0))
+ = new QWheelEvent(command.pos(), command.pos(), {0, 0},
+ {0, angleDelta + command.angleDelta()},
+ command.buttons(), command.modifiers(), Qt::NoScrollPhase,
+ false);
+#else
+ = new QWheelEvent(command.pos(), command.pos(), {0, 0}, {0, command.angleDelta()},
+ 0, Qt::Horizontal, command.buttons(), command.modifiers(),
+ Qt::NoScrollPhase, Qt::MouseEventNotSynthesized);
+#endif
+ angleDelta = 0;
+ QGuiApplication::sendEvent(m_editView3DData.window, we);
+ } else {
+ if (command.type() == QEvent::MouseMove && i < m_pendingInputEventCommands.size() - 1) {
+ // Peek at next command. If that is also a move with only difference being
+ // the position, skip this event as it is pointless
+ auto nextCommand = m_pendingInputEventCommands[i + 1];
+ if (nextCommand.type() == QEvent::MouseMove
+ && nextCommand.button() == command.button()
+ && nextCommand.buttons() == command.buttons()
+ && nextCommand.modifiers() == command.modifiers()) {
+ continue;
+ }
+ }
+ auto me = new QMouseEvent(command.type(), command.pos(), command.button(),
+ command.buttons(), command.modifiers());
+ // We must use sendEvent in Qt 6, as using postEvent allows the associated position
+ // data stored internally in QMutableEventPoint to potentially be updated by system
+ // before the event is delivered.
+ QGuiApplication::sendEvent(m_editView3DData.window, me);
+ }
+ }
+
+ m_pendingInputEventCommands.clear();
+
+ render3DEditView();
+ }
+}
+
void Qt5InformationNodeInstanceServer::createEditView3D()
{
#ifdef QUICK3D_MODULE
@@ -199,10 +275,10 @@ void Qt5InformationNodeInstanceServer::createEditView3D()
new QmlDesigner::Internal::IconGizmoImageProvider);
m_3dHelper = helper;
- m_editView3D = createAuxiliaryQuickView(QUrl("qrc:/qtquickplugin/mockfiles/EditView3D.qml"), m_editView3DRootItem);
+ createAuxiliaryQuickView(QUrl("qrc:/qtquickplugin/mockfiles/EditView3D.qml"), m_editView3DData);
- if (m_editView3DRootItem)
- helper->setParent(m_editView3DRootItem);
+ if (m_editView3DData.rootItem)
+ helper->setParent(m_editView3DData.rootItem);
#endif
}
@@ -373,10 +449,10 @@ void Qt5InformationNodeInstanceServer::handleNode3DDestroyed(QObject *obj)
{
#ifdef QUICK3D_MODULE
if (qobject_cast(obj)) {
- QMetaObject::invokeMethod(m_editView3DRootItem, "releaseCameraGizmo",
+ QMetaObject::invokeMethod(m_editView3DData.rootItem, "releaseCameraGizmo",
Q_ARG(QVariant, objectToVariant(obj)));
} else if (qobject_cast(obj)) {
- QMetaObject::invokeMethod(m_editView3DRootItem, "releaseLightGizmo",
+ QMetaObject::invokeMethod(m_editView3DData.rootItem, "releaseLightGizmo",
Q_ARG(QVariant, objectToVariant(obj)));
}
removeNode3D(obj);
@@ -392,7 +468,7 @@ void Qt5InformationNodeInstanceServer::updateView3DRect(QObject *view3D)
viewPortrect = QRectF(0., 0., view3D->property("width").toDouble(),
view3D->property("height").toDouble());
}
- QQmlProperty viewPortProperty(m_editView3DRootItem, "viewPortRect", context());
+ QQmlProperty viewPortProperty(m_editView3DData.rootItem, "viewPortRect", context());
viewPortProperty.write(viewPortrect);
}
@@ -405,7 +481,7 @@ void Qt5InformationNodeInstanceServer::updateActiveSceneToEditView3D()
// Active scene change handling on qml side is async, so a deleted importScene would crash
// editView when it updates next. Disable/enable edit view update synchronously to avoid this.
QVariant activeSceneVar = objectToVariant(m_active3DScene);
- QMetaObject::invokeMethod(m_editView3DRootItem, "enableEditViewUpdate",
+ QMetaObject::invokeMethod(m_editView3DData.rootItem, "enableEditViewUpdate",
Q_ARG(QVariant, activeSceneVar));
ServerNodeInstance sceneInstance = active3DSceneInstance();
@@ -419,7 +495,7 @@ void Qt5InformationNodeInstanceServer::updateActiveSceneToEditView3D()
m_active3DSceneUpdatePending = false;
}
- QMetaObject::invokeMethod(m_editView3DRootItem, "setActiveScene", Qt::QueuedConnection,
+ QMetaObject::invokeMethod(m_editView3DData.rootItem, "setActiveScene", Qt::QueuedConnection,
Q_ARG(QVariant, activeSceneVar),
Q_ARG(QVariant, QVariant::fromValue(sceneId)));
@@ -472,11 +548,11 @@ void Qt5InformationNodeInstanceServer::resolveSceneRoots()
if (newRoot != oldRoot) {
if (qobject_cast(node)) {
- QMetaObject::invokeMethod(m_editView3DRootItem, "updateCameraGizmoScene",
+ QMetaObject::invokeMethod(m_editView3DData.rootItem, "updateCameraGizmoScene",
Q_ARG(QVariant, objectToVariant(newRoot)),
Q_ARG(QVariant, objectToVariant(node)));
} else if (qobject_cast(node)) {
- QMetaObject::invokeMethod(m_editView3DRootItem, "updateLightGizmoScene",
+ QMetaObject::invokeMethod(m_editView3DData.rootItem, "updateLightGizmoScene",
Q_ARG(QVariant, objectToVariant(newRoot)),
Q_ARG(QVariant, objectToVariant(node)));
}
@@ -535,30 +611,30 @@ void Qt5InformationNodeInstanceServer::render3DEditView(int count)
void Qt5InformationNodeInstanceServer::doRender3DEditView()
{
if (m_editView3DSetupDone) {
- if (!m_editView3DContentItem)
- m_editView3DContentItem = getContentItemForRendering(m_editView3DRootItem);
+ if (!m_editView3DData.contentItem)
+ m_editView3DData.contentItem = getContentItemForRendering(m_editView3DData.rootItem);
QImage renderImage;
- updateNodesRecursive(m_editView3DContentItem);
+ updateNodesRecursive(m_editView3DData.contentItem);
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (Internal::QuickItemNodeInstance::unifiedRenderPath()) {
- renderImage = m_editView3D->grabWindow();
+ renderImage = m_editView3DData.window->grabWindow();
} else {
// Fake render loop signaling to update things like QML items as 3D textures
- m_editView3D->beforeSynchronizing();
- m_editView3D->beforeRendering();
+ m_editView3DData.window->beforeSynchronizing();
+ m_editView3DData.window->beforeRendering();
- QSizeF size = qobject_cast(m_editView3DContentItem)->size();
+ QSizeF size = qobject_cast(m_editView3DData.contentItem)->size();
QRectF renderRect(QPointF(0., 0.), size);
- renderImage = designerSupport()->renderImageForItem(m_editView3DContentItem,
+ renderImage = designerSupport()->renderImageForItem(m_editView3DData.contentItem,
renderRect, size.toSize());
- m_editView3D->afterRendering();
+ m_editView3DData.window->afterRendering();
}
#else
- renderImage = m_editView3D->grabWindow();
+ renderImage = grabRenderControl(m_editView3DData);
#endif
// There's no instance related to image, so instance id is -1.
@@ -572,6 +648,18 @@ void Qt5InformationNodeInstanceServer::doRender3DEditView()
m_render3DEditViewTimer.start(0);
--m_need3DEditViewRender;
}
+#ifdef FPS_COUNTER
+ // Force constant rendering for accurate fps count
+ if (!m_render3DEditViewTimer.isActive())
+ m_render3DEditViewTimer.start(0);
+ ++_frameCount;
+ if (_fpsTimer->elapsed() > 1000) {
+ QQmlProperty fpsProperty(m_editView3DData.rootItem, "fps", context());
+ fpsProperty.write(_frameCount);
+ _frameCount = 0;
+ _fpsTimer->start();
+ }
+#endif
}
}
@@ -601,9 +689,9 @@ void Qt5InformationNodeInstanceServer::doRenderModelNodeImageView()
void Qt5InformationNodeInstanceServer::doRenderModelNode3DImageView()
{
#ifdef QUICK3D_MODULE
- if (m_ModelNode3DImageViewRootItem) {
- if (!m_ModelNode3DImageViewContentItem)
- m_ModelNode3DImageViewContentItem = getContentItemForRendering(m_ModelNode3DImageViewRootItem);
+ if (m_modelNode3DImageViewData.rootItem) {
+ if (!m_modelNode3DImageViewData.contentItem)
+ m_modelNode3DImageViewData.contentItem = getContentItemForRendering(m_modelNode3DImageViewData.rootItem);
// Key number is selected so that it is unlikely to conflict other ImageContainer use.
auto imgContainer = ImageContainer(m_modelNodePreviewImageCommand.instanceId(), {}, 2100000001);
@@ -628,43 +716,48 @@ void Qt5InformationNodeInstanceServer::doRenderModelNode3DImageView()
if (Internal::QuickItemNodeInstance::unifiedRenderPath()) {
// Requested size is already adjusted for target pixel ratio, so we have to adjust
// back if ratio is not default for our window.
- double ratio = m_ModelNode3DImageView->devicePixelRatio();
+ double ratio = m_modelNode3DImageViewData.window->devicePixelRatio();
renderSize.setWidth(qRound(qreal(renderSize.width()) / ratio));
renderSize.setHeight(qRound(qreal(renderSize.height()) / ratio));
}
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ m_modelNode3DImageViewData.bufferDirty = m_modelNode3DImageViewData.bufferDirty
+ || m_modelNode3DImageViewData.rootItem->width() != renderSize.width()
+ || m_modelNode3DImageViewData.rootItem->height() != renderSize.height();
+#endif
- QMetaObject::invokeMethod(m_ModelNode3DImageViewRootItem, "createViewForObject",
- Q_ARG(QVariant, objectToVariant(instanceObj)),
- Q_ARG(QVariant, QVariant::fromValue(renderSize.width())),
- Q_ARG(QVariant, QVariant::fromValue(renderSize.height())));
+ m_modelNode3DImageViewData.window->resize(renderSize);
+ m_modelNode3DImageViewData.rootItem->setSize(renderSize);
+ QMetaObject::invokeMethod(m_modelNode3DImageViewData.rootItem, "createViewForObject",
+ Q_ARG(QVariant, objectToVariant(instanceObj)));
bool ready = false;
int count = 0; // Ensure we don't ever get stuck in an infinite loop
while (!ready && ++count < 10) {
- updateNodesRecursive(m_ModelNode3DImageViewContentItem);
+ updateNodesRecursive(m_modelNode3DImageViewData.contentItem);
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (Internal::QuickItemNodeInstance::unifiedRenderPath()) {
- renderImage = m_ModelNode3DImageView->grabWindow();
+ renderImage = m_modelNode3DImageViewData.window->grabWindow();
} else {
// Fake render loop signaling to update things like QML items as 3D textures
- m_ModelNode3DImageView->beforeSynchronizing();
- m_ModelNode3DImageView->beforeRendering();
+ m_modelNode3DImageViewData.window->beforeSynchronizing();
+ m_modelNode3DImageViewData.window->beforeRendering();
- QSizeF size = qobject_cast(m_ModelNode3DImageViewContentItem)->size();
+ QSizeF size = qobject_cast(m_modelNode3DImageViewData.contentItem)->size();
QRectF renderRect(QPointF(0., 0.), size);
- renderImage = designerSupport()->renderImageForItem(m_ModelNode3DImageViewContentItem,
+ renderImage = designerSupport()->renderImageForItem(m_modelNode3DImageViewData.contentItem,
renderRect, size.toSize());
- m_ModelNode3DImageView->afterRendering();
+ m_modelNode3DImageViewData.window->afterRendering();
}
#else
- renderImage = m_ModelNode3DImageView->grabWindow();
+ renderImage = grabRenderControl(m_modelNode3DImageViewData);
#endif
- QMetaObject::invokeMethod(m_ModelNode3DImageViewRootItem, "afterRender");
- ready = QQmlProperty::read(m_ModelNode3DImageViewRootItem, "ready").value();
+ QMetaObject::invokeMethod(m_modelNode3DImageViewData.rootItem, "afterRender");
+ ready = QQmlProperty::read(m_modelNode3DImageViewData.rootItem, "ready").value();
}
- QMetaObject::invokeMethod(m_ModelNode3DImageViewRootItem, "destroyView");
+ QMetaObject::invokeMethod(m_modelNode3DImageViewData.rootItem, "destroyView");
if (!m_modelNodePreviewImageCommand.componentPath().isEmpty()) {
// If component changes, puppet will need a reset anyway, so we can cache the image
m_modelNodePreviewImageCache.insert(m_modelNodePreviewImageCommand.componentPath(), renderImage);
@@ -705,9 +798,9 @@ static QRectF itemBoundingRect(QQuickItem *item)
void Qt5InformationNodeInstanceServer::doRenderModelNode2DImageView()
{
- if (m_ModelNode2DImageViewRootItem) {
- if (!m_ModelNode2DImageViewContentItem)
- m_ModelNode2DImageViewContentItem = getContentItemForRendering(m_ModelNode2DImageViewRootItem);
+ if (m_modelNode2DImageViewData.rootItem) {
+ if (!m_modelNode2DImageViewData.contentItem)
+ m_modelNode2DImageViewData.contentItem = getContentItemForRendering(m_modelNode2DImageViewData.rootItem);
// Key number is the same as in 3D case as they produce image for same purpose
auto imgContainer = ImageContainer(m_modelNodePreviewImageCommand.instanceId(), {}, 2100000001);
@@ -730,7 +823,7 @@ void Qt5InformationNodeInstanceServer::doRenderModelNode2DImageView()
return;
}
- instanceItem->setParentItem(m_ModelNode2DImageViewContentItem);
+ instanceItem->setParentItem(m_modelNode2DImageViewData.contentItem);
// Some component may expect to always be shown at certain size, so their layouts may
// not support scaling, so let's always render at the default size if item has one and
@@ -742,21 +835,28 @@ void Qt5InformationNodeInstanceServer::doRenderModelNode2DImageView()
renderSize = finalSize;
renderRect = QRectF(QPointF(0., 0.), QSizeF(renderSize));
}
- m_ModelNode2DImageView->resize(renderSize);
- m_ModelNode2DImageViewRootItem->setSize(renderSize);
- m_ModelNode2DImageViewContentItem->setPosition(QPointF(-renderRect.x(), -renderRect.y()));
- updateNodesRecursive(m_ModelNode2DImageViewContentItem);
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ m_modelNode2DImageViewData.bufferDirty = m_modelNode2DImageViewData.bufferDirty
+ || m_modelNode2DImageViewData.rootItem->width() != renderSize.width()
+ || m_modelNode2DImageViewData.rootItem->height() != renderSize.height();
+#endif
+
+ m_modelNode2DImageViewData.window->resize(renderSize);
+ m_modelNode2DImageViewData.rootItem->setSize(renderSize);
+ m_modelNode2DImageViewData.contentItem->setPosition(QPointF(-renderRect.x(), -renderRect.y()));
+
+ updateNodesRecursive(m_modelNode2DImageViewData.contentItem);
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (Internal::QuickItemNodeInstance::unifiedRenderPath()) {
- renderImage = m_ModelNode2DImageView->grabWindow();
+ renderImage = m_modelNode2DImageViewData.window->grabWindow();
} else {
- renderImage = designerSupport()->renderImageForItem(m_ModelNode2DImageViewContentItem,
+ renderImage = designerSupport()->renderImageForItem(m_modelNode2DImageViewData.contentItem,
renderRect, renderSize);
}
#else
- renderImage = m_ModelNode2DImageView->grabWindow();
+ renderImage = grabRenderControl(m_modelNode2DImageViewData);
#endif
if (!imageHasContent(renderImage))
@@ -788,13 +888,34 @@ Qt5InformationNodeInstanceServer::Qt5InformationNodeInstanceServer(NodeInstanceC
m_propertyChangeTimer.setSingleShot(true);
m_selectionChangeTimer.setSingleShot(true);
m_render3DEditViewTimer.setSingleShot(true);
+ m_inputEventTimer.setSingleShot(true);
m_renderModelNodeImageViewTimer.setSingleShot(true);
+
+#ifdef FPS_COUNTER
+ if (!_fpsTimer) {
+ _fpsTimer = new QElapsedTimer;
+ _fpsTimer->start();
+ }
+#endif
}
Qt5InformationNodeInstanceServer::~Qt5InformationNodeInstanceServer()
{
+ m_editView3DSetupDone = false;
+
+ m_propertyChangeTimer.stop();
+ m_propertyChangeTimer.stop();
+ m_selectionChangeTimer.stop();
+ m_render3DEditViewTimer.stop();
+ m_inputEventTimer.stop();
+
for (auto view : qAsConst(m_view3Ds))
- QObject::disconnect(view, nullptr, this, nullptr);
+ view->disconnect();
+ for (auto node : qAsConst(m_3DSceneMap))
+ node->disconnect();
+
+ if (m_editView3DData.rootItem)
+ QMetaObject::invokeMethod(m_editView3DData.rootItem, "aboutToShutDown", Qt::DirectConnection);
}
void Qt5InformationNodeInstanceServer::sendTokenBack()
@@ -887,29 +1008,14 @@ void Qt5InformationNodeInstanceServer::initializeAuxiliaryViews()
#ifdef QUICK3D_MODULE
if (isQuick3DMode())
createEditView3D();
- m_ModelNode3DImageView = createAuxiliaryQuickView(QUrl("qrc:/qtquickplugin/mockfiles/ModelNode3DImageView.qml"),
- m_ModelNode3DImageViewRootItem);
+ createAuxiliaryQuickView(QUrl("qrc:/qtquickplugin/mockfiles/ModelNode3DImageView.qml"),
+ m_modelNode3DImageViewData);
#endif
- m_ModelNode2DImageView = createAuxiliaryQuickView(QUrl("qrc:/qtquickplugin/mockfiles/ModelNode2DImageView.qml"),
- m_ModelNode2DImageViewRootItem);
- m_ModelNode2DImageView->setDefaultAlphaBuffer(true);
- m_ModelNode2DImageView->setColor(Qt::transparent);
-
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
- if (!m_editView3D.isNull()) {
- m_editView3D->show();
- m_editView3D->lower();
- }
- if (!m_ModelNode3DImageView.isNull()) {
- m_ModelNode3DImageView->show();
- m_ModelNode3DImageView->lower();
- }
- if (!m_ModelNode2DImageView.isNull()) {
- m_ModelNode2DImageView->show();
- m_ModelNode2DImageView->lower();
- }
-#endif
+ createAuxiliaryQuickView(QUrl("qrc:/qtquickplugin/mockfiles/ModelNode2DImageView.qml"),
+ m_modelNode2DImageViewData);
+ m_modelNode2DImageViewData.window->setDefaultAlphaBuffer(true);
+ m_modelNode2DImageViewData.window->setColor(Qt::transparent);
}
void Qt5InformationNodeInstanceServer::handleObjectPropertyChangeTimeout()
@@ -940,7 +1046,7 @@ void Qt5InformationNodeInstanceServer::createCameraAndLightGizmos(
while (cameraIt != cameras.constEnd()) {
const auto cameraObjs = cameraIt.value();
for (auto &obj : cameraObjs) {
- QMetaObject::invokeMethod(m_editView3DRootItem, "addCameraGizmo",
+ QMetaObject::invokeMethod(m_editView3DData.rootItem, "addCameraGizmo",
Q_ARG(QVariant, objectToVariant(cameraIt.key())),
Q_ARG(QVariant, objectToVariant(obj)));
}
@@ -950,7 +1056,7 @@ void Qt5InformationNodeInstanceServer::createCameraAndLightGizmos(
while (lightIt != lights.constEnd()) {
const auto lightObjs = lightIt.value();
for (auto &obj : lightObjs) {
- QMetaObject::invokeMethod(m_editView3DRootItem, "addLightGizmo",
+ QMetaObject::invokeMethod(m_editView3DData.rootItem, "addLightGizmo",
Q_ARG(QVariant, objectToVariant(lightIt.key())),
Q_ARG(QVariant, objectToVariant(obj)));
}
@@ -1134,7 +1240,7 @@ void Qt5InformationNodeInstanceServer::setup3DEditView(const QList &toolStates)
{
#ifdef QUICK3D_MODULE
- if (!m_editView3DRootItem)
+ if (!m_editView3DData.rootItem)
return;
ServerNodeInstance root = rootNodeInstance();
@@ -1142,13 +1248,13 @@ void Qt5InformationNodeInstanceServer::setup3DEditView(const QList(m_3dHelper);
@@ -1167,7 +1275,7 @@ void Qt5InformationNodeInstanceServer::setup3DEditView(const QListglobalStateId())) {
if (toolStates[helper->globalStateId()].contains(helper->rootSizeKey()))
- m_editView3DRootItem->setSize(toolStates[helper->globalStateId()][helper->rootSizeKey()].value());
+ m_editView3DData.rootItem->setSize(toolStates[helper->globalStateId()][helper->rootSizeKey()].value());
if (toolStates[helper->globalStateId()].contains(helper->lastSceneIdKey()))
lastSceneId = toolStates[helper->globalStateId()][helper->lastSceneIdKey()].toString();
}
@@ -1198,7 +1306,7 @@ void Qt5InformationNodeInstanceServer::setup3DEditView(const QList informationChangedInstanceSet;
QVector propertyChangedList;
- if (quickView()) {
+ if (quickWindow()) {
foreach (QQuickItem *item, allItems()) {
if (item && hasInstanceForObject(item)) {
ServerNodeInstance instance = instanceForObject(item);
@@ -1456,13 +1564,13 @@ void Qt5InformationNodeInstanceServer::changeSelection(const ChangeSelectionComm
// Ensure the UI has enough selection box items. If it doesn't yet have them, which can be the
// case when the first selection processed is a multiselection, we wait a bit as
// using the new boxes immediately leads to visual glitches.
- int boxCount = m_editView3DRootItem->property("selectionBoxes").value().size();
+ int boxCount = m_editView3DData.rootItem->property("selectionBoxes").value().size();
if (boxCount < selectedObjs.size()) {
- QMetaObject::invokeMethod(m_editView3DRootItem, "ensureSelectionBoxes",
+ QMetaObject::invokeMethod(m_editView3DData.rootItem, "ensureSelectionBoxes",
Q_ARG(QVariant, QVariant::fromValue(selectedObjs.size())));
m_selectionChangeTimer.start(0);
} else {
- QMetaObject::invokeMethod(m_editView3DRootItem, "selectObjects",
+ QMetaObject::invokeMethod(m_editView3DData.rootItem, "selectObjects",
Q_ARG(QVariant, QVariant::fromValue(selectedObjs)));
}
@@ -1511,27 +1619,10 @@ void Qt5InformationNodeInstanceServer::removeInstances(const RemoveInstancesComm
void Qt5InformationNodeInstanceServer::inputEvent(const InputEventCommand &command)
{
- if (m_editView3D) {
- if (command.type() == QEvent::Wheel) {
- QWheelEvent *we
-#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))
- = new QWheelEvent(command.pos(), command.pos(), {0, 0}, {0, command.angleDelta()},
- command.buttons(), command.modifiers(), Qt::NoScrollPhase,
- false);
-#else
- = new QWheelEvent(command.pos(), command.pos(), {0, 0}, {0, command.angleDelta()},
- 0, Qt::Horizontal, command.buttons(), command.modifiers(),
- Qt::NoScrollPhase, Qt::MouseEventNotSynthesized);
-#endif
-
- QGuiApplication::postEvent(m_editView3D, we);
- } else {
- auto me = new QMouseEvent(command.type(), command.pos(), command.button(),
- command.buttons(), command.modifiers());
- QGuiApplication::postEvent(m_editView3D, me);
- }
-
- render3DEditView();
+ if (m_editView3DData.window) {
+ m_pendingInputEventCommands.append(command);
+ if (!m_inputEventTimer.isActive())
+ m_inputEventTimer.start(0);
}
}
@@ -1554,7 +1645,7 @@ void Qt5InformationNodeInstanceServer::view3DAction(const View3DActionCommand &c
updatedState.insert("transformMode", 2);
break;
case View3DActionCommand::FitToView:
- QMetaObject::invokeMethod(m_editView3DRootItem, "fitToView");
+ QMetaObject::invokeMethod(m_editView3DData.rootItem, "fitToView");
break;
case View3DActionCommand::SelectionModeToggle:
updatedState.insert("selectionMode", command.isEnabled() ? 1 : 0);
@@ -1578,7 +1669,7 @@ void Qt5InformationNodeInstanceServer::view3DAction(const View3DActionCommand &c
}
if (!updatedState.isEmpty()) {
- QMetaObject::invokeMethod(m_editView3DRootItem, "updateToolStates",
+ QMetaObject::invokeMethod(m_editView3DData.rootItem, "updateToolStates",
Q_ARG(QVariant, updatedState),
Q_ARG(QVariant, QVariant::fromValue(false)));
}
@@ -1619,7 +1710,7 @@ void Qt5InformationNodeInstanceServer::changeIds(const ChangeIdsCommand &command
qint32 sceneInstanceId = sceneInstance.instanceId();
for (const auto &id : command.ids) {
if (sceneInstanceId == id.instanceId()) {
- QMetaObject::invokeMethod(m_editView3DRootItem, "handleActiveSceneIdChange",
+ QMetaObject::invokeMethod(m_editView3DData.rootItem, "handleActiveSceneIdChange",
Qt::QueuedConnection,
Q_ARG(QVariant, QVariant(sceneInstance.id())));
render3DEditView();
@@ -1763,12 +1854,18 @@ void Qt5InformationNodeInstanceServer::update3DViewState(const Update3dViewState
#ifdef QUICK3D_MODULE
if (command.type() == Update3dViewStateCommand::SizeChange) {
if (m_editView3DSetupDone) {
- m_editView3DRootItem->setSize(command.size());
+ m_editView3DData.rootItem->setSize(command.size());
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ m_editView3DData.window->contentItem()->setSize(m_editView3DData.rootItem->size());
+ m_editView3DData.window->setGeometry(0, 0, m_editView3DData.rootItem->width(),
+ m_editView3DData.rootItem->height());
+ m_editView3DData.bufferDirty = true;
+#endif
auto helper = qobject_cast(m_3dHelper);
if (helper)
helper->storeToolState(helper->globalStateId(), helper->rootSizeKey(), QVariant(command.size()), 0);
- // Queue two renders to make sure icon gizmos update properly
- render3DEditView(2);
+ // Queue three renders to make sure icon gizmos update properly
+ render3DEditView(3);
}
}
#else
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h
index f703e9fcb89..353f57b3fc4 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h
@@ -129,19 +129,16 @@ private:
void doRenderModelNodeImageView();
void doRenderModelNode3DImageView();
void doRenderModelNode2DImageView();
- QQuickView *createAuxiliaryQuickView(const QUrl &url, QQuickItem *&rootItem);
void updateLockedAndHiddenStates(const QSet &instances);
+ void handleInputEvents();
+
+ void createAuxiliaryQuickView(const QUrl &url, RenderViewData &viewData);
+
+ RenderViewData m_editView3DData;
+ RenderViewData m_modelNode3DImageViewData;
+ RenderViewData m_modelNode2DImageViewData;
- QPointer m_editView3D;
- QQuickItem *m_editView3DRootItem = nullptr;
- QQuickItem *m_editView3DContentItem = nullptr;
bool m_editView3DSetupDone = false;
- QPointer m_ModelNode3DImageView;
- QQuickItem *m_ModelNode3DImageViewRootItem = nullptr;
- QQuickItem *m_ModelNode3DImageViewContentItem = nullptr;
- QPointer m_ModelNode2DImageView;
- QQuickItem *m_ModelNode2DImageViewRootItem = nullptr;
- QQuickItem *m_ModelNode2DImageViewContentItem = nullptr;
RequestModelNodePreviewImageCommand m_modelNodePreviewImageCommand;
QHash m_modelNodePreviewImageCache;
QSet m_view3Ds;
@@ -156,9 +153,11 @@ private:
QTimer m_selectionChangeTimer;
QTimer m_render3DEditViewTimer;
QTimer m_renderModelNodeImageViewTimer;
+ QTimer m_inputEventTimer;
QVariant m_changedNode;
PropertyName m_changedProperty;
ChangeSelectionCommand m_lastSelectionChangeCommand;
+ QList m_pendingInputEventCommands;
QObject *m_3dHelper = nullptr;
int m_need3DEditViewRender = 0;
};
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp
index 90f959dd2be..620ed0352b3 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp
@@ -31,6 +31,7 @@
#include
#include
+#include
#include
#include
@@ -40,6 +41,14 @@
#include
#include
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+#include
+#include
+#include
+#include
+#include
+#endif
+
namespace QmlDesigner {
Qt5NodeInstanceServer::Qt5NodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient)
@@ -50,30 +59,44 @@ Qt5NodeInstanceServer::Qt5NodeInstanceServer(NodeInstanceClientInterface *nodeIn
Qt5NodeInstanceServer::~Qt5NodeInstanceServer()
{
- delete quickView();
+ delete quickWindow();
}
QQuickView *Qt5NodeInstanceServer::quickView() const
{
- return m_quickView.data();
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ return static_cast(m_viewData.window.data());
+#else
+ return nullptr;
+#endif
+}
+
+QQuickWindow *Qt5NodeInstanceServer::quickWindow() const
+{
+ return m_viewData.window.data();
}
void Qt5NodeInstanceServer::initializeView()
{
- Q_ASSERT(!quickView());
-
- m_quickView = new QQuickView;
+ Q_ASSERT(!quickWindow());
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ auto view = new QQuickView;
+ m_viewData.window = view;
/* enables grab window without show */
- QSurfaceFormat surfaceFormat = m_quickView->requestedFormat();
+ QSurfaceFormat surfaceFormat = view->requestedFormat();
surfaceFormat.setVersion(4, 1);
surfaceFormat.setProfile(QSurfaceFormat::CoreProfile);
QSurfaceFormat::setDefaultFormat(surfaceFormat);
+ view->setFormat(surfaceFormat);
- m_quickView->setFormat(surfaceFormat);
-
- DesignerSupport::createOpenGLContext(m_quickView.data());
+ DesignerSupport::createOpenGLContext(view);
+ m_qmlEngine = view->engine();
+#else
+ m_viewData.renderControl = new QQuickRenderControl;
+ m_viewData.window = new QQuickWindow(m_viewData.renderControl);
+ m_viewData.renderControl->initialize();
+ m_qmlEngine = new QQmlEngine;
#endif
if (qEnvironmentVariableIsSet("QML_FILE_SELECTORS")) {
@@ -90,16 +113,39 @@ QQmlView *Qt5NodeInstanceServer::declarativeView() const
return nullptr;
}
-QQmlEngine *Qt5NodeInstanceServer::engine() const
+QQuickItem *Qt5NodeInstanceServer::rootItem() const
{
- if (quickView())
- return quickView()->engine();
-
- return nullptr;
+ return m_viewData.rootItem;
}
-void Qt5NodeInstanceServer::resizeCanvasSizeToRootItemSize()
+void Qt5NodeInstanceServer::setRootItem(QQuickItem *item)
{
+ m_viewData.rootItem = item;
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ DesignerSupport::setRootItem(quickView(), item);
+#else
+ quickWindow()->setGeometry(0, 0, item->width(), item->height());
+ // Insert an extra item above the root to adjust root item position to 0,0 to make entire
+ // item to be always rendered.
+ if (!m_viewData.contentItem)
+ m_viewData.contentItem = new QQuickItem(quickWindow()->contentItem());
+ m_viewData.contentItem->setPosition(-item->position());
+ item->setParentItem(m_viewData.contentItem);
+#endif
+}
+
+QQmlEngine *Qt5NodeInstanceServer::engine() const
+{
+ return m_qmlEngine;
+}
+
+void Qt5NodeInstanceServer::resizeCanvasToRootItem()
+{
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ m_viewData.bufferDirty = true;
+ m_viewData.contentItem->setPosition(-m_viewData.rootItem->position());
+#endif
+ quickWindow()->resize(rootNodeInstance().boundingRect().size().toSize());
}
void Qt5NodeInstanceServer::resetAllItems()
@@ -116,7 +162,7 @@ void Qt5NodeInstanceServer::setupScene(const CreateSceneCommand &command)
setupDummyData(command.fileUrl);
setupInstances(command);
- quickView()->resize(rootNodeInstance().boundingRect().size().toSize());
+ resizeCanvasToRootItem();
}
QList subItems(QQuickItem *parentItem)
@@ -138,6 +184,127 @@ QList Qt5NodeInstanceServer::allItems() const
return QList();
}
+bool Qt5NodeInstanceServer::initRhi(RenderViewData &viewData)
+{
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ if (!viewData.renderControl) {
+ qWarning() << __FUNCTION__ << "Render control not created";
+ return false;
+ }
+
+ if (!viewData.rhi) {
+ QQuickRenderControlPrivate *rd = QQuickRenderControlPrivate::get(viewData.renderControl);
+ viewData.rhi = rd->rhi;
+
+ if (!viewData.rhi) {
+ qWarning() << __FUNCTION__ << "Rhi is null";
+ return false;
+ }
+ }
+
+ auto cleanRhiResources = [&viewData]() {
+ // Releasing cached resources is a workaround for bug QTBUG-88761
+ auto renderer = QQuickWindowPrivate::get(viewData.window)->renderer;
+ if (renderer)
+ renderer->releaseCachedResources();
+
+ if (viewData.rpDesc) {
+ viewData.rpDesc->deleteLater();
+ viewData.rpDesc = nullptr;
+ }
+ if (viewData.texTarget) {
+ viewData.texTarget->deleteLater();
+ viewData.texTarget = nullptr;
+ }
+ if (viewData.buffer) {
+ viewData.buffer->deleteLater();
+ viewData.buffer = nullptr;
+ }
+ if (viewData.texture) {
+ viewData.texture->deleteLater();
+ viewData.texture = nullptr;
+ }
+ };
+ if (viewData.bufferDirty) {
+ cleanRhiResources();
+ viewData.bufferDirty = false;
+ }
+
+ const QSize size = viewData.window->size();
+ viewData.texture = viewData.rhi->newTexture(QRhiTexture::RGBA8, size, 1,
+ QRhiTexture::RenderTarget | QRhiTexture::UsedAsTransferSource);
+ if (!viewData.texture->create()) {
+ qWarning() << __FUNCTION__ << "QRhiTexture creation failed";
+ cleanRhiResources();
+ return false;
+ }
+
+ viewData.buffer = viewData.rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, size, 1);
+ if (!viewData.buffer->create()) {
+ qWarning() << __FUNCTION__ << "Depth/stencil buffer creation failed";
+ cleanRhiResources();
+ return false;
+ }
+
+ QRhiTextureRenderTargetDescription rtDesc(QRhiColorAttachment(viewData.texture));
+ rtDesc.setDepthStencilBuffer(viewData.buffer);
+ viewData.texTarget = viewData.rhi->newTextureRenderTarget(rtDesc);
+ viewData.rpDesc = viewData.texTarget->newCompatibleRenderPassDescriptor();
+ viewData.texTarget->setRenderPassDescriptor(viewData.rpDesc);
+ if (!viewData.texTarget->create()) {
+ qWarning() << __FUNCTION__ << "Texture render target creation failed";
+ cleanRhiResources();
+ return false;
+ }
+
+ // redirect Qt Quick rendering into our texture
+ viewData.window->setRenderTarget(QQuickRenderTarget::fromRhiRenderTarget(viewData.texTarget));
+#endif
+ return true;
+}
+
+QImage Qt5NodeInstanceServer::grabRenderControl(RenderViewData &viewData)
+{
+ QImage renderImage;
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ if (viewData.bufferDirty && !initRhi(viewData))
+ return renderImage;
+
+ viewData.renderControl->polishItems();
+ viewData.renderControl->beginFrame();
+ viewData.renderControl->sync();
+ viewData.renderControl->render();
+
+ bool readCompleted = false;
+ QRhiReadbackResult readResult;
+ readResult.completed = [&] {
+ readCompleted = true;
+ QImage wrapperImage(reinterpret_cast(readResult.data.constData()),
+ readResult.pixelSize.width(), readResult.pixelSize.height(),
+ QImage::Format_RGBA8888_Premultiplied);
+ if (viewData.rhi->isYUpInFramebuffer())
+ renderImage = wrapperImage.mirrored();
+ else
+ renderImage = wrapperImage.copy();
+ };
+ QRhiResourceUpdateBatch *readbackBatch = viewData.rhi->nextResourceUpdateBatch();
+ readbackBatch->readBackTexture(viewData.texture, &readResult);
+
+ QQuickRenderControlPrivate *rd = QQuickRenderControlPrivate::get(viewData.renderControl);
+ rd->cb->resourceUpdate(readbackBatch);
+
+ viewData.renderControl->endFrame();
+#endif
+ return renderImage;
+}
+
+QImage Qt5NodeInstanceServer::grabWindow()
+{
+ if (m_viewData.rootItem)
+ return grabRenderControl(m_viewData);
+ return {};
+}
+
void Qt5NodeInstanceServer::refreshBindings()
{
DesignerSupport::refreshExpressions(context());
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.h
index ca43363a9a8..e6a2754f997 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.h
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.h
@@ -26,12 +26,22 @@
#pragma once
#include
+#include
#include "nodeinstanceserver.h"
#include
QT_BEGIN_NAMESPACE
class QQuickItem;
+class QQmlEngine;
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+class QQuickRenderControl;
+class QRhi;
+class QRhiTexture;
+class QRhiRenderBuffer;
+class QRhiTextureRenderTarget;
+class QRhiRenderPassDescriptor;
+#endif
QT_END_NAMESPACE
namespace QmlDesigner {
@@ -44,7 +54,11 @@ public:
~Qt5NodeInstanceServer() override;
QQuickView *quickView() const override;
+ QQuickWindow *quickWindow() const override;
QQmlView *declarativeView() const override;
+ QQuickItem *rootItem() const override;
+ void setRootItem(QQuickItem *item) override;
+
QQmlEngine *engine() const override;
void refreshBindings() override;
@@ -54,16 +68,37 @@ public:
void clearScene(const ClearSceneCommand &command) override;
void reparentInstances(const ReparentInstancesCommand &command) override;
+ QImage grabWindow() override;
+
protected:
void initializeView() override;
- void resizeCanvasSizeToRootItemSize() override;
+ void resizeCanvasToRootItem() override;
void resetAllItems();
void setupScene(const CreateSceneCommand &command) override;
QList allItems() const;
+ struct RenderViewData {
+ QPointer window = nullptr;
+ QQuickItem *rootItem = nullptr;
+ QQuickItem *contentItem = nullptr;
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ bool bufferDirty = true;
+ QQuickRenderControl *renderControl = nullptr;
+ QRhi *rhi = nullptr;
+ QRhiTexture *texture = nullptr;
+ QRhiRenderBuffer *buffer = nullptr;
+ QRhiTextureRenderTarget *texTarget = nullptr;
+ QRhiRenderPassDescriptor *rpDesc = nullptr;
+#endif
+ };
+
+ virtual bool initRhi(RenderViewData &viewData);
+ virtual QImage grabRenderControl(RenderViewData &viewData);
+
private:
- QPointer m_quickView;
+ RenderViewData m_viewData;
DesignerSupport m_designerSupport;
+ QQmlEngine *m_qmlEngine = nullptr;
};
} // QmlDesigner
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5previewnodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5previewnodeinstanceserver.cpp
index ae167ad6ca3..2a34864a844 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5previewnodeinstanceserver.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5previewnodeinstanceserver.cpp
@@ -71,7 +71,7 @@ void Qt5PreviewNodeInstanceServer::collectItemChangesAndSendChangeCommands()
if (!inFunction && nodeInstanceClient()->bytesToWrite() < 10000) {
inFunction = true;
- DesignerSupport::polishItems(quickView());
+ DesignerSupport::polishItems(quickWindow());
QVector imageContainerVector;
imageContainerVector.append(ImageContainer(0, renderPreviewImage(), -1));
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp
index 4a45c626be3..bb1aa724450 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp
@@ -74,9 +74,9 @@ void Qt5RenderNodeInstanceServer::collectItemChangesAndSendChangeCommands()
if (!inFunction) {
inFunction = true;
- DesignerSupport::polishItems(quickView());
+ DesignerSupport::polishItems(quickWindow());
- if (quickView() && nodeInstanceClient()->bytesToWrite() < 10000) {
+ if (quickWindow() && nodeInstanceClient()->bytesToWrite() < 10000) {
foreach (QQuickItem *item, allItems()) {
if (item) {
if (hasInstanceForObject(item)) {
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5testnodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5testnodeinstanceserver.cpp
index a6570b4a1e9..9edb567d5ba 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5testnodeinstanceserver.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5testnodeinstanceserver.cpp
@@ -257,13 +257,13 @@ void Qt5TestNodeInstanceServer::removeSharedMemory(const RemoveSharedMemoryComma
void QmlDesigner::Qt5TestNodeInstanceServer::collectItemChangesAndSendChangeCommands()
{
- DesignerSupport::polishItems(quickView());
+ DesignerSupport::polishItems(quickWindow());
QSet informationChangedInstanceSet;
QVector propertyChangedList;
QSet parentChangedSet;
- if (quickView()) {
+ if (quickWindow()) {
foreach (QQuickItem *item, allItems()) {
if (item && hasInstanceForObject(item)) {
ServerNodeInstance instance = instanceForObject(item);
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.cpp
index e9e6328ce9e..81607cbdd6e 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.cpp
@@ -174,11 +174,10 @@ void QuickItemNodeInstance::initialize(const ObjectNodeInstance::Pointer &object
InstanceContainer::NodeFlags flags)
{
- if (instanceId() == 0) {
- DesignerSupport::setRootItem(nodeInstanceServer()->quickView(), quickItem());
- } else {
- quickItem()->setParentItem(qobject_cast(nodeInstanceServer()->quickView()->rootObject()));
- }
+ if (instanceId() == 0)
+ nodeInstanceServer()->setRootItem(quickItem());
+ else
+ quickItem()->setParentItem(nodeInstanceServer()->rootItem());
if (quickItem()->window() && checkIfRefFromEffect(instanceId())) {
designerSupport()->refFromEffectItem(quickItem(),
@@ -420,19 +419,19 @@ QImage QuickItemNodeInstance::renderImage() const
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (s_unifiedRenderPath) {
- renderImage = nodeInstanceServer()->quickView()->grabWindow();
+ renderImage = nodeInstanceServer()->quickWindow()->grabWindow();
} else {
// Fake render loop signaling to update things like QML items as 3D textures
- nodeInstanceServer()->quickView()->beforeSynchronizing();
- nodeInstanceServer()->quickView()->beforeRendering();
+ nodeInstanceServer()->quickWindow()->beforeSynchronizing();
+ nodeInstanceServer()->quickWindow()->beforeRendering();
renderImage = designerSupport()->renderImageForItem(quickItem(), renderBoundingRect, size);
- nodeInstanceServer()->quickView()->afterRendering();
+ nodeInstanceServer()->quickWindow()->afterRendering();
}
renderImage.setDevicePixelRatio(devicePixelRatio);
#else
- renderImage = nodeInstanceServer()->quickView()->grabWindow();
+ renderImage = nodeInstanceServer()->grabWindow();
renderImage = renderImage.copy(renderBoundingRect.toRect());
/* When grabbing an offscren window the device pixel ratio is 1 */
renderImage.setDevicePixelRatio(1);
@@ -452,20 +451,20 @@ QImage QuickItemNodeInstance::renderPreviewImage(const QSize &previewImageSize)
QImage image;
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (s_unifiedRenderPath) {
- image = nodeInstanceServer()->quickView()->grabWindow();
+ image = nodeInstanceServer()->quickWindow()->grabWindow();
} else {
// Fake render loop signaling to update things like QML items as 3D textures
- nodeInstanceServer()->quickView()->beforeSynchronizing();
- nodeInstanceServer()->quickView()->beforeRendering();
+ nodeInstanceServer()->quickWindow()->beforeSynchronizing();
+ nodeInstanceServer()->quickWindow()->beforeRendering();
image = designerSupport()->renderImageForItem(quickItem(),
previewItemBoundingRect,
size);
- nodeInstanceServer()->quickView()->afterRendering();
+ nodeInstanceServer()->quickWindow()->afterRendering();
}
#else
- image = nodeInstanceServer()->quickView()->grabWindow();
+ image = nodeInstanceServer()->grabWindow();
image = image.copy(previewItemBoundingRect.toRect());
#endif
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/main.cpp b/share/qtcreator/templates/wizards/projects/qtquickapplication/main.cpp
index 70ae0ef96ce..466c23fe69a 100644
--- a/share/qtcreator/templates/wizards/projects/qtquickapplication/main.cpp
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/main.cpp
@@ -11,10 +11,14 @@ int main(int argc, char *argv[])
qputenv("QT_QPA_EGLFS_PHYSICAL_WIDTH", QByteArray("213"));
qputenv("QT_QPA_EGLFS_PHYSICAL_HEIGHT", QByteArray("120"));
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+#endif
}
@else
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+#endif
@endif
QGuiApplication app(argc, argv);
diff --git a/src/libs/qmljs/parser/qmldirparser.cpp b/src/libs/qmljs/parser/qmldirparser.cpp
index ffe5edcf20d..e15d467b8fe 100644
--- a/src/libs/qmljs/parser/qmldirparser.cpp
+++ b/src/libs/qmljs/parser/qmldirparser.cpp
@@ -25,10 +25,14 @@
#include "qmldirparser_p.h"
+#include
+
#include
QT_QML_BEGIN_NAMESPACE
+using namespace LanguageUtils;
+
static int parseInt(const QStringView &str, bool *ok)
{
int pos = 0;
@@ -60,6 +64,33 @@ static bool parseVersion(const QString &str, int *major, int *minor)
return false;
}
+static ComponentVersion parseImportVersion(const QString &str)
+{
+ int minor = -1;
+ int major = -1;
+ const int dotIndex = str.indexOf(QLatin1Char('.'));
+ bool ok = false;
+ if (dotIndex != -1 && str.indexOf(QLatin1Char('.'), dotIndex + 1) == -1) {
+ major = parseInt(QStringView(str.constData(), dotIndex), &ok);
+ if (ok) {
+ if (str.length() > dotIndex + 1) {
+ minor = parseInt(QStringView(str.constData() + dotIndex + 1, str.length() - dotIndex - 1),
+ &ok);
+ if (!ok)
+ minor = ComponentVersion::NoVersion;
+ } else {
+ minor = ComponentVersion::MaxVersion;
+ }
+ }
+ } else if (str.length() > 0) {
+ QTC_ASSERT(str != QLatin1String("auto"), return ComponentVersion(-1, -1));
+ major = parseInt(QStringView(str.constData(), str.length()),
+ &ok);
+ minor = ComponentVersion::MaxVersion;
+ }
+ return ComponentVersion(major, minor);
+}
+
void QmlDirParser::clear()
{
_errors.clear();
@@ -97,6 +128,50 @@ bool QmlDirParser::parse(const QString &source)
quint16 lineNumber = 0;
bool firstLine = true;
+ auto readImport = [&](const QString *sections, int sectionCount, Import::Flags flags) {
+ Import import;
+ if (sectionCount == 2) {
+ import = Import(sections[1], ComponentVersion(), flags);
+ } else if (sectionCount == 3) {
+ if (sections[2] == QLatin1String("auto")) {
+ import = Import(sections[1], ComponentVersion(), flags | Import::Auto);
+ } else {
+ const auto version = parseImportVersion(sections[2]);
+ if (version.isValid()) {
+ import = Import(sections[1], version, flags);
+ } else {
+ reportError(lineNumber, 0,
+ QStringLiteral("invalid version %1, expected .")
+ .arg(sections[2]));
+ return false;
+ }
+ }
+ } else {
+ reportError(lineNumber, 0,
+ QStringLiteral("%1 requires 1 or 2 arguments, but %2 were provided")
+ .arg(sections[0]).arg(sectionCount - 1));
+ return false;
+ }
+ if (sections[0] == QStringLiteral("import"))
+ _imports.append(import);
+ else
+ _dependencies.append(import);
+ return true;
+ };
+
+ auto readPlugin = [&](const QString *sections, int sectionCount, bool isOptional) {
+ if (sectionCount < 2 || sectionCount > 3) {
+ reportError(lineNumber, 0, QStringLiteral("plugin directive requires one or two "
+ "arguments, but %1 were provided")
+ .arg(sectionCount - 1));
+ return false;
+ }
+
+ const Plugin entry(sections[1], sections[2], isOptional);
+ _plugins.append(entry);
+ return true;
+ };
+
const QChar *ch = source.constData();
while (!ch->isNull()) {
++lineNumber;
@@ -163,16 +238,26 @@ bool QmlDirParser::parse(const QString &source)
_typeNamespace = sections[1];
} else if (sections[0] == QLatin1String("plugin")) {
- if (sectionCount < 2 || sectionCount > 3) {
- reportError(lineNumber, 0,
- QStringLiteral("plugin directive requires one or two arguments, but %1 were provided").arg(sectionCount - 1));
-
+ if (!readPlugin(sections, sectionCount, false))
+ continue;
+ } else if (sections[0] == QLatin1String("optional")) {
+ if (sectionCount < 2) {
+ reportError(lineNumber, 0, QStringLiteral("optional directive requires further "
+ "arguments, but none were provided."));
continue;
}
- const Plugin entry(sections[1], sections[2]);
-
- _plugins.append(entry);
+ if (sections[1] == QStringLiteral("plugin")) {
+ if (!readPlugin(sections + 1, sectionCount - 1, true))
+ continue;
+ } else if (sections[1] == QLatin1String("import")) {
+ if (!readImport(sections + 1, sectionCount - 1, Import::Optional))
+ continue;
+ } else {
+ reportError(lineNumber, 0, QStringLiteral("only import and plugin can be optional, "
+ "not %1.").arg(sections[1]));
+ continue;
+ }
} else if (sections[0] == QLatin1String("classname")) {
if (sectionCount < 2) {
@@ -233,28 +318,9 @@ bool QmlDirParser::parse(const QString &source)
reportError(lineNumber, 0, QStringLiteral("designersupported does not expect any argument"));
else
_designerSupported = true;
- } else if (sections[0] == QLatin1String("depends")) {
- if (sectionCount != 3) {
- reportError(lineNumber, 0,
- QStringLiteral("depends requires 2 arguments, but %1 were provided").arg(sectionCount - 1));
+ } else if (sections[0] == QLatin1String("depends") || sections[0] == QLatin1String("import")) {
+ if (!readImport(sections, sectionCount, Import::Default))
continue;
- }
-
- int major, minor;
- if (parseVersion(sections[2], &major, &minor)) {
- Component entry(sections[1], QString(), major, minor);
- entry.internal = true;
- _dependencies.insert(entry.typeName, entry);
- } else {
- reportError(lineNumber, 0, QStringLiteral("invalid version %1, expected .").arg(sections[2]));
- }
- } else if (sections[0] == QLatin1String("import")) {
- if (sectionCount != 2) {
- reportError(lineNumber, 0,
- QStringLiteral("import requires 2 arguments, but %1 were provided").arg(sectionCount - 1));
- continue;
- }
- _imports << sections[1];
} else if (sectionCount == 2) {
// No version specified (should only be used for relative qmldir files)
const Component entry(sections[0], sections[1], -1, -1);
@@ -342,12 +408,12 @@ QMultiHash QmlDirParser::components() const
return _components;
}
-QHash QmlDirParser::dependencies() const
+QList QmlDirParser::dependencies() const
{
return _dependencies;
}
-QStringList QmlDirParser::imports() const
+QList QmlDirParser::imports() const
{
return _imports;
}
diff --git a/src/libs/qmljs/parser/qmldirparser_p.h b/src/libs/qmljs/parser/qmldirparser_p.h
index 9b26d023510..5576cfa515c 100644
--- a/src/libs/qmljs/parser/qmldirparser_p.h
+++ b/src/libs/qmljs/parser/qmldirparser_p.h
@@ -39,6 +39,9 @@
#include
#include
#include
+
+#include
+
#include "qmljs/parser/qmljsglobal_p.h"
#include "qmljs/parser/qmljsengine_p.h"
#include "qmljs/parser/qmljsdiagnosticmessage_p.h"
@@ -72,14 +75,15 @@ public:
{
Plugin() = default;
- Plugin(const QString &name, const QString &path)
- : name(name), path(path)
+ Plugin(const QString &name, const QString &path, bool optional)
+ : name(name), path(path), optional(optional)
{
checkNonRelative("Plugin", name, path);
}
QString name;
QString path;
+ bool optional = false;
};
struct Component
@@ -117,9 +121,29 @@ public:
int minorVersion = 0;
};
+ struct Import
+ {
+ enum Flag {
+ Default = 0x0,
+ Auto = 0x1, // forward the version of the importing module
+ Optional = 0x2 // is not automatically imported but only a tooling hint
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ Import() = default;
+ Import(QString module, LanguageUtils::ComponentVersion version, Flags flags)
+ : module(module), version(version), flags(flags)
+ {
+ }
+
+ QString module;
+ LanguageUtils::ComponentVersion version; // invalid version is latest version, unless Flag::Auto
+ Flags flags;
+ };
+
QMultiHash components() const;
- QHash dependencies() const;
- QStringList imports() const;
+ QList dependencies() const;
+ QList imports() const;
QList