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{3D Views}
\li \l{Group}
\li \l{Instanced Rendering}
\li \l{Skeletal Animation}
\li \l{3D Models}
\li \l{Materials and Shaders}

View File

@@ -49,20 +49,19 @@
\list 1
\li Select \uicontrol File > \uicontrol {New File or Project} >
\if defined(qtcreator)
\uicontrol Qt > \uicontrol {QML File (Qt Quick 2)} >
\uicontrol Qt > \uicontrol {Qt Quick UI File} >
\else
\uicontrol {Qt Quick Files} > \uicontrol {Qt Quick File} >
\uicontrol {Qt Quick Files} > \uicontrol {Qt Quick UI File} >
\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 >
\uicontrol Components > \uicontrol {My Components} only
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}.
\li Drag-and-drop a component from \uicontrol Library to
\uicontrol Navigator or \uicontrol {Form Editor}.
\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
\l{Specifying Dynamic Properties}{add properties for
components} in \uicontrol {Connection View} > \uicontrol Properties.

View File

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

View File

@@ -94,6 +94,9 @@
\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
To immediately change a property value during an animation

View File

@@ -42,12 +42,12 @@
\li Select \uicontrol File > \uicontrol {New File or Project} >
\if defined(qtcreator)
\uicontrol Qt > \uicontrol {QML File (Qt Quick 2)} >
\uicontrol Qt > \uicontrol {Qt Quick UI File} >
\else
\uicontrol {Qt Quick Files} > \uicontrol {Qt Quick File} >
\uicontrol {Qt Quick Files} > \uicontrol {Qt Quick UI File} >
\endif
\uicontrol Choose to create a QML 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 >
\uicontrol {My Components} only if the filename begins with a
@@ -160,11 +160,12 @@
To create a button component, select \uicontrol File >
\uicontrol {New File or Project} >
\if defined(qtcreator)
\uicontrol Qt > \uicontrol {QML File (Qt Quick 2)} >
\uicontrol Qt > \uicontrol {Qt Quick UI File} >
\else
\uicontrol {Qt Quick Files} > \uicontrol {Qt Quick File} >
\uicontrol {Qt Quick Files} > \uicontrol {Qt Quick UI File} >
\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 >
\uicontrol {My Components} only if the filename begins with a
@@ -175,8 +176,7 @@
To construct the button component:
\list 1
\li Click \uicontrol {Design} to edit the component file in
\l {Form Editor}.
\li Click \uicontrol {Design} to edit the UI file in \l {Form Editor}.
\li Select \l Library > \uicontrol Assets > \inlineimage plus.png
to copy the image files you want to use to the project folder.
\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.
You can set the \l{Managing 2D Transformations}{origin} in \l Properties >
\uicontrol Advanced > \uicontrol Origin. There, you can also enter the value
of the \uicontrol Rotation property in degrees.
\uicontrol {Geometry - 2D} > \uicontrol Origin. There, you can also enter
the value of the \uicontrol Rotation property in degrees.
\section1 Zooming

View File

@@ -55,8 +55,10 @@
from the Qt UI Quick project to the application project.
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
file.
automatically add all the QML files and related assets to a
\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
file for specifying the required
@@ -132,6 +134,21 @@
\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
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{3D Views}
\li \l{Group}
\li \l{Instanced Rendering}
\li \l{Skeletal Animation}
\li \l{3D Models}
\li \l{Materials and Shaders}

View File

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

View File

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

View File

@@ -38,10 +38,10 @@
sliders. The progress of the brewing process is displayed as
an animation. When the coffee is ready, the startup screen appears again.
The \e {ApplicationFlow.ui.qml} file contains all the screens in the
UI. We use states to display the appropriate screen in the
viewport and the timeline to animate the transitions between and on
the screens.
The \e {ApplicationFlowForm.ui.qml} file contains all the screens in the
UI. We use \l{glossary-state}{states} to display the appropriate screen in
the viewport and the timeline to animate the \l{glossary-transition}
{transitions} between and on the screens.
\section1 Application Flow
@@ -55,10 +55,10 @@
\printuntil }
\dots
Selecting the coffee type triggers the respective signal handler in
\e {SideBar.qml}, which sets the default mix for the selected coffee type.
The following code snippet displays the \c {cappuccinoButton.onClicked()}
signal handler:
Selecting the coffee type triggers the respective \l{glossary-signal}
{signal handler} in \e {SideBar.qml}, which sets the default mix for
the selected coffee type. The following code snippet displays the
\c {cappuccinoButton.onClicked()} signal handler:
\quotefromfile CoffeeMachine/SideBar.qml
\skipto cappuccinoButton.onClicked
@@ -113,11 +113,11 @@
\section1 Using Timelines to Animate Transitions
The Coffee Machine application screens for choosing coffee, empty cup, and
brewing each use custom components specified in separate component files
(.qml).
brewing each use custom components specified in separate \l{UI Files}
{UI files} (ui.qml).
We use the \uicontrol Timeline view to animate the transitions between
the screens during the application flow in \e {ApplicationFlow.ui.qml}.
We use the \l Timeline view to animate the transitions between the screens
during the application flow in \e {ApplicationFlowForm.ui.qml}.
\image coffee-machine-timeline.png
@@ -132,9 +132,9 @@
select the \inlineimage recordfill.png
(\uicontrol {Auto Key (K)}) button (or press \key k).
At frame 0, we set the X coordinate to 0 in \l Properties > \uicontrol
Geometry > \uicontrol Position. We then move the playhead to 400 frames and
set the X coordinate to a negative value.
At frame 0, we set the X coordinate to 0 in \l Properties >
\uicontrol {Geometry - 2D} > \uicontrol Position. We then move the
playhead to 400 frames and set the X coordinate to a negative value.
\image coffee-machine-properties.png
@@ -146,13 +146,13 @@
\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.
\image coffee-machine-states.png
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.
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 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
bind the states that don't have animations to fixed frames.
*/

View File

@@ -34,9 +34,9 @@
\image ebikedesign.png "Standard screen"
\e {E-Bike Design} is a control center application for electric bikes.
The application contains a Standard screen that displays a speedometer,
a Trip screen that displays statistics about the current trip, and a
Navigator screen that displays a map.
The application contains a \e Standard screen that displays a speedometer,
a \e Trip screen that displays statistics about the current trip, and a
\e Navigator screen that displays a map.
The Trip and Navigator screens display a small animated speedometer that
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
following order from left to right: Trip, Standard, Navigator. We will
use states to show the appropriate screen in the viewport, and the timeline
to animate the transitions between and on the screens.
use \l{glossary-state}{states} to show the appropriate screen in the
viewport, and the timeline to animate the \l{glossary-transition}
{transitions} between and on the screens.
\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}.
Our viewport contains 1000 frames, so we select the
@@ -67,7 +68,7 @@
\image ebikedesign-timeline.png "Timeline view"
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
-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
@@ -84,8 +85,8 @@
\image ebikedesign-trip-properties.png "Properties view of the Trip component"
We set values for the \uicontrol Visibility,
\uicontrol Opacity, \uicontrol currentFrame, and \uicontrol Scale properties
We set values for the \uicontrol Scale, \uicontrol Visibility,
\uicontrol Opacity, and \uicontrol currentFrame properties
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.
@@ -94,7 +95,7 @@
\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
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}.
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
create the progress bar. For another example of a progress bar, see the
\l {progress-bar-control}{Progress Bar} component in Qt Quick Controls.
In this example, we use two overlapping instances of the preset
\l{basic-rectangle}{Rectangle} component and an instance of the preset
\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
\l Library > \uicontrol Components > \uicontrol {Default Components} >
\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.
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"
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.
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
@@ -87,8 +89,8 @@
\section2 Adding Color Animation
First, we add a color animation to the \e root component. We select the
\inlineimage plus.png
First, we add a color animation to the \e root component in the \e Root.qml
file. We select the \inlineimage plus.png
button to add a 100-frame timeline to root. You can use the default
values for all other fields.
@@ -103,8 +105,9 @@
We then set the color at frame 0 to green (\e {#8de98d}) in
\uicontrol Properties > \uicontrol Text > \uicontrol {Text Color}.
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
(\uicontrol Settings) menu to open the \uicontrol {Binding Editor}.
or use the \uicontrol {Set Binding} command in the
\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
(\e {#de4f4f}). Finally, we move the playhead to frame 100 and set
@@ -117,10 +120,11 @@
\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
width to 0 in \uicontrol Properties > \uicontrol Geometry > \uicontrol Size.
We then move the playhead to 100 frames and set the width to 590.
width to 0 in \uicontrol Properties > \uicontrol {Geometry - 2D} >
\uicontrol Size. We then move the playhead to 100 frames and set the width
to 590.
\image progressbar-timeline-indicator.png "Indicator timeline"
@@ -160,9 +164,9 @@
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,
so we will export it as a property alias. We select \e timeline in
\uicontrol Navigator and then \uicontrol Properties > \uicontrol Timeline >
\uicontrol {Current frame} > \uicontrol Settings >
so we will export it as a \l{Adding Property Aliases}{property alias}. We
select \e timeline in \uicontrol Navigator and then \uicontrol Properties >
\uicontrol Timeline > \uicontrol {Current frame} > \uicontrol Actions >
\uicontrol {Export Property as Alias}.
\image progressbar-root-export-property.png "Export keyframe group as a property"

View File

@@ -29,7 +29,7 @@
\title Side 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"
@@ -41,6 +41,9 @@
\l {2D Effects}{graphical effects}, such as hue, saturation,
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
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
\l {Form Editor}. The CustomButton component is listed in
\l Library > \uicontrol Components > \uicontrol {My Components}.
We drag-and-drop several instances of the component to the
\uicontrol {Form Editor} and enclose them in a RowLayout component instance
to lay them out as a menu bar.
We drag-and-drop several instances of the component to \uicontrol Navigator
or \uicontrol {Form Editor} and enclose them in a \uicontrol {Row Layout}
component instance to lay them out as a menu bar.
\image sidemenu-menubar.png
@@ -123,20 +126,23 @@
\section1 Creating a Side Menu
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
\l Text and \l {slider-control}{Slider} components to create separate
click the burger menu. We drag-and-drop a \l Text component from
\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
a background image for the menu background and a BurgerMenu custom
component for the burger menu icon.
\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
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
animation. When the animation finishes, the side menu state changes to
\e open and the side menu is fully visible.
\l{glossary-signal}{signal handler} triggers the \l{glossary-transition}
{transition} to the \e opening state and runs an animation. When the
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
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).
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.
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
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
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.
frame 400 and select \uicontrol {Insert Keyframe} in the
\inlineimage icons/action-icon.png
(\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"
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
\l {2D Effects}{graphical effects}. To have access to the
properties from all the slider component instances, we export them as
in \e SliderMenu.ui.qml. We select \uicontrol {Export Property as Alias}
aliases in \e SliderMenu.ui.qml. We select \uicontrol {Export Property as Alias}
in the \uicontrol Settings menu of the \uicontrol Value property in
\uicontrol Properties > \uicontrol Slider.
We use the \uicontrol {Form Editor} to create the effect stack in the
\e {EffectStack.qml} file:
We open the \e {EffectStack.qml} file, and drag-and-drop components from
\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"
We use the \l {Images}{Image} component as the last item in the stack to
display images that we apply the effects to. We export the image source
property as an \l{Adding Property Aliases}{alias} to be able to switch
the image inside the stack.
We use an instance of the \l {Images}{Image} component as the last item in
the stack to display images that we apply the effects to. We export the
image source property as an \l{Adding Property Aliases}{alias} to be able
to switch the image inside the stack.
For more information about the available graphical effects, see
\l {2D Effects}.

View File

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

View File

@@ -50,15 +50,15 @@
We organize our design in Photoshop using artboards as instructed in
\l{Organizing Assets}.
\QB automatically proposes identifiers for all groups and layers. The ids
\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
\uicontrol {QML 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
\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
a lower-case letter or an underscore character, and that only letters,
numbers, and underscore characters are allowed.
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
will be exported as PNG files, with references to them in the component file
that contains them.
@@ -94,23 +94,27 @@
\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.
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
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.
\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"
We want to apply the \l {FastBlur} effect to the smallPopup UI control.
In the artboard, we have a blurEffect layer that we want to export as a
FastBlurItem component. In the \uicontrol {QML Type} field, we enter
We want to apply the \l {FastBlur} effect to the \e smallPopup UI control.
In the artboard, we have a \e blurEffect layer that we want to export as a
\e FastBlurItem component. In the \uicontrol Component field, we enter
\e FastBlurItem.
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
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
the \uicontrol Radius field in the \uicontrol Properties view in \QDS.
in the \uicontrol Properties field. We can modify the property in \QDS by
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"
@@ -162,8 +169,8 @@
The \e {LayoutReference.ui.qml} file contains a reference image of
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
listed in \uicontrol Library > \uicontrol Components >
\uicontrol {My Components}, and we can drag-and-drop them to \l {Form Editor}.
listed in \l Library > \uicontrol Components > \uicontrol {My Components},
and we can drag-and-drop them to \l {Form Editor}.
\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
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.
\section2 Animating Components
We open the \e {Largepopup.ui.qml} file in the Design mode to add animation
to it. In the \uicontrol States view, we add the \e opening, \e open,
We open the \e {Largepopup.ui.qml} file in the \uicontrol Design mode to add
animation to it. In the \l States view, we add the \e opening, \e open,
\e closing, and \e closed states for the popup.
\image webinardemo-states.png "Popup states in the States view"
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.
\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
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
to enter the settings needed for that particular type of project and create
the necessary files for you.
step-by-step through the project creation process. The wizard templates
prompt you to enter the settings needed for a particular type of project
and create the necessary files for you.
\QDS projects are useful for creating UIs. You cannot use them for
application development, because they do not contain:
@@ -65,25 +65,43 @@
\image studio-project-wizards.png "A list of project wizards"
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
\li \uicontrol {Qt for MCUs Application} 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.
\li \uicontrol {Qt Quick Application - Empty} creates a project that
uses default components and preset UI controls and can be run on
all target platforms.
\li \uicontrol {Qt Quick 3D Application} creates a project that uses
default components, UI controls, and 3D components.
\li \uicontrol {Qt Quick Application - Scroll} and
\uicontrol {Qt Quick Application - Stack} create an application
that uses UI controls to implement a scrollable list or a set of
pages with a stack-based navigation model.
\li \uicontrol {Qt Quick Application - Launcher} creates a
project that uses default components and UI controls and
\table
\header
\li Category
\li Wizard Template
\li Purpose
\row
\li {1,2} General
\li Qt Quick Application - Empty
\li Creates a project that uses default components and preset UI
controls and can be run on all target platforms.
\row
\li Qt Quick 3D Application
\li Creates a project that uses default components, UI controls, and
3D components.
\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.
\endlist
\endtable
For an example of creating a \uicontrol {Qt Quick 3D Application} project,
watch the following video:
@@ -94,19 +112,31 @@
\list 1
\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.
When naming your own projects, keep in mind that they cannot be
easily renamed later.
Keep in mind that projects cannot be easily renamed later.
\image studio-project-location.png "Project Location dialog"
\li In the \uicontrol {Create in} field, enter the path for the project
files, and then select \uicontrol Next (or \uicontrol Continue on
\macos). You can move project folders later without problems.
files. 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
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.
\li In the \uicontrol {Qt Quick Controls Style} field, select one of
the predefined \l{Styling Qt Quick Controls}{UI styles} to use,
and then select \uicontrol Finish (or \uicontrol Done on \macos).
the predefined \l{Styling Qt Quick Controls}{UI styles} to use.
\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
\QDS creates the following files and folders:
@@ -144,51 +174,77 @@
\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:
\list
\li \uicontrol {Qt Quick Files}
\list
\li \uicontrol {Flow Item} and \uicontrol {Flow View}
generate components that you can use to design the
\table
\header
\li Category
\li Wizard Template
\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}.
\li \uicontrol {Qt Quick File} generates a component with one
of the following default components or \l{Using Positioners}
{positioners} as the root component: \l {basic-item}{Item},
\l {basic-rectangle}{Rectangle}, \l {Images}{Image},
\l {Border Image}, \l Flickable, Row, Column, Flow, or Grid.
\li \uicontrol {Qt Quick UI File} generates a component file
with one of the above components as the root component.
\li \uicontrol {Qt Quick Views} generates a Grid View or a
List View. For more information, see \l{List and Grid Views}.
\endlist
\li \uicontrol {Qt Quick Controls} create stylable versions of the
components in the Qt Quick Controls module:
\list
\li \l {Button}{Custom Button} creates a push button with a text
label.
\li \l {Check Box}{Custom CheckBox} creates a check box.
\li \l {Slider and Dial}{Custom Dial} creates a dial.
\li \l {Slider and Dial}{Custom Slider} creates a slider.
\li \l {Spin Box}{Custom SpinBox} creates a spin box.
\li \l {Switch}{Custom Switch} creates a switch with on and off
states.
\li \l [Qt Quick Controls 2] {Pane} provides a background that
matches the UI style and theme.
\li \l [Qt Quick Controls 2] {StackView} provides a stack-based
navigation model.
\li \l [Qt Quick Controls 2] {SwipeView} enables users to
navigate pages by swiping sideways.
\endlist
For more information, see \l{Creating Custom Controls}.
\li \uicontrol ListModel adds a \l{Editing List Models}{list model} to
the project.
\li \uicontrol {JavaScript File} 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}.
\endlist
\row
\li Qt Quick File
\li Generates a component with one of the following default components
or \l{Using Positioners}{positioners} as the root component:
\l {basic-item}{Item}, \l {basic-rectangle}{Rectangle}, \l {Images}
{Image}, \l {Border Image}, \l Flickable, Row, Column, Flow, or
Grid.
\row
\li Qt Quick UI File
\li Generates a UI file with one of the above components as the root
component.
\row
\li Qt Quick Views
\li Generates a Grid View or a List View. For more information, see
\l{List and Grid Views}.
\row
\li {1,9} Qt Quick Controls
\li Custom Button
\li Creates a \l {Button}{push button} with a text label.
\row
\li Custom \CheckBox
\li Creates a \l {Check Box}{check box}.
\row
\li Custom Dial
\li Creates a \l {Slider and Dial}{dial}.
\row
\li Custom Slider
\li Creates a \l {Slider and Dial}{slider}.
\row
\li Custom \SpinBox
\li Creates a \l {Spin Box}{spin box}.
\row
\li Custom Switch
\li Creates a \l {Switch}{switch} with on and off states.
\row
\li \l Pane
\li Provides a background that matches the UI style and theme.
\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{3D Views}
\li \l{Group}
\li \l{Instanced Rendering}
\li \l{Skeletal Animation}
\li \l{3D Models}
\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.
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
instance's coordinate system.

View File

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

View File

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

View File

@@ -36,6 +36,10 @@
\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
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,
@@ -55,6 +59,11 @@
\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
in order to improve the rendering performance. Every time the source or
effect properties are changed, the pixels in the cache must be updated.
@@ -78,7 +87,8 @@
\section1 Summary of 2D Effects
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.
@@ -86,10 +96,12 @@
\header
\li Icon
\li Effect
\li Qt 6
\li Description
\row
\li \inlineimage icons/blend-mode-16px.png
\li \l [QML] {Blend}
\li
\li Merges two source components by using a blend mode.
The default \uicontrol Mode is \c subtract, where the pixel value
@@ -102,21 +114,25 @@
\row
\li \inlineimage icons/brightness-contrast-16px.png
\li \l {BrightnessContrast}{Brightness Contrast}
\li \inlineimage ok.png
\li Adjusts \uicontrol Brightness and \uicontrol Contrast.
\row
\li \inlineimage icons/colourize-16px.png
\li \l {ColorOverlay}{Color Overlay}
\li \inlineimage ok.png
\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}.
\row
\li \inlineimage icons/colourize-16px.png
\li \l Colorize
\li \inlineimage ok.png
\li Sets the color in the HSL color space by specifying \uicontrol Hue,
\uicontrol Lightness, and \uicontrol Saturation values.
\row
\li \inlineimage icons/desaturation-16px.png
\li \l {Desaturate}{Desaturation}
\li \inlineimage ok.png
\li Reduces the saturation of the colors by the value set in the
\uicontrol Desaturation field. The value ranges from \c 0.0
(no change) to \c 1.0 (desaturated). Desaturated pixel values are
@@ -125,8 +141,9 @@
\row
\li \inlineimage icons/directional-blur-16px.png
\li \l {DirectionalBlur}{Directional Blur}
\li \inlineimage ok.png
\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
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.
@@ -141,6 +158,7 @@
\row
\li \inlineimage icons/displace-16px.png
\li \l Displace
\li \inlineimage ok.png
\li Moves the pixels of the source component according to the displacement
map specified in the \uicontrol {Displacement source} field.
@@ -153,13 +171,14 @@
\row
\li \inlineimage icons/drop-shadow-16px.png
\li \l {DropShadow}{Drop Shadow}
\li \inlineimage ok.png
\li Generates a soft shadow behind the source component using a
gaussian blur. This effect blurs the alpha channel of the input and
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
\uicontrol {Drop Shadow Color} field and change its location in the
\uicontrol {Horizontal offset} and \uicontrol {Vertical offset}
fields.
\uicontrol {Drop shadow color} field and change its location in the
horizontal (\uicontrol H) and vertical (\uicontrol V)
\uicontrol Offset fields.
The value of the \uicontrol Radius field specifies the softness of
the shadow. A larger radius causes the edges of the shadow to appear
@@ -174,6 +193,7 @@
\row
\li \inlineimage icons/fast-blur-16px.png
\li \l {FastBlur}{Fast Blur}
\li \inlineimage ok.png
\li Applies a fast blur effect to one or more source components.
\uicontrol {Fast Blur} offers lower blur quality than
\uicontrol {Gaussian Blur}, but it is faster to render.
@@ -191,6 +211,7 @@
\row
\li \inlineimage icons/gamma-adjust-16px.png
\li \l [QML] {GammaAdjust}{Gamma Adjust}
\li \inlineimage ok.png
\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
power-law expression, where the value of the \uicontrol Gamma
@@ -198,6 +219,7 @@
\row
\li \inlineimage icons/gaussian-blur-16px.png
\li \l [QML] {GaussianBlur}{Gaussian Blur}
\li
\li Applies a gaussian blur effect to one or more source components.
The effect softens the image by blurring it with an algorithm that
uses the gaussian function to calculate the effect. The effect
@@ -219,6 +241,7 @@
\row
\li \inlineimage icons/glow-16px.png
\li \l [QML] {Glow}
\li \inlineimage ok.png
\li Generates a halo-like glow around the source component. This effect
blurs the alpha channel of the source and colorizes it with
\uicontrol {Glow color}. It then places the alpha channel behind the
@@ -229,6 +252,7 @@
\row
\li \inlineimage icons/hue-saturation-16px.png
\li \l {HueSaturation}{Hue Saturation}
\li \inlineimage ok.png
\li Alters the source component colors in the HSL color space.
This effect is similar to the \uicontrol Colorize effect, but
the \uicontrol Hue and \uicontrol Saturation values are handled
@@ -238,8 +262,9 @@
\row
\li \inlineimage icons/inner-shadow-16px.png
\li \l {InnerShadow}{Inner Shadow}
\li
\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.
The quality of the shadow can be controlled by the values of the
@@ -259,6 +284,7 @@
\row
\li \inlineimage icons/levels-16px.png
\li \l {LevelAdjust}{Level Adjust}
\li \inlineimage ok.png
\li Adjusts color levels in the RGBA color space. This effect adjusts
the source component colors separately for each color channel. Source
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
(lightest).
You can specify the maximum and minimum input and output levels for
each color channel. \uicontrol {Maximum input} sets the white-point,
which means that all pixels with a higher value are rendered as
white (per color channel). Decreasing this value lightens the light
areas. To darken the light areas and to increase the contrast,
decrease the value of the \uicontrol {Maximum output} field.
You can specify the maximum and minimum \uicontrol Input and
\uicontrol Output levels for each color channel. \uicontrol Maximum
input sets the white-point, which means that all pixels with a
higher value are rendered as white (per color channel). Decreasing
this value lightens the light areas. To darken the light areas and
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
means that all pixels with a lower value are rendered as black
(per color channel). Increasing this value darkens the dark areas.
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
\li \inlineimage icons/mask-blur-16px.png
\li \l {MaskedBlur}{Masked Blur}
\li
\li Softens the image by blurring it. The intensity of the blur can be
controlled for each pixel by specifying a \uicontrol {Mask source},
so that some parts of the source are blurred more than others.
@@ -301,6 +329,7 @@
\row
\li \inlineimage icons/opacity-mask-16px.png
\li \l {OpacityMask}{Opacity Mask}
\li \inlineimage ok.png
\li Masks the source component with another component specified in the
\uicontrol {Mask source} field. The mask component gets rendered into an
intermediate pixel buffer and the alpha values from the result are
@@ -315,6 +344,7 @@
\row
\li \inlineimage icons/radial-blur-16px.png
\li \l {RadialBlur}{Radial Blur}
\li
\li Applies a directional blur effect in a circular direction around the
component's center point. This effect makes the source component appear
to be rotating into the direction of the blur. Other available
@@ -329,6 +359,7 @@
\row
\li \inlineimage icons/recursive-blur-16px.png
\li \l {RecursiveBlur}{Recursive Blur}
\li
\li Blurs repeatedly, providing a strong blur effect. This effect
softens the image by blurring it with an algorithm that uses a
recursive feedback loop to blur the source as many times as
@@ -344,6 +375,7 @@
\row
\li \inlineimage icons/threshold-16px.png
\li \l {ThresholdMask}{Threshold Mask}
\li \inlineimage ok.png
\li Masks the source component with another component specified by
\uicontrol {Mask source}. The value of the \uicontrol Spread
field determines the smoothness of the mask edges near the
@@ -354,6 +386,7 @@
\row
\li \inlineimage icons/zoom-blur-16px.png
\li \l {ZoomBlur}{Zoom Blur}
\li
\li Applies a directional blur effect towards source component's
center point. This effect makes the source component appear to be
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
perceived amount of movement for each pixel. The amount is smaller
near the center specified by the \uicontrol {Horizontal offset} and
\uicontrol {Vertical offset} fields and reaches the specified value
at the edges.
near the center specified by the horizontal (\uicontrol H) and
vertical (\uicontrol V) \uicontrol Offset fields and reaches the
specified value at the edges.
The quality of the blur depends on the value of the
\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" \
"-executable=$qbsapp-config" \
"-executable=$qbsapp-config-ui" \
"-executable=$qbsapp-qmltypes" \
"-executable=$qbsapp-setup-android" \
"-executable=$qbsapp-setup-qt" \
"-executable=$qbsapp-setup-toolchains" \

View File

@@ -54,7 +54,7 @@ def main():
os.symlink('/Applications', os.path.join(tempdir, 'Applications'))
shutil.copy(os.path.join(arguments.source_directory, 'LICENSE.GPL3-EXCEPT'), tempdir)
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)
# sleep a few seconds to make sure disk image is fully unmounted etc
time.sleep(5)

View File

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

View File

@@ -36,18 +36,20 @@ Column {
}
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 saturationHSL: 0
property real saturationHSV: 0
property real lightness: 0
property real value: 0
property real saturationHSL: 0.5
property real saturationHSV: 0.5
property real lightness: 0.5
property real value: 0.5
property real alpha: 1
property bool achromatic: false
property int sliderMargins: 6
property bool block: false
@@ -57,81 +59,90 @@ Column {
spacing: 10
onModeChanged: {
onColorChanged: {
if (root.block)
return
switch (root.mode) {
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
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
case ColorPicker.Mode.HSVA:
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
}
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() {
if (root.block)
return
root.block = true
if (root.color.hsvSaturation > 0.0
&& root.color.hsvValue > 0.0
&& root.color.hsvHue !== -1.0)
root.hue = root.color.hsvHue
switch (root.mode) {
case ColorPicker.Mode.RGBA:
root.color = Qt.rgba(root.red, root.green, root.blue, root.alpha)
// 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
&& 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)
if (root.color.hslLightness !== 0.0 && root.color.hslLightness !== 1.0)
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.lightness = root.color.hslLightness
root.value = root.color.hsvValue
if (root.color.hslLightness === 0.0 || root.color.hslLightness === 1.0
|| 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)
break
case ColorPicker.Mode.HSLA:
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)
// 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)
hueSlider.value = root.hue
@@ -142,21 +153,21 @@ Column {
root.block = false
}
function drawHSVA(ctx) {
for (var row = 0; row < gradientOverlay.height; row++) {
var gradient = ctx.createLinearGradient(0, 0, gradientOverlay.width, 0)
var v = Math.abs(row - gradientOverlay.height) / gradientOverlay.height
function drawHSVA(ctx, width, height, hue) {
for (var row = 0; row < height; row++) {
var gradient = ctx.createLinearGradient(0, 0, width, 0)
var v = Math.abs(row - height) / height
gradient.addColorStop(0, Qt.hsva(root.hue, 0, v, 1))
gradient.addColorStop(1, Qt.hsva(root.hue, 1, v, 1))
gradient.addColorStop(0, Qt.hsva(hue, 0, v, 1))
gradient.addColorStop(1, Qt.hsva(hue, 1, v, 1))
ctx.fillStyle = gradient
ctx.fillRect(0, row, gradientOverlay.width, 1)
ctx.fillRect(0, row, width, 1)
}
}
function drawRGBA(ctx) {
var gradient = ctx.createLinearGradient(0, 0, gradientOverlay.width, 0)
function drawRGBA(ctx, width, height) {
var gradient = ctx.createLinearGradient(0, 0, width, 0)
gradient.addColorStop(0.000, Qt.rgba(1, 0, 0, 1))
gradient.addColorStop(0.167, Qt.rgba(1, 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))
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(1.000, Qt.rgba(1, 1, 1, 1))
ctx.fillStyle = gradient
ctx.fillRect(0, 0, gradientOverlay.width, gradientOverlay.height)
ctx.fillRect(0, 0, width, height)
}
function drawHSLA(ctx) {
for (var row = 0; row < gradientOverlay.height; row++) {
var gradient = ctx.createLinearGradient(0, 0, gradientOverlay.width, 0)
var l = Math.abs(row - gradientOverlay.height) / gradientOverlay.height
function drawHSLA(ctx, width, height, hue) {
for (var row = 0; row < height; row++) {
var gradient = ctx.createLinearGradient(0, 0, width, 0)
var l = Math.abs(row - height) / height
gradient.addColorStop(0, Qt.hsla(root.hue, 0, l, 1))
gradient.addColorStop(1, Qt.hsla(root.hue, 1, l, 1))
gradient.addColorStop(0, Qt.hsla(hue, 0, l, 1))
gradient.addColorStop(1, Qt.hsla(hue, 1, l, 1))
ctx.fillStyle = gradient
ctx.fillRect(0, row, gradientOverlay.width, 1)
ctx.fillRect(0, row, width, 1)
}
}
@@ -211,11 +222,12 @@ Column {
id: gradientOverlay
anchors.fill: parent
opacity: root.color.a
opacity: root.alpha
Connections {
target: root
function onHueChanged() { gradientOverlay.requestPaint() }
function onModeChanged() { gradientOverlay.requestPaint() }
}
onPaint: {
@@ -225,14 +237,14 @@ Column {
switch (root.mode) {
case ColorPicker.Mode.RGBA:
root.drawRGBA(ctx)
root.drawRGBA(ctx, gradientOverlay.width, gradientOverlay.height)
break
case ColorPicker.Mode.HSLA:
root.drawHSLA(ctx)
root.drawHSLA(ctx, gradientOverlay.width, gradientOverlay.height, root.hue)
break
case ColorPicker.Mode.HSVA:
default:
root.drawHSVA(ctx)
root.drawHSVA(ctx, gradientOverlay.width, gradientOverlay.height, root.hue)
break
}
@@ -244,9 +256,14 @@ Column {
id: pickerCross
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.margins: -pickerCross.radius
antialiasing: true
Connections {
@@ -261,35 +278,63 @@ Column {
ctx.save()
ctx.clearRect(0, 0, pickerCross.width, pickerCross.height)
var yy, xx = 0
var normX, normY = 0
switch (root.mode) {
case ColorPicker.Mode.RGBA:
yy = pickerCross.height - root.saturationHSV * pickerCross.height
xx = root.hue * pickerCross.width
normX = root.hue
normY = 1.0 - root.saturationHSV
break
case ColorPicker.Mode.HSLA:
yy = pickerCross.height - root.lightness * pickerCross.height
xx = root.saturationHSL * pickerCross.width
normX = root.saturationHSL
normY = 1.0 - root.lightness
break
case ColorPicker.Mode.HSVA:
default:
yy = pickerCross.height - root.value * pickerCross.height
xx = root.saturationHSV * pickerCross.width
normX = root.saturationHSV
normY = 1.0 - root.value
break
}
ctx.strokeStyle = pickerCross.strokeStyle
ctx.lineWidth = 1
var width = pickerCross.width - pickerCross.radius * 2
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.moveTo(0, yy)
ctx.lineTo(pickerCross.width, yy)
ctx.arc(centerX, centerY, pickerCross.radius, 0, 2 * Math.PI)
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.strokeStyle = "white"
ctx.beginPath()
ctx.moveTo(xx, 0)
ctx.lineTo(xx, pickerCross.height)
ctx.arc(centerX, centerY, pickerCross.radius - 2, 0, 2 * Math.PI)
ctx.stroke()
ctx.restore()
@@ -298,31 +343,48 @@ Column {
MouseArea {
id: mouseArea
anchors.fill: parent
anchors.margins: -pickerCross.radius
preventStealing: true
acceptedButtons: Qt.LeftButton | Qt.RightButton
onPositionChanged: function(mouse) {
if (mouseArea.pressed && mouse.buttons === Qt.LeftButton) {
var xx = Math.max(0, Math.min(mouse.x, parent.width))
var yy = Math.max(0, Math.min(mouse.y, parent.height))
// Generate color values from mouse position
// 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) {
case ColorPicker.Mode.RGBA:
root.saturationHSV = 1.0 - yy / parent.height
root.hue = xx / parent.width
var tmpColor = Qt.hsva(normX, // hue
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
case ColorPicker.Mode.HSLA:
root.saturationHSL = xx / parent.width
root.lightness = 1.0 - yy / parent.height
root.saturationHSL = normX
root.lightness = 1.0 - normY
break
case ColorPicker.Mode.HSVA:
default:
root.saturationHSV = xx / parent.width
root.value = 1.0 - yy / parent.height
root.saturationHSV = normX
root.value = 1.0 - normY
break
}
root.invalidateColor()
}
}
onPressed: function(mouse) {
@@ -345,9 +407,11 @@ Column {
id: hueSlider
visible: root.mode !== ColorPicker.Mode.RGBA
width: parent.width
onValueChanged: {
onMoved: {
if (root.hue !== hueSlider.value)
root.hue = hueSlider.value
root.invalidateColor()
}
onClicked: root.updateColor()
}
@@ -356,10 +420,21 @@ Column {
id: luminanceSlider
visible: root.mode === ColorPicker.Mode.RGBA
width: parent.width
color: Qt.hsva(root.hue, root.color.hsvSaturation, 1, 1)
onValueChanged: {
if (root.value !== luminanceSlider.value)
color: Qt.hsva(root.hue, root.saturationHSV, root.value, root.alpha)
onMoved: {
if (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()
}
@@ -367,10 +442,12 @@ Column {
OpacitySlider {
id: opacitySlider
width: parent.width
color: Qt.rgba(root.color.r, root.color.g, root.color.b, 1)
onValueChanged: {
if (root.alpha !== opacitySlider.value)
color: root.color
onMoved: {
if (root.alpha !== (1.0 - opacitySlider.value))
root.alpha = (1.0 - opacitySlider.value)
root.invalidateColor()
}
onClicked: root.updateColor()
}

View File

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

View File

@@ -96,13 +96,12 @@ Item {
height: 80
width: parent.width
property int effectiveWidth: width - 10
property int effectiveWidth: colorLine.width - 10
property int selectedIndex: 0
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
}
if (repeater.model.count < index + 1)
return
@@ -113,11 +112,12 @@ Item {
gradientModel.lock()
root.currentColor = repeater.itemAt(index).item.color
gradientModel.unlock()
root.selectedNodeChanged()
}
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++) {
gradientString += "GradientStop {}"
@@ -209,21 +209,21 @@ Item {
anchors.left: parent.left
anchors.right: parent.right
Image {
id: checkerboard
anchors.fill: parent
source: "images/checkers.png"
fillMode: Image.Tile
}
Rectangle {
id: gradientRectangle
smooth: true
x: 0
y: 16
radius: 1
border.color: "#555555"
border.width: 1
width: parent.height
height: parent.width
anchors.fill: parent
border.color: StudioTheme.Values.themeControlOutline
border.width: StudioTheme.Values.border
gradient: Gradient {
id: gradient
}
transformOrigin: Item.TopLeft
rotation: 270
}
}
}
@@ -270,6 +270,13 @@ Item {
onXChanged: gradientStopHandle.refreshToolTip(gradientStopHandle.toolTipVisible)
Image {
width: 10
height: 10
source: "images/checkers.png"
fillMode: Image.Tile
}
Rectangle {
id: rectangle
width: 10
@@ -277,7 +284,6 @@ Item {
color: "red"
border.color: "gray"
border.width: 1
radius: 1
}
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
signal clicked
signal moved
height: StudioTheme.Values.hueSliderHeight
function updatePos() {
if (root.maximum > root.minimum) {
var pos = (track.width - handle.width) * (root.value - root.minimum) / (root.maximum - root.minimum)
return Math.min(Math.max(pos, 0), track.width - handle.width)
var pos = track.width * (root.value - root.minimum) / (root.maximum - root.minimum)
return Math.min(Math.max(pos, 0), track.width)
} else {
return 0
}
@@ -50,7 +51,6 @@ Item {
Item {
id: track
width: parent.width
height: parent.height
@@ -74,21 +74,20 @@ Item {
Rectangle {
id: handle
width: StudioTheme.Values.hueSliderHandleWidth
height: track.height - 4
height: track.height + 4
anchors.verticalCenter: parent.verticalCenter
smooth: true
color: "transparent"
radius: 2
border.color: "black"
border.width: 1
x: root.updatePos()
x: root.updatePos() - handle.width * 0.5
y: 2
z: 1
Rectangle {
anchors.fill: parent
anchors.margins: 1
color: "transparent"
color: Qt.hsva(value, 1, 1, 1)
radius: 1
border.color: "white"
border.width: 1
@@ -98,21 +97,23 @@ Item {
MouseArea {
id: mouseArea
anchors.fill: parent
anchors.margins: -StudioTheme.Values.hueSliderHandleWidth * 0.5
preventStealing: true
function calculateValue() {
var handleX = Math.max(0, Math.min(mouseArea.mouseX, mouseArea.width))
var realValue = (root.maximum - root.minimum) * handleX / mouseArea.width + root.minimum
var halfHandle = StudioTheme.Values.hueSliderHandleWidth * 0.5
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.moved()
}
onPressed: calculateValue()
onPressed: mouseArea.calculateValue()
onReleased: root.clicked()
onPositionChanged: {
if (pressed)
calculateValue()
if (mouseArea.pressed)
mouseArea.calculateValue()
}
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -81,6 +81,7 @@ T.SpinBox {
signal dragStarted
signal dragEnded
signal dragging
signal indicatorPressed
// Use custom wheel handling due to bugs
property bool __wheelEnabled: false
@@ -124,6 +125,7 @@ T.SpinBox {
myControl: mySpinBox
iconFlip: -1
visible: mySpinBox.spinBoxIndicatorVisible
onRealPressed: mySpinBox.indicatorPressed()
onRealReleased: mySpinBox.realIncrease()
onRealPressAndHold: mySpinBox.realIncrease()
x: actionIndicator.width + StudioTheme.Values.border
@@ -139,6 +141,7 @@ T.SpinBox {
id: spinBoxIndicatorDown
myControl: mySpinBox
visible: mySpinBox.spinBoxIndicatorVisible
onRealPressed: mySpinBox.indicatorPressed()
onRealReleased: mySpinBox.realDecrease()
onRealPressAndHold: mySpinBox.realDecrease()
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);
process->disconnect();
process->setParent(nullptr);
if (process->state() == QProcess::NotRunning) {
process->deleteLater();
return;

View File

@@ -473,7 +473,13 @@ FilePath AndroidConfig::avdManagerToolPath() 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
QStringList hostPatterns;

View File

@@ -544,11 +544,13 @@ void AndroidDeployQtStep::stdError(const QString &line)
return;
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));
else if (newOutput != QLatin1String("All files should be loaded. Notifying the device."))
} else {
TaskHub::addTask(DeploymentTask(Task::Error, newOutput));
}
}
AndroidDeployQtStep::DeployErrorCode AndroidDeployQtStep::parseDeployErrors(
const QString &deployOutputLine) const

View File

@@ -117,12 +117,16 @@ QList<ITestConfiguration *> CTestTreeItem::testConfigurationsFor(const QStringLi
config->setProject(project);
config->setCommandLine(command);
const ProjectExplorer::RunConfiguration *runConfig = target->activeRunConfiguration();
Utils::Environment env = Utils::Environment::systemEnvironment();
if (QTC_GUARD(runConfig)) {
if (auto envAspect = runConfig->aspect<ProjectExplorer::EnvironmentAspect>())
config->setEnvironment(envAspect->environment());
else
config->setEnvironment(Utils::Environment::systemEnvironment());
env = envAspect->environment();
}
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();
if (QTC_GUARD(buildConfig))
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 result(env);
if (Utils::HostOsInfo::isWindowsHost())
if (Utils::HostOsInfo::isWindowsHost()) {
result.set("QT_FORCE_STDERR_LOGGING", "1");
result.set("QT_LOGGING_TO_CONSOLE", "1");
}
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
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);
});
if (timestampChanged) {
m_watchedFiles[directory] = filesAndDates;
PathsAndLanguages paths;
paths.maybeInsert(Utils::FilePath::fromString(directory), Dialect::Qml);
QFutureInterface<void> future;

View File

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

View File

@@ -68,6 +68,7 @@
#include <QMenu>
#include <QTextBlock>
#include <QTimer>
#include <QtDebug>
using namespace CppEditor;
using namespace LanguageClient;
@@ -381,7 +382,7 @@ ClangdClient *ClangModelManagerSupport::clientForProject(
&& c->state() != Client::ShutdownRequested
&& 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());
}

View File

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

View File

@@ -44,12 +44,26 @@ namespace Internal {
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
{
public:
QString errorMessage;
CMakeConfig cache;
QSet<Utils::FilePath> cmakeFiles;
QSet<CMakeFileInfo> cmakeFiles;
QList<CMakeBuildTarget> buildTargets;
ProjectExplorer::RawProjectParts projectParts;
std::unique_ptr<CMakeProjectNode> rootProjectNode;

View File

@@ -249,10 +249,10 @@ static std::vector<CMakeFileInfo> readCMakeFilesFile(const FilePath &cmakeFilesF
for (const QJsonValue &v : inputs) {
CMakeFileInfo info;
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();
const QString filename = FilePath::fromString(info.path).fileName();
const QString filename = info.path.fileName();
info.isCMakeListsDotTxt = (filename.compare("CMakeLists.txt",
HostOsInfo::fileNameCaseSensitivity())
== 0);

View File

@@ -71,16 +71,6 @@ public:
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
{
public:
@@ -243,7 +233,7 @@ class FileApiData
public:
FileApiDetails::ReplyFileContents replyFile;
CMakeConfig cache;
std::vector<FileApiDetails::CMakeFileInfo> cmakeFiles;
std::vector<CMakeFileInfo> cmakeFiles;
FileApiDetails::Configuration codemodel;
std::vector<FileApiDetails::TargetDetails> targetDetails;
};

View File

@@ -88,8 +88,12 @@ void FileApiReader::setParameters(const BuildDirParameters &p)
void FileApiReader::resetData()
{
m_cmakeFiles.clear();
if (!m_parameters.sourceDirectory.isEmpty())
m_cmakeFiles.insert(m_parameters.sourceDirectory.pathAppended("CMakeLists.txt"));
if (!m_parameters.sourceDirectory.isEmpty()) {
CMakeFileInfo cmakeListsTxt;
cmakeListsTxt.path = m_parameters.sourceDirectory.pathAppended("CMakeLists.txt");
cmakeListsTxt.isCMakeListsDotTxt = true;
m_cmakeFiles.insert(cmakeListsTxt);
}
m_cache.clear();
m_buildTargets.clear();
@@ -124,8 +128,9 @@ void FileApiReader::parse(bool forceCMakeRun,
const bool hasArguments = !args.isEmpty();
const bool replyFileMissing = !replyFile.exists();
const bool cmakeFilesChanged = m_parameters.cmakeTool() && m_parameters.cmakeTool()->isAutoRun()
&& anyOf(m_cmakeFiles, [&replyFile](const FilePath &f) {
return f.lastModified() > replyFile.lastModified();
&& anyOf(m_cmakeFiles, [&replyFile](const CMakeFileInfo &info) {
return !info.isGenerated
&& info.path.lastModified() > replyFile.lastModified();
});
const bool queryFileChanged = anyOf(FileApiParser::cmakeQueryFilePaths(m_parameters.buildDirectory),
[&replyFile](const FilePath &qf) {
@@ -175,7 +180,10 @@ bool FileApiReader::isParsing() 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){
@@ -249,7 +257,7 @@ void FileApiReader::endState(const FilePath &replyFilePath)
const FilePath sourceDirectory = m_parameters.sourceDirectory;
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;
QTC_CHECK(!replyFilePath.needsDevice());

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -158,26 +158,6 @@ QList<QMakeAssignment> MakeFileParse::parseAssignments(const QList<QMakeAssignme
m_qmakeBuildConfig.explicitBuildAll = false;
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")) {
if (qa.op == QLatin1String("+="))
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 BuildAll" << m_qmakeBuildConfig.explicitBuildAll;
qCDebug(logging()) << " Explicit NoBuildAll" << m_qmakeBuildConfig.explicitNoBuildAll;
qCDebug(logging()) << " TargetArch" << m_config.archConfig;
qCDebug(logging()) << " OsType" << m_config.osType;
qCDebug(logging()) << " LinkQmlDebuggingQQ2"
<< (m_config.linkQmlDebuggingQQ2 == TriState::Enabled);
@@ -530,7 +509,6 @@ void QmakeProjectManagerPlugin::testMakefileParser()
QCOMPARE(parser.effectiveBuildConfig({}), effectiveBuildConfig);
const QMakeStepConfig qmsc = parser.config();
QCOMPARE(qmsc.archConfig, static_cast<QMakeStepConfig::TargetArchConfig>(archConfig));
QCOMPARE(qmsc.osType, static_cast<QMakeStepConfig::OsType>(osType));
QCOMPARE(qmsc.linkQmlDebuggingQQ2 == TriState::Enabled, linkQmlDebuggingQQ2);
QCOMPARE(qmsc.useQtQuickCompiler == TriState::Enabled, useQtQuickCompiler);

View File

@@ -71,7 +71,6 @@ struct DirectoryData
BaseQtVersion::QmakeBuildConfigs buildConfig;
QString additionalArguments;
QMakeStepConfig config;
QMakeStepConfig::TargetArchConfig archConfig;
QMakeStepConfig::OsType osType;
};
@@ -154,10 +153,8 @@ QList<void *> QmakeProjectImporter::examineDirectory(const FilePath &importPath,
qCDebug(logs) << " qt version:" << version->displayName() << " temporary:" << isTemporaryVersion;
data->archConfig = parse.config().archConfig;
data->osType = parse.config().osType;
qCDebug(logs) << " archConfig:" << data->archConfig;
qCDebug(logs) << " osType: " << data->osType;
if (version->type() == QLatin1String(IOSQT)
&& 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;
}
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
data->additionalArguments = parse.unparsedArguments();
qCDebug(logs) << " Unparsed arguments:" << data->additionalArguments;
@@ -210,27 +193,23 @@ bool QmakeProjectImporter::matchKit(void *directoryData, const Kit *k) const
ToolChain *tc = ToolChainKitAspect::cxxToolChain(k);
if (kitSpec.isEmpty() && kitVersion)
kitSpec = kitVersion->mkspecFor(tc);
QMakeStepConfig::TargetArchConfig kitTargetArch = QMakeStepConfig::NoArch;
QMakeStepConfig::OsType kitOsType = QMakeStepConfig::NoOsType;
if (tc) {
kitTargetArch = QMakeStepConfig::targetArchFor(tc->targetAbi(), kitVersion);
kitOsType = QMakeStepConfig::osTypeFor(tc->targetAbi(), kitVersion);
}
qCDebug(logs) << k->displayName()
<< "version:" << (kitVersion == data->qtVersionData.qt)
<< "spec:" << (kitSpec == data->parsedSpec)
<< "targetarch:" << (kitTargetArch == data->archConfig)
<< "ostype:" << (kitOsType == data->osType);
return kitVersion == data->qtVersionData.qt
&& kitSpec == data->parsedSpec
&& kitTargetArch == data->archConfig
&& kitOsType == data->osType;
}
Kit *QmakeProjectImporter::createKit(void *directoryData) const
{
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
@@ -262,17 +241,14 @@ void QmakeProjectImporter::deleteDirectoryData(void *directoryData) const
delete static_cast<DirectoryData *>(directoryData);
}
static const QList<ToolChain *> preferredToolChains(BaseQtVersion *qtVersion, const QString &ms,
const QMakeStepConfig::TargetArchConfig &archConfig)
static const QList<ToolChain *> preferredToolChains(BaseQtVersion *qtVersion, const QString &ms)
{
const QString spec = ms.isEmpty() ? qtVersion->mkspec() : ms;
const QList<ToolChain *> toolchains = ToolChainManager::toolChains();
const Abis qtAbis = qtVersion->qtAbis();
const auto matcher = [&](const ToolChain *tc) {
return qtAbis.contains(tc->targetAbi())
&& tc->suggestedMkspecList().contains(spec)
&& QMakeStepConfig::targetArchFor(tc->targetAbi(), qtVersion) == archConfig;
return qtAbis.contains(tc->targetAbi()) && tc->suggestedMkspecList().contains(spec);
};
ToolChain * const cxxToolchain = findOrDefault(toolchains, [matcher](const ToolChain *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,
const QString &parsedSpec,
const QMakeStepConfig::TargetArchConfig &archConfig,
const QMakeStepConfig::OsType &osType) const
{
Q_UNUSED(osType) // TODO use this to select the right toolchain?
return QtProjectImporter::createTemporaryKit(data,
[&data, parsedSpec, archConfig](Kit *k) -> void {
for (ToolChain * const tc : preferredToolChains(data.qt, parsedSpec, archConfig))
return QtProjectImporter::createTemporaryKit(data, [&data, parsedSpec](Kit *k) -> void {
for (ToolChain *const tc : preferredToolChains(data.qt, parsedSpec))
ToolChainKitAspect::setToolChain(k, tc);
if (parsedSpec != data.qt->mkspec())
QmakeKitAspect::setMkspec(k, parsedSpec, QmakeKitAspect::MkspecSource::Code);

View File

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

View File

@@ -185,7 +185,6 @@ QMakeStepConfig QMakeStep::deducedArguments() const
BaseQtVersion *version = QtKitAspect::qtVersion(kit);
config.archConfig = QMakeStepConfig::targetArchFor(targetAbi, version);
config.osType = QMakeStepConfig::osTypeFor(targetAbi, version);
config.separateDebugInfo = qmakeBuildConfiguration()->separateDebugInfo();
config.linkQmlDebuggingQQ2 = qmakeBuildConfiguration()->qmlDebugging();
@@ -780,25 +779,9 @@ QMakeStepFactory::QMakeStepFactory()
setFlags(BuildStepInfo::UniqueStep);
}
QMakeStepConfig::TargetArchConfig QMakeStepConfig::targetArchFor(const Abi &targetAbi, const BaseQtVersion *version)
QMakeStepConfig::TargetArchConfig QMakeStepConfig::targetArchFor(const Abi &, const BaseQtVersion *)
{
TargetArchConfig arch = 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;
return NoArch;
}
QMakeStepConfig::OsType QMakeStepConfig::osTypeFor(const Abi &targetAbi, const BaseQtVersion *version)

View File

@@ -66,15 +66,14 @@ public:
class QMAKEPROJECTMANAGER_EXPORT QMakeStepConfig
{
public:
enum TargetArchConfig {
NoArch, X86, X86_64, PowerPC, PowerPC64
};
// TODO remove, does nothing
enum TargetArchConfig { NoArch, X86, X86_64, PowerPC, PowerPC64 };
enum OsType {
NoOsType, IphoneSimulator, IphoneOS
};
enum OsType { 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);
QStringList toArguments() const;
@@ -82,6 +81,7 @@ public:
// Actual data
QString sysRoot;
QString targetTriple;
// TODO remove, does nothing
TargetArchConfig archConfig = NoArch;
OsType osType = NoOsType;
Utils::TriState separateDebugInfo;

View File

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

View File

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

View File

@@ -161,6 +161,8 @@ ItemLibraryWidget::ItemLibraryWidget(AsynchronousImageCache &imageCache,
{
m_compressionTimer.setInterval(200);
m_compressionTimer.setSingleShot(true);
m_assetCompressionTimer.setInterval(200);
m_assetCompressionTimer.setSingleShot(true);
ItemLibraryModel::registerQmlTypes();
setWindowTitle(tr("Library", "Title of library view"));
@@ -234,17 +236,7 @@ ItemLibraryWidget::ItemLibraryWidget(AsynchronousImageCache &imageCache,
// reconstruct the model to update the icons
connect(m_fileSystemWatcher, &Utils::FileSystemWatcher::directoryChanged, [this](const QString & changedDirPath) {
Q_UNUSED(changedDirPath)
// TODO: find a clever way to only refresh the changed directory part of the model
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_assetCompressionTimer.start();
});
m_stackedWidget = new QStackedWidget(this);
@@ -270,6 +262,26 @@ ItemLibraryWidget::ItemLibraryWidget(AsynchronousImageCache &imageCache,
connect(m_qmlSourceUpdateShortcut, &QShortcut::activated, this, &ItemLibraryWidget::reloadQmlSource);
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",
new ItemLibraryIconImageProvider{m_imageCache});

View File

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

View File

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

View File

@@ -45,6 +45,8 @@
#include <qmldesignerplugin.h>
#endif
#include <utils/qtcassert.h>
#include <QRegularExpression>
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.
Everything that belongs to this Object, the ModelNode, and ChangeOperations
@@ -366,6 +378,7 @@ void QmlObjectNode::destroy()
if (!isValid())
throw new InvalidModelNodeException(__LINE__, __FUNCTION__, __FILE__);
removeLayerEnabled(modelNode());
removeAliasExports(modelNode());
for (QmlModelStateOperation stateOperation : allAffectingStatesOperations()) {

View File

@@ -1099,7 +1099,6 @@ bool TextToModelMerger::load(const QString &data, DifferenceHandler &differenceH
m_rewriterView->setWarnings(warnings);
qCInfo(rewriterBenchmark) << "checked semantic errors:" << time.elapsed();
}
setupUsedImports();
AST::UiObjectMember *astRootNode = nullptr;
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();
setupUsedImports();
setActive(false);
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()));
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
if (!Utils::HostOsInfo::isMacHost())

View File

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

View File

@@ -34,6 +34,7 @@
#include <coreplugin/documentmanager.h>
#include <coreplugin/editormanager/documentmodel.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/icontext.h>
#include <coreplugin/icore.h>
@@ -144,6 +145,18 @@ QmlProject::QmlProject(const Utils::FilePath &fileName)
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