Merge remote-tracking branch 'origin/4.14'

Conflicts:
	src/plugins/projectexplorer/gcctoolchain.cpp

Change-Id: I2136ba89d3aa3c4c2a0e7a4f9d8ba9cec32924ce
This commit is contained in:
Eike Ziller
2020-11-30 16:14:32 +01:00
92 changed files with 1268 additions and 655 deletions

View File

@@ -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"

View File

@@ -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

View File

@@ -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

View File

@@ -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.

View File

@@ -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

View File

@@ -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 \

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 228 KiB

After

Width:  |  Height:  |  Size: 206 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -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.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -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

View File

@@ -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}

View File

@@ -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
*/

View File

@@ -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

View File

@@ -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
*/

View File

@@ -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]

View File

@@ -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

View File

@@ -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

View File

@@ -30,9 +30,9 @@
\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
@@ -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}

View File

@@ -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
*/

View File

@@ -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

View File

@@ -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}

View File

@@ -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}

View File

@@ -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

View File

@@ -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
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,16 +1784,24 @@ 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.
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')
@@ -1784,11 +1810,24 @@ class DumperBase():
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:
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)
revision = 7 if self.qtVersion() >= 0x050000 else 6
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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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,9 +134,13 @@ 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.
// 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
}
}
}

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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
};

View File

@@ -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,7 +501,8 @@ void NodeInstanceServer::setupOnlyWorkingImports(const QStringList &workingImpor
QByteArray componentCode = workingImportStatementList.join("\n").toUtf8().append("\n");
m_importCode = componentCode;
m_importComponent = new QQmlComponent(engine(), quickView());
m_importComponent = new QQmlComponent(engine(), quickWindow());
if (quickView())
quickView()->setContent(fileUrl(), m_importComponent, quickView()->rootObject());
m_importComponent->setData(componentCode.append("\nItem {}\n"), fileUrl());
@@ -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();
}
}

View File

@@ -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:

View File

@@ -70,7 +70,7 @@ void Qt5CaptureImageNodeInstanceServer::collectItemChangesAndSendChangeCommands(
auto rooNodeInstance = rootNodeInstance();
rooNodeInstance.rootQuickItem()->setClip(true);
DesignerSupport::polishItems(quickView());
DesignerSupport::polishItems(quickWindow());
QImage image = renderImage(rooNodeInstance);

View File

@@ -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));

View File

@@ -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

View File

@@ -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;
};

View File

@@ -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());

View File

@@ -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

View File

@@ -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));

View File

@@ -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)) {

View File

@@ -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);

View File

@@ -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

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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');

View File

@@ -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

View File

@@ -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,15 +489,21 @@ 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;
if (!(optional || (toImport.flags & QmlDirParser::Import::Optional)))
error(doc, errorLoc,
Link::tr(
"Implicit import '%1' of QML module '%2' not found.\n\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)) {

View File

@@ -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(), {}) }));
}
}

View File

@@ -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));

View File

@@ -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));

View File

@@ -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,6 +280,7 @@ void AndroidManifestEditorIconWidget::copyIcon()
if (m_iconPath != targetPath)
removeIcon();
if (original.isNull()) {
if (!similarFilesExist(m_iconPath))
m_iconPath.clear();
return;
}

View File

@@ -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());

View File

@@ -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()) {

View File

@@ -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;

View File

@@ -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()) {

View File

@@ -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;

View File

@@ -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()) {

View File

@@ -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;

View File

@@ -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)
{

View File

@@ -837,12 +837,16 @@ FilePath CMakeBuildSystem::workDirectory(const BuildDirParameters &parameters)
{
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()));

View File

@@ -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()

View File

@@ -109,6 +109,7 @@ private:
void filterNewContent();
void handleNextOutputChunk();
void handleOutputChunk(const QString &output, Utils::OutputFormat format);
void updateAutoScroll();
Internal::OutputWindowPrivate *d = nullptr;
};

View File

@@ -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;

View File

@@ -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\""}});
}
}

View File

@@ -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();
}

View File

@@ -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()) {

View File

@@ -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())

View File

@@ -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;

View File

@@ -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()) {

View File

@@ -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;

View File

@@ -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,

View File

@@ -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;

View File

@@ -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).

View File

@@ -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;

View File

@@ -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;

View File

@@ -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 {}; }

View File

@@ -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();
}

View File

@@ -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;

View File

@@ -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)

View File

@@ -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;

View File

@@ -236,6 +236,7 @@ void FormEditorView::temporaryBlockView(int duration)
timer->start(duration);
connect(timer, &QTimer::timeout, this, [this]() {
if (m_formEditorWidget && m_formEditorWidget->graphicsView())
m_formEditorWidget->graphicsView()->setUpdatesEnabled(true);
});
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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")