Merge remote-tracking branch 'origin/qds/dev'
Change-Id: I8aa6ace80911b440485f9006f066aa2113cca63d
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
\page creator-editor-refactoring.html
|
\page creator-editor-refactoring.html
|
||||||
\previouspage creator-editor-locator.html
|
\previouspage creator-jump-to-the-code.html
|
||||||
\nextpage creator-editor-quick-fixes.html
|
\nextpage creator-editor-quick-fixes.html
|
||||||
|
|
||||||
\title Refactoring
|
\title Refactoring
|
||||||
|
@@ -37,6 +37,14 @@
|
|||||||
through projects, files, classes, functions, documentation and
|
through projects, files, classes, functions, documentation and
|
||||||
file systems.
|
file systems.
|
||||||
|
|
||||||
|
\li \l{Jump to the Code}
|
||||||
|
|
||||||
|
Jump to the code for a specific component directly from
|
||||||
|
the \uicontrol {2D} view or \uicontrol {Navigator} view.
|
||||||
|
You can also jump to the code of a particular
|
||||||
|
\uicontrol {State} or \uicontrol {Connection} from their
|
||||||
|
corresponding views.
|
||||||
|
|
||||||
\endlist
|
\endlist
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
66
doc/qtcreator/src/editors/creator-jump-to-the-code.qdoc
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\previouspage creator-editor-locator.html
|
||||||
|
\page creator-jump-to-the-code.html
|
||||||
|
\nextpage creator-editor-refactoring.html
|
||||||
|
|
||||||
|
\title Jump to the Code
|
||||||
|
|
||||||
|
Jump to the code is a feature that gives you instant access to a particular
|
||||||
|
part of the code. It takes you to the \uicontrol {Code} view location of a particular
|
||||||
|
component, \uicontrol {State}, or \uicontrol {Connection}.
|
||||||
|
|
||||||
|
You can jump to the code from:
|
||||||
|
\list
|
||||||
|
\li \uicontrol {Navigator} view
|
||||||
|
\li \uicontrol {2D} view
|
||||||
|
\li \uicontrol {States} view
|
||||||
|
\li \uicontrol {Connections} view
|
||||||
|
\endlist
|
||||||
|
|
||||||
|
\section1 Jump to the Code from the Navigator View
|
||||||
|
|
||||||
|
\list 1
|
||||||
|
\li Right-click on a component in the \uicontrol {Navigator} view.
|
||||||
|
\li Select \uicontrol {Jump to the Code}.
|
||||||
|
\endlist
|
||||||
|
|
||||||
|
\image jump-to-the-code-from-navigator-view.webp
|
||||||
|
|
||||||
|
\section1 Jump to the Code from the 2D View
|
||||||
|
|
||||||
|
\list 1
|
||||||
|
\li Right-click on a component in the \uicontrol {2D} view.
|
||||||
|
\li Select \uicontrol {Jump to the Code}.
|
||||||
|
\endlist
|
||||||
|
|
||||||
|
\image jump-to-the-code-from-2D-view.webp
|
||||||
|
|
||||||
|
\note Alternatively, you can select the component in the \uicontrol {Navigator} view
|
||||||
|
or in the \uicontrol {2D} view and press \key {F4}. That takes you to the code
|
||||||
|
location in the \uicontrol {Code} view.
|
||||||
|
|
||||||
|
\section1 Jump to the Code from the States View
|
||||||
|
|
||||||
|
\list 1
|
||||||
|
\li Locate the state you want to check in the \uicontrol {States} view.
|
||||||
|
\li Select \inlineimage icons/browse-button.png
|
||||||
|
to open additional options.
|
||||||
|
\li Select \uicontrol {Jump to the Code}.
|
||||||
|
\endlist
|
||||||
|
|
||||||
|
\image jump-to-the-code-from-state-view.webp
|
||||||
|
|
||||||
|
\section1 Jump to the Code from the Connections View
|
||||||
|
|
||||||
|
\list 1
|
||||||
|
\li Select a connection in the \uicontrol {Connections} view.
|
||||||
|
\li Select \inlineimage icons/jump-to-code-16px.png
|
||||||
|
to jump to the code segment related to the connection.
|
||||||
|
\endlist
|
||||||
|
|
||||||
|
\image jump-to-the-code-from-connections-view.webp
|
||||||
|
|
||||||
|
*/
|
@@ -4,7 +4,7 @@
|
|||||||
/*!
|
/*!
|
||||||
\previouspage creator-editor-finding.html
|
\previouspage creator-editor-finding.html
|
||||||
\page creator-editor-locator.html
|
\page creator-editor-locator.html
|
||||||
\nextpage creator-editor-refactoring.html
|
\nextpage creator-jump-to-the-code.html
|
||||||
|
|
||||||
\title Searching with the Locator
|
\title Searching with the Locator
|
||||||
|
|
||||||
|
@@ -31,7 +31,7 @@
|
|||||||
\li \e fire-color-table.png
|
\li \e fire-color-table.png
|
||||||
\endlist
|
\endlist
|
||||||
|
|
||||||
You can download the assets from
|
Download the assets
|
||||||
\l{https://git.qt.io/public-demos/qtdesign-studio/-/tree/master/tutorial%20projects/fire-particles/FireParticles/content/images}
|
\l{https://git.qt.io/public-demos/qtdesign-studio/-/tree/master/tutorial%20projects/fire-particles/FireParticles/content/images}
|
||||||
{here}.
|
{here}.
|
||||||
|
|
||||||
@@ -48,14 +48,14 @@
|
|||||||
\li In the \uicontrol Presets section, select \uicontrol General >
|
\li In the \uicontrol Presets section, select \uicontrol General >
|
||||||
\uicontrol {3D}.
|
\uicontrol {3D}.
|
||||||
\li In the \uicontrol Details section, set the name to \e FireParticles
|
\li In the \uicontrol Details section, set the name to \e FireParticles
|
||||||
and select the folder where you want to save the project.
|
, and select the folder where you want to save the project.
|
||||||
\li Select \uicontrol {Create}.
|
\li Select \uicontrol {Create}.
|
||||||
\endlist
|
\endlist
|
||||||
|
|
||||||
Next, remove unwanted default components from the project:
|
Next, remove any unwanted default components from the project:
|
||||||
|
|
||||||
\list 1
|
\list 1
|
||||||
\li In \uicontrol {Navigator}, select \e Text and select the \key Delete
|
\li In the \uicontrol {Navigator} view, select \e Text and then select the \key Delete
|
||||||
key.
|
key.
|
||||||
\li In the same way, delete \e {cubeModel}.
|
\li In the same way, delete \e {cubeModel}.
|
||||||
\endlist
|
\endlist
|
||||||
@@ -63,11 +63,10 @@
|
|||||||
For a better visual effect, set the background color to black:
|
For a better visual effect, set the background color to black:
|
||||||
|
|
||||||
\list
|
\list
|
||||||
\li In \uicontrol {Navigator}, select \e Rectangle and in
|
\li In the \uicontrol {Navigator} view, select \e Rectangle and in
|
||||||
\uicontrol {Properties}, set \uicontrol {Fill Color} to #000000.
|
\uicontrol {Properties}, set \uicontrol {Fill Color} to #000000.
|
||||||
\endlist
|
\endlist
|
||||||
|
|
||||||
|
|
||||||
\section2 Adding a Particle System to Your Scene
|
\section2 Adding a Particle System to Your Scene
|
||||||
|
|
||||||
To add a particle system, you first need to import the QtQuick3D.Particles3D
|
To add a particle system, you first need to import the QtQuick3D.Particles3D
|
||||||
@@ -79,16 +78,19 @@
|
|||||||
\li Find QtQuick3D.Particles3D, and select it to add it to your project.
|
\li Find QtQuick3D.Particles3D, and select it to add it to your project.
|
||||||
\endlist
|
\endlist
|
||||||
|
|
||||||
|
\image fire-particles-components.png
|
||||||
|
|
||||||
In this project, you use an animated sprite to simulate a fire. For
|
In this project, you use an animated sprite to simulate a fire. For
|
||||||
this, use the Animated Sprite particle system template:
|
this, use the \uicontrol {Animated Sprite} particle system template:
|
||||||
|
|
||||||
\list
|
\list
|
||||||
\li From \uicontrol Components >
|
\li From \uicontrol Components >
|
||||||
\uicontrol{Qt Quick 3D Particle System Templates} drag an
|
\uicontrol{Qt Quick 3D Particle System Templates} drag an
|
||||||
\uicontrol {Animated Sprite} component to the \uicontrol{3D} view. You can
|
\uicontrol {Animated Sprite} component [1] to \e scene in \uicontrol {Navigator}.
|
||||||
also drag it to \e scene in \uicontrol {Navigator}.
|
|
||||||
\endlist
|
\endlist
|
||||||
|
|
||||||
|
\image fire-particles-animated-sprite-comp.png
|
||||||
|
|
||||||
\image fire-particles-navigator.png
|
\image fire-particles-navigator.png
|
||||||
|
|
||||||
You now have the particle system in place. To preview it, select
|
You now have the particle system in place. To preview it, select
|
||||||
@@ -97,26 +99,33 @@
|
|||||||
|
|
||||||
\section2 Adding Sprites and Sprite Animations
|
\section2 Adding Sprites and Sprite Animations
|
||||||
|
|
||||||
First, import the sprite to use for the fire:
|
In this project, you use a spritesheet with 3 sprites.
|
||||||
|
A spritesheet is a single image file that contains multiple sprites arranged
|
||||||
|
in a grid. You use these sprites to create a looping animation to add variation
|
||||||
|
to the movement of the flames.
|
||||||
|
|
||||||
|
First, import the spritesheet you downloaded in the beginning of this tutorial
|
||||||
|
(\e{fire-sprites.png}) to use for the fire:
|
||||||
|
|
||||||
\list 1
|
\list 1
|
||||||
\li In \uicontrol {Assets}, select \inlineimage icons/plus.png
|
\li In the \uicontrol {Assets} view, select \inlineimage icons/plus.png
|
||||||
.
|
.
|
||||||
\li Select \e {fire-sprites.png}.
|
\li In the \uicontrol {Add Assets} dialog, find and select \e {fire-sprites.png}.
|
||||||
\endlist
|
\endlist
|
||||||
|
|
||||||
\image fire-particles-assets.png
|
\image fire-particles-assets.png
|
||||||
|
|
||||||
Next, add the sprite to the particle system and create the animation:
|
Next, add the spritesheet to the particle system, and create the animation:
|
||||||
|
|
||||||
\list 1
|
\list 1
|
||||||
\li From \uicontrol{Assets}, drag \e {fire-sprites.png} to
|
\li From the \uicontrol{Assets} view, drag \e {fire-sprites.png} to
|
||||||
\e animatedTexture in \uicontrol {Navigator}.
|
\e animatedTexture in the \uicontrol {Navigator} view.
|
||||||
\li In \uicontrol{Navigator}, select \e{animatedSequence} and in
|
\image fire-particles-drag-sprites.png
|
||||||
\uicontrol {Properties}, set:
|
\li In the \uicontrol{Navigator} view, select \e{animatedSequence} and in
|
||||||
|
the \uicontrol {Properties} view, set:
|
||||||
\list
|
\list
|
||||||
\li \uicontrol{Frame Count} to 3.
|
\li \uicontrol{Frame Count} to 3.
|
||||||
There are 3 sprites in \e {fire-sprites.png} so you want to
|
There are three sprites in \e {fire-sprites.png} so you want to
|
||||||
divide the image into 3 different sprites for this animation.
|
divide the image into 3 different sprites for this animation.
|
||||||
\li \uicontrol Interpolate to true. This makes the animation between
|
\li \uicontrol Interpolate to true. This makes the animation between
|
||||||
the sprites smooth.
|
the sprites smooth.
|
||||||
@@ -132,21 +141,25 @@
|
|||||||
change the color of a single sprite during its life span. In this
|
change the color of a single sprite during its life span. In this
|
||||||
project, you use a gradient color table ranging from yellow to dark orange.
|
project, you use a gradient color table ranging from yellow to dark orange.
|
||||||
This results in the sprites being yellow when they are emitted and dark
|
This results in the sprites being yellow when they are emitted and dark
|
||||||
orange at the end of the life span.
|
orange at the end of their life span.
|
||||||
|
|
||||||
To set the color table:
|
To set the color table:
|
||||||
|
|
||||||
\list 1
|
\list 1
|
||||||
\li Import \e{fire-color-table.png} to your project.
|
\li Go to the \uicontrol {Asstes} view and import \e{fire-color-table.png} to your project.
|
||||||
\li From \uicontrol{Components}, drag a \uicontrol Texture to
|
\li From the \uicontrol{Components} view, drag a \uicontrol Texture [1] to
|
||||||
\e animatedSpriteParticle in \uicontrol{Navigator}.
|
\e animatedSpriteParticle in \uicontrol{Navigator}.
|
||||||
|
\image fire-particles-drag-texture.png
|
||||||
\li Rename the texture to \e {fireColorTable}.
|
\li Rename the texture to \e {fireColorTable}.
|
||||||
\li In \uicontrol {Navigator}, select \e {fireColorTable} and in
|
\li In the \uicontrol {Navigator} view, select \e {fireColorTable} and in
|
||||||
\uicontrol {Properties}, set \uicontrol Source to
|
the \uicontrol {Properties} view, set \uicontrol Source to
|
||||||
\e{fire-color-table.png}.
|
\e{fire-color-table.png}.
|
||||||
\li In \uicontrol {Navigator}, select \e {animatedSpriteParticle} and:
|
\li In the \uicontrol {Navigator} view, select \e {animatedSpriteParticle} and in the
|
||||||
|
\uicontrol Properties view:
|
||||||
\list
|
\list
|
||||||
\li Ensure that \uicontrol Sprite is set to \e {animatedTexture}.
|
\li Ensure that \uicontrol Sprite is set to \e {animatedTexture}. This sets which image
|
||||||
\li Set \uicontrol {Particle Scale} to 5.
|
to emit from the particle emitter, which in this case is the spritesheet added earlier.
|
||||||
|
\li Set \uicontrol {Particle Scale} to 5 to adjust the size of the flames.
|
||||||
\li Set \uicontrol {Color Table} to \e{fireColorTable}.
|
\li Set \uicontrol {Color Table} to \e{fireColorTable}.
|
||||||
\endlist
|
\endlist
|
||||||
\endlist
|
\endlist
|
||||||
@@ -158,48 +171,71 @@
|
|||||||
The next step is to adjust the particle emitter properties:
|
The next step is to adjust the particle emitter properties:
|
||||||
|
|
||||||
\list 1
|
\list 1
|
||||||
\li In \uicontrol{Navigator}, select \e animatedSpriteEmitter and in
|
\li First, in the \uicontrol{Navigator} view, select \e animatedSpriteEmitter and then, in
|
||||||
\uicontrol {Properties}, set:
|
the \uicontrol {Properties} view, set:
|
||||||
\list
|
\list
|
||||||
\li \uicontrol {Emit Rate} to 300.
|
\li \uicontrol {Emit Rate} to 300 to emit 300 particles per second.
|
||||||
\li \uicontrol {Life Span} to 2500.
|
\li \uicontrol {Life Span} to 2500 to set the life span of each particle to
|
||||||
\li \uicontrol {Life Span Variation} to 100.
|
2500 milliseconds (2.5 seconds).
|
||||||
\li \uicontrol {Particle End Scale} to 1,50.
|
\li \uicontrol {Life Span Variation} to 100 to set variation to the particle
|
||||||
|
life spans. The life span of each particle is now between 2.4 and 2.6 seconds to make
|
||||||
|
the fire look more realistic.
|
||||||
|
\li \uicontrol {Particle End Scale} to 1.50. When a particle is emitted, its
|
||||||
|
scale is 1.00 by default. By the end of its life span, it will grow to a scale of 1.50.
|
||||||
\endlist
|
\endlist
|
||||||
This sets the emitter to emit 300 particles per second. The life span of
|
|
||||||
each particle is ranging from 2.4 to 2.6 seconds. The size of each
|
\image fire-particles-particle-emitter.png
|
||||||
particle is increasing slightly throughout its life span.
|
|
||||||
\li In \uicontrol{Navigator}, select \e animatedSpriteParticle and in
|
\li First, in the \uicontrol{Navigator} view, select \e animatedSpriteParticle and then, in
|
||||||
\uicontrol {Properties}, set:
|
the \uicontrol {Properties} view, set:
|
||||||
\list
|
\list
|
||||||
\li \uicontrol {Blend Mode} to Screen.
|
\li \uicontrol {Blend Mode} to Screen to blend the fire nicely with the background.
|
||||||
\li \uicontrol {Max Amount} to 1000.
|
\li \uicontrol {Max Amount} to 1000 to define the maximum amount of particles visible at the
|
||||||
\li \uicontrol {Color Variation} > \uicontrol W to 0,50. This adds
|
same time. Setting a higher number allocates more memory.
|
||||||
|
\li \uicontrol {Color Variation} > \uicontrol W to 0.50. This adds
|
||||||
randomness to the opacity of the sprites.
|
randomness to the opacity of the sprites.
|
||||||
\endlist
|
\endlist
|
||||||
\li In \uicontrol{Navigator}, select \e animatedSpriteDirection and in
|
|
||||||
\uicontrol {Properties}, set:
|
\image fire-particle-sprite-particle.png
|
||||||
|
|
||||||
|
\li The \e animatedSpriteDirection component defines the direction and the velocity of
|
||||||
|
the particles emitted from the particle emitter. In this tutorial, you want the particles to
|
||||||
|
go straight up with a small variation.
|
||||||
|
|
||||||
|
In the \uicontrol{Navigator} view, select \e animatedSpriteDirection and in the
|
||||||
|
\uicontrol {Properties} view, set:
|
||||||
\list
|
\list
|
||||||
\li \uicontrol Direction > \uicontrol Y to 20.
|
\li \uicontrol Direction > \uicontrol X to 0 and \uicontrol Direction > \uicontrol Y
|
||||||
\li \uicontrol {Direction Variation} > \uicontrol X to 3.
|
to 20. This makes the particles go straight up (along the Y axis) at the velocity of 20.
|
||||||
\li \uicontrol {Direction Variation} > \uicontrol Y to 10.
|
\li \uicontrol {Direction Variation} > \uicontrol X to 3. This adds small variation along
|
||||||
\endlist
|
the X axis, making the flames a little bit wider.
|
||||||
This makes the particles go straight up with a small amount of randomness
|
\li \uicontrol {Direction Variation} > \uicontrol Y to 10. This adds variation to the
|
||||||
to the direction.
|
velocity of the particles along the Y axis. Because this makes some particles slower,
|
||||||
|
the flames appears thicker in the lower part.
|
||||||
\endlist
|
\endlist
|
||||||
|
|
||||||
\section1 Previewing
|
\image fire-particles-direction.png
|
||||||
|
|
||||||
Now, the fire effect is done. Before you preview it, adjust the camera:
|
\endlist
|
||||||
|
|
||||||
|
\section1 Running the Project
|
||||||
|
|
||||||
|
Now, the fire effect is ready. Before you run it, position the camera to show the effect
|
||||||
|
from a suitable perspective:
|
||||||
\list 1
|
\list 1
|
||||||
\li In \uicontrol {Navigator}, select \e sceneCamera and in
|
\li In the \uicontrol {Navigator} view, select \e sceneCamera and in the
|
||||||
\uicontrol {Properties}, set:
|
\uicontrol {Properties} view, set:
|
||||||
\list
|
\list
|
||||||
\li \uicontrol {Field of View} to 20.
|
\li \uicontrol {Field of View} to 20.
|
||||||
\li \uicontrol {Translation} > \uicontrol Y to 35.
|
\li \uicontrol {Translation} > \uicontrol Y to 35.
|
||||||
|
\li \uicontrol {Translation} > \uicontrol Z to 350.
|
||||||
\endlist
|
\endlist
|
||||||
\endlist
|
\endlist
|
||||||
|
|
||||||
Now, preview the fire effect by selecting \key Alt + \key{P}.
|
\image fire-particles-camera.png
|
||||||
|
|
||||||
|
Now, run the project by selecting \key Ctrl + \key{R} or the
|
||||||
|
\inlineimage icons/run_project.png
|
||||||
|
button in the top toolbar.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 23 KiB |
BIN
doc/qtdesignstudio/examples/doc/images/fire-particles-camera.png
Normal file
After Width: | Height: | Size: 38 KiB |
After Width: | Height: | Size: 8.2 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 9.9 KiB |
After Width: | Height: | Size: 30 KiB |
BIN
doc/qtdesignstudio/images/icons/jump-to-code-16px.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
doc/qtdesignstudio/images/icons/run_project.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
doc/qtdesignstudio/images/jump-to-the-code-from-2D-view.webp
Normal file
After Width: | Height: | Size: 7.5 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 8.4 KiB |
BIN
doc/qtdesignstudio/images/jump-to-the-code-from-state-view.webp
Normal file
After Width: | Height: | Size: 14 KiB |
@@ -214,6 +214,7 @@
|
|||||||
\list
|
\list
|
||||||
\li \l{Finding and Replacing}
|
\li \l{Finding and Replacing}
|
||||||
\li \l{Searching with the Locator}
|
\li \l{Searching with the Locator}
|
||||||
|
\li \l{Jump to the Code}
|
||||||
\endlist
|
\endlist
|
||||||
\li \l{Refactoring}
|
\li \l{Refactoring}
|
||||||
\li \l{Applying Refactoring Actions}
|
\li \l{Applying Refactoring Actions}
|
||||||
|
@@ -120,7 +120,7 @@ StudioControls.Dialog {
|
|||||||
actionIndicator.visible: false
|
actionIndicator.visible: false
|
||||||
translationIndicator.visible: false
|
translationIndicator.visible: false
|
||||||
validator: RegularExpressionValidator {
|
validator: RegularExpressionValidator {
|
||||||
regularExpression: /^\w+$/
|
regularExpression: /^[\w ]+$/
|
||||||
}
|
}
|
||||||
|
|
||||||
Keys.onEnterPressed: btnImport.onClicked()
|
Keys.onEnterPressed: btnImport.onClicked()
|
||||||
|
@@ -87,7 +87,7 @@ StudioControls.Dialog {
|
|||||||
actionIndicator.visible: false
|
actionIndicator.visible: false
|
||||||
translationIndicator.visible: false
|
translationIndicator.visible: false
|
||||||
validator: RegularExpressionValidator {
|
validator: RegularExpressionValidator {
|
||||||
regularExpression: /^\w+$/
|
regularExpression: /^[\w ]+$/
|
||||||
}
|
}
|
||||||
|
|
||||||
Keys.onEnterPressed: btnCreate.onClicked()
|
Keys.onEnterPressed: btnCreate.onClicked()
|
||||||
|
@@ -25,7 +25,6 @@ Item {
|
|||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
id: priv
|
id: priv
|
||||||
property bool useBlurItem1: true
|
|
||||||
property bool useBlurItem2: rootItem.blurMax > 2
|
property bool useBlurItem2: rootItem.blurMax > 2
|
||||||
property bool useBlurItem3: rootItem.blurMax > 8
|
property bool useBlurItem3: rootItem.blurMax > 8
|
||||||
property bool useBlurItem4: rootItem.blurMax > 16
|
property bool useBlurItem4: rootItem.blurMax > 16
|
||||||
@@ -34,12 +33,12 @@ Item {
|
|||||||
|
|
||||||
BlurItem {
|
BlurItem {
|
||||||
id: blurredItemSource1
|
id: blurredItemSource1
|
||||||
property Item src: priv.useBlurItem1 ? source : null
|
property Item src: source
|
||||||
// Size of the first blurred item is by default half of the source.
|
// Size of the first blurred item is by default half of the source.
|
||||||
// Increase for quality and decrease for performance & more blur.
|
// Increase for quality and decrease for performance & more blur.
|
||||||
readonly property int blurItemSize: 8
|
readonly property int blurItemSize: 8
|
||||||
width: src ? Math.ceil(src.width / 16) * blurItemSize : 0
|
width: Math.ceil(rootItem.width / 16) * blurItemSize
|
||||||
height: src ? Math.ceil(src.height / 16) * blurItemSize : 0
|
height: Math.ceil(rootItem.height / 16) * blurItemSize
|
||||||
}
|
}
|
||||||
BlurItem {
|
BlurItem {
|
||||||
id: blurredItemSource2
|
id: blurredItemSource2
|
||||||
|
@@ -86,6 +86,9 @@ T.TextField {
|
|||||||
// was closed due to an menu item click.
|
// was closed due to an menu item click.
|
||||||
if (control.activeFocus && control.focusReason !== Qt.OtherFocusReason)
|
if (control.activeFocus && control.focusReason !== Qt.OtherFocusReason)
|
||||||
control.preFocusText = control.text
|
control.preFocusText = control.text
|
||||||
|
|
||||||
|
if (!control.activeFocus)
|
||||||
|
control.deselect()
|
||||||
}
|
}
|
||||||
|
|
||||||
onEditChanged: {
|
onEditChanged: {
|
||||||
|
@@ -189,7 +189,8 @@ struct DockAreaWidgetPrivate
|
|||||||
{
|
{
|
||||||
DockAreaWidget *q = nullptr;
|
DockAreaWidget *q = nullptr;
|
||||||
QBoxLayout *m_layout = nullptr;
|
QBoxLayout *m_layout = nullptr;
|
||||||
DockAreaLayout *m_contentsLayout = nullptr;
|
// DockAreaLayout is not a QObject -> std::unique_ptr manages deletion
|
||||||
|
std::unique_ptr<DockAreaLayout> m_contentsLayout;
|
||||||
DockAreaTitleBar *m_titleBar = nullptr;
|
DockAreaTitleBar *m_titleBar = nullptr;
|
||||||
DockManager *m_dockManager = nullptr;
|
DockManager *m_dockManager = nullptr;
|
||||||
AutoHideDockContainer *m_autoHideDockContainer = nullptr;
|
AutoHideDockContainer *m_autoHideDockContainer = nullptr;
|
||||||
@@ -328,7 +329,7 @@ DockAreaWidget::DockAreaWidget(DockManager *dockManager, DockContainerWidget *pa
|
|||||||
setLayout(d->m_layout);
|
setLayout(d->m_layout);
|
||||||
|
|
||||||
d->createTitleBar();
|
d->createTitleBar();
|
||||||
d->m_contentsLayout = new DockAreaLayout(d->m_layout);
|
d->m_contentsLayout = std::make_unique<DockAreaLayout>(d->m_layout);
|
||||||
if (d->m_dockManager)
|
if (d->m_dockManager)
|
||||||
emit d->m_dockManager->dockAreaCreated(this);
|
emit d->m_dockManager->dockAreaCreated(this);
|
||||||
}
|
}
|
||||||
@@ -336,8 +337,6 @@ DockAreaWidget::DockAreaWidget(DockManager *dockManager, DockContainerWidget *pa
|
|||||||
DockAreaWidget::~DockAreaWidget()
|
DockAreaWidget::~DockAreaWidget()
|
||||||
{
|
{
|
||||||
qCInfo(adsLog) << Q_FUNC_INFO;
|
qCInfo(adsLog) << Q_FUNC_INFO;
|
||||||
delete d->m_contentsLayout;
|
|
||||||
delete d;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DockManager *DockAreaWidget::dockManager() const
|
DockManager *DockAreaWidget::dockManager() const
|
||||||
|
@@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
#include <QFrame>
|
#include <QFrame>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QAbstractButton;
|
class QAbstractButton;
|
||||||
class QXmlStreamWriter;
|
class QXmlStreamWriter;
|
||||||
@@ -33,7 +35,7 @@ class ADS_EXPORT DockAreaWidget : public QFrame
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
private:
|
private:
|
||||||
DockAreaWidgetPrivate *d; ///< private data (pimpl)
|
std::unique_ptr<DockAreaWidgetPrivate> d; ///< private data (pimpl)
|
||||||
friend struct DockAreaWidgetPrivate;
|
friend struct DockAreaWidgetPrivate;
|
||||||
friend class DockContainerWidget;
|
friend class DockContainerWidget;
|
||||||
friend class DockContainerWidgetPrivate;
|
friend class DockContainerWidgetPrivate;
|
||||||
|
@@ -137,9 +137,9 @@ void CompositionNode::parse(const QString &effectName, const QString &qenPath, c
|
|||||||
QString trimmedLine = codeLine.trimmed();
|
QString trimmedLine = codeLine.trimmed();
|
||||||
if (trimmedLine.startsWith("@requires")) {
|
if (trimmedLine.startsWith("@requires")) {
|
||||||
// Get the required node, remove "@requires "
|
// Get the required node, remove "@requires "
|
||||||
QString nodeName = trimmedLine.sliced(10);
|
QString nodeId = trimmedLine.sliced(10).toLower();
|
||||||
if (!nodeName.isEmpty() && !m_requiredNodes.contains(nodeName))
|
if (!nodeId.isEmpty() && !m_requiredNodes.contains(nodeId))
|
||||||
m_requiredNodes << nodeName;
|
m_requiredNodes << nodeId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -124,6 +124,10 @@ void EffectMakerModel::addNode(const QString &nodeQenPath)
|
|||||||
|
|
||||||
const QString path = EffectUtils::nodesSourcesPath() + "/common/" + requiredId + ".qen";
|
const QString path = EffectUtils::nodesSourcesPath() + "/common/" + requiredId + ".qen";
|
||||||
auto requiredNode = new CompositionNode({}, path);
|
auto requiredNode = new CompositionNode({}, path);
|
||||||
|
connect(qobject_cast<EffectMakerUniformsModel *>(requiredNode->uniformsModel()),
|
||||||
|
&EffectMakerUniformsModel::dataChanged, this, [this] {
|
||||||
|
setHasUnsavedChanges(true);
|
||||||
|
});
|
||||||
requiredNode->setRefCount(1);
|
requiredNode->setRefCount(1);
|
||||||
m_nodes.prepend(requiredNode);
|
m_nodes.prepend(requiredNode);
|
||||||
}
|
}
|
||||||
@@ -490,6 +494,9 @@ QJsonObject nodeToJson(const CompositionNode &node)
|
|||||||
QString type = Uniform::stringFromType(uniform->type());
|
QString type = Uniform::stringFromType(uniform->type());
|
||||||
uniformObject.insert("type", type);
|
uniformObject.insert("type", type);
|
||||||
|
|
||||||
|
if (!uniform->displayName().isEmpty())
|
||||||
|
uniformObject.insert("displayName", QString(uniform->displayName()));
|
||||||
|
|
||||||
QString value = variantAsDataString(uniform->type(), uniform->value());
|
QString value = variantAsDataString(uniform->type(), uniform->value());
|
||||||
if (uniform->type() == Uniform::Type::Sampler)
|
if (uniform->type() == Uniform::Type::Sampler)
|
||||||
value = QFileInfo(value).fileName();
|
value = QFileInfo(value).fileName();
|
||||||
|
@@ -114,6 +114,11 @@ QString Uniform::description() const
|
|||||||
return m_description;
|
return m_description;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Uniform::displayName() const
|
||||||
|
{
|
||||||
|
return m_displayName;
|
||||||
|
}
|
||||||
|
|
||||||
QString Uniform::customValue() const
|
QString Uniform::customValue() const
|
||||||
{
|
{
|
||||||
return m_customValue;
|
return m_customValue;
|
||||||
|
@@ -59,6 +59,7 @@ public:
|
|||||||
|
|
||||||
QString name() const;
|
QString name() const;
|
||||||
QString description() const;
|
QString description() const;
|
||||||
|
QString displayName() const;
|
||||||
|
|
||||||
QString customValue() const;
|
QString customValue() const;
|
||||||
void setCustomValue(const QString &newCustomValue);
|
void setCustomValue(const QString &newCustomValue);
|
||||||
|
@@ -115,9 +115,8 @@ AssetsLibraryWidget::AssetsLibraryWidget(AsynchronousImageCache &asynchronousFon
|
|||||||
m_assetsWidget->setClearColor(Theme::getColor(Theme::Color::QmlDesigner_BackgroundColorDarkAlternate));
|
m_assetsWidget->setClearColor(Theme::getColor(Theme::Color::QmlDesigner_BackgroundColorDarkAlternate));
|
||||||
m_assetsWidget->engine()->addImageProvider("qmldesigner_assets", m_assetsIconProvider);
|
m_assetsWidget->engine()->addImageProvider("qmldesigner_assets", m_assetsIconProvider);
|
||||||
|
|
||||||
connect(m_assetsModel, &AssetsLibraryModel::fileChanged, [](const QString &changeFilePath) {
|
connect(m_assetsModel, &AssetsLibraryModel::fileChanged,
|
||||||
QmlDesignerPlugin::instance()->emitAssetChanged(changeFilePath);
|
QmlDesignerPlugin::instance(), &QmlDesignerPlugin::assetChanged);
|
||||||
});
|
|
||||||
|
|
||||||
auto layout = new QVBoxLayout(this);
|
auto layout = new QVBoxLayout(this);
|
||||||
layout->setContentsMargins({});
|
layout->setContentsMargins({});
|
||||||
|
@@ -179,15 +179,16 @@ bool CollectionDetailsModel::setHeaderData(int section,
|
|||||||
return headerChanged;
|
return headerChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CollectionDetailsModel::insertRows(int row, int count, const QModelIndex &parent)
|
bool CollectionDetailsModel::insertRows(int row, int count, [[maybe_unused]] const QModelIndex &parent)
|
||||||
{
|
{
|
||||||
if (count < 1)
|
if (count < 1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
row = qBound(0, row, rowCount());
|
row = qBound(0, row, rowCount());
|
||||||
beginInsertRows(parent, row, row + count);
|
|
||||||
|
beginResetModel();
|
||||||
m_currentCollection.insertEmptyElements(row, count);
|
m_currentCollection.insertEmptyElements(row, count);
|
||||||
endInsertRows();
|
endResetModel();
|
||||||
|
|
||||||
selectRow(row);
|
selectRow(row);
|
||||||
return true;
|
return true;
|
||||||
|
@@ -3,11 +3,9 @@
|
|||||||
|
|
||||||
#include "collectioneditorutils.h"
|
#include "collectioneditorutils.h"
|
||||||
|
|
||||||
#include "abstractview.h"
|
#include "model.h"
|
||||||
#include "bindingproperty.h"
|
|
||||||
#include "nodemetainfo.h"
|
#include "nodemetainfo.h"
|
||||||
#include "propertymetainfo.h"
|
#include "propertymetainfo.h"
|
||||||
#include "variantproperty.h"
|
|
||||||
|
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
@@ -137,33 +135,6 @@ QString getSourceCollectionType(const ModelNode &node)
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void assignCollectionToNode(AbstractView *view,
|
|
||||||
const ModelNode &modelNode,
|
|
||||||
const ModelNode &collectionSourceNode,
|
|
||||||
const QString &collectionName)
|
|
||||||
{
|
|
||||||
QTC_ASSERT(modelNode.isValid() && collectionSourceNode.isValid(), return);
|
|
||||||
|
|
||||||
QString sourceId = isDataStoreNode(collectionSourceNode) ? "DataStore"
|
|
||||||
: collectionSourceNode.id();
|
|
||||||
|
|
||||||
if (sourceId.isEmpty() || !canAcceptCollectionAsModel(modelNode))
|
|
||||||
return;
|
|
||||||
|
|
||||||
VariantProperty sourceProperty = collectionSourceNode.variantProperty(collectionName.toLatin1());
|
|
||||||
if (!sourceProperty.exists())
|
|
||||||
return;
|
|
||||||
|
|
||||||
BindingProperty modelProperty = modelNode.bindingProperty("model");
|
|
||||||
|
|
||||||
QString identifier = QString("%1.%2").arg(sourceId, QString::fromLatin1(sourceProperty.name()));
|
|
||||||
|
|
||||||
view->executeInTransaction("CollectionEditor::assignCollectionToNode",
|
|
||||||
[&modelProperty, &identifier]() {
|
|
||||||
modelProperty.setExpression(identifier);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Utils::FilePath dataStoreJsonFilePath()
|
Utils::FilePath dataStoreJsonFilePath()
|
||||||
{
|
{
|
||||||
return collectionPath("models.json");
|
return collectionPath("models.json");
|
||||||
|
@@ -24,11 +24,6 @@ QString getSourceCollectionType(const QmlDesigner::ModelNode &node);
|
|||||||
|
|
||||||
QString getSourceCollectionPath(const QmlDesigner::ModelNode &dataStoreNode);
|
QString getSourceCollectionPath(const QmlDesigner::ModelNode &dataStoreNode);
|
||||||
|
|
||||||
void assignCollectionToNode(AbstractView *view,
|
|
||||||
const ModelNode &modelNode,
|
|
||||||
const ModelNode &collectionSourceNode,
|
|
||||||
const QString &collectionName);
|
|
||||||
|
|
||||||
Utils::FilePath dataStoreJsonFilePath();
|
Utils::FilePath dataStoreJsonFilePath();
|
||||||
|
|
||||||
Utils::FilePath dataStoreQmlFilePath();
|
Utils::FilePath dataStoreQmlFilePath();
|
||||||
|
@@ -394,27 +394,24 @@ void CollectionSourceModel::updateNodeSource(const ModelNode &node)
|
|||||||
updateCollectionList(index);
|
updateCollectionList(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CollectionSourceModel::onSelectedCollectionChanged(int collectionIndex)
|
void CollectionSourceModel::onSelectedCollectionChanged(CollectionListModel *collectionList,
|
||||||
|
int collectionIndex)
|
||||||
{
|
{
|
||||||
CollectionListModel *collectionList = qobject_cast<CollectionListModel *>(sender());
|
if (collectionIndex > -1) {
|
||||||
if (collectionIndex > -1 && collectionList) {
|
|
||||||
if (m_previousSelectedList && m_previousSelectedList != collectionList)
|
if (m_previousSelectedList && m_previousSelectedList != collectionList)
|
||||||
m_previousSelectedList->selectCollectionIndex(-1);
|
m_previousSelectedList->selectCollectionIndex(-1);
|
||||||
|
|
||||||
m_previousSelectedList = collectionList;
|
m_previousSelectedList = collectionList;
|
||||||
|
|
||||||
emit collectionSelected(collectionList->sourceNode(),
|
emit collectionSelected(collectionList->collectionNameAt(collectionIndex));
|
||||||
collectionList->collectionNameAt(collectionIndex));
|
|
||||||
|
|
||||||
selectSourceIndex(sourceIndex(collectionList->sourceNode()));
|
selectSourceIndex(sourceIndex(collectionList->sourceNode()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CollectionSourceModel::onCollectionNameChanged(const QString &oldName, const QString &newName)
|
void CollectionSourceModel::onCollectionNameChanged(CollectionListModel *collectionList,
|
||||||
|
const QString &oldName, const QString &newName)
|
||||||
{
|
{
|
||||||
CollectionListModel *collectionList = qobject_cast<CollectionListModel *>(sender());
|
|
||||||
QTC_ASSERT(collectionList, return);
|
|
||||||
|
|
||||||
auto emitRenameWarning = [this](const QString &msg) -> void {
|
auto emitRenameWarning = [this](const QString &msg) -> void {
|
||||||
emit this->warning(tr("Rename Model"), msg);
|
emit this->warning(tr("Rename Model"), msg);
|
||||||
};
|
};
|
||||||
@@ -496,15 +493,14 @@ void CollectionSourceModel::onCollectionNameChanged(const QString &oldName, cons
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emit collectionRenamed(oldName, newName);
|
||||||
updateCollectionList(nodeIndex);
|
updateCollectionList(nodeIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CollectionSourceModel::onCollectionsRemoved(const QStringList &removedCollections)
|
void CollectionSourceModel::onCollectionsRemoved(CollectionListModel *collectionList,
|
||||||
|
const QStringList &removedCollections)
|
||||||
{
|
{
|
||||||
CollectionListModel *collectionList = qobject_cast<CollectionListModel *>(sender());
|
|
||||||
QTC_ASSERT(collectionList, return);
|
|
||||||
|
|
||||||
auto emitDeleteWarning = [this](const QString &msg) -> void {
|
auto emitDeleteWarning = [this](const QString &msg) -> void {
|
||||||
emit warning(tr("Delete Model"), msg);
|
emit warning(tr("Delete Model"), msg);
|
||||||
};
|
};
|
||||||
@@ -551,10 +547,12 @@ void CollectionSourceModel::onCollectionsRemoved(const QStringList &removedColle
|
|||||||
if (document.isObject()) {
|
if (document.isObject()) {
|
||||||
QJsonObject rootObject = document.object();
|
QJsonObject rootObject = document.object();
|
||||||
|
|
||||||
|
QStringList collectionsRemovedFromDocument;
|
||||||
for (const QString &collectionName : removedCollections) {
|
for (const QString &collectionName : removedCollections) {
|
||||||
bool sourceContainsCollection = rootObject.contains(collectionName);
|
bool sourceContainsCollection = rootObject.contains(collectionName);
|
||||||
if (sourceContainsCollection) {
|
if (sourceContainsCollection) {
|
||||||
rootObject.remove(collectionName);
|
rootObject.remove(collectionName);
|
||||||
|
collectionsRemovedFromDocument << collectionName;
|
||||||
} else {
|
} else {
|
||||||
emitDeleteWarning(tr("The model group doesn't contain the model name (%1).")
|
emitDeleteWarning(tr("The model group doesn't contain the model name (%1).")
|
||||||
.arg(sourceContainsCollection));
|
.arg(sourceContainsCollection));
|
||||||
@@ -576,6 +574,9 @@ void CollectionSourceModel::onCollectionsRemoved(const QStringList &removedColle
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const QString &collectionName : std::as_const(collectionsRemovedFromDocument))
|
||||||
|
emit this->collectionRemoved(collectionName);
|
||||||
|
|
||||||
updateCollectionList(nodeIndex);
|
updateCollectionList(nodeIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -606,7 +607,7 @@ void CollectionSourceModel::setSelectedIndex(int idx)
|
|||||||
} else if (m_previousSelectedList) {
|
} else if (m_previousSelectedList) {
|
||||||
m_previousSelectedList->selectCollectionIndex(-1);
|
m_previousSelectedList->selectCollectionIndex(-1);
|
||||||
m_previousSelectedList = {};
|
m_previousSelectedList = {};
|
||||||
emit this->collectionSelected(sourceNodeAt(idx), {});
|
emit this->collectionSelected({});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -630,37 +631,38 @@ void CollectionSourceModel::updateCollectionList(QModelIndex index)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
ModelNode sourceNode = sourceNodeAt(index.row());
|
ModelNode sourceNode = sourceNodeAt(index.row());
|
||||||
QSharedPointer<CollectionListModel> currentList = m_collectionList.at(index.row());
|
QSharedPointer<CollectionListModel> oldList = m_collectionList.at(index.row());
|
||||||
QSharedPointer<CollectionListModel> newList = loadCollection(sourceNode, currentList);
|
QSharedPointer<CollectionListModel> newList = loadCollection(sourceNode, oldList);
|
||||||
if (currentList != newList) {
|
if (oldList != newList) {
|
||||||
m_collectionList.replace(index.row(), newList);
|
m_collectionList.replace(index.row(), newList);
|
||||||
emit dataChanged(index, index, {CollectionsRole});
|
emit dataChanged(index, index, {CollectionsRole});
|
||||||
emit collectionNamesChanged(sourceNode, newList->stringList());
|
registerCollection(newList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CollectionSourceModel::registerCollection(const QSharedPointer<CollectionListModel> &collection)
|
void CollectionSourceModel::registerCollection(const QSharedPointer<CollectionListModel> &collection)
|
||||||
{
|
{
|
||||||
connect(collection.data(),
|
CollectionListModel *collectionList = collection.data();
|
||||||
&CollectionListModel::selectedIndexChanged,
|
if (collectionList == nullptr)
|
||||||
this,
|
return;
|
||||||
&CollectionSourceModel::onSelectedCollectionChanged,
|
|
||||||
Qt::UniqueConnection);
|
|
||||||
|
|
||||||
connect(collection.data(),
|
connect(collectionList, &CollectionListModel::selectedIndexChanged, this,
|
||||||
&CollectionListModel::collectionNameChanged,
|
[this, collectionList](int idx) {
|
||||||
this,
|
onSelectedCollectionChanged(collectionList, idx);
|
||||||
&CollectionSourceModel::onCollectionNameChanged,
|
}, Qt::UniqueConnection);
|
||||||
Qt::UniqueConnection);
|
|
||||||
|
|
||||||
connect(collection.data(),
|
connect(collectionList, &CollectionListModel::collectionNameChanged, this,
|
||||||
&CollectionListModel::collectionsRemoved,
|
[this, collectionList](const QString &oldName, const QString &newName) {
|
||||||
this,
|
onCollectionNameChanged(collectionList, oldName, newName);
|
||||||
&CollectionSourceModel::onCollectionsRemoved,
|
}, Qt::UniqueConnection);
|
||||||
Qt::UniqueConnection);
|
|
||||||
|
|
||||||
if (collection.data() && collection->sourceNode())
|
connect(collectionList, &CollectionListModel::collectionsRemoved, this,
|
||||||
emit collectionNamesChanged(collection->sourceNode(), collection->stringList());
|
[this, collectionList](const QStringList &removedCollections) {
|
||||||
|
onCollectionsRemoved(collectionList, removedCollections);
|
||||||
|
}, Qt::UniqueConnection);
|
||||||
|
|
||||||
|
if (collectionList->sourceNode().isValid())
|
||||||
|
emit collectionNamesInitialized(collection->stringList());
|
||||||
}
|
}
|
||||||
|
|
||||||
QModelIndex CollectionSourceModel::indexOfNode(const ModelNode &node) const
|
QModelIndex CollectionSourceModel::indexOfNode(const ModelNode &node) const
|
||||||
|
@@ -70,15 +70,20 @@ public:
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void selectedIndexChanged(int idx);
|
void selectedIndexChanged(int idx);
|
||||||
void collectionSelected(const ModelNode &sourceNode, const QString &collectionName);
|
void collectionSelected(const QString &collectionName);
|
||||||
void collectionNamesChanged(const ModelNode &sourceNode, QStringList collections);
|
void collectionNamesInitialized(const QStringList &initialList);
|
||||||
|
void collectionRenamed(const QString &oldname, const QString &newName);
|
||||||
|
void collectionRemoved(const QString &collectionName);
|
||||||
|
|
||||||
void isEmptyChanged(bool);
|
void isEmptyChanged(bool);
|
||||||
void warning(const QString &title, const QString &body);
|
void warning(const QString &title, const QString &body);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onSelectedCollectionChanged(int collectionIndex);
|
void onSelectedCollectionChanged(CollectionListModel *collectionList, int collectionIndex);
|
||||||
void onCollectionNameChanged(const QString &oldName, const QString &newName);
|
void onCollectionNameChanged(CollectionListModel *collectionList, const QString &oldName,
|
||||||
void onCollectionsRemoved(const QStringList &removedCollections);
|
const QString &newName);
|
||||||
|
void onCollectionsRemoved(CollectionListModel *collectionList,
|
||||||
|
const QStringList &removedCollections);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setSelectedIndex(int idx);
|
void setSelectedIndex(int idx);
|
||||||
|
@@ -70,8 +70,8 @@ QmlDesigner::WidgetInfo CollectionView::widgetInfo()
|
|||||||
connect(sourceModel,
|
connect(sourceModel,
|
||||||
&CollectionSourceModel::collectionSelected,
|
&CollectionSourceModel::collectionSelected,
|
||||||
this,
|
this,
|
||||||
[this](const ModelNode &sourceNode, const QString &collection) {
|
[this](const QString &collection) {
|
||||||
m_widget->collectionDetailsModel()->loadCollection(sourceNode, collection);
|
m_widget->collectionDetailsModel()->loadCollection(dataStoreNode(), collection);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(sourceModel, &CollectionSourceModel::isEmptyChanged, this, [this](bool isEmpty) {
|
connect(sourceModel, &CollectionSourceModel::isEmptyChanged, this, [this](bool isEmpty) {
|
||||||
@@ -80,12 +80,25 @@ QmlDesigner::WidgetInfo CollectionView::widgetInfo()
|
|||||||
});
|
});
|
||||||
|
|
||||||
connect(sourceModel,
|
connect(sourceModel,
|
||||||
&CollectionSourceModel::collectionNamesChanged,
|
&CollectionSourceModel::collectionNamesInitialized,
|
||||||
this,
|
this,
|
||||||
[this](const ModelNode &sourceNode, const QStringList &collectionNames) {
|
[this](const QStringList &collectionNames) {
|
||||||
if (sourceNode == m_dataStore->modelNode())
|
|
||||||
m_dataStore->setCollectionNames(collectionNames);
|
m_dataStore->setCollectionNames(collectionNames);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
connect(sourceModel,
|
||||||
|
&CollectionSourceModel::collectionRenamed,
|
||||||
|
this,
|
||||||
|
[this](const QString &oldName, const QString &newName) {
|
||||||
|
m_dataStore->renameCollection(oldName, newName);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(sourceModel,
|
||||||
|
&CollectionSourceModel::collectionRemoved,
|
||||||
|
this,
|
||||||
|
[this](const QString &collectionName) {
|
||||||
|
m_dataStore->removeCollection(collectionName);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return createWidgetInfo(m_widget.data(),
|
return createWidgetInfo(m_widget.data(),
|
||||||
@@ -200,6 +213,12 @@ void CollectionView::addResource(const QUrl &url, const QString &name, const QSt
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CollectionView::assignCollectionToSelectedNode(const QString &collectionName)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(dataStoreNode() && hasSingleSelectedModelNode(), return);
|
||||||
|
m_dataStore->assignCollectionToNode(this, singleSelectedModelNode(), collectionName);
|
||||||
|
}
|
||||||
|
|
||||||
void CollectionView::registerDeclarativeType()
|
void CollectionView::registerDeclarativeType()
|
||||||
{
|
{
|
||||||
CollectionDetails::registerDeclarativeType();
|
CollectionDetails::registerDeclarativeType();
|
||||||
|
@@ -43,6 +43,8 @@ public:
|
|||||||
|
|
||||||
void addResource(const QUrl &url, const QString &name, const QString &type);
|
void addResource(const QUrl &url, const QString &name, const QString &type);
|
||||||
|
|
||||||
|
void assignCollectionToSelectedNode(const QString &collectionName);
|
||||||
|
|
||||||
static void registerDeclarativeType();
|
static void registerDeclarativeType();
|
||||||
|
|
||||||
void resetDataStoreNode();
|
void resetDataStoreNode();
|
||||||
|
@@ -337,17 +337,7 @@ bool CollectionWidget::addCollectionToDataStore(const QString &collectionName)
|
|||||||
|
|
||||||
void CollectionWidget::assignCollectionToSelectedNode(const QString collectionName)
|
void CollectionWidget::assignCollectionToSelectedNode(const QString collectionName)
|
||||||
{
|
{
|
||||||
ModelNode dsNode = dataStoreNode();
|
m_view->assignCollectionToSelectedNode(collectionName);
|
||||||
ModelNode targetNode = m_view->singleSelectedModelNode();
|
|
||||||
|
|
||||||
QTC_ASSERT(dsNode.isValid() && targetNode.isValid(), return);
|
|
||||||
|
|
||||||
if (dsNode.id().isEmpty()) {
|
|
||||||
warn(tr("Assigning the model"), tr("The model must have a valid id to be assigned."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CollectionEditor::assignCollectionToNode(m_view, targetNode, dsNode, collectionName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CollectionWidget::ensureDataStoreExists()
|
void CollectionWidget::ensureDataStoreExists()
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "datastoremodelnode.h"
|
#include "datastoremodelnode.h"
|
||||||
|
|
||||||
|
#include "abstractview.h"
|
||||||
#include "collectioneditorconstants.h"
|
#include "collectioneditorconstants.h"
|
||||||
#include "collectioneditorutils.h"
|
#include "collectioneditorutils.h"
|
||||||
#include "model/qmltextgenerator.h"
|
#include "model/qmltextgenerator.h"
|
||||||
@@ -22,6 +23,9 @@
|
|||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
|
#include <QRegularExpression>
|
||||||
|
#include <QRegularExpressionMatch>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
QmlDesigner::PropertyNameList createNameList(const QmlDesigner::ModelNode &node)
|
QmlDesigner::PropertyNameList createNameList(const QmlDesigner::ModelNode &node)
|
||||||
@@ -42,6 +46,19 @@ QmlDesigner::PropertyNameList createNameList(const QmlDesigner::ModelNode &node)
|
|||||||
return defaultsNodeProps + dynamicPropertyNames;
|
return defaultsNodeProps + dynamicPropertyNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isValidCollectionPropertyName(const QString &collectionId)
|
||||||
|
{
|
||||||
|
static const QmlDesigner::PropertyNameList reservedKeywords = {
|
||||||
|
QmlDesigner::CollectionEditor::SOURCEFILE_PROPERTY,
|
||||||
|
QmlDesigner::CollectionEditor::JSONBACKEND_TYPENAME,
|
||||||
|
"backend",
|
||||||
|
"models",
|
||||||
|
};
|
||||||
|
|
||||||
|
return QmlDesigner::ModelNode::isValidId(collectionId)
|
||||||
|
&& !reservedKeywords.contains(collectionId.toLatin1());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
@@ -85,15 +102,13 @@ void DataStoreModelNode::reloadModel()
|
|||||||
|
|
||||||
m_dataRelativePath = dataStoreJsonPath.relativePathFrom(dataStoreQmlPath).toFSPathString();
|
m_dataRelativePath = dataStoreJsonPath.relativePathFrom(dataStoreQmlPath).toFSPathString();
|
||||||
|
|
||||||
if (forceUpdate) {
|
if (forceUpdate)
|
||||||
updateDataStoreProperties();
|
update();
|
||||||
updateSingletonFile();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList DataStoreModelNode::collectionNames() const
|
QStringList DataStoreModelNode::collectionNames() const
|
||||||
{
|
{
|
||||||
return m_collectionNames;
|
return m_collectionPropertyNames.keys();
|
||||||
}
|
}
|
||||||
|
|
||||||
Model *DataStoreModelNode::model() const
|
Model *DataStoreModelNode::model() const
|
||||||
@@ -137,23 +152,60 @@ void DataStoreModelNode::updateDataStoreProperties()
|
|||||||
|
|
||||||
static TypeName childNodeTypename = "ChildListModel";
|
static TypeName childNodeTypename = "ChildListModel";
|
||||||
|
|
||||||
|
QSet<QString> collectionNamesToBeAdded;
|
||||||
|
const QStringList allCollectionNames = m_collectionPropertyNames.keys();
|
||||||
|
for (const QString &collectionName : allCollectionNames)
|
||||||
|
collectionNamesToBeAdded << collectionName;
|
||||||
|
|
||||||
const QList<AbstractProperty> formerPropertyNames = rootNode.dynamicProperties();
|
const QList<AbstractProperty> formerPropertyNames = rootNode.dynamicProperties();
|
||||||
for (const AbstractProperty &property : formerPropertyNames)
|
|
||||||
|
// Remove invalid collection names from the properties
|
||||||
|
for (const AbstractProperty &property : formerPropertyNames) {
|
||||||
|
if (!property.isNodeProperty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
NodeProperty nodeProprty = property.toNodeProperty();
|
||||||
|
if (!nodeProprty.hasDynamicTypeName(childNodeTypename))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ModelNode childNode = nodeProprty.modelNode();
|
||||||
|
if (childNode.hasProperty(CollectionEditor::JSONCHILDMODELNAME_PROPERTY)) {
|
||||||
|
QString modelName = childNode.property(CollectionEditor::JSONCHILDMODELNAME_PROPERTY)
|
||||||
|
.toVariantProperty()
|
||||||
|
.value()
|
||||||
|
.toString();
|
||||||
|
if (collectionNamesToBeAdded.contains(modelName)) {
|
||||||
|
m_collectionPropertyNames.insert(modelName, property.name());
|
||||||
|
collectionNamesToBeAdded.remove(modelName);
|
||||||
|
} else {
|
||||||
rootNode.removeProperty(property.name());
|
rootNode.removeProperty(property.name());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rootNode.removeProperty(property.name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rootNode.setIdWithoutRefactoring("models");
|
rootNode.setIdWithoutRefactoring("models");
|
||||||
|
|
||||||
for (const QString &collectionName : std::as_const(m_collectionNames)) {
|
QStringList collectionNamesLeft = collectionNamesToBeAdded.values();
|
||||||
PropertyName newName = collectionName.toLatin1();
|
Utils::sort(collectionNamesLeft);
|
||||||
|
for (const QString &collectionName : std::as_const(collectionNamesLeft)) {
|
||||||
|
PropertyName newPropertyName = getUniquePropertyName(collectionName);
|
||||||
|
if (newPropertyName.isEmpty()) {
|
||||||
|
qWarning() << __FUNCTION__ << __LINE__
|
||||||
|
<< QString("The property name cannot be generated from \"%1\"").arg(collectionName);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
ModelNode collectionNode = model()->createModelNode(childNodeTypename);
|
ModelNode collectionNode = model()->createModelNode(childNodeTypename);
|
||||||
|
|
||||||
VariantProperty modelNameProperty = collectionNode.variantProperty(
|
VariantProperty modelNameProperty = collectionNode.variantProperty(
|
||||||
CollectionEditor::JSONCHILDMODELNAME_PROPERTY);
|
CollectionEditor::JSONCHILDMODELNAME_PROPERTY);
|
||||||
modelNameProperty.setValue(newName);
|
modelNameProperty.setValue(collectionName);
|
||||||
|
|
||||||
NodeProperty nodeProp = rootNode.nodeProperty(newName);
|
NodeProperty nodeProp = rootNode.nodeProperty(newPropertyName);
|
||||||
nodeProp.setDynamicTypeNameAndsetModelNode(childNodeTypename, collectionNode);
|
nodeProp.setDynamicTypeNameAndsetModelNode(childNodeTypename, collectionNode);
|
||||||
|
|
||||||
|
m_collectionPropertyNames.insert(collectionName, newPropertyName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Backend Property
|
// Backend Property
|
||||||
@@ -186,13 +238,127 @@ void DataStoreModelNode::updateSingletonFile()
|
|||||||
file.finalize();
|
file.finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataStoreModelNode::setCollectionNames(const QStringList &newCollectionNames)
|
void DataStoreModelNode::update()
|
||||||
{
|
{
|
||||||
if (m_collectionNames != newCollectionNames) {
|
|
||||||
m_collectionNames = newCollectionNames;
|
|
||||||
updateDataStoreProperties();
|
updateDataStoreProperties();
|
||||||
updateSingletonFile();
|
updateSingletonFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
PropertyName DataStoreModelNode::getUniquePropertyName(const QString &collectionName)
|
||||||
|
{
|
||||||
|
ModelNode dataStoreNode = modelNode();
|
||||||
|
QTC_ASSERT(!collectionName.isEmpty() && dataStoreNode.isValid(), return {});
|
||||||
|
|
||||||
|
QString newProperty;
|
||||||
|
|
||||||
|
// convert to camel case
|
||||||
|
QStringList nameWords = collectionName.split(' ');
|
||||||
|
nameWords[0] = nameWords[0].at(0).toLower() + nameWords[0].mid(1);
|
||||||
|
for (int i = 1; i < nameWords.size(); ++i)
|
||||||
|
nameWords[i] = nameWords[i].at(0).toUpper() + nameWords[i].mid(1);
|
||||||
|
newProperty = nameWords.join("");
|
||||||
|
|
||||||
|
// if id starts with a number prepend an underscore
|
||||||
|
if (newProperty.at(0).isDigit())
|
||||||
|
newProperty.prepend('_');
|
||||||
|
|
||||||
|
// If the new id is not valid (e.g. qml keyword match), prepend an underscore
|
||||||
|
if (!isValidCollectionPropertyName(newProperty))
|
||||||
|
newProperty.prepend('_');
|
||||||
|
|
||||||
|
static const QRegularExpression rgx("\\d+$"); // matches a number at the end of a string
|
||||||
|
while (dataStoreNode.hasProperty(newProperty.toLatin1())) { // id exists
|
||||||
|
QRegularExpressionMatch match = rgx.match(newProperty);
|
||||||
|
if (match.hasMatch()) { // ends with a number, increment it
|
||||||
|
QString numStr = match.captured();
|
||||||
|
int num = numStr.toInt() + 1;
|
||||||
|
newProperty = newProperty.mid(0, match.capturedStart()) + QString::number(num);
|
||||||
|
} else {
|
||||||
|
newProperty.append('1');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newProperty.toLatin1();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataStoreModelNode::setCollectionNames(const QStringList &newCollectionNames)
|
||||||
|
{
|
||||||
|
m_collectionPropertyNames.clear();
|
||||||
|
for (const QString &collectionName : newCollectionNames)
|
||||||
|
m_collectionPropertyNames.insert(collectionName, {});
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataStoreModelNode::renameCollection(const QString &oldName, const QString &newName)
|
||||||
|
{
|
||||||
|
ModelNode dataStoreNode = modelNode();
|
||||||
|
QTC_ASSERT(dataStoreNode.isValid(), return);
|
||||||
|
|
||||||
|
if (m_collectionPropertyNames.contains(oldName)) {
|
||||||
|
const PropertyName oldPropertyName = m_collectionPropertyNames.value(oldName);
|
||||||
|
if (!oldPropertyName.isEmpty() && dataStoreNode.hasProperty(oldPropertyName)) {
|
||||||
|
NodeProperty collectionNode = dataStoreNode.property(oldPropertyName).toNodeProperty();
|
||||||
|
if (collectionNode.isValid()) {
|
||||||
|
VariantProperty modelNameProperty = collectionNode.modelNode().variantProperty(
|
||||||
|
CollectionEditor::JSONCHILDMODELNAME_PROPERTY);
|
||||||
|
modelNameProperty.setValue(newName);
|
||||||
|
m_collectionPropertyNames.remove(oldName);
|
||||||
|
m_collectionPropertyNames.insert(newName, collectionNode.name());
|
||||||
|
update();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
qWarning() << __FUNCTION__ << __LINE__
|
||||||
|
<< "There is no valid node for the old collection name";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
qWarning() << __FUNCTION__ << __LINE__ << QString("Invalid old property name")
|
||||||
|
<< oldPropertyName;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
qWarning() << __FUNCTION__ << __LINE__
|
||||||
|
<< QString("There is no old collection name registered with this name \"%1\"").arg(oldName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataStoreModelNode::removeCollection(const QString &collectionName)
|
||||||
|
{
|
||||||
|
if (m_collectionPropertyNames.contains(collectionName)) {
|
||||||
|
m_collectionPropertyNames.remove(collectionName);
|
||||||
|
update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DataStoreModelNode::assignCollectionToNode(AbstractView *view,
|
||||||
|
const ModelNode &targetNode,
|
||||||
|
const QString &collectionName)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(targetNode.isValid(), return);
|
||||||
|
|
||||||
|
if (!CollectionEditor::canAcceptCollectionAsModel(targetNode))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!m_collectionPropertyNames.contains(collectionName)) {
|
||||||
|
qWarning() << __FUNCTION__ << __LINE__ << "Collection doesn't exist in the DataStore"
|
||||||
|
<< collectionName;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PropertyName propertyName = m_collectionPropertyNames.value(collectionName);
|
||||||
|
|
||||||
|
const ModelNode dataStore = modelNode();
|
||||||
|
VariantProperty sourceProperty = dataStore.variantProperty(propertyName);
|
||||||
|
if (!sourceProperty.exists()) {
|
||||||
|
qWarning() << __FUNCTION__ << __LINE__
|
||||||
|
<< "The source property doesn't exist in the DataStore.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BindingProperty modelProperty = targetNode.bindingProperty("model");
|
||||||
|
|
||||||
|
QString identifier = QString("DataStore.%1").arg(QString::fromLatin1(sourceProperty.name()));
|
||||||
|
|
||||||
|
view->executeInTransaction("assignCollectionToNode", [&modelProperty, &identifier]() {
|
||||||
|
modelProperty.setExpression(identifier);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
@@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
#include <modelnode.h>
|
#include <modelnode.h>
|
||||||
|
|
||||||
|
#include <QMap>
|
||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
class Model;
|
class Model;
|
||||||
@@ -21,6 +23,12 @@ public:
|
|||||||
ModelNode modelNode() const;
|
ModelNode modelNode() const;
|
||||||
|
|
||||||
void setCollectionNames(const QStringList &newCollectionNames);
|
void setCollectionNames(const QStringList &newCollectionNames);
|
||||||
|
void renameCollection(const QString &oldName, const QString &newName);
|
||||||
|
void removeCollection(const QString &collectionName);
|
||||||
|
|
||||||
|
void assignCollectionToNode(AbstractView *view,
|
||||||
|
const ModelNode &targetNode,
|
||||||
|
const QString &collectionName);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString getModelQmlText();
|
QString getModelQmlText();
|
||||||
@@ -28,9 +36,11 @@ private:
|
|||||||
void reset();
|
void reset();
|
||||||
void updateDataStoreProperties();
|
void updateDataStoreProperties();
|
||||||
void updateSingletonFile();
|
void updateSingletonFile();
|
||||||
|
void update();
|
||||||
|
PropertyName getUniquePropertyName(const QString &collectionName);
|
||||||
|
|
||||||
ModelPointer m_model;
|
ModelPointer m_model;
|
||||||
QStringList m_collectionNames;
|
QMap<QString, PropertyName> m_collectionPropertyNames;
|
||||||
QString m_dataRelativePath;
|
QString m_dataRelativePath;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -27,8 +27,15 @@ QWidget *EventListDelegate::createEditor(QWidget *parent,
|
|||||||
{
|
{
|
||||||
if (index.column() == EventListModel::shortcutColumn) {
|
if (index.column() == EventListModel::shortcutColumn) {
|
||||||
auto *editor = new ShortcutWidget(parent);
|
auto *editor = new ShortcutWidget(parent);
|
||||||
connect(editor, &ShortcutWidget::done, this, &EventListDelegate::commitAndClose);
|
connect(editor, &ShortcutWidget::done, this, [this, editor] {
|
||||||
connect(editor, &ShortcutWidget::cancel, this, &EventListDelegate::close);
|
auto that = const_cast<EventListDelegate *>(this);
|
||||||
|
emit that->commitData(editor);
|
||||||
|
emit that->closeEditor(editor);
|
||||||
|
});
|
||||||
|
connect(editor, &ShortcutWidget::cancel, this, [this, editor] {
|
||||||
|
auto that = const_cast<EventListDelegate *>(this);
|
||||||
|
emit that->closeEditor(editor);
|
||||||
|
});
|
||||||
return editor;
|
return editor;
|
||||||
} else if (index.column() == EventListModel::connectColumn) {
|
} else if (index.column() == EventListModel::connectColumn) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -170,18 +177,4 @@ QSize EventListDelegate::sizeHint(const QStyleOptionViewItem &option, const QMod
|
|||||||
return QStyledItemDelegate::sizeHint(option, index);
|
return QStyledItemDelegate::sizeHint(option, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventListDelegate::commitAndClose()
|
|
||||||
{
|
|
||||||
if (auto *editor = qobject_cast<ShortcutWidget *>(sender())) {
|
|
||||||
emit commitData(editor);
|
|
||||||
emit closeEditor(editor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EventListDelegate::close()
|
|
||||||
{
|
|
||||||
if (auto *editor = qobject_cast<ShortcutWidget *>(sender()))
|
|
||||||
emit closeEditor(editor);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace QmlDesigner.
|
} // namespace QmlDesigner.
|
||||||
|
@@ -39,9 +39,6 @@ protected:
|
|||||||
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void close();
|
|
||||||
void commitAndClose();
|
|
||||||
|
|
||||||
static bool hasConnectionColumn(QObject *parent);
|
static bool hasConnectionColumn(QObject *parent);
|
||||||
static QRect connectButtonRect(const QStyleOptionViewItem &option);
|
static QRect connectButtonRect(const QStyleOptionViewItem &option);
|
||||||
};
|
};
|
||||||
|
@@ -51,18 +51,4 @@ bool NodeListDelegate::eventFilter(QObject *editor, QEvent *event)
|
|||||||
return QStyledItemDelegate::eventFilter(editor, event);
|
return QStyledItemDelegate::eventFilter(editor, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeListDelegate::commitAndClose()
|
|
||||||
{
|
|
||||||
if (auto *editor = qobject_cast<ShortcutWidget *>(sender())) {
|
|
||||||
emit commitData(editor);
|
|
||||||
emit closeEditor(editor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void NodeListDelegate::close()
|
|
||||||
{
|
|
||||||
if (auto *editor = qobject_cast<ShortcutWidget *>(sender()))
|
|
||||||
emit closeEditor(editor);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace QmlDesigner.
|
} // namespace QmlDesigner.
|
||||||
|
@@ -16,10 +16,6 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool eventFilter(QObject *editor, QEvent *event) override;
|
bool eventFilter(QObject *editor, QEvent *event) override;
|
||||||
|
|
||||||
private:
|
|
||||||
void close();
|
|
||||||
void commitAndClose();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QmlDesigner.
|
} // namespace QmlDesigner.
|
||||||
|
@@ -41,12 +41,12 @@ EasingCurveDialog::EasingCurveDialog(const QList<ModelNode> &frames, QWidget *pa
|
|||||||
{
|
{
|
||||||
setWindowFlag(Qt::Tool, true);
|
setWindowFlag(Qt::Tool, true);
|
||||||
|
|
||||||
auto tw = new QTabWidget;
|
m_tabWidget = new QTabWidget;
|
||||||
tw->setTabPosition(QTabWidget::East);
|
m_tabWidget->setTabPosition(QTabWidget::East);
|
||||||
tw->addTab(m_splineEditor, "Curve");
|
m_tabWidget->addTab(m_splineEditor, "Curve");
|
||||||
tw->addTab(m_text, "Text");
|
m_tabWidget->addTab(m_text, "Text");
|
||||||
|
|
||||||
connect(tw, &QTabWidget::currentChanged, this, &EasingCurveDialog::tabClicked);
|
connect(m_tabWidget, &QTabWidget::currentChanged, this, &EasingCurveDialog::tabClicked);
|
||||||
connect(m_text, &QPlainTextEdit::textChanged, this, &EasingCurveDialog::textChanged);
|
connect(m_text, &QPlainTextEdit::textChanged, this, &EasingCurveDialog::textChanged);
|
||||||
|
|
||||||
auto labelFont = m_label->font();
|
auto labelFont = m_label->font();
|
||||||
@@ -105,7 +105,7 @@ EasingCurveDialog::EasingCurveDialog(const QList<ModelNode> &frames, QWidget *pa
|
|||||||
grid->addLayout(vbox, 0, 0);
|
grid->addLayout(vbox, 0, 0);
|
||||||
grid->addWidget(presetBar, 0, 1, Qt::AlignBottom);
|
grid->addWidget(presetBar, 0, 1, Qt::AlignBottom);
|
||||||
|
|
||||||
grid->addWidget(tw);
|
grid->addWidget(m_tabWidget);
|
||||||
grid->addWidget(m_presets, 1, 1);
|
grid->addWidget(m_presets, 1, 1);
|
||||||
grid->addLayout(m_durationLayout, 2, 0);
|
grid->addLayout(m_durationLayout, 2, 0);
|
||||||
grid->addLayout(buttonLayout, 2, 1);
|
grid->addLayout(buttonLayout, 2, 1);
|
||||||
@@ -126,7 +126,6 @@ EasingCurveDialog::EasingCurveDialog(const QList<ModelNode> &frames, QWidget *pa
|
|||||||
connect(durationEdit, &QSpinBox::valueChanged, m_splineEditor, &SplineEditor::setDuration);
|
connect(durationEdit, &QSpinBox::valueChanged, m_splineEditor, &SplineEditor::setDuration);
|
||||||
connect(animateButton, &QPushButton::clicked, m_splineEditor, &SplineEditor::animate);
|
connect(animateButton, &QPushButton::clicked, m_splineEditor, &SplineEditor::animate);
|
||||||
|
|
||||||
|
|
||||||
resize(QSize(1421, 918));
|
resize(QSize(1421, 918));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,7 +184,7 @@ bool EasingCurveDialog::apply()
|
|||||||
}
|
}
|
||||||
AbstractView *view = m_frames.first().view();
|
AbstractView *view = m_frames.first().view();
|
||||||
|
|
||||||
return view->executeInTransaction("EasingCurveDialog::apply", [this](){
|
return view->executeInTransaction("EasingCurveDialog::apply", [this] {
|
||||||
auto expression = m_splineEditor->easingCurve().toString();
|
auto expression = m_splineEditor->easingCurve().toString();
|
||||||
for (const auto &frame : std::as_const(m_frames))
|
for (const auto &frame : std::as_const(m_frames))
|
||||||
frame.bindingProperty(m_easingCurveProperty).setExpression(expression);
|
frame.bindingProperty(m_easingCurveProperty).setExpression(expression);
|
||||||
@@ -201,30 +200,23 @@ void EasingCurveDialog::textChanged()
|
|||||||
|
|
||||||
void EasingCurveDialog::tabClicked(int id)
|
void EasingCurveDialog::tabClicked(int id)
|
||||||
{
|
{
|
||||||
if (auto tw = qobject_cast<const QTabWidget *>(sender())) {
|
const int seid = m_tabWidget->indexOf(m_splineEditor);
|
||||||
int seid = tw->indexOf(m_splineEditor);
|
|
||||||
if (seid == id) {
|
if (seid == id) {
|
||||||
for (int i = 0; i < m_durationLayout->count(); ++i) {
|
for (int i = 0; i < m_durationLayout->count(); ++i) {
|
||||||
auto *item = m_durationLayout->itemAt(i);
|
if (auto *widget = m_durationLayout->itemAt(i)->widget())
|
||||||
if (auto *widget = item->widget())
|
|
||||||
widget->show();
|
widget->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto curve = m_splineEditor->easingCurve();
|
auto curve = m_splineEditor->easingCurve();
|
||||||
curve.fromString(m_text->toPlainText());
|
curve.fromString(m_text->toPlainText());
|
||||||
m_splineEditor->setEasingCurve(curve);
|
m_splineEditor->setEasingCurve(curve);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < m_durationLayout->count(); ++i) {
|
for (int i = 0; i < m_durationLayout->count(); ++i) {
|
||||||
auto *item = m_durationLayout->itemAt(i);
|
if (auto *widget = m_durationLayout->itemAt(i)->widget())
|
||||||
if (auto *widget = item->widget())
|
|
||||||
widget->hide();
|
widget->hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto curve = m_splineEditor->easingCurve();
|
auto curve = m_splineEditor->easingCurve();
|
||||||
m_text->setPlainText(curve.toString());
|
m_text->setPlainText(curve.toString());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EasingCurveDialog::presetTabClicked(int id)
|
void EasingCurveDialog::presetTabClicked(int id)
|
||||||
|
@@ -9,9 +9,10 @@
|
|||||||
#include <modelnode.h>
|
#include <modelnode.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QHBoxLayout;
|
||||||
class QLabel;
|
class QLabel;
|
||||||
class QPlainTextEdit;
|
class QPlainTextEdit;
|
||||||
class QHBoxLayout;
|
class QTabWidget;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
@@ -33,32 +34,21 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
bool apply();
|
bool apply();
|
||||||
|
|
||||||
void textChanged();
|
void textChanged();
|
||||||
|
|
||||||
void tabClicked(int id);
|
void tabClicked(int id);
|
||||||
|
|
||||||
void presetTabClicked(int id);
|
void presetTabClicked(int id);
|
||||||
|
|
||||||
void buttonsClicked(QDialogButtonBox::StandardButton button);
|
void buttonsClicked(QDialogButtonBox::StandardButton button);
|
||||||
|
|
||||||
void updateEasingCurve(const EasingCurve &curve);
|
void updateEasingCurve(const EasingCurve &curve);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
QTabWidget *m_tabWidget = nullptr;
|
||||||
SplineEditor *m_splineEditor = nullptr;
|
SplineEditor *m_splineEditor = nullptr;
|
||||||
|
|
||||||
QPlainTextEdit *m_text = nullptr;
|
QPlainTextEdit *m_text = nullptr;
|
||||||
|
|
||||||
PresetEditor *m_presets = nullptr;
|
PresetEditor *m_presets = nullptr;
|
||||||
|
|
||||||
QHBoxLayout *m_durationLayout = nullptr;
|
QHBoxLayout *m_durationLayout = nullptr;
|
||||||
|
|
||||||
QDialogButtonBox *m_buttons = nullptr;
|
QDialogButtonBox *m_buttons = nullptr;
|
||||||
|
|
||||||
QLabel *m_label = nullptr;
|
QLabel *m_label = nullptr;
|
||||||
|
|
||||||
QList<ModelNode> m_frames;
|
QList<ModelNode> m_frames;
|
||||||
|
|
||||||
PropertyName m_easingCurveProperty;
|
PropertyName m_easingCurveProperty;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -62,11 +62,12 @@
|
|||||||
#include <projectexplorer/projectexplorerconstants.h>
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
#include <projectexplorer/projectmanager.h>
|
#include <projectexplorer/projectmanager.h>
|
||||||
#include <projectexplorer/target.h>
|
#include <projectexplorer/target.h>
|
||||||
#include <sqlitelibraryinitializer.h>
|
|
||||||
#include <qmldesignerbase/qmldesignerbaseplugin.h>
|
#include <qmldesignerbase/qmldesignerbaseplugin.h>
|
||||||
#include <qmljs/qmljsmodelmanagerinterface.h>
|
#include <qmljs/qmljsmodelmanagerinterface.h>
|
||||||
|
#include <sqlite/sqlitelibraryinitializer.h>
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
|
#include <utils/guard.h>
|
||||||
#include <utils/hostosinfo.h>
|
#include <utils/hostosinfo.h>
|
||||||
#include <utils/mimeconstants.h>
|
#include <utils/mimeconstants.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
@@ -82,9 +83,10 @@
|
|||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QWindow>
|
#include <QWindow>
|
||||||
|
|
||||||
#include "nanotrace/nanotrace.h"
|
|
||||||
#include <modelnodecontextmenu_helper.h>
|
#include <modelnodecontextmenu_helper.h>
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
static Q_LOGGING_CATEGORY(qmldesignerLog, "qtc.qmldesigner", QtWarningMsg)
|
static Q_LOGGING_CATEGORY(qmldesignerLog, "qtc.qmldesigner", QtWarningMsg)
|
||||||
|
|
||||||
using namespace QmlDesigner::Internal;
|
using namespace QmlDesigner::Internal;
|
||||||
@@ -162,7 +164,7 @@ public:
|
|||||||
SettingsPage settingsPage{externalDependencies};
|
SettingsPage settingsPage{externalDependencies};
|
||||||
DesignModeWidget mainWidget;
|
DesignModeWidget mainWidget;
|
||||||
QtQuickDesignerFactory m_qtQuickDesignerFactory;
|
QtQuickDesignerFactory m_qtQuickDesignerFactory;
|
||||||
bool blockEditorChange = false;
|
Utils::Guard m_ignoreChanges;
|
||||||
Utils::UniqueObjectPtr<QToolBar> toolBar;
|
Utils::UniqueObjectPtr<QToolBar> toolBar;
|
||||||
Utils::UniqueObjectPtr<QWidget> statusBar;
|
Utils::UniqueObjectPtr<QWidget> statusBar;
|
||||||
QHash<QString, TraceIdentifierData> m_traceIdentifierDataHash;
|
QHash<QString, TraceIdentifierData> m_traceIdentifierDataHash;
|
||||||
@@ -497,7 +499,7 @@ void QmlDesignerPlugin::hideDesigner()
|
|||||||
|
|
||||||
void QmlDesignerPlugin::changeEditor()
|
void QmlDesignerPlugin::changeEditor()
|
||||||
{
|
{
|
||||||
if (d->blockEditorChange)
|
if (d->m_ignoreChanges.isLocked())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
clearDesigner();
|
clearDesigner();
|
||||||
@@ -666,18 +668,12 @@ void QmlDesignerPlugin::enforceDelayedInitialize()
|
|||||||
|
|
||||||
DesignDocument *QmlDesignerPlugin::currentDesignDocument() const
|
DesignDocument *QmlDesignerPlugin::currentDesignDocument() const
|
||||||
{
|
{
|
||||||
if (d)
|
return d ? d->documentManager.currentDesignDocument() : nullptr;
|
||||||
return d->documentManager.currentDesignDocument();
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Internal::DesignModeWidget *QmlDesignerPlugin::mainWidget() const
|
Internal::DesignModeWidget *QmlDesignerPlugin::mainWidget() const
|
||||||
{
|
{
|
||||||
if (d)
|
return d ? &d->mainWidget : nullptr;
|
||||||
return &d->mainWidget;
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget *QmlDesignerPlugin::createProjectExplorerWidget(QWidget *parent) const
|
QWidget *QmlDesignerPlugin::createProjectExplorerWidget(QWidget *parent) const
|
||||||
@@ -687,21 +683,15 @@ QWidget *QmlDesignerPlugin::createProjectExplorerWidget(QWidget *parent) const
|
|||||||
|
|
||||||
void QmlDesignerPlugin::switchToTextModeDeferred()
|
void QmlDesignerPlugin::switchToTextModeDeferred()
|
||||||
{
|
{
|
||||||
QTimer::singleShot(0, this, [] () {
|
QTimer::singleShot(0, this, [] {
|
||||||
Core::ModeManager::activateMode(Core::Constants::MODE_EDIT);
|
Core::ModeManager::activateMode(Core::Constants::MODE_EDIT);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlDesignerPlugin::emitCurrentTextEditorChanged(Core::IEditor *editor)
|
void QmlDesignerPlugin::emitCurrentTextEditorChanged(Core::IEditor *editor)
|
||||||
{
|
{
|
||||||
d->blockEditorChange = true;
|
const std::lock_guard locker(d->m_ignoreChanges);
|
||||||
emit Core::EditorManager::instance()->currentEditorChanged(editor);
|
emit Core::EditorManager::instance()->currentEditorChanged(editor);
|
||||||
d->blockEditorChange = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlDesignerPlugin::emitAssetChanged(const QString &assetPath)
|
|
||||||
{
|
|
||||||
emit assetChanged(assetPath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double QmlDesignerPlugin::formEditorDevicePixelRatio()
|
double QmlDesignerPlugin::formEditorDevicePixelRatio()
|
||||||
@@ -717,7 +707,7 @@ double QmlDesignerPlugin::formEditorDevicePixelRatio()
|
|||||||
|
|
||||||
void QmlDesignerPlugin::contextHelp(const Core::IContext::HelpCallback &callback, const QString &id)
|
void QmlDesignerPlugin::contextHelp(const Core::IContext::HelpCallback &callback, const QString &id)
|
||||||
{
|
{
|
||||||
emitUsageStatisticsHelpRequested(id);
|
emitUsageStatistics(Constants::EVENT_HELP_REQUESTED + id);
|
||||||
QmlDesignerPlugin::instance()->viewManager().qmlJSEditorContextHelp(callback);
|
QmlDesignerPlugin::instance()->viewManager().qmlJSEditorContextHelp(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -733,7 +723,7 @@ void QmlDesignerPlugin::emitUsageStatistics(const QString &identifier)
|
|||||||
const int currentTime = privateInstance()->timer.elapsed();
|
const int currentTime = privateInstance()->timer.elapsed();
|
||||||
const int currentDuration = (currentTime - activeData.time);
|
const int currentDuration = (currentTime - activeData.time);
|
||||||
if (currentDuration < activeData.maxDuration)
|
if (currentDuration < activeData.maxDuration)
|
||||||
instance()->emitUsageStatisticsUsageDuration(activeData.newIdentifer, currentDuration);
|
emit instance()->usageStatisticsUsageDuration(activeData.newIdentifer, currentDuration);
|
||||||
|
|
||||||
privateInstance()->m_activeTraceIdentifierDataHash.remove(identifier);
|
privateInstance()->m_activeTraceIdentifierDataHash.remove(identifier);
|
||||||
}
|
}
|
||||||
@@ -761,11 +751,6 @@ void QmlDesignerPlugin::emitUsageStatisticsContextAction(const QString &identifi
|
|||||||
emitUsageStatistics(Constants::EVENT_ACTION_EXECUTED + identifier);
|
emitUsageStatistics(Constants::EVENT_ACTION_EXECUTED + identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlDesignerPlugin::emitUsageStatisticsHelpRequested(const QString &identifier)
|
|
||||||
{
|
|
||||||
emitUsageStatistics(Constants::EVENT_HELP_REQUESTED + identifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
AsynchronousImageCache &QmlDesignerPlugin::imageCache()
|
AsynchronousImageCache &QmlDesignerPlugin::imageCache()
|
||||||
{
|
{
|
||||||
return m_instance->d->projectManager.asynchronousImageCache();
|
return m_instance->d->projectManager.asynchronousImageCache();
|
||||||
@@ -776,32 +761,18 @@ void QmlDesignerPlugin::registerPreviewImageProvider(QQmlEngine *engine)
|
|||||||
m_instance->d->projectManager.registerPreviewImageProvider(engine);
|
m_instance->d->projectManager.registerPreviewImageProvider(engine);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool isParent(QWidget *parent, QWidget *widget)
|
|
||||||
{
|
|
||||||
if (!widget)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (widget == parent)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return isParent(parent, widget->parentWidget());
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlDesignerPlugin::trackWidgetFocusTime(QWidget *widget, const QString &identifier)
|
void QmlDesignerPlugin::trackWidgetFocusTime(QWidget *widget, const QString &identifier)
|
||||||
{
|
{
|
||||||
connect(qApp,
|
connect(qApp, &QApplication::focusChanged,
|
||||||
&QApplication::focusChanged,
|
widget, [widget, identifier](QWidget *from, QWidget *to) {
|
||||||
widget,
|
|
||||||
[widget, identifier](QWidget *from, QWidget *to) {
|
|
||||||
static QElapsedTimer widgetUsageTimer;
|
static QElapsedTimer widgetUsageTimer;
|
||||||
static QString lastIdentifier;
|
static QString lastIdentifier;
|
||||||
if (isParent(widget, to)) {
|
if (widget->isAncestorOf(to)) {
|
||||||
if (!lastIdentifier.isEmpty())
|
if (!lastIdentifier.isEmpty())
|
||||||
emitUsageStatisticsTime(lastIdentifier, widgetUsageTimer.elapsed());
|
emitUsageStatisticsTime(lastIdentifier, widgetUsageTimer.elapsed());
|
||||||
widgetUsageTimer.restart();
|
widgetUsageTimer.restart();
|
||||||
lastIdentifier = identifier;
|
lastIdentifier = identifier;
|
||||||
} else if (isParent(widget, from) && lastIdentifier == identifier) {
|
} else if (widget->isAncestorOf(from) && lastIdentifier == identifier) {
|
||||||
emitUsageStatisticsTime(identifier, widgetUsageTimer.elapsed());
|
emitUsageStatisticsTime(identifier, widgetUsageTimer.elapsed());
|
||||||
lastIdentifier.clear();
|
lastIdentifier.clear();
|
||||||
}
|
}
|
||||||
@@ -880,14 +851,13 @@ void QmlDesignerPlugin::closeFeedbackPopup()
|
|||||||
|
|
||||||
void QmlDesignerPlugin::emitUsageStatisticsTime(const QString &identifier, int elapsed)
|
void QmlDesignerPlugin::emitUsageStatisticsTime(const QString &identifier, int elapsed)
|
||||||
{
|
{
|
||||||
|
|
||||||
QTC_ASSERT(instance(), return);
|
QTC_ASSERT(instance(), return);
|
||||||
emit instance()->usageStatisticsUsageTimer(normalizeIdentifier(identifier), elapsed);
|
emit instance()->usageStatisticsUsageTimer(normalizeIdentifier(identifier), elapsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlDesignerPlugin::emitUsageStatisticsUsageDuration(const QString &identifier, int elapsed)
|
void QmlDesignerPlugin::emitUsageStatisticsUsageDuration(const QString &identifier, int elapsed)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(instance(), return );
|
QTC_ASSERT(instance(), return);
|
||||||
emit instance()->usageStatisticsUsageDuration(identifier, elapsed);
|
emit instance()->usageStatisticsUsageDuration(identifier, elapsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -66,15 +66,12 @@ public:
|
|||||||
void switchToTextModeDeferred();
|
void switchToTextModeDeferred();
|
||||||
void emitCurrentTextEditorChanged(Core::IEditor *editor);
|
void emitCurrentTextEditorChanged(Core::IEditor *editor);
|
||||||
|
|
||||||
void emitAssetChanged(const QString &assetPath);
|
|
||||||
|
|
||||||
static double formEditorDevicePixelRatio();
|
static double formEditorDevicePixelRatio();
|
||||||
|
|
||||||
static void contextHelp(const Core::IContext::HelpCallback &callback, const QString &id);
|
static void contextHelp(const Core::IContext::HelpCallback &callback, const QString &id);
|
||||||
|
|
||||||
static void emitUsageStatistics(const QString &identifier);
|
static void emitUsageStatistics(const QString &identifier);
|
||||||
static void emitUsageStatisticsContextAction(const QString &identifier);
|
static void emitUsageStatisticsContextAction(const QString &identifier);
|
||||||
static void emitUsageStatisticsHelpRequested(const QString &identifier);
|
|
||||||
static void emitUsageStatisticsTime(const QString &identifier, int elapsed);
|
static void emitUsageStatisticsTime(const QString &identifier, int elapsed);
|
||||||
static void emitUsageStatisticsUsageDuration(const QString &identifier, int elapsed);
|
static void emitUsageStatisticsUsageDuration(const QString &identifier, int elapsed);
|
||||||
|
|
||||||
|
@@ -45,6 +45,11 @@
|
|||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
static DesignDocument *currentDesignDocument()
|
||||||
|
{
|
||||||
|
return QmlDesignerPlugin::instance()->currentDesignDocument();
|
||||||
|
}
|
||||||
|
|
||||||
ShortCutManager::ShortCutManager()
|
ShortCutManager::ShortCutManager()
|
||||||
: QObject()
|
: QObject()
|
||||||
, m_exportAsImageAction(tr("Export as &Image..."))
|
, m_exportAsImageAction(tr("Export as &Image..."))
|
||||||
@@ -58,9 +63,7 @@ ShortCutManager::ShortCutManager()
|
|||||||
, m_duplicateAction(tr("&Duplicate"))
|
, m_duplicateAction(tr("&Duplicate"))
|
||||||
, m_selectAllAction(tr("Select &All"))
|
, m_selectAllAction(tr("Select &All"))
|
||||||
, m_escapeAction(this)
|
, m_escapeAction(this)
|
||||||
{
|
{}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShortCutManager::registerActions(const Core::Context &qmlDesignerMainContext,
|
void ShortCutManager::registerActions(const Core::Context &qmlDesignerMainContext,
|
||||||
const Core::Context &qmlDesignerFormEditorContext,
|
const Core::Context &qmlDesignerFormEditorContext,
|
||||||
@@ -327,16 +330,24 @@ void ShortCutManager::selectAll()
|
|||||||
void ShortCutManager::connectUndoActions(DesignDocument *designDocument)
|
void ShortCutManager::connectUndoActions(DesignDocument *designDocument)
|
||||||
{
|
{
|
||||||
if (designDocument) {
|
if (designDocument) {
|
||||||
connect(designDocument, &DesignDocument::undoAvailable, this, &ShortCutManager::undoAvailable);
|
connect(designDocument, &DesignDocument::undoAvailable, this,
|
||||||
connect(designDocument, &DesignDocument::redoAvailable, this, &ShortCutManager::redoAvailable);
|
[this, designDocument](bool isAvailable) {
|
||||||
|
if (currentDesignDocument() == designDocument)
|
||||||
|
m_undoAction.setEnabled(isAvailable);
|
||||||
|
});
|
||||||
|
connect(designDocument, &DesignDocument::redoAvailable, this,
|
||||||
|
[this, designDocument](bool isAvailable) {
|
||||||
|
if (currentDesignDocument() == designDocument)
|
||||||
|
m_redoAction.setEnabled(isAvailable);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShortCutManager::disconnectUndoActions(DesignDocument *designDocument)
|
void ShortCutManager::disconnectUndoActions(DesignDocument *designDocument)
|
||||||
{
|
{
|
||||||
if (currentDesignDocument()) {
|
if (designDocument) {
|
||||||
disconnect(designDocument, &DesignDocument::undoAvailable, this, &ShortCutManager::undoAvailable);
|
disconnect(designDocument, &DesignDocument::undoAvailable, this, nullptr);
|
||||||
disconnect(designDocument, &DesignDocument::redoAvailable, this, &ShortCutManager::redoAvailable);
|
disconnect(designDocument, &DesignDocument::redoAvailable, this, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -351,29 +362,6 @@ void ShortCutManager::updateUndoActions(DesignDocument *designDocument)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DesignDocument *ShortCutManager::currentDesignDocument() const
|
|
||||||
{
|
|
||||||
return QmlDesignerPlugin::instance()->currentDesignDocument();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShortCutManager::undoAvailable(bool isAvailable)
|
|
||||||
{
|
|
||||||
auto documentController = qobject_cast<DesignDocument*>(sender());
|
|
||||||
if (currentDesignDocument() &&
|
|
||||||
currentDesignDocument() == documentController) {
|
|
||||||
m_undoAction.setEnabled(isAvailable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShortCutManager::redoAvailable(bool isAvailable)
|
|
||||||
{
|
|
||||||
auto documentController = qobject_cast<DesignDocument*>(sender());
|
|
||||||
if (currentDesignDocument() &&
|
|
||||||
currentDesignDocument() == documentController) {
|
|
||||||
m_redoAction.setEnabled(isAvailable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShortCutManager::goIntoComponent()
|
void ShortCutManager::goIntoComponent()
|
||||||
{
|
{
|
||||||
if (currentDesignDocument()
|
if (currentDesignDocument()
|
||||||
|
@@ -30,8 +30,6 @@ public:
|
|||||||
void connectUndoActions(DesignDocument *designDocument);
|
void connectUndoActions(DesignDocument *designDocument);
|
||||||
void disconnectUndoActions(DesignDocument *designDocument);
|
void disconnectUndoActions(DesignDocument *designDocument);
|
||||||
void updateUndoActions(DesignDocument *designDocument);
|
void updateUndoActions(DesignDocument *designDocument);
|
||||||
DesignDocument *currentDesignDocument() const;
|
|
||||||
|
|
||||||
void updateActions(Core::IEditor* editor);
|
void updateActions(Core::IEditor* editor);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -43,8 +41,6 @@ private:
|
|||||||
void duplicateSelected();
|
void duplicateSelected();
|
||||||
void paste();
|
void paste();
|
||||||
void selectAll();
|
void selectAll();
|
||||||
void undoAvailable(bool isAvailable);
|
|
||||||
void redoAvailable(bool isAvailable);
|
|
||||||
void goIntoComponent();
|
void goIntoComponent();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@@ -74,7 +74,7 @@ void FileDownloader::start()
|
|||||||
QNetworkReply *reply = Utils::NetworkAccessManager::instance()->get(request);
|
QNetworkReply *reply = Utils::NetworkAccessManager::instance()->get(request);
|
||||||
m_reply = reply;
|
m_reply = reply;
|
||||||
|
|
||||||
QNetworkReply::connect(reply, &QNetworkReply::readyRead, this, [this, reply]() {
|
QNetworkReply::connect(reply, &QNetworkReply::readyRead, this, [this, reply] {
|
||||||
bool isDownloadingFile = false;
|
bool isDownloadingFile = false;
|
||||||
QString contentType;
|
QString contentType;
|
||||||
if (!reply->hasRawHeader("Content-Type")) {
|
if (!reply->hasRawHeader("Content-Type")) {
|
||||||
@@ -115,7 +115,7 @@ void FileDownloader::start()
|
|||||||
emit reply->redirectAllowed();
|
emit reply->redirectAllowed();
|
||||||
});
|
});
|
||||||
|
|
||||||
QNetworkReply::connect(reply, &QNetworkReply::finished, this, [this, reply]() {
|
QNetworkReply::connect(reply, &QNetworkReply::finished, this, [this, reply] {
|
||||||
if (reply->error()) {
|
if (reply->error()) {
|
||||||
if (reply->error() != QNetworkReply::OperationCanceledError) {
|
if (reply->error() != QNetworkReply::OperationCanceledError) {
|
||||||
qWarning() << Q_FUNC_INFO << m_url << reply->errorString();
|
qWarning() << Q_FUNC_INFO << m_url << reply->errorString();
|
||||||
@@ -282,7 +282,7 @@ void FileDownloader::doProbeUrl()
|
|||||||
emit reply->redirectAllowed();
|
emit reply->redirectAllowed();
|
||||||
});
|
});
|
||||||
|
|
||||||
QNetworkReply::connect(reply, &QNetworkReply::finished, this, [this, reply]() {
|
QNetworkReply::connect(reply, &QNetworkReply::finished, this, [this, reply] {
|
||||||
if (reply->error())
|
if (reply->error())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -295,18 +295,14 @@ void FileDownloader::doProbeUrl()
|
|||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
});
|
});
|
||||||
|
|
||||||
QNetworkReply::connect(reply,
|
QNetworkReply::connect(reply, &QNetworkReply::errorOccurred,
|
||||||
&QNetworkReply::errorOccurred,
|
this, [this, reply](QNetworkReply::NetworkError code) {
|
||||||
this,
|
|
||||||
[this](QNetworkReply::NetworkError code) {
|
|
||||||
|
|
||||||
if (QQmlData::wasDeleted(this)) {
|
if (QQmlData::wasDeleted(this)) {
|
||||||
qDebug() << Q_FUNC_INFO << "FileDownloader was deleted.";
|
qDebug() << Q_FUNC_INFO << "FileDownloader was deleted.";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << Q_FUNC_INFO << "Network error:" << code
|
qDebug() << Q_FUNC_INFO << "Network error:" << code << reply->errorString();
|
||||||
<< qobject_cast<QNetworkReply *>(sender())->errorString();
|
|
||||||
|
|
||||||
m_available = false;
|
m_available = false;
|
||||||
emit availableChanged();
|
emit availableChanged();
|
||||||
|
@@ -216,14 +216,16 @@ void FileExtractor::extract()
|
|||||||
m_targetFolder = m_targetPath.toString() + "/" + m_archiveName;
|
m_targetFolder = m_targetPath.toString() + "/" + m_archiveName;
|
||||||
|
|
||||||
// If the target directory already exists, remove it and its content
|
// If the target directory already exists, remove it and its content
|
||||||
QDir targetDir(m_targetFolder);
|
|
||||||
if (targetDir.exists() && m_clearTargetPathContents)
|
|
||||||
targetDir.removeRecursively();
|
|
||||||
|
|
||||||
if (m_alwaysCreateDir) {
|
QTC_ASSERT(!m_targetPath.isEmpty(), return );
|
||||||
|
|
||||||
|
FilePath targetFilePath = FilePath::fromUserInput(m_targetFolder);
|
||||||
|
if (targetFilePath.exists() && m_clearTargetPathContents)
|
||||||
|
targetFilePath.removeRecursively();
|
||||||
|
|
||||||
// Create a new directory to generate a proper creation date
|
// Create a new directory to generate a proper creation date
|
||||||
targetDir.mkdir(m_targetFolder);
|
if (m_alwaysCreateDir)
|
||||||
}
|
targetFilePath.createDir();
|
||||||
|
|
||||||
const auto sourceAndCommand = Unarchiver::sourceAndCommand(m_sourceFile);
|
const auto sourceAndCommand = Unarchiver::sourceAndCommand(m_sourceFile);
|
||||||
QTC_ASSERT(sourceAndCommand, return);
|
QTC_ASSERT(sourceAndCommand, return);
|
||||||
@@ -261,6 +263,8 @@ void FileExtractor::extract()
|
|||||||
void QmlDesigner::FileExtractor::removeTempTargetPath()
|
void QmlDesigner::FileExtractor::removeTempTargetPath()
|
||||||
{
|
{
|
||||||
if (m_isTempTargetPath && m_targetPath.exists()) {
|
if (m_isTempTargetPath && m_targetPath.exists()) {
|
||||||
|
QTC_ASSERT(m_targetPath.toString().startsWith(QDir::tempPath()), qDebug() << m_targetPath;
|
||||||
|
return );
|
||||||
m_targetPath.removeRecursively();
|
m_targetPath.removeRecursively();
|
||||||
m_isTempTargetPath = false;
|
m_isTempTargetPath = false;
|
||||||
}
|
}
|
||||||
|