Merge "Merge remote-tracking branch 'origin/8.0' into 9.0" into 9.0

This commit is contained in:
The Qt Project
2022-10-04 13:45:23 +00:00
91 changed files with 719 additions and 244 deletions

View File

@@ -0,0 +1,245 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Design Studio 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.
**
****************************************************************************/
/*!
\page animation-tutorial.html
\ingroup gstutorials
\sa {Creating Timeline Animations}
\title Timeline Animation Tutorial
\brief Illustrates how to create timeline animations and bind them to
properties in \QDS.
\image animation-tutorial.gif
The \e{Timeline Animation} tutorial illustrates how to create timeline animations
and bind them to properties in \QDS. First you create a keyframe animation
which you control the running state of with a switch in the UI. Next, you
create another keyframe animation where you use a slider in the UI to
control the position of the playhead.
The starting point of this tutorial is the Animation Tutorial project,
you can download it from
\l{https://git.qt.io/public-demos/qtdesign-studio/-/tree/master/tutorial%20projects/animation-tutorial/AnimationTutorial/Start}
{here}.
You can download the completed project from
\l{https://git.qt.io/public-demos/qtdesign-studio/-/tree/master/tutorial%20projects/animation-tutorial/AnimationTutorial/Completed}
{here}.
This tutorial requires that you know the basics of \QDS, see
\l{Getting Started}.
\section1 Creating a Timeline Animation
First, you create an animation where the ball bearing continuously rotates
around its Y axis.
\section2 Adding a Timeline and an Animation
To add a timeline to your project:
\list 1
\li In the \uicontrol Timeline view, select
\inlineimage icons/plus.png
.
This creates a timeline and one animation.
\li On the \uicontrol {Animation Settings} tab in the
\uicontrol {Timeline Settings} dialog:
\list
\li Set \uicontrol Duration to 7500.
This sets the duration of the animation in milliseconds.
\li Select \uicontrol {Contiunous}.
This sets the animation to start over again when it reaches the
end.
\endlist
\image animation-tutorial-timeline-1.png
\li Select \uicontrol {Close}.
\endlist
You can see the timeline in the \uicontrol Timeline and
\uicontrol Navigator views.
\section2 Adding Keyframes
Next, you add keyframes to animate the rotation of the ball bearing:
\list 1
\li In the \uicontrol Navigator view, select \e {ballbearing1}.
\li In the \uicontrol Properties view, select
\inlineimage icons/action-icon.png (Actions)
next to \uicontrol Rotation > \uicontrol {Y}.
\li Select \uicontrol {Insert Keyframe}.
\image animation-tutorial-insert-keyframe.png
\li In the \uicontrol Timeline view, select the
\uicontrol {Per Property Recording} button to start recording property
changes.
\image animation-tutorial-per-property-recording.png
\li In the \uicontrol Timeline view, move the playhead to the end of the
animation (frame 1000).
\li In the \uicontrol Properties view, set \uicontrol Rotation >
\uicontrol Z to 360.
This creates a second keyframe.
\li Select the \uicontrol {Per Property Recording} button to end the per
property recording. To preview the animation, drag the playhead along the
timeline.
\endlist
\section2 Controlling the Running State of the Animation
There is a toggle switch in the UI of this project. To use this switch to
control the running state of the animation:
\list 1
\li In the \uicontrol Navigator view, select \e {timelineAnimation}.
\li In the \uicontrol Connections view, go to the \uicontrol Bindings tab.
\li Select \inlineimage icons/plus.png
to create a binding.
\li For the binding you created, set:
\list
\li \uicontrol Property to \e {paused}.
\li \uicontrol {Source Item} to \e {switch1}.
\li \uicontrol {Source Property} to \e {checked}.
\endlist
\image animation-tutorial-binding.png
\endlist
You can preview the animation and try the toggle switch in the live preview.
To run the live preview, select \key Alt + \key{P}.
\section1 Creating a Timeline and Binding it to a Property
Next, you create the exploded view animation of the ball bearing. You don't
want this animation to run automatically but instead you want to control it
with a slider in the UI.
\section2 Adding a Timeline Inside a Component
You create this animation inside the ball bearing component, to do this:
\list 1
\li In the \uicontrol Navigator view, select \e {ballBearing1}.
\li Select \key {F2} to go into the component.
\li In the \uicontrol Timeline view, select
\inlineimage icons/plus.png
to add a timeline and open the \uicontrol {Timeline Settings} dialog.
\li Select \inlineimage icons/minus.png
next to the \uicontrol {Animation Settings} tab to remove the animation
in this timeline.
You do not need an animation when you bind the timeline to a property.
\li Select \uicontrol {Close}.
\endlist
\image animation-tutorial-timeline-2.png
\section2 Adding Keyframes
Now, you add keyframes for the different parts of the ball bearing:
\list 1
\li In the \uicontrol{Navigator} view, select \e{inner_race}.
\li In the \uicontrol Properties view, select
\inlineimage icons/action-icon.png (Actions)
next to \uicontrol Translation > \uicontrol Y.
\li Select \uicontrol {Insert Keyframe}.
\li In the \uicontrol Timeline view, select the
\uicontrol {Per Property Recording} button to start recording property
changes.
\li In the \uicontrol Timeline view, move the playhead to the end of the
animation (frame 1000).
\li In the \uicontrol Properties view, set \uicontrol Translation >
\uicontrol Y to 0,50.
\li Select the \uicontrol {Per Property Recording} button to end the per
property recording.
\li Next, you set the keyframe values for the other parts of the ball
bearing. For the following parts, set the \uicontrol Translation >
\uicontrol Y value for frame 1000:
\list
\li \e balls to 1,00.
\li \e retainer to 1,50.
\li \e shield_left to 1,80.
\li \e shield_right to -0,30.
\endlist
\image animation-tutorial-ballbearing-animation.png
\endlist
You can preview the animation by dragging the playhead in the
\uicontrol Timeline view.
\section2 Controlling the Animation with a Slider
Now, you use the slider on the main screen to control the exploded
view animation that you created.
To do this, you first need to define a property for the slider:
\list 1
\li In the \uicontrol Navigator view, select \e Node.
\li On the \uicontrol Properties tab in the \uicontrol Connections view,
select \inlineimage icons/plus.png
.
\li In the \uicontrol {Property Type} field, enter \e {Item}.
This field is a drop-down list, but you can also type text.
\li In the \uicontrol {Property Value} field, enter \e {null}.
\endlist
\image animation-tutorial-property.png
Next, you set the property you just created to control the timeline
animation:
\list 1
\li In the \uicontrol {Timeline} view, select
\inlineimage icons/animation.png
.
\li In the \uicontrol {Expression binding field}, enter
\c {property0.value}.
\li Select \uicontrol {Close}.
\endlist
Next, you go out from the component back to the main project and bind the
property to the slider:
\list 1
\li In the toolbar, select the \e {Screen01.ui.qml} breadcrumb.
\image animation-tutorial-breadcrumb.png
\li In the \uicontrol {Navigator} view, select \e {ballbearing1}.
\li In the \uicontrol {Connections} view, go to the
\uicontrol {Bindings} tab.
\li Select \inlineimage icons/plus.png
.
\li For the binding you just created:
\list
\li Set \uicontrol {Source Item} to \e {slider}.
\li Remove the value from \uicontrol {Source Property}.
\endlist
\image animation-tutorial-binding-2.png
\endlist
\section1 Previewing
Now, the animations are done. To preview and test your application,
select \key Alt + \key{P}.
*/

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -29,7 +29,7 @@
custom properties on the \uicontrol {Properties} tab in the custom properties on the \uicontrol {Properties} tab in the
\l {Connections} view. \l {Connections} view.
\image qmldesigner-dynamicprops.png "Connections View Properties tab" \image qmldesigner-dynamicprops.png "Connections View Properties tab"
For more information, see \l{Specifying Dynamic Properties}. For more information, see \l{Specifying Custom Properties}.
\li To enable users to interact with the component instances, connect \li To enable users to interact with the component instances, connect
the instances to signals on the \uicontrol Connections tab in the the instances to signals on the \uicontrol Connections tab in the
\uicontrol {Connections} view. For example, you can specify what \uicontrol {Connections} view. For example, you can specify what

View File

@@ -41,7 +41,7 @@
\uicontrol Navigator or the \uicontrol {2D} view. \uicontrol Navigator or the \uicontrol {2D} view.
\li Edit component properties in the \uicontrol Properties view. \li Edit component properties in the \uicontrol Properties view.
The available properties depend on the component type. You can The available properties depend on the component type. You can
\l{Specifying Dynamic Properties}{add properties for \l{Specifying Custom Properties}{add properties for
components} on the \uicontrol {Properties} tab in the components} on the \uicontrol {Properties} tab in the
\uicontrol Connections view. \uicontrol Connections view.
\li To change the appearance and behavior of the component instances \li To change the appearance and behavior of the component instances

View File

@@ -139,7 +139,7 @@
When you add a \l{GridView}{Grid View}, \l{ListView}{List View}, or When you add a \l{GridView}{Grid View}, \l{ListView}{List View}, or
\l{PathView}{Path View}, the ListModel and the delegate component that \l{PathView}{Path View}, the ListModel and the delegate component that
creates an instance for each item in the model are added automatically. creates an instance for each item in the model are added automatically.
For grid and list views, you can edit the list model in \QC. For grid and list views, you can edit the list model in \QDS.
\image qtquick-designer-listview-preview.png "Preview of a list view" \image qtquick-designer-listview-preview.png "Preview of a list view"

View File

@@ -28,7 +28,7 @@
\image qtquick-designer-image-type.png "Image component in different views" \image qtquick-designer-image-type.png "Image component in different views"
When you drag-and-drop an image file from \uicontrol Assets to \l Navigator When you drag-and-drop an image file from \uicontrol Assets to \l Navigator
or the \l {2D} view, \QC automatically or the \l {2D} view, \QDS automatically
creates an instance of the Image component for you with the path to the creates an instance of the Image component for you with the path to the
image file set as the value of the \uicontrol Source field in image file set as the value of the \uicontrol Source field in
\uicontrol Properties. \uicontrol Properties.

View File

@@ -73,7 +73,7 @@
For more information on the JavaScript environment provided, see For more information on the JavaScript environment provided, see
\l{Integrating QML and JavaScript}. \l{Integrating QML and JavaScript}.
Bindings are a black box for \QC and using them might have a Bindings are a black box for \QDS and using them might have a
negative impact on performance, so consider setting anchors and margins for negative impact on performance, so consider setting anchors and margins for
components, instead. For example, instead of setting \c {parent.width} for a components, instead. For example, instead of setting \c {parent.width} for a
component, you could anchor the component to its sibling components on the component, you could anchor the component to its sibling components on the
@@ -342,7 +342,7 @@
to right and top to bottom. Each component is positioned at the top-left to right and top to bottom. Each component is positioned at the top-left
corner of its cell with position (0, 0). corner of its cell with position (0, 0).
\QC generates the grid based on the positions of the child components in \QDS generates the grid based on the positions of the child components in
the \l {2D} view. You can modify the number of rows and columns in the the \l {2D} view. You can modify the number of rows and columns in the
\uicontrol Rows and \uicontrol Columns fields. \uicontrol Rows and \uicontrol Columns fields.

View File

@@ -27,7 +27,7 @@
working Qt 6 application that you can build and run in Qt Creator using working Qt 6 application that you can build and run in Qt Creator using
CMake. Therefore, you can open, build, and run the projects with Qt Creator. CMake. Therefore, you can open, build, and run the projects with Qt Creator.
\QDS continues to use the \e .qmlproject file format, while \QC uses a \QDS continues to use the \e .qmlproject file format, while Qt Creator uses a
\e CMakeLists.txt file as the project file. This enables you to share \e CMakeLists.txt file as the project file. This enables you to share
your project as a fully working C++ application with developers. your project as a fully working C++ application with developers.
@@ -46,9 +46,10 @@
\section1 Converting Project Structure for CMake \section1 Converting Project Structure for CMake
\QDS can generate \e CMakeLists.txt and other related files to use with \QC and to compile into \QDS can generate \e CMakeLists.txt and other related files to use with
an executable application but only if the project has a certain folder structure. If you have a Qt Creator and to compile into an executable application but only if the
\QDS QML project that doesn't have the CMake configuration, follow these steps to convert its project has a certain folder structure. If you have a \QDS QML project that
doesn't have the CMake configuration, follow these steps to convert its
file structure to the correct format. file structure to the correct format.
\list 1 \list 1

View File

@@ -46,7 +46,7 @@
\section2 Timeline and Keyframe Based Animation \section2 Timeline and Keyframe Based Animation
Timeline animation is based on \e keyframes. In \QC, keyframes determine the Timeline animation is based on \e keyframes. In \QDS, keyframes determine the
value of the property of a \l{glossary_component}{component} at a certain value of the property of a \l{glossary_component}{component} at a certain
time. Animating properties enables their values to move through intermediate time. Animating properties enables their values to move through intermediate
values instead of immediately changing to the target value. values instead of immediately changing to the target value.

View File

@@ -114,7 +114,7 @@
\endif \endif
\row \row
\li Adding custom properties for a particular component type \li Adding custom properties for a particular component type
\li \l{Specifying Dynamic Properties} \li \l{Specifying Custom Properties}
\omit \omit
\row \row
\li Adding properties for controlling states \li Adding properties for controlling states

View File

@@ -48,7 +48,7 @@
\section1 Profiling UI Code \section1 Profiling UI Code
You can use \l{Profiling QML Applications}{QML Profiler} that is integrated You can use \l{Profiling QML Applications}{QML Profiler} that is integrated
into \QC to find causes for typical performance problems in your UI. For into \QDS to find causes for typical performance problems in your UI. For
example, your UI might be slow, unresponsive, or stuttering. Typically, such example, your UI might be slow, unresponsive, or stuttering. Typically, such
problems are caused by executing too much JavaScript in too few frames. All problems are caused by executing too much JavaScript in too few frames. All
JavaScript must return before the GUI thread can proceed, and frames are JavaScript must return before the GUI thread can proceed, and frames are

View File

@@ -73,7 +73,7 @@
\li \l {Importing 3D Assets} \li \l {Importing 3D Assets}
You can import exported assets into \QC. For a list of formats You can import exported assets into \QDS. For a list of formats
supported by each \l{Qt Quick 3D} version, see the module supported by each \l{Qt Quick 3D} version, see the module
documentation. documentation.

View File

@@ -20,14 +20,14 @@
components, and states, you need. Create a descriptive wireframe components, and states, you need. Create a descriptive wireframe
and acquire a detailed UI specification before you start to make and acquire a detailed UI specification before you start to make
the process of creating the UI more efficient. the process of creating the UI more efficient.
\QC enables you to turn your UI concept into a wireframe with \QDS enables you to turn your UI concept into a wireframe with
a scalable layout where all your screens and controls are in a scalable layout where all your screens and controls are in
place. You can present your wireframe to developers and other place. You can present your wireframe to developers and other
stakeholders for discussion, review, and approval before stakeholders for discussion, review, and approval before
continuing into the prototyping phase. continuing into the prototyping phase.
\endtable \endtable
In \QC, you build UIs around the behavior of \l{glossary-component} In \QDS, you build UIs around the behavior of \l{glossary-component}
{components} and how they connect with one another. You can use preset {components} and how they connect with one another. You can use preset
components available in the \l Components view or combine them to create components available in the \l Components view or combine them to create
your own components. You can specify values for the \e properties of a your own components. You can specify values for the \e properties of a

View File

@@ -49,7 +49,7 @@
\li Edit component properties in the \l Properties view. \li Edit component properties in the \l Properties view.
The available properties depend on the component type. You can The available properties depend on the component type. You can
\l{Specifying Dynamic Properties}{add properties for components} on \l{Specifying Custom Properties}{add properties for components} on
the \uicontrol Properties tab in the {Connections} view. the \uicontrol Properties tab in the {Connections} view.
\endlist \endlist

View File

@@ -26,7 +26,7 @@
\li \l{Converting UI Projects to Applications} \li \l{Converting UI Projects to Applications}
\QDS projects are useful for creating UIs. To use them for \QDS projects are useful for creating UIs. To use them for
application development in \QC, you have to convert application development in Qt Creator, you have to convert
them to Qt Quick Application projects that contain .pro, them to Qt Quick Application projects that contain .pro,
.cpp, and .qrc files. .cpp, and .qrc files.
\li \l{Using External Tools} \li \l{Using External Tools}

View File

@@ -19,7 +19,7 @@
\li \l {FAQ - Assets}{Assets} \li \l {FAQ - Assets}{Assets}
\li \l {FAQ - Components}{Components} \li \l {FAQ - Components}{Components}
\li \l {FAQ - Views}{Views} \li \l {FAQ - Views}{Views}
\li \l {FAQ - Integration Between \QDS and \QC}{Integration Between \QDS and \QC} \li \l {FAQ - Integration Between \QDS and Qt Creator}{Integration Between \QDS and Qt Creator}
\li \l {FAQ - Performance}{Performance} \li \l {FAQ - Performance}{Performance}
\li \l {FAQ - Data Simulation}{Data Simulation} \li \l {FAQ - Data Simulation}{Data Simulation}
\endlist \endlist
@@ -67,7 +67,7 @@
\section1 FAQ - Components \section1 FAQ - Components
\section2 Can custom components be used? \section2 Can I use custom components?
Yes, you can create custom components and controls by using wizard templates Yes, you can create custom components and controls by using wizard templates
or move component instances into separate files to turn them into new or move component instances into separate files to turn them into new
@@ -81,7 +81,7 @@
For more information, see \l {Importing 3D Assets}. For more information, see \l {Importing 3D Assets}.
\section2 How to integrate custom C++ components into QDS? \section2 How can I integrate custom C++ components into QDS?
You must create your own QML module that contains the components and You must create your own QML module that contains the components and
provides additional information about your components. For more information, provides additional information about your components. For more information,
@@ -99,21 +99,21 @@
For more information, see the \l {3D} view. For more information, see the \l {3D} view.
\section1 FAQ - Integration Between \QDS and \QC \section1 FAQ - Integration Between \QDS and Qt Creator
\section2 Is there a way to automatically propagate name changes between \QDS and \QC? \section2 Can I automatically propagate name changes between \QDS and Qt Creator?
Unfortunately we do not automate renaming files between tools at the moment. Unfortunately we do not automate renaming files between tools at the moment.
If you decide to change the name of a property, alias, or signal in \QDS, If you decide to change the name of a property, alias, or signal in \QDS,
you need to manually change the name in \QC to maintain the connection. you need to manually change the name in Qt Creator to maintain the connection.
However, you can rename symbols in all files within a project. To rename a However, you can rename symbols in all files within a project. To rename a
QML type in a project, select \uicontrol Tools > \uicontrol QML/JS > QML type in a project, select \uicontrol Tools > \uicontrol QML/JS >
\uicontrol {Rename Symbol Under Cursor} or press \key Ctrl+Shift+R. For more \uicontrol {Rename Symbol Under Cursor} or press \key Ctrl+Shift+R. For more
information, see \l {Renaming Symbols}. information, see \l {Renaming Symbols}.
\section2 When turning your \QDS project into application in \QC, what is the best way to add .qml files? \section2 How can I add .qml files to my project in Qt Creator?
Use the project wizard templates to create an application in \QC and copy Use the project wizard templates to create an application in \QDS and copy
your .qml files to the project folder. Then make some changes to the project your .qml files to the project folder. Then make some changes to the project
configuration and source files, as instructed in configuration and source files, as instructed in
\l {Converting UI Projects to Applications}. \l {Converting UI Projects to Applications}.

View File

@@ -143,7 +143,7 @@
Navigator to add the properties on the \uicontrol Properties tab in the Navigator to add the properties on the \uicontrol Properties tab in the
\l Connections view. \l Connections view.
See \l {Specifying Dynamic Properties} for a detailed description of how See \l {Specifying Custom Properties} for a detailed description of how
to add a custom property. The name of the property and the data type to add a custom property. The name of the property and the data type
need to match those of the send or receive property of the Simulink model. need to match those of the send or receive property of the Simulink model.

View File

@@ -197,7 +197,7 @@
\li \l{Preset Components} \li \l{Preset Components}
\li \l{Specifying Component Properties} \li \l{Specifying Component Properties}
\li \l{Adding Bindings Between Properties} \li \l{Adding Bindings Between Properties}
\li \l{Specifying Dynamic Properties} \li \l{Specifying Custom Properties}
\endlist \endlist
\section1 Signal \section1 Signal
@@ -294,7 +294,7 @@
deploys it to the \l{glossary-device}{device} specified in the deploys it to the \l{glossary-device}{device} specified in the
selected \l{glossary-buildandrun-kit}{kit}, and runs it there. However, selected \l{glossary-buildandrun-kit}{kit}, and runs it there. However,
if you have not made any changes to the project since you last deployed if you have not made any changes to the project since you last deployed
it, \QC simply runs it again. it, \QDS simply runs it again.
\endomit \endomit
*/ */

View File

@@ -122,7 +122,7 @@
\list \list
\li\l{Connecting Components to Signals} \li\l{Connecting Components to Signals}
\li\l{Adding Bindings Between Properties} \li\l{Adding Bindings Between Properties}
\li\l{Specifying Dynamic Properties} \li\l{Specifying Custom Properties}
\endlist \endlist
\li \l{Adding States} \li \l{Adding States}
\endlist \endlist

View File

@@ -193,5 +193,5 @@
\image studio-custom-material-uniform-properties.png "Uniforms as properties in Connections view Properties tab" \image studio-custom-material-uniform-properties.png "Uniforms as properties in Connections view Properties tab"
For more information about adding properties, see For more information about adding properties, see
\l{Specifying Dynamic Properties}. \l{Specifying Custom Properties}.
*/ */

View File

@@ -12,7 +12,7 @@
\title Creating Optimized 3D Scenes \title Creating Optimized 3D Scenes
In \QC, you can use various means to create a 3D scene. Your choice of In \QDS, you can use various means to create a 3D scene. Your choice of
strategy should always depend on the target platform of your scene. strategy should always depend on the target platform of your scene.
The way the content of your scene is authored can have dramatic effects on The way the content of your scene is authored can have dramatic effects on
the runtime performance of your UI. The Optimal 3D Scene described the runtime performance of your UI. The Optimal 3D Scene described
@@ -88,7 +88,7 @@
The scene graph is the hierarchy of nodes that describe the scene to be The scene graph is the hierarchy of nodes that describe the scene to be
rendered. rendered.
In \QC, the scene graph is represented by the tree-like view in In \QDS, the scene graph is represented by the tree-like view in
\uicontrol Navigator. You can also view the hierarchy of nodes in the \uicontrol Navigator. You can also view the hierarchy of nodes in the
\l {Code} view. By minimizing the size of the scene graph, \l {Code} view. By minimizing the size of the scene graph,
you can minimize the effort needed when running the scene. In terms of you can minimize the effort needed when running the scene. In terms of

View File

@@ -9,10 +9,10 @@
\else \else
\nextpage quick-connections-backend.html \nextpage quick-connections-backend.html
\endif \endif
\sa {Specifying Component Properties}
\title Specifying Custom Properties
\title Specifying Dynamic Properties Each \l{Preset Components}{preset component }has a set of preset properties
Each preset \l{glossary-component}{component} has a set of preset properties
that you can specify values for. You can add custom properties that would that you can specify values for. You can add custom properties that would
not otherwise exist for a particular \l{Component Types}{component type}. not otherwise exist for a particular \l{Component Types}{component type}.
You bind the properties to dynamic expressions to define global properties You bind the properties to dynamic expressions to define global properties
@@ -33,50 +33,36 @@
should have an \e int or \e real property for speed to which the UI is should have an \e int or \e real property for speed to which the UI is
bound. bound.
You can add properties for components on the \uicontrol Properties tab in \section1 Adding Properties for a Component
in the \l {Connections} view.
\image qmldesigner-dynamicprops.png "Custom properties in the Connections view Custom Properties tab" To add a custom property for a component:
To add properties for a component:
\list 1 \list 1
\li Go to the \uicontrol Properties tab in the \l Connections view. \li Go to the \uicontrol {Local Custom Properties} section in the
\uicontrol Properties view.
\li Select the \inlineimage icons/plus.png \li Select the \inlineimage icons/plus.png
(\uicontrol Add) button to add a dynamic property for the currently (\uicontrol Add) button to add a custom property for the currently
selected component. The component ID is displayed in the \uicontrol Item selected component.
column. \image add-local-custom-property.png
\li Double-click the value in the \uicontrol Property column to give a \li Set the \uicontrol Name and \uicontrol Type for the property.
name to the property. Property names must begin with a lower case \image add-new-property-dialog.png
letter and can only contain letters, numbers, and underscores. \endlist
JavaScript \e {reserved words} are not valid property names.
\li Double-click the value in the \uicontrol {Property Type} column to \section1 Binding a Property Value
specify the \l{Supported Property Types}{type of the property}.
\li Double-click the value in the \uicontrol {Property Value} column To bind the value of the property to that of another one or to data
to specify the value of the property. accessible in the application.
\list 1
\li In the \uicontrol Properties view, select
\inlineimage icons/action-icon.png
next to the property.
\li Select \uicontrol {Set Binding}.
\image qmldesigner-binding-editor.png "Binding Editor"
\endlist \endlist
Right-click a property and select \uicontrol {Open Binding Editor} in
the context menu to bind the value of the property to that of another one
or to data accessible in the application in \uicontrol {Binding Editor}.
For more information, see \l{Setting Bindings}. For more information, see \l{Setting Bindings}.
\image qmldesigner-binding-editor.png "Binding Editor"
The properties you add for a component are displayed in the \l Properties
view when you select a component of that type in the \l Navigator or
\l {2D} view.
\image qtquick-custom-properties.png "Custom properties in Properties view"
For more information about setting property values in the
\l Properties view, see \l{Specifying Component Properties}.
\if defined(qtcreator)
For an example of using custom properties in an application, see
\l{Creating a Mobile Application}.
\endif
\section1 Supported Property Types \section1 Supported Property Types
The following table describes the supported property types: The following table describes the supported property types:
@@ -112,6 +98,9 @@
\row \row
\li string \li string
\li Free form text string \li Free form text string
\row
\li TextureInput
\li Specifies a texture exposed to the shaders of a CustomMaterial or Effect.
\row \row
\li url \li url
\li Resource locator, such as a file name. It can be either absolute, \li Resource locator, such as a file name. It can be either absolute,
@@ -122,5 +111,14 @@
\li variant \li variant
\li Generic property type. For example, variant properties can store \li Generic property type. For example, variant properties can store
numbers, strings, objects, arrays, and functions. numbers, strings, objects, arrays, and functions.
\row
\li vector2d
\li Refers to a value with x and y attributes.
\row
\li vector3d
\li Refers to a value with x, y, and z attributes.
\row
\li vector4d
\li Refers to a value with x, y, z, and w attributes.
\endtable \endtable
*/ */

View File

@@ -26,7 +26,7 @@
the value of a property changes, the values of any properties that the value of a property changes, the values of any properties that
are bound to it are automatically updated accordingly. are bound to it are automatically updated accordingly.
\li \l{Specifying Dynamic Properties} \li \l{Specifying Custom Properties}
Each preset component has a set of preset properties that you Each preset component has a set of preset properties that you
can specify values for. You can add custom properties that would can specify values for. You can add custom properties that would

View File

@@ -63,7 +63,7 @@
\li \uicontrol Properties \li \uicontrol Properties
\li Add custom properties that would not otherwise exist for a \li Add custom properties that would not otherwise exist for a
particular preset component or your own custom component. particular preset component or your own custom component.
\li \l{Specifying Dynamic Properties} \li \l{Specifying Custom Properties}
\if defined(qtcreator) \if defined(qtcreator)
\row \row
\li \uicontrol Backends \li \uicontrol Backends

View File

@@ -107,7 +107,7 @@
\section1 Locking Components \section1 Locking Components
When designing complex applications, it is easy to accidentally modify When designing complex applications, it is easy to accidentally modify
the properties of a component in one of the \QC views in ways that lead to the properties of a component in one of the \QDS views in ways that lead to
surprising results. For example, the \uicontrol {2D} view can become surprising results. For example, the \uicontrol {2D} view can become
crowded and other components can get in the way when you are trying to crowded and other components can get in the way when you are trying to
select or transform a particular component, so that you end up transforming select or transform a particular component, so that you end up transforming
@@ -115,7 +115,7 @@
To lock components that you are not currently editing and their children, To lock components that you are not currently editing and their children,
click \inlineimage icons/lockon.png click \inlineimage icons/lockon.png
in \uicontrol Navigator. Locked components cannot be handled in any \QC in \uicontrol Navigator. Locked components cannot be handled in any \QDS
views. You can unlock the components when you want to edit them again. views. You can unlock the components when you want to edit them again.
\image qtquick-designer-navigator-lock.gif "Locking components in Navigator" \image qtquick-designer-navigator-lock.gif "Locking components in Navigator"

View File

@@ -22,6 +22,26 @@
\image qmldesigner-element-properties.png "Rectangle and Text properties" \image qmldesigner-element-properties.png "Rectangle and Text properties"
\section1 Custom Properties
Custom Properties are properties that the user has added to the component.
There are two types of custom properties:
\table
\header
\li Custom Property Type
\li Description
\row
\li Local Custom Property
\li A property that has been added for a \l{Preset Components}{preset component}.
\row
\li Exposed Custom Property
\li A property that has been added inside a component.
\endtable
\image custom-properties.png
\section1 Summary of Properties View Buttons \section1 Summary of Properties View Buttons
The following table lists the \uicontrol Properties view buttons: The following table lists the \uicontrol Properties view buttons:

View File

@@ -29,7 +29,7 @@
another preset component in the field. another preset component in the field.
If you have specified values for properties that are not supported by the If you have specified values for properties that are not supported by the
new component type, \QC offers to remove them for you. If you'd rather do new component type, \QDS offers to remove them for you. If you'd rather do
this yourself, you can select the \inlineimage icons/action-icon.png this yourself, you can select the \inlineimage icons/action-icon.png
(\uicontrol Actions) menu next to the property name, and then select (\uicontrol Actions) menu next to the property name, and then select
\uicontrol Reset to remove the property values before trying again. \uicontrol Reset to remove the property values before trying again.

View File

@@ -8,7 +8,7 @@
\title Managing Workspaces \title Managing Workspaces
In the \uicontrol Design mode, you can arrange a set of \QC In the \uicontrol Design mode, you can arrange a set of \QDS
views as a \e workspace on the screen. views as a \e workspace on the screen.
To detach views: To detach views:
@@ -34,10 +34,10 @@
\section1 Saving Workspaces \section1 Saving Workspaces
The changes you make to a workspace are saved when you exit \QC. The changes you make to a workspace are saved when you exit \QDS.
Select \uicontrol View > \uicontrol Workspaces > Select \uicontrol View > \uicontrol Workspaces >
\uicontrol Manage > \uicontrol {Restore last workspace on startup} \uicontrol Manage > \uicontrol {Restore last workspace on startup}
to restore the current workspace the next time you start \QC. to restore the current workspace the next time you start \QDS.
\image qtcreator-workspace-manager.png "Workspace Manager" \image qtcreator-workspace-manager.png "Workspace Manager"

View File

@@ -17,6 +17,7 @@ Item {
property var currentMaterial: null property var currentMaterial: null
property int currentMaterialIdx: 0 property int currentMaterialIdx: 0
property var currentBundleMaterial: null property var currentBundleMaterial: null
property int copiedMaterialInternalId: -1
property var matSectionsModel: [] property var matSectionsModel: []
@@ -125,15 +126,20 @@ Item {
StudioControls.MenuItem { StudioControls.MenuItem {
text: modelData text: modelData
enabled: root.currentMaterial enabled: root.currentMaterial
onTriggered: materialBrowserModel.copyMaterialProperties(root.currentMaterialIdx, modelData) onTriggered: {
root.copiedMaterialInternalId = root.currentMaterial.materialInternalId
materialBrowserModel.copyMaterialProperties(root.currentMaterialIdx, modelData)
}
} }
} }
} }
StudioControls.MenuItem { StudioControls.MenuItem {
text: qsTr("Paste properties") text: qsTr("Paste properties")
enabled: root.currentMaterial && root.currentMaterial.materialType enabled: root.currentMaterial
=== materialBrowserModel.copiedMaterialType && root.copiedMaterialInternalId !== root.currentMaterial.materialInternalId
&& root.currentMaterial.materialType === materialBrowserModel.copiedMaterialType
&& materialBrowserModel.isCopiedMaterialValid()
onTriggered: materialBrowserModel.pasteMaterialProperties(root.currentMaterialIdx) onTriggered: materialBrowserModel.pasteMaterialProperties(root.currentMaterialIdx)
} }
@@ -213,7 +219,22 @@ Item {
width: root.width - addMaterialButton.width width: root.width - addMaterialButton.width
onSearchChanged: (searchText) => rootView.handleSearchFilterChanged(searchText) onSearchChanged: (searchText) => {
rootView.handleSearchFilterChanged(searchText)
// make sure searched categories that have matches are expanded
if (!materialBrowserModel.isEmpty && !userMaterialsSection.expanded)
userMaterialsSection.expanded = true
if (!materialBrowserBundleModel.isEmpty && !bundleMaterialsSection.expanded)
bundleMaterialsSection.expanded = true
for (let i = 0; i < bundleMaterialsSectionRepeater.count; ++i) {
let sec = bundleMaterialsSectionRepeater.itemAt(i)
if (sec.visible && !sec.expanded)
sec.expanded = true
}
}
} }
IconButton { IconButton {
@@ -282,10 +303,8 @@ Item {
height: root.cellHeight height: root.cellHeight
onShowContextMenu: { onShowContextMenu: {
if (searchBox.isEmpty()) { root.currentMaterial = model
root.currentMaterial = model cxtMenu.popup()
cxtMenu.popup()
}
} }
} }
} }
@@ -312,6 +331,8 @@ Item {
} }
Section { Section {
id: bundleMaterialsSection
width: root.width width: root.width
caption: qsTr("Material Library") caption: qsTr("Material Library")
addTopPadding: noMatchText.visible addTopPadding: noMatchText.visible
@@ -319,6 +340,8 @@ Item {
Column { Column {
Repeater { Repeater {
id: bundleMaterialsSectionRepeater
model: materialBrowserBundleModel model: materialBrowserBundleModel
delegate: Section { delegate: Section {
@@ -343,10 +366,8 @@ Item {
height: root.cellHeight height: root.cellHeight
onShowContextMenu: { onShowContextMenu: {
if (searchBox.isEmpty()) { root.currentBundleMaterial = modelData
root.currentBundleMaterial = modelData cxtMenuBundle.popup()
cxtMenuBundle.popup()
}
} }
} }
} }

View File

@@ -303,18 +303,50 @@ Rectangle {
width: Math.min(300, root.width) width: Math.min(300, root.width)
onApplied: { function apply() {
let renamed = statesEditorModel.renameActiveStateGroup(editTextField.text) let renamed = statesEditorModel.renameActiveStateGroup(editTextField.text)
if (renamed) if (renamed)
editDialog.close() editDialog.close()
} }
onApplied: editDialog.accept()
StudioControls.TextField { StudioControls.TextField {
id: editTextField id: editTextField
text: statesEditorModel.activeStateGroup
actionIndicatorVisible: false actionIndicatorVisible: false
translationIndicatorVisible: false translationIndicatorVisible: false
anchors.fill: parent anchors.fill: parent
onTextChanged: {
let btn = editDialog.standardButton(Dialog.Apply)
if (!btn)
return
if (editDialog.previousString !== editTextField.text) {
btn.enabled = true
} else {
btn.enabled = false
}
}
onAccepted: editDialog.accept()
onRejected: editDialog.reject()
}
onAccepted: {
let renamed = statesEditorModel.renameActiveStateGroup(editTextField.text)
if (renamed)
editDialog.close()
}
property string previousString
onAboutToShow: {
editTextField.text = statesEditorModel.activeStateGroup
editDialog.previousString = statesEditorModel.activeStateGroup
let btn = editDialog.standardButton(Dialog.Apply)
btn.enabled = false
} }
} }
@@ -747,8 +779,7 @@ Rectangle {
height: extendGap.portraitOneColumn ? root.innerGridSpacing : Constants.thumbnailSize height: extendGap.portraitOneColumn ? root.innerGridSpacing : Constants.thumbnailSize
+ 2 * root.extend + 2 * root.extend
color: StudioTheme.Values.themeStateHighlight color: StudioTheme.Values.themeStateHighlight
visible: extendBackground.radius !== 0 visible: extendBackground.visible
&& extendBackground.visible
} }
StateThumbnail { StateThumbnail {

View File

@@ -35,7 +35,7 @@ Section {
id: root id: root
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
caption: qsTr("User Added Properties") caption: qsTr("Local Custom Properties")
property DynamicPropertiesModel propertiesModel: null property DynamicPropertiesModel propertiesModel: null

View File

@@ -11,8 +11,6 @@ import StudioTheme 1.0 as StudioTheme
StudioControls.TextField { StudioControls.TextField {
id: textField id: textField
signal rejected
translationIndicator.visible: false translationIndicator.visible: false
actionIndicator.visible: false actionIndicator.visible: false
@@ -136,6 +134,11 @@ StudioControls.TextField {
onPressed: listView.model = null onPressed: listView.model = null
onRejected: {
if (textField.completionActive)
listView.model = null
}
Keys.priority: Keys.BeforeItem Keys.priority: Keys.BeforeItem
Keys.onPressed: function(event) { Keys.onPressed: function(event) {
var text = textField.text var text = textField.text
@@ -222,15 +225,6 @@ StudioControls.TextField {
} }
} }
Keys.onEscapePressed: function(event) {
event.accepted = true
if (textField.completionActive) {
listView.model = null
} else {
textField.rejected()
}
}
Keys.onUpPressed: function(event) { Keys.onUpPressed: function(event) {
listView.decrementCurrentIndex() listView.decrementCurrentIndex()
event.accepted = false event.accepted = false

View File

@@ -60,7 +60,7 @@ T.Button {
states: [ states: [
State { State {
name: "default" name: "default"
when: !root.down && !root.hovered && !root.checked when: root.enabled && !root.down && !root.hovered && !root.checked
PropertyChanges { PropertyChanges {
target: background target: background
@@ -75,7 +75,7 @@ T.Button {
}, },
State { State {
name: "hover" name: "hover"
when: root.hovered && !root.checked && !root.down when: root.enabled && root.hovered && !root.checked && !root.down
PropertyChanges { PropertyChanges {
target: background target: background
@@ -88,8 +88,8 @@ T.Button {
} }
}, },
State { State {
name: "pressed" name: "press"
when: root.checked || root.down when: root.enabled && (root.checked || root.down)
PropertyChanges { PropertyChanges {
target: background target: background
@@ -100,6 +100,19 @@ T.Button {
target: textItem target: textItem
color: StudioTheme.Values.themeTextColor color: StudioTheme.Values.themeTextColor
} }
},
State {
name: "disable"
when: !root.enabled
PropertyChanges {
target: background
color: StudioTheme.Values.themeControlBackgroundDisabled
border.color: StudioTheme.Values.themeControlOutlineDisabled
}
PropertyChanges {
target: textItem
color: StudioTheme.Values.themeTextColorDisabled
}
} }
] ]
} }

View File

@@ -30,6 +30,8 @@ T.TextField {
property bool contextMenuAboutToShow: false property bool contextMenuAboutToShow: false
signal rejected
horizontalAlignment: Qt.AlignLeft horizontalAlignment: Qt.AlignLeft
verticalAlignment: Qt.AlignVCenter verticalAlignment: Qt.AlignVCenter
@@ -225,10 +227,10 @@ T.TextField {
} }
] ]
Keys.onPressed: function(event) { Keys.onEscapePressed: function(event) {
if (event.key === Qt.Key_Escape) { event.accepted = true
root.text = root.preFocusText root.text = root.preFocusText
root.focus = false root.rejected()
} root.focus = false
} }
} }

View File

@@ -567,14 +567,16 @@ bool AndroidBuildApkStep::init()
if (m_buildAAB) if (m_buildAAB)
arguments << "--aab" << "--jarsigner"; arguments << "--aab" << "--jarsigner";
if (buildType() == BuildConfiguration::Release) {
arguments << "--release";
}
QStringList argumentsPasswordConcealed = arguments; QStringList argumentsPasswordConcealed = arguments;
if (m_signPackage) { if (m_signPackage) {
arguments << "--release" arguments << "--sign" << m_keystorePath.toString() << m_certificateAlias
<< "--sign" << m_keystorePath.toString() << m_certificateAlias
<< "--storepass" << m_keystorePasswd; << "--storepass" << m_keystorePasswd;
argumentsPasswordConcealed << "--release" argumentsPasswordConcealed << "--sign" << "******"
<< "--sign" << "******"
<< "--storepass" << "******"; << "--storepass" << "******";
if (!m_certificatePasswd.isEmpty()) { if (!m_certificatePasswd.isEmpty()) {
arguments << "--keypass" << m_certificatePasswd; arguments << "--keypass" << m_certificatePasswd;

View File

@@ -240,6 +240,9 @@ bool AndroidDeployQtStep::init()
m_androiddeployqtArgs.addArg("--gradle"); m_androiddeployqtArgs.addArg("--gradle");
if (buildType() == BuildConfiguration::Release)
m_androiddeployqtArgs.addArgs({"--release"});
if (androidBuildApkStep && androidBuildApkStep->signPackage()) { if (androidBuildApkStep && androidBuildApkStep->signPackage()) {
// The androiddeployqt tool is not really written to do stand-alone installations. // The androiddeployqt tool is not really written to do stand-alone installations.
// This hack forces it to use the correct filename for the apk file when installing // This hack forces it to use the correct filename for the apk file when installing

View File

@@ -576,6 +576,8 @@ public:
{ {
menu()->clear(); menu()->clear();
menu()->setEnabled(true);
const auto selection = selectionContext(); const auto selection = selectionContext();
if (!selection.isValid()) if (!selection.isValid())
return; return;
@@ -585,11 +587,19 @@ public:
return; return;
ModelNode currentNode = selection.currentSingleSelectedNode(); ModelNode currentNode = selection.currentSingleSelectedNode();
if (!currentNode.isValid())
return;
QmlObjectNode currentObjectNode(currentNode); QmlObjectNode currentObjectNode(currentNode);
QStringList signalsList = getSignalsList(currentNode); QStringList signalsList = getSignalsList(currentNode);
QList<SlotEntry> slotsList = getSlotsLists(currentNode); QList<SlotEntry> slotsList = getSlotsLists(currentNode);
currentNode.validId();
if (!currentNode.hasId()) {
menu()->setEnabled(false);
return;
}
for (const ModelNode &connectionNode : currentObjectNode.getAllConnections()) { for (const ModelNode &connectionNode : currentObjectNode.getAllConnections()) {
for (const AbstractProperty &property : connectionNode.properties()) { for (const AbstractProperty &property : connectionNode.properties()) {

View File

@@ -1631,6 +1631,7 @@ void addMouseAreaFill(const SelectionContext &selectionContext)
QmlDesigner::ModelNode mouseAreaNode = QmlDesigner::ModelNode mouseAreaNode =
selectionContext.view()->createModelNode("QtQuick.MouseArea", itemMetaInfo.majorVersion(), itemMetaInfo.minorVersion()); selectionContext.view()->createModelNode("QtQuick.MouseArea", itemMetaInfo.majorVersion(), itemMetaInfo.minorVersion());
mouseAreaNode.validId();
modelNode.defaultNodeListProperty().reparentHere(mouseAreaNode); modelNode.defaultNodeListProperty().reparentHere(mouseAreaNode);
QmlItemNode mouseAreaItemNode(mouseAreaNode); QmlItemNode mouseAreaItemNode(mouseAreaNode);

View File

@@ -315,6 +315,8 @@ void Edit3DWidget::dragEnterEvent(QDragEnterEvent *dragEnterEvent)
void Edit3DWidget::dropEvent(QDropEvent *dropEvent) void Edit3DWidget::dropEvent(QDropEvent *dropEvent)
{ {
const QPointF pos = m_canvas->mapFrom(this, dropEvent->position());
// handle dropping materials // handle dropping materials
if (dropEvent->mimeData()->hasFormat(Constants::MIME_TYPE_MATERIAL)) { if (dropEvent->mimeData()->hasFormat(Constants::MIME_TYPE_MATERIAL)) {
QByteArray data = dropEvent->mimeData()->data(Constants::MIME_TYPE_MATERIAL); QByteArray data = dropEvent->mimeData()->data(Constants::MIME_TYPE_MATERIAL);
@@ -323,13 +325,13 @@ void Edit3DWidget::dropEvent(QDropEvent *dropEvent)
stream >> internalId; stream >> internalId;
if (ModelNode matNode = m_view->modelNodeForInternalId(internalId)) if (ModelNode matNode = m_view->modelNodeForInternalId(internalId))
m_view->dropMaterial(matNode, dropEvent->position()); m_view->dropMaterial(matNode, pos);
return; return;
} }
// handle dropping bundle materials // handle dropping bundle materials
if (dropEvent->mimeData()->hasFormat(Constants::MIME_TYPE_BUNDLE_MATERIAL)) { if (dropEvent->mimeData()->hasFormat(Constants::MIME_TYPE_BUNDLE_MATERIAL)) {
m_view->dropBundleMaterial(dropEvent->position()); m_view->dropBundleMaterial(pos);
return; return;
} }

View File

@@ -7,7 +7,8 @@
#include <designmodewidget.h> #include <designmodewidget.h>
#include <qmldesignerplugin.h> #include <qmldesignerplugin.h>
#include <qmlobjectnode.h> #include <qmlobjectnode.h>
#include "variantproperty.h" #include <variantproperty.h>
#include <qmltimelinekeyframegroup.h>
#include "utils/qtcassert.h" #include "utils/qtcassert.h"
namespace QmlDesigner { namespace QmlDesigner {
@@ -326,40 +327,84 @@ void MaterialBrowserModel::duplicateMaterial(int idx)
void MaterialBrowserModel::copyMaterialProperties(int idx, const QString &section) void MaterialBrowserModel::copyMaterialProperties(int idx, const QString &section)
{ {
ModelNode mat = m_materialList.at(idx); m_copiedMaterial = m_materialList.at(idx);
QString matType = QString::fromLatin1(mat.type());
QTC_ASSERT(m_copiedMaterial.isValid(), return);
QString matType = QString::fromLatin1(m_copiedMaterial.type());
if (matType.startsWith("QtQuick3D.")) if (matType.startsWith("QtQuick3D."))
matType.remove("QtQuick3D."); matType.remove("QtQuick3D.");
setCopiedMaterialType(matType); setCopiedMaterialType(matType);
m_allPropsCopied = section == "All"; m_allPropsCopied = section == "All";
QmlObjectNode mat(m_copiedMaterial);
QSet<PropertyName> validProps;
PropertyNameList copiedProps;
// Base state properties are always valid
const auto baseProps = m_copiedMaterial.propertyNames();
for (const auto &baseProp : baseProps)
validProps.insert(baseProp);
if (!mat.isInBaseState()) {
QmlPropertyChanges changes = mat.propertyChangeForCurrentState();
if (changes.isValid()) {
const QList<AbstractProperty> changedProps = changes.targetProperties();
for (const auto &changedProp : changedProps)
validProps.insert(changedProp.name());
}
}
if (mat.timelineIsActive()) {
const QList<QmlTimelineKeyframeGroup> keyframeGroups
= mat.currentTimeline().keyframeGroupsForTarget(m_copiedMaterial);
for (const auto &kfg : keyframeGroups)
validProps.insert(kfg.propertyName());
}
if (m_allPropsCopied || m_propertyGroupsObj.empty()) { if (m_allPropsCopied || m_propertyGroupsObj.empty()) {
m_copiedMaterialProps = mat.properties(); copiedProps = validProps.values();
} else { } else {
QJsonObject propsSpecObj = m_propertyGroupsObj.value(m_copiedMaterialType).toObject(); QJsonObject propsSpecObj = m_propertyGroupsObj.value(m_copiedMaterialType).toObject();
if (propsSpecObj.contains(section)) { // should always be true if (propsSpecObj.contains(section)) { // should always be true
m_copiedMaterialProps.clear();
const QJsonArray propNames = propsSpecObj.value(section).toArray(); const QJsonArray propNames = propsSpecObj.value(section).toArray();
// auto == QJsonValueConstRef after 04dc959d49e5e3 / Qt 6.4, QJsonValueRef before // auto == QJsonValueConstRef after 04dc959d49e5e3 / Qt 6.4, QJsonValueRef before
for (const auto &propName : propNames) for (const auto &propName : propNames)
m_copiedMaterialProps.append(mat.property(propName.toString().toLatin1())); copiedProps.append(propName.toString().toLatin1());
if (section == "Base") { // add QtQuick3D.Material base props as well if (section == "Base") { // add QtQuick3D.Material base props as well
QJsonObject propsMatObj = m_propertyGroupsObj.value("Material").toObject(); QJsonObject propsMatObj = m_propertyGroupsObj.value("Material").toObject();
const QJsonArray propNames = propsMatObj.value("Base").toArray(); const QJsonArray propNames = propsMatObj.value("Base").toArray();
// auto == QJsonValueConstRef after 04dc959d49e5e3 / Qt 6.4, QJsonValueRef before // auto == QJsonValueConstRef after 04dc959d49e5e3 / Qt 6.4, QJsonValueRef before
for (const auto &propName : propNames) for (const auto &propName : propNames)
m_copiedMaterialProps.append(mat.property(propName.toString().toLatin1())); copiedProps.append(propName.toString().toLatin1());
} }
} }
} }
m_copiedMaterialProps.clear();
for (const auto &propName : copiedProps) {
PropertyCopyData data;
data.name = propName;
data.isValid = m_allPropsCopied || validProps.contains(propName);
data.isBinding = mat.hasBindingProperty(propName);
if (data.isValid) {
if (data.isBinding)
data.value = mat.expression(propName);
else
data.value = mat.modelValue(propName);
}
m_copiedMaterialProps.append(data);
}
} }
void MaterialBrowserModel::pasteMaterialProperties(int idx) void MaterialBrowserModel::pasteMaterialProperties(int idx)
{ {
emit pasteMaterialPropertiesTriggered(m_materialList.at(idx), m_copiedMaterialProps, m_allPropsCopied); ModelNode targetMat = m_materialList.at(idx);
if (targetMat.isValid() && m_copiedMaterial.isValid() && targetMat != m_copiedMaterial)
emit pasteMaterialPropertiesTriggered(targetMat, m_copiedMaterialProps, m_allPropsCopied);
} }
void MaterialBrowserModel::deleteMaterial(int idx) void MaterialBrowserModel::deleteMaterial(int idx)
@@ -396,4 +441,11 @@ void MaterialBrowserModel::openMaterialEditor()
QmlDesignerPlugin::instance()->mainWidget()->showDockWidget("MaterialEditor", true); QmlDesignerPlugin::instance()->mainWidget()->showDockWidget("MaterialEditor", true);
} }
// This is provided as invokable instead of property, as it is difficult to know when ModelNode
// becomes invalid. Much simpler to evaluate this on demand.
bool MaterialBrowserModel::isCopiedMaterialValid() const
{
return m_copiedMaterial.isValid();
}
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -70,6 +70,15 @@ public:
Q_INVOKABLE void addNewMaterial(); Q_INVOKABLE void addNewMaterial();
Q_INVOKABLE void applyToSelected(qint64 internalId, bool add = false); Q_INVOKABLE void applyToSelected(qint64 internalId, bool add = false);
Q_INVOKABLE void openMaterialEditor(); Q_INVOKABLE void openMaterialEditor();
Q_INVOKABLE bool isCopiedMaterialValid() const;
struct PropertyCopyData
{
PropertyName name;
QVariant value;
bool isBinding = false;
bool isValid = false;
};
signals: signals:
void isEmptyChanged(); void isEmptyChanged();
@@ -83,9 +92,10 @@ signals:
void applyToSelectedTriggered(const QmlDesigner::ModelNode &material, bool add = false); void applyToSelectedTriggered(const QmlDesigner::ModelNode &material, bool add = false);
void addNewMaterialTriggered(); void addNewMaterialTriggered();
void duplicateMaterialTriggered(const QmlDesigner::ModelNode &material); void duplicateMaterialTriggered(const QmlDesigner::ModelNode &material);
void pasteMaterialPropertiesTriggered(const QmlDesigner::ModelNode &material, void pasteMaterialPropertiesTriggered(
const QList<QmlDesigner::AbstractProperty> &props, const QmlDesigner::ModelNode &material,
bool all); const QList<QmlDesigner::MaterialBrowserModel::PropertyCopyData> &props,
bool all);
private: private:
bool isMaterialVisible(int idx) const; bool isMaterialVisible(int idx) const;
@@ -96,7 +106,8 @@ private:
QStringList m_defaultMaterialSections; QStringList m_defaultMaterialSections;
QStringList m_principledMaterialSections; QStringList m_principledMaterialSections;
QStringList m_customMaterialSections; QStringList m_customMaterialSections;
QList<AbstractProperty> m_copiedMaterialProps; ModelNode m_copiedMaterial;
QList<PropertyCopyData> m_copiedMaterialProps;
QHash<qint32, int> m_materialIndexHash; // internalId -> index QHash<qint32, int> m_materialIndexHash; // internalId -> index
QJsonObject m_propertyGroupsObj; QJsonObject m_propertyGroupsObj;

View File

@@ -72,29 +72,43 @@ WidgetInfo MaterialBrowserView::widgetInfo()
}); });
connect(matBrowserModel, &MaterialBrowserModel::pasteMaterialPropertiesTriggered, this, connect(matBrowserModel, &MaterialBrowserModel::pasteMaterialPropertiesTriggered, this,
[&] (const ModelNode &material, const QList<AbstractProperty> &props, bool all) { [&] (const ModelNode &material,
const QList<QmlDesigner::MaterialBrowserModel::PropertyCopyData> &propDatas,
bool all) {
QmlObjectNode mat(material); QmlObjectNode mat(material);
executeInTransaction(__FUNCTION__, [&] { executeInTransaction(__FUNCTION__, [&] {
if (all) { // all material properties copied if (all) { // all material properties copied
// remove current properties // remove current properties
const PropertyNameList propNames = material.propertyNames(); PropertyNameList propNames;
for (const PropertyName &propName : propNames) { if (mat.isInBaseState()) {
propNames = material.propertyNames();
} else {
QmlPropertyChanges changes = mat.propertyChangeForCurrentState();
if (changes.isValid()) {
const QList<AbstractProperty> changedProps = changes.targetProperties();
for (const auto &changedProp : changedProps)
propNames.append(changedProp.name());
}
}
for (const PropertyName &propName : qAsConst(propNames)) {
if (propName != "objectName") if (propName != "objectName")
mat.removeProperty(propName); mat.removeProperty(propName);
} }
} }
// apply pasted properties // apply pasted properties
for (const AbstractProperty &prop : props) { for (const QmlDesigner::MaterialBrowserModel::PropertyCopyData &propData : propDatas) {
if (prop.name() == "objectName") if (propData.name == "objectName")
continue; continue;
if (prop.isVariantProperty()) if (propData.isValid) {
mat.setVariantProperty(prop.name(), prop.toVariantProperty().value()); if (propData.isBinding)
else if (prop.isBindingProperty()) mat.setBindingProperty(propData.name, propData.value.toString());
mat.setBindingProperty(prop.name(), prop.toBindingProperty().expression()); else
else if (!all) mat.setVariantProperty(propData.name, propData.value);
mat.removeProperty(prop.name()); } else {
mat.removeProperty(propData.name);
}
} }
}); });
}); });
@@ -164,7 +178,8 @@ void MaterialBrowserView::applyBundleMaterialToDropTarget(const ModelNode &bundl
newMatNode = bundleMat; newMatNode = bundleMat;
} }
if (m_bundleMaterialDropTarget.isValid()) { if (m_bundleMaterialDropTarget.isValid()
&& m_bundleMaterialDropTarget.metaInfo().isQtQuick3DModel()) {
QmlObjectNode qmlObjNode(m_bundleMaterialDropTarget); QmlObjectNode qmlObjNode(m_bundleMaterialDropTarget);
if (m_bundleMaterialAddToSelected) { if (m_bundleMaterialAddToSelected) {
// TODO: unify this logic as it exist elsewhere also // TODO: unify this logic as it exist elsewhere also
@@ -211,12 +226,12 @@ void MaterialBrowserView::modelAttached(Model *model)
rootModelNode().metaInfo().isQtQuick3DMaterial()); rootModelNode().metaInfo().isQtQuick3DMaterial());
m_hasQuick3DImport = model->hasImport("QtQuick3D"); m_hasQuick3DImport = model->hasImport("QtQuick3D");
loadPropertyGroups();
// Project load is already very busy and may even trigger puppet reset, so let's wait a moment // Project load is already very busy and may even trigger puppet reset, so let's wait a moment
// before refreshing the model // before refreshing the model
QTimer::singleShot(1000, this, [this]() { QTimer::singleShot(1000, this, [this]() {
refreshModel(true); refreshModel(true);
loadPropertyGroups(); // Needs the delay because it uses metaInfo
}); });
} }
@@ -429,7 +444,6 @@ void MaterialBrowserView::customNotification(const AbstractView *view,
} else if (identifier == "drop_bundle_material") { } else if (identifier == "drop_bundle_material") {
m_bundleMaterialDropTarget = nodeList.first(); m_bundleMaterialDropTarget = nodeList.first();
ModelNode defaultMat = getBundleMaterialDefaultInstance(m_draggedBundleMaterial->type()); ModelNode defaultMat = getBundleMaterialDefaultInstance(m_draggedBundleMaterial->type());
if (defaultMat.isValid()) if (defaultMat.isValid())
applyBundleMaterialToDropTarget(defaultMat); applyBundleMaterialToDropTarget(defaultMat);

View File

@@ -110,15 +110,21 @@ bool MaterialBrowserWidget::eventFilter(QObject *obj, QEvent *event)
} else if (m_bundleMaterialToDrag != nullptr) { } else if (m_bundleMaterialToDrag != nullptr) {
QMouseEvent *me = static_cast<QMouseEvent *>(event); QMouseEvent *me = static_cast<QMouseEvent *>(event);
if ((me->globalPos() - m_dragStartPoint).manhattanLength() > 20) { if ((me->globalPos() - m_dragStartPoint).manhattanLength() > 20) {
QByteArray data;
QMimeData *mimeData = new QMimeData; QMimeData *mimeData = new QMimeData;
mimeData->setData(Constants::MIME_TYPE_BUNDLE_MATERIAL, {}); QDataStream stream(&data, QIODevice::WriteOnly);
stream << m_bundleMaterialToDrag->type();
mimeData->setData(Constants::MIME_TYPE_BUNDLE_MATERIAL, data);
mimeData->removeFormat("text/plain"); mimeData->removeFormat("text/plain");
model->startDrag(mimeData, m_bundleMaterialToDrag->icon().toLocalFile());
emit bundleMaterialDragStarted(m_bundleMaterialToDrag); emit bundleMaterialDragStarted(m_bundleMaterialToDrag);
model->startDrag(mimeData, m_bundleMaterialToDrag->icon().toLocalFile());
m_bundleMaterialToDrag = {}; m_bundleMaterialToDrag = {};
} }
} }
} else if (event->type() == QMouseEvent::MouseButtonRelease) {
m_materialToDrag = {};
m_bundleMaterialToDrag = {};
} }
return QObject::eventFilter(obj, event); return QObject::eventFilter(obj, event);

View File

@@ -36,6 +36,8 @@ ChooseFromPropertyListFilter::ChooseFromPropertyListFilter(const NodeMetaInfo &i
// -> Attractor3D // -> Attractor3D
// Material // Material
// -> Model // -> Model
// BundleMaterial
// -> Model
if (insertInfo.isQtQuick3DTexture()) { if (insertInfo.isQtQuick3DTexture()) {
if (parentInfo.isQtQuick3DDefaultMaterial() || parentInfo.isQtQuick3DPrincipledMaterial()) { if (parentInfo.isQtQuick3DDefaultMaterial() || parentInfo.isQtQuick3DPrincipledMaterial()) {
@@ -83,6 +85,9 @@ ChooseFromPropertyListFilter::ChooseFromPropertyListFilter(const NodeMetaInfo &i
} else if (insertInfo.isQtQuick3DMaterial()) { } else if (insertInfo.isQtQuick3DMaterial()) {
if (parentInfo.isQtQuick3DParticles3DModel()) if (parentInfo.isQtQuick3DParticles3DModel())
propertyList.append("materials"); propertyList.append("materials");
// TODO merge conflict between Change-Id: If3c58f82797beabe76baf99ea2dddc59032729df and Change-Id: Iff2dea66e253b412105427134bd49cb16ed76193
// } else if (insertInfo.typeName().startsWith("ComponentBundles.MaterialBundle")) {
// if (parentInfo.isSubclassOf("QtQuick3D.Model"))
} }
} }

View File

@@ -443,6 +443,7 @@ QStringList NavigatorTreeModel::mimeTypes() const
const static QStringList types({Constants::MIME_TYPE_MODELNODE_LIST, const static QStringList types({Constants::MIME_TYPE_MODELNODE_LIST,
Constants::MIME_TYPE_ITEM_LIBRARY_INFO, Constants::MIME_TYPE_ITEM_LIBRARY_INFO,
Constants::MIME_TYPE_MATERIAL, Constants::MIME_TYPE_MATERIAL,
Constants::MIME_TYPE_BUNDLE_MATERIAL,
Constants::MIME_TYPE_ASSETS}); Constants::MIME_TYPE_ASSETS});
return types; return types;
@@ -540,6 +541,10 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
handleItemLibraryItemDrop(mimeData, rowNumber, dropModelIndex); handleItemLibraryItemDrop(mimeData, rowNumber, dropModelIndex);
} else if (mimeData->hasFormat(Constants::MIME_TYPE_MATERIAL)) { } else if (mimeData->hasFormat(Constants::MIME_TYPE_MATERIAL)) {
handleMaterialDrop(mimeData, rowNumber, dropModelIndex); handleMaterialDrop(mimeData, rowNumber, dropModelIndex);
} else if (mimeData->hasFormat(Constants::MIME_TYPE_BUNDLE_MATERIAL)) {
ModelNode targetNode(modelNodeForIndex(dropModelIndex));
if (targetNode.isValid())
m_view->emitCustomNotification("drop_bundle_material", {targetNode}); // To MaterialBrowserView
} else if (mimeData->hasFormat(Constants::MIME_TYPE_ASSETS)) { } else if (mimeData->hasFormat(Constants::MIME_TYPE_ASSETS)) {
const QStringList assetsPaths = QString::fromUtf8(mimeData->data(Constants::MIME_TYPE_ASSETS)).split(','); const QStringList assetsPaths = QString::fromUtf8(mimeData->data(Constants::MIME_TYPE_ASSETS)).split(',');
NodeAbstractProperty targetProperty; NodeAbstractProperty targetProperty;

View File

@@ -260,6 +260,14 @@ void NavigatorView::dragStarted(QMimeData *mimeData)
m_widget->setDragType(matNode.metaInfo().typeName()); m_widget->setDragType(matNode.metaInfo().typeName());
m_widget->update(); m_widget->update();
} else if (mimeData->hasFormat(Constants::MIME_TYPE_BUNDLE_MATERIAL)) {
QByteArray data = mimeData->data(Constants::MIME_TYPE_BUNDLE_MATERIAL);
QDataStream stream(data);
TypeName bundleMatType;
stream >> bundleMatType;
m_widget->setDragType(bundleMatType);
m_widget->update();
} }
} }

View File

@@ -335,7 +335,8 @@ void DynamicPropertyRow::commitValue(const QVariant &value)
QByteArrayLiteral("DynamicPropertiesModel::commitValue")); QByteArrayLiteral("DynamicPropertiesModel::commitValue"));
try { try {
QmlObjectNode objectNode = variantProperty.parentQmlObjectNode(); QmlObjectNode objectNode = variantProperty.parentQmlObjectNode();
if (view->currentState().isBaseState() && !objectNode.timelineIsActive()) { if (view->currentState().isBaseState()
&& !(objectNode.timelineIsActive() && objectNode.currentTimeline().isRecording())) {
if (variantProperty.value() != value) if (variantProperty.value() != value)
variantProperty.setDynamicTypeNameAndValue(variantProperty.dynamicTypeName(), value); variantProperty.setDynamicTypeNameAndValue(variantProperty.dynamicTypeName(), value);
} else { } else {

View File

@@ -446,7 +446,7 @@ QmlDesigner::AbstractView *GradientModel::view() const
void GradientModel::resetPuppet() void GradientModel::resetPuppet()
{ {
QTimer::singleShot(1000, [this]() { view()->resetPuppet(); }); QTimer::singleShot(1000, view(), &QmlDesigner::AbstractView::resetPuppet);
} }
QmlDesigner::ModelNode GradientModel::createGradientNode() QmlDesigner::ModelNode GradientModel::createGradientNode()

View File

@@ -704,7 +704,7 @@ QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &metaTyp
QString qmlInnerTemplate = ""; QString qmlInnerTemplate = "";
qmlInnerTemplate += "Section {\n"; qmlInnerTemplate += "Section {\n";
qmlInnerTemplate += "caption: \""+ QObject::tr("User Added Properties") + "\"\n"; qmlInnerTemplate += "caption: \"" + QObject::tr("Exposed Custom Properties") + "\"\n";
qmlInnerTemplate += anchorLeftRight; qmlInnerTemplate += anchorLeftRight;
qmlInnerTemplate += "leftPadding: 0\n"; qmlInnerTemplate += "leftPadding: 0\n";
qmlInnerTemplate += "rightPadding: 0\n"; qmlInnerTemplate += "rightPadding: 0\n";

View File

@@ -95,6 +95,7 @@ void StatesEditorModel::reset()
QAbstractListModel::endResetModel(); QAbstractListModel::endResetModel();
evaluateExtend(); evaluateExtend();
emit baseStateChanged();
} }
QVariant StatesEditorModel::data(const QModelIndex &index, int role) const QVariant StatesEditorModel::data(const QModelIndex &index, int role) const

View File

@@ -122,7 +122,6 @@ public slots:
void removeState(int nodeId); void removeState(int nodeId);
private: private:
StatesEditorWidget *statesEditorWidget() const;
void resetModel(); void resetModel();
void resetPropertyChangesModels(); void resetPropertyChangesModels();
void resetExtend(); void resetExtend();

View File

@@ -34,9 +34,8 @@ void DesignerSettings::insert(const QHash<QByteArray, QVariant> &settingsHash)
QVariant DesignerSettings::value(const QByteArray &key, const QVariant &defaultValue) const QVariant DesignerSettings::value(const QByteArray &key, const QVariant &defaultValue) const
{ {
Q_UNUSED(defaultValue)
QMutexLocker locker(&m_mutex); QMutexLocker locker(&m_mutex);
return m_cache.value(key); return m_cache.value(key, defaultValue);
} }
void DesignerSettings::restoreValue(QSettings *settings, const QByteArray &key, const QVariant &defaultValue) void DesignerSettings::restoreValue(QSettings *settings, const QByteArray &key, const QVariant &defaultValue)

View File

@@ -11,7 +11,7 @@ namespace Internal {
DebugMessagesModel::DebugMessagesModel(QmlProfilerModelManager *manager, DebugMessagesModel::DebugMessagesModel(QmlProfilerModelManager *manager,
Timeline::TimelineModelAggregator *parent) : Timeline::TimelineModelAggregator *parent) :
QmlProfilerTimelineModel(manager, DebugMessage, MaximumRangeType, ProfileDebugMessages, parent), QmlProfilerTimelineModel(manager, DebugMessage, UndefinedRangeType, ProfileDebugMessages, parent),
m_maximumMsgType(-1) m_maximumMsgType(-1)
{ {
} }

View File

@@ -17,7 +17,7 @@ namespace Internal {
InputEventsModel::InputEventsModel(QmlProfilerModelManager *manager, InputEventsModel::InputEventsModel(QmlProfilerModelManager *manager,
Timeline::TimelineModelAggregator *parent) : Timeline::TimelineModelAggregator *parent) :
QmlProfilerTimelineModel(manager, Event, MaximumRangeType, ProfileInputEvents, parent), QmlProfilerTimelineModel(manager, Event, UndefinedRangeType, ProfileInputEvents, parent),
m_keyTypeId(-1), m_mouseTypeId(-1) m_keyTypeId(-1), m_mouseTypeId(-1)
{ {
} }
@@ -128,6 +128,8 @@ int InputEventsModel::collapsedRow(int index) const
void InputEventsModel::loadEvent(const QmlEvent &event, const QmlEventType &type) void InputEventsModel::loadEvent(const QmlEvent &event, const QmlEventType &type)
{ {
if (type.detailType() >= MaximumInputEventType)
return;
m_data.insert(insert(event.timestamp(), 0, type.detailType()), m_data.insert(insert(event.timestamp(), 0, type.detailType()),
Item(static_cast<InputEventType>(event.number<qint32>(0)), Item(static_cast<InputEventType>(event.number<qint32>(0)),
event.number<qint32>(1), event.number<qint32>(2))); event.number<qint32>(1), event.number<qint32>(2)));

View File

@@ -14,7 +14,7 @@ class InputEventsModel : public QmlProfilerTimelineModel
public: public:
struct Item { struct Item {
Item(InputEventType type = MaximumInputEventType, int a = 0, int b = 0); Item(InputEventType type = UndefinedInputEventType, int a = 0, int b = 0);
InputEventType type; InputEventType type;
int a; int a;
int b; int b;

View File

@@ -13,7 +13,7 @@ namespace Internal {
MemoryUsageModel::MemoryUsageModel(QmlProfilerModelManager *manager, MemoryUsageModel::MemoryUsageModel(QmlProfilerModelManager *manager,
Timeline::TimelineModelAggregator *parent) : Timeline::TimelineModelAggregator *parent) :
QmlProfilerTimelineModel(manager, MemoryAllocation, MaximumRangeType, ProfileMemory, parent) QmlProfilerTimelineModel(manager, MemoryAllocation, UndefinedRangeType, ProfileMemory, parent)
{ {
// Register additional features. The base class already registers the main feature. // Register additional features. The base class already registers the main feature.
// Don't register initializer, finalizer, or clearer as the base class has done so already. // Don't register initializer, finalizer, or clearer as the base class has done so already.
@@ -121,7 +121,7 @@ QVariantMap MemoryUsageModel::details(int index) const
void MemoryUsageModel::loadEvent(const QmlEvent &event, const QmlEventType &type) void MemoryUsageModel::loadEvent(const QmlEvent &event, const QmlEventType &type)
{ {
if (type.message() != MemoryAllocation) { if (type.message() != MemoryAllocation) {
if (type.rangeType() != MaximumRangeType) { if (type.rangeType() != UndefinedRangeType) {
m_continuation = ContinueNothing; m_continuation = ContinueNothing;
if (event.rangeStage() == RangeStart) if (event.rangeStage() == RangeStart)
m_rangeStack.push(RangeStackFrame(event.typeIndex(), event.timestamp())); m_rangeStack.push(RangeStackFrame(event.typeIndex(), event.timestamp()));

View File

@@ -13,7 +13,7 @@ namespace Internal {
PixmapCacheModel::PixmapCacheModel(QmlProfilerModelManager *manager, PixmapCacheModel::PixmapCacheModel(QmlProfilerModelManager *manager,
Timeline::TimelineModelAggregator *parent) : Timeline::TimelineModelAggregator *parent) :
QmlProfilerTimelineModel(manager, PixmapCacheEvent, MaximumRangeType, ProfilePixmapCache, QmlProfilerTimelineModel(manager, PixmapCacheEvent, UndefinedRangeType, ProfilePixmapCache,
parent) parent)
{ {
} }

View File

@@ -17,7 +17,7 @@ static ProfileFeature qmlFeatureFromType(Message message, RangeType rangeType, i
case AnimationFrame: case AnimationFrame:
return ProfileAnimations; return ProfileAnimations;
default: default:
return MaximumProfileFeature; return UndefinedProfileFeature;
} }
} }
case PixmapCacheEvent: case PixmapCacheEvent:
@@ -29,7 +29,11 @@ static ProfileFeature qmlFeatureFromType(Message message, RangeType rangeType, i
case DebugMessage: case DebugMessage:
return ProfileDebugMessages; return ProfileDebugMessages;
case Quick3DEvent: case Quick3DEvent:
return ProfileQuick3D; // Check if it's actually Quick3DEvent since old traces used MaximumMessage
// (whose value is now Quick3DEvent value) as undefined value
if (rangeType == UndefinedRangeType)
return ProfileQuick3D;
return featureFromRangeType(rangeType);
default: default:
return featureFromRangeType(rangeType); return featureFromRangeType(rangeType);
} }
@@ -46,6 +50,9 @@ QDataStream &operator>>(QDataStream &stream, QmlEventType &type)
type.m_message = static_cast<Message>(message); type.m_message = static_cast<Message>(message);
type.m_rangeType = static_cast<RangeType>(rangeType); type.m_rangeType = static_cast<RangeType>(rangeType);
type.setFeature(qmlFeatureFromType(type.m_message, type.m_rangeType, type.m_detailType)); type.setFeature(qmlFeatureFromType(type.m_message, type.m_rangeType, type.m_detailType));
// Update message if qmlFeatureFromType determined it is not Quick3D event
if (type.m_message == Quick3DEvent && type.feature() != ProfileQuick3D)
type.m_message = UndefinedMessage;
return stream; return stream;
} }

View File

@@ -17,7 +17,7 @@ class QmlEventType : public Timeline::TraceEventType {
public: public:
static const qint32 staticClassId = 0x716d6c74; // 'qmlt'; static const qint32 staticClassId = 0x716d6c74; // 'qmlt';
QmlEventType(Message message = MaximumMessage, RangeType rangeType = MaximumRangeType, QmlEventType(Message message = UndefinedMessage, RangeType rangeType = UndefinedRangeType,
int detailType = -1, const QmlEventLocation &location = QmlEventLocation(), int detailType = -1, const QmlEventLocation &location = QmlEventLocation(),
const QString &data = QString(), const QString &displayName = QString()); const QString &data = QString(), const QString &displayName = QString());

View File

@@ -21,7 +21,7 @@ namespace Internal {
QmlProfilerAnimationsModel::QmlProfilerAnimationsModel(QmlProfilerModelManager *manager, QmlProfilerAnimationsModel::QmlProfilerAnimationsModel(QmlProfilerModelManager *manager,
Timeline::TimelineModelAggregator *parent) : Timeline::TimelineModelAggregator *parent) :
QmlProfilerTimelineModel(manager, Event, MaximumRangeType, ProfileAnimations, parent) QmlProfilerTimelineModel(manager, Event, UndefinedRangeType, ProfileAnimations, parent)
{ {
m_minNextStartTimes[0] = m_minNextStartTimes[1] = 0; m_minNextStartTimes[0] = m_minNextStartTimes[1] = 0;
} }

View File

@@ -8,7 +8,8 @@
namespace QmlProfiler { namespace QmlProfiler {
enum Message { enum Message {
Event, UndefinedMessage = 0xff,
Event = 0,
RangeStart, RangeStart,
RangeData, RangeData,
RangeLocation, RangeLocation,
@@ -24,7 +25,8 @@ enum Message {
}; };
enum EventType { enum EventType {
FramePaint, // unused UndefinedEventType = 0xff,
FramePaint = 0, // unused
Mouse, Mouse,
Key, Key,
AnimationFrame, // new Qt5 paint events AnimationFrame, // new Qt5 paint events
@@ -35,7 +37,8 @@ enum EventType {
}; };
enum Quick3DEventType { enum Quick3DEventType {
Quick3DRenderFrame, UndefinedQuick3DEventType = 0xff,
Quick3DRenderFrame = 0,
Quick3DSynchronizeFrame, Quick3DSynchronizeFrame,
Quick3DPrepareFrame, Quick3DPrepareFrame,
Quick3DMeshLoad, Quick3DMeshLoad,
@@ -50,7 +53,8 @@ enum Quick3DEventType {
}; };
enum RangeType { enum RangeType {
Painting, // old Qt4 paint events UndefinedRangeType = 0xff,
Painting = 0, // old Qt4 paint events
Compiling, Compiling,
Creating, Creating,
Binding, Binding,
@@ -61,7 +65,8 @@ enum RangeType {
}; };
enum BindingType { enum BindingType {
QmlBinding, UndefinedBindingType = 0xff,
QmlBinding = 0,
V8Binding, V8Binding,
OptimizedBinding, OptimizedBinding,
QPainterEvent, QPainterEvent,
@@ -70,7 +75,8 @@ enum BindingType {
}; };
enum PixmapEventType { enum PixmapEventType {
PixmapSizeKnown, UndefinedPixmapEventType = 0xff,
PixmapSizeKnown = 0,
PixmapReferenceCountChanged, PixmapReferenceCountChanged,
PixmapCacheCountChanged, PixmapCacheCountChanged,
PixmapLoadingStarted, PixmapLoadingStarted,
@@ -81,7 +87,8 @@ enum PixmapEventType {
}; };
enum InputEventType { enum InputEventType {
InputKeyPress, UndefinedInputEventType = 0xff,
InputKeyPress = 0,
InputKeyRelease, InputKeyRelease,
InputKeyUnknown, InputKeyUnknown,
@@ -96,7 +103,8 @@ enum InputEventType {
}; };
enum SceneGraphFrameType { enum SceneGraphFrameType {
SceneGraphRendererFrame, // Render Thread UndefinedSceheGraphFrameType = 0xff,
SceneGraphRendererFrame = 0, // Render Thread
SceneGraphAdaptationLayerFrame, // Render Thread SceneGraphAdaptationLayerFrame, // Render Thread
SceneGraphContextFrame, // Render Thread SceneGraphContextFrame, // Render Thread
SceneGraphRenderLoopFrame, // Render Thread SceneGraphRenderLoopFrame, // Render Thread
@@ -111,7 +119,8 @@ enum SceneGraphFrameType {
}; };
enum MemoryType { enum MemoryType {
HeapPage, UndefinedMemoryType = 0xff,
HeapPage = 0,
LargeItem, LargeItem,
SmallItem, SmallItem,
@@ -119,14 +128,16 @@ enum MemoryType {
}; };
enum AnimationThread { enum AnimationThread {
GuiThread, UndefinedAnimationThread = 0xff,
GuiThread = 0,
RenderThread, RenderThread,
MaximumAnimationThread MaximumAnimationThread
}; };
enum ProfileFeature { enum ProfileFeature {
ProfileJavaScript, UndefinedProfileFeature = 0xff,
ProfileJavaScript = 0,
ProfileMemory, ProfileMemory,
ProfilePixmapCache, ProfilePixmapCache,
ProfileSceneGraph, ProfileSceneGraph,
@@ -159,7 +170,7 @@ inline ProfileFeature featureFromRangeType(RangeType range)
case Javascript: case Javascript:
return ProfileJavaScript; return ProfileJavaScript;
default: default:
return MaximumProfileFeature; return UndefinedProfileFeature;
} }
} }

View File

@@ -377,7 +377,7 @@ QmlProfilerModelManager::rangeFilter(qint64 rangeStart, qint64 rangeEnd) const
// Double-check if rangeStart has been crossed. Some versions of Qt send dirty data. // Double-check if rangeStart has been crossed. Some versions of Qt send dirty data.
qint64 adjustedTimestamp = event.timestamp(); qint64 adjustedTimestamp = event.timestamp();
if (event.timestamp() < rangeStart && !crossedRangeStart) { if (event.timestamp() < rangeStart && !crossedRangeStart) {
if (type.rangeType() != MaximumRangeType) { if (type.rangeType() != UndefinedRangeType) {
if (event.rangeStage() == RangeStart) if (event.rangeStage() == RangeStart)
stack.push(event); stack.push(event);
else if (event.rangeStage() == RangeEnd && !stack.isEmpty()) else if (event.rangeStage() == RangeEnd && !stack.isEmpty())
@@ -398,7 +398,7 @@ QmlProfilerModelManager::rangeFilter(qint64 rangeStart, qint64 rangeEnd) const
crossedRangeStart = true; crossedRangeStart = true;
} }
if (event.timestamp() > rangeEnd) { if (event.timestamp() > rangeEnd) {
if (type.rangeType() != MaximumRangeType) { if (type.rangeType() != UndefinedRangeType) {
if (event.rangeStage() == RangeEnd) { if (event.rangeStage() == RangeEnd) {
if (stack.isEmpty()) { if (stack.isEmpty()) {
QmlEvent endEvent(event); QmlEvent endEvent(event);

View File

@@ -23,7 +23,7 @@ namespace Internal {
QmlProfilerRangeModel::QmlProfilerRangeModel(QmlProfilerModelManager *manager, RangeType range, QmlProfilerRangeModel::QmlProfilerRangeModel(QmlProfilerModelManager *manager, RangeType range,
Timeline::TimelineModelAggregator *parent) : Timeline::TimelineModelAggregator *parent) :
QmlProfilerTimelineModel(manager, MaximumMessage, range, featureFromRangeType(range), parent) QmlProfilerTimelineModel(manager, UndefinedMessage, range, featureFromRangeType(range), parent)
{ {
m_expandedRowTypes << -1; m_expandedRowTypes << -1;
} }

View File

@@ -148,7 +148,7 @@ void QmlProfilerTraceClientPrivate::processCurrentEvent()
// all ranges are perfectly nested. This is why we can defer the type resolution until either // all ranges are perfectly nested. This is why we can defer the type resolution until either
// the range ends or a child range starts. With only the information in RangeStart we wouldn't // the range ends or a child range starts. With only the information in RangeStart we wouldn't
// be able to uniquely identify the event type. // be able to uniquely identify the event type.
Message rangeStage = currentEvent.type.rangeType() == MaximumRangeType ? Message rangeStage = currentEvent.type.rangeType() == UndefinedRangeType ?
currentEvent.type.message() : currentEvent.event.rangeStage(); currentEvent.type.message() : currentEvent.event.rangeStage();
switch (rangeStage) { switch (rangeStage) {
case RangeStart: case RangeStart:
@@ -311,7 +311,7 @@ void QmlProfilerTraceClient::setRequestedFeatures(quint64 features)
d->currentEvent.event.setTimestamp(context.timestamp > 0 ? context.timestamp : 0); d->currentEvent.event.setTimestamp(context.timestamp > 0 ? context.timestamp : 0);
d->currentEvent.event.setTypeIndex(-1); d->currentEvent.event.setTypeIndex(-1);
d->currentEvent.event.setString(text); d->currentEvent.event.setString(text);
d->currentEvent.type = QmlEventType(DebugMessage, MaximumRangeType, type, d->currentEvent.type = QmlEventType(DebugMessage, UndefinedRangeType, type,
QmlEventLocation(context.file, context.line, 1)); QmlEventLocation(context.file, context.line, 1));
d->currentEvent.serverTypeId = 0; d->currentEvent.serverTypeId = 0;
d->processCurrentEvent(); d->processCurrentEvent();
@@ -328,6 +328,8 @@ void QmlProfilerTraceClient::setFlushInterval(quint32 flushInterval)
bool QmlProfilerTraceClientPrivate::updateFeatures(quint8 feature) bool QmlProfilerTraceClientPrivate::updateFeatures(quint8 feature)
{ {
if (feature == UndefinedProfileFeature)
return true;
quint64 flag = 1ULL << feature; quint64 flag = 1ULL << feature;
if (!(requestedFeatures & flag)) if (!(requestedFeatures & flag))
return false; return false;

View File

@@ -59,7 +59,7 @@ Q_STATIC_ASSERT(sizeof(MESSAGE_STRINGS) == MaximumMessage * sizeof(const char *)
static QPair<Message, RangeType> qmlTypeAsEnum(const QString &typeString) static QPair<Message, RangeType> qmlTypeAsEnum(const QString &typeString)
{ {
QPair<Message, RangeType> ret(MaximumMessage, MaximumRangeType); QPair<Message, RangeType> ret(UndefinedMessage, UndefinedRangeType);
for (int i = 0; i < MaximumMessage; ++i) { for (int i = 0; i < MaximumMessage; ++i) {
if (typeString == _(MESSAGE_STRINGS[i])) { if (typeString == _(MESSAGE_STRINGS[i])) {
@@ -75,7 +75,7 @@ static QPair<Message, RangeType> qmlTypeAsEnum(const QString &typeString)
} }
} }
if (ret.first == MaximumMessage && ret.second == MaximumRangeType) { if (ret.first == UndefinedMessage && ret.second == UndefinedRangeType) {
bool isNumber = false; bool isNumber = false;
int type = typeString.toUInt(&isNumber); int type = typeString.toUInt(&isNumber);
if (isNumber && type < MaximumRangeType) if (isNumber && type < MaximumRangeType)
@@ -288,7 +288,7 @@ void QmlProfilerTraceFile::loadEventTypes(QXmlStreamReader &stream)
int typeIndex = -1; int typeIndex = -1;
QPair<Message, RangeType> messageAndRange(MaximumMessage, MaximumRangeType); QPair<Message, RangeType> messageAndRange(UndefinedMessage, UndefinedRangeType);
int detailType = -1; int detailType = -1;
QString displayName; QString displayName;
QString data; QString data;
@@ -296,7 +296,7 @@ void QmlProfilerTraceFile::loadEventTypes(QXmlStreamReader &stream)
int line = 0, column = 0; int line = 0, column = 0;
auto clearType = [&](){ auto clearType = [&](){
messageAndRange = QPair<Message, RangeType>(MaximumMessage, MaximumRangeType); messageAndRange = QPair<Message, RangeType>(UndefinedMessage, UndefinedRangeType);
detailType = -1; detailType = -1;
displayName.clear(); displayName.clear();
data.clear(); data.clear();
@@ -368,7 +368,7 @@ void QmlProfilerTraceFile::loadEventTypes(QXmlStreamReader &stream)
// confusing), even though they clearly aren't ranges. Convert that to something // confusing), even though they clearly aren't ranges. Convert that to something
// sane here. // sane here.
if (detailType == 4) { if (detailType == 4) {
messageAndRange = QPair<Message, RangeType>(Event, MaximumRangeType); messageAndRange = QPair<Message, RangeType>(Event, UndefinedRangeType);
detailType = AnimationFrame; detailType = AnimationFrame;
} }
} }
@@ -674,13 +674,13 @@ void QmlProfilerTraceFile::saveQtd(QIODevice *device)
QStack<QmlEvent> stack; QStack<QmlEvent> stack;
qint64 lastProgressTimestamp = traceStart(); qint64 lastProgressTimestamp = traceStart();
modelManager()->replayQmlEvents([&](const QmlEvent &event, const QmlEventType &type) { modelManager()->replayQmlEvents([&](const QmlEvent &event, const QmlEventType &type) {
if (type.rangeType() != MaximumRangeType && event.rangeStage() == RangeStart) { if (type.rangeType() != UndefinedRangeType && event.rangeStage() == RangeStart) {
stack.push(event); stack.push(event);
return; return;
} }
stream.writeStartElement(_("range")); stream.writeStartElement(_("range"));
if (type.rangeType() != MaximumRangeType && event.rangeStage() == RangeEnd) { if (type.rangeType() != UndefinedRangeType && event.rangeStage() == RangeEnd) {
QmlEvent start = stack.pop(); QmlEvent start = stack.pop();
stream.writeAttribute(_("startTime"), QString::number(start.timestamp())); stream.writeAttribute(_("startTime"), QString::number(start.timestamp()));
stream.writeAttribute(_("duration"), stream.writeAttribute(_("duration"),

View File

@@ -14,10 +14,10 @@ QDataStream &operator>>(QDataStream &stream, QmlTypedEvent &event)
stream >> time >> messageType; stream >> time >> messageType;
if (messageType < 0 || messageType > MaximumMessage) if (messageType < 0 || messageType >= MaximumMessage)
messageType = MaximumMessage; messageType = UndefinedMessage;
RangeType rangeType = MaximumRangeType; RangeType rangeType = UndefinedRangeType;
if (!stream.atEnd()) { if (!stream.atEnd()) {
stream >> subtype; stream >> subtype;
if (subtype >= 0 && subtype < MaximumRangeType) if (subtype >= 0 && subtype < MaximumRangeType)
@@ -32,7 +32,9 @@ QDataStream &operator>>(QDataStream &stream, QmlTypedEvent &event)
switch (messageType) { switch (messageType) {
case Event: { case Event: {
event.type = QmlEventType(static_cast<Message>(messageType), MaximumRangeType, subtype); if (subtype >= MaximumEventType)
subtype = UndefinedEventType;
event.type = QmlEventType(static_cast<Message>(messageType), UndefinedRangeType, subtype);
switch (subtype) { switch (subtype) {
case StartTrace: case StartTrace:
case EndTrace: { case EndTrace: {
@@ -76,7 +78,7 @@ QDataStream &operator>>(QDataStream &stream, QmlTypedEvent &event)
break; break;
} }
case Complete: { case Complete: {
event.type = QmlEventType(static_cast<Message>(messageType), MaximumRangeType, subtype); event.type = QmlEventType(static_cast<Message>(messageType), UndefinedRangeType, subtype);
break; break;
} }
case SceneGraphFrame: { case SceneGraphFrame: {
@@ -88,7 +90,7 @@ QDataStream &operator>>(QDataStream &stream, QmlTypedEvent &event)
params.push_back(param); params.push_back(param);
} }
event.type = QmlEventType(static_cast<Message>(messageType), MaximumRangeType, subtype); event.type = QmlEventType(static_cast<Message>(messageType), UndefinedRangeType, subtype);
event.event.setNumbers<QVarLengthArray<qint64>, qint64>(params); event.event.setNumbers<QVarLengthArray<qint64>, qint64>(params);
break; break;
} }
@@ -103,7 +105,7 @@ QDataStream &operator>>(QDataStream &stream, QmlTypedEvent &event)
refcount = 1; refcount = 1;
} }
event.type = QmlEventType(static_cast<Message>(messageType), MaximumRangeType, subtype, event.type = QmlEventType(static_cast<Message>(messageType), UndefinedRangeType, subtype,
QmlEventLocation(filename, 0, 0)); QmlEventLocation(filename, 0, 0));
event.event.setNumbers<qint32>({width, height, refcount}); event.event.setNumbers<qint32>({width, height, refcount});
break; break;
@@ -112,7 +114,7 @@ QDataStream &operator>>(QDataStream &stream, QmlTypedEvent &event)
qint64 delta; qint64 delta;
stream >> delta; stream >> delta;
event.type = QmlEventType(static_cast<Message>(messageType), MaximumRangeType, subtype); event.type = QmlEventType(static_cast<Message>(messageType), UndefinedRangeType, subtype);
event.event.setNumbers<qint64>({delta}); event.event.setNumbers<qint64>({delta});
break; break;
} }
@@ -125,7 +127,7 @@ QDataStream &operator>>(QDataStream &stream, QmlTypedEvent &event)
// otherwise it's the old binding type of 4 bytes // otherwise it's the old binding type of 4 bytes
} }
event.type = QmlEventType(MaximumMessage, rangeType, -1); event.type = QmlEventType(UndefinedMessage, rangeType, -1);
event.event.setRangeStage(RangeStart); event.event.setRangeStage(RangeStart);
break; break;
} }
@@ -133,7 +135,7 @@ QDataStream &operator>>(QDataStream &stream, QmlTypedEvent &event)
QString data; QString data;
stream >> data; stream >> data;
event.type = QmlEventType(MaximumMessage, rangeType, -1, QmlEventLocation(), data); event.type = QmlEventType(UndefinedMessage, rangeType, -1, QmlEventLocation(), data);
event.event.setRangeStage(RangeData); event.event.setRangeStage(RangeData);
if (!stream.atEnd()) if (!stream.atEnd())
stream >> event.serverTypeId; stream >> event.serverTypeId;
@@ -151,13 +153,13 @@ QDataStream &operator>>(QDataStream &stream, QmlTypedEvent &event)
stream >> event.serverTypeId; stream >> event.serverTypeId;
} }
event.type = QmlEventType(MaximumMessage, rangeType, -1, event.type = QmlEventType(UndefinedMessage, rangeType, -1,
QmlEventLocation(filename, line, column)); QmlEventLocation(filename, line, column));
event.event.setRangeStage(RangeLocation); event.event.setRangeStage(RangeLocation);
break; break;
} }
case RangeEnd: { case RangeEnd: {
event.type = QmlEventType(MaximumMessage, rangeType, -1); event.type = QmlEventType(UndefinedMessage, rangeType, -1);
event.event.setRangeStage(RangeEnd); event.event.setRangeStage(RangeEnd);
break; break;
} }
@@ -170,13 +172,13 @@ QDataStream &operator>>(QDataStream &stream, QmlTypedEvent &event)
stream >> param; stream >> param;
params.push_back(param); params.push_back(param);
} }
event.type = QmlEventType(static_cast<Message>(messageType), MaximumRangeType, subtype); event.type = QmlEventType(static_cast<Message>(messageType), UndefinedRangeType, subtype);
event.event.setNumbers<QVarLengthArray<qint64>, qint64>(params); event.event.setNumbers<QVarLengthArray<qint64>, qint64>(params);
break; break;
} }
default: default:
event.event.setNumbers<char>({}); event.event.setNumbers<char>({});
event.type = QmlEventType(static_cast<Message>(messageType), MaximumRangeType, subtype); event.type = QmlEventType(static_cast<Message>(messageType), UndefinedRangeType, subtype);
break; break;
} }

View File

@@ -12,7 +12,7 @@ namespace Internal {
Quick3DModel::Quick3DModel(QmlProfilerModelManager *manager, Quick3DModel::Quick3DModel(QmlProfilerModelManager *manager,
Timeline::TimelineModelAggregator *parent) : Timeline::TimelineModelAggregator *parent) :
QmlProfilerTimelineModel(manager, Quick3DEvent, MaximumRangeType, ProfileQuick3D, parent), QmlProfilerTimelineModel(manager, Quick3DEvent, UndefinedRangeType, ProfileQuick3D, parent),
m_maximumMsgType(-1) m_maximumMsgType(-1)
{ {
} }
@@ -135,7 +135,9 @@ int Quick3DModel::collapsedRow(int index) const
void Quick3DModel::loadEvent(const QmlEvent &event, const QmlEventType &type) void Quick3DModel::loadEvent(const QmlEvent &event, const QmlEventType &type)
{ {
auto detailType = type.detailType(); int detailType = type.detailType();
if (detailType >= MaximumQuick3DFrameType)
return;
qint64 eventDuration = event.number<qint64>(0); qint64 eventDuration = event.number<qint64>(0);
qint64 eventTime = event.timestamp() - eventDuration; qint64 eventTime = event.timestamp() - eventDuration;
QVector<quint64> numbers = event.numbers<QVector<quint64>>(); QVector<quint64> numbers = event.numbers<QVector<quint64>>();

View File

@@ -56,7 +56,7 @@ Q_STATIC_ASSERT(sizeof(StageLabels) ==
SceneGraphTimelineModel::SceneGraphTimelineModel(QmlProfilerModelManager *manager, SceneGraphTimelineModel::SceneGraphTimelineModel(QmlProfilerModelManager *manager,
Timeline::TimelineModelAggregator *parent) : Timeline::TimelineModelAggregator *parent) :
QmlProfilerTimelineModel(manager, SceneGraphFrame, MaximumRangeType, ProfileSceneGraph, parent) QmlProfilerTimelineModel(manager, SceneGraphFrame, UndefinedRangeType, ProfileSceneGraph, parent)
{ {
} }

View File

@@ -24,7 +24,7 @@ void DebugMessagesModelTest::initTestCase()
QmlEvent event; QmlEvent event;
event.setTimestamp(i); event.setTimestamp(i);
event.setString(QString::fromLatin1("message %1").arg(i)); event.setString(QString::fromLatin1("message %1").arg(i));
QmlEventType type(DebugMessage, MaximumRangeType, i % (QtMsgType::QtInfoMsg + 1), QmlEventType type(DebugMessage, UndefinedRangeType, i % (QtMsgType::QtInfoMsg + 1),
QmlEventLocation("somefile.js", i, 10 - i)); QmlEventLocation("somefile.js", i, 10 - i));
event.setTypeIndex(manager.numEventTypes()); event.setTypeIndex(manager.numEventTypes());
manager.appendEventType(std::move(type)); manager.appendEventType(std::move(type));

View File

@@ -34,7 +34,7 @@ int FlameGraphModelTest::generateData(QmlProfilerModelManager *manager,
QmlEvent event; QmlEvent event;
if (i < 5) { if (i < 5) {
typeIndex = manager->appendEventType( typeIndex = manager->appendEventType(
QmlEventType(MaximumMessage, QmlEventType(UndefinedMessage,
static_cast<RangeType>(static_cast<int>(Javascript) - i), -1, static_cast<RangeType>(static_cast<int>(Javascript) - i), -1,
QmlEventLocation("somefile.js", i, 20 - i), QmlEventLocation("somefile.js", i, 20 - i),
QString("funcfunc"))); QString("funcfunc")));

View File

@@ -20,8 +20,8 @@ static InputEventType inputType(int i)
InputEventsModelTest::InputEventsModelTest(QObject *parent) : InputEventsModelTest::InputEventsModelTest(QObject *parent) :
QObject(parent), model(&manager, &aggregator) QObject(parent), model(&manager, &aggregator)
{ {
keyTypeId = manager.appendEventType(QmlEventType(Event, MaximumRangeType, Key)); keyTypeId = manager.appendEventType(QmlEventType(Event, UndefinedRangeType, Key));
mouseTypeId = manager.appendEventType(QmlEventType(Event, MaximumRangeType, Mouse)); mouseTypeId = manager.appendEventType(QmlEventType(Event, UndefinedRangeType, Mouse));
} }
void InputEventsModelTest::initTestCase() void InputEventsModelTest::initTestCase()

View File

@@ -20,11 +20,11 @@ void MemoryUsageModelTest::initTestCase()
heapPageTypeId = manager.numEventTypes(); heapPageTypeId = manager.numEventTypes();
manager.appendEventType(QmlEventType(MemoryAllocation, MaximumRangeType, HeapPage)); manager.appendEventType(QmlEventType(MemoryAllocation, UndefinedRangeType, HeapPage));
smallItemTypeId = manager.numEventTypes(); smallItemTypeId = manager.numEventTypes();
manager.appendEventType(QmlEventType(MemoryAllocation, MaximumRangeType, SmallItem)); manager.appendEventType(QmlEventType(MemoryAllocation, UndefinedRangeType, SmallItem));
largeItemTypeId = manager.numEventTypes(); largeItemTypeId = manager.numEventTypes();
manager.appendEventType(QmlEventType(MemoryAllocation, MaximumRangeType, LargeItem)); manager.appendEventType(QmlEventType(MemoryAllocation, UndefinedRangeType, LargeItem));
auto addMemoryEvents = [&]() { auto addMemoryEvents = [&]() {
QmlEvent event; QmlEvent event;
@@ -53,7 +53,7 @@ void MemoryUsageModelTest::initTestCase()
addMemoryEvents(); addMemoryEvents();
rangeTypeId = manager.numEventTypes(); rangeTypeId = manager.numEventTypes();
manager.appendEventType(QmlEventType(MaximumMessage, Javascript, -1, manager.appendEventType(QmlEventType(UndefinedMessage, Javascript, -1,
QmlEventLocation(QString("somefile.js"), 10, 20), QmlEventLocation(QString("somefile.js"), 10, 20),
QString("funcfunc"))); QString("funcfunc")));

View File

@@ -22,7 +22,7 @@ void PixmapCacheModelTest::initTestCase()
for (int i = 0; i < MaximumPixmapEventType; ++i) { for (int i = 0; i < MaximumPixmapEventType; ++i) {
eventTypeIndices[i] = manager.numEventTypes(); eventTypeIndices[i] = manager.numEventTypes();
manager.appendEventType(QmlEventType(PixmapCacheEvent, MaximumRangeType, i, manager.appendEventType(QmlEventType(PixmapCacheEvent, UndefinedRangeType, i,
QmlEventLocation("dings.png", 0, 0))); QmlEventLocation("dings.png", 0, 0)));
} }
@@ -37,7 +37,7 @@ void PixmapCacheModelTest::initTestCase()
for (int i = 0; i < MaximumPixmapEventType; ++i) { for (int i = 0; i < MaximumPixmapEventType; ++i) {
eventTypeIndices[i + MaximumPixmapEventType] = manager.numEventTypes(); eventTypeIndices[i + MaximumPixmapEventType] = manager.numEventTypes();
manager.appendEventType(QmlEventType(PixmapCacheEvent, MaximumRangeType, i, manager.appendEventType(QmlEventType(PixmapCacheEvent, UndefinedRangeType, i,
QmlEventLocation("blah.png", 0, 0))); QmlEventLocation("blah.png", 0, 0)));
} }

View File

@@ -15,13 +15,13 @@ QmlEventTypeTest::QmlEventTypeTest(QObject *parent) : QObject(parent)
void QmlEventTypeTest::testAccessors() void QmlEventTypeTest::testAccessors()
{ {
QmlEventType type; QmlEventType type;
QCOMPARE(type.message(), MaximumMessage); QCOMPARE(type.message(), UndefinedMessage);
QCOMPARE(type.rangeType(), MaximumRangeType); QCOMPARE(type.rangeType(), UndefinedMessage);
QCOMPARE(type.detailType(), -1); QCOMPARE(type.detailType(), -1);
QVERIFY(!type.location().isValid()); QVERIFY(!type.location().isValid());
QVERIFY(type.data().isEmpty()); QVERIFY(type.data().isEmpty());
QVERIFY(type.displayName().isEmpty()); QVERIFY(type.displayName().isEmpty());
QCOMPARE(static_cast<ProfileFeature>(type.feature()), MaximumProfileFeature); QCOMPARE(static_cast<ProfileFeature>(type.feature()), UndefinedProfileFeature);
type.setLocation(QmlEventLocation("blah.js", 12, 13)); type.setLocation(QmlEventLocation("blah.js", 12, 13));
QCOMPARE(type.location().filename(), QString("blah.js")); QCOMPARE(type.location().filename(), QString("blah.js"));
@@ -34,9 +34,9 @@ void QmlEventTypeTest::testAccessors()
type.setDisplayName("disdis"); type.setDisplayName("disdis");
QCOMPARE(type.displayName(), QString("disdis")); QCOMPARE(type.displayName(), QString("disdis"));
QmlEventType type2(MaximumMessage, Javascript, 12, QmlEventLocation("lala.js", 2, 3), "nehhh", QmlEventType type2(UndefinedMessage, Javascript, 12, QmlEventLocation("lala.js", 2, 3), "nehhh",
"brbr"); "brbr");
QCOMPARE(type2.message(), MaximumMessage); QCOMPARE(type2.message(), UndefinedMessage);
QCOMPARE(type2.rangeType(), Javascript); QCOMPARE(type2.rangeType(), Javascript);
QCOMPARE(type2.detailType(), 12); QCOMPARE(type2.detailType(), 12);
QCOMPARE(type2.location(), QmlEventLocation("lala.js", 2, 3)); QCOMPARE(type2.location(), QmlEventLocation("lala.js", 2, 3));
@@ -49,23 +49,23 @@ void QmlEventTypeTest::testFeature()
{ {
const quint8 features[][MaximumEventType] = { const quint8 features[][MaximumEventType] = {
// Event // Event
{MaximumProfileFeature, ProfileInputEvents, ProfileInputEvents, {UndefinedProfileFeature, ProfileInputEvents, ProfileInputEvents,
ProfileAnimations, MaximumProfileFeature, MaximumProfileFeature}, ProfileAnimations, UndefinedProfileFeature, UndefinedProfileFeature},
// RangeStart // RangeStart
{MaximumProfileFeature, MaximumProfileFeature, MaximumProfileFeature, {UndefinedProfileFeature, UndefinedProfileFeature, UndefinedProfileFeature,
MaximumProfileFeature, MaximumProfileFeature, MaximumProfileFeature}, UndefinedProfileFeature, UndefinedProfileFeature, UndefinedProfileFeature},
// RangeData // RangeData
{MaximumProfileFeature, MaximumProfileFeature, MaximumProfileFeature, {UndefinedProfileFeature, UndefinedProfileFeature, UndefinedProfileFeature,
MaximumProfileFeature, MaximumProfileFeature, MaximumProfileFeature}, UndefinedProfileFeature, UndefinedProfileFeature, UndefinedProfileFeature},
// RangeLocation // RangeLocation
{MaximumProfileFeature, MaximumProfileFeature, MaximumProfileFeature, {UndefinedProfileFeature, UndefinedProfileFeature, UndefinedProfileFeature,
MaximumProfileFeature, MaximumProfileFeature, MaximumProfileFeature}, UndefinedProfileFeature, UndefinedProfileFeature, UndefinedProfileFeature},
// RangeEnd // RangeEnd
{MaximumProfileFeature, MaximumProfileFeature, MaximumProfileFeature, {UndefinedProfileFeature, UndefinedProfileFeature, UndefinedProfileFeature,
MaximumProfileFeature, MaximumProfileFeature, MaximumProfileFeature}, UndefinedProfileFeature, UndefinedProfileFeature, UndefinedProfileFeature},
// Complete // Complete
{MaximumProfileFeature, MaximumProfileFeature, MaximumProfileFeature, {UndefinedProfileFeature, UndefinedProfileFeature, UndefinedProfileFeature,
MaximumProfileFeature, MaximumProfileFeature, MaximumProfileFeature}, UndefinedProfileFeature, UndefinedProfileFeature, UndefinedProfileFeature},
// PixmapCacheEvent // PixmapCacheEvent
{ProfilePixmapCache, ProfilePixmapCache, ProfilePixmapCache, {ProfilePixmapCache, ProfilePixmapCache, ProfilePixmapCache,
ProfilePixmapCache, ProfilePixmapCache, ProfilePixmapCache}, ProfilePixmapCache, ProfilePixmapCache, ProfilePixmapCache},
@@ -85,13 +85,13 @@ void QmlEventTypeTest::testFeature()
for (int i = 0; i < MaximumMessage; ++i) { for (int i = 0; i < MaximumMessage; ++i) {
for (int j = 0; j < MaximumEventType; ++j) { for (int j = 0; j < MaximumEventType; ++j) {
QmlEventType type(static_cast<Message>(i), MaximumRangeType, j); QmlEventType type(static_cast<Message>(i), UndefinedRangeType, j);
QCOMPARE(type.feature(), features[i][j]); QCOMPARE(type.feature(), features[i][j]);
} }
} }
for (int i = 0; i < MaximumRangeType; ++i) { for (int i = 0; i < MaximumRangeType; ++i) {
QmlEventType type(MaximumMessage, static_cast<RangeType>(i)); QmlEventType type(UndefinedMessage, static_cast<RangeType>(i));
QCOMPARE(static_cast<ProfileFeature>(type.feature()), QCOMPARE(static_cast<ProfileFeature>(type.feature()),
featureFromRangeType(static_cast<RangeType>(i))); featureFromRangeType(static_cast<RangeType>(i)));
} }
@@ -99,7 +99,7 @@ void QmlEventTypeTest::testFeature()
void QmlEventTypeTest::testStreamOps() void QmlEventTypeTest::testStreamOps()
{ {
QmlEventType type(MaximumMessage, Javascript, -1, QmlEventLocation("socken.js", 12, 13), QmlEventType type(UndefinedMessage, Javascript, -1, QmlEventLocation("socken.js", 12, 13),
"lalala", "lelele"); "lalala", "lelele");
QBuffer wbuffer; QBuffer wbuffer;

View File

@@ -25,7 +25,7 @@ void QmlProfilerAnimationsModelTest::initTestCase()
QmlEvent event; QmlEvent event;
event.setTypeIndex(manager.appendEventType( event.setTypeIndex(manager.appendEventType(
QmlEventType(Event, MaximumRangeType, AnimationFrame))); QmlEventType(Event, UndefinedRangeType, AnimationFrame)));
for (int i = 0; i < 10; ++i) { for (int i = 0; i < 10; ++i) {
event.setTimestamp(i); event.setTimestamp(i);

View File

@@ -27,7 +27,7 @@ DummyModel::DummyModel(QmlProfilerModelManager *manager,
void DummyModel::loadData() void DummyModel::loadData()
{ {
QmlEventType type(MaximumMessage, Binding); QmlEventType type(UndefinedMessage, Binding);
const int typeIndex = modelManager()->appendEventType(QmlEventType(type)); const int typeIndex = modelManager()->appendEventType(QmlEventType(type));
QCOMPARE(typeIndex, 0); QCOMPARE(typeIndex, 0);

View File

@@ -57,9 +57,13 @@ void QmlProfilerTraceClientTest::testMessageReceived()
modelManager.replayQmlEvents([&](const QmlEvent &event, const QmlEventType &type) { modelManager.replayQmlEvents([&](const QmlEvent &event, const QmlEventType &type) {
qint64 timestamp; qint64 timestamp;
qint32 message; quint8 message;
qint32 rangeType; quint8 rangeType;
checkStream >> timestamp >> message >> rangeType; checkStream >> timestamp >> message >> rangeType;
QVERIFY(message != MaximumMessage);
QVERIFY(rangeType != MaximumRangeType);
QVERIFY(type.message() != MaximumMessage);
QVERIFY(type.rangeType() != MaximumRangeType);
QCOMPARE(event.timestamp(), timestamp); QCOMPARE(event.timestamp(), timestamp);
QCOMPARE(type.message(), static_cast<Message>(message)); QCOMPARE(type.message(), static_cast<Message>(message));
QCOMPARE(type.rangeType(), static_cast<RangeType>(rangeType)); QCOMPARE(type.rangeType(), static_cast<RangeType>(rangeType));

View File

@@ -120,7 +120,8 @@ void UpdateInfoPlugin::doAutoCheckForUpdates()
void UpdateInfoPlugin::startCheckForUpdates() void UpdateInfoPlugin::startCheckForUpdates()
{ {
stopCheckForUpdates(); if (d->m_maintenanceToolProcess)
return; // do not trigger while update task is already running
QFutureInterface<void> futureIf; QFutureInterface<void> futureIf;
FutureProgress *futureProgress FutureProgress *futureProgress