Merge remote-tracking branch 'origin/4.14'
Conflicts: src/plugins/projectexplorer/gcctoolchain.cpp Change-Id: I2136ba89d3aa3c4c2a0e7a4f9d8ba9cec32924ce
@@ -48,3 +48,17 @@ macro.beginfloatright.HTML = "<div style=\"float: right; margin-left: 2em\">"
|
||||
macro.endfloat.HTML = "</div>"
|
||||
macro.clearfloat.HTML = "<br style=\"clear: both\" />"
|
||||
macro.emptyspan.HTML = "<span></span>"
|
||||
|
||||
# Embed YouTube content by video ID - Example: \youtube dQw4w9WgXcQ
|
||||
# Also requires a <ID>.jpg thumbnail for offline docs. In .qdocconf, add:
|
||||
#
|
||||
# HTML.extraimages += images/dQw4w9WgXcQ.jpg
|
||||
# qhp.ProjectName.extraFiles += images/dQw4w9WgXcQ.jpg
|
||||
#
|
||||
macro.youtube.HTML = "<div class=\"video\">\n<span class=\"vspan\"></span>\n" \
|
||||
"<iframe src=\"https://www.youtube.com/embed/\1\"" \
|
||||
"frameborder=\"0\" allowfullscreen>\n" \
|
||||
"<a href=\"https://www.youtube.com/watch/?v=\1\">\n"\
|
||||
"<img src=\"images/\1.jpg\"" \
|
||||
"title=\"Click to play in a browser\" /></a>\n" \
|
||||
"</iframe></div>\n"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -418,6 +418,52 @@
|
||||
optipng -o 7 -strip all doc/images/<screenshot_name>
|
||||
\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/<ID>/0.jpg}. The \e {<ID>} 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
|
||||
|
||||
@@ -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 \
|
||||
|
||||
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 228 KiB After Width: | Height: | Size: 206 KiB |
|
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 14 KiB |
@@ -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.
|
||||
|
||||
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 17 KiB |
BIN
doc/qtdesignstudio/images/videoicons/9ihYeC0YJ0M.jpg
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
BIN
doc/qtdesignstudio/images/videoicons/SsFWyUeAA_4.jpg
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
doc/qtdesignstudio/images/videoicons/ZzbucmQPU44.jpg
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
doc/qtdesignstudio/images/videoicons/aV6kFxH3Xws.jpg
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
@@ -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
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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]
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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}
|
||||
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<QByteArray> propertyNames;
|
||||
# - QList<QVariant> propertyValues;
|
||||
# - QVector<int> runningTimers;
|
||||
# - QList<QPointer<QObject> > 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<int> runningTimers;
|
||||
# - QList<QPointer<QObject> > 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 '<not available>'
|
||||
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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -45,6 +45,12 @@
|
||||
#include <QtQuick3D/private/qquick3dviewport_p.h>
|
||||
#endif
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
#include <QtGui/private/qrhi_p.h>
|
||||
#include <QtQuick/private/qquickrendercontrol_p.h>
|
||||
#include <QtQuick/private/qquickrendertarget_p.h>
|
||||
#endif
|
||||
|
||||
#include <private/qquickdesignersupportitems_p.h>
|
||||
|
||||
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<QQuick3DNode *>(iconItem)) {
|
||||
qmlRegisterType<QmlDesigner::Internal::SelectionBoxGeometry>("SelectionBoxGeometry", 1, 0, "SelectionBoxGeometry");
|
||||
QQmlComponent component(m_quickView->engine());
|
||||
QQmlComponent component(engine);
|
||||
component.loadUrl(QUrl("qrc:/qtquickplugin/mockfiles/IconRenderer3D.qml"));
|
||||
m_containerItem = qobject_cast<QQuickItem *>(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<QQuickItem *>();
|
||||
auto view3D = qobject_cast<QQuick3DViewport *>(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<const uchar *>(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;
|
||||
}
|
||||
|
||||
@@ -31,8 +31,16 @@
|
||||
#include <designersupportdelegate.h>
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
@@ -189,9 +189,14 @@ NodeInstanceServer::NodeInstanceServer(NodeInstanceClientInterface *nodeInstance
|
||||
Internal::QmlPrivateGate::registerFixResourcePathsForObjectCallBack();
|
||||
}
|
||||
|
||||
NodeInstanceServer::~NodeInstanceServer()
|
||||
{
|
||||
m_objectInstanceHash.clear();
|
||||
}
|
||||
|
||||
QList<ServerNodeInstance> NodeInstanceServer::createInstances(const QVector<InstanceContainer> &containerVector)
|
||||
{
|
||||
Q_ASSERT(declarativeView() || quickView());
|
||||
Q_ASSERT(declarativeView() || quickWindow());
|
||||
QList<ServerNodeInstance> instanceList;
|
||||
for (const InstanceContainer &instanceContainer : containerVector) {
|
||||
ServerNodeInstance instance;
|
||||
@@ -207,7 +212,6 @@ QList<ServerNodeInstance> NodeInstanceServer::createInstances(const QVector<Inst
|
||||
m_rootNodeInstance = instance;
|
||||
if (quickView())
|
||||
quickView()->setContent(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<AddImportContainer> &containerVector)
|
||||
{
|
||||
Q_ASSERT(quickView());
|
||||
Q_ASSERT(quickWindow());
|
||||
QSet<QString> 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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <QSet>
|
||||
#include <QStringList>
|
||||
#include <QPointer>
|
||||
#include <QImage>
|
||||
|
||||
#ifdef MULTILANGUAGE_TRANSLATIONPROVIDER
|
||||
#include <multilanguagelink.h>
|
||||
@@ -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<QQmlContext*> allSubContextsForObject(QObject *object);
|
||||
static QList<QObject*> allSubObjectsForObject(QObject *object);
|
||||
|
||||
virtual void resizeCanvasSizeToRootItemSize() = 0;
|
||||
virtual void resizeCanvasToRootItem() = 0;
|
||||
void setupState(qint32 stateInstanceId);
|
||||
|
||||
private:
|
||||
|
||||
@@ -70,7 +70,7 @@ void Qt5CaptureImageNodeInstanceServer::collectItemChangesAndSendChangeCommands(
|
||||
auto rooNodeInstance = rootNodeInstance();
|
||||
rooNodeInstance.rootQuickItem()->setClip(true);
|
||||
|
||||
DesignerSupport::polishItems(quickView());
|
||||
DesignerSupport::polishItems(quickWindow());
|
||||
|
||||
QImage image = renderImage(rooNodeInstance);
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ void Qt5CapturePreviewNodeInstanceServer::collectItemChangesAndSendChangeCommand
|
||||
if (!inFunction) {
|
||||
inFunction = true;
|
||||
|
||||
DesignerSupport::polishItems(quickView());
|
||||
DesignerSupport::polishItems(quickWindow());
|
||||
|
||||
QVector<CapturedDataCommand::StateData> stateDatas;
|
||||
stateDatas.push_back(collectStateData(rootNodeInstance(), nodeInstances(), 0));
|
||||
|
||||
@@ -87,6 +87,10 @@
|
||||
#include <QtGui/qevent.h>
|
||||
#include <QtGui/qguiapplication.h>
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
#include <QtQuick/private/qquickrendercontrol_p.h>
|
||||
#endif
|
||||
|
||||
#ifdef QUICK3D_MODULE
|
||||
#include <QtQuick3D/private/qquick3dnode_p.h>
|
||||
#include <QtQuick3D/private/qquick3dcamera_p.h>
|
||||
@@ -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 <QtCore/qelapsedtimer.h>
|
||||
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<QQuickView *>(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<QQuickItem *>(component.create());
|
||||
viewData.rootItem = qobject_cast<QQuickItem *>(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<QQuickView *>(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<ServerNodeInstance> &instances)
|
||||
@@ -177,6 +194,65 @@ void Qt5InformationNodeInstanceServer::updateLockedAndHiddenStates(const QSet<Se
|
||||
}
|
||||
}
|
||||
|
||||
void Qt5InformationNodeInstanceServer::handleInputEvents()
|
||||
{
|
||||
if (m_editView3DData.window) {
|
||||
int angleDelta = 0;
|
||||
for (int i = 0; i < m_pendingInputEventCommands.size(); ++i) {
|
||||
const InputEventCommand &command = m_pendingInputEventCommands[i];
|
||||
if (command.type() == QEvent::Wheel) {
|
||||
if (i < m_pendingInputEventCommands.size() - 1) {
|
||||
// Peek at next command. If that is also a wheel with same button/modifiers
|
||||
// state, skip this event and add the angle delta to the next one.
|
||||
auto nextCommand = m_pendingInputEventCommands[i + 1];
|
||||
if (nextCommand.type() == QEvent::MouseMove
|
||||
&& nextCommand.button() == command.button()
|
||||
&& nextCommand.buttons() == command.buttons()
|
||||
&& nextCommand.modifiers() == command.modifiers()) {
|
||||
angleDelta += command.angleDelta();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
QWheelEvent *we
|
||||
#if (QT_VERSION >= 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<QQuick3DCamera *>(obj)) {
|
||||
QMetaObject::invokeMethod(m_editView3DRootItem, "releaseCameraGizmo",
|
||||
QMetaObject::invokeMethod(m_editView3DData.rootItem, "releaseCameraGizmo",
|
||||
Q_ARG(QVariant, objectToVariant(obj)));
|
||||
} else if (qobject_cast<QQuick3DAbstractLight *>(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<QQuick3DCamera *>(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<QQuick3DAbstractLight *>(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<QQuickItem *>(m_editView3DContentItem)->size();
|
||||
QSizeF size = qobject_cast<QQuickItem *>(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<QQuickItem *>(m_ModelNode3DImageViewContentItem)->size();
|
||||
QSizeF size = qobject_cast<QQuickItem *>(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<bool>();
|
||||
QMetaObject::invokeMethod(m_modelNode3DImageViewData.rootItem, "afterRender");
|
||||
ready = QQmlProperty::read(m_modelNode3DImageViewData.rootItem, "ready").value<bool>();
|
||||
}
|
||||
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<ServerNodeIns
|
||||
const QHash<QString, QVariantMap> &toolStates)
|
||||
{
|
||||
#ifdef QUICK3D_MODULE
|
||||
if (!m_editView3DRootItem)
|
||||
if (!m_editView3DData.rootItem)
|
||||
return;
|
||||
|
||||
ServerNodeInstance root = rootNodeInstance();
|
||||
@@ -1142,13 +1248,13 @@ void Qt5InformationNodeInstanceServer::setup3DEditView(const QList<ServerNodeIns
|
||||
add3DViewPorts(instanceList);
|
||||
add3DScenes(instanceList);
|
||||
|
||||
QObject::connect(m_editView3DRootItem, SIGNAL(selectionChanged(QVariant)),
|
||||
QObject::connect(m_editView3DData.rootItem, SIGNAL(selectionChanged(QVariant)),
|
||||
this, SLOT(handleSelectionChanged(QVariant)));
|
||||
QObject::connect(m_editView3DRootItem, SIGNAL(commitObjectProperty(QVariant, QVariant)),
|
||||
QObject::connect(m_editView3DData.rootItem, SIGNAL(commitObjectProperty(QVariant, QVariant)),
|
||||
this, SLOT(handleObjectPropertyCommit(QVariant, QVariant)));
|
||||
QObject::connect(m_editView3DRootItem, SIGNAL(changeObjectProperty(QVariant, QVariant)),
|
||||
QObject::connect(m_editView3DData.rootItem, SIGNAL(changeObjectProperty(QVariant, QVariant)),
|
||||
this, SLOT(handleObjectPropertyChange(QVariant, QVariant)));
|
||||
QObject::connect(m_editView3DRootItem, SIGNAL(notifyActiveSceneChange()),
|
||||
QObject::connect(m_editView3DData.rootItem, SIGNAL(notifyActiveSceneChange()),
|
||||
this, SLOT(handleActiveSceneChange()));
|
||||
QObject::connect(&m_propertyChangeTimer, &QTimer::timeout,
|
||||
this, &Qt5InformationNodeInstanceServer::handleObjectPropertyChangeTimeout);
|
||||
@@ -1156,6 +1262,8 @@ void Qt5InformationNodeInstanceServer::setup3DEditView(const QList<ServerNodeIns
|
||||
this, &Qt5InformationNodeInstanceServer::handleSelectionChangeTimeout);
|
||||
QObject::connect(&m_render3DEditViewTimer, &QTimer::timeout,
|
||||
this, &Qt5InformationNodeInstanceServer::doRender3DEditView);
|
||||
QObject::connect(&m_inputEventTimer, &QTimer::timeout,
|
||||
this, &Qt5InformationNodeInstanceServer::handleInputEvents);
|
||||
|
||||
QString lastSceneId;
|
||||
auto helper = qobject_cast<QmlDesigner::Internal::GeneralHelper *>(m_3dHelper);
|
||||
@@ -1167,7 +1275,7 @@ void Qt5InformationNodeInstanceServer::setup3DEditView(const QList<ServerNodeIns
|
||||
}
|
||||
if (toolStates.contains(helper->globalStateId())) {
|
||||
if (toolStates[helper->globalStateId()].contains(helper->rootSizeKey()))
|
||||
m_editView3DRootItem->setSize(toolStates[helper->globalStateId()][helper->rootSizeKey()].value<QSize>());
|
||||
m_editView3DData.rootItem->setSize(toolStates[helper->globalStateId()][helper->rootSizeKey()].value<QSize>());
|
||||
if (toolStates[helper->globalStateId()].contains(helper->lastSceneIdKey()))
|
||||
lastSceneId = toolStates[helper->globalStateId()][helper->lastSceneIdKey()].toString();
|
||||
}
|
||||
@@ -1198,7 +1306,7 @@ void Qt5InformationNodeInstanceServer::setup3DEditView(const QList<ServerNodeIns
|
||||
if (toolStates.contains({})) {
|
||||
// Update tool state to an existing no-scene state before updating the active scene to
|
||||
// ensure the previous state is inherited properly in all cases.
|
||||
QMetaObject::invokeMethod(m_editView3DRootItem, "updateToolStates", Qt::QueuedConnection,
|
||||
QMetaObject::invokeMethod(m_editView3DData.rootItem, "updateToolStates", Qt::QueuedConnection,
|
||||
Q_ARG(QVariant, toolStates[{}]),
|
||||
Q_ARG(QVariant, QVariant::fromValue(false)));
|
||||
}
|
||||
@@ -1221,12 +1329,12 @@ void Qt5InformationNodeInstanceServer::collectItemChangesAndSendChangeCommands()
|
||||
if (!inFunction) {
|
||||
inFunction = true;
|
||||
|
||||
DesignerSupport::polishItems(quickView());
|
||||
DesignerSupport::polishItems(quickWindow());
|
||||
|
||||
QSet<ServerNodeInstance> informationChangedInstanceSet;
|
||||
QVector<InstancePropertyPair> 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<QVariantList>().size();
|
||||
int boxCount = m_editView3DData.rootItem->property("selectionBoxes").value<QVariantList>().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<QmlDesigner::Internal::GeneralHelper *>(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
|
||||
|
||||
@@ -129,19 +129,16 @@ private:
|
||||
void doRenderModelNodeImageView();
|
||||
void doRenderModelNode3DImageView();
|
||||
void doRenderModelNode2DImageView();
|
||||
QQuickView *createAuxiliaryQuickView(const QUrl &url, QQuickItem *&rootItem);
|
||||
void updateLockedAndHiddenStates(const QSet<ServerNodeInstance> &instances);
|
||||
void handleInputEvents();
|
||||
|
||||
void createAuxiliaryQuickView(const QUrl &url, RenderViewData &viewData);
|
||||
|
||||
RenderViewData m_editView3DData;
|
||||
RenderViewData m_modelNode3DImageViewData;
|
||||
RenderViewData m_modelNode2DImageViewData;
|
||||
|
||||
QPointer<QQuickView> m_editView3D;
|
||||
QQuickItem *m_editView3DRootItem = nullptr;
|
||||
QQuickItem *m_editView3DContentItem = nullptr;
|
||||
bool m_editView3DSetupDone = false;
|
||||
QPointer<QQuickView> m_ModelNode3DImageView;
|
||||
QQuickItem *m_ModelNode3DImageViewRootItem = nullptr;
|
||||
QQuickItem *m_ModelNode3DImageViewContentItem = nullptr;
|
||||
QPointer<QQuickView> m_ModelNode2DImageView;
|
||||
QQuickItem *m_ModelNode2DImageViewRootItem = nullptr;
|
||||
QQuickItem *m_ModelNode2DImageViewContentItem = nullptr;
|
||||
RequestModelNodePreviewImageCommand m_modelNodePreviewImageCommand;
|
||||
QHash<QString, QImage> m_modelNodePreviewImageCache;
|
||||
QSet<QObject *> 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<InputEventCommand> m_pendingInputEventCommands;
|
||||
QObject *m_3dHelper = nullptr;
|
||||
int m_need3DEditViewRender = 0;
|
||||
};
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
#include <QQuickItem>
|
||||
#include <QQuickView>
|
||||
#include <QQuickWindow>
|
||||
|
||||
#include <designersupportdelegate.h>
|
||||
#include <addimportcontainer.h>
|
||||
@@ -40,6 +41,14 @@
|
||||
#include <QDebug>
|
||||
#include <QOpenGLContext>
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
#include <QtGui/private/qrhi_p.h>
|
||||
#include <QtQuick/private/qquickwindow_p.h>
|
||||
#include <QtQuick/private/qsgrenderer_p.h>
|
||||
#include <QtQuick/private/qquickrendercontrol_p.h>
|
||||
#include <QtQuick/private/qquickrendertarget_p.h>
|
||||
#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<QQuickView *>(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<QQuickItem*> subItems(QQuickItem *parentItem)
|
||||
@@ -138,6 +184,127 @@ QList<QQuickItem*> Qt5NodeInstanceServer::allItems() const
|
||||
return QList<QQuickItem*>();
|
||||
}
|
||||
|
||||
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<const uchar *>(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());
|
||||
|
||||
@@ -26,12 +26,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QtQuick/qquickwindow.h>
|
||||
|
||||
#include "nodeinstanceserver.h"
|
||||
#include <designersupportdelegate.h>
|
||||
|
||||
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<QQuickItem*> allItems() const;
|
||||
|
||||
struct RenderViewData {
|
||||
QPointer<QQuickWindow> 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<QQuickView> m_quickView;
|
||||
RenderViewData m_viewData;
|
||||
DesignerSupport m_designerSupport;
|
||||
QQmlEngine *m_qmlEngine = nullptr;
|
||||
};
|
||||
|
||||
} // QmlDesigner
|
||||
|
||||
@@ -71,7 +71,7 @@ void Qt5PreviewNodeInstanceServer::collectItemChangesAndSendChangeCommands()
|
||||
if (!inFunction && nodeInstanceClient()->bytesToWrite() < 10000) {
|
||||
inFunction = true;
|
||||
|
||||
DesignerSupport::polishItems(quickView());
|
||||
DesignerSupport::polishItems(quickWindow());
|
||||
|
||||
QVector<ImageContainer> imageContainerVector;
|
||||
imageContainerVector.append(ImageContainer(0, renderPreviewImage(), -1));
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -257,13 +257,13 @@ void Qt5TestNodeInstanceServer::removeSharedMemory(const RemoveSharedMemoryComma
|
||||
|
||||
void QmlDesigner::Qt5TestNodeInstanceServer::collectItemChangesAndSendChangeCommands()
|
||||
{
|
||||
DesignerSupport::polishItems(quickView());
|
||||
DesignerSupport::polishItems(quickWindow());
|
||||
|
||||
QSet<ServerNodeInstance> informationChangedInstanceSet;
|
||||
QVector<InstancePropertyPair> propertyChangedList;
|
||||
QSet<ServerNodeInstance> parentChangedSet;
|
||||
|
||||
if (quickView()) {
|
||||
if (quickWindow()) {
|
||||
foreach (QQuickItem *item, allItems()) {
|
||||
if (item && hasInstanceForObject(item)) {
|
||||
ServerNodeInstance instance = instanceForObject(item);
|
||||
|
||||
@@ -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<QQuickItem*>(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
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -25,10 +25,14 @@
|
||||
|
||||
#include "qmldirparser_p.h"
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QtCore/QtDebug>
|
||||
|
||||
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 <major>.<minor>")
|
||||
.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 <major>.<minor>").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<QString, QmlDirParser::Component> QmlDirParser::components() const
|
||||
return _components;
|
||||
}
|
||||
|
||||
QHash<QString, QmlDirParser::Component> QmlDirParser::dependencies() const
|
||||
QList<QmlDirParser::Import> QmlDirParser::dependencies() const
|
||||
{
|
||||
return _dependencies;
|
||||
}
|
||||
|
||||
QStringList QmlDirParser::imports() const
|
||||
QList<QmlDirParser::Import> QmlDirParser::imports() const
|
||||
{
|
||||
return _imports;
|
||||
}
|
||||
|
||||
@@ -39,6 +39,9 @@
|
||||
#include <QtCore/QUrl>
|
||||
#include <QtCore/QHash>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
#include <languageutils/componentversion.h>
|
||||
|
||||
#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<QString,Component> components() const;
|
||||
QHash<QString,Component> dependencies() const;
|
||||
QStringList imports() const;
|
||||
QList<Import> dependencies() const;
|
||||
QList<Import> imports() const;
|
||||
QList<Script> scripts() const;
|
||||
QList<Plugin> plugins() const;
|
||||
bool designerSupported() const;
|
||||
@@ -145,8 +169,8 @@ private:
|
||||
QList<QmlJS::DiagnosticMessage> _errors;
|
||||
QString _typeNamespace;
|
||||
QMultiHash<QString,Component> _components;
|
||||
QHash<QString,Component> _dependencies;
|
||||
QStringList _imports;
|
||||
QList<Import> _dependencies;
|
||||
QList<Import> _imports;
|
||||
QList<Script> _scripts;
|
||||
QList<Plugin> _plugins;
|
||||
bool _designerSupported = false;
|
||||
|
||||
@@ -447,8 +447,8 @@ QByteArray LibraryInfo::calculateFingerprint() const
|
||||
|
||||
len = _imports.size();
|
||||
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
||||
foreach (const QString &import, _imports)
|
||||
hash.addData(import.toUtf8()); // import order matters, keep order-dependent
|
||||
foreach (const QmlDirParser::Import &import, _imports)
|
||||
hash.addData(import.module.toUtf8()); // import order matters, keep order-dependent
|
||||
|
||||
QByteArray res(hash.result());
|
||||
res.append('L');
|
||||
|
||||
@@ -158,7 +158,7 @@ private:
|
||||
FakeMetaObjectList _metaObjects;
|
||||
QList<ModuleApiInfo> _moduleApis;
|
||||
QStringList _dependencies; // from qmltypes "dependencies: [...]"
|
||||
QStringList _imports; // from qmldir "import" commands
|
||||
QList<QmlDirParser::Import> _imports; // from qmldir "import" commands
|
||||
QByteArray _fingerprint;
|
||||
|
||||
PluginTypeInfoStatus _dumpStatus = NoTypeInfo;
|
||||
@@ -204,10 +204,10 @@ public:
|
||||
void setDependencies(const QStringList &deps)
|
||||
{ _dependencies = deps; }
|
||||
|
||||
QStringList imports() const
|
||||
QList<QmlDirParser::Import> imports() const
|
||||
{ return _imports; }
|
||||
|
||||
void setImports(const QStringList &imports)
|
||||
void setImports(const QList<QmlDirParser::Import> &imports)
|
||||
{ _imports = imports; }
|
||||
|
||||
bool isValid() const
|
||||
|
||||
@@ -94,7 +94,8 @@ public:
|
||||
bool importLibrary(const Document::Ptr &doc,
|
||||
const QString &libraryPath,
|
||||
Import *import, ObjectValue *targetObject,
|
||||
const QString &importPath = QString());
|
||||
const QString &importPath = QString(),
|
||||
bool optional = false);
|
||||
void loadQmldirComponents(ObjectValue *import,
|
||||
LanguageUtils::ComponentVersion version,
|
||||
const LibraryInfo &libraryInfo,
|
||||
@@ -465,7 +466,9 @@ bool LinkPrivate::importLibrary(const Document::Ptr &doc,
|
||||
const QString &libraryPath,
|
||||
Import *import,
|
||||
ObjectValue *targetObject,
|
||||
const QString &importPath)
|
||||
const QString &importPath,
|
||||
bool optional
|
||||
)
|
||||
{
|
||||
const ImportInfo &importInfo = import->info;
|
||||
|
||||
@@ -486,18 +489,24 @@ bool LinkPrivate::importLibrary(const Document::Ptr &doc,
|
||||
// Note: Since this works on the same targetObject, the ModuleApi setPrototype()
|
||||
// logic will not work. But ModuleApi isn't used in Qt versions that use import
|
||||
// commands in qmldir files, and is pending removal in Qt 6.
|
||||
for (const auto &importName : libraryInfo.imports()) {
|
||||
for (const auto &toImport : libraryInfo.imports()) {
|
||||
QString importName = toImport.module;
|
||||
ComponentVersion vNow = toImport.version;
|
||||
// there was a period in which no version == auto, should we add || !vNow.isValid() to the if?
|
||||
if (toImport.flags & QmlDirParser::Import::Auto)
|
||||
vNow = version;
|
||||
Import subImport;
|
||||
subImport.valid = true;
|
||||
subImport.info = ImportInfo::moduleImport(importName, version, importInfo.as(), importInfo.ast());
|
||||
subImport.libraryPath = modulePath(importName, version.toString(), m_importPaths);
|
||||
bool subImportFound = importLibrary(doc, subImport.libraryPath, &subImport, targetObject, importPath);
|
||||
subImport.info = ImportInfo::moduleImport(importName, vNow, importInfo.as(), importInfo.ast());
|
||||
subImport.libraryPath = modulePath(importName, vNow.toString(), m_importPaths);
|
||||
bool subImportFound = importLibrary(doc, subImport.libraryPath, &subImport, targetObject, importPath, true);
|
||||
|
||||
if (!subImportFound && errorLoc.isValid()) {
|
||||
import->valid = false;
|
||||
error(doc, errorLoc,
|
||||
Link::tr(
|
||||
"Implicit import '%1' of QML module '%2' not found.\n\n"
|
||||
if (!(optional || (toImport.flags & QmlDirParser::Import::Optional)))
|
||||
error(doc, errorLoc,
|
||||
Link::tr(
|
||||
"Implicit import '%1' of QML module '%2' not found.\n\n"
|
||||
"Import paths:\n"
|
||||
"%3\n\n"
|
||||
"For qmake projects, use the QML_IMPORT_PATH variable to add import paths.\n"
|
||||
@@ -529,11 +538,11 @@ bool LinkPrivate::importLibrary(const Document::Ptr &doc,
|
||||
QString(), version.toString());
|
||||
}
|
||||
}
|
||||
if (errorLoc.isValid()) {
|
||||
if (!optional && errorLoc.isValid()) {
|
||||
appendDiagnostic(doc, DiagnosticMessage(
|
||||
Severity::ReadingTypeInfoWarning, errorLoc,
|
||||
Link::tr("QML module contains C++ plugins, "
|
||||
"currently reading type information...")));
|
||||
"currently reading type information... %1").arg(import->info.name())));
|
||||
import->valid = false;
|
||||
}
|
||||
} else if (libraryInfo.pluginTypeInfoStatus() == LibraryInfo::DumpError
|
||||
@@ -541,7 +550,7 @@ bool LinkPrivate::importLibrary(const Document::Ptr &doc,
|
||||
// Only underline import if package isn't described in .qmltypes anyway
|
||||
// and is not a private package
|
||||
QString packageName = importInfo.name();
|
||||
if (errorLoc.isValid()
|
||||
if (!optional && errorLoc.isValid()
|
||||
&& (packageName.isEmpty()
|
||||
|| !m_valueOwner->cppQmlTypes().hasModule(packageName))
|
||||
&& !packageName.endsWith(QLatin1String("private"), Qt::CaseInsensitive)) {
|
||||
|
||||
@@ -554,11 +554,12 @@ static void applyQt515MissingImportWorkaround(const QString &path, LibraryInfo &
|
||||
return;
|
||||
|
||||
if (isQtQuick) {
|
||||
info.setImports(QStringList(QStringLiteral("QtQml")));
|
||||
info.setImports(QList<QmlDirParser::Import>(
|
||||
{QmlDirParser::Import("QtQml", ComponentVersion(), {})}));
|
||||
} else if (isQtQml) {
|
||||
info.setImports(QStringList(
|
||||
{ QStringLiteral("QtQml.Models"),
|
||||
QStringLiteral("QtQml.WorkerScript") }));
|
||||
info.setImports(QList<QmlDirParser::Import>(
|
||||
{ QmlDirParser::Import("QtQml.Models", ComponentVersion(), {}),
|
||||
QmlDirParser::Import("QtQml.WorkerScript", ComponentVersion(), {}) }));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -490,8 +490,7 @@ AndroidBuildApkStep::AndroidBuildApkStep(BuildStepList *parent, Utils::Id id)
|
||||
sdkManager()->latestAndroidSdkPlatform()))
|
||||
{
|
||||
setImmutable(true);
|
||||
setDisplayName("<b>" + tr("Build Android APK") + "</b>");
|
||||
setSummaryText(displayName());
|
||||
setDisplayName(tr("Build Android APK"));
|
||||
}
|
||||
|
||||
bool AndroidBuildApkStep::init()
|
||||
@@ -899,6 +898,9 @@ void AndroidBuildApkStep::stdError(const QString &output)
|
||||
QString newOutput = output;
|
||||
newOutput.remove(QRegularExpression("^(\\n)+"));
|
||||
|
||||
if (newOutput.isEmpty())
|
||||
return;
|
||||
|
||||
if (newOutput.startsWith("warning", Qt::CaseInsensitive)
|
||||
|| newOutput.startsWith("note", Qt::CaseInsensitive))
|
||||
TaskHub::addTask(BuildSystemTask(Task::Warning, newOutput));
|
||||
|
||||
@@ -556,6 +556,9 @@ void AndroidDeployQtStep::stdError(const QString &line)
|
||||
QString newOutput = line;
|
||||
newOutput.remove(QRegularExpression("^(\\n)+"));
|
||||
|
||||
if (newOutput.isEmpty())
|
||||
return;
|
||||
|
||||
if (newOutput.startsWith("warning", Qt::CaseInsensitive)
|
||||
|| newOutput.startsWith("note", Qt::CaseInsensitive))
|
||||
TaskHub::addTask(DeploymentTask(Task::Warning, newOutput));
|
||||
|
||||
@@ -255,6 +255,17 @@ static QImage scaleWithoutStretching(const QImage& original, const QSize& target
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool similarFilesExist(const QString &path)
|
||||
{
|
||||
QFileInfo fileInfo(path);
|
||||
QDir imageDir(fileInfo.absolutePath());
|
||||
QString baseName(fileInfo.completeBaseName());
|
||||
baseName.append(QLatin1String(".*"));
|
||||
imageDir.setNameFilters({baseName});
|
||||
auto entries = imageDir.entryList();
|
||||
return !entries.empty();
|
||||
}
|
||||
|
||||
void AndroidManifestEditorIconWidget::copyIcon()
|
||||
{
|
||||
if (m_targetIconPath.isEmpty())
|
||||
@@ -269,7 +280,8 @@ void AndroidManifestEditorIconWidget::copyIcon()
|
||||
if (m_iconPath != targetPath)
|
||||
removeIcon();
|
||||
if (original.isNull()) {
|
||||
m_iconPath.clear();
|
||||
if (!similarFilesExist(m_iconPath))
|
||||
m_iconPath.clear();
|
||||
return;
|
||||
}
|
||||
if (m_iconPath == targetPath)
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
#include "androidsdkdownloader.h"
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
|
||||
#include <QDir>
|
||||
#include <QDirIterator>
|
||||
#include <QLoggingCategory>
|
||||
@@ -85,8 +87,9 @@ void AndroidSdkDownloader::downloadAndExtractSdk(const QString &jdkPath, const Q
|
||||
connect(m_reply, &QNetworkReply::sslErrors, this, &AndroidSdkDownloader::sslErrors);
|
||||
#endif
|
||||
|
||||
m_progressDialog = new QProgressDialog(tr("Downloading SDK Tools package..."), tr("Cancel"), 0, 100);
|
||||
m_progressDialog->setWindowModality(Qt::WindowModal);
|
||||
m_progressDialog = new QProgressDialog(tr("Downloading SDK Tools package..."), tr("Cancel"),
|
||||
0, 100, Core::ICore::dialogParent());
|
||||
m_progressDialog->setWindowModality(Qt::ApplicationModal);
|
||||
m_progressDialog->setWindowTitle(dialogTitle());
|
||||
m_progressDialog->setFixedSize(m_progressDialog->sizeHint());
|
||||
|
||||
|
||||
@@ -331,11 +331,6 @@ ToolChain::MacroInspectionRunner IarToolChain::createMacroInspectionRunner() con
|
||||
};
|
||||
}
|
||||
|
||||
Macros IarToolChain::predefinedMacros(const QStringList &cxxflags) const
|
||||
{
|
||||
return createMacroInspectionRunner()(cxxflags).macros;
|
||||
}
|
||||
|
||||
Utils::LanguageExtensions IarToolChain::languageExtensions(const QStringList &) const
|
||||
{
|
||||
return LanguageExtension::None;
|
||||
@@ -371,13 +366,6 @@ ToolChain::BuiltInHeaderPathsRunner IarToolChain::createBuiltInHeaderPathsRunner
|
||||
};
|
||||
}
|
||||
|
||||
HeaderPaths IarToolChain::builtInHeaderPaths(const QStringList &cxxFlags,
|
||||
const FilePath &fileName,
|
||||
const Environment &env) const
|
||||
{
|
||||
return createBuiltInHeaderPathsRunner(env)(cxxFlags, fileName.toString(), "");
|
||||
}
|
||||
|
||||
void IarToolChain::addToEnvironment(Environment &env) const
|
||||
{
|
||||
if (!compilerCommand().isEmpty()) {
|
||||
|
||||
@@ -56,15 +56,11 @@ public:
|
||||
bool isValid() const final;
|
||||
|
||||
MacroInspectionRunner createMacroInspectionRunner() const final;
|
||||
ProjectExplorer::Macros predefinedMacros(const QStringList &cxxflags) const final;
|
||||
|
||||
Utils::LanguageExtensions languageExtensions(const QStringList &cxxflags) const final;
|
||||
Utils::WarningFlags warningFlags(const QStringList &cxxflags) const final;
|
||||
|
||||
BuiltInHeaderPathsRunner createBuiltInHeaderPathsRunner(const Utils::Environment &) const final;
|
||||
ProjectExplorer::HeaderPaths builtInHeaderPaths(const QStringList &cxxFlags,
|
||||
const Utils::FilePath &,
|
||||
const Utils::Environment &env) const final;
|
||||
void addToEnvironment(Utils::Environment &env) const final;
|
||||
QList<Utils::OutputLineParser *> createOutputParsers() const final;
|
||||
|
||||
|
||||
@@ -462,11 +462,6 @@ ToolChain::MacroInspectionRunner KeilToolChain::createMacroInspectionRunner() co
|
||||
};
|
||||
}
|
||||
|
||||
Macros KeilToolChain::predefinedMacros(const QStringList &cxxflags) const
|
||||
{
|
||||
return createMacroInspectionRunner()(cxxflags).macros;
|
||||
}
|
||||
|
||||
Utils::LanguageExtensions KeilToolChain::languageExtensions(const QStringList &) const
|
||||
{
|
||||
return LanguageExtension::None;
|
||||
@@ -496,13 +491,6 @@ ToolChain::BuiltInHeaderPathsRunner KeilToolChain::createBuiltInHeaderPathsRunne
|
||||
};
|
||||
}
|
||||
|
||||
HeaderPaths KeilToolChain::builtInHeaderPaths(const QStringList &cxxFlags,
|
||||
const FilePath &fileName,
|
||||
const Environment &env) const
|
||||
{
|
||||
return createBuiltInHeaderPathsRunner(env)(cxxFlags, fileName.toString(), "");
|
||||
}
|
||||
|
||||
void KeilToolChain::addToEnvironment(Environment &env) const
|
||||
{
|
||||
if (!compilerCommand().isEmpty()) {
|
||||
|
||||
@@ -56,16 +56,12 @@ public:
|
||||
bool isValid() const final;
|
||||
|
||||
MacroInspectionRunner createMacroInspectionRunner() const final;
|
||||
ProjectExplorer::Macros predefinedMacros(const QStringList &cxxflags) const final;
|
||||
|
||||
Utils::LanguageExtensions languageExtensions(const QStringList &cxxflags) const final;
|
||||
Utils::WarningFlags warningFlags(const QStringList &cxxflags) const final;
|
||||
|
||||
BuiltInHeaderPathsRunner createBuiltInHeaderPathsRunner(
|
||||
const Utils::Environment &) const final;
|
||||
ProjectExplorer::HeaderPaths builtInHeaderPaths(const QStringList &cxxFlags,
|
||||
const Utils::FilePath &,
|
||||
const Utils::Environment &env) const final;
|
||||
void addToEnvironment(Utils::Environment &env) const final;
|
||||
QList<Utils::OutputLineParser *> createOutputParsers() const final;
|
||||
|
||||
|
||||
@@ -248,11 +248,6 @@ ToolChain::MacroInspectionRunner SdccToolChain::createMacroInspectionRunner() co
|
||||
};
|
||||
}
|
||||
|
||||
Macros SdccToolChain::predefinedMacros(const QStringList &cxxflags) const
|
||||
{
|
||||
return createMacroInspectionRunner()(cxxflags).macros;
|
||||
}
|
||||
|
||||
Utils::LanguageExtensions SdccToolChain::languageExtensions(const QStringList &) const
|
||||
{
|
||||
return LanguageExtension::None;
|
||||
@@ -278,13 +273,6 @@ ToolChain::BuiltInHeaderPathsRunner SdccToolChain::createBuiltInHeaderPathsRunne
|
||||
};
|
||||
}
|
||||
|
||||
HeaderPaths SdccToolChain::builtInHeaderPaths(const QStringList &cxxFlags,
|
||||
const FilePath &fileName,
|
||||
const Environment &env) const
|
||||
{
|
||||
return createBuiltInHeaderPathsRunner(env)(cxxFlags, fileName.toString(), "");
|
||||
}
|
||||
|
||||
void SdccToolChain::addToEnvironment(Environment &env) const
|
||||
{
|
||||
if (!compilerCommand().isEmpty()) {
|
||||
|
||||
@@ -55,16 +55,12 @@ public:
|
||||
bool isValid() const final;
|
||||
|
||||
MacroInspectionRunner createMacroInspectionRunner() const final;
|
||||
ProjectExplorer::Macros predefinedMacros(const QStringList &cxxflags) const final;
|
||||
|
||||
Utils::LanguageExtensions languageExtensions(const QStringList &cxxflags) const final;
|
||||
Utils::WarningFlags warningFlags(const QStringList &cxxflags) const final;
|
||||
|
||||
BuiltInHeaderPathsRunner createBuiltInHeaderPathsRunner(
|
||||
const Utils::Environment &) const final;
|
||||
ProjectExplorer::HeaderPaths builtInHeaderPaths(const QStringList &cxxFlags,
|
||||
const Utils::FilePath &,
|
||||
const Utils::Environment &env) const final;
|
||||
void addToEnvironment(Utils::Environment &env) const final;
|
||||
QList<Utils::OutputLineParser *> createOutputParsers() const final;
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ using namespace Core;
|
||||
namespace BinEditor {
|
||||
namespace Internal {
|
||||
|
||||
const QChar MidpointChar = QLatin1Char(0xB7);
|
||||
const QChar MidpointChar(u'\u00B7');
|
||||
|
||||
static QByteArray calculateHexPattern(const QByteArray &pattern)
|
||||
{
|
||||
|
||||
@@ -837,12 +837,16 @@ FilePath CMakeBuildSystem::workDirectory(const BuildDirParameters ¶meters)
|
||||
{
|
||||
const Utils::FilePath bdir = parameters.buildDirectory;
|
||||
const CMakeTool *cmake = parameters.cmakeTool();
|
||||
|
||||
// use the build directory if it already exists anyhow
|
||||
if (bdir.exists()) {
|
||||
m_buildDirToTempDir.erase(bdir);
|
||||
return bdir;
|
||||
}
|
||||
|
||||
if (cmake && cmake->autoCreateBuildDirectory()) {
|
||||
// use the build directory if the cmake tool settings are set to automatically create them,
|
||||
// or if the configuration was changed by the user
|
||||
if ((cmake && cmake->autoCreateBuildDirectory()) || !parameters.extraCMakeArguments.isEmpty()) {
|
||||
if (!cmakeBuildConfiguration()->createBuildDirectory())
|
||||
handleParsingFailed(
|
||||
tr("Failed to create build directory \"%1\".").arg(bdir.toUserOutput()));
|
||||
|
||||
@@ -153,6 +153,9 @@ OutputWindow::OutputWindow(Context context, const QString &settingsKey, QWidget
|
||||
EditorManager::openEditorAt(fp.toString(), line, column);
|
||||
});
|
||||
|
||||
connect(verticalScrollBar(), &QAbstractSlider::sliderMoved,
|
||||
this, &OutputWindow::updateAutoScroll);
|
||||
|
||||
undoAction->setEnabled(false);
|
||||
redoAction->setEnabled(false);
|
||||
cutAction->setEnabled(false);
|
||||
@@ -219,9 +222,8 @@ void OutputWindow::resizeEvent(QResizeEvent *e)
|
||||
{
|
||||
//Keep scrollbar at bottom of window while resizing, to ensure we keep scrolling
|
||||
//This can happen if window is resized while building, or if the horizontal scrollbar appears
|
||||
bool atBottom = isScrollbarAtBottom();
|
||||
QPlainTextEdit::resizeEvent(e);
|
||||
if (atBottom)
|
||||
if (d->scrollToBottom)
|
||||
scrollToBottom();
|
||||
}
|
||||
|
||||
@@ -252,7 +254,6 @@ void OutputWindow::showEvent(QShowEvent *e)
|
||||
QPlainTextEdit::showEvent(e);
|
||||
if (d->scrollToBottom)
|
||||
verticalScrollBar()->setValue(verticalScrollBar()->maximum());
|
||||
d->scrollToBottom = false;
|
||||
}
|
||||
|
||||
void OutputWindow::wheelEvent(QWheelEvent *e)
|
||||
@@ -272,6 +273,7 @@ void OutputWindow::wheelEvent(QWheelEvent *e)
|
||||
}
|
||||
}
|
||||
QAbstractScrollArea::wheelEvent(e);
|
||||
updateAutoScroll();
|
||||
updateMicroFocus();
|
||||
}
|
||||
|
||||
@@ -348,8 +350,6 @@ void OutputWindow::updateFilterProperties(
|
||||
|
||||
void OutputWindow::filterNewContent()
|
||||
{
|
||||
bool atBottom = isScrollbarAtBottom();
|
||||
|
||||
QTextBlock lastBlock = document()->findBlockByNumber(d->lastFilteredBlockNumber);
|
||||
if (!lastBlock.isValid())
|
||||
lastBlock = document()->begin();
|
||||
@@ -381,7 +381,7 @@ void OutputWindow::filterNewContent()
|
||||
// FIXME: Why on earth is this necessary? We should probably do something else instead...
|
||||
setDocument(document());
|
||||
|
||||
if (atBottom)
|
||||
if (d->scrollToBottom)
|
||||
scrollToBottom();
|
||||
}
|
||||
|
||||
@@ -432,11 +432,9 @@ void OutputWindow::handleOutputChunk(const QString &output, OutputFormat format)
|
||||
}
|
||||
}
|
||||
|
||||
const bool atBottom = isScrollbarAtBottom() || d->scrollTimer.isActive();
|
||||
d->scrollToBottom = true;
|
||||
d->formatter.appendMessage(out, format);
|
||||
|
||||
if (atBottom) {
|
||||
if (d->scrollToBottom) {
|
||||
if (d->lastMessage.elapsed() < 5) {
|
||||
d->scrollTimer.start();
|
||||
} else {
|
||||
@@ -449,6 +447,11 @@ void OutputWindow::handleOutputChunk(const QString &output, OutputFormat format)
|
||||
enableUndoRedo();
|
||||
}
|
||||
|
||||
void OutputWindow::updateAutoScroll()
|
||||
{
|
||||
d->scrollToBottom = isScrollbarAtBottom();
|
||||
}
|
||||
|
||||
void OutputWindow::setMaxCharCount(int count)
|
||||
{
|
||||
d->maxCharCount = count;
|
||||
@@ -505,6 +508,7 @@ QMimeData *OutputWindow::createMimeDataFromSelection() const
|
||||
void OutputWindow::clear()
|
||||
{
|
||||
d->formatter.clear();
|
||||
d->scrollToBottom = true;
|
||||
}
|
||||
|
||||
void OutputWindow::flush()
|
||||
|
||||
@@ -109,6 +109,7 @@ private:
|
||||
void filterNewContent();
|
||||
void handleNextOutputChunk();
|
||||
void handleOutputChunk(const QString &output, Utils::OutputFormat format);
|
||||
void updateAutoScroll();
|
||||
|
||||
Internal::OutputWindowPrivate *d = nullptr;
|
||||
};
|
||||
|
||||
@@ -43,9 +43,9 @@ static QByteArray overwrittenToolchainDefines(const ProjectPart &projectPart)
|
||||
// MSVC's predefined macros like __FUNCSIG__ expand to itself.
|
||||
// We can't parse this, so redefine to the empty string literal.
|
||||
if (projectPart.toolchainType == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) {
|
||||
defines += "#define __FUNCSIG__ \"\"\n"
|
||||
"#define __FUNCDNAME__ \"\"\n"
|
||||
"#define __FUNCTION__ \"\"\n";
|
||||
defines += "#define __FUNCSIG__ \"void __cdecl someLegalAndLongishFunctionNameThatWorksAroundQTCREATORBUG-24580(void)\"\n"
|
||||
"#define __FUNCDNAME__ \"?someLegalAndLongishFunctionNameThatWorksAroundQTCREATORBUG-24580@@YAXXZ\"\n"
|
||||
"#define __FUNCTION__ \"someLegalAndLongishFunctionNameThatWorksAroundQTCREATORBUG-24580\"\n";
|
||||
}
|
||||
|
||||
return defines;
|
||||
|
||||
@@ -356,7 +356,7 @@ void CompilerOptionsBuilder::addHeaderPathOptions()
|
||||
for (const HeaderPath &headerPath : filter.systemHeaderPaths)
|
||||
addIncludeDirOptionForPath(headerPath);
|
||||
|
||||
if (m_useTweakedHeaderPaths == UseTweakedHeaderPaths::Yes) {
|
||||
if (m_useTweakedHeaderPaths != UseTweakedHeaderPaths::No) {
|
||||
QTC_CHECK(!m_clangVersion.isEmpty()
|
||||
&& "Clang resource directory is required with UseTweakedHeaderPaths::Yes.");
|
||||
|
||||
@@ -657,9 +657,9 @@ void CompilerOptionsBuilder::undefineCppLanguageFeatureMacrosForMsvc2015()
|
||||
void CompilerOptionsBuilder::addDefineFunctionMacrosMsvc()
|
||||
{
|
||||
if (m_projectPart.toolchainType == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) {
|
||||
addMacros({{"__FUNCSIG__", "\"\""},
|
||||
{"__FUNCTION__", "\"\""},
|
||||
{"__FUNCDNAME__", "\"\""}});
|
||||
addMacros({{"__FUNCSIG__", "\"void __cdecl someLegalAndLongishFunctionNameThatWorksAroundQTCREATORBUG-24580(void)\""},
|
||||
{"__FUNCTION__", "\"someLegalAndLongishFunctionNameThatWorksAroundQTCREATORBUG-24580\""},
|
||||
{"__FUNCDNAME__", "\"?someLegalAndLongishFunctionNameThatWorksAroundQTCREATORBUG-24580@@YAXXZ\""}});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -108,9 +108,8 @@ bool FileIterationOrder::isValid() const
|
||||
|
||||
static int commonPrefixLength(const QString &filePath1, const QString &filePath2)
|
||||
{
|
||||
const auto mismatches = std::mismatch(filePath1.begin(),
|
||||
filePath1.end(),
|
||||
filePath2.begin());
|
||||
const auto mismatches = std::mismatch(filePath1.begin(), filePath1.end(),
|
||||
filePath2.begin(), filePath2.end());
|
||||
return mismatches.first - filePath1.begin();
|
||||
}
|
||||
|
||||
|
||||
@@ -4165,7 +4165,7 @@ void GdbEngine::setupInferior()
|
||||
}
|
||||
|
||||
if (!symbolFile.isEmpty()) {
|
||||
runCommand({"-file-symbol-file \"" + symbolFile + '"',
|
||||
runCommand({"-file-exec-and-symbols \"" + symbolFile + '"',
|
||||
CB(handleFileExecAndSymbols)});
|
||||
}
|
||||
|
||||
@@ -4197,7 +4197,7 @@ void GdbEngine::setupInferior()
|
||||
// Do that first, otherwise no symbols are loaded.
|
||||
QFileInfo fi = executable.toFileInfo();
|
||||
QString path = fi.absoluteFilePath();
|
||||
runCommand({"-file-exec-and-symbols \"" + path + '"',
|
||||
runCommand({"-file-symbol-file \"" + path + '"',
|
||||
CB(handleFileExecAndSymbols)});
|
||||
|
||||
} else if (isTermEngine()) {
|
||||
|
||||
@@ -66,11 +66,6 @@ ToolChain::MacroInspectionRunner NimToolChain::createMacroInspectionRunner() con
|
||||
return ToolChain::MacroInspectionRunner();
|
||||
}
|
||||
|
||||
Macros NimToolChain::predefinedMacros(const QStringList &) const
|
||||
{
|
||||
return Macros();
|
||||
}
|
||||
|
||||
LanguageExtensions NimToolChain::languageExtensions(const QStringList &) const
|
||||
{
|
||||
return LanguageExtension::None;
|
||||
@@ -87,12 +82,6 @@ ToolChain::BuiltInHeaderPathsRunner NimToolChain::createBuiltInHeaderPathsRunner
|
||||
return ToolChain::BuiltInHeaderPathsRunner();
|
||||
}
|
||||
|
||||
HeaderPaths NimToolChain::builtInHeaderPaths(const QStringList &, const FilePath &,
|
||||
const Environment &) const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
void NimToolChain::addToEnvironment(Environment &env) const
|
||||
{
|
||||
if (isValid())
|
||||
|
||||
@@ -41,15 +41,11 @@ public:
|
||||
bool isValid() const override;
|
||||
|
||||
MacroInspectionRunner createMacroInspectionRunner() const override;
|
||||
ProjectExplorer::Macros predefinedMacros(const QStringList &flags) const final;
|
||||
Utils::LanguageExtensions languageExtensions(const QStringList &flags) const final;
|
||||
Utils::WarningFlags warningFlags(const QStringList &flags) const final;
|
||||
|
||||
BuiltInHeaderPathsRunner createBuiltInHeaderPathsRunner(
|
||||
const Utils::Environment &) const override;
|
||||
ProjectExplorer::HeaderPaths builtInHeaderPaths(const QStringList &flags,
|
||||
const Utils::FilePath &sysRoot,
|
||||
const Utils::Environment &) const final;
|
||||
void addToEnvironment(Utils::Environment &env) const final;
|
||||
Utils::FilePath makeCommand(const Utils::Environment &env) const final;
|
||||
QString compilerVersion() const;
|
||||
|
||||
@@ -109,11 +109,6 @@ ToolChain::MacroInspectionRunner CustomToolChain::createMacroInspectionRunner()
|
||||
};
|
||||
}
|
||||
|
||||
Macros CustomToolChain::predefinedMacros(const QStringList &cxxflags) const
|
||||
{
|
||||
return createMacroInspectionRunner()(cxxflags).macros;
|
||||
}
|
||||
|
||||
Utils::LanguageExtensions CustomToolChain::languageExtensions(const QStringList &) const
|
||||
{
|
||||
return LanguageExtension::None;
|
||||
@@ -156,13 +151,6 @@ ToolChain::BuiltInHeaderPathsRunner CustomToolChain::createBuiltInHeaderPathsRun
|
||||
};
|
||||
}
|
||||
|
||||
HeaderPaths CustomToolChain::builtInHeaderPaths(const QStringList &cxxFlags,
|
||||
const FilePath &fileName,
|
||||
const Environment &env) const
|
||||
{
|
||||
return createBuiltInHeaderPathsRunner(env)(cxxFlags, fileName.toString(), "");
|
||||
}
|
||||
|
||||
void CustomToolChain::addToEnvironment(Environment &env) const
|
||||
{
|
||||
if (!m_compilerCommand.isEmpty()) {
|
||||
|
||||
@@ -67,7 +67,6 @@ public:
|
||||
bool isValid() const override;
|
||||
|
||||
MacroInspectionRunner createMacroInspectionRunner() const override;
|
||||
Macros predefinedMacros(const QStringList &cxxflags) const override;
|
||||
Utils::LanguageExtensions languageExtensions(const QStringList &cxxflags) const override;
|
||||
Utils::WarningFlags warningFlags(const QStringList &cxxflags) const override;
|
||||
const Macros &rawPredefinedMacros() const;
|
||||
@@ -75,9 +74,6 @@ public:
|
||||
|
||||
BuiltInHeaderPathsRunner createBuiltInHeaderPathsRunner(
|
||||
const Utils::Environment &) const override;
|
||||
HeaderPaths builtInHeaderPaths(const QStringList &cxxFlags,
|
||||
const Utils::FilePath &,
|
||||
const Utils::Environment &env) const override;
|
||||
void addToEnvironment(Utils::Environment &env) const override;
|
||||
QStringList suggestedMkspecList() const override;
|
||||
QList<Utils::OutputLineParser *> createOutputParsers() const override;
|
||||
|
||||
@@ -427,7 +427,16 @@ ToolChain::MacroInspectionRunner GccToolChain::createMacroInspectionRunner() con
|
||||
MacrosCache macroCache = predefinedMacrosCache();
|
||||
Utils::Id lang = language();
|
||||
|
||||
// This runner must be thread-safe!
|
||||
/*
|
||||
* Asks compiler for set of predefined macros
|
||||
* flags are the compiler flags collected from project settings
|
||||
* returns the list of defines, one per line, e.g. "#define __GXX_WEAK__ 1"
|
||||
* Note: changing compiler flags sometimes changes macros set, e.g. -fopenmp
|
||||
* adds _OPENMP macro, for full list of macro search by word "when" on this page:
|
||||
* http://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
|
||||
*
|
||||
* This runner must be thread-safe!
|
||||
*/
|
||||
return [env, compilerCommand = compilerCommand(),
|
||||
platformCodeGenFlags, reinterpretOptions, macroCache, lang]
|
||||
(const QStringList &flags) {
|
||||
@@ -458,20 +467,6 @@ ToolChain::MacroInspectionRunner GccToolChain::createMacroInspectionRunner() con
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Asks compiler for set of predefined macros
|
||||
* @param cxxflags - compiler flags collected from project settings
|
||||
* @return defines list, one per line, e.g. "#define __GXX_WEAK__ 1"
|
||||
*
|
||||
* @note changing compiler flags sometimes changes macros set, e.g. -fopenmp
|
||||
* adds _OPENMP macro, for full list of macro search by word "when" on this page:
|
||||
* http://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
|
||||
*/
|
||||
ProjectExplorer::Macros GccToolChain::predefinedMacros(const QStringList &cxxflags) const
|
||||
{
|
||||
return createMacroInspectionRunner()(cxxflags).macros;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Parses gcc flags -std=*, -fopenmp, -fms-extensions.
|
||||
* @see http://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html
|
||||
@@ -645,16 +640,6 @@ ToolChain::BuiltInHeaderPathsRunner GccToolChain::createBuiltInHeaderPathsRunner
|
||||
};
|
||||
}
|
||||
|
||||
HeaderPaths GccToolChain::builtInHeaderPaths(const QStringList &flags,
|
||||
const FilePath &sysRootPath,
|
||||
const Environment &env) const
|
||||
{
|
||||
return createBuiltInHeaderPathsRunner(env)(flags,
|
||||
sysRootPath.isEmpty() ? sysRoot()
|
||||
: sysRootPath.toString(),
|
||||
originalTargetTriple());
|
||||
}
|
||||
|
||||
void GccToolChain::addCommandPathToEnvironment(const FilePath &command, Environment &env)
|
||||
{
|
||||
const Utils::FilePath compilerDir = command.parentDir();
|
||||
@@ -845,7 +830,7 @@ GccToolChain::DetectedAbisResult GccToolChain::detectSupportedAbis() const
|
||||
{
|
||||
Environment env = Environment::systemEnvironment();
|
||||
addToEnvironment(env);
|
||||
ProjectExplorer::Macros macros = predefinedMacros(QStringList());
|
||||
ProjectExplorer::Macros macros = createMacroInspectionRunner()({}).macros;
|
||||
return guessGccAbi(findLocalCompiler(compilerCommand(), env),
|
||||
env.toStringList(),
|
||||
macros,
|
||||
|
||||
@@ -83,12 +83,7 @@ public:
|
||||
const QString &directoryPath) const override;
|
||||
|
||||
MacroInspectionRunner createMacroInspectionRunner() const override;
|
||||
Macros predefinedMacros(const QStringList &cxxflags) const override;
|
||||
|
||||
BuiltInHeaderPathsRunner createBuiltInHeaderPathsRunner(const Utils::Environment &env) const override;
|
||||
HeaderPaths builtInHeaderPaths(const QStringList &flags,
|
||||
const Utils::FilePath &sysRootPath,
|
||||
const Utils::Environment &env) const override;
|
||||
|
||||
void addToEnvironment(Utils::Environment &env) const override;
|
||||
Utils::FilePath makeCommand(const Utils::Environment &environment) const override;
|
||||
|
||||
@@ -591,10 +591,10 @@ Macros MsvcToolChain::msvcPredefinedMacros(const QStringList &cxxflags,
|
||||
|
||||
QStringList toProcess;
|
||||
for (const QString &arg : cxxflags) {
|
||||
if (arg.startsWith(QLatin1String("/D"))) {
|
||||
if (arg.startsWith("/D") || arg.startsWith("-D")) {
|
||||
const QString define = arg.mid(2);
|
||||
predefinedMacros.append(Macro::fromKeyValue(define));
|
||||
} else if (arg.startsWith(QLatin1String("/U"))) {
|
||||
} else if (arg.startsWith("/U") || arg.startsWith("-U")) {
|
||||
predefinedMacros.append(
|
||||
{arg.mid(2).toLocal8Bit(), ProjectExplorer::MacroType::Undefine});
|
||||
} else {
|
||||
@@ -991,11 +991,6 @@ ToolChain::MacroInspectionRunner MsvcToolChain::createMacroInspectionRunner() co
|
||||
};
|
||||
}
|
||||
|
||||
Macros MsvcToolChain::predefinedMacros(const QStringList &cxxflags) const
|
||||
{
|
||||
return createMacroInspectionRunner()(cxxflags).macros;
|
||||
}
|
||||
|
||||
Utils::LanguageExtensions MsvcToolChain::languageExtensions(const QStringList &cxxflags) const
|
||||
{
|
||||
using Utils::LanguageExtension;
|
||||
@@ -1081,13 +1076,6 @@ ToolChain::BuiltInHeaderPathsRunner MsvcToolChain::createBuiltInHeaderPathsRunne
|
||||
};
|
||||
}
|
||||
|
||||
HeaderPaths MsvcToolChain::builtInHeaderPaths(const QStringList &cxxflags,
|
||||
const Utils::FilePath &sysRoot,
|
||||
const Environment &env) const
|
||||
{
|
||||
return createBuiltInHeaderPathsRunner(env)(cxxflags, sysRoot.toString(), "");
|
||||
}
|
||||
|
||||
void MsvcToolChain::addToEnvironment(Utils::Environment &env) const
|
||||
{
|
||||
// We cache the full environment (incoming + modifications by setup script).
|
||||
|
||||
@@ -74,16 +74,12 @@ public:
|
||||
std::unique_ptr<ToolChainConfigWidget> createConfigurationWidget() override;
|
||||
|
||||
MacroInspectionRunner createMacroInspectionRunner() const override;
|
||||
Macros predefinedMacros(const QStringList &cxxflags) const override;
|
||||
Utils::LanguageExtensions languageExtensions(const QStringList &cxxflags) const override;
|
||||
Utils::WarningFlags warningFlags(const QStringList &cflags) const override;
|
||||
QStringList includedFiles(const QStringList &flags,
|
||||
const QString &directoryPath) const override;
|
||||
BuiltInHeaderPathsRunner createBuiltInHeaderPathsRunner(
|
||||
const Utils::Environment &env) const override;
|
||||
HeaderPaths builtInHeaderPaths(const QStringList &cxxflags,
|
||||
const Utils::FilePath &sysRoot,
|
||||
const Utils::Environment &env) const override;
|
||||
void addToEnvironment(Utils::Environment &env) const override;
|
||||
|
||||
Utils::FilePath makeCommand(const Utils::Environment &environment) const override;
|
||||
|
||||
@@ -123,15 +123,11 @@ public:
|
||||
// A MacroInspectionRunner is created in the ui thread and runs in another thread.
|
||||
using MacroInspectionRunner = std::function<MacroInspectionReport(const QStringList &cxxflags)>;
|
||||
virtual MacroInspectionRunner createMacroInspectionRunner() const = 0;
|
||||
virtual Macros predefinedMacros(const QStringList &cxxflags) const = 0;
|
||||
|
||||
// A BuiltInHeaderPathsRunner is created in the ui thread and runs in another thread.
|
||||
using BuiltInHeaderPathsRunner = std::function<HeaderPaths(
|
||||
const QStringList &cxxflags, const QString &sysRoot, const QString &originalTargetTriple)>;
|
||||
virtual BuiltInHeaderPathsRunner createBuiltInHeaderPathsRunner(const Utils::Environment &env) const = 0;
|
||||
virtual HeaderPaths builtInHeaderPaths(const QStringList &cxxflags,
|
||||
const Utils::FilePath &sysRoot,
|
||||
const Utils::Environment &env) const = 0;
|
||||
virtual void addToEnvironment(Utils::Environment &env) const = 0;
|
||||
virtual Utils::FilePath makeCommand(const Utils::Environment &env) const = 0;
|
||||
|
||||
|
||||
@@ -316,12 +316,9 @@ public:
|
||||
|
||||
bool isValid() const override { return m_valid; }
|
||||
MacroInspectionRunner createMacroInspectionRunner() const override { return MacroInspectionRunner(); }
|
||||
Macros predefinedMacros(const QStringList &cxxflags) const override { Q_UNUSED(cxxflags) return Macros(); }
|
||||
LanguageExtensions languageExtensions(const QStringList &cxxflags) const override { Q_UNUSED(cxxflags) return LanguageExtension::None; }
|
||||
WarningFlags warningFlags(const QStringList &cflags) const override { Q_UNUSED(cflags) return WarningFlags::NoWarnings; }
|
||||
BuiltInHeaderPathsRunner createBuiltInHeaderPathsRunner(const Utils::Environment &) const override { return BuiltInHeaderPathsRunner(); }
|
||||
HeaderPaths builtInHeaderPaths(const QStringList &cxxflags, const FilePath &sysRoot, const Utils::Environment &) const override
|
||||
{ Q_UNUSED(cxxflags) Q_UNUSED(sysRoot) return {}; }
|
||||
void addToEnvironment(Environment &env) const override { Q_UNUSED(env) }
|
||||
FilePath makeCommand(const Environment &) const override { return FilePath::fromString("make"); }
|
||||
QList<OutputLineParser *> createOutputParsers() const override { return {}; }
|
||||
|
||||
@@ -103,11 +103,12 @@ TreeScanner::Result TreeScanner::result() const
|
||||
|
||||
TreeScanner::Result TreeScanner::release()
|
||||
{
|
||||
if (isFinished()) {
|
||||
if (isFinished() && m_scanFuture.resultCount() > 0) {
|
||||
auto result = m_scanFuture.result();
|
||||
m_scanFuture = Future();
|
||||
return result;
|
||||
}
|
||||
m_scanFuture = Future();
|
||||
return Result();
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include <projectexplorer/projectexplorer.h>
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
#include <projectexplorer/target.h>
|
||||
#include <projectexplorer/taskhub.h>
|
||||
#include <qtsupport/profilereader.h>
|
||||
#include <texteditor/icodestylepreferences.h>
|
||||
#include <texteditor/tabsettings.h>
|
||||
@@ -774,7 +775,7 @@ QPair<ProFile *, QStringList> QmakePriFile::readProFile()
|
||||
&contents,
|
||||
&m_textFormat,
|
||||
&errorMsg) != TextFileFormat::ReadSuccess) {
|
||||
QmakeBuildSystem::proFileParseError(errorMsg);
|
||||
QmakeBuildSystem::proFileParseError(errorMsg, filePath());
|
||||
return qMakePair(includeFile, lines);
|
||||
}
|
||||
lines = contents.split('\n');
|
||||
@@ -1655,7 +1656,7 @@ void QmakeProFile::applyEvaluate(QmakeEvalResult *evalResult)
|
||||
}
|
||||
|
||||
foreach (const QString &error, evalResult->errors)
|
||||
QmakeBuildSystem::proFileParseError(error);
|
||||
QmakeBuildSystem::proFileParseError(error, filePath());
|
||||
|
||||
// we are changing what is executed in that case
|
||||
if (result->state == QmakeEvalResult::EvalFail || m_buildSystem->wasEvaluateCanceled()) {
|
||||
@@ -1666,8 +1667,10 @@ void QmakeProFile::applyEvaluate(QmakeEvalResult *evalResult)
|
||||
|
||||
if (result->state == QmakeEvalResult::EvalFail) {
|
||||
QmakeBuildSystem::proFileParseError(
|
||||
QCoreApplication::translate("QmakeProFile", "Error while parsing file %1. Giving up.")
|
||||
.arg(filePath().toUserOutput()));
|
||||
QCoreApplication::translate("QmakeProFile",
|
||||
"Error while parsing file %1. Giving up.")
|
||||
.arg(filePath().toUserOutput()),
|
||||
filePath());
|
||||
if (m_projectType == ProjectType::Invalid)
|
||||
return;
|
||||
|
||||
|
||||
@@ -649,6 +649,7 @@ bool QmakeBuildSystem::wasEvaluateCanceled()
|
||||
|
||||
void QmakeBuildSystem::asyncUpdate()
|
||||
{
|
||||
TaskHub::clearTasks(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM);
|
||||
setParseDelay(UPDATE_INTERVAL);
|
||||
TRACE("");
|
||||
|
||||
@@ -674,7 +675,7 @@ void QmakeBuildSystem::asyncUpdate()
|
||||
"have a valid Qt.")
|
||||
.arg(project()->displayName(), k->displayName())
|
||||
: tr("Cannot parse project \"%1\": No kit selected.").arg(project()->displayName());
|
||||
proFileParseError(errorMessage);
|
||||
proFileParseError(errorMessage, project()->projectFilePath());
|
||||
m_asyncUpdateFutureInterface.reportCanceled();
|
||||
m_asyncUpdateFutureInterface.reportFinished();
|
||||
return;
|
||||
@@ -764,9 +765,9 @@ FilePath QmakeBuildSystem::buildDir(const FilePath &proFilePath) const
|
||||
return FilePath::fromString(QDir::cleanPath(QDir(buildDir).absoluteFilePath(relativeDir)));
|
||||
}
|
||||
|
||||
void QmakeBuildSystem::proFileParseError(const QString &errorMessage)
|
||||
void QmakeBuildSystem::proFileParseError(const QString &errorMessage, const FilePath &filePath)
|
||||
{
|
||||
Core::MessageManager::write(errorMessage);
|
||||
TaskHub::addTask(BuildSystemTask(Task::Error, errorMessage, filePath));
|
||||
}
|
||||
|
||||
QtSupport::ProFileReader *QmakeBuildSystem::createProFileReader(const QmakeProFile *qmakeProFile)
|
||||
|
||||
@@ -158,7 +158,7 @@ public:
|
||||
void watchFolders(const QStringList &l, QmakePriFile *file);
|
||||
void unwatchFolders(const QStringList &l, QmakePriFile *file);
|
||||
|
||||
static void proFileParseError(const QString &errorMessage);
|
||||
static void proFileParseError(const QString &errorMessage, const Utils::FilePath &filePath);
|
||||
|
||||
enum AsyncUpdateState { Base, AsyncFullUpdatePending, AsyncPartialUpdatePending, AsyncUpdateInProgress, ShuttingDown };
|
||||
AsyncUpdateState asyncUpdateState() const;
|
||||
|
||||
@@ -236,7 +236,8 @@ void FormEditorView::temporaryBlockView(int duration)
|
||||
timer->start(duration);
|
||||
|
||||
connect(timer, &QTimer::timeout, this, [this]() {
|
||||
m_formEditorWidget->graphicsView()->setUpdatesEnabled(true);
|
||||
if (m_formEditorWidget && m_formEditorWidget->graphicsView())
|
||||
m_formEditorWidget->graphicsView()->setUpdatesEnabled(true);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -458,8 +458,12 @@ QProcessEnvironment PuppetCreator::processEnvironment() const
|
||||
environment.set("QML_BAD_GUI_RENDER_LOOP", "true");
|
||||
environment.set("QML_PUPPET_MODE", "true");
|
||||
environment.set("QML_DISABLE_DISK_CACHE", "true");
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
if (!environment.hasKey("QT_SCREEN_SCALE_FACTORS") && !environment.hasKey("QT_SCALE_FACTOR")
|
||||
&& QApplication::testAttribute(Qt::AA_EnableHighDpiScaling))
|
||||
#else
|
||||
if (!environment.hasKey("QT_SCREEN_SCALE_FACTORS") && !environment.hasKey("QT_SCALE_FACTOR"))
|
||||
#endif
|
||||
environment.set("QT_AUTO_SCREEN_SCALE_FACTOR", "1");
|
||||
|
||||
#ifndef QMLDESIGNER_TEST
|
||||
|
||||
@@ -26,10 +26,12 @@
|
||||
#include "profilereader.h"
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <projectexplorer/taskhub.h>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
using namespace QtSupport;
|
||||
|
||||
static QString format(const QString &fileName, int lineNo, const QString &msg)
|
||||
@@ -53,7 +55,7 @@ ProMessageHandler::ProMessageHandler(bool verbose, bool exact)
|
||||
ProMessageHandler::~ProMessageHandler()
|
||||
{
|
||||
if (!m_messages.isEmpty())
|
||||
Core::MessageManager::writeMessages(m_messages);
|
||||
Core::MessageManager::writeMessages(m_messages, Core::MessageManager::Flash);
|
||||
}
|
||||
|
||||
|
||||
@@ -61,14 +63,22 @@ ProMessageHandler::~ProMessageHandler()
|
||||
void ProMessageHandler::message(int type, const QString &msg, const QString &fileName, int lineNo)
|
||||
{
|
||||
if ((type & CategoryMask) == ErrorMessage && ((type & SourceMask) == SourceParser || m_verbose)) {
|
||||
appendMessage(format(fileName, lineNo, msg));
|
||||
// parse error in qmake files
|
||||
TaskHub::addTask(
|
||||
BuildSystemTask(Task::Error, msg, Utils::FilePath::fromString(fileName), lineNo));
|
||||
}
|
||||
}
|
||||
|
||||
void ProMessageHandler::fileMessage(int type, const QString &msg)
|
||||
{
|
||||
Q_UNUSED(type)
|
||||
if (m_verbose)
|
||||
// message(), warning() or error() calls in qmake files
|
||||
if (!m_verbose)
|
||||
return;
|
||||
if (type == QMakeHandler::ErrorMessage)
|
||||
TaskHub::addTask(BuildSystemTask(Task::Error, msg));
|
||||
else if (type == QMakeHandler::WarningMessage)
|
||||
TaskHub::addTask(BuildSystemTask(Task::Warning, msg));
|
||||
else
|
||||
appendMessage(msg);
|
||||
}
|
||||
|
||||
|
||||
@@ -2704,7 +2704,7 @@ void tst_Dumpers::dumper_data()
|
||||
+ Check("l3", "<2 items>", "@QList<@QString>")
|
||||
+ Check("l3.0", "[0]", "\"1\"", "@QString")
|
||||
|
||||
+ Check("l4", "<2 items>", "@QStringList")
|
||||
+ Check("l4", "<2 items>", TypePattern("@QList<@QString>|@QStringList"))
|
||||
+ Check("l4.0", "[0]", "\"1\"", "@QString")
|
||||
|
||||
+ Check("l5", "<3 items>", "@QList<int*>")
|
||||
@@ -2721,7 +2721,7 @@ void tst_Dumpers::dumper_data()
|
||||
|
||||
+ Check5("l8", "<2 items>", "@QList<@QStringList>")
|
||||
+ Check6("l8", "<2 items>", "@QList<@QList<@QString>>")
|
||||
+ Check("sl", "<1 items>", "@QStringList")
|
||||
+ Check("sl", "<1 items>", TypePattern("@QList<@QString>|@QStringList"))
|
||||
+ Check5("l8.1", "[1]", "<1 items>", "@QStringList")
|
||||
+ Check6("l8.1", "[1]", "<1 items>", "@QList<@QString>")
|
||||
+ Check("l8.1.0", "[0]", "\"aaa\"", "@QString")
|
||||
@@ -3904,7 +3904,7 @@ void tst_Dumpers::dumper_data()
|
||||
+ Check("s8", "\"el\"", "@QStringRef") % Qt5
|
||||
+ Check("s9", "(null)", "@QStringRef") % Qt5
|
||||
|
||||
+ Check("l", "<2 items>", "@QStringList")
|
||||
+ Check("l", "<2 items>", TypePattern("@QList<@QString>|@QStringList"))
|
||||
+ Check("l.0", "[0]", "\" big, \"", "@QString")
|
||||
+ Check("l.1", "[1]", "\" World \"", "@QString")
|
||||
|
||||
@@ -4042,12 +4042,12 @@ void tst_Dumpers::dumper_data()
|
||||
//+ Check("v1", "\"Some string\"", "@QVariant (QString)")
|
||||
+ CheckType("v1", "@QVariant (QString)")
|
||||
|
||||
+ Check("my", "<2 items>", TypeDef("@QMap<unsigned int,@QStringList>", "MyType"))
|
||||
+ Check("my", "<2 items>", TypePattern("@QMap<unsigned int,@QStringList>|@QMap<unsigned int,@List<@QString>>|MyType"))
|
||||
+ Check("my.0.key", "1", "unsigned int")
|
||||
+ Check("my.0.value", "<1 items>", "@QStringList")
|
||||
+ Check("my.0.value", "<1 items>", TypePattern("@QList<@QString>|@QStringList"))
|
||||
+ Check("my.0.value.0", "[0]", "\"Hello\"", "@QString")
|
||||
+ Check("my.1.key", "3", "unsigned int")
|
||||
+ Check("my.1.value", "<1 items>", "@QStringList")
|
||||
+ Check("my.1.value", "<1 items>", TypePattern("@QList<@QString>|@QStringList"))
|
||||
+ Check("my.1.value.0", "[0]", "\"World\"", "@QString")
|
||||
//+ CheckType("v2", "@QVariant (MyType)")
|
||||
+ Check("v2.data.0.key", "1", "unsigned int") % NeedsInferiorCall
|
||||
@@ -4405,40 +4405,40 @@ void tst_Dumpers::dumper_data()
|
||||
|
||||
+ BigArrayProfile()
|
||||
|
||||
+ Check("v1", "<10000 items>", "@QVector<int>")
|
||||
+ Check("v1", "<10000 items>", TypePattern("@QList<int>|@QVector<int>"))
|
||||
+ Check("v1.0", "[0]", "0", "int")
|
||||
+ Check("v1.8999", "[8999]", "80982001", "int")
|
||||
|
||||
+ Check("v2", "<2 items>", "@QVector<Foo>")
|
||||
+ Check("v2", "<2 items>", TypePattern("@QList<Foo>|@QVector<Foo>"))
|
||||
+ Check("v2.0", "[0]", "", "Foo")
|
||||
+ Check("v2.0.a", "1", "int")
|
||||
+ Check("v2.1", "[1]", "", "Foo")
|
||||
+ Check("v2.1.a", "2", "int")
|
||||
|
||||
+ Check("v3", "<2 items>", TypeDef("@QVector<Foo>", "FooVector"))
|
||||
+ Check("v3", "<2 items>", TypePattern("@QVector<Foo>|@QList<Foo>|FooVector"))
|
||||
+ Check("v3.0", "[0]", "", "Foo")
|
||||
+ Check("v3.0.a", "1", "int")
|
||||
+ Check("v3.1", "[1]", "", "Foo")
|
||||
+ Check("v3.1.a", "2", "int")
|
||||
|
||||
+ Check("v4", "<3 items>", "@QVector<Foo*>")
|
||||
+ Check("v4", "<3 items>", TypePattern("@QList<Foo \\*>|@QVector<Foo\\*>"))
|
||||
+ CheckType("v4.0", "[0]", "Foo")
|
||||
+ Check("v4.0.a", "1", "int")
|
||||
+ Check("v4.1", "[1]", "0x0", "Foo *")
|
||||
+ CheckType("v4.2", "[2]", "Foo")
|
||||
+ Check("v4.2.a", "5", "int")
|
||||
|
||||
+ Check("v5", "<2 items>", "@QVector<bool>")
|
||||
+ Check("v5", "<2 items>", TypePattern("@QList<bool>|@QVector<bool>"))
|
||||
+ Check("v5.0", "[0]", "1", "bool")
|
||||
+ Check("v5.1", "[1]", "0", "bool")
|
||||
|
||||
+ CheckType("pv", "@QVector<@QList<int>>")
|
||||
+ CheckType("pv", TypePattern("@QList<@QList<int>>|@QVector<@QList<int>>"))
|
||||
+ Check("pv.0", "[0]", "<1 items>", "@QList<int>")
|
||||
+ Check("pv.0.0", "[0]", "1", "int")
|
||||
+ Check("pv.1", "[1]", "<2 items>", "@QList<int>")
|
||||
+ Check("pv.1.0", "[0]", "2", "int")
|
||||
+ Check("pv.1.1", "[1]", "3", "int")
|
||||
+ Check("v6", "<2 items>", "@QVector<@QList<int>>")
|
||||
+ Check("v6", "<2 items>", TypePattern("@QList<@QList<int>>|@QVector<@QList<int>>"))
|
||||
+ Check("v6.0", "[0]", "<1 items>", "@QList<int>")
|
||||
+ Check("v6.0.0", "[0]", "1", "int")
|
||||
+ Check("v6.1", "[1]", "<2 items>", "@QList<int>")
|
||||
@@ -4931,14 +4931,14 @@ void tst_Dumpers::dumper_data()
|
||||
+ Check("map2.1.second", "", "Foo")
|
||||
+ Check("map2.1.second.a", "33", "int")
|
||||
|
||||
+ Check("map3", "<2 items>", "std::map<unsigned int, @QStringList>")
|
||||
+ Check("map3", "<2 items>", TypePattern("std::map<unsigned int, @QList<@QString>>|std::map<unsigned int, @QStringList>"))
|
||||
+ Check("map3.0", "[0] 11", "<1 items>", "")
|
||||
+ Check("map3.0.first", "11", "unsigned int")
|
||||
+ Check("map3.0.second", "<1 items>", "@QStringList")
|
||||
+ Check("map3.0.second", "<1 items>", TypePattern("@QList<@QString>|@QStringList"))
|
||||
+ Check("map3.0.second.0", "[0]", "\"11\"", "@QString")
|
||||
+ Check("map3.1", "[1] 22", "<1 items>", "")
|
||||
+ Check("map3.1.first", "22", "unsigned int")
|
||||
+ Check("map3.1.second", "<1 items>", "@QStringList")
|
||||
+ Check("map3.1.second", "<1 items>", TypePattern("@QList<@QString>|@QStringList"))
|
||||
+ Check("map3.1.second.0", "[0]", "\"22\"", "@QString")
|
||||
|
||||
+ Check("map4.1.second.0", "[0]", "\"22\"", "@QString")
|
||||
@@ -6611,7 +6611,7 @@ void tst_Dumpers::dumper_data()
|
||||
+ Check("i0", "<uninitialized>", "boost::optional<int>")
|
||||
+ Check("i1", "1", "boost::optional<int>")
|
||||
|
||||
+ Check("sl", "<3 items>", "boost::optional<@QStringList>");
|
||||
+ Check("sl", "<3 items>", TypePattern("boost::optional<@QList<@QString>>|boost::optional<@QStringList>"));
|
||||
|
||||
|
||||
QTest::newRow("BoostSharedPtr")
|
||||
|
||||