Merge remote-tracking branch 'origin/5.0'

Conflicts:
	src/libs/utils/processreaper.cpp
	src/plugins/clangcodemodel/clangmodelmanagersupport.cpp
	src/plugins/cmakeprojectmanager/cmakeprocess.cpp

Change-Id: Ie248bcb02a80f3e02ab19d73033ce2ba31e7fd83
This commit is contained in:
Eike Ziller
2021-09-07 08:56:42 +02:00
101 changed files with 1050 additions and 663 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -132,6 +132,7 @@
\li \l{Animations} \li \l{Animations}
\li \l{3D Views} \li \l{3D Views}
\li \l{Group} \li \l{Group}
\li \l{Instanced Rendering}
\li \l{Skeletal Animation} \li \l{Skeletal Animation}
\li \l{3D Models} \li \l{3D Models}
\li \l{Materials and Shaders} \li \l{Materials and Shaders}

View File

@@ -49,20 +49,19 @@
\list 1 \list 1
\li Select \uicontrol File > \uicontrol {New File or Project} > \li Select \uicontrol File > \uicontrol {New File or Project} >
\if defined(qtcreator) \if defined(qtcreator)
\uicontrol Qt > \uicontrol {QML File (Qt Quick 2)} > \uicontrol Qt > \uicontrol {Qt Quick UI File} >
\else \else
\uicontrol {Qt Quick Files} > \uicontrol {Qt Quick File} > \uicontrol {Qt Quick Files} > \uicontrol {Qt Quick UI File} >
\endif \endif
\uicontrol Choose to create a new .qml file. \uicontrol Choose to create a new \c .ui.qml file.
\note Components are listed in \uicontrol Library > \note Components are listed in \uicontrol Library >
\uicontrol Components > \uicontrol {My Components} only \uicontrol Components > \uicontrol {My Components} only
if the filename begins with a capital letter. if the filename begins with a capital letter.
\li Click \uicontrol Design to open the component file (ui.qml) in \li Click \uicontrol Design to open the file in
\uicontrol {Form Editor}. \uicontrol {Form Editor}.
\li Drag-and-drop a component from \uicontrol Library to \li Drag-and-drop a component from \uicontrol Library to
\uicontrol Navigator or \uicontrol {Form Editor}. \uicontrol Navigator or \uicontrol {Form Editor}.
\li Edit component properties in the \uicontrol Properties view. \li Edit component properties in the \uicontrol Properties view.
\image qmldesigner-custom-component-properties.png
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 Dynamic Properties}{add properties for
components} in \uicontrol {Connection View} > \uicontrol Properties. components} in \uicontrol {Connection View} > \uicontrol Properties.

View File

@@ -70,6 +70,7 @@
\list \list
\li \l {3D Views} \li \l {3D Views}
\li \l {Group} \li \l {Group}
\li \l {Instanced Rendering}
\li \l {Skeletal Animation} \li \l {Skeletal Animation}
\li \l {3D Models} \li \l {3D Models}
\li \l {Materials and Shaders} \li \l {Materials and Shaders}

View File

@@ -94,6 +94,9 @@
\image qtquick-number-animation.gif "Number animation" \image qtquick-number-animation.gif "Number animation"
For an example of using property animation to animate the scale and opacity
of components, see the \l{Coffee Machine} example.
\section2 Setting Non-Animated Properties \section2 Setting Non-Animated Properties
To immediately change a property value during an animation To immediately change a property value during an animation

View File

@@ -42,12 +42,12 @@
\li Select \uicontrol File > \uicontrol {New File or Project} > \li Select \uicontrol File > \uicontrol {New File or Project} >
\if defined(qtcreator) \if defined(qtcreator)
\uicontrol Qt > \uicontrol {QML File (Qt Quick 2)} > \uicontrol Qt > \uicontrol {Qt Quick UI File} >
\else \else
\uicontrol {Qt Quick Files} > \uicontrol {Qt Quick File} > \uicontrol {Qt Quick Files} > \uicontrol {Qt Quick UI File} >
\endif \endif
\uicontrol Choose to create a QML file called Button.qml (for \uicontrol Choose to create a \l{UI Files}{UI file} called
example). Button.ui.qml (for example).
\note Components are listed in \l Library > \uicontrol Components > \note Components are listed in \l Library > \uicontrol Components >
\uicontrol {My Components} only if the filename begins with a \uicontrol {My Components} only if the filename begins with a
@@ -160,11 +160,12 @@
To create a button component, select \uicontrol File > To create a button component, select \uicontrol File >
\uicontrol {New File or Project} > \uicontrol {New File or Project} >
\if defined(qtcreator) \if defined(qtcreator)
\uicontrol Qt > \uicontrol {QML File (Qt Quick 2)} > \uicontrol Qt > \uicontrol {Qt Quick UI File} >
\else \else
\uicontrol {Qt Quick Files} > \uicontrol {Qt Quick File} > \uicontrol {Qt Quick Files} > \uicontrol {Qt Quick UI File} >
\endif \endif
\uicontrol Choose to create a file called Button.qml (for example). \uicontrol Choose to create a \l{UI Files}{UI file} called Button.ui.qml
(for example).
\note Components are listed in \l Library > \uicontrol Components > \note Components are listed in \l Library > \uicontrol Components >
\uicontrol {My Components} only if the filename begins with a \uicontrol {My Components} only if the filename begins with a
@@ -175,8 +176,7 @@
To construct the button component: To construct the button component:
\list 1 \list 1
\li Click \uicontrol {Design} to edit the component file in \li Click \uicontrol {Design} to edit the UI file in \l {Form Editor}.
\l {Form Editor}.
\li Select \l Library > \uicontrol Assets > \inlineimage plus.png \li Select \l Library > \uicontrol Assets > \inlineimage plus.png
to copy the image files you want to use to the project folder. to copy the image files you want to use to the project folder.
\li In \l Navigator, select the root component and set the \li In \l Navigator, select the root component and set the

View File

@@ -156,8 +156,8 @@
to rotate component instances in steps of 5 or 45 degrees, respectively. to rotate component instances in steps of 5 or 45 degrees, respectively.
You can set the \l{Managing 2D Transformations}{origin} in \l Properties > You can set the \l{Managing 2D Transformations}{origin} in \l Properties >
\uicontrol Advanced > \uicontrol Origin. There, you can also enter the value \uicontrol {Geometry - 2D} > \uicontrol Origin. There, you can also enter
of the \uicontrol Rotation property in degrees. the value of the \uicontrol Rotation property in degrees.
\section1 Zooming \section1 Zooming

View File

@@ -55,8 +55,10 @@
from the Qt UI Quick project to the application project. from the Qt UI Quick project to the application project.
You can use the \c RESOURCES option in the project configuration file to You can use the \c RESOURCES option in the project configuration file to
automatically add all the QML files and related assets to a Qt resource automatically add all the QML files and related assets to a
file. \l{The Qt Resource System}{Qt resource collection file (.qrc)}. However,
large files should be included as external binary resources instead of
compiling them into the binary.
The wizard automatically adds the \c QML_IMPORT_PATH option to the project The wizard automatically adds the \c QML_IMPORT_PATH option to the project
file for specifying the required file for specifying the required
@@ -132,6 +134,21 @@
\quotefile progressbar/main.cpp \quotefile progressbar/main.cpp
\section1 Handling Large Data Files
Graphical assets used in the UI, such as images, effects, or 3D scenes
are a typical cause for performance problems in UIs. Even building the
application requires huge amounts of memory if you try to include large
asset files, such as 100-MB 3D models or 64-MB textures, into the \c .qrc
file for compiling them into the binary.
First try to optimize your assets, as described in \l{Optimizing Designs}
and \l {Creating Optimized 3D Scenes}.
If you really need large assets, they should either be loaded directly from
the file system or use the Qt resource system in the dynamic way. For more
information, see \l{The Qt Resource System} in the Qt documentation.
\section1 Adding Custom Fonts \section1 Adding Custom Fonts
To \l{Using Custom Fonts}{use custom fonts} from the Qt Quick UI project, To \l{Using Custom Fonts}{use custom fonts} from the Qt Quick UI project,

View File

@@ -71,6 +71,7 @@
\li \l Animations \li \l Animations
\li \l{3D Views} \li \l{3D Views}
\li \l{Group} \li \l{Group}
\li \l{Instanced Rendering}
\li \l{Skeletal Animation} \li \l{Skeletal Animation}
\li \l{3D Models} \li \l{3D Models}
\li \l{Materials and Shaders} \li \l{Materials and Shaders}

View File

@@ -52,10 +52,10 @@
To animate component properties in the \uicontrol Timeline view, you To animate component properties in the \uicontrol Timeline view, you
must \l{Setting Keyframe Values}{insert keyframes} for them. In the must \l{Setting Keyframe Values}{insert keyframes} for them. In the
\l Properties view, select \uicontrol Settings > \l Properties view, select \inlineimage icons/action-icon.png
\uicontrol {Insert Keyframe} for a property that you want to animate. (\uicontrol Actions) > \uicontrol {Insert Keyframe} for a property that you
A keyframe track is generated for each component that you insert keyframes want to animate. A keyframe track is generated for each component that you
for. insert keyframes for.
\image studio-timeline-with-empty-tracks.png "Timeline view with a property" \image studio-timeline-with-empty-tracks.png "Timeline view with a property"

View File

@@ -132,9 +132,9 @@
\list 1 \list 1
\li In the \l Navigator view, select the component to animate. \li In the \l Navigator view, select the component to animate.
\li In the \l Properties view, select \uicontrol Settings > \li In the \l Properties view, select \inlineimage icons/action-icon.png
\uicontrol {Insert Keyframe} for the property that you want to (\uicontrol Actions) > \uicontrol {Insert Keyframe} for the property
animate. that you want to animate.
\li In the \l Timeline view, select the \li In the \l Timeline view, select the
\uicontrol {Per Property Recording} button \uicontrol {Per Property Recording} button
to start recording property changes. to start recording property changes.

View File

@@ -38,10 +38,10 @@
sliders. The progress of the brewing process is displayed as sliders. The progress of the brewing process is displayed as
an animation. When the coffee is ready, the startup screen appears again. an animation. When the coffee is ready, the startup screen appears again.
The \e {ApplicationFlow.ui.qml} file contains all the screens in the The \e {ApplicationFlowForm.ui.qml} file contains all the screens in the
UI. We use states to display the appropriate screen in the UI. We use \l{glossary-state}{states} to display the appropriate screen in
viewport and the timeline to animate the transitions between and on the viewport and the timeline to animate the \l{glossary-transition}
the screens. {transitions} between and on the screens.
\section1 Application Flow \section1 Application Flow
@@ -55,10 +55,10 @@
\printuntil } \printuntil }
\dots \dots
Selecting the coffee type triggers the respective signal handler in Selecting the coffee type triggers the respective \l{glossary-signal}
\e {SideBar.qml}, which sets the default mix for the selected coffee type. {signal handler} in \e {SideBar.qml}, which sets the default mix for
The following code snippet displays the \c {cappuccinoButton.onClicked()} the selected coffee type. The following code snippet displays the
signal handler: \c {cappuccinoButton.onClicked()} signal handler:
\quotefromfile CoffeeMachine/SideBar.qml \quotefromfile CoffeeMachine/SideBar.qml
\skipto cappuccinoButton.onClicked \skipto cappuccinoButton.onClicked
@@ -113,11 +113,11 @@
\section1 Using Timelines to Animate Transitions \section1 Using Timelines to Animate Transitions
The Coffee Machine application screens for choosing coffee, empty cup, and The Coffee Machine application screens for choosing coffee, empty cup, and
brewing each use custom components specified in separate component files brewing each use custom components specified in separate \l{UI Files}
(.qml). {UI files} (ui.qml).
We use the \uicontrol Timeline view to animate the transitions between We use the \l Timeline view to animate the transitions between the screens
the screens during the application flow in \e {ApplicationFlow.ui.qml}. during the application flow in \e {ApplicationFlowForm.ui.qml}.
\image coffee-machine-timeline.png \image coffee-machine-timeline.png
@@ -132,9 +132,9 @@
select the \inlineimage recordfill.png select the \inlineimage recordfill.png
(\uicontrol {Auto Key (K)}) button (or press \key k). (\uicontrol {Auto Key (K)}) button (or press \key k).
At frame 0, we set the X coordinate to 0 in \l Properties > \uicontrol At frame 0, we set the X coordinate to 0 in \l Properties >
Geometry > \uicontrol Position. We then move the playhead to 400 frames and \uicontrol {Geometry - 2D} > \uicontrol Position. We then move the
set the X coordinate to a negative value. playhead to 400 frames and set the X coordinate to a negative value.
\image coffee-machine-properties.png \image coffee-machine-properties.png
@@ -146,13 +146,13 @@
\section1 Using States to Move Between Screens \section1 Using States to Move Between Screens
We use the \uicontrol States view to determine the contents of the We use the \l States view to determine the contents of the
viewport. The animations are run when moving from one state to another. viewport. The animations are run when moving from one state to another.
\image coffee-machine-states.png \image coffee-machine-states.png
We create the states by moving from viewport to viewport in We create the states by moving from viewport to viewport in
\e ApplicationFlow.ui.qml and clicking \inlineimage plus.png "Add button" \e ApplicationFlowForm.ui.qml and selecting \uicontrol {Create New State}
in the \uicontrol States view. in the \uicontrol States view.
We also create states for animations that are run when moving to the We also create states for animations that are run when moving to the
@@ -171,7 +171,7 @@
the end frame to 200, because we are moving back on the timeline to display the end frame to 200, because we are moving back on the timeline to display
the selection sidebar. the selection sidebar.
In the \uicontrol {Transitions to states} field, we select the state to In the \uicontrol {Transition to state} field, we select the state to
switch to when the animation ends. In the lower part of the dialog, we switch to when the animation ends. In the lower part of the dialog, we
bind the states that don't have animations to fixed frames. bind the states that don't have animations to fixed frames.
*/ */

View File

@@ -34,9 +34,9 @@
\image ebikedesign.png "Standard screen" \image ebikedesign.png "Standard screen"
\e {E-Bike Design} is a control center application for electric bikes. \e {E-Bike Design} is a control center application for electric bikes.
The application contains a Standard screen that displays a speedometer, The application contains a \e Standard screen that displays a speedometer,
a Trip screen that displays statistics about the current trip, and a a \e Trip screen that displays statistics about the current trip, and a
Navigator screen that displays a map. \e Navigator screen that displays a map.
The Trip and Navigator screens display a small animated speedometer that The Trip and Navigator screens display a small animated speedometer that
the users can select to move back to the Standard screen. the users can select to move back to the Standard screen.
@@ -45,12 +45,13 @@
In the \e {Screen01.ui.qml} file, we place the screens in a row in the In the \e {Screen01.ui.qml} file, we place the screens in a row in the
following order from left to right: Trip, Standard, Navigator. We will following order from left to right: Trip, Standard, Navigator. We will
use states to show the appropriate screen in the viewport, and the timeline use \l{glossary-state}{states} to show the appropriate screen in the
to animate the transitions between and on the screens. viewport, and the timeline to animate the \l{glossary-transition}
{transitions} between and on the screens.
\section1 Using Timelines to Animate Transitions \section1 Using Timelines to Animate Transitions
We use the \uicontrol Timeline view to animate the transitions between We use the \l Timeline view to animate the transitions between
the screens in \e {Screen01.ui.qml}. the screens in \e {Screen01.ui.qml}.
Our viewport contains 1000 frames, so we select the Our viewport contains 1000 frames, so we select the
@@ -67,7 +68,7 @@
\image ebikedesign-timeline.png "Timeline view" \image ebikedesign-timeline.png "Timeline view"
At frame 0, we set the X coordinate to 0 in \l Properties > At frame 0, we set the X coordinate to 0 in \l Properties >
\uicontrol Geometry > \uicontrol Position to display the Trip screen. \uicontrol {Geometry - 2D} > \uicontrol Position to display the Trip screen.
We then move the playhead to frame 1000 and set the X coordinate to We then move the playhead to frame 1000 and set the X coordinate to
-1286 to display the Standard screen. We continue by moving the playhead -1286 to display the Standard screen. We continue by moving the playhead
to frame 2000 and setting the X coordinate to -2560 to display the to frame 2000 and setting the X coordinate to -2560 to display the
@@ -84,8 +85,8 @@
\image ebikedesign-trip-properties.png "Properties view of the Trip component" \image ebikedesign-trip-properties.png "Properties view of the Trip component"
We set values for the \uicontrol Visibility, We set values for the \uicontrol Scale, \uicontrol Visibility,
\uicontrol Opacity, \uicontrol currentFrame, and \uicontrol Scale properties \uicontrol Opacity, and \uicontrol currentFrame properties
to fade out the current screen when moving to another one and to make the to fade out the current screen when moving to another one and to make the
speedometer grow and shrink in size depending on its current position. speedometer grow and shrink in size depending on its current position.
@@ -94,7 +95,7 @@
\section1 Using States to Move Between Screens \section1 Using States to Move Between Screens
We use the \uicontrol States view to determine the contents of the viewport. We use the \l States view to determine the contents of the viewport.
The animations are run in a particular state or when moving from one state The animations are run in a particular state or when moving from one state
to another. to another.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@@ -39,14 +39,16 @@
First, we create an empty project, as described in \l {Creating Projects}. First, we create an empty project, as described in \l {Creating Projects}.
For the purposes of this example, we call the project \e progressbar. For the purposes of this example, we call the project \e progressbar.
In this example, we use two overlapping rectangles and a text label to In this example, we use two overlapping instances of the preset
create the progress bar. For another example of a progress bar, see the \l{basic-rectangle}{Rectangle} component and an instance of the preset
\l {progress-bar-control}{Progress Bar} component in Qt Quick Controls. \l{Text} component to create the progress bar. There is also a preset
\l {progress-bar-control}{Progress Bar} component available in
\uicontrol Library > \uicontrol Components > \uicontrol {Qt Quick Controls}.
In the \uicontrol Design mode, we drag-and-drop a \uicontrol Rectangle from In the \uicontrol Design mode, we drag-and-drop a \uicontrol Rectangle from
\l Library > \uicontrol Components > \uicontrol {Default Components} > \l Library > \uicontrol Components > \uicontrol {Default Components} >
\uicontrol Basic to \l {Form Editor} and modify its size to create the \uicontrol Basic to \l {Form Editor} and modify its size to create the
background for the progress bar. We change its ID to \e background in background for the progress bar. We change its ID to \e pb_back in
\l Properties. \l Properties.
We want to be able to control the background rectangle and the text label We want to be able to control the background rectangle and the text label
@@ -66,7 +68,7 @@
\image progressbar-rectangle.png "Progress bar background in the Form Editor" \image progressbar-rectangle.png "Progress bar background in the Form Editor"
We now drag-and-drop another rectangle on top of the background rectangle in We now drag-and-drop another rectangle on top of the background rectangle in
\uicontrol Navigator and change its ID to \e indicator in \uicontrol Navigator and change its ID to \e pb_front in
\uicontrol Properties. \uicontrol Properties.
We then anchor the left, top, and bottom of the indicator to its parent with We then anchor the left, top, and bottom of the indicator to its parent with
5-pixel margins. We leave the right side free because its value needs to 5-pixel margins. We leave the right side free because its value needs to
@@ -87,8 +89,8 @@
\section2 Adding Color Animation \section2 Adding Color Animation
First, we add a color animation to the \e root component. We select the First, we add a color animation to the \e root component in the \e Root.qml
\inlineimage plus.png file. We select the \inlineimage plus.png
button to add a 100-frame timeline to root. You can use the default button to add a 100-frame timeline to root. You can use the default
values for all other fields. values for all other fields.
@@ -103,8 +105,9 @@
We then set the color at frame 0 to green (\e {#8de98d}) in We then set the color at frame 0 to green (\e {#8de98d}) in
\uicontrol Properties > \uicontrol Text > \uicontrol {Text Color}. \uicontrol Properties > \uicontrol Text > \uicontrol {Text Color}.
We can either \l{Picking Colors}{pick a color} from the color selector We can either \l{Picking Colors}{pick a color} from the color selector
or use the \uicontrol {Set Binding} command in the \inlineimage submenu.png or use the \uicontrol {Set Binding} command in the
(\uicontrol Settings) menu to open the \uicontrol {Binding Editor}. \inlineimage icons/action-icon.png
(\uicontrol Actions) menu to open the \uicontrol {Binding Editor}.
We then move the playhead to frame 50 and set the text color to red We then move the playhead to frame 50 and set the text color to red
(\e {#de4f4f}). Finally, we move the playhead to frame 100 and set (\e {#de4f4f}). Finally, we move the playhead to frame 100 and set
@@ -117,10 +120,11 @@
\section2 Animating the Indicator \section2 Animating the Indicator
We select \e indicator in \uicontrol Navigator and then select the record We select \e pb_front in \uicontrol Navigator and then select the record
button again to animate the width of the indicator. At frame 0, we set the button again to animate the width of the indicator. At frame 0, we set the
width to 0 in \uicontrol Properties > \uicontrol Geometry > \uicontrol Size. width to 0 in \uicontrol Properties > \uicontrol {Geometry - 2D} >
We then move the playhead to 100 frames and set the width to 590. \uicontrol Size. We then move the playhead to 100 frames and set the width
to 590.
\image progressbar-timeline-indicator.png "Indicator timeline" \image progressbar-timeline-indicator.png "Indicator timeline"
@@ -160,9 +164,9 @@
open \e Root.qml in \uicontrol {Form Editor}. open \e Root.qml in \uicontrol {Form Editor}.
We want to be able to use the keyframe value as the value of the text label, We want to be able to use the keyframe value as the value of the text label,
so we will export it as a property alias. We select \e timeline in so we will export it as a \l{Adding Property Aliases}{property alias}. We
\uicontrol Navigator and then \uicontrol Properties > \uicontrol Timeline > select \e timeline in \uicontrol Navigator and then \uicontrol Properties >
\uicontrol {Current frame} > \uicontrol Settings > \uicontrol Timeline > \uicontrol {Current frame} > \uicontrol Actions >
\uicontrol {Export Property as Alias}. \uicontrol {Export Property as Alias}.
\image progressbar-root-export-property.png "Export keyframe group as a property" \image progressbar-root-export-property.png "Export keyframe group as a property"

View File

@@ -29,7 +29,7 @@
\title Side Menu \title Side Menu
\brief Illustrates how to create reusable components and an animated menu \brief Illustrates how to create reusable components and an animated menu
for applying effects. for applying 2D visual effects in Qt 5 projects.
\image sidemenu.png "Side menu example application" \image sidemenu.png "Side menu example application"
@@ -41,6 +41,9 @@
\l {2D Effects}{graphical effects}, such as hue, saturation, \l {2D Effects}{graphical effects}, such as hue, saturation,
and blur, to the images. and blur, to the images.
\note Only a subset of effects is available if you select
\uicontrol {Qt 6} when \l{Creating Projects}{creating the project}.
\section1 Creating Reusable Buttons \section1 Creating Reusable Buttons
We select \uicontrol File > \uicontrol {New File or Project} > We select \uicontrol File > \uicontrol {New File or Project} >
@@ -101,9 +104,9 @@
We construct the menu bar in the \e {MainFile.ui.qml} file using the We construct the menu bar in the \e {MainFile.ui.qml} file using the
\l {Form Editor}. The CustomButton component is listed in \l {Form Editor}. The CustomButton component is listed in
\l Library > \uicontrol Components > \uicontrol {My Components}. \l Library > \uicontrol Components > \uicontrol {My Components}.
We drag-and-drop several instances of the component to the We drag-and-drop several instances of the component to \uicontrol Navigator
\uicontrol {Form Editor} and enclose them in a RowLayout component instance or \uicontrol {Form Editor} and enclose them in a \uicontrol {Row Layout}
to lay them out as a menu bar. component instance to lay them out as a menu bar.
\image sidemenu-menubar.png \image sidemenu-menubar.png
@@ -123,20 +126,23 @@
\section1 Creating a Side Menu \section1 Creating a Side Menu
We can now continue to create a side menu that slides open when users We can now continue to create a side menu that slides open when users
click the burger menu. In the \uicontrol {Form Editor}, we use the click the burger menu. We drag-and-drop a \l Text component from
\l Text and \l {slider-control}{Slider} components to create separate \uicontrol Library > \uicontrol Components > \uicontrol {Default Components}
> \uicontrol Basic and a \l {slider-control}{Slider} component from
\uicontrol {Qt Quick Controls} to \uicontrol Navigator to create separate
submenus for each set of effects we want to apply to the images. We use submenus for each set of effects we want to apply to the images. We use
a background image for the menu background and a BurgerMenu custom a background image for the menu background and a BurgerMenu custom
component for the burger menu icon. component for the burger menu icon.
\image sidemenu-ui.png "SliderMenu component" \image sidemenu-ui.png "SliderMenu component"
We add states to the \e {SideMenu.qml} file in the \uicontrol {Form Editor}. We add states to the \e {SideMenu.qml} file in the \uicontrol States view.
When the application starts, the side menu is in the \e closed state, which When the application starts, the side menu is in the \e closed state, which
means that it is hidden. When users click the burger menu, the \c onClicked means that it is hidden. When users click the burger menu, the \c onClicked
signal handler triggers the transition to the \e opening state and runs an \l{glossary-signal}{signal handler} triggers the \l{glossary-transition}
animation. When the animation finishes, the side menu state changes to {transition} to the \e opening state and runs an animation. When the
\e open and the side menu is fully visible. animation finishes, the side menu state changes to \e open and the side
menu is fully visible.
When users click the burger menu again, the state changes to \e closing and When users click the burger menu again, the state changes to \e closing and
another animation is run that closes the side menu. When the animation another animation is run that closes the side menu. When the animation
@@ -165,7 +171,7 @@
(\uicontrol {Auto Key (K)}) button (or press \key k). (\uicontrol {Auto Key (K)}) button (or press \key k).
At frame 0, we set the X coordinate to -423 in \uicontrol Properties > At frame 0, we set the X coordinate to -423 in \uicontrol Properties >
\uicontrol Geometry > \uicontrol Position. We then move the playhead \uicontrol {Geometry - 2D} > \uicontrol Position. We then move the playhead
to frame 1000 and set the X coordinate to 0. to frame 1000 and set the X coordinate to 0.
When we deselect the record button to stop recording the timeline, the When we deselect the record button to stop recording the timeline, the
@@ -175,9 +181,11 @@
We then record the transition of the \e imageBackground image. At frame We then record the transition of the \e imageBackground image. At frame
0, we set the X coordinate to -424 again. We then move the playhead to 0, we set the X coordinate to -424 again. We then move the playhead to
frame 400 and select \uicontrol {Insert Keyframe} in the \uicontrol Settings frame 400 and select \uicontrol {Insert Keyframe} in the
menu of the X coordinate. We keep the value of the X coordinate -424. We \inlineimage icons/action-icon.png
then move the playhead to frame 1000 and set the X coordinate to 0. (\uicontrol Actions) menu of the X coordinate. We keep the value of the
X coordinate -424. We then move the playhead to frame 1000 and set the X
coordinate to 0.
We select \inlineimage animation.png "Timeline Settings button" We select \inlineimage animation.png "Timeline Settings button"
to open the \uicontrol {Timeline Settings} dialog. In the to open the \uicontrol {Timeline Settings} dialog. In the
@@ -219,20 +227,21 @@
We use property bindings to connect the controls in the slider menu to We use property bindings to connect the controls in the slider menu to
\l {2D Effects}{graphical effects}. To have access to the \l {2D Effects}{graphical effects}. To have access to the
properties from all the slider component instances, we export them as properties from all the slider component instances, we export them as
aliases in \e SliderMenu.ui.qml. We select \uicontrol {Export Property as Alias}
in \e SliderMenu.ui.qml. We select \uicontrol {Export Property as Alias}
in the \uicontrol Settings menu of the \uicontrol Value property in in the \uicontrol Settings menu of the \uicontrol Value property in
\uicontrol Properties > \uicontrol Slider. \uicontrol Properties > \uicontrol Slider.
We use the \uicontrol {Form Editor} to create the effect stack in the We open the \e {EffectStack.qml} file, and drag-and-drop components from
\e {EffectStack.qml} file: \uicontrol Library > \uicontrol Components >
\uicontrol {Qt Quick Studio Effects} to \uicontrol Navigator to create the
effect stack.
\image sidemenu-effects-stack.png "Effects stack in the Navigator" \image sidemenu-effects-stack.png "Effects stack in the Navigator"
We use the \l {Images}{Image} component as the last item in the stack to We use an instance of the \l {Images}{Image} component as the last item in
display images that we apply the effects to. We export the image source the stack to display images that we apply the effects to. We export the
property as an \l{Adding Property Aliases}{alias} to be able to switch image source property as an \l{Adding Property Aliases}{alias} to be able
the image inside the stack. to switch the image inside the stack.
For more information about the available graphical effects, see For more information about the available graphical effects, see
\l {2D Effects}. \l {2D Effects}.

View File

@@ -46,8 +46,8 @@
\endlist \endlist
Users select buttons to navigate between the screens. Users select buttons to navigate between the screens.
We use \l{Connecting Components to Signals}{connections} to determine which We use \l{glossary-connection}{connections} to determine which
screen to open when users select a particular button and \l{Adding States} screen to open when users select a particular button and \l{glossary-state}
{states} to show the screens. We use the \l{Creating Timeline Animations} {states} to show the screens. We use the \l{Creating Timeline Animations}
{timeline} to create progress indicators for buttons and the \e Running {timeline} to create progress indicators for buttons and the \e Running
screen. screen.
@@ -76,9 +76,9 @@
that we can use to configure and build our example application for running that we can use to configure and build our example application for running
it on MCUs. it on MCUs.
\note This example was developed using Qt for MCUs version 1.6. You \note This example has been tested to run using Qt for MCUs versions since
cannot run it on older versions, and we cannot make any promises about 1.6. You cannot run it on older versions. Also, at the time of writing,
newer versions. Qt for MCUs only supports Qt 5.
\section1 Creating Screens \section1 Creating Screens
@@ -142,10 +142,10 @@
First, we select the initial arc segment, \e arcSegment1, in First, we select the initial arc segment, \e arcSegment1, in
\l Navigator to display its properties in \uicontrol Properties. \l Navigator to display its properties in \uicontrol Properties.
In the \uicontrol Layout tab, \uicontrol Rotation field, we select In \uicontrol {Geometry - 2D} > \uicontrol Rotation, we select
\inlineimage icons/action-icon.png \inlineimage icons/action-icon.png
, and then select \uicontrol {Insert Keyframe} to insert a keyframe (\uicontrol Actions), and then select \uicontrol {Insert Keyframe} to
that we can animate in the \uicontrol Timeline view. insert a keyframe that we can animate in the \uicontrol Timeline view.
\image washingmachineui-insert-keyframe.png "Inserting keyframe for Rotation property" \image washingmachineui-insert-keyframe.png "Inserting keyframe for Rotation property"
@@ -154,8 +154,8 @@
(\uicontrol {Auto Key (K)}) button (or press \key k). (\uicontrol {Auto Key (K)}) button (or press \key k).
First, we set the rotation at frame 0 to -90 in \uicontrol Properties > First, we set the rotation at frame 0 to -90 in \uicontrol Properties >
\uicontrol Layout > \uicontrol Rotation. Next, we move the playhead to \uicontrol {Geometry - 2D} > \uicontrol Rotation. Next, we move the playhead
frame 250 and set the rotation to 0. to frame 250 and set the rotation to 0.
When we deselect the record button to stop recording the timeline, the When we deselect the record button to stop recording the timeline, the
new timeline appears in the view. new timeline appears in the view.

View File

@@ -50,15 +50,15 @@
We organize our design in Photoshop using artboards as instructed in We organize our design in Photoshop using artboards as instructed in
\l{Organizing Assets}. \l{Organizing Assets}.
\QB automatically proposes identifiers for all groups and layers. The ids \QB automatically proposes identifiers for all groups and layers. The IDs
will be used as filenames in \QDS. We want to change some of them in the will be used as filenames in \QDS. We want to change some of them in the
\uicontrol {QML ID} field, so that we can easily find them in \QDS. We \uicontrol ID field, so that we can easily find them in \QDS. We
must keep in mind that the ids must be unique, that they must begin with must keep in mind that the IDs must be unique, that they must begin with
a lower-case letter or an underscore character, and that only letters, a lower-case letter or an underscore character, and that only letters,
numbers, and underscore characters are allowed. numbers, and underscore characters are allowed.
Each artboard is exported automatically as a component. That is, a separate Each artboard is exported automatically as a component. That is, a separate
QML file that contains all the artwork on the artboard. We determine whether file that contains all the artwork on the artboard. We determine whether
each group or layer is exported as a component or a child item. Child items each group or layer is exported as a component or a child item. Child items
will be exported as PNG files, with references to them in the component file will be exported as PNG files, with references to them in the component file
that contains them. that contains them.
@@ -94,23 +94,27 @@
\image webinardemo-qb-stacklayout.png "Settings for exporting stackLayout artboard" \image webinardemo-qb-stacklayout.png "Settings for exporting stackLayout artboard"
For the stackLayoutFrame layer, we want to use a \l StackLayout component, For the \e stackLayoutFrame layer, we want to use a \l StackLayout component,
which provides a stack of items where only one item is visible at a time. which provides a stack of items where only one item is visible at a time.
In the \uicontrol {QML Type} field, we enter \e StackLayout. In the \uicontrol Component field, we enter \e StackLayout.
To be able to use the component, we enter the statement that imports the To be able to use the component, we enter the statement that imports the
Qt Quick Layouts module, which contains the component, in the Qt Quick Layouts module, which contains the component, in the
\uicontrol {Add Imports} field: \c {QtQuick.Layouts 1.3}. \uicontrol Imports field: \c {QtQuick.Layouts 1.3}.
We will add content to the stack layout in \QDS. We will add content to the stack layout in \QDS.
\section2 Using Qt Studio Effects \section2 Using Qt Studio Effects
\note The availability of effects depends on whether you select
\uicontrol {Qt 5} or \uicontrol {Qt 6} when creating your project
in \QDS.
\image webinardemo-qb-fastblur.png "Settings for exporting blurEffect layer" \image webinardemo-qb-fastblur.png "Settings for exporting blurEffect layer"
We want to apply the \l {FastBlur} effect to the smallPopup UI control. We want to apply the \l {FastBlur} effect to the \e smallPopup UI control.
In the artboard, we have a blurEffect layer that we want to export as a In the artboard, we have a \e blurEffect layer that we want to export as a
FastBlurItem component. In the \uicontrol {QML Type} field, we enter \e FastBlurItem component. In the \uicontrol Component field, we enter
\e FastBlurItem. \e FastBlurItem.
To be able to use the component, we added the statement that imports the To be able to use the component, we added the statement that imports the
@@ -118,8 +122,11 @@
We specify that the component to which we want to apply the effect is a We specify that the component to which we want to apply the effect is a
child of the effect. We then specify the radius property for the effect, child of the effect. We then specify the radius property for the effect,
in the \uicontrol {QML Properties} field. We can modify the property in in the \uicontrol Properties field. We can modify the property in \QDS by
the \uicontrol Radius field in the \uicontrol Properties view in \QDS. opening the \e {SmallPopup.ui.qml} file and selecting the instance of the
\uicontrol {Fast Blur Item} component in \uicontrol Navigator. We can find
the property in \l Properties > \uicontrol {Geometry- 2D} >
\uicontrol Radius.
\image webinardemo-blureffect.png "FastBlurItem component in Design mode" \image webinardemo-blureffect.png "FastBlurItem component in Design mode"
@@ -162,8 +169,8 @@
The \e {LayoutReference.ui.qml} file contains a reference image of The \e {LayoutReference.ui.qml} file contains a reference image of
the UI we will create. We use the imported components to create the the UI we will create. We use the imported components to create the
UI in the \e {MainApp.ui.qml} file. The imported components are UI in the \e {MainApp.ui.qml} file. The imported components are
listed in \uicontrol Library > \uicontrol Components > listed in \l Library > \uicontrol Components > \uicontrol {My Components},
\uicontrol {My Components}, and we can drag-and-drop them to \l {Form Editor}. and we can drag-and-drop them to \l {Form Editor}.
\image webinardemo-mainappui.png "Main app UI in Design mode" \image webinardemo-mainappui.png "Main app UI in Design mode"
@@ -172,21 +179,21 @@
context menu. Any changes we make to a component are immediately visible in context menu. Any changes we make to a component are immediately visible in
all the other components where it appears. all the other components where it appears.
We can view the QML code for each component in \l{Text Editor}. We can view the code for each component in \l{Text Editor}.
We can now use states and the timeline to animate the components in the UI. We can now use states and the timeline to animate the components in the UI.
\section2 Animating Components \section2 Animating Components
We open the \e {Largepopup.ui.qml} file in the Design mode to add animation We open the \e {Largepopup.ui.qml} file in the \uicontrol Design mode to add
to it. In the \uicontrol States view, we add the \e opening, \e open, animation to it. In the \l States view, we add the \e opening, \e open,
\e closing, and \e closed states for the popup. \e closing, and \e closed states for the popup.
\image webinardemo-states.png "Popup states in the States view" \image webinardemo-states.png "Popup states in the States view"
For more information about using states, see \l {Creating States}. For more information about using states, see \l {Creating States}.
We then use the \uicontrol Timeline view to add animations that are run We then use the \l Timeline view to add animations that are run
when moving from one state to another. when moving from one state to another.
\image webinardemo-timeline.png "Popup animations in the Timeline view" \image webinardemo-timeline.png "Popup animations in the Timeline view"

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -44,9 +44,9 @@
\endlist \endlist
Setting up a new project in \QDS is aided by a wizard that guides you Setting up a new project in \QDS is aided by a wizard that guides you
step-by-step through the project creation process. The wizards prompt you step-by-step through the project creation process. The wizard templates
to enter the settings needed for that particular type of project and create prompt you to enter the settings needed for a particular type of project
the necessary files for you. and create the necessary files for you.
\QDS projects are useful for creating UIs. You cannot use them for \QDS projects are useful for creating UIs. You cannot use them for
application development, because they do not contain: application development, because they do not contain:
@@ -65,25 +65,43 @@
\image studio-project-wizards.png "A list of project wizards" \image studio-project-wizards.png "A list of project wizards"
You can export designs from other design tools and import them to projects You can export designs from other design tools and import them to projects
or create them from scratch using the following wizards: or create them from scratch using the following wizard templates:
\list \table
\li \uicontrol {Qt for MCUs Application} creates an application that \header
uses a subset of preset components (as supported by Qt for MCUs) \li Category
that you can deploy, run, and debug on MCU boards. \li Wizard Template
\li \uicontrol {Qt Quick Application - Empty} creates a project that \li Purpose
uses default components and preset UI controls and can be run on \row
all target platforms. \li {1,2} General
\li \uicontrol {Qt Quick 3D Application} creates a project that uses \li Qt Quick Application - Empty
default components, UI controls, and 3D components. \li Creates a project that uses default components and preset UI
\li \uicontrol {Qt Quick Application - Scroll} and controls and can be run on all target platforms.
\uicontrol {Qt Quick Application - Stack} create an application \row
that uses UI controls to implement a scrollable list or a set of \li Qt Quick 3D Application
pages with a stack-based navigation model. \li Creates a project that uses default components, UI controls, and
\li \uicontrol {Qt Quick Application - Launcher} creates a 3D components.
project that uses default components and UI controls and \row
\li Qt for MCUs
\li Qt for MCUs Application
\li Creates an application that uses a subset of preset components
(as supported by Qt for MCUs) that you can deploy, run, and debug
on MCU boards.
\row
\li {1,2} Mobile
\li Qt Quick Application - Scroll
\li Creates an application that uses UI controls to implement a
scrollable list.
\row
\li Qt Quick Application - Stack
\li Creates an application that uses UI controls to implement a
set of pages with a stack-based navigation model.
\row
\li Desktop
\li Qt Quick Application - Launcher
\li Creates a project that uses default components and UI controls and
defines a launcher application. defines a launcher application.
\endlist \endtable
For an example of creating a \uicontrol {Qt Quick 3D Application} project, For an example of creating a \uicontrol {Qt Quick 3D Application} project,
watch the following video: watch the following video:
@@ -94,19 +112,31 @@
\list 1 \list 1
\li Select \uicontrol File > \uicontrol {New File or Project}. \li Select \uicontrol File > \uicontrol {New File or Project}.
\li Select the type of your project, and then select \uicontrol Choose. \li Select a wizard template, and then select \uicontrol Choose.
\li In the \uicontrol Name field, enter a name for the project. \li In the \uicontrol Name field, enter a name for the project.
When naming your own projects, keep in mind that they cannot be Keep in mind that projects cannot be easily renamed later.
easily renamed later. \image studio-project-location.png "Project Location dialog"
\li In the \uicontrol {Create in} field, enter the path for the project \li In the \uicontrol {Create in} field, enter the path for the project
files, and then select \uicontrol Next (or \uicontrol Continue on files. You can move project folders later without problems.
\macos). You can move project folders later without problems. \li Select \uicontrol Next (or \uicontrol Continue on \macos).
\li In the \uicontrol {Screen resolution} field, select the screen \li In the \uicontrol {Screen resolution} field, select the screen
resolution for previewing the UI on the desktop or on a device. resolution for previewing the UI on the desktop or on a device.
This determines the screen size.
\image studio-project-custom-screen-size.png "Define Project Details dialog"
\li To use a custom screen size, specify the width and height of the
screen in the \uicontrol {Custom screen width} and
\uicontrol {Custom screen height} fields.
You can easily change the screen size later in \l Properties. You can easily change the screen size later in \l Properties.
\li In the \uicontrol {Qt Quick Controls Style} field, select one of \li In the \uicontrol {Qt Quick Controls Style} field, select one of
the predefined \l{Styling Qt Quick Controls}{UI styles} to use, the predefined \l{Styling Qt Quick Controls}{UI styles} to use.
and then select \uicontrol Finish (or \uicontrol Done on \macos). \li Select the \uicontrol {Use Qt Virtual Keyboard} check box to enable
users to enter text using a virtual keyboard.
\li In the \uicontrol {Target Qt Version} field, select the Qt version
to use for developing the application. While you can change the
Qt version later in the \uicontrol {Run Settings} of the project,
keep in mind that the two versions are not fully compatible.
\li Select \uicontrol Finish (or \uicontrol Done on \macos) to create
the project.
\endlist \endlist
\QDS creates the following files and folders: \QDS creates the following files and folders:
@@ -144,51 +174,77 @@
\section1 Adding Files to Projects \section1 Adding Files to Projects
You can use wizards also to add individual files to your projects. You can use wizard templates also to add individual files to projects.
The wizard templates in the \uicontrol {Qt Quick Controls} category create
stylable versions of the components in the \uicontrol {Qt Quick Controls}
module. For more information, see \l{Creating Custom Controls}.
You can create the following types of files: You can create the following types of files:
\list \table
\li \uicontrol {Qt Quick Files} \header
\list \li Category
\li \uicontrol {Flow Item} and \uicontrol {Flow View} \li Wizard Template
generate components that you can use to design the \li Purpose
\row
\li {1,4} Qt Quick Files
\li Flow Item and Flow View
\li Generate components that you can use to design the
\l{Designing Application Flows}{application flow}. \l{Designing Application Flows}{application flow}.
\li \uicontrol {Qt Quick File} generates a component with one \row
of the following default components or \l{Using Positioners} \li Qt Quick File
{positioners} as the root component: \l {basic-item}{Item}, \li Generates a component with one of the following default components
\l {basic-rectangle}{Rectangle}, \l {Images}{Image}, or \l{Using Positioners}{positioners} as the root component:
\l {Border Image}, \l Flickable, Row, Column, Flow, or Grid. \l {basic-item}{Item}, \l {basic-rectangle}{Rectangle}, \l {Images}
\li \uicontrol {Qt Quick UI File} generates a component file {Image}, \l {Border Image}, \l Flickable, Row, Column, Flow, or
with one of the above components as the root component. Grid.
\li \uicontrol {Qt Quick Views} generates a Grid View or a \row
List View. For more information, see \l{List and Grid Views}. \li Qt Quick UI File
\li Generates a UI file with one of the above components as the root
\endlist component.
\li \uicontrol {Qt Quick Controls} create stylable versions of the \row
components in the Qt Quick Controls module: \li Qt Quick Views
\list \li Generates a Grid View or a List View. For more information, see
\li \l {Button}{Custom Button} creates a push button with a text \l{List and Grid Views}.
label. \row
\li \l {Check Box}{Custom CheckBox} creates a check box. \li {1,9} Qt Quick Controls
\li \l {Slider and Dial}{Custom Dial} creates a dial. \li Custom Button
\li \l {Slider and Dial}{Custom Slider} creates a slider. \li Creates a \l {Button}{push button} with a text label.
\li \l {Spin Box}{Custom SpinBox} creates a spin box. \row
\li \l {Switch}{Custom Switch} creates a switch with on and off \li Custom \CheckBox
states. \li Creates a \l {Check Box}{check box}.
\li \l [Qt Quick Controls 2] {Pane} provides a background that \row
matches the UI style and theme. \li Custom Dial
\li \l [Qt Quick Controls 2] {StackView} provides a stack-based \li Creates a \l {Slider and Dial}{dial}.
navigation model. \row
\li \l [Qt Quick Controls 2] {SwipeView} enables users to \li Custom Slider
navigate pages by swiping sideways. \li Creates a \l {Slider and Dial}{slider}.
\endlist \row
For more information, see \l{Creating Custom Controls}. \li Custom \SpinBox
\li \uicontrol ListModel adds a \l{Editing List Models}{list model} to \li Creates a \l {Spin Box}{spin box}.
the project. \row
\li \uicontrol {JavaScript File} generates files that you can use to \li Custom Switch
write the application logic. This is useful for testing the \li Creates a \l {Switch}{switch} with on and off states.
application before the developers implement the application logic \row
in C++, for example. For more information, see \li \l Pane
\l {Simulating Application Logic}. \li Provides a background that matches the UI style and theme.
\endlist \row
\li StackView
\li Provides a stack-based navigation model.
\row
\li SwipeView
\li Enables users to navigate pages by swiping sideways.
\row
\li QML Files
\li ListModel
\li Adds a \l{Editing List Models}{list model} to the project.
\row
\li JavaScript
\li JavaScript File
\li Generates files that you can use to write the application logic.
This is useful for testing the application before the developers
implement the application logic in C++, for example. For more
information, see \l {Simulating Application Logic}.
\endtable
*/ */

View File

@@ -89,6 +89,7 @@
\li \l Animations \li \l Animations
\li \l{3D Views} \li \l{3D Views}
\li \l{Group} \li \l{Group}
\li \l{Instanced Rendering}
\li \l{Skeletal Animation} \li \l{Skeletal Animation}
\li \l{3D Models} \li \l{3D Models}
\li \l{Materials and Shaders} \li \l{Materials and Shaders}

View File

@@ -0,0 +1,153 @@
/****************************************************************************
**
** Copyright (C) 2021 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 studio-3d-instancing.html
\previouspage studio-3d-node.html
\nextpage studio-skeletal-components.html
\title Instanced Rendering
Instancing allows duplicating a model with variations. In contrast to using
the \uicontrol Repeater3D component, the model and its graphics resources are
only allocated once. The rendering of the duplicated instances is done at a
low level by the GPU. Depending on the complexity of the model, this can
give a performance improvement of several orders of magnitude.
In practice, instancing is done by defining a table that specifies how each
instance is modified relative to the base model.
You can add instancing to your scenes by using the instancing components
available in \uicontrol Library > \uicontrol Components >
\uicontrol {Qt Quick 3D} > \uicontrol {Qt Quick 3D}:
\list
\li \uicontrol {Instancing}
\li \uicontrol {Instance List}
\li \uicontrol {Instance List Entry}.
\endlist
\section1 Reading Instance Tables from Files
The \uicontrol Instancing component makes it possible to read instance tables
from files in XML or binary format. The binary file format uses the same
layout as the table that is uploaded to the GPU, so it can be directly mapped
to memory.
In order to be valid, the XML file must have a top-level instance table
element. Each instance is represented by an Instance element inside the
InstanceTable. Unknown elements are silently ignored.
An Instance element can have a number of attributes. Color attributes are
specified by using SVG color names, such as "red", "green", or
"lightsteelblue", or by using a hexadecimal notation. \c Vector3d and
\c vector4d attributes are specified by a string of space-separated numbers,
where missing trailing numbers indicate zeroes. The following attributes are
supported: position, scale, eulerRotation, quaternion, custom, and color.
For more information about instance tables, see the documentation for the
\l[Instancing]{FileInstancing} QML type.
To use the \uicontrol Instancing component, drag-and-drop it from
\uicontrol Library to \uicontrol Scene in \uicontrol Navigator.
\section2 Instancing Properties
Define the location of an XML or a binary file containing the instance data
in \uicontrol Properties > \uicontrol {File Instancing} > \uicontrol Source.
\image studio-3d-instancing-properties.png "File Instancing in the Properties View"
If the file name has a \c .bin extension, it is assumed to refer to a binary
file. Otherwise it is assumed to refer to an XML file. If an XML file
\c foo.xml is specified, and the file \c foo.xml.bin exists, the binary file
\c foo.xml.bin will be loaded instead.
After defining the \uicontrol Source property for the \uicontrol Instancing
component, select a model in \uicontrol Navigator, and in
\uicontrol Properties > \uicontrol Model > \uicontrol Instancing, select the
name of the \uicontrol Instancing component.
\image studio-3d-instancing-model.png "The Instancing property"
\section1 Using Instance Lists to Build Instance Tables
Use the \uicontrol {Instance List} component to define an instance table in
\QDS. An instance table consists of instances defined as
\uicontrol {Instance List Entry} components, which can have property bindings
and animation. This gives great flexibility but also causes memory overhead.
Therefore, it is not recommended to use \uicontrol {Instance List}
for procedurally generated tables containing a large number of instances.
Also, any property change to an entry will cause the entire instance table
to be recalculated and uploaded to the GPU.
\image studio-3d-instancing-instance-list.png "Instance List and Instance Entries in Navigator"
To build an instance table:
\list 1
\li Drag-and-drop an \uicontrol {Instance List} component from
\uicontrol Library > \uicontrol Components > \uicontrol {Qt Quick 3D}
> \uicontrol {Qt Quick 3D} to \uicontrol Scene in
\uicontrol Navigator.
\li Drag-and-drop \uicontrol {Instance List Entry} components to the
\uicontrol {Instance List} component to create list items.
\image studio-3d-instancing-instance-list.png "Instance List and Instance Entries in Navigator"
\li Select the \uicontrol {Instance List} in \uicontrol Navigator, and in
\uicontrol Properties > \uicontrol {Instance List} >
\uicontrol Instances, select each \uicontrol {Instance List Entry}
you wish to include in the \uicontrol {Instance List} by using
the dropdown menu. You can add more fields for the property by
clicking the \inlineimage plus.png
icon.
\li To define an \uicontrol {Instance List Entry}, select it in
\uicontrol Navigator, and specify its properties in
\uicontrol Properties > \uicontrol {Instance List Entry}.
\li Select a model component in \uicontrol Navigator, and in
\uicontrol Properties > \uicontrol Instancing, select the name
of the \uicontrol {Instance List} component.
\endlist
\section2 Defining Instance List Entries
Use the \uicontrol {Instance List Entry} component to specify each instance
in an \uicontrol {Instance List}.
Each of the \uicontrol {Instance List Entry} properties can have
\l {Adding Bindings Between Properties}{bindings} and animation. Select an
\uicontrol {Instance List Entry} in \uicontrol Navigator to specify the
properties in \uicontrol Properties > \uicontrol {Instance List Entry}.
\image studio-3d-instancing-instance-list-entry-properties.png "Instance List Entry Properties"
Use the \uicontrol Color property to \l{Picking Colors}{specify the color}
for the instance.
Specify the position for the instance using the \uicontrol Position property,
and the scale by defining the scale factors of the \uicontrol Scale property
along the x, y, and z axes.
Set the rotation for the instance using the \uicontrol Rotation
property, which specifies the rotation for the instance as an Euler vector
containing the rotation in degrees around the x, y, and z axes.
*/

View File

@@ -77,7 +77,10 @@
The \uicontrol Source field must be empty when custom geometry is used. The \uicontrol Source field must be empty when custom geometry is used.
Set the \uicontrol Instancing property to render a number of instances of Set the \uicontrol Instancing property to render a number of instances of
the model as defined by the instance table. the model as defined by an instancing table. The instancing tables can be
defined by using one of the \l{Instanced Rendering}{instancing components}
available in \uicontrol Library > \uicontrol Components >
\uicontrol {Qt Quick 3D} > {Qt Quick 3D}.
Set the \uicontrol {Instance root} property to define the origin of the Set the \uicontrol {Instance root} property to define the origin of the
instance's coordinate system. instance's coordinate system.

View File

@@ -26,7 +26,7 @@
/*! /*!
\page studio-3d-node.html \page studio-3d-node.html
\previouspage quick-animations.html \previouspage quick-animations.html
\nextpage studio-skeletal-components.html \nextpage studio-3d-instancing.html
\title Group \title Group

View File

@@ -25,7 +25,7 @@
/*! /*!
\page studio-skeletal-components.html \page studio-skeletal-components.html
\previouspage studio-3d-node.html \previouspage studio-3d-instancing.html
\nextpage studio-3d-model.html \nextpage studio-3d-model.html
\title Skeletal Animation \title Skeletal Animation

View File

@@ -36,6 +36,10 @@
\image studio-2d-effects.png "Effects tab in Library" \image studio-2d-effects.png "Effects tab in Library"
\note The availability of effects depends on whether you selected
\uicontrol {Qt 5} or \uicontrol {Qt 6} when \l{Creating Projects}
{creating your project}.
Effects have one or more source properties for specifying the visual input Effects have one or more source properties for specifying the visual input
for which the effect is applied to a component. The altered visual output is for which the effect is applied to a component. The altered visual output is
then presented in the effect component itself. The source can be another, then presented in the effect component itself. The source can be another,
@@ -55,6 +59,11 @@
\section1 Caching and Borders \section1 Caching and Borders
Specify common properties for 2D effects in the \uicontrol Caching or
\uicontrol {Caching and Border} section.
\image studio-2d-effects-caching-and-border.png "Studio Effects Caching and Border properties"
The \uicontrol Cached property allows the effect output pixels to be cached The \uicontrol Cached property allows the effect output pixels to be cached
in order to improve the rendering performance. Every time the source or in order to improve the rendering performance. Every time the source or
effect properties are changed, the pixels in the cache must be updated. effect properties are changed, the pixels in the cache must be updated.
@@ -78,7 +87,8 @@
\section1 Summary of 2D Effects \section1 Summary of 2D Effects
The following table summarizes the available effects and contains links to The following table summarizes the available effects and contains links to
the developer documentation of the inherited component. the developer documentation of the inherited component. The Qt 6 column
indicates which effects are available for Qt 6 projects.
\note The effects are available when running with OpenGL. \note The effects are available when running with OpenGL.
@@ -86,10 +96,12 @@
\header \header
\li Icon \li Icon
\li Effect \li Effect
\li Qt 6
\li Description \li Description
\row \row
\li \inlineimage icons/blend-mode-16px.png \li \inlineimage icons/blend-mode-16px.png
\li \l [QML] {Blend} \li \l [QML] {Blend}
\li
\li Merges two source components by using a blend mode. \li Merges two source components by using a blend mode.
The default \uicontrol Mode is \c subtract, where the pixel value The default \uicontrol Mode is \c subtract, where the pixel value
@@ -102,21 +114,25 @@
\row \row
\li \inlineimage icons/brightness-contrast-16px.png \li \inlineimage icons/brightness-contrast-16px.png
\li \l {BrightnessContrast}{Brightness Contrast} \li \l {BrightnessContrast}{Brightness Contrast}
\li \inlineimage ok.png
\li Adjusts \uicontrol Brightness and \uicontrol Contrast. \li Adjusts \uicontrol Brightness and \uicontrol Contrast.
\row \row
\li \inlineimage icons/colourize-16px.png \li \inlineimage icons/colourize-16px.png
\li \l {ColorOverlay}{Color Overlay} \li \l {ColorOverlay}{Color Overlay}
\li \inlineimage ok.png
\li Alters the colors of the source component by applying an \li Alters the colors of the source component by applying an
\uicontrol {Overlay Color}. You can use the color picker \uicontrol {Overlay color}. You can use the color picker
to \l{Picking Colors}{select the color}. to \l{Picking Colors}{select the color}.
\row \row
\li \inlineimage icons/colourize-16px.png \li \inlineimage icons/colourize-16px.png
\li \l Colorize \li \l Colorize
\li \inlineimage ok.png
\li Sets the color in the HSL color space by specifying \uicontrol Hue, \li Sets the color in the HSL color space by specifying \uicontrol Hue,
\uicontrol Lightness, and \uicontrol Saturation values. \uicontrol Lightness, and \uicontrol Saturation values.
\row \row
\li \inlineimage icons/desaturation-16px.png \li \inlineimage icons/desaturation-16px.png
\li \l {Desaturate}{Desaturation} \li \l {Desaturate}{Desaturation}
\li \inlineimage ok.png
\li Reduces the saturation of the colors by the value set in the \li Reduces the saturation of the colors by the value set in the
\uicontrol Desaturation field. The value ranges from \c 0.0 \uicontrol Desaturation field. The value ranges from \c 0.0
(no change) to \c 1.0 (desaturated). Desaturated pixel values are (no change) to \c 1.0 (desaturated). Desaturated pixel values are
@@ -125,8 +141,9 @@
\row \row
\li \inlineimage icons/directional-blur-16px.png \li \inlineimage icons/directional-blur-16px.png
\li \l {DirectionalBlur}{Directional Blur} \li \l {DirectionalBlur}{Directional Blur}
\li \inlineimage ok.png
\li Applies a blur effect to the specified direction. The value of the \li Applies a blur effect to the specified direction. The value of the
\uicontrol Angle field, defines the direction of the blur. This \uicontrol Angle field defines the direction of the blur. This
effect makes the source component appear to be moving in the direction of effect makes the source component appear to be moving in the direction of
the blur. Blur is applied to both sides of each pixel, and therefore the blur. Blur is applied to both sides of each pixel, and therefore
setting the direction to \c 0 and \c 180 provides the same result. setting the direction to \c 0 and \c 180 provides the same result.
@@ -141,6 +158,7 @@
\row \row
\li \inlineimage icons/displace-16px.png \li \inlineimage icons/displace-16px.png
\li \l Displace \li \l Displace
\li \inlineimage ok.png
\li Moves the pixels of the source component according to the displacement \li Moves the pixels of the source component according to the displacement
map specified in the \uicontrol {Displacement source} field. map specified in the \uicontrol {Displacement source} field.
@@ -153,13 +171,14 @@
\row \row
\li \inlineimage icons/drop-shadow-16px.png \li \inlineimage icons/drop-shadow-16px.png
\li \l {DropShadow}{Drop Shadow} \li \l {DropShadow}{Drop Shadow}
\li \inlineimage ok.png
\li Generates a soft shadow behind the source component using a \li Generates a soft shadow behind the source component using a
gaussian blur. This effect blurs the alpha channel of the input and gaussian blur. This effect blurs the alpha channel of the input and
colorizes the result, which it then places behind the source component colorizes the result, which it then places behind the source component
to create a soft shadow. You can set the shadow's color in the to create a soft shadow. You can set the shadow's color in the
\uicontrol {Drop Shadow Color} field and change its location in the \uicontrol {Drop shadow color} field and change its location in the
\uicontrol {Horizontal offset} and \uicontrol {Vertical offset} horizontal (\uicontrol H) and vertical (\uicontrol V)
fields. \uicontrol Offset fields.
The value of the \uicontrol Radius field specifies the softness of The value of the \uicontrol Radius field specifies the softness of
the shadow. A larger radius causes the edges of the shadow to appear the shadow. A larger radius causes the edges of the shadow to appear
@@ -174,6 +193,7 @@
\row \row
\li \inlineimage icons/fast-blur-16px.png \li \inlineimage icons/fast-blur-16px.png
\li \l {FastBlur}{Fast Blur} \li \l {FastBlur}{Fast Blur}
\li \inlineimage ok.png
\li Applies a fast blur effect to one or more source components. \li Applies a fast blur effect to one or more source components.
\uicontrol {Fast Blur} offers lower blur quality than \uicontrol {Fast Blur} offers lower blur quality than
\uicontrol {Gaussian Blur}, but it is faster to render. \uicontrol {Gaussian Blur}, but it is faster to render.
@@ -191,6 +211,7 @@
\row \row
\li \inlineimage icons/gamma-adjust-16px.png \li \inlineimage icons/gamma-adjust-16px.png
\li \l [QML] {GammaAdjust}{Gamma Adjust} \li \l [QML] {GammaAdjust}{Gamma Adjust}
\li \inlineimage ok.png
\li Alters the luminance of the source component. This effect is applied \li Alters the luminance of the source component. This effect is applied
to each pixel according to the curve that is pre-defined as a to each pixel according to the curve that is pre-defined as a
power-law expression, where the value of the \uicontrol Gamma power-law expression, where the value of the \uicontrol Gamma
@@ -198,6 +219,7 @@
\row \row
\li \inlineimage icons/gaussian-blur-16px.png \li \inlineimage icons/gaussian-blur-16px.png
\li \l [QML] {GaussianBlur}{Gaussian Blur} \li \l [QML] {GaussianBlur}{Gaussian Blur}
\li
\li Applies a gaussian blur effect to one or more source components. \li Applies a gaussian blur effect to one or more source components.
The effect softens the image by blurring it with an algorithm that The effect softens the image by blurring it with an algorithm that
uses the gaussian function to calculate the effect. The effect uses the gaussian function to calculate the effect. The effect
@@ -219,6 +241,7 @@
\row \row
\li \inlineimage icons/glow-16px.png \li \inlineimage icons/glow-16px.png
\li \l [QML] {Glow} \li \l [QML] {Glow}
\li \inlineimage ok.png
\li Generates a halo-like glow around the source component. This effect \li Generates a halo-like glow around the source component. This effect
blurs the alpha channel of the source and colorizes it with blurs the alpha channel of the source and colorizes it with
\uicontrol {Glow color}. It then places the alpha channel behind the \uicontrol {Glow color}. It then places the alpha channel behind the
@@ -229,6 +252,7 @@
\row \row
\li \inlineimage icons/hue-saturation-16px.png \li \inlineimage icons/hue-saturation-16px.png
\li \l {HueSaturation}{Hue Saturation} \li \l {HueSaturation}{Hue Saturation}
\li \inlineimage ok.png
\li Alters the source component colors in the HSL color space. \li Alters the source component colors in the HSL color space.
This effect is similar to the \uicontrol Colorize effect, but This effect is similar to the \uicontrol Colorize effect, but
the \uicontrol Hue and \uicontrol Saturation values are handled the \uicontrol Hue and \uicontrol Saturation values are handled
@@ -238,8 +262,9 @@
\row \row
\li \inlineimage icons/inner-shadow-16px.png \li \inlineimage icons/inner-shadow-16px.png
\li \l {InnerShadow}{Inner Shadow} \li \l {InnerShadow}{Inner Shadow}
\li
\li Generates a colorized and blurred shadow inside the source using \li Generates a colorized and blurred shadow inside the source using
the color that you specify in the \uicontrol {Inner Shadow Color} the color that you specify in the \uicontrol {Inner shadow color}
field. field.
The quality of the shadow can be controlled by the values of the The quality of the shadow can be controlled by the values of the
@@ -259,6 +284,7 @@
\row \row
\li \inlineimage icons/levels-16px.png \li \inlineimage icons/levels-16px.png
\li \l {LevelAdjust}{Level Adjust} \li \l {LevelAdjust}{Level Adjust}
\li \inlineimage ok.png
\li Adjusts color levels in the RGBA color space. This effect adjusts \li Adjusts color levels in the RGBA color space. This effect adjusts
the source component colors separately for each color channel. Source the source component colors separately for each color channel. Source
component contrast can be adjusted and color balance altered. component contrast can be adjusted and color balance altered.
@@ -271,22 +297,24 @@
ranges from \c QtVector3d(0.0, 0.0, 0.0) (darkest) to \c inf ranges from \c QtVector3d(0.0, 0.0, 0.0) (darkest) to \c inf
(lightest). (lightest).
You can specify the maximum and minimum input and output levels for You can specify the maximum and minimum \uicontrol Input and
each color channel. \uicontrol {Maximum input} sets the white-point, \uicontrol Output levels for each color channel. \uicontrol Maximum
which means that all pixels with a higher value are rendered as input sets the white-point, which means that all pixels with a
white (per color channel). Decreasing this value lightens the light higher value are rendered as white (per color channel). Decreasing
areas. To darken the light areas and to increase the contrast, this value lightens the light areas. To darken the light areas and
decrease the value of the \uicontrol {Maximum output} field. to increase the contrast, decrease the value of the
\uicontrol Maximum output field.
The value of the \uicontrol {Minimum input} field sets the minimum The value of the \uicontrol Minimum input field sets the minimum
input level for each color channel. It sets the black-point, which input level for each color channel. It sets the black-point, which
means that all pixels with a lower value are rendered as black means that all pixels with a lower value are rendered as black
(per color channel). Increasing this value darkens the dark areas. (per color channel). Increasing this value darkens the dark areas.
To lighten the dark areas and to reduce the contrast, increase the To lighten the dark areas and to reduce the contrast, increase the
value of the \uicontrol {Minimum output} field. value of the \uicontrol Minimum output field.
\row \row
\li \inlineimage icons/mask-blur-16px.png \li \inlineimage icons/mask-blur-16px.png
\li \l {MaskedBlur}{Masked Blur} \li \l {MaskedBlur}{Masked Blur}
\li
\li Softens the image by blurring it. The intensity of the blur can be \li Softens the image by blurring it. The intensity of the blur can be
controlled for each pixel by specifying a \uicontrol {Mask source}, controlled for each pixel by specifying a \uicontrol {Mask source},
so that some parts of the source are blurred more than others. so that some parts of the source are blurred more than others.
@@ -301,6 +329,7 @@
\row \row
\li \inlineimage icons/opacity-mask-16px.png \li \inlineimage icons/opacity-mask-16px.png
\li \l {OpacityMask}{Opacity Mask} \li \l {OpacityMask}{Opacity Mask}
\li \inlineimage ok.png
\li Masks the source component with another component specified in the \li Masks the source component with another component specified in the
\uicontrol {Mask source} field. The mask component gets rendered into an \uicontrol {Mask source} field. The mask component gets rendered into an
intermediate pixel buffer and the alpha values from the result are intermediate pixel buffer and the alpha values from the result are
@@ -315,6 +344,7 @@
\row \row
\li \inlineimage icons/radial-blur-16px.png \li \inlineimage icons/radial-blur-16px.png
\li \l {RadialBlur}{Radial Blur} \li \l {RadialBlur}{Radial Blur}
\li
\li Applies a directional blur effect in a circular direction around the \li Applies a directional blur effect in a circular direction around the
component's center point. This effect makes the source component appear component's center point. This effect makes the source component appear
to be rotating into the direction of the blur. Other available to be rotating into the direction of the blur. Other available
@@ -329,6 +359,7 @@
\row \row
\li \inlineimage icons/recursive-blur-16px.png \li \inlineimage icons/recursive-blur-16px.png
\li \l {RecursiveBlur}{Recursive Blur} \li \l {RecursiveBlur}{Recursive Blur}
\li
\li Blurs repeatedly, providing a strong blur effect. This effect \li Blurs repeatedly, providing a strong blur effect. This effect
softens the image by blurring it with an algorithm that uses a softens the image by blurring it with an algorithm that uses a
recursive feedback loop to blur the source as many times as recursive feedback loop to blur the source as many times as
@@ -344,6 +375,7 @@
\row \row
\li \inlineimage icons/threshold-16px.png \li \inlineimage icons/threshold-16px.png
\li \l {ThresholdMask}{Threshold Mask} \li \l {ThresholdMask}{Threshold Mask}
\li \inlineimage ok.png
\li Masks the source component with another component specified by \li Masks the source component with another component specified by
\uicontrol {Mask source}. The value of the \uicontrol Spread \uicontrol {Mask source}. The value of the \uicontrol Spread
field determines the smoothness of the mask edges near the field determines the smoothness of the mask edges near the
@@ -354,6 +386,7 @@
\row \row
\li \inlineimage icons/zoom-blur-16px.png \li \inlineimage icons/zoom-blur-16px.png
\li \l {ZoomBlur}{Zoom Blur} \li \l {ZoomBlur}{Zoom Blur}
\li
\li Applies a directional blur effect towards source component's \li Applies a directional blur effect towards source component's
center point. This effect makes the source component appear to be center point. This effect makes the source component appear to be
moving towards the center point in Z-direction or the camera moving towards the center point in Z-direction or the camera
@@ -361,9 +394,9 @@
The value of the \uicontrol Length field specifies the maximum The value of the \uicontrol Length field specifies the maximum
perceived amount of movement for each pixel. The amount is smaller perceived amount of movement for each pixel. The amount is smaller
near the center specified by the \uicontrol {Horizontal offset} and near the center specified by the horizontal (\uicontrol H) and
\uicontrol {Vertical offset} fields and reaches the specified value vertical (\uicontrol V) \uicontrol Offset fields and reaches the
at the edges. specified value at the edges.
The quality of the blur depends on the value of the The quality of the blur depends on the value of the
\uicontrol Samples field. If the length value is large, \uicontrol Samples field. If the length value is large,

View File

@@ -187,7 +187,6 @@ if [ ! -d "$app_path/Contents/Frameworks/QtCore.framework" ]; then
qbsArguments=("-executable=$qbsapp" \ qbsArguments=("-executable=$qbsapp" \
"-executable=$qbsapp-config" \ "-executable=$qbsapp-config" \
"-executable=$qbsapp-config-ui" \ "-executable=$qbsapp-config-ui" \
"-executable=$qbsapp-qmltypes" \
"-executable=$qbsapp-setup-android" \ "-executable=$qbsapp-setup-android" \
"-executable=$qbsapp-setup-qt" \ "-executable=$qbsapp-setup-qt" \
"-executable=$qbsapp-setup-toolchains" \ "-executable=$qbsapp-setup-toolchains" \

View File

@@ -54,7 +54,7 @@ def main():
os.symlink('/Applications', os.path.join(tempdir, 'Applications')) os.symlink('/Applications', os.path.join(tempdir, 'Applications'))
shutil.copy(os.path.join(arguments.source_directory, 'LICENSE.GPL3-EXCEPT'), tempdir) shutil.copy(os.path.join(arguments.source_directory, 'LICENSE.GPL3-EXCEPT'), tempdir)
dmg_cmd = ['hdiutil', 'create', '-srcfolder', tempdir, '-volname', arguments.dmg_volumename, dmg_cmd = ['hdiutil', 'create', '-srcfolder', tempdir, '-volname', arguments.dmg_volumename,
'-format', 'UDBZ', arguments.target_diskimage, '-ov', '-scrub', '-size', '1g', '-verbose'] '-format', 'UDBZ', arguments.target_diskimage, '-ov', '-scrub', '-size', '1500m', '-verbose']
subprocess.check_call(dmg_cmd) subprocess.check_call(dmg_cmd)
# sleep a few seconds to make sure disk image is fully unmounted etc # sleep a few seconds to make sure disk image is fully unmounted etc
time.sleep(5) time.sleep(5)

View File

@@ -189,8 +189,20 @@ SecondColumnLayout {
colorEditor.originalColor = colorEditor.color colorEditor.originalColor = colorEditor.color
} }
onValueChanged: colorEditor.color = colorEditor.value Connections {
onBackendValueChanged: colorEditor.color = colorEditor.value id: backendConnection
target: colorEditor
function onValueChanged() {
if (isNotInGradientMode())
colorEditor.color = colorEditor.value
}
function onBackendValueChanged() {
if (isNotInGradientMode())
colorEditor.color = colorEditor.value
}
}
Timer { Timer {
id: colorEditorTimer id: colorEditorTimer
@@ -198,15 +210,18 @@ SecondColumnLayout {
interval: 100 interval: 100
running: false running: false
onTriggered: { onTriggered: {
backendConnection.enabled = false
if (colorEditor.backendValue !== undefined) { if (colorEditor.backendValue !== undefined) {
if (isVector3D) { if (colorEditor.isVector3D)
colorEditor.backendValue.value = Qt.vector3d(colorEditor.color.r, colorEditor.backendValue.value = Qt.vector3d(colorEditor.color.r,
colorEditor.color.g, colorEditor.color.g,
colorEditor.color.b) colorEditor.color.b)
} else { else
colorEditor.backendValue.value = colorEditor.color colorEditor.backendValue.value = colorEditor.color
} }
}
backendConnection.enabled = true
} }
} }
@@ -223,8 +238,6 @@ SecondColumnLayout {
if (isNotInGradientMode()) if (isNotInGradientMode())
colorEditorTimer.restart() // Delay setting the color to keep ui responsive colorEditorTimer.restart() // Delay setting the color to keep ui responsive
colorPalette.selectedColor = colorEditor.color
} }
Spacer { implicitWidth: StudioTheme.Values.actionIndicatorWidth } Spacer { implicitWidth: StudioTheme.Values.actionIndicatorWidth }
@@ -419,6 +432,7 @@ SecondColumnLayout {
tooltip: qsTr("Transparent") tooltip: qsTr("Transparent")
onClicked: { onClicked: {
colorPicker.alpha = 0 colorPicker.alpha = 0
colorPicker.invalidateColor()
colorPicker.updateColor() colorPicker.updateColor()
} }
} }
@@ -503,8 +517,10 @@ SecondColumnLayout {
visible: !isNotInGradientMode() visible: !isNotInGradientMode()
onCurrentColorChanged: { onCurrentColorChanged: {
if (colorEditor.supportGradient && gradientLine.hasGradient) if (colorEditor.supportGradient && gradientLine.hasGradient) {
colorEditor.color = gradientLine.currentColor colorEditor.color = gradientLine.currentColor
colorPicker.color = colorEditor.color
}
} }
onHasGradientChanged: { onHasGradientChanged: {
@@ -515,10 +531,9 @@ SecondColumnLayout {
} }
onSelectedNodeChanged: { onSelectedNodeChanged: {
if (colorEditor.supportGradient && gradientLine.hasGradient) { if (colorEditor.supportGradient && gradientLine.hasGradient)
colorEditor.originalColor = gradientLine.currentColor colorEditor.originalColor = gradientLine.currentColor
} }
}
onInvalidated: colorEditor.updateThumbnail() onInvalidated: colorEditor.updateThumbnail()
@@ -546,13 +561,15 @@ SecondColumnLayout {
function onSelectionChanged() { function onSelectionChanged() {
if (colorEditor.supportGradient && gradientLine.hasGradient) { if (colorEditor.supportGradient && gradientLine.hasGradient) {
colorEditor.color = gradientLine.currentColor colorEditor.color = gradientLine.currentColor
gradientLine.currentColor = color gradientLine.currentColor = colorEditor.color
hexTextField.text = colorEditor.color hexTextField.text = colorEditor.color
popupHexTextField.text = colorEditor.color popupHexTextField.text = colorEditor.color
} }
gradientLine.isInValidState = true gradientLine.isInValidState = true
colorEditor.originalColor = colorEditor.color colorEditor.originalColor = colorEditor.color
colorPalette.selectedColor = colorEditor.color colorPalette.selectedColor = colorEditor.color
colorPicker.color = colorEditor.color
colorEditor.createModel() colorEditor.createModel()
colorEditor.determineActiveColorMode() colorEditor.determineActiveColorMode()
@@ -563,44 +580,32 @@ SecondColumnLayout {
ColorPicker { ColorPicker {
id: colorPicker id: colorPicker
property color boundColor: colorEditor.color
width: parent.width width: parent.width
sliderMargins: 4 sliderMargins: 4
// Prevent the binding to be deleted by assignment
onBoundColorChanged: colorPicker.color = colorPicker.boundColor
onUpdateColor: { onUpdateColor: {
colorEditor.color = colorPicker.color colorEditor.color = colorPicker.color
if (contextMenu.opened) if (contextMenu.opened)
contextMenu.close() contextMenu.close()
} }
onRightMouseButtonClicked: contextMenu.popup(colorPicker) onRightMouseButtonClicked: contextMenu.popup(colorPicker)
onColorInvalidated: { onColorInvalidated: {
switch (colorPicker.mode) {
case ColorPicker.Mode.HSLA:
hslHueSpinBox.value = colorPicker.hue hslHueSpinBox.value = colorPicker.hue
hslSaturationSpinBox.value = colorPicker.saturationHSL hslSaturationSpinBox.value = colorPicker.saturationHSL
hslLightnessSpinBox.value = colorPicker.lightness hslLightnessSpinBox.value = colorPicker.lightness
hslAlphaSpinBox.value = colorPicker.alpha hslAlphaSpinBox.value = colorPicker.alpha
break
case ColorPicker.Mode.RGBA: redSpinBox.value = (colorPicker.red * 255)
redSpinBox.value = (colorPicker.color.r * 255) greenSpinBox.value = (colorPicker.green * 255)
greenSpinBox.value = (colorPicker.color.g * 255) blueSpinBox.value = (colorPicker.blue * 255)
blueSpinBox.value = (colorPicker.color.b * 255)
rgbAlphaSpinBox.value = (colorPicker.alpha * 255) rgbAlphaSpinBox.value = (colorPicker.alpha * 255)
break
case ColorPicker.Mode.HSVA:
default:
hsvHueSpinBox.value = colorPicker.hue hsvHueSpinBox.value = colorPicker.hue
hsvSaturationSpinBox.value = colorPicker.saturationHSV hsvSaturationSpinBox.value = colorPicker.saturationHSV
hsvValueSpinBox.value = colorPicker.value hsvValueSpinBox.value = colorPicker.value
hsvAlphaSpinBox.value = colorPicker.alpha hsvAlphaSpinBox.value = colorPicker.alpha
break
}
} }
} }
@@ -790,7 +795,6 @@ SecondColumnLayout {
RowLayout { RowLayout {
id: rgbaRow id: rgbaRow
visible: colorPicker.mode === ColorPicker.Mode.RGBA visible: colorPicker.mode === ColorPicker.Mode.RGBA
Layout.fillWidth: true Layout.fillWidth: true
spacing: StudioTheme.Values.controlGap spacing: StudioTheme.Values.controlGap
@@ -798,7 +802,6 @@ SecondColumnLayout {
DoubleSpinBox { DoubleSpinBox {
id: redSpinBox id: redSpinBox
width: StudioTheme.Values.colorEditorPopupSpinBoxWidth width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
stepSize: 1 stepSize: 1
minimumValue: 0 minimumValue: 0
maximumValue: 255 maximumValue: 255
@@ -806,17 +809,19 @@ SecondColumnLayout {
onValueModified: { onValueModified: {
var tmp = redSpinBox.value / 255.0 var tmp = redSpinBox.value / 255.0
if (colorPicker.color.r !== tmp && !colorPicker.block) { if (colorPicker.red !== tmp && !colorPicker.block) {
colorPicker.color.r = tmp colorPicker.red = tmp
colorPicker.invalidateColor()
colorPicker.updateColor() colorPicker.updateColor()
} }
} }
onDragStarted: colorEditorTimer.stop()
onIndicatorPressed: colorEditorTimer.stop()
} }
DoubleSpinBox { DoubleSpinBox {
id: greenSpinBox id: greenSpinBox
width: StudioTheme.Values.colorEditorPopupSpinBoxWidth width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
stepSize: 1 stepSize: 1
minimumValue: 0 minimumValue: 0
maximumValue: 255 maximumValue: 255
@@ -824,17 +829,19 @@ SecondColumnLayout {
onValueModified: { onValueModified: {
var tmp = greenSpinBox.value / 255.0 var tmp = greenSpinBox.value / 255.0
if (colorPicker.color.g !== tmp && !colorPicker.block) { if (colorPicker.green !== tmp && !colorPicker.block) {
colorPicker.color.g = tmp colorPicker.green = tmp
colorPicker.invalidateColor()
colorPicker.updateColor() colorPicker.updateColor()
} }
} }
onDragStarted: colorEditorTimer.stop()
onIndicatorPressed: colorEditorTimer.stop()
} }
DoubleSpinBox { DoubleSpinBox {
id: blueSpinBox id: blueSpinBox
width: StudioTheme.Values.colorEditorPopupSpinBoxWidth width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
stepSize: 1 stepSize: 1
minimumValue: 0 minimumValue: 0
maximumValue: 255 maximumValue: 255
@@ -842,17 +849,19 @@ SecondColumnLayout {
onValueModified: { onValueModified: {
var tmp = blueSpinBox.value / 255.0 var tmp = blueSpinBox.value / 255.0
if (colorPicker.color.b !== tmp && !colorPicker.block) { if (colorPicker.blue !== tmp && !colorPicker.block) {
colorPicker.color.b = tmp colorPicker.blue = tmp
colorPicker.invalidateColor()
colorPicker.updateColor() colorPicker.updateColor()
} }
} }
onDragStarted: colorEditorTimer.stop()
onIndicatorPressed: colorEditorTimer.stop()
} }
DoubleSpinBox { DoubleSpinBox {
id: rgbAlphaSpinBox id: rgbAlphaSpinBox
width: StudioTheme.Values.colorEditorPopupSpinBoxWidth width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
stepSize: 1 stepSize: 1
minimumValue: 0 minimumValue: 0
maximumValue: 255 maximumValue: 255
@@ -862,15 +871,17 @@ SecondColumnLayout {
var tmp = rgbAlphaSpinBox.value / 255.0 var tmp = rgbAlphaSpinBox.value / 255.0
if (colorPicker.alpha !== tmp && !colorPicker.block) { if (colorPicker.alpha !== tmp && !colorPicker.block) {
colorPicker.alpha = tmp colorPicker.alpha = tmp
colorPicker.invalidateColor()
colorPicker.updateColor() colorPicker.updateColor()
} }
} }
onDragStarted: colorEditorTimer.stop()
onIndicatorPressed: colorEditorTimer.stop()
} }
} }
RowLayout { RowLayout {
id: hslaRow id: hslaRow
visible: colorPicker.mode === ColorPicker.Mode.HSLA visible: colorPicker.mode === ColorPicker.Mode.HSLA
Layout.fillWidth: true Layout.fillWidth: true
spacing: StudioTheme.Values.controlGap spacing: StudioTheme.Values.controlGap
@@ -882,9 +893,12 @@ SecondColumnLayout {
if (colorPicker.hue !== hslHueSpinBox.value if (colorPicker.hue !== hslHueSpinBox.value
&& !colorPicker.block) { && !colorPicker.block) {
colorPicker.hue = hslHueSpinBox.value colorPicker.hue = hslHueSpinBox.value
colorPicker.invalidateColor()
colorPicker.updateColor() colorPicker.updateColor()
} }
} }
onDragStarted: colorEditorTimer.stop()
onIndicatorPressed: colorEditorTimer.stop()
} }
DoubleSpinBox { DoubleSpinBox {
@@ -894,9 +908,12 @@ SecondColumnLayout {
if (colorPicker.saturationHSL !== hslSaturationSpinBox.value if (colorPicker.saturationHSL !== hslSaturationSpinBox.value
&& !colorPicker.block) { && !colorPicker.block) {
colorPicker.saturationHSL = hslSaturationSpinBox.value colorPicker.saturationHSL = hslSaturationSpinBox.value
colorPicker.invalidateColor()
colorPicker.updateColor() colorPicker.updateColor()
} }
} }
onDragStarted: colorEditorTimer.stop()
onIndicatorPressed: colorEditorTimer.stop()
} }
DoubleSpinBox { DoubleSpinBox {
@@ -906,6 +923,7 @@ SecondColumnLayout {
if (colorPicker.lightness !== hslLightnessSpinBox.value if (colorPicker.lightness !== hslLightnessSpinBox.value
&& !colorPicker.block) { && !colorPicker.block) {
colorPicker.lightness = hslLightnessSpinBox.value colorPicker.lightness = hslLightnessSpinBox.value
colorPicker.invalidateColor()
colorPicker.updateColor() colorPicker.updateColor()
} }
} }
@@ -918,15 +936,17 @@ SecondColumnLayout {
if (colorPicker.alpha !== hslAlphaSpinBox.value if (colorPicker.alpha !== hslAlphaSpinBox.value
&& !colorPicker.block) { && !colorPicker.block) {
colorPicker.alpha = hslAlphaSpinBox.value colorPicker.alpha = hslAlphaSpinBox.value
colorPicker.invalidateColor()
colorPicker.updateColor() colorPicker.updateColor()
} }
} }
onDragStarted: colorEditorTimer.stop()
onIndicatorPressed: colorEditorTimer.stop()
} }
} }
RowLayout { RowLayout {
id: hsvaRow id: hsvaRow
visible: colorPicker.mode === ColorPicker.Mode.HSVA visible: colorPicker.mode === ColorPicker.Mode.HSVA
Layout.fillWidth: true Layout.fillWidth: true
spacing: StudioTheme.Values.controlGap spacing: StudioTheme.Values.controlGap
@@ -938,9 +958,12 @@ SecondColumnLayout {
if (colorPicker.hue !== hsvHueSpinBox.value if (colorPicker.hue !== hsvHueSpinBox.value
&& !colorPicker.block) { && !colorPicker.block) {
colorPicker.hue = hsvHueSpinBox.value colorPicker.hue = hsvHueSpinBox.value
colorPicker.invalidateColor()
colorPicker.updateColor() colorPicker.updateColor()
} }
} }
onDragStarted: colorEditorTimer.stop()
onIndicatorPressed: colorEditorTimer.stop()
} }
DoubleSpinBox { DoubleSpinBox {
@@ -950,9 +973,12 @@ SecondColumnLayout {
if (colorPicker.saturationHSV !== hsvSaturationSpinBox.value if (colorPicker.saturationHSV !== hsvSaturationSpinBox.value
&& !colorPicker.block) { && !colorPicker.block) {
colorPicker.saturationHSV = hsvSaturationSpinBox.value colorPicker.saturationHSV = hsvSaturationSpinBox.value
colorPicker.invalidateColor()
colorPicker.updateColor() colorPicker.updateColor()
} }
} }
onDragStarted: colorEditorTimer.stop()
onIndicatorPressed: colorEditorTimer.stop()
} }
DoubleSpinBox { DoubleSpinBox {
@@ -962,9 +988,12 @@ SecondColumnLayout {
if (colorPicker.value !== hsvValueSpinBox.value if (colorPicker.value !== hsvValueSpinBox.value
&& !colorPicker.block) { && !colorPicker.block) {
colorPicker.value = hsvValueSpinBox.value colorPicker.value = hsvValueSpinBox.value
colorPicker.invalidateColor()
colorPicker.updateColor() colorPicker.updateColor()
} }
} }
onDragStarted: colorEditorTimer.stop()
onIndicatorPressed: colorEditorTimer.stop()
} }
DoubleSpinBox { DoubleSpinBox {
@@ -974,9 +1003,12 @@ SecondColumnLayout {
if (colorPicker.alpha !== hsvAlphaSpinBox.value if (colorPicker.alpha !== hsvAlphaSpinBox.value
&& !colorPicker.block) { && !colorPicker.block) {
colorPicker.alpha = hsvAlphaSpinBox.value colorPicker.alpha = hsvAlphaSpinBox.value
colorPicker.invalidateColor()
colorPicker.updateColor() colorPicker.updateColor()
} }
} }
onDragStarted: colorEditorTimer.stop()
onIndicatorPressed: colorEditorTimer.stop()
} }
} }
} }
@@ -986,7 +1018,6 @@ SecondColumnLayout {
caption: qsTr("Palette") caption: qsTr("Palette")
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
leftPadding: 10 leftPadding: 10
rightPadding: 10 rightPadding: 10
bottomPadding: 5 bottomPadding: 5
@@ -994,8 +1025,14 @@ SecondColumnLayout {
ColorPalette { ColorPalette {
id: colorPalette id: colorPalette
enableSingletonConnection: cePopup.opened enableSingletonConnection: cePopup.opened
onSelectedColorChanged: colorEditor.color = colorPalette.selectedColor onSelectedColorChanged: {
onDialogColorChanged: colorEditor.color = colorPalette.selectedColor colorPicker.color = colorPalette.selectedColor
colorEditor.color = colorPalette.selectedColor
}
onDialogColorChanged: {
colorPicker.color = colorPalette.selectedColor
colorEditor.color = colorPalette.selectedColor
}
} }
} }
@@ -1005,7 +1042,6 @@ SecondColumnLayout {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
visible: !colorEditor.isNotInGradientMode() visible: !colorEditor.isNotInGradientMode()
leftPadding: 10 leftPadding: 10
rightPadding: 10 rightPadding: 10
@@ -1039,12 +1075,10 @@ SecondColumnLayout {
Column { Column {
id: defaultGradientControls id: defaultGradientControls
spacing: 10 spacing: 10
visible: colorEditor.hasLinearGradient() && !colorEditor.shapeGradients visible: colorEditor.hasLinearGradient() && !colorEditor.shapeGradients
RowLayout { RowLayout {
id: defaultGradientOrientation id: defaultGradientOrientation
Layout.fillWidth: true Layout.fillWidth: true
spacing: 0 spacing: 0
@@ -1055,9 +1089,9 @@ SecondColumnLayout {
width: implicitWidth width: implicitWidth
model: [{ value: Gradient.Vertical, text: qsTr("Vertical") }, model: [{ value: Gradient.Vertical, text: qsTr("Vertical") },
{ value: Gradient.Horizontal, text: qsTr("Horizontal") }] { value: Gradient.Horizontal, text: qsTr("Horizontal") }]
textRole: "text" textRole: "text"
valueRole: "value" valueRole: "value"
onActivated: { onActivated: {
gradientLine.model.setGradientOrientation(gradientOrientation.currentValue) gradientLine.model.setGradientOrientation(gradientOrientation.currentValue)
colorEditor.updateThumbnail() colorEditor.updateThumbnail()
@@ -1090,7 +1124,6 @@ SecondColumnLayout {
Column { Column {
id: linearGradientControls id: linearGradientControls
spacing: 10 spacing: 10
visible: colorEditor.hasLinearGradient() && colorEditor.shapeGradients visible: colorEditor.hasLinearGradient() && colorEditor.shapeGradients
ControlsRow { ControlsRow {
@@ -1126,7 +1159,6 @@ SecondColumnLayout {
Column { Column {
id: radialGradientControls id: radialGradientControls
spacing: 10 spacing: 10
visible: colorEditor.hasRadialGradient() visible: colorEditor.hasRadialGradient()
ControlsRow { ControlsRow {
@@ -1170,7 +1202,6 @@ SecondColumnLayout {
Column { Column {
id: concialGradientControls id: concialGradientControls
spacing: 10 spacing: 10
visible: colorEditor.hasConicalGradient() visible: colorEditor.hasConicalGradient()
ControlsRow { ControlsRow {

View File

@@ -36,18 +36,20 @@ Column {
} }
property int mode: ColorPicker.Mode.HSVA property int mode: ColorPicker.Mode.HSVA
property color color property color color: "#303091"
property real red: 0
property real green: 0
property real blue: 0
property real hue: 0 property real hue: 0
property real saturationHSL: 0 property real saturationHSL: 0.5
property real saturationHSV: 0 property real saturationHSV: 0.5
property real lightness: 0 property real lightness: 0.5
property real value: 0 property real value: 0.5
property real alpha: 1 property real alpha: 1
property bool achromatic: false
property int sliderMargins: 6 property int sliderMargins: 6
property bool block: false property bool block: false
@@ -57,81 +59,90 @@ Column {
spacing: 10 spacing: 10
onModeChanged: { onColorChanged: {
if (root.block)
return
switch (root.mode) { switch (root.mode) {
case ColorPicker.Mode.RGBA: case ColorPicker.Mode.RGBA:
root.color = Qt.rgba(root.color.r, root.color.g, root.color.b, root.alpha) root.red = root.color.r
root.green = root.color.g
root.blue = root.color.b
root.alpha = root.color.a
break break
case ColorPicker.Mode.HSLA: case ColorPicker.Mode.HSLA:
root.color = Qt.hsla(root.hue, root.saturationHSL, root.lightness, root.alpha) if (root.color.hslHue !== -1)
root.hue = root.color.hslHue
root.saturationHSL = root.color.hslSaturation
root.lightness = root.color.hslLightness
root.alpha = root.color.a
break break
case ColorPicker.Mode.HSVA: case ColorPicker.Mode.HSVA:
default: default:
root.color = Qt.hsva(root.hue, root.saturationHSV, root.value, root.alpha) if (root.color.hsvHue !== -1)
root.hue = root.color.hsvHue
root.saturationHSV = root.color.hsvSaturation
root.value = root.color.hsvValue
root.alpha = root.color.a
break break
} }
gradientOverlay.requestPaint() root.invalidateColor()
} }
onHueChanged: {
if (root.mode === ColorPicker.Mode.HSLA)
root.color.hslHue = root.hue
else
root.color.hsvHue = root.hue
}
onSaturationHSLChanged: {
root.color.hslSaturation = root.saturationHSL
invalidateColor()
}
onSaturationHSVChanged: {
root.color.hsvSaturation = root.saturationHSV
}
onLightnessChanged: {
root.color.hslLightness = root.lightness
}
onValueChanged: {
root.color.hsvValue = root.value
}
onAlphaChanged: invalidateColor()
onColorChanged: invalidateColor()
function invalidateColor() { function invalidateColor() {
if (root.block) if (root.block)
return return
root.block = true root.block = true
if (root.color.hsvSaturation > 0.0 switch (root.mode) {
&& root.color.hsvValue > 0.0 case ColorPicker.Mode.RGBA:
&& root.color.hsvHue !== -1.0) root.color = Qt.rgba(root.red, root.green, root.blue, root.alpha)
root.hue = root.color.hsvHue // Set HSVA and HSLA
if (root.color.hsvHue !== -1)
root.hue = root.color.hsvHue // doesn't matter if hsvHue or hslHue
if (root.color.hslSaturation > 0.0 if (root.color.hslLightness !== 0.0 && root.color.hslLightness !== 1.0)
&& root.color.hslLightness > 0.0
&& root.color.hslHue !== -1.0)
root.hue = root.color.hslHue
if (root.color.hslLightness !== 0.0 && root.color.hslLightness !== 1.0 && !root.achromatic)
root.saturationHSL = root.color.hslSaturation root.saturationHSL = root.color.hslSaturation
if (root.color.hsvValue !== 0.0 && root.color.hsvValue !== 1.0 && !root.achromatic) if (root.color.hsvValue !== 0.0)
root.saturationHSV = root.color.hsvSaturation root.saturationHSV = root.color.hsvSaturation
root.lightness = root.color.hslLightness root.lightness = root.color.hslLightness
root.value = root.color.hsvValue root.value = root.color.hsvValue
break
if (root.color.hslLightness === 0.0 || root.color.hslLightness === 1.0 case ColorPicker.Mode.HSLA:
|| root.color.hsvValue === 0.0 || root.color.hsvValue === 1.0
|| root.color.hsvHue === -1.0 || root.color.hslHue === -1.0)
root.achromatic = true
else
root.achromatic = false
if (root.mode === ColorPicker.Mode.HSLA)
root.color = Qt.hsla(root.hue, root.saturationHSL, root.lightness, root.alpha) root.color = Qt.hsla(root.hue, root.saturationHSL, root.lightness, root.alpha)
else // Set RGBA and HSVA
root.red = root.color.r
root.green = root.color.g
root.blue = root.color.b
if (root.color.hsvValue !== 0.0)
root.saturationHSV = root.color.hsvSaturation
root.value = root.color.hsvValue
break
case ColorPicker.Mode.HSVA:
default:
root.color = Qt.hsva(root.hue, root.saturationHSV, root.value, root.alpha) root.color = Qt.hsva(root.hue, root.saturationHSV, root.value, root.alpha)
// Set RGBA and HSLA
root.red = root.color.r
root.green = root.color.g
root.blue = root.color.b
if (root.color.hslLightness !== 0.0 && root.color.hslLightness !== 1.0)
root.saturationHSL = root.color.hslSaturation
root.lightness = root.color.hslLightness
break
}
luminanceSlider.value = (1.0 - root.value) luminanceSlider.value = (1.0 - root.value)
hueSlider.value = root.hue hueSlider.value = root.hue
@@ -142,21 +153,21 @@ Column {
root.block = false root.block = false
} }
function drawHSVA(ctx) { function drawHSVA(ctx, width, height, hue) {
for (var row = 0; row < gradientOverlay.height; row++) { for (var row = 0; row < height; row++) {
var gradient = ctx.createLinearGradient(0, 0, gradientOverlay.width, 0) var gradient = ctx.createLinearGradient(0, 0, width, 0)
var v = Math.abs(row - gradientOverlay.height) / gradientOverlay.height var v = Math.abs(row - height) / height
gradient.addColorStop(0, Qt.hsva(root.hue, 0, v, 1)) gradient.addColorStop(0, Qt.hsva(hue, 0, v, 1))
gradient.addColorStop(1, Qt.hsva(root.hue, 1, v, 1)) gradient.addColorStop(1, Qt.hsva(hue, 1, v, 1))
ctx.fillStyle = gradient ctx.fillStyle = gradient
ctx.fillRect(0, row, gradientOverlay.width, 1) ctx.fillRect(0, row, width, 1)
} }
} }
function drawRGBA(ctx) { function drawRGBA(ctx, width, height) {
var gradient = ctx.createLinearGradient(0, 0, gradientOverlay.width, 0) var gradient = ctx.createLinearGradient(0, 0, width, 0)
gradient.addColorStop(0.000, Qt.rgba(1, 0, 0, 1)) gradient.addColorStop(0.000, Qt.rgba(1, 0, 0, 1))
gradient.addColorStop(0.167, Qt.rgba(1, 1, 0, 1)) gradient.addColorStop(0.167, Qt.rgba(1, 1, 0, 1))
gradient.addColorStop(0.333, Qt.rgba(0, 1, 0, 1)) gradient.addColorStop(0.333, Qt.rgba(0, 1, 0, 1))
@@ -166,26 +177,26 @@ Column {
gradient.addColorStop(1.000, Qt.rgba(1, 0, 0, 1)) gradient.addColorStop(1.000, Qt.rgba(1, 0, 0, 1))
ctx.fillStyle = gradient ctx.fillStyle = gradient
ctx.fillRect(0, 0, gradientOverlay.width, gradientOverlay.height) ctx.fillRect(0, 0, width, height)
gradient = ctx.createLinearGradient(0, 0, 0, gradientOverlay.height) gradient = ctx.createLinearGradient(0, 0, 0, height)
gradient.addColorStop(0.000, Qt.rgba(0, 0, 0, 0)) gradient.addColorStop(0.000, Qt.rgba(0, 0, 0, 0))
gradient.addColorStop(1.000, Qt.rgba(1, 1, 1, 1)) gradient.addColorStop(1.000, Qt.rgba(1, 1, 1, 1))
ctx.fillStyle = gradient ctx.fillStyle = gradient
ctx.fillRect(0, 0, gradientOverlay.width, gradientOverlay.height) ctx.fillRect(0, 0, width, height)
} }
function drawHSLA(ctx) { function drawHSLA(ctx, width, height, hue) {
for (var row = 0; row < gradientOverlay.height; row++) { for (var row = 0; row < height; row++) {
var gradient = ctx.createLinearGradient(0, 0, gradientOverlay.width, 0) var gradient = ctx.createLinearGradient(0, 0, width, 0)
var l = Math.abs(row - gradientOverlay.height) / gradientOverlay.height var l = Math.abs(row - height) / height
gradient.addColorStop(0, Qt.hsla(root.hue, 0, l, 1)) gradient.addColorStop(0, Qt.hsla(hue, 0, l, 1))
gradient.addColorStop(1, Qt.hsla(root.hue, 1, l, 1)) gradient.addColorStop(1, Qt.hsla(hue, 1, l, 1))
ctx.fillStyle = gradient ctx.fillStyle = gradient
ctx.fillRect(0, row, gradientOverlay.width, 1) ctx.fillRect(0, row, width, 1)
} }
} }
@@ -211,11 +222,12 @@ Column {
id: gradientOverlay id: gradientOverlay
anchors.fill: parent anchors.fill: parent
opacity: root.color.a opacity: root.alpha
Connections { Connections {
target: root target: root
function onHueChanged() { gradientOverlay.requestPaint() } function onHueChanged() { gradientOverlay.requestPaint() }
function onModeChanged() { gradientOverlay.requestPaint() }
} }
onPaint: { onPaint: {
@@ -225,14 +237,14 @@ Column {
switch (root.mode) { switch (root.mode) {
case ColorPicker.Mode.RGBA: case ColorPicker.Mode.RGBA:
root.drawRGBA(ctx) root.drawRGBA(ctx, gradientOverlay.width, gradientOverlay.height)
break break
case ColorPicker.Mode.HSLA: case ColorPicker.Mode.HSLA:
root.drawHSLA(ctx) root.drawHSLA(ctx, gradientOverlay.width, gradientOverlay.height, root.hue)
break break
case ColorPicker.Mode.HSVA: case ColorPicker.Mode.HSVA:
default: default:
root.drawHSVA(ctx) root.drawHSVA(ctx, gradientOverlay.width, gradientOverlay.height, root.hue)
break break
} }
@@ -244,9 +256,14 @@ Column {
id: pickerCross id: pickerCross
property color strokeStyle: "lightGray" property color strokeStyle: "lightGray"
property string loadImageUrl: "images/checkers.png"
property int radius: 10
Component.onCompleted: pickerCross.loadImage(pickerCross.loadImageUrl)
onImageLoaded: pickerCross.requestPaint()
opacity: 0.8
anchors.fill: parent anchors.fill: parent
anchors.margins: -pickerCross.radius
antialiasing: true antialiasing: true
Connections { Connections {
@@ -261,35 +278,63 @@ Column {
ctx.save() ctx.save()
ctx.clearRect(0, 0, pickerCross.width, pickerCross.height) ctx.clearRect(0, 0, pickerCross.width, pickerCross.height)
var yy, xx = 0 var normX, normY = 0
switch (root.mode) { switch (root.mode) {
case ColorPicker.Mode.RGBA: case ColorPicker.Mode.RGBA:
yy = pickerCross.height - root.saturationHSV * pickerCross.height normX = root.hue
xx = root.hue * pickerCross.width normY = 1.0 - root.saturationHSV
break break
case ColorPicker.Mode.HSLA: case ColorPicker.Mode.HSLA:
yy = pickerCross.height - root.lightness * pickerCross.height normX = root.saturationHSL
xx = root.saturationHSL * pickerCross.width normY = 1.0 - root.lightness
break break
case ColorPicker.Mode.HSVA: case ColorPicker.Mode.HSVA:
default: default:
yy = pickerCross.height - root.value * pickerCross.height normX = root.saturationHSV
xx = root.saturationHSV * pickerCross.width normY = 1.0 - root.value
break break
} }
ctx.strokeStyle = pickerCross.strokeStyle var width = pickerCross.width - pickerCross.radius * 2
ctx.lineWidth = 1 var height = pickerCross.height - pickerCross.radius * 2
var x = normX * width
var y = normY * height
var centerX = pickerCross.radius + x
var centerY = pickerCross.radius + y
// Draw checkerboard
if (isImageLoaded(pickerCross.loadImageUrl)) {
ctx.beginPath() ctx.beginPath()
ctx.moveTo(0, yy) ctx.arc(centerX, centerY, pickerCross.radius, 0, 2 * Math.PI)
ctx.lineTo(pickerCross.width, yy) ctx.clip()
var pattern = context.createPattern(pickerCross.loadImageUrl, 'repeat')
context.fillStyle = pattern
ctx.fillRect(x, y, pickerCross.radius * 2, pickerCross.radius * 2)
}
// Draw current color
if (root.mode === ColorPicker.Mode.RGBA)
ctx.fillStyle = Qt.hsva(root.hue, root.saturationHSV, 1, root.alpha)
else
ctx.fillStyle = root.color
ctx.fillRect(x, y, pickerCross.radius * 2, pickerCross.radius * 2)
// Draw black and white circle
ctx.lineWidth = 2
ctx.strokeStyle = "black"
ctx.beginPath()
ctx.arc(centerX, centerY, pickerCross.radius, 0, 2 * Math.PI)
ctx.stroke() ctx.stroke()
ctx.strokeStyle = "white"
ctx.beginPath() ctx.beginPath()
ctx.moveTo(xx, 0) ctx.arc(centerX, centerY, pickerCross.radius - 2, 0, 2 * Math.PI)
ctx.lineTo(xx, pickerCross.height)
ctx.stroke() ctx.stroke()
ctx.restore() ctx.restore()
@@ -298,31 +343,48 @@ Column {
MouseArea { MouseArea {
id: mouseArea id: mouseArea
anchors.fill: parent anchors.fill: parent
anchors.margins: -pickerCross.radius
preventStealing: true preventStealing: true
acceptedButtons: Qt.LeftButton | Qt.RightButton acceptedButtons: Qt.LeftButton | Qt.RightButton
onPositionChanged: function(mouse) { onPositionChanged: function(mouse) {
if (mouseArea.pressed && mouse.buttons === Qt.LeftButton) { if (mouseArea.pressed && mouse.buttons === Qt.LeftButton) {
var xx = Math.max(0, Math.min(mouse.x, parent.width)) // Generate color values from mouse position
var yy = Math.max(0, Math.min(mouse.y, parent.height))
// Clip/limit to margin
var x = Math.max(0, Math.min(mouse.x - pickerCross.radius, parent.width))
var y = Math.max(0, Math.min(mouse.y - pickerCross.radius, parent.height))
var normX = x / parent.width
var normY = y / parent.height
switch (root.mode) { switch (root.mode) {
case ColorPicker.Mode.RGBA: case ColorPicker.Mode.RGBA:
root.saturationHSV = 1.0 - yy / parent.height var tmpColor = Qt.hsva(normX, // hue
root.hue = xx / parent.width 1.0 - normY, // saturation
root.value,
root.alpha)
root.hue = normX
root.saturationHSV = 1.0 - normY
root.red = tmpColor.r
root.green = tmpColor.g
root.blue = tmpColor.b
break break
case ColorPicker.Mode.HSLA: case ColorPicker.Mode.HSLA:
root.saturationHSL = xx / parent.width root.saturationHSL = normX
root.lightness = 1.0 - yy / parent.height root.lightness = 1.0 - normY
break break
case ColorPicker.Mode.HSVA: case ColorPicker.Mode.HSVA:
default: default:
root.saturationHSV = xx / parent.width root.saturationHSV = normX
root.value = 1.0 - yy / parent.height root.value = 1.0 - normY
break break
} }
root.invalidateColor()
} }
} }
onPressed: function(mouse) { onPressed: function(mouse) {
@@ -345,9 +407,11 @@ Column {
id: hueSlider id: hueSlider
visible: root.mode !== ColorPicker.Mode.RGBA visible: root.mode !== ColorPicker.Mode.RGBA
width: parent.width width: parent.width
onValueChanged: { onMoved: {
if (root.hue !== hueSlider.value) if (root.hue !== hueSlider.value)
root.hue = hueSlider.value root.hue = hueSlider.value
root.invalidateColor()
} }
onClicked: root.updateColor() onClicked: root.updateColor()
} }
@@ -356,10 +420,21 @@ Column {
id: luminanceSlider id: luminanceSlider
visible: root.mode === ColorPicker.Mode.RGBA visible: root.mode === ColorPicker.Mode.RGBA
width: parent.width width: parent.width
color: Qt.hsva(root.hue, root.color.hsvSaturation, 1, 1) color: Qt.hsva(root.hue, root.saturationHSV, root.value, root.alpha)
onValueChanged: { onMoved: {
if (root.value !== luminanceSlider.value) if (root.value !== (1.0 - luminanceSlider.value))
root.value = (1.0 - luminanceSlider.value) root.value = (1.0 - luminanceSlider.value)
var tmpColor = Qt.hsva(root.hue,
root.saturationHSV,
root.value,
root.alpha)
root.red = tmpColor.r
root.green = tmpColor.g
root.blue = tmpColor.b
root.invalidateColor()
} }
onClicked: root.updateColor() onClicked: root.updateColor()
} }
@@ -367,10 +442,12 @@ Column {
OpacitySlider { OpacitySlider {
id: opacitySlider id: opacitySlider
width: parent.width width: parent.width
color: Qt.rgba(root.color.r, root.color.g, root.color.b, 1) color: root.color
onValueChanged: { onMoved: {
if (root.alpha !== opacitySlider.value) if (root.alpha !== (1.0 - opacitySlider.value))
root.alpha = (1.0 - opacitySlider.value) root.alpha = (1.0 - opacitySlider.value)
root.invalidateColor()
} }
onClicked: root.updateColor() onClicked: root.updateColor()
} }

View File

@@ -39,6 +39,8 @@ Item {
property alias hover: spinBox.hover property alias hover: spinBox.hover
signal valueModified signal valueModified
signal dragStarted
signal indicatorPressed
width: 90 width: 90
implicitHeight: spinBox.height implicitHeight: spinBox.height
@@ -48,9 +50,13 @@ Item {
StudioControls.RealSpinBox { StudioControls.RealSpinBox {
id: spinBox id: spinBox
onDragStarted: hideCursor() onDragStarted: {
hideCursor()
wrapper.dragStarted()
}
onDragEnded: restoreCursor() onDragEnded: restoreCursor()
onDragging: holdCursorInPlace() onDragging: holdCursorInPlace()
onIndicatorPressed: wrapper.indicatorPressed()
property bool hasSlider: spinBox.sliderIndicatorVisible property bool hasSlider: spinBox.sliderIndicatorVisible

View File

@@ -96,13 +96,12 @@ Item {
height: 80 height: 80
width: parent.width width: parent.width
property int effectiveWidth: width - 10 property int effectiveWidth: colorLine.width - 10
property int selectedIndex: 0 property int selectedIndex: 0
function select(index) { function select(index) {
for (var i = 0; i < repeater.model.count; i++) { for (var i = 0; i < repeater.model.count; i++)
repeater.itemAt(i).item.highlighted = false repeater.itemAt(i).item.highlighted = false
}
if (repeater.model.count < index + 1) if (repeater.model.count < index + 1)
return return
@@ -113,11 +112,12 @@ Item {
gradientModel.lock() gradientModel.lock()
root.currentColor = repeater.itemAt(index).item.color root.currentColor = repeater.itemAt(index).item.color
gradientModel.unlock() gradientModel.unlock()
root.selectedNodeChanged() root.selectedNodeChanged()
} }
function invalidate() { function invalidate() {
var gradientString = "import QtQuick 2.15; Gradient {" var gradientString = "import QtQuick 2.15; Gradient { orientation: Gradient.Horizontal;"
for (var i = 0; i < gradientModel.count; i++) { for (var i = 0; i < gradientModel.count; i++) {
gradientString += "GradientStop {}" gradientString += "GradientStop {}"
@@ -209,21 +209,21 @@ Item {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
Image {
id: checkerboard
anchors.fill: parent
source: "images/checkers.png"
fillMode: Image.Tile
}
Rectangle { Rectangle {
id: gradientRectangle id: gradientRectangle
smooth: true anchors.fill: parent
x: 0 border.color: StudioTheme.Values.themeControlOutline
y: 16 border.width: StudioTheme.Values.border
radius: 1
border.color: "#555555"
border.width: 1
width: parent.height
height: parent.width
gradient: Gradient { gradient: Gradient {
id: gradient id: gradient
} }
transformOrigin: Item.TopLeft
rotation: 270
} }
} }
} }
@@ -270,6 +270,13 @@ Item {
onXChanged: gradientStopHandle.refreshToolTip(gradientStopHandle.toolTipVisible) onXChanged: gradientStopHandle.refreshToolTip(gradientStopHandle.toolTipVisible)
Image {
width: 10
height: 10
source: "images/checkers.png"
fillMode: Image.Tile
}
Rectangle { Rectangle {
id: rectangle id: rectangle
width: 10 width: 10
@@ -277,7 +284,6 @@ Item {
color: "red" color: "red"
border.color: "gray" border.color: "gray"
border.width: 1 border.width: 1
radius: 1
} }
Canvas { Canvas {

View File

@@ -1,50 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** 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 General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
import QtQuick 2.15
import QtQuick.Layouts 1.15
Image {
id: root
signal clicked
visible: colorEditor.shapeGradients && parent.checked
width: 8
height: 4
source: "image://icons/down-arrow"
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.bottom
anchors.topMargin: 2
opacity: popupRegion.containsMouse ? 1 : 0.8
ToolTipArea {
id: popupRegion
onClicked: root.clicked()
hoverEnabled: true
anchors.fill: parent
anchors.margins: -2
tooltip: qsTr("Edit Gradient Properties")
}
}

View File

@@ -36,13 +36,14 @@ Item {
property bool integer: false property bool integer: false
signal clicked signal clicked
signal moved
height: StudioTheme.Values.hueSliderHeight height: StudioTheme.Values.hueSliderHeight
function updatePos() { function updatePos() {
if (root.maximum > root.minimum) { if (root.maximum > root.minimum) {
var pos = (track.width - handle.width) * (root.value - root.minimum) / (root.maximum - root.minimum) var pos = track.width * (root.value - root.minimum) / (root.maximum - root.minimum)
return Math.min(Math.max(pos, 0), track.width - handle.width) return Math.min(Math.max(pos, 0), track.width)
} else { } else {
return 0 return 0
} }
@@ -50,7 +51,6 @@ Item {
Item { Item {
id: track id: track
width: parent.width width: parent.width
height: parent.height height: parent.height
@@ -74,21 +74,20 @@ Item {
Rectangle { Rectangle {
id: handle id: handle
width: StudioTheme.Values.hueSliderHandleWidth width: StudioTheme.Values.hueSliderHandleWidth
height: track.height - 4 height: track.height + 4
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
smooth: true
color: "transparent" color: "transparent"
radius: 2 radius: 2
border.color: "black" border.color: "black"
border.width: 1 border.width: 1
x: root.updatePos() x: root.updatePos() - handle.width * 0.5
y: 2 y: 2
z: 1 z: 1
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
anchors.margins: 1 anchors.margins: 1
color: "transparent" color: Qt.hsva(value, 1, 1, 1)
radius: 1 radius: 1
border.color: "white" border.color: "white"
border.width: 1 border.width: 1
@@ -98,21 +97,23 @@ Item {
MouseArea { MouseArea {
id: mouseArea id: mouseArea
anchors.fill: parent anchors.fill: parent
anchors.margins: -StudioTheme.Values.hueSliderHandleWidth * 0.5
preventStealing: true preventStealing: true
function calculateValue() { function calculateValue() {
var handleX = Math.max(0, Math.min(mouseArea.mouseX, mouseArea.width)) var halfHandle = StudioTheme.Values.hueSliderHandleWidth * 0.5
var realValue = (root.maximum - root.minimum) * handleX / mouseArea.width + root.minimum var handleX = Math.max(0, Math.min(mouseArea.mouseX - halfHandle, parent.width))
var realValue = (root.maximum - root.minimum) * handleX / parent.width + root.minimum
root.value = root.integer ? Math.round(realValue) : realValue root.value = root.integer ? Math.round(realValue) : realValue
root.moved()
} }
onPressed: calculateValue() onPressed: mouseArea.calculateValue()
onReleased: root.clicked() onReleased: root.clicked()
onPositionChanged: { onPositionChanged: {
if (pressed) if (mouseArea.pressed)
calculateValue() mouseArea.calculateValue()
} }
} }
} }
} }

View File

@@ -37,13 +37,14 @@ Item {
property color color property color color
signal clicked signal clicked
signal moved
height: StudioTheme.Values.hueSliderHeight height: StudioTheme.Values.hueSliderHeight
function updatePos() { function updatePos() {
if (root.maximum > root.minimum) { if (root.maximum > root.minimum) {
var pos = (track.width - handle.width) * (root.value - root.minimum) / (root.maximum - root.minimum) var pos = track.width * (root.value - root.minimum) / (root.maximum - root.minimum)
return Math.min(Math.max(pos, 0), track.width - handle.width) return Math.min(Math.max(pos, 0), track.width)
} else { } else {
return 0 return 0
} }
@@ -51,17 +52,9 @@ Item {
Item { Item {
id: track id: track
width: parent.width width: parent.width
height: parent.height height: parent.height
Image {
id: checkerboard
anchors.fill: parent
source: "images/checkers.png"
fillMode: Image.Tile
}
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
border.color: StudioTheme.Values.themeControlOutline border.color: StudioTheme.Values.themeControlOutline
@@ -69,7 +62,7 @@ Item {
gradient: Gradient { gradient: Gradient {
orientation: Gradient.Horizontal orientation: Gradient.Horizontal
GradientStop { position: 0.000; color: root.color } GradientStop { position: 0.000; color: Qt.hsva(root.color.hsvHue, root.color.hsvSaturation, 1, 1) }
GradientStop { position: 1.000; color: "black" } GradientStop { position: 1.000; color: "black" }
} }
} }
@@ -77,21 +70,20 @@ Item {
Rectangle { Rectangle {
id: handle id: handle
width: StudioTheme.Values.hueSliderHandleWidth width: StudioTheme.Values.hueSliderHandleWidth
height: track.height - 4 height: track.height + 4
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
smooth: true
color: "transparent" color: "transparent"
radius: 2 radius: 2
border.color: "black" border.color: "black"
border.width: 1 border.width: 1
x: root.updatePos() x: root.updatePos() - handle.width * 0.5
y: 2 y: 2
z: 1 z: 1
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
anchors.margins: 1 anchors.margins: 1
color: "transparent" color: Qt.hsva(root.color.hsvHue, root.color.hsvSaturation, root.color.hsvValue, 1)
radius: 1 radius: 1
border.color: "white" border.color: "white"
border.width: 1 border.width: 1
@@ -101,19 +93,22 @@ Item {
MouseArea { MouseArea {
id: mouseArea id: mouseArea
anchors.fill: parent anchors.fill: parent
anchors.margins: -StudioTheme.Values.hueSliderHandleWidth * 0.5
preventStealing: true preventStealing: true
function calculateValue() { function calculateValue() {
var handleX = Math.max(0, Math.min(mouseArea.mouseX, mouseArea.width)) var halfHandle = StudioTheme.Values.hueSliderHandleWidth * 0.5
var realValue = (root.maximum - root.minimum) * handleX / mouseArea.width + root.minimum var handleX = Math.max(0, Math.min(mouseArea.mouseX - halfHandle, parent.width))
var realValue = (root.maximum - root.minimum) * handleX / parent.width + root.minimum
root.value = root.integer ? Math.round(realValue) : realValue root.value = root.integer ? Math.round(realValue) : realValue
root.moved()
} }
onPressed: calculateValue() onPressed: mouseArea.calculateValue()
onReleased: root.clicked() onReleased: root.clicked()
onPositionChanged: { onPositionChanged: {
if (pressed) if (mouseArea.pressed)
calculateValue() mouseArea.calculateValue()
} }
} }

View File

@@ -37,13 +37,14 @@ Item {
property color color property color color
signal clicked signal clicked
signal moved
height: StudioTheme.Values.hueSliderHeight height: StudioTheme.Values.hueSliderHeight
function updatePos() { function updatePos() {
if (root.maximum > root.minimum) { if (root.maximum > root.minimum) {
var pos = (track.width - handle.width) * (root.value - root.minimum) / (root.maximum - root.minimum) var pos = track.width * (root.value - root.minimum) / (root.maximum - root.minimum)
return Math.min(Math.max(pos, 0), track.width - handle.width) return Math.min(Math.max(pos, 0), track.width)
} else { } else {
return 0 return 0
} }
@@ -51,12 +52,10 @@ Item {
Item { Item {
id: track id: track
width: parent.width width: parent.width
height: parent.height height: parent.height
Image { Image {
id: checkerboard
anchors.fill: parent anchors.fill: parent
source: "images/checkers.png" source: "images/checkers.png"
fillMode: Image.Tile fillMode: Image.Tile
@@ -69,7 +68,7 @@ Item {
gradient: Gradient { gradient: Gradient {
orientation: Gradient.Horizontal orientation: Gradient.Horizontal
GradientStop { position: 0.000; color: root.color } GradientStop { position: 0.000; color: Qt.rgba(root.color.r, root.color.g, root.color.b, 1) }
GradientStop { position: 1.000; color: "transparent" } GradientStop { position: 1.000; color: "transparent" }
} }
} }
@@ -77,21 +76,27 @@ Item {
Rectangle { Rectangle {
id: handle id: handle
width: StudioTheme.Values.hueSliderHandleWidth width: StudioTheme.Values.hueSliderHandleWidth
height: track.height - 4 height: track.height + 4
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
smooth: true
color: "transparent" color: "transparent"
radius: 2 radius: 2
border.color: "black" border.color: "black"
border.width: 1 border.width: 1
x: root.updatePos() x: root.updatePos() - handle.width * 0.5
y: 2 y: 2
z: 1 z: 1
Image {
anchors.fill: handleInside
source: "images/checkers.png"
fillMode: Image.Tile
}
Rectangle { Rectangle {
id: handleInside
anchors.fill: parent anchors.fill: parent
anchors.margins: 1 anchors.margins: 1
color: "transparent" color: root.color
radius: 1 radius: 1
border.color: "white" border.color: "white"
border.width: 1 border.width: 1
@@ -101,19 +106,22 @@ Item {
MouseArea { MouseArea {
id: mouseArea id: mouseArea
anchors.fill: parent anchors.fill: parent
anchors.margins: -StudioTheme.Values.hueSliderHandleWidth * 0.5
preventStealing: true preventStealing: true
function calculateValue() { function calculateValue() {
var handleX = Math.max(0, Math.min(mouseArea.mouseX, mouseArea.width)) var halfHandle = StudioTheme.Values.hueSliderHandleWidth * 0.5
var realValue = (root.maximum - root.minimum) * handleX / mouseArea.width + root.minimum var handleX = Math.max(0, Math.min(mouseArea.mouseX - halfHandle, parent.width))
var realValue = (root.maximum - root.minimum) * handleX / parent.width + root.minimum
root.value = root.integer ? Math.round(realValue) : realValue root.value = root.integer ? Math.round(realValue) : realValue
root.moved()
} }
onPressed: calculateValue() onPressed: mouseArea.calculateValue()
onReleased: root.clicked() onReleased: root.clicked()
onPositionChanged: { onPositionChanged: {
if (pressed) if (mouseArea.pressed)
calculateValue() mouseArea.calculateValue()
} }
} }

View File

@@ -71,7 +71,7 @@ Row {
border.color: StudioTheme.Values.themeToolTipOutline border.color: StudioTheme.Values.themeToolTipOutline
border.width: StudioTheme.Values.border border.width: StudioTheme.Values.border
} }
contentItem: Label { contentItem: Text {
color: StudioTheme.Values.themeToolTipText color: StudioTheme.Values.themeToolTipText
text: toolTip.text text: toolTip.text
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
@@ -135,7 +135,7 @@ Row {
border.color: StudioTheme.Values.themeToolTipOutline border.color: StudioTheme.Values.themeToolTipOutline
border.width: StudioTheme.Values.border border.width: StudioTheme.Values.border
} }
contentItem: Label { contentItem: Text {
color: StudioTheme.Values.themeToolTipText color: StudioTheme.Values.themeToolTipText
text: itemToolTip.text text: itemToolTip.text
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter

View File

@@ -31,7 +31,6 @@ FontExtrasSection 2.0 FontExtrasSection.qml
FontSection 2.0 FontSection.qml FontSection 2.0 FontSection.qml
FontStyleButtons 2.0 FontStyleButtons.qml FontStyleButtons 2.0 FontStyleButtons.qml
GradientLine 2.0 GradientLine.qml GradientLine 2.0 GradientLine.qml
GradientPopupIndicator 2.0 GradientPopupIndicator.qml
GradientPresetList 2.0 GradientPresetList.qml GradientPresetList 2.0 GradientPresetList.qml
GradientPresetTabContent 2.0 GradientPresetTabContent.qml GradientPresetTabContent 2.0 GradientPresetTabContent.qml
GradientPropertySpinBox 2.0 GradientPropertySpinBox.qml GradientPropertySpinBox 2.0 GradientPropertySpinBox.qml

View File

@@ -131,7 +131,7 @@ T.CheckBox {
}, },
State { State {
name: "globalHover" name: "globalHover"
when: actionIndicator.hover && myCheckBox.hover && !myCheckBox.pressed when: actionIndicator.hover && !myCheckBox.pressed && myCheckBox.enabled
PropertyChanges { PropertyChanges {
target: checkBoxBackground target: checkBoxBackground
color: StudioTheme.Values.themeControlBackgroundGlobalHover color: StudioTheme.Values.themeControlBackgroundGlobalHover

View File

@@ -121,7 +121,7 @@ T.ComboBox {
ComboBox.ActivatedReason.Other) ComboBox.ActivatedReason.Other)
} }
onActivated: { onActivated: function(index) {
myTimer.activatedIndex = index myTimer.activatedIndex = index
myTimer.restart() myTimer.restart()
} }

View File

@@ -81,6 +81,7 @@ T.SpinBox {
signal dragStarted signal dragStarted
signal dragEnded signal dragEnded
signal dragging signal dragging
signal indicatorPressed
// Use custom wheel handling due to bugs // Use custom wheel handling due to bugs
property bool __wheelEnabled: false property bool __wheelEnabled: false
@@ -124,6 +125,7 @@ T.SpinBox {
myControl: mySpinBox myControl: mySpinBox
iconFlip: -1 iconFlip: -1
visible: mySpinBox.spinBoxIndicatorVisible visible: mySpinBox.spinBoxIndicatorVisible
onRealPressed: mySpinBox.indicatorPressed()
onRealReleased: mySpinBox.realIncrease() onRealReleased: mySpinBox.realIncrease()
onRealPressAndHold: mySpinBox.realIncrease() onRealPressAndHold: mySpinBox.realIncrease()
x: actionIndicator.width + StudioTheme.Values.border x: actionIndicator.width + StudioTheme.Values.border
@@ -139,6 +141,7 @@ T.SpinBox {
id: spinBoxIndicatorDown id: spinBoxIndicatorDown
myControl: mySpinBox myControl: mySpinBox
visible: mySpinBox.spinBoxIndicatorVisible visible: mySpinBox.spinBoxIndicatorVisible
onRealPressed: mySpinBox.indicatorPressed()
onRealReleased: mySpinBox.realDecrease() onRealReleased: mySpinBox.realDecrease()
onRealPressAndHold: mySpinBox.realDecrease() onRealPressAndHold: mySpinBox.realDecrease()
x: actionIndicator.width + StudioTheme.Values.border x: actionIndicator.width + StudioTheme.Values.border

View File

@@ -157,7 +157,6 @@ void ProcessReaper::reap(QProcess *process, int timeoutMs)
QTC_ASSERT(QThread::currentThread() == process->thread(), return); QTC_ASSERT(QThread::currentThread() == process->thread(), return);
process->disconnect(); process->disconnect();
process->setParent(nullptr);
if (process->state() == QProcess::NotRunning) { if (process->state() == QProcess::NotRunning) {
process->deleteLater(); process->deleteLater();
return; return;

View File

@@ -473,7 +473,13 @@ FilePath AndroidConfig::avdManagerToolPath() const
FilePath AndroidConfig::toolchainPathFromNdk(const FilePath &ndkLocation) const FilePath AndroidConfig::toolchainPathFromNdk(const FilePath &ndkLocation) const
{ {
const FilePath toolchainPath = ndkLocation / "toolchains/llvm/prebuilt/"; const FilePath tcPath = ndkLocation / "toolchains/";
FilePath toolchainPath;
QDirIterator llvmIter(tcPath.toString(), {"llvm*"}, QDir::Dirs);
if (llvmIter.hasNext()) {
llvmIter.next();
toolchainPath = tcPath / llvmIter.fileName() / "prebuilt/";
}
// detect toolchain host // detect toolchain host
QStringList hostPatterns; QStringList hostPatterns;

View File

@@ -544,11 +544,13 @@ void AndroidDeployQtStep::stdError(const QString &line)
return; return;
if (newOutput.startsWith("warning", Qt::CaseInsensitive) if (newOutput.startsWith("warning", Qt::CaseInsensitive)
|| newOutput.startsWith("note", Qt::CaseInsensitive)) || newOutput.startsWith("note", Qt::CaseInsensitive)
|| newOutput.startsWith(QLatin1String("All files should be loaded."))) {
TaskHub::addTask(DeploymentTask(Task::Warning, newOutput)); TaskHub::addTask(DeploymentTask(Task::Warning, newOutput));
else if (newOutput != QLatin1String("All files should be loaded. Notifying the device.")) } else {
TaskHub::addTask(DeploymentTask(Task::Error, newOutput)); TaskHub::addTask(DeploymentTask(Task::Error, newOutput));
} }
}
AndroidDeployQtStep::DeployErrorCode AndroidDeployQtStep::parseDeployErrors( AndroidDeployQtStep::DeployErrorCode AndroidDeployQtStep::parseDeployErrors(
const QString &deployOutputLine) const const QString &deployOutputLine) const

View File

@@ -117,12 +117,16 @@ QList<ITestConfiguration *> CTestTreeItem::testConfigurationsFor(const QStringLi
config->setProject(project); config->setProject(project);
config->setCommandLine(command); config->setCommandLine(command);
const ProjectExplorer::RunConfiguration *runConfig = target->activeRunConfiguration(); const ProjectExplorer::RunConfiguration *runConfig = target->activeRunConfiguration();
Utils::Environment env = Utils::Environment::systemEnvironment();
if (QTC_GUARD(runConfig)) { if (QTC_GUARD(runConfig)) {
if (auto envAspect = runConfig->aspect<ProjectExplorer::EnvironmentAspect>()) if (auto envAspect = runConfig->aspect<ProjectExplorer::EnvironmentAspect>())
config->setEnvironment(envAspect->environment()); env = envAspect->environment();
else
config->setEnvironment(Utils::Environment::systemEnvironment());
} }
if (Utils::HostOsInfo::isWindowsHost()) {
env.set("QT_FORCE_STDERR_LOGGING", "1");
env.set("QT_LOGGING_TO_CONSOLE", "1");
}
config->setEnvironment(env);
const ProjectExplorer::BuildConfiguration *buildConfig = target->activeBuildConfiguration(); const ProjectExplorer::BuildConfiguration *buildConfig = target->activeBuildConfiguration();
if (QTC_GUARD(buildConfig)) if (QTC_GUARD(buildConfig))
config->setWorkingDirectory(buildConfig->buildDirectory()); config->setWorkingDirectory(buildConfig->buildDirectory());

View File

@@ -153,8 +153,10 @@ QStringList filterInterfering(const QStringList &provided, QStringList *omitted,
Utils::Environment prepareBasicEnvironment(const Utils::Environment &env) Utils::Environment prepareBasicEnvironment(const Utils::Environment &env)
{ {
Utils::Environment result(env); Utils::Environment result(env);
if (Utils::HostOsInfo::isWindowsHost()) if (Utils::HostOsInfo::isWindowsHost()) {
result.set("QT_FORCE_STDERR_LOGGING", "1");
result.set("QT_LOGGING_TO_CONSOLE", "1"); result.set("QT_LOGGING_TO_CONSOLE", "1");
}
const int timeout = AutotestPlugin::settings()->timeout; const int timeout = AutotestPlugin::settings()->timeout;
if (timeout > 5 * 60 * 1000) // Qt5.5 introduced hard limit, Qt5.6.1 added env var to raise this if (timeout > 5 * 60 * 1000) // Qt5.5 introduced hard limit, Qt5.6.1 added env var to raise this
result.set("QTEST_FUNCTION_TIMEOUT", QString::number(timeout)); result.set("QTEST_FUNCTION_TIMEOUT", QString::number(timeout));

View File

@@ -312,6 +312,7 @@ void QuickTestParser::handleDirectoryChanged(const QString &directory)
return filesAndDates.value(file) != watched.value(file); return filesAndDates.value(file) != watched.value(file);
}); });
if (timestampChanged) { if (timestampChanged) {
m_watchedFiles[directory] = filesAndDates;
PathsAndLanguages paths; PathsAndLanguages paths;
paths.maybeInsert(Utils::FilePath::fromString(directory), Dialect::Qml); paths.maybeInsert(Utils::FilePath::fromString(directory), Dialect::Qml);
QFutureInterface<void> future; QFutureInterface<void> future;

View File

@@ -391,12 +391,10 @@ void TestTreeModel::synchronizeTestTools()
for (ITestTool *testTool : qAsConst(tools)) { for (ITestTool *testTool : qAsConst(tools)) {
ITestTreeItem *testToolRootNode = testTool->rootNode(); ITestTreeItem *testToolRootNode = testTool->rootNode();
if (testTool->active()) {
invisibleRoot->appendChild(testToolRootNode); invisibleRoot->appendChild(testToolRootNode);
if (!oldFrameworkRoots.removeOne(testToolRootNode)) if (!oldFrameworkRoots.removeOne(testToolRootNode))
newlyAdded.insert(testTool); newlyAdded.insert(testTool);
} }
}
if (project) { if (project) {
const QList<Target *> &allTargets = project->targets(); const QList<Target *> &allTargets = project->targets();

View File

@@ -68,6 +68,7 @@
#include <QMenu> #include <QMenu>
#include <QTextBlock> #include <QTextBlock>
#include <QTimer> #include <QTimer>
#include <QtDebug>
using namespace CppEditor; using namespace CppEditor;
using namespace LanguageClient; using namespace LanguageClient;
@@ -381,7 +382,7 @@ ClangdClient *ClangModelManagerSupport::clientForProject(
&& c->state() != Client::ShutdownRequested && c->state() != Client::ShutdownRequested
&& c->state() != Client::Shutdown; && c->state() != Client::Shutdown;
}); });
QTC_CHECK(clients.size() <= 1); QTC_ASSERT(clients.size() <= 1, qDebug() << project << clients.size());
return clients.empty() ? nullptr : qobject_cast<ClangdClient *>(clients.first()); return clients.empty() ? nullptr : qobject_cast<ClangdClient *>(clients.first());
} }

View File

@@ -53,7 +53,7 @@ using namespace CMakeProjectManager::Internal::FileApiDetails;
class CMakeFileResult class CMakeFileResult
{ {
public: public:
QSet<FilePath> cmakeFiles; QSet<CMakeFileInfo> cmakeFiles;
std::vector<std::unique_ptr<ProjectExplorer::FileNode>> cmakeNodesSource; std::vector<std::unique_ptr<ProjectExplorer::FileNode>> cmakeNodesSource;
std::vector<std::unique_ptr<ProjectExplorer::FileNode>> cmakeNodesBuild; std::vector<std::unique_ptr<ProjectExplorer::FileNode>> cmakeNodesBuild;
@@ -61,7 +61,7 @@ public:
std::vector<std::unique_ptr<ProjectExplorer::FileNode>> cmakeListNodes; std::vector<std::unique_ptr<ProjectExplorer::FileNode>> cmakeListNodes;
}; };
CMakeFileResult extractCMakeFilesData(const std::vector<FileApiDetails::CMakeFileInfo> &cmakefiles, CMakeFileResult extractCMakeFilesData(const std::vector<CMakeFileInfo> &cmakefiles,
const FilePath &sourceDirectory, const FilePath &sourceDirectory,
const FilePath &buildDirectory) const FilePath &buildDirectory)
{ {
@@ -72,9 +72,11 @@ CMakeFileResult extractCMakeFilesData(const std::vector<FileApiDetails::CMakeFil
for (const CMakeFileInfo &info : cmakefiles) { for (const CMakeFileInfo &info : cmakefiles) {
const FilePath sfn = FilePath::fromString( const FilePath sfn = FilePath::fromString(
QDir::cleanPath(sourceDir.absoluteFilePath(info.path))); QDir::cleanPath(sourceDir.absoluteFilePath(info.path.toString())));
const int oldCount = result.cmakeFiles.count(); const int oldCount = result.cmakeFiles.count();
result.cmakeFiles.insert(sfn); CMakeFileInfo absolute(info);
absolute.path = sfn;
result.cmakeFiles.insert(absolute);
if (oldCount < result.cmakeFiles.count()) { if (oldCount < result.cmakeFiles.count()) {
if (info.isCMake && !info.isCMakeListsDotTxt) { if (info.isCMake && !info.isCMakeListsDotTxt) {
// Skip files that cmake considers to be part of the installation -- but include // Skip files that cmake considers to be part of the installation -- but include
@@ -109,7 +111,7 @@ class PreprocessedData
public: public:
CMakeProjectManager::CMakeConfig cache; CMakeProjectManager::CMakeConfig cache;
QSet<FilePath> cmakeFiles; QSet<CMakeFileInfo> cmakeFiles;
std::vector<std::unique_ptr<ProjectExplorer::FileNode>> cmakeNodesSource; std::vector<std::unique_ptr<ProjectExplorer::FileNode>> cmakeNodesSource;
std::vector<std::unique_ptr<ProjectExplorer::FileNode>> cmakeNodesBuild; std::vector<std::unique_ptr<ProjectExplorer::FileNode>> cmakeNodesBuild;

View File

@@ -44,12 +44,26 @@ namespace Internal {
class FileApiData; class FileApiData;
class CMakeFileInfo
{
public:
bool operator==(const CMakeFileInfo& other) const { return path == other.path; }
Utils::FilePath path;
bool isCMake = false;
bool isCMakeListsDotTxt = false;
bool isExternal = false;
bool isGenerated = false;
};
inline uint qHash(const CMakeFileInfo &info, uint seed = 0) { return info.path.hash(seed); }
class FileApiQtcData class FileApiQtcData
{ {
public: public:
QString errorMessage; QString errorMessage;
CMakeConfig cache; CMakeConfig cache;
QSet<Utils::FilePath> cmakeFiles; QSet<CMakeFileInfo> cmakeFiles;
QList<CMakeBuildTarget> buildTargets; QList<CMakeBuildTarget> buildTargets;
ProjectExplorer::RawProjectParts projectParts; ProjectExplorer::RawProjectParts projectParts;
std::unique_ptr<CMakeProjectNode> rootProjectNode; std::unique_ptr<CMakeProjectNode> rootProjectNode;

View File

@@ -249,10 +249,10 @@ static std::vector<CMakeFileInfo> readCMakeFilesFile(const FilePath &cmakeFilesF
for (const QJsonValue &v : inputs) { for (const QJsonValue &v : inputs) {
CMakeFileInfo info; CMakeFileInfo info;
const QJsonObject input = v.toObject(); const QJsonObject input = v.toObject();
info.path = input.value("path").toString(); info.path = FilePath::fromString(input.value("path").toString());
info.isCMake = input.value("isCMake").toBool(); info.isCMake = input.value("isCMake").toBool();
const QString filename = FilePath::fromString(info.path).fileName(); const QString filename = info.path.fileName();
info.isCMakeListsDotTxt = (filename.compare("CMakeLists.txt", info.isCMakeListsDotTxt = (filename.compare("CMakeLists.txt",
HostOsInfo::fileNameCaseSensitivity()) HostOsInfo::fileNameCaseSensitivity())
== 0); == 0);

View File

@@ -71,16 +71,6 @@ public:
Utils::FilePath jsonFile(const QString &kind, const Utils::FilePath &replyDir) const; Utils::FilePath jsonFile(const QString &kind, const Utils::FilePath &replyDir) const;
}; };
class CMakeFileInfo
{
public:
QString path;
bool isCMake = false;
bool isCMakeListsDotTxt = false;
bool isExternal = false;
bool isGenerated = false;
};
class Directory class Directory
{ {
public: public:
@@ -243,7 +233,7 @@ class FileApiData
public: public:
FileApiDetails::ReplyFileContents replyFile; FileApiDetails::ReplyFileContents replyFile;
CMakeConfig cache; CMakeConfig cache;
std::vector<FileApiDetails::CMakeFileInfo> cmakeFiles; std::vector<CMakeFileInfo> cmakeFiles;
FileApiDetails::Configuration codemodel; FileApiDetails::Configuration codemodel;
std::vector<FileApiDetails::TargetDetails> targetDetails; std::vector<FileApiDetails::TargetDetails> targetDetails;
}; };

View File

@@ -88,8 +88,12 @@ void FileApiReader::setParameters(const BuildDirParameters &p)
void FileApiReader::resetData() void FileApiReader::resetData()
{ {
m_cmakeFiles.clear(); m_cmakeFiles.clear();
if (!m_parameters.sourceDirectory.isEmpty()) if (!m_parameters.sourceDirectory.isEmpty()) {
m_cmakeFiles.insert(m_parameters.sourceDirectory.pathAppended("CMakeLists.txt")); CMakeFileInfo cmakeListsTxt;
cmakeListsTxt.path = m_parameters.sourceDirectory.pathAppended("CMakeLists.txt");
cmakeListsTxt.isCMakeListsDotTxt = true;
m_cmakeFiles.insert(cmakeListsTxt);
}
m_cache.clear(); m_cache.clear();
m_buildTargets.clear(); m_buildTargets.clear();
@@ -124,8 +128,9 @@ void FileApiReader::parse(bool forceCMakeRun,
const bool hasArguments = !args.isEmpty(); const bool hasArguments = !args.isEmpty();
const bool replyFileMissing = !replyFile.exists(); const bool replyFileMissing = !replyFile.exists();
const bool cmakeFilesChanged = m_parameters.cmakeTool() && m_parameters.cmakeTool()->isAutoRun() const bool cmakeFilesChanged = m_parameters.cmakeTool() && m_parameters.cmakeTool()->isAutoRun()
&& anyOf(m_cmakeFiles, [&replyFile](const FilePath &f) { && anyOf(m_cmakeFiles, [&replyFile](const CMakeFileInfo &info) {
return f.lastModified() > replyFile.lastModified(); return !info.isGenerated
&& info.path.lastModified() > replyFile.lastModified();
}); });
const bool queryFileChanged = anyOf(FileApiParser::cmakeQueryFilePaths(m_parameters.buildDirectory), const bool queryFileChanged = anyOf(FileApiParser::cmakeQueryFilePaths(m_parameters.buildDirectory),
[&replyFile](const FilePath &qf) { [&replyFile](const FilePath &qf) {
@@ -175,7 +180,10 @@ bool FileApiReader::isParsing() const
QSet<FilePath> FileApiReader::projectFilesToWatch() const QSet<FilePath> FileApiReader::projectFilesToWatch() const
{ {
return m_cmakeFiles; return Utils::transform(
Utils::filtered(m_cmakeFiles,
[](const CMakeFileInfo &info) { return !info.isGenerated; }),
[](const CMakeFileInfo &info) { return info.path;});
} }
QList<CMakeBuildTarget> FileApiReader::takeBuildTargets(QString &errorMessage){ QList<CMakeBuildTarget> FileApiReader::takeBuildTargets(QString &errorMessage){
@@ -249,7 +257,7 @@ void FileApiReader::endState(const FilePath &replyFilePath)
const FilePath sourceDirectory = m_parameters.sourceDirectory; const FilePath sourceDirectory = m_parameters.sourceDirectory;
const FilePath buildDirectory = m_parameters.buildDirectory; const FilePath buildDirectory = m_parameters.buildDirectory;
const FilePath topCmakeFile = m_cmakeFiles.size() == 1 ? *m_cmakeFiles.begin() : FilePath{}; const FilePath topCmakeFile = m_cmakeFiles.size() == 1 ? (*m_cmakeFiles.begin()).path : FilePath{};
const QString cmakeBuildType = m_parameters.cmakeBuildType == "Build" ? "" : m_parameters.cmakeBuildType; const QString cmakeBuildType = m_parameters.cmakeBuildType == "Build" ? "" : m_parameters.cmakeBuildType;
QTC_CHECK(!replyFilePath.needsDevice()); QTC_CHECK(!replyFilePath.needsDevice());

View File

@@ -28,6 +28,7 @@
#include "cmakebuildtarget.h" #include "cmakebuildtarget.h"
#include "cmakeprocess.h" #include "cmakeprocess.h"
#include "cmakeprojectnodes.h" #include "cmakeprojectnodes.h"
#include "fileapidataextractor.h"
#include <projectexplorer/rawprojectpart.h> #include <projectexplorer/rawprojectpart.h>
#include <projectexplorer/treescanner.h> #include <projectexplorer/treescanner.h>
@@ -100,7 +101,7 @@ private:
// cmake data: // cmake data:
CMakeConfig m_cache; CMakeConfig m_cache;
QSet<Utils::FilePath> m_cmakeFiles; QSet<CMakeFileInfo> m_cmakeFiles;
QList<CMakeBuildTarget> m_buildTargets; QList<CMakeBuildTarget> m_buildTargets;
ProjectExplorer::RawProjectParts m_projectParts; ProjectExplorer::RawProjectParts m_projectParts;
std::unique_ptr<CMakeProjectNode> m_rootProjectNode; std::unique_ptr<CMakeProjectNode> m_rootProjectNode;

View File

@@ -440,8 +440,13 @@ Utils::FilePath CompilationDatabaseProject::rootPathFromSettings() const
#ifdef WITH_TESTS #ifdef WITH_TESTS
return Utils::FilePath::fromString(projectDirectory().fileName()); return Utils::FilePath::fromString(projectDirectory().fileName());
#else #else
return Utils::FilePath::fromString( auto rootPath = Utils::FilePath::fromString(
namedSettings(ProjectExplorer::Constants::PROJECT_ROOT_PATH_KEY).toString()); namedSettings(ProjectExplorer::Constants::PROJECT_ROOT_PATH_KEY).toString());
if (rootPath.isEmpty())
rootPath = Utils::FilePath::fromString(projectDirectory().fileName());
return rootPath;
#endif #endif
} }

View File

@@ -49,7 +49,7 @@ public:
virtual QString currentFindString() const = 0; virtual QString currentFindString() const = 0;
virtual QString completedFindString() const = 0; virtual QString completedFindString() const = 0;
virtual void highlightAll(const QString &txt, FindFlags findFlags); virtual void highlightAll(const QString &txt, FindFlags findFlags) {}
virtual Result findIncremental(const QString &txt, FindFlags findFlags) = 0; virtual Result findIncremental(const QString &txt, FindFlags findFlags) = 0;
virtual Result findStep(const QString &txt, FindFlags findFlags) = 0; virtual Result findStep(const QString &txt, FindFlags findFlags) = 0;
virtual void replace(const QString &before, const QString &after, virtual void replace(const QString &before, const QString &after,
@@ -68,6 +68,4 @@ signals:
void changed(); void changed();
}; };
inline void IFindSupport::highlightAll(const QString &, FindFlags) {}
} // namespace Core } // namespace Core

View File

@@ -2816,7 +2816,7 @@ public:
N2::test *getBar() const; N2::test *getBar() const;
void setBar(const custom<N2::test> &newBar); void setBar(const custom<N2::test> &newBar);
signals: signals:
void barChanged(N2::test*); void barChanged(N2::test *bar);
private: private:
Q_PROPERTY(N2::test *bar READ getBar NOTIFY barChanged) Q_PROPERTY(N2::test *bar READ getBar NOTIFY barChanged)
}; };
@@ -3613,7 +3613,7 @@ void QuickfixTest::testInsertQtPropertyMembers_data()
" }\n" " }\n"
"\n" "\n"
"signals:\n" "signals:\n"
" void itChanged(int);\n" " void itChanged(int it);\n"
"\n" "\n"
"private:\n" "private:\n"
" int m_it;\n" " int m_it;\n"
@@ -3646,7 +3646,7 @@ void QuickfixTest::testInsertQtPropertyMembers_data()
" }\n" " }\n"
"\n" "\n"
"signals:\n" "signals:\n"
" void itChanged(int);\n" " void itChanged(int it);\n"
"\n" "\n"
"private:\n" "private:\n"
" int m_it;\n" " int m_it;\n"
@@ -3708,7 +3708,7 @@ void QuickfixTest::testInsertQtPropertyMembers_data()
" emit itChanged(m_it);\n" " emit itChanged(m_it);\n"
" }\n" " }\n"
"signals:\n" "signals:\n"
" void itChanged(int);\n" " void itChanged(int it);\n"
"};\n" "};\n"
"\n" "\n"
"int XmarksTheSpot::getIt() const\n" "int XmarksTheSpot::getIt() const\n"

View File

@@ -4117,8 +4117,8 @@ void GetterSetterRefactoringHelper::performGeneration(ExistingGetterSetterData d
// signal declaration // signal declaration
if (generateFlags & Flag::GenerateSignal) { if (generateFlags & Flag::GenerateSignal) {
const auto &paramType = overview.prettyType(returnTypeHeader); const auto &parameter = overview.prettyType(returnTypeHeader, data.qPropertyName);
const QString newValue = m_settings->signalWithNewValue ? paramType : QString(); const QString newValue = m_settings->signalWithNewValue ? parameter : QString();
const QString declaration = QString("void %1(%2);\n").arg(data.signalName, newValue); const QString declaration = QString("void %1(%2);\n").arg(data.signalName, newValue);
addHeaderCode(InsertionPointLocator::Signals, declaration); addHeaderCode(InsertionPointLocator::Signals, declaration);
} }
@@ -4140,8 +4140,9 @@ void GetterSetterRefactoringHelper::performGeneration(ExistingGetterSetterData d
type = ref->elementType(); type = ref->elementType();
type.setConst(false); type.setConst(false);
QString propertyDeclaration = QLatin1String("Q_PROPERTY(") + overview.prettyType(type) QString propertyDeclaration = QLatin1String("Q_PROPERTY(")
+ QLatin1Char(' ') + memberBaseName(data.memberVariableName); + overview.prettyType(type,
memberBaseName(data.memberVariableName));
bool needMember = false; bool needMember = false;
if (data.getterName.isEmpty()) if (data.getterName.isEmpty())
needMember = true; needMember = true;

View File

@@ -158,26 +158,6 @@ QList<QMakeAssignment> MakeFileParse::parseAssignments(const QList<QMakeAssignme
m_qmakeBuildConfig.explicitBuildAll = false; m_qmakeBuildConfig.explicitBuildAll = false;
m_qmakeBuildConfig.explicitNoBuildAll = true; m_qmakeBuildConfig.explicitNoBuildAll = true;
} }
} else if (value == QLatin1String("x86")) {
if (qa.op == QLatin1String("+="))
m_config.archConfig = QMakeStepConfig::X86;
else
m_config.archConfig = QMakeStepConfig::NoArch;
} else if (value == QLatin1String("x86_64")) {
if (qa.op == QLatin1String("+="))
m_config.archConfig = QMakeStepConfig::X86_64;
else
m_config.archConfig = QMakeStepConfig::NoArch;
} else if (value == QLatin1String("ppc")) {
if (qa.op == QLatin1String("+="))
m_config.archConfig = QMakeStepConfig::PowerPC;
else
m_config.archConfig = QMakeStepConfig::NoArch;
} else if (value == QLatin1String("ppc64")) {
if (qa.op == QLatin1String("+="))
m_config.archConfig = QMakeStepConfig::PowerPC64;
else
m_config.archConfig = QMakeStepConfig::NoArch;
} else if (value == QLatin1String("iphonesimulator")) { } else if (value == QLatin1String("iphonesimulator")) {
if (qa.op == QLatin1String("+=")) if (qa.op == QLatin1String("+="))
m_config.osType = QMakeStepConfig::IphoneSimulator; m_config.osType = QMakeStepConfig::IphoneSimulator;
@@ -376,7 +356,6 @@ void MakeFileParse::parseCommandLine(const QString &command, const QString &proj
qCDebug(logging()) << " Explicit Release" << m_qmakeBuildConfig.explicitRelease; qCDebug(logging()) << " Explicit Release" << m_qmakeBuildConfig.explicitRelease;
qCDebug(logging()) << " Explicit BuildAll" << m_qmakeBuildConfig.explicitBuildAll; qCDebug(logging()) << " Explicit BuildAll" << m_qmakeBuildConfig.explicitBuildAll;
qCDebug(logging()) << " Explicit NoBuildAll" << m_qmakeBuildConfig.explicitNoBuildAll; qCDebug(logging()) << " Explicit NoBuildAll" << m_qmakeBuildConfig.explicitNoBuildAll;
qCDebug(logging()) << " TargetArch" << m_config.archConfig;
qCDebug(logging()) << " OsType" << m_config.osType; qCDebug(logging()) << " OsType" << m_config.osType;
qCDebug(logging()) << " LinkQmlDebuggingQQ2" qCDebug(logging()) << " LinkQmlDebuggingQQ2"
<< (m_config.linkQmlDebuggingQQ2 == TriState::Enabled); << (m_config.linkQmlDebuggingQQ2 == TriState::Enabled);
@@ -530,7 +509,6 @@ void QmakeProjectManagerPlugin::testMakefileParser()
QCOMPARE(parser.effectiveBuildConfig({}), effectiveBuildConfig); QCOMPARE(parser.effectiveBuildConfig({}), effectiveBuildConfig);
const QMakeStepConfig qmsc = parser.config(); const QMakeStepConfig qmsc = parser.config();
QCOMPARE(qmsc.archConfig, static_cast<QMakeStepConfig::TargetArchConfig>(archConfig));
QCOMPARE(qmsc.osType, static_cast<QMakeStepConfig::OsType>(osType)); QCOMPARE(qmsc.osType, static_cast<QMakeStepConfig::OsType>(osType));
QCOMPARE(qmsc.linkQmlDebuggingQQ2 == TriState::Enabled, linkQmlDebuggingQQ2); QCOMPARE(qmsc.linkQmlDebuggingQQ2 == TriState::Enabled, linkQmlDebuggingQQ2);
QCOMPARE(qmsc.useQtQuickCompiler == TriState::Enabled, useQtQuickCompiler); QCOMPARE(qmsc.useQtQuickCompiler == TriState::Enabled, useQtQuickCompiler);

View File

@@ -71,7 +71,6 @@ struct DirectoryData
BaseQtVersion::QmakeBuildConfigs buildConfig; BaseQtVersion::QmakeBuildConfigs buildConfig;
QString additionalArguments; QString additionalArguments;
QMakeStepConfig config; QMakeStepConfig config;
QMakeStepConfig::TargetArchConfig archConfig;
QMakeStepConfig::OsType osType; QMakeStepConfig::OsType osType;
}; };
@@ -154,10 +153,8 @@ QList<void *> QmakeProjectImporter::examineDirectory(const FilePath &importPath,
qCDebug(logs) << " qt version:" << version->displayName() << " temporary:" << isTemporaryVersion; qCDebug(logs) << " qt version:" << version->displayName() << " temporary:" << isTemporaryVersion;
data->archConfig = parse.config().archConfig;
data->osType = parse.config().osType; data->osType = parse.config().osType;
qCDebug(logs) << " archConfig:" << data->archConfig;
qCDebug(logs) << " osType: " << data->osType; qCDebug(logs) << " osType: " << data->osType;
if (version->type() == QLatin1String(IOSQT) if (version->type() == QLatin1String(IOSQT)
&& data->osType == QMakeStepConfig::NoOsType) { && data->osType == QMakeStepConfig::NoOsType) {
@@ -165,20 +162,6 @@ QList<void *> QmakeProjectImporter::examineDirectory(const FilePath &importPath,
qCDebug(logs) << " IOS found without osType, adjusting osType" << data->osType; qCDebug(logs) << " IOS found without osType, adjusting osType" << data->osType;
} }
if (version->type() == QtSupport::Constants::DESKTOPQT) {
const ProjectExplorer::Abis abis = version->qtAbis();
if (!abis.isEmpty()) {
ProjectExplorer::Abi abi = abis.first();
if (abi.os() == ProjectExplorer::Abi::DarwinOS) {
if (abi.wordWidth() == 64)
data->archConfig = QMakeStepConfig::X86_64;
else
data->archConfig = QMakeStepConfig::X86;
qCDebug(logs) << " OS X found without targetarch, adjusting archType" << data->archConfig;
}
}
}
// find qmake arguments and mkspec // find qmake arguments and mkspec
data->additionalArguments = parse.unparsedArguments(); data->additionalArguments = parse.unparsedArguments();
qCDebug(logs) << " Unparsed arguments:" << data->additionalArguments; qCDebug(logs) << " Unparsed arguments:" << data->additionalArguments;
@@ -210,27 +193,23 @@ bool QmakeProjectImporter::matchKit(void *directoryData, const Kit *k) const
ToolChain *tc = ToolChainKitAspect::cxxToolChain(k); ToolChain *tc = ToolChainKitAspect::cxxToolChain(k);
if (kitSpec.isEmpty() && kitVersion) if (kitSpec.isEmpty() && kitVersion)
kitSpec = kitVersion->mkspecFor(tc); kitSpec = kitVersion->mkspecFor(tc);
QMakeStepConfig::TargetArchConfig kitTargetArch = QMakeStepConfig::NoArch;
QMakeStepConfig::OsType kitOsType = QMakeStepConfig::NoOsType; QMakeStepConfig::OsType kitOsType = QMakeStepConfig::NoOsType;
if (tc) { if (tc) {
kitTargetArch = QMakeStepConfig::targetArchFor(tc->targetAbi(), kitVersion);
kitOsType = QMakeStepConfig::osTypeFor(tc->targetAbi(), kitVersion); kitOsType = QMakeStepConfig::osTypeFor(tc->targetAbi(), kitVersion);
} }
qCDebug(logs) << k->displayName() qCDebug(logs) << k->displayName()
<< "version:" << (kitVersion == data->qtVersionData.qt) << "version:" << (kitVersion == data->qtVersionData.qt)
<< "spec:" << (kitSpec == data->parsedSpec) << "spec:" << (kitSpec == data->parsedSpec)
<< "targetarch:" << (kitTargetArch == data->archConfig)
<< "ostype:" << (kitOsType == data->osType); << "ostype:" << (kitOsType == data->osType);
return kitVersion == data->qtVersionData.qt return kitVersion == data->qtVersionData.qt
&& kitSpec == data->parsedSpec && kitSpec == data->parsedSpec
&& kitTargetArch == data->archConfig
&& kitOsType == data->osType; && kitOsType == data->osType;
} }
Kit *QmakeProjectImporter::createKit(void *directoryData) const Kit *QmakeProjectImporter::createKit(void *directoryData) const
{ {
auto *data = static_cast<DirectoryData *>(directoryData); auto *data = static_cast<DirectoryData *>(directoryData);
return createTemporaryKit(data->qtVersionData, data->parsedSpec, data->archConfig, data->osType); return createTemporaryKit(data->qtVersionData, data->parsedSpec, data->osType);
} }
const QList<BuildInfo> QmakeProjectImporter::buildInfoList(void *directoryData) const const QList<BuildInfo> QmakeProjectImporter::buildInfoList(void *directoryData) const
@@ -262,17 +241,14 @@ void QmakeProjectImporter::deleteDirectoryData(void *directoryData) const
delete static_cast<DirectoryData *>(directoryData); delete static_cast<DirectoryData *>(directoryData);
} }
static const QList<ToolChain *> preferredToolChains(BaseQtVersion *qtVersion, const QString &ms, static const QList<ToolChain *> preferredToolChains(BaseQtVersion *qtVersion, const QString &ms)
const QMakeStepConfig::TargetArchConfig &archConfig)
{ {
const QString spec = ms.isEmpty() ? qtVersion->mkspec() : ms; const QString spec = ms.isEmpty() ? qtVersion->mkspec() : ms;
const QList<ToolChain *> toolchains = ToolChainManager::toolChains(); const QList<ToolChain *> toolchains = ToolChainManager::toolChains();
const Abis qtAbis = qtVersion->qtAbis(); const Abis qtAbis = qtVersion->qtAbis();
const auto matcher = [&](const ToolChain *tc) { const auto matcher = [&](const ToolChain *tc) {
return qtAbis.contains(tc->targetAbi()) return qtAbis.contains(tc->targetAbi()) && tc->suggestedMkspecList().contains(spec);
&& tc->suggestedMkspecList().contains(spec)
&& QMakeStepConfig::targetArchFor(tc->targetAbi(), qtVersion) == archConfig;
}; };
ToolChain * const cxxToolchain = findOrDefault(toolchains, [matcher](const ToolChain *tc) { ToolChain * const cxxToolchain = findOrDefault(toolchains, [matcher](const ToolChain *tc) {
return tc->language() == ProjectExplorer::Constants::CXX_LANGUAGE_ID && matcher(tc); return tc->language() == ProjectExplorer::Constants::CXX_LANGUAGE_ID && matcher(tc);
@@ -290,13 +266,11 @@ static const QList<ToolChain *> preferredToolChains(BaseQtVersion *qtVersion, co
Kit *QmakeProjectImporter::createTemporaryKit(const QtProjectImporter::QtVersionData &data, Kit *QmakeProjectImporter::createTemporaryKit(const QtProjectImporter::QtVersionData &data,
const QString &parsedSpec, const QString &parsedSpec,
const QMakeStepConfig::TargetArchConfig &archConfig,
const QMakeStepConfig::OsType &osType) const const QMakeStepConfig::OsType &osType) const
{ {
Q_UNUSED(osType) // TODO use this to select the right toolchain? Q_UNUSED(osType) // TODO use this to select the right toolchain?
return QtProjectImporter::createTemporaryKit(data, return QtProjectImporter::createTemporaryKit(data, [&data, parsedSpec](Kit *k) -> void {
[&data, parsedSpec, archConfig](Kit *k) -> void { for (ToolChain *const tc : preferredToolChains(data.qt, parsedSpec))
for (ToolChain * const tc : preferredToolChains(data.qt, parsedSpec, archConfig))
ToolChainKitAspect::setToolChain(k, tc); ToolChainKitAspect::setToolChain(k, tc);
if (parsedSpec != data.qt->mkspec()) if (parsedSpec != data.qt->mkspec())
QmakeKitAspect::setMkspec(k, parsedSpec, QmakeKitAspect::MkspecSource::Code); QmakeKitAspect::setMkspec(k, parsedSpec, QmakeKitAspect::MkspecSource::Code);

View File

@@ -50,7 +50,6 @@ private:
ProjectExplorer::Kit *createTemporaryKit(const QtProjectImporter::QtVersionData &data, ProjectExplorer::Kit *createTemporaryKit(const QtProjectImporter::QtVersionData &data,
const QString &parsedSpec, const QString &parsedSpec,
const QmakeProjectManager::QMakeStepConfig::TargetArchConfig &archConfig,
const QMakeStepConfig::OsType &osType) const; const QMakeStepConfig::OsType &osType) const;
}; };

View File

@@ -185,7 +185,6 @@ QMakeStepConfig QMakeStep::deducedArguments() const
BaseQtVersion *version = QtKitAspect::qtVersion(kit); BaseQtVersion *version = QtKitAspect::qtVersion(kit);
config.archConfig = QMakeStepConfig::targetArchFor(targetAbi, version);
config.osType = QMakeStepConfig::osTypeFor(targetAbi, version); config.osType = QMakeStepConfig::osTypeFor(targetAbi, version);
config.separateDebugInfo = qmakeBuildConfiguration()->separateDebugInfo(); config.separateDebugInfo = qmakeBuildConfiguration()->separateDebugInfo();
config.linkQmlDebuggingQQ2 = qmakeBuildConfiguration()->qmlDebugging(); config.linkQmlDebuggingQQ2 = qmakeBuildConfiguration()->qmlDebugging();
@@ -780,25 +779,9 @@ QMakeStepFactory::QMakeStepFactory()
setFlags(BuildStepInfo::UniqueStep); setFlags(BuildStepInfo::UniqueStep);
} }
QMakeStepConfig::TargetArchConfig QMakeStepConfig::targetArchFor(const Abi &targetAbi, const BaseQtVersion *version) QMakeStepConfig::TargetArchConfig QMakeStepConfig::targetArchFor(const Abi &, const BaseQtVersion *)
{ {
TargetArchConfig arch = NoArch; return NoArch;
if (!version || version->type() != QtSupport::Constants::DESKTOPQT)
return arch;
if (targetAbi.os() == Abi::DarwinOS && targetAbi.binaryFormat() == Abi::MachOFormat) {
if (targetAbi.architecture() == Abi::X86Architecture) {
if (targetAbi.wordWidth() == 32)
arch = X86;
else if (targetAbi.wordWidth() == 64)
arch = X86_64;
} else if (targetAbi.architecture() == Abi::PowerPCArchitecture) {
if (targetAbi.wordWidth() == 32)
arch = PowerPC;
else if (targetAbi.wordWidth() == 64)
arch = PowerPC64;
}
}
return arch;
} }
QMakeStepConfig::OsType QMakeStepConfig::osTypeFor(const Abi &targetAbi, const BaseQtVersion *version) QMakeStepConfig::OsType QMakeStepConfig::osTypeFor(const Abi &targetAbi, const BaseQtVersion *version)

View File

@@ -66,15 +66,14 @@ public:
class QMAKEPROJECTMANAGER_EXPORT QMakeStepConfig class QMAKEPROJECTMANAGER_EXPORT QMakeStepConfig
{ {
public: public:
enum TargetArchConfig { // TODO remove, does nothing
NoArch, X86, X86_64, PowerPC, PowerPC64 enum TargetArchConfig { NoArch, X86, X86_64, PowerPC, PowerPC64 };
};
enum OsType { enum OsType { NoOsType, IphoneSimulator, IphoneOS };
NoOsType, IphoneSimulator, IphoneOS
};
static TargetArchConfig targetArchFor(const ProjectExplorer::Abi &targetAbi, const QtSupport::BaseQtVersion *version); // TODO remove, does nothing
static TargetArchConfig targetArchFor(const ProjectExplorer::Abi &targetAbi,
const QtSupport::BaseQtVersion *version);
static OsType osTypeFor(const ProjectExplorer::Abi &targetAbi, const QtSupport::BaseQtVersion *version); static OsType osTypeFor(const ProjectExplorer::Abi &targetAbi, const QtSupport::BaseQtVersion *version);
QStringList toArguments() const; QStringList toArguments() const;
@@ -82,6 +81,7 @@ public:
// Actual data // Actual data
QString sysRoot; QString sysRoot;
QString targetTriple; QString targetTriple;
// TODO remove, does nothing
TargetArchConfig archConfig = NoArch; TargetArchConfig archConfig = NoArch;
OsType osType = NoOsType; OsType osType = NoOsType;
Utils::TriState separateDebugInfo; Utils::TriState separateDebugInfo;

View File

@@ -35,6 +35,7 @@
#include "nodemetainfo.h" #include "nodemetainfo.h"
#include "qmlitemnode.h" #include "qmlitemnode.h"
#include "bindingproperty.h"
#include <qmldesignerplugin.h> #include <qmldesignerplugin.h>
#include <abstractaction.h> #include <abstractaction.h>
#include <designeractionmanager.h> #include <designeractionmanager.h>
@@ -162,13 +163,16 @@ void ColorTool::itemsAboutToRemoved(const QList<FormEditorItem*> &removedItemLis
void ColorTool::selectedItemsChanged(const QList<FormEditorItem*> &itemList) void ColorTool::selectedItemsChanged(const QList<FormEditorItem*> &itemList)
{ {
if (m_colorDialog.data() if (m_colorDialog.data() && m_oldColor.isValid())
&& m_oldColor.isValid())
m_formEditorItem->qmlItemNode().setVariantProperty("color", m_oldColor); m_formEditorItem->qmlItemNode().setVariantProperty("color", m_oldColor);
if (!itemList.isEmpty() if (!itemList.isEmpty()
&& itemList.constFirst()->qmlItemNode().modelNode().metaInfo().hasProperty("color")) { && itemList.constFirst()->qmlItemNode().modelNode().metaInfo().hasProperty("color")) {
m_formEditorItem = itemList.constFirst(); m_formEditorItem = itemList.constFirst();
if (m_formEditorItem->qmlItemNode().hasBindingProperty("color"))
m_oldExpression = m_formEditorItem->qmlItemNode().modelNode().bindingProperty("color").expression();
else
m_oldColor = m_formEditorItem->qmlItemNode().modelValue("color").value<QColor>(); m_oldColor = m_formEditorItem->qmlItemNode().modelValue("color").value<QColor>();
if (m_colorDialog.isNull()) { if (m_colorDialog.isNull()) {
@@ -217,27 +221,31 @@ QString ColorTool::name() const
void ColorTool::colorDialogAccepted() void ColorTool::colorDialogAccepted()
{ {
m_oldExpression.clear();
view()->changeToSelectionTool(); view()->changeToSelectionTool();
} }
void ColorTool::colorDialogRejected() void ColorTool::colorDialogRejected()
{ {
if (m_formEditorItem) { if (m_formEditorItem) {
if (!m_oldExpression.isEmpty())
m_formEditorItem->qmlItemNode().setBindingProperty("color", m_oldExpression);
else {
if (m_oldColor.isValid()) if (m_oldColor.isValid())
m_formEditorItem->qmlItemNode().setVariantProperty("color", m_oldColor); m_formEditorItem->qmlItemNode().setVariantProperty("color", m_oldColor);
else else
m_formEditorItem->qmlItemNode().removeProperty("color"); m_formEditorItem->qmlItemNode().removeProperty("color");
}
} }
m_oldExpression.clear();
view()->changeToSelectionTool(); view()->changeToSelectionTool();
} }
void ColorTool::currentColorChanged(const QColor &color) void ColorTool::currentColorChanged(const QColor &color)
{ {
if (m_formEditorItem) { if (m_formEditorItem)
m_formEditorItem->qmlItemNode().setVariantProperty("color", color); m_formEditorItem->qmlItemNode().setVariantProperty("color", color);
} }
}
} }

View File

@@ -84,6 +84,7 @@ private:
QPointer<QColorDialog> m_colorDialog; QPointer<QColorDialog> m_colorDialog;
FormEditorItem *m_formEditorItem = nullptr; FormEditorItem *m_formEditorItem = nullptr;
QColor m_oldColor; QColor m_oldColor;
QString m_oldExpression;
}; };
} }

View File

@@ -161,6 +161,8 @@ ItemLibraryWidget::ItemLibraryWidget(AsynchronousImageCache &imageCache,
{ {
m_compressionTimer.setInterval(200); m_compressionTimer.setInterval(200);
m_compressionTimer.setSingleShot(true); m_compressionTimer.setSingleShot(true);
m_assetCompressionTimer.setInterval(200);
m_assetCompressionTimer.setSingleShot(true);
ItemLibraryModel::registerQmlTypes(); ItemLibraryModel::registerQmlTypes();
setWindowTitle(tr("Library", "Title of library view")); setWindowTitle(tr("Library", "Title of library view"));
@@ -234,17 +236,7 @@ ItemLibraryWidget::ItemLibraryWidget(AsynchronousImageCache &imageCache,
// reconstruct the model to update the icons // reconstruct the model to update the icons
connect(m_fileSystemWatcher, &Utils::FileSystemWatcher::directoryChanged, [this](const QString & changedDirPath) { connect(m_fileSystemWatcher, &Utils::FileSystemWatcher::directoryChanged, [this](const QString & changedDirPath) {
Q_UNUSED(changedDirPath) Q_UNUSED(changedDirPath)
// TODO: find a clever way to only refresh the changed directory part of the model m_assetCompressionTimer.start();
m_assetsModel->refresh();
if (!QApplication::activeModalWidget()) {
// reload assets qml so that an overridden file's image shows the new image
QTimer::singleShot(100, this, [this] {
const QString assetsQmlPath = qmlSourcesPath() + "/Assets.qml";
m_assetsWidget->engine()->clearComponentCache();
m_assetsWidget->setSource(QUrl::fromLocalFile(assetsQmlPath));
});
}
}); });
m_stackedWidget = new QStackedWidget(this); m_stackedWidget = new QStackedWidget(this);
@@ -270,6 +262,26 @@ ItemLibraryWidget::ItemLibraryWidget(AsynchronousImageCache &imageCache,
connect(m_qmlSourceUpdateShortcut, &QShortcut::activated, this, &ItemLibraryWidget::reloadQmlSource); connect(m_qmlSourceUpdateShortcut, &QShortcut::activated, this, &ItemLibraryWidget::reloadQmlSource);
connect(&m_compressionTimer, &QTimer::timeout, this, &ItemLibraryWidget::updateModel); connect(&m_compressionTimer, &QTimer::timeout, this, &ItemLibraryWidget::updateModel);
connect(&m_assetCompressionTimer, &QTimer::timeout, this, [this]() {
// TODO: find a clever way to only refresh the changed directory part of the model
// Don't bother with asset updates after model has detached, project is probably closing
if (!m_model.isNull()) {
if (QApplication::activeModalWidget()) {
// Retry later, as updating file system watchers can crash when there is an active
// modal widget
m_assetCompressionTimer.start();
} else {
m_assetsModel->refresh();
// reload assets qml so that an overridden file's image shows the new image
QTimer::singleShot(100, this, [this] {
const QString assetsQmlPath = qmlSourcesPath() + "/Assets.qml";
m_assetsWidget->engine()->clearComponentCache();
m_assetsWidget->setSource(QUrl::fromLocalFile(assetsQmlPath));
});
}
}
});
m_itemViewQuickWidget->engine()->addImageProvider("itemlibrary_preview", m_itemViewQuickWidget->engine()->addImageProvider("itemlibrary_preview",
new ItemLibraryIconImageProvider{m_imageCache}); new ItemLibraryIconImageProvider{m_imageCache});

View File

@@ -119,6 +119,7 @@ private:
void handlePriorityImportsChanged(); void handlePriorityImportsChanged();
QTimer m_compressionTimer; QTimer m_compressionTimer;
QTimer m_assetCompressionTimer;
QSize m_itemIconSize; QSize m_itemIconSize;
SynchronousImageCache &m_fontImageCache; SynchronousImageCache &m_fontImageCache;

View File

@@ -155,15 +155,17 @@ void PropertyEditorValue::setValueWithEmit(const QVariant &value)
void PropertyEditorValue::setValue(const QVariant &value) void PropertyEditorValue::setValue(const QVariant &value)
{ {
const bool colorsEqual = cleverColorCompare(value, m_value);
if (!compareVariants(m_value, value) && if (!compareVariants(m_value, value) &&
!cleverDoubleCompare(value, m_value) && !cleverDoubleCompare(value, m_value) &&
!cleverColorCompare(value, m_value)) !colorsEqual)
m_value = value; m_value = value;
fixAmbigousColorNames(modelNode(), name(), &m_value); fixAmbigousColorNames(modelNode(), name(), &m_value);
fixUrl(modelNode(), name(), &m_value); fixUrl(modelNode(), name(), &m_value);
if (m_value.isValid()) if (m_value.isValid() && !colorsEqual)
emit valueChangedQml(); emit valueChangedQml();
emit isExplicitChanged(); emit isExplicitChanged();

View File

@@ -45,6 +45,8 @@
#include <qmldesignerplugin.h> #include <qmldesignerplugin.h>
#endif #endif
#include <utils/qtcassert.h>
#include <QRegularExpression> #include <QRegularExpression>
namespace QmlDesigner { namespace QmlDesigner {
@@ -356,6 +358,16 @@ static void removeAliasExports(const QmlObjectNode &node)
} }
static void removeLayerEnabled(const ModelNode &node)
{
QTC_ASSERT(node.isValid(), return );
if (node.parentProperty().isValid() && node.parentProperty().name() == "layer.effect") {
ModelNode parent = node.parentProperty().parentModelNode();
if (parent.isValid() && parent.hasProperty("layer.enabled"))
parent.removeProperty("layer.enabled");
}
}
/*! /*!
Deletes this object's node and its dependencies from the model. Deletes this object's node and its dependencies from the model.
Everything that belongs to this Object, the ModelNode, and ChangeOperations Everything that belongs to this Object, the ModelNode, and ChangeOperations
@@ -366,6 +378,7 @@ void QmlObjectNode::destroy()
if (!isValid()) if (!isValid())
throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__); throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
removeLayerEnabled(modelNode());
removeAliasExports(modelNode()); removeAliasExports(modelNode());
for (QmlModelStateOperation stateOperation : allAffectingStatesOperations()) { for (QmlModelStateOperation stateOperation : allAffectingStatesOperations()) {

View File

@@ -1099,7 +1099,6 @@ bool TextToModelMerger::load(const QString &data, DifferenceHandler &differenceH
m_rewriterView->setWarnings(warnings); m_rewriterView->setWarnings(warnings);
qCInfo(rewriterBenchmark) << "checked semantic errors:" << time.elapsed(); qCInfo(rewriterBenchmark) << "checked semantic errors:" << time.elapsed();
} }
setupUsedImports();
AST::UiObjectMember *astRootNode = nullptr; AST::UiObjectMember *astRootNode = nullptr;
if (AST::UiProgram *program = m_document->qmlProgram()) if (AST::UiProgram *program = m_document->qmlProgram())
@@ -1111,6 +1110,8 @@ bool TextToModelMerger::load(const QString &data, DifferenceHandler &differenceH
qCInfo(rewriterBenchmark) << "synced nodes:" << time.elapsed(); qCInfo(rewriterBenchmark) << "synced nodes:" << time.elapsed();
setupUsedImports();
setActive(false); setActive(false);
return true; return true;

View File

@@ -154,7 +154,7 @@ void ShortCutManager::registerActions(const Core::Context &qmlDesignerMainContex
m_deleteAction.setIcon(QIcon::fromTheme(QLatin1String("edit-cut"), Utils::Icons::EDIT_CLEAR_TOOLBAR.icon())); m_deleteAction.setIcon(QIcon::fromTheme(QLatin1String("edit-cut"), Utils::Icons::EDIT_CLEAR_TOOLBAR.icon()));
command = Core::ActionManager::registerAction(&m_deleteAction, QmlDesigner::Constants::C_DELETE, qmlDesignerMainContext); command = Core::ActionManager::registerAction(&m_deleteAction, QmlDesigner::Constants::C_DELETE, qmlDesignerMainContext);
command->setDefaultKeySequences({QKeySequence::Delete, QKeySequence::Backspace}); command->setDefaultKeySequences({Qt::Key_Backspace, Qt::Key_Delete});
command->setAttribute(Core::Command::CA_Hide); // don't show delete in other modes command->setAttribute(Core::Command::CA_Hide); // don't show delete in other modes
if (!Utils::HostOsInfo::isMacHost()) if (!Utils::HostOsInfo::isMacHost())

View File

@@ -73,6 +73,7 @@ public:
if (!m_idName.isEmpty()) { if (!m_idName.isEmpty()) {
m_componentName = m_idName; m_componentName = m_idName;
m_componentName[0] = m_componentName.at(0).toUpper(); m_componentName[0] = m_componentName.at(0).toUpper();
m_componentName.prepend("My");
} }
setDescription(QCoreApplication::translate("QmlJSEditor::ComponentFromObjectDef", setDescription(QCoreApplication::translate("QmlJSEditor::ComponentFromObjectDef",

View File

@@ -34,6 +34,7 @@
#include <coreplugin/documentmanager.h> #include <coreplugin/documentmanager.h>
#include <coreplugin/editormanager/documentmodel.h> #include <coreplugin/editormanager/documentmodel.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h> #include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/icontext.h> #include <coreplugin/icontext.h>
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
@@ -144,6 +145,18 @@ QmlProject::QmlProject(const Utils::FilePath &fileName)
QTimer::singleShot(0, this, lambda); QTimer::singleShot(0, this, lambda);
} }
} else {
connect(this, &QmlProject::anyParsingFinished, this, [this](Target *target, bool success) {
if (target && success) {
const Utils::FilePath &folder = projectDirectory();
const Utils::FilePaths &uiFiles = files([&](const ProjectExplorer::Node *node) {
return node->filePath().completeSuffix() == "ui.qml"
&& node->filePath().parentDir() == folder;
});
if (!uiFiles.isEmpty())
Core::EditorManager::openEditor(uiFiles.first(), Utils::Id());
}
});
} }
} }

Some files were not shown because too many files have changed in this diff Show More