Merge remote-tracking branch 'origin/6.0'

Change-Id: Ie46e0028f0dca9f3ddc45ed8794ba6cddd97df26
This commit is contained in:
Eike Ziller
2021-10-28 10:31:51 +02:00
77 changed files with 506 additions and 575 deletions

View File

@@ -1,59 +1,24 @@
cmake_minimum_required(VERSION 3.14) cmake_minimum_required(VERSION 3.16)
project(transitions VERSION 0.1 LANGUAGES CXX) project(transitions VERSION 0.1 LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Quick REQUIRED) find_package(Qt6 6.2 COMPONENTS Quick REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Quick REQUIRED)
set(PROJECT_SOURCES qt_add_executable(transitionsexample
main.cpp main.cpp
qml.qrc
) )
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) qt_add_qml_module(transitionsexample
qt_add_executable(transitions URI transitions
MANUAL_FINALIZATION VERSION 1.0
${PROJECT_SOURCES} QML_FILES main.qml Page.qml
) RESOURCES qt-logo.png
# Define target properties for Android with Qt 6 as:
# set_property(TARGET transitions APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
# ${CMAKE_CURRENT_SOURCE_DIR}/android)
# For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation
else()
if(ANDROID)
add_library(transitions SHARED
${PROJECT_SOURCES}
)
# Define properties for Android with Qt 5 after find_package() calls as:
# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
else()
add_executable(transitions
${PROJECT_SOURCES}
)
endif()
endif()
target_compile_definitions(transitions
PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
target_link_libraries(transitions
PRIVATE Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Quick)
set_target_properties(transitions PROPERTIES
MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
) )
if(QT_VERSION_MAJOR EQUAL 6) target_compile_definitions(transitionsexample
qt_import_qml_plugins(transitions) PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
qt_finalize_executable(transitions) target_link_libraries(transitionsexample
endif() PRIVATE Qt6::Quick)

View File

@@ -48,19 +48,18 @@
** **
****************************************************************************/ ****************************************************************************/
import QtQuick 2.15 import QtQuick
import QtQuick.Window 2.15
Rectangle { Rectangle {
id: page id: page
state: "State1" anchors.fill: parent
color: "#ffffff"
Image { Image {
id: icon id: icon
x: 20 x: 20
y: 20 y: 20
source: "images/qt-logo.png" source: "qt-logo.png"
fillMode: Image.PreserveAspectFit
} }
Rectangle { Rectangle {
@@ -88,7 +87,6 @@ Rectangle {
} }
} }
Rectangle { Rectangle {
id: middleRightRect id: middleRightRect
width: 55 width: 55
@@ -112,7 +110,6 @@ Rectangle {
} }
} }
Rectangle { Rectangle {
id: bottomLeftRect id: bottomLeftRect
width: 55 width: 55
@@ -160,6 +157,7 @@ Rectangle {
} }
} }
] ]
transitions: [ transitions: [
Transition { Transition {
id: toState1 id: toState1
@@ -202,7 +200,7 @@ Rectangle {
PropertyAnimation { PropertyAnimation {
target: icon target: icon
property: "y" property: "y"
easing.bezierCurve: [0.233,0.161,0.264,0.997,0.393,0.997,0.522,0.997,0.555,0.752,0.61,0.75,0.664,0.748,0.736,1,0.775,1,0.814,0.999,0.861,0.901,0.888,0.901,0.916,0.901,0.923,0.995,1,1] easing.type: Easing.OutBounce
duration: 1006 duration: 1006
} }
} }
@@ -215,7 +213,7 @@ Rectangle {
PropertyAnimation { PropertyAnimation {
target: icon target: icon
property: "x" property: "x"
easing.bezierCurve: [0.233,0.161,0.264,0.997,0.393,0.997,0.522,0.997,0.555,0.752,0.61,0.75,0.664,0.748,0.736,1,0.775,1,0.814,0.999,0.861,0.901,0.888,0.901,0.916,0.901,0.923,0.995,1,1] easing.type: Easing.OutBounce
duration: 1006 duration: 1006
} }
} }
@@ -234,7 +232,7 @@ Rectangle {
PropertyAnimation { PropertyAnimation {
target: icon target: icon
property: "y" property: "y"
easing.bezierCurve: [0.455,0.03,0.515,0.955,1,1] easing.type: Easing.InOutQuad
duration: 2000 duration: 2000
} }
} }
@@ -247,7 +245,7 @@ Rectangle {
PropertyAnimation { PropertyAnimation {
target: icon target: icon
property: "x" property: "x"
easing.bezierCurve: [0.455,0.03,0.515,0.955,1,1] easing.type: Easing.InOutQuad
duration: 2000 duration: 2000
} }
} }
@@ -257,10 +255,3 @@ Rectangle {
} }
] ]
} }
/*##^##
Designer {
D{i:0;height:480;width:640}D{i:1}D{i:16;transitionDuration:2000}D{i:24;transitionDuration:2000}
D{i:32;transitionDuration:2000}
}
##^##*/

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -54,19 +54,10 @@
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
if (qEnvironmentVariableIsEmpty("QTGLESSTREAM_DISPLAY")) {
qputenv("QT_QPA_EGLFS_PHYSICAL_WIDTH", QByteArray("213"));
qputenv("QT_QPA_EGLFS_PHYSICAL_HEIGHT", QByteArray("120"));
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
}
QGuiApplication app(argc, argv); QGuiApplication app(argc, argv);
QQmlApplicationEngine engine; QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml")); const QUrl url(u"qrc:/transitions/main.qml"_qs);
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) { &app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl) if (!obj && url == objUrl)

View File

@@ -48,24 +48,16 @@
** **
****************************************************************************/ ****************************************************************************/
import QtQuick 2.15 import QtQuick
import QtQuick.Window 2.15
Window { Window {
width: 640 width: 640
height: 480 height: 480
visible: true visible: true
title: qsTr("Hello World") title: qsTr("Transitions")
Page { Page {
id: page id: page
anchors.fill: parent anchors.fill: parent
color: "#ffffff"
} }
} }
/*##^##
Designer {
D{i:0;formeditorZoom:0.75}
}
##^##*/

View File

@@ -1,7 +0,0 @@
<RCC>
<qresource prefix="/">
<file>main.qml</file>
<file>images/qt-logo.png</file>
<file>Page.qml</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

View File

@@ -43,7 +43,6 @@
\li \l{File System} \li \l{File System}
\li \l{Open Documents} \li \l{Open Documents}
\endlist \endlist
\li \l{Managing Workspaces}
\li \l{Viewing Output} \li \l{Viewing Output}
\endlist \endlist
\li \l{Configuring Qt Creator} \li \l{Configuring Qt Creator}

View File

@@ -30,33 +30,29 @@
\title Creating a Qt Quick Application \title Creating a Qt Quick Application
This tutorial uses preset components and illustrates basic concepts of This tutorial illustrates basic concepts of \l{Qt Quick}. For more
\l{Qt Quick}. information about the UI choices you have, see \l{User Interfaces}.
For more information about the UI choices you have, see \l{User Interfaces}.
This tutorial describes how to use \QC to implement states and This tutorial describes how to use \QC to implement \l{Qt Quick States}
transitions. We create an application that displays a Qt logo that moves {states} and \l{Animation and Transitions in Qt Quick}{transitions}
between three rectangles on the page when you click them. when using Qt 6 as the minimum Qt version and CMake as the build system.
\image qmldesigner-tutorial.png "States and transitions example" We use the \l{Working in Edit Mode}{Edit mode} to create an application
that moves a Qt logo between three rectangles when you click them.
For more information about developing Qt Quick applications in the Design \image qtquick-tutorial.gif "Transitions example"
mode, see \l{Developing Qt Quick Applications}.
For examples of using Qt Quick Controls, see \l{Qt Quick Controls Examples}. For more examples, see \l{Qt Quick Examples and Tutorials}.
You can develop Qt Quick applications also in \QDS. For more information,
see \l{Qt Design Studio Manual}.
\include qtquick-tutorial-create-empty-project.qdocinc qtquick empty application \include qtquick-tutorial-create-empty-project.qdocinc qtquick empty application
\QC generates a component file, \e main.qml, and opens it in the \QC generates a component file, \e main.qml, and opens it in the
\l {Text Editor} view. Select \uicontrol Design to open the file in \uicontrol Edit mode.
the \l {Form Editor} view.
\note The visibility of Design views depends on the selected workspace. \section1 Deploying Applications
To open hidden views, select \uicontrol View > \uicontrol Views
in the \uicontrol Design mode. For more information about moving
views around, see \l {Managing Workspaces}.
\section1 Creating the Main View
The main view of the application displays a Qt logo inside a rectangle in The main view of the application displays a Qt logo inside a rectangle in
the top left corner of the view and two empty rectangles. the top left corner of the view and two empty rectangles.
@@ -64,256 +60,122 @@
We use the \e qt-logo.png image in this tutorial, but you can also use We use the \e qt-logo.png image in this tutorial, but you can also use
any other image or a component, instead. any other image or a component, instead.
For the image to appear when you run the application, you must specify it
as a resource in the \c RESOURCES section of \e CMakeLists.txt file that
the wizard created for you:
\quotefromfile transitions/CMakeLists.txt
\skipto qt_add_qml_module
\printuntil )
\section1 Creating Custom QML Types
Because the \l Window QML type requires states to be added into child
components, we use the wizard to create a custom QML type called
\e Page that we will refer to from \e main.qml.
To create a custom QML type:
\list 1 \list 1
\li Select \uicontrol File > \uicontrol {New File or Project} >
\li In \uicontrol Library > \uicontrol Components > \uicontrol {Files and Classes} > \uicontrol Qt >
\uicontrol {Default Components} > \uicontrol Basic, select \uicontrol {QML File (Qt Quick 2)}.
\uicontrol Rectangle and drag and drop it to \e Window in \li Select \uicontrol Choose to open the \uicontrol Location dialog.
\uicontrol Navigator. \li In the \uicontrol {File name} field, enter a name for the custom
QML type. In this example, we call the type \e Page.
\li Select the \uicontrol Rectangle instance in \l Navigator, and enter \li Select \uicontrol Next to open the \uicontrol {Project Management}
\e page in the \uicontrol ID field in \l Properties. dialog.
\li Select \uicontrol Finish to create \e Page.qml.
\li In \uicontrol Layout, select the
\inlineimage icons/anchor-fill.png "Fill anchor button"
fill anchor button to anchor the rectangle to the window on all
sides.
\li Select \uicontrol Library > \uicontrol Assets > \inlineimage plus.png
to locate qt-logo.png (or your own image) and add it to the
project folder.
\li Drag and drop the image from \uicontrol Assets to \e page in
\uicontrol Navigator. \QC automatically generates an instance
of the \l{Images}{Image} component for you, with the image as
the source image.
\image qmldesigner-tutorial-user-icon.png "Image properties"
\li In \uicontrol Properties, edit the properties of the Image
component instance:
\list a
\li In the \uicontrol ID field, enter \e icon.
\li In the \uicontrol Position field, set \uicontrol X and
\uicontrol Y to \e 20.
\endlist
\li In \uicontrol Library > \uicontrol Components >
\uicontrol {Default Components} > \uicontrol Basic, select
\uicontrol Rectangle and drag and drop it to \e page in
\uicontrol Navigator.
\image qmldesigner-tutorial-topleftrect.png "Rectangle properties"
\li In \uicontrol Properties, edit the properties of the Rectangle
component instance:
\list a
\li In the \uicontrol ID field, enter \e topLeftRect.
\li In the \uicontrol Size field, set \uicontrol W and
\uicontrol H to values that match the image size
(\e 55 and \e 41).
\li Select the \uicontrol Color field, and then select the
\inlineimage icons/transparent.png "Transparent button"
button in the \l{Picking colors}{color picker} to make
the rectangle transparent.
\li In the \uicontrol {Border color} field, set the border
color to \e #808080 to make the rectangle visible on
the background.
\li Click \uicontrol {Layout}, and then click the
\inlineimage icons/anchor-top.png "Top anchor button"
top and \inlineimage icons/anchor-left.png "Left anchor button"
left anchor buttons to anchor the rectangle to the top left
corner of the page.
\li In the \uicontrol Margin field, select \e 20 for both anchors.
\image qmldesigner-tutorial-topleftrect-layout.png "Anchor margins"
\endlist
\li Drag and drop a \uicontrol {Mouse Area} component from the
\uicontrol Library to \e topLeftRect in \uicontrol Navigator.
\li Click \uicontrol {Layout}, and then click the
\inlineimage icons/anchor-fill.png "Fill anchor button"
button to anchor the mouse area to its parent.
\li In the \uicontrol Navigator, copy \e topLeftRect (by pressing
\key {Ctrl+C}) and paste it to \e page in \uicontrol Navigator
twice (by pressing \key {Ctrl+V}). \QC renames the new instances
of the component \e topLeftRect1 and \e topLeftRect2.
\li Select \e topLeftRect1 and edit its properties:
\list a
\li In the \uicontrol ID field, enter \e middleRightRect.
\li In \uicontrol {Layout}, select the
\inlineimage icons/anchor-center-vertical.png "Vertical center anchor button"
vertical center anchor button and then the
\inlineimage icons/anchor-right.png "Right anchor button"
right anchor button to anchor the rectangle
to the middle right margin of its parent.
\li In the \uicontrol Margin field, select \e 20 for the right
anchor and \e 0 for the vertical center anchor.
\endlist
\li Select \e topLeftRect2 and edit its properties:
\list a
\li In the \uicontrol ID field, enter \e bottomLeftRect.
\li In \uicontrol {Layout}, select the
\inlineimage icons/anchor-bottom.png
(\uicontrol Bottom) and \inlineimage icons/anchor-left.png
(\uicontrol Left) anchor buttons to anchor the rectangle
to the bottom left margin of its parent.
\li In the \uicontrol Margin field, select \e 20 for both anchors.
\endlist
\li Press \key {Ctrl+S} to save the changes.
\endlist \endlist
To check your code, you can view your \e {main.qml} file in the \QC opens \e Page.qml in the \uicontrol Edit mode. It contains a root item
\uicontrol {Text Editor} and compare it with the \e {main.qml} of the type \l Item that we replace with a \l Rectangle type. We give the
example file. type the ID \e page, anchor it to the parent item on all sides, and set
its color to white:
The UI design is now ready. \quotefromfile transitions/Page.qml
\skipto import
\printuntil color
\image qmldesigner-tutorial-ui-ready.png "Transitions UI" Because we develop with Qt 6, where version numbers are not used with
modules, we remove the version number from the import statement.
For more information about the views you used, see: When you start typing the QML type name, \QC suggests available types
and properties to \l{Completing Code}{complete the code}.
\list Select the light bulb icon \inlineimage refactormarker.png
\li \l {Form Editor} next to the type name to open the \l{Editing Rectangles}
\li \l Library {Qt Quick Toolbar for rectangles}. You can use it to specify
\li \l Navigator rectangle properties, such as color, transparency, and gradients.
\li \l Properties
\endlist \image qml-toolbar-rectangle.png "Qt Quick Toolbar for rectangles"
Next, we add an \l Image type with \e qt-logo.png as the source. We
position the image in the top-left corner of the rectangle:
\printuntil }
You can use the \l{Previewing Images}{Qt Quick Toolbar for images} to
specify image properties, such as source file and fill mode.
\image qml-toolbar-image.png "Logo visible in Qt Quick Toolbar for images"
We now create the rectangles that the image will move between. Their size
should match the image size and they should be transparent, so that the
image is visible. We set the border color to light gray to make the
rectangles visible:
\printuntil border.color
We anchor the rectangles to their parent to position them in its
top-left and and bottom-left corners, as well as the vertical center
of its right edge. The following code snippet anchors a rectangle to
the top-left corner of its parent:
\printuntil anchors.topMargin
We add a \l MouseArea type to make the rectangle clickable by users:
\printuntil anchors.fill
To check your code, you can compare it with the \e {Page.qml} example file.
Next, we will make the image move between the rectangles when users click Next, we will make the image move between the rectangles when users click
them by \l{Adding States}{adding states} and by connecting mouse clicks them, by adding states and by connecting mouse clicks to state changes.
to state changes.
Because the Window component requires states to be added into child
components, we must first move \e page into a separate component.
\section1 Turning Page into a Custom Component
To turn \e page into a custom component, right-click it
in \uicontrol Navigator or \uicontrol {Form Editor}, and select
\uicontrol {Move Component into Separate File} in the context menu.
\image qmldesigner-tutorial-page-component.png "Move page component instance into a separate file"
\list 1
\li In \uicontrol {Component name}, enter \e Page.
\li In \uicontrol {Property assignments for main.qml} select both
check boxes to preserve the appearance of the UI.
\li Select \uicontrol OK to create a file called \e Page.qml that
defines the Page custom component and to add an instance of it
into \e main.qml.
\endlist
\section1 Connecting Mouse Clicks to State Changes \section1 Connecting Mouse Clicks to State Changes
To make the image move between the rectangles when users click them, we add To make the image move between the rectangles when users click them, we add
states to the Page component, where we change the values of the \c x and states to the Page component, where we change the values of the \c x and
\c y properties of \c y properties of \e icon to match those of the middle right and top left
\e icon to match those of the middle right and top left rectangles. Then, rectangles. To make sure that the image is displayed within the rectangle
we connect the \c onClicked signals of the mouse areas to the state changes. when the view is scaled on different sizes of screens, we \e bind the values
of the \c x and \c y properties of \e icon to those of the rectangles:
To make sure that the image is displayed within the rectangle when the view \dots
is scaled on different sizes of screens, we bind the values of the \c x and \skipto states:
\c y properties of \e icon to those of the rectangles. \printuntil ]
\list 1 Then, we connect the \c onClicked signals of the mouse areas to the state
\li Right-click \e page in \uicontrol Navigator, and select changes:
\uicontrol {Go into Component} in the context menu to open
\e Page.qml in \uicontrol {Form Editor}.
\li In the \uicontrol States view, select \uicontrol {Create New State}
three times to create \e State1, \e State2, and \e State3.
\li Select \e State1 in \uicontrol States.
\li Select \inlineimage icons/action-icon.png
to open the \uicontrol Actions menu, and then select
\uicontrol {Set as Default} to display \e State1 when
the application starts.
\li Select \e State2 in \uicontrol States.
\li Select \e icon in \uicontrol Navigator to display its properties
in \uicontrol Properties.
\li In \uicontrol {Geometry - 2D} > \uicontrol Position > \uicontrol X,
select \inlineimage icons/action-icon.png "Actions button"
, and then select \uicontrol {Set Binding} to open
\uicontrol {Binding Editor}.
\li Select the \e middleRightRect component and the \e x property
to bind the \e x property value of \e icon to that of
\e middleRightRect.
\image qmldesigner-tutorial-bindings.png "Binding Editor"
\li Select \uicontrol OK to create the binding.
\li Repeat for \uicontrol Y, but set the binding as
\e middleRightRect.y.
\li Select \e State3 in \uicontrol States, and bind the \e x and \e y
property values of \e icon to those of \e bottomLeftRect
(\e bottomLeftRect.x and \e bottomLeftRect.y).
\li In \l {Connection View} > \uicontrol Connections, click the
\inlineimage plus.png
button to create a new connection.
\image qmldesigner-tutorial-connections.png "Connections tab"
\li Double-click the value in the \uicontrol Target column, and select
\e mouseArea in the list.
\li In the \uicontrol {Signal Handler} column, select \e onClicked.
\li In the \uicontrol Action column, select \e {page.state = 'State1'}.
\li Create two more connections to connect the \c onClicked signal of
\uicontrol mouseArea1 to State2, and that of \uicontrol mouseArea2
to State3.
\li Press \key {Ctrl+R} to run the application.
\endlist
Click the rectangles to move the Qt logo from one rectangle to another. \quotefromfile transitions/Page.qml
\skipto Connections {
\printuntil }
If you develop with Qt 6, you must specify the connections as Because we develop with Qt 6, we must specify the connections as functions.
functions. This is currently not supported in \uicontrol {Connections},
so you must do it in \uicontrol {Text Editor}. For example:
\code \section1 Adding Page to the Main View
MouseArea {
id: mouseArea
anchors.fill: parent
Connections { We now open \e main.qml for editing and add an instance of the Page custom
target: mouseArea component to it:
function onClicked()
{
page.state = "State1"
}
}
}
\endcode
For more information about the views you used, see: \quotefromfile transitions/main.qml
\skipto import
\printuntil /^\ {0}\}/
\list Press \key {Ctrl+R} to run the application, and click the rectangles to
\li \l States move the Qt logo from one rectangle to another.
\li \l{Setting Bindings}
\li \l{Connecting Components to Signals}
\endlist
\section1 Animating Transitions \section1 Animating Transitions
@@ -321,56 +183,29 @@
the image bounces back when it moves to \e middleRightRect and eases into the image bounces back when it moves to \e middleRightRect and eases into
\e bottomLeftRect. \e bottomLeftRect.
\list 1 We specify transitions for switching from each state to the other two
\li In the \uicontrol {Transition Editor} view, click the states:
\inlineimage plus.png
button to create a new transition.
\li Click the \inlineimage animation.png
button to specify transitions for switching to each state.
\image qmldesigner-tutorial-transition-settings.png "Transition Settings dialog"
\li In the \uicontrol {Transition ID} field, enter \e toState1.
\li In the \uicontrol From field, select \e State2 and \e State3.
\li In the \uicontrol To field, select \e State1.
\li Click \inlineimage plus.png
to add transitions for switching to \e State2 and \e State3, with
the IDs \e toState2 and \e toState3.
\li Select \uicontrol Close to save the settings and return to
\uicontrol {Transition Editor}.
\li Select \e toState2 in the list of transitions.
\image qmldesigner-tutorial-transitions.png "Transition Editor view"
\li Pull the right edge of the blue bar next to \e icon to frame 1000
to specify that the x and y coordinates of the image change
linearly over a duration of 1 second.
\li Select the \uicontrol x property, and click
\inlineimage curve_editor.png
to change the easing curve type from linear to easeOutBounce
(\c{[0.233,0.161,0.264,0.997,0.393,0.997,0.522,0.997,0.555,0.752,
0.61,0.75,0.664,0.748,0.736,1,0.775,1,0.814,0.999,0.861,0.901,0.888,
0.901,0.916,0.901,0.923,0.995,1,1]})
in \uicontrol {Easing Curve Editor}.
\image qmldesigner-tutorial-easing-curves.png "Easing Curve Editor"
\li Select the \uicontrol y property and set the easing curve for it,
too.
\li Close \uicontrol {Easing Curve Editor} to return to
\uicontrol {Transition Editor}, and select \e toState3
in the list of transitions.
\li Pull the right edge of the blue bar next to \e icon to frame 2000
to specify that the x and y coordinates of the image change
linearly over a duration of 2 seconds.
\li In \uicontrol {Easing Curve Editor}, change the easing curve type
from linear to easeInOutQuad (\c{[0.455,0.03,0.515,0.955,1,1]}).
\li Select \e toState1 in the list of transitions, and pull the blue
bar to frame 200 to specify that the x and y coordinates of the
image change linearly over a duration of 200 milliseconds.
\li Press \key {Ctrl+R} to run the application.
\endlist
For more information about the views you used, see: \quotefromfile transitions/Page.qml
\skipto transitions:
\printuntil },
\list We change the easing curve type for transitions to \e State2 from linear to
\li \l{Editing Easing Curves} \c Easing.OutBounce to create the bounce effect:
\li \l{Transition Editor}
\endlist
Click the rectangles to view the animated transitions. \printuntil },
\note You can use the \l{Previewing Animation}
{Qt Quick Toolbar for animation} to specify the
easing curve type and animation duration.
\image qml-toolbar-animation.png "Qt Quick Toolbar for animation"
Then, we change the easing curve type for transitions to \e State2 from
linear to \c Easing.InOutQuad to create the easing effect:
\printuntil /^\ {0}\}/
Press \key {Ctrl+R} to run the application, and click the rectangles to
view the animated transitions.
*/ */

View File

@@ -46,16 +46,18 @@
\li Select \uicontrol Next (or \uicontrol Continue on \macos) to open \li Select \uicontrol Next (or \uicontrol Continue on \macos) to open
the \uicontrol {Define Build System} dialog. the \uicontrol {Define Build System} dialog.
\li In the \uicontrol {Build system} field, select the build system to \li In the \uicontrol {Build system} field, select \l {Setting Up CMake}
use for building and running the project: \l qmake, {CMake} as the build system to use for building and running the
\l {Setting Up CMake}{CMake}, or \l {Setting Up Qbs}{Qbs}. project.
\note If you select \l qmake, the instructions for configuring the
project won't apply.
\li Select \uicontrol Next to open the \li Select \uicontrol Next to open the
\uicontrol {Define Project Details} dialog. \uicontrol {Define Project Details} dialog.
\li In the \uicontrol {Screen resolution} field, select the initial \li In the \uicontrol {Minimal required Qt version} field, select
size of the UI. You can easily change the screen size later Qt 6.2.
in \l Properties.
\li Select \uicontrol Next to open the \uicontrol {Translation File} \li Select \uicontrol Next to open the \uicontrol {Translation File}
dialog. dialog.
@@ -63,9 +65,10 @@
\li Select \uicontrol Next to use the default settings and to open \li Select \uicontrol Next to use the default settings and to open
the \uicontrol {Kit Selection} dialog. the \uicontrol {Kit Selection} dialog.
\li Select \l{glossary-buildandrun-kit}{kits} for the platforms that \li Select Qt 6.2 or later \l{glossary-buildandrun-kit}{kits} for the
you want to build the application for. To build applications for platforms that you want to build the application for. To build
mobile devices, select kits for Android ARM and iPhone OS. applications for mobile devices, select kits also for Android and
iOS.
\note Kits are listed if they have been specified in \uicontrol \note Kits are listed if they have been specified in \uicontrol
Tools > \uicontrol Options > \uicontrol Kits (on Windows and Linux) Tools > \uicontrol Options > \uicontrol Kits (on Windows and Linux)
@@ -82,8 +85,7 @@
\endlist \endlist
For more information about the settings that you skipped and the other For more information about the settings that you skipped and the other
templates available, see \l{Creating Qt Quick Applications}. wizard templates available, see \l{Creating Qt Quick Applications}.
//! [qtquick empty application] //! [qtquick empty application]
*/ */
Con

View File

@@ -26,7 +26,7 @@
/*! /*!
\page creator-open-documents-view.html \page creator-open-documents-view.html
\previouspage creator-file-system-view.html \previouspage creator-file-system-view.html
\nextpage creator-project-managing-workspaces.html \nextpage creator-output-panes.html
\title Open Documents \title Open Documents

View File

@@ -93,7 +93,6 @@
\li \l{Selecting Modes}{Mode selector} \li \l{Selecting Modes}{Mode selector}
\li \l{Working with Sidebars}{Sidebars} \li \l{Working with Sidebars}{Sidebars}
\li \l{Browsing Project Contents}{Views} \li \l{Browsing Project Contents}{Views}
\li \l{Managing Workspaces}{Workspaces}
\li \l{Viewing Output}{Output panes} \li \l{Viewing Output}{Output panes}
\endlist \endlist
@@ -350,7 +349,7 @@
\previouspage creator-views.html \previouspage creator-views.html
\nextpage creator-highlighting.html \nextpage creator-highlighting.html
\else \else
\previouspage creator-project-managing-workspaces.html \previouspage creator-open-documents-view.html
\nextpage creator-configuring.html \nextpage creator-configuring.html
\endif \endif

View File

@@ -35,7 +35,12 @@
\title Browsing Project Contents \title Browsing Project Contents
You can organize \QC views in \l {Working with Sidebars}{sidebars} or as You can organize \QC views in \l {Working with Sidebars}{sidebars} or as
\l {Managing Workspaces}{workspaces}, depending on the \l{Selecting Modes} \if defined(qtdesignstudio)
\l {Managing Workspaces}{workspaces},
\else
workspaces
\endif
depending on the \l{Selecting Modes}
{mode} you are working in. Only views that are relevant to a mode are {mode} you are working in. Only views that are relevant to a mode are
available in it. available in it.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

View File

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 65 KiB

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

View File

@@ -26,15 +26,11 @@
/*! /*!
\page creator-project-managing-workspaces.html \page creator-project-managing-workspaces.html
\previouspage creator-open-documents-view.html \previouspage creator-open-documents-view.html
\if defined(qtdesignstudio)
\nextpage creator-project-managing-sessions.html \nextpage creator-project-managing-sessions.html
\else
\nextpage creator-output-panes.html
\endif
\title Managing Workspaces \title Managing Workspaces
In the Design and Debug modes, you can arrange a set of \QC In the \uicontrol Design mode, you can arrange a set of \QC
views as a \e workspace on the screen. views as a \e workspace on the screen.
To detach views: To detach views:

View File

@@ -1221,7 +1221,15 @@ ValuesChangedCommand NodeInstanceServer::createValuesChangedCommand(const QVecto
if (instance.isValid()) { if (instance.isValid()) {
QVariant propertyValue = instance.property(propertyName); QVariant propertyValue = instance.property(propertyName);
if (QMetaType::isRegistered(propertyValue.userType()) && supportedVariantType(propertyValue.type())) { bool isValid = QMetaType::isRegistered(propertyValue.userType())
&& supportedVariantType(propertyValue.type());
if (!isValid && propertyValue.userType() == 0) {
// If the property is QVariant type, invalid variant can be a valid value
const QMetaObject *mo = instance.internalObject()->metaObject();
const int idx = mo->indexOfProperty(propertyName);
isValid = idx >= 0 && mo->property(idx).userType() == QMetaType::QVariant;
}
if (isValid) {
valueVector.append(PropertyValueContainer(instance.instanceId(), propertyName, valueVector.append(PropertyValueContainer(instance.instanceId(), propertyName,
propertyValue, PropertyName())); propertyValue, PropertyName()));
} }

View File

@@ -76,13 +76,13 @@ StudioControls.TextField {
id: colorLogic id: colorLogic
backendValue: lineEdit.backendValue backendValue: lineEdit.backendValue
onValueFromBackendChanged: { onValueFromBackendChanged: {
if (colorLogic.valueFromBackend === undefined) if (colorLogic.valueFromBackend === undefined) {
return lineEdit.text = ""
if (writeValueManually) {
lineEdit.text = convertColorToString(colorLogic.valueFromBackend)
} else { } else {
lineEdit.text = colorLogic.valueFromBackend if (writeValueManually)
lineEdit.text = convertColorToString(colorLogic.valueFromBackend)
else
lineEdit.text = colorLogic.valueFromBackend
} }
__dirty = false __dirty = false
} }

View File

@@ -7,17 +7,17 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt6 6.2 COMPONENTS Quick REQUIRED) find_package(Qt6 6.2 COMPONENTS Quick REQUIRED)
qt_add_executable(%{ProjectName} qt_add_executable(%{TargetName}
main.cpp main.cpp
) )
qt_add_qml_module(%{ProjectName} qt_add_qml_module(%{TargetName}
URI %{ProjectName} URI %{ProjectName}
VERSION 1.0 VERSION 1.0
QML_FILES main.qml %{AdditionalQmlFiles} QML_FILES main.qml %{AdditionalQmlFiles}
) )
target_compile_definitions(%{ProjectName} target_compile_definitions(%{TargetName}
PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>) PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
target_link_libraries(%{ProjectName} target_link_libraries(%{TargetName}
PRIVATE Qt6::Quick) PRIVATE Qt6::Quick)

View File

@@ -27,7 +27,8 @@
{ "key": "HasTranslation", "value": "%{JS: value('TsFileName') !== ''}" }, { "key": "HasTranslation", "value": "%{JS: value('TsFileName') !== ''}" },
{ "key": "SetQPAPhysicalSize", "value": "%{UseVirtualKeyboardByDefault}" }, { "key": "SetQPAPhysicalSize", "value": "%{UseVirtualKeyboardByDefault}" },
{ "key": "AdditionalQmlFiles", "value": "" }, { "key": "AdditionalQmlFiles", "value": "" },
{ "key": "AdditionalQmlFilesQbs", "value": "" } { "key": "AdditionalQmlFilesQbs", "value": "" },
{ "key": "TargetName", "value": "%{JS: 'app' + value('ProjectName')}" }
], ],
"pages": "pages":

View File

@@ -25,6 +25,9 @@
#include "CoreTypes.h" #include "CoreTypes.h"
#include "Symbols.h" #include "Symbols.h"
#include "Names.h" #include "Names.h"
#include <QList>
#include <map> #include <map>
#include <set> #include <set>
#include <algorithm> #include <algorithm>
@@ -844,3 +847,15 @@ void Control::addSymbol(Symbol *symbol)
{ {
d->symbols.push_back(symbol); d->symbols.push_back(symbol);
} }
const Name *Control::toName(const QList<const Name *> &names)
{
const Name *n = nullptr;
for (int i = names.size() - 1; i >= 0; --i) {
if (! n)
n = names.at(i);
else
n = qualifiedNameId(names.at(i), n);
}
return n;
}

View File

@@ -218,6 +218,8 @@ public:
bool hasSymbol(Symbol *symbol) const; bool hasSymbol(Symbol *symbol) const;
void addSymbol(Symbol *symbol); void addSymbol(Symbol *symbol);
const Name *toName(const QList<const Name *> &names);
private: private:
class Data; class Data;
friend class Data; friend class Data;

View File

@@ -22,7 +22,6 @@ HEADERS += \
src/lib/format_p.h \ src/lib/format_p.h \
src/lib/htmlhighlighter.h \ src/lib/htmlhighlighter.h \
src/lib/keywordlist_p.h \ src/lib/keywordlist_p.h \
src/lib/ksyntaxhighlighting_export.h \
src/lib/matchresult_p.h \ src/lib/matchresult_p.h \
src/lib/repository.h \ src/lib/repository.h \
src/lib/repository_p.h \ src/lib/repository_p.h \

View File

@@ -283,8 +283,21 @@ public:
number->size())); number->size()));
} }
} }
temps.append(control()->templateNameId(identifier(name->identifier()), name->isSpecialization(),
args.data(), args.size())); const FullySpecifiedType ty = rewrite->env->apply(name->identifier(), rewrite);
const Name * const minName = ty->isNamedType() ? ty->asNamedType()->name() : name;
const TemplateNameId * const newTemplateNameId = control()->templateNameId(
identifier(minName->identifier()), name->isSpecialization(), args.data(),
args.size());
const QList<const Name *> names = disassembledName(minName);
if (names.size() == 1) {
temps.append(newTemplateNameId);
} else {
const Name * const newBaseName = control()->toName(names.mid(0, names.size() - 1));
const Name * const fullName = control()->qualifiedNameId(newBaseName,
newTemplateNameId);
temps.append(fullName);
}
} }
void visit(const DestructorNameId *name) override void visit(const DestructorNameId *name) override
@@ -317,6 +330,36 @@ public: // attributes
SubstitutionEnvironment *env; SubstitutionEnvironment *env;
RewriteType rewriteType; RewriteType rewriteType;
RewriteName rewriteName; RewriteName rewriteName;
private:
static QList<const Name *> disassembledName(const Name *name)
{
class NameDisassembler : public NameVisitor
{
public:
QList<const Name *> names() const { return m_names; }
void visit(const AnonymousNameId *n) override { m_names << n; }
virtual void visit(const Identifier *n) override { m_names << n; }
virtual void visit(const TemplateNameId *n) override { m_names << n; }
virtual void visit(const DestructorNameId *n) override { m_names << n; }
virtual void visit(const OperatorNameId *n) override { m_names << n; }
virtual void visit(const ConversionNameId *n) override { m_names << n; }
virtual void visit(const SelectorNameId *n) override { m_names << n; }
virtual void visit(const QualifiedNameId *n) override
{
if (n->base())
n->base()->accept(this);
n->name()->accept(this);
}
private:
QList<const Name *> m_names;
};
NameDisassembler nd;
nd.accept(name);
return nd.names();
}
}; };
SubstitutionEnvironment::SubstitutionEnvironment() SubstitutionEnvironment::SubstitutionEnvironment()

View File

@@ -241,19 +241,6 @@ static bool symbolIdentical(Symbol *s1, Symbol *s2)
return QByteArray(s1->fileName()) == QByteArray(s2->fileName()); return QByteArray(s1->fileName()) == QByteArray(s2->fileName());
} }
static const Name *toName(const QList<const Name *> &names, Control *control)
{
const Name *n = nullptr;
for (int i = names.size() - 1; i >= 0; --i) {
if (! n)
n = names.at(i);
else
n = control->qualifiedNameId(names.at(i), n);
}
return n;
}
static bool isInlineNamespace(ClassOrNamespace *con, const Name *name) static bool isInlineNamespace(ClassOrNamespace *con, const Name *name)
{ {
const QList<LookupItem> items = con->find(name); const QList<LookupItem> items = con->find(name);
@@ -282,12 +269,12 @@ const Name *LookupContext::minimalName(Symbol *symbol, ClassOrNamespace *target,
// eliminate inline namespaces // eliminate inline namespaces
QList<const Name *> minimal = names; QList<const Name *> minimal = names;
for (int i = minimal.size() - 2; i >= 0; --i) { for (int i = minimal.size() - 2; i >= 0; --i) {
const Name *candidate = toName(minimal.mid(0, i + 1), control); const Name *candidate = control->toName(minimal.mid(0, i + 1));
if (isInlineNamespace(target, candidate)) if (isInlineNamespace(target, candidate))
minimal.removeAt(i); minimal.removeAt(i);
} }
return toName(minimal, control); return control->toName(minimal);
} }
return nullptr; return nullptr;

View File

@@ -819,15 +819,6 @@ FilePath FilePath::symLinkTarget() const
return FilePath::fromString(info.symLinkTarget()); return FilePath::fromString(info.symLinkTarget());
} }
FilePath FilePath::mapToGlobalPath() const
{
if (needsDevice()) {
QTC_ASSERT(s_deviceHooks.mapToGlobalPath, return {});
return s_deviceHooks.mapToGlobalPath(*this);
}
return *this;
}
QString FilePath::mapToDevicePath() const QString FilePath::mapToDevicePath() const
{ {
if (needsDevice()) { if (needsDevice()) {
@@ -1182,11 +1173,11 @@ QString FilePath::calcRelativePath(const QString &absolutePath, const QString &a
*/ */
FilePath FilePath::onDevice(const FilePath &deviceTemplate) const FilePath FilePath::onDevice(const FilePath &deviceTemplate) const
{ {
if (!deviceTemplate.needsDevice())
return mapToGlobalPath();
const bool sameDevice = m_scheme == deviceTemplate.m_scheme && m_host == deviceTemplate.m_host; const bool sameDevice = m_scheme == deviceTemplate.m_scheme && m_host == deviceTemplate.m_host;
if (sameDevice)
return *this;
// TODO: converting paths between different non local devices is still unsupported // TODO: converting paths between different non local devices is still unsupported
QTC_CHECK(!needsDevice() || sameDevice); QTC_CHECK(!needsDevice());
FilePath res; FilePath res;
res.m_scheme = deviceTemplate.m_scheme; res.m_scheme = deviceTemplate.m_scheme;
res.m_host = deviceTemplate.m_host; res.m_host = deviceTemplate.m_host;

View File

@@ -162,9 +162,6 @@ public:
QDir::Filters filters = QDir::NoFilter, QDir::Filters filters = QDir::NoFilter,
QDirIterator::IteratorFlags flags = QDirIterator::NoIteratorFlags) const; QDirIterator::IteratorFlags flags = QDirIterator::NoIteratorFlags) const;
[[nodiscard]] FilePath mapToGlobalPath() const;
[[nodiscard]] QString mapToDevicePath() const;
// makes sure that capitalization of directories is canonical // makes sure that capitalization of directories is canonical
// on Windows and macOS. This is rarely needed. // on Windows and macOS. This is rarely needed.
[[nodiscard]] FilePath normalizedPathName() const; [[nodiscard]] FilePath normalizedPathName() const;
@@ -194,6 +191,7 @@ private:
friend class ::tst_fileutils; friend class ::tst_fileutils;
static QString calcRelativePath(const QString &absolutePath, const QString &absoluteAnchorPath); static QString calcRelativePath(const QString &absolutePath, const QString &absoluteAnchorPath);
void setFromString(const QString &filepath); void setFromString(const QString &filepath);
[[nodiscard]] QString mapToDevicePath() const;
QString m_scheme; QString m_scheme;
QString m_host; QString m_host;

View File

@@ -359,49 +359,89 @@ public:
} }
}; };
static QList<AstNode> getAstPath(const AstNode &root, const Range &range) class AstPathCollector
{ {
QList<AstNode> path; public:
QList<AstNode> queue{root}; AstPathCollector(const AstNode &root, const Range &range) : m_root(root), m_range(range) {}
bool isRoot = true;
while (!queue.isEmpty()) { QList<AstNode> collectPath()
AstNode curNode = queue.takeFirst(); {
if (!isRoot && !curNode.hasRange()) if (!m_root.isValid())
continue; return {};
if (curNode.range() == range) visitNode(m_root, true);
return path << curNode; return m_done ? m_path : m_longestSubPath;
if (isRoot || curNode.range().contains(range)) { }
path << curNode;
const auto children = curNode.children();
if (!children)
break;
if (curNode.kind() == "Function" || curNode.role() == "expression") {
// Functions and expressions can contain implicit nodes that make the list unsorted.
// They cannot be ignored, as we need to consider them in certain contexts.
// Therefore, the binary search cannot be used here.
queue = *children;
} else {
queue.clear();
// Class and struct nodes can contain implicit constructors, destructors and private:
// operators, which appear at the end of the list, but whose range is the same void visitNode(const AstNode &node, bool isRoot = false)
// as the class name. Therefore, we must force them not to compare less to {
// anything else. if (!isRoot && (!node.hasRange() || !node.range().contains(m_range)))
static const auto leftOfRange = [](const AstNode &node, const Range &range) { return;
return node.range().isLeftOf(range) && !node.arcanaContains(" implicit "); m_path << node;
};
for (auto it = std::lower_bound(children->cbegin(), children->cend(), range, class PathDropper {
leftOfRange); public:
it != children->cend() && !range.isLeftOf(it->range()); ++it) { PathDropper(AstPathCollector &collector) : m_collector(collector) {};
queue << *it; ~PathDropper() {
} if (m_collector.m_done)
return;
if (m_collector.m_path.size() > m_collector.m_longestSubPath.size())
m_collector.m_longestSubPath = m_collector.m_path;
m_collector.m_path.removeLast();
}
private:
AstPathCollector &m_collector;
} pathDropper(*this);
// Still traverse the children, because they could have the same range.
if (node.range() == m_range)
m_done = true;
const auto children = node.children();
if (!children)
return;
QList<AstNode> childrenToCheck;
if (node.kind() == "Function" || node.role() == "expression") {
// Functions and expressions can contain implicit nodes that make the list unsorted.
// They cannot be ignored, as we need to consider them in certain contexts.
// Therefore, the binary search cannot be used here.
childrenToCheck = *children;
} else {
for (auto it = std::lower_bound(children->cbegin(), children->cend(), m_range,
leftOfRange);
it != children->cend() && !m_range.isLeftOf(it->range()); ++it) {
childrenToCheck << *it;
} }
} }
isRoot = false;
const bool wasDone = m_done;
for (const AstNode &child : qAsConst(childrenToCheck)) {
visitNode(child);
if (m_done && !wasDone)
break;
}
} }
return path;
static bool leftOfRange(const AstNode &node, const Range &range)
{
// Class and struct nodes can contain implicit constructors, destructors and
// operators, which appear at the end of the list, but whose range is the same
// as the class name. Therefore, we must force them not to compare less to
// anything else.
return node.range().isLeftOf(range) && !node.arcanaContains(" implicit ");
};
const AstNode &m_root;
const Range &m_range;
QList<AstNode> m_path;
QList<AstNode> m_longestSubPath;
bool m_done = false;
};
static QList<AstNode> getAstPath(const AstNode &root, const Range &range)
{
return AstPathCollector(root, range).collectPath();
} }
static QList<AstNode> getAstPath(const AstNode &root, const Position &pos) static QList<AstNode> getAstPath(const AstNode &root, const Position &pos)
@@ -521,8 +561,10 @@ static BaseClientInterface *clientInterface(Project *project, const Utils::FileP
const CppEditor::ClangdSettings settings(CppEditor::ClangdProjectSettings(project).settings()); const CppEditor::ClangdSettings settings(CppEditor::ClangdProjectSettings(project).settings());
if (!settings.indexingEnabled()) if (!settings.indexingEnabled())
indexingOption += "=0"; indexingOption += "=0";
Utils::CommandLine cmd{settings.clangdFilePath(), {indexingOption, "--limit-results=0", const QString headerInsertionOption = QString("--header-insertion=")
"--clang-tidy=0"}}; + (settings.autoIncludeHeaders() ? "iwyu" : "never");
Utils::CommandLine cmd{settings.clangdFilePath(), {indexingOption, headerInsertionOption,
"--limit-results=0", "--clang-tidy=0"}};
if (settings.workerThreadLimit() != 0) if (settings.workerThreadLimit() != 0)
cmd.addArg("-j=" + QString::number(settings.workerThreadLimit())); cmd.addArg("-j=" + QString::number(settings.workerThreadLimit()));
if (!jsonDbDir.isEmpty()) if (!jsonDbDir.isEmpty())
@@ -2332,7 +2374,7 @@ static void semanticHighlighter(QFutureInterface<HighlightingResult> &future,
return false; return false;
for (auto it = path.rbegin() + 1; it != path.rend(); ++it) { for (auto it = path.rbegin() + 1; it != path.rend(); ++it) {
if (it->kind() == "Call" || it->kind() == "CXXConstruct" if (it->kind() == "Call" || it->kind() == "CXXConstruct"
|| it->kind() == "MemberInitializer") { || it->kind() == "MemberInitializer" || it->kind() == "CXXOperatorCall") {
return true; return true;
} }
if (it->kind().endsWith("Cast") && it->hasConstType()) if (it->kind().endsWith("Cast") && it->hasConstType())

View File

@@ -1040,7 +1040,7 @@ void ClangdTestHighlighting::test_data()
QTest::newRow("typedef as underlying type in enum declaration") << 424 << 21 << 424 << 39 QTest::newRow("typedef as underlying type in enum declaration") << 424 << 21 << 424 << 39
<< QList<int>{C_TYPE} << 0; << QList<int>{C_TYPE} << 0;
QTest::newRow("argument to user-defined subscript operator") << 434 << 12 << 434 << 17 QTest::newRow("argument to user-defined subscript operator") << 434 << 12 << 434 << 17
<< QList<int>{C_PARAMETER} << 0; << QList<int>{C_PARAMETER, C_OUTPUT_ARGUMENT} << 0;
QTest::newRow("partial class template specialization") << 553 << 25 << 553 << 28 QTest::newRow("partial class template specialization") << 553 << 25 << 553 << 28
<< QList<int>{C_TYPE, C_DECLARATION} << 0; << QList<int>{C_TYPE, C_DECLARATION} << 0;
QTest::newRow("using declaration for function") << 556 << 10 << 556 << 13 QTest::newRow("using declaration for function") << 556 << 10 << 556 << 13
@@ -1237,6 +1237,14 @@ void ClangdTestHighlighting::test_data()
<< QList<int>{C_LOCAL, C_OUTPUT_ARGUMENT} << 0; << QList<int>{C_LOCAL, C_OUTPUT_ARGUMENT} << 0;
QTest::newRow("override attribute") << 186 << 28 << 186 << 36 << QList<int>{C_KEYWORD} << 0; QTest::newRow("override attribute") << 186 << 28 << 186 << 36 << QList<int>{C_KEYWORD} << 0;
QTest::newRow("final attribute") << 187 << 33 << 187 << 38 << QList<int>{C_KEYWORD} << 0; QTest::newRow("final attribute") << 187 << 33 << 187 << 38 << QList<int>{C_KEYWORD} << 0;
QTest::newRow("non-const argument to named lambda") << 827 << 10 << 827 << 13
<< QList<int>{C_LOCAL, C_OUTPUT_ARGUMENT} << 0;
QTest::newRow("const argument to named lambda") << 828 << 10 << 828 << 13
<< QList<int>{C_LOCAL} << 0;
QTest::newRow("non-const argument to unnamed lambda") << 829 << 18 << 829 << 21
<< QList<int>{C_LOCAL, C_OUTPUT_ARGUMENT} << 0;
QTest::newRow("const argument to unnamed lambda") << 830 << 16 << 830 << 19
<< QList<int>{C_LOCAL} << 0;
} }
void ClangdTestHighlighting::test() void ClangdTestHighlighting::test()

View File

@@ -818,3 +818,14 @@ void staticMemberFuncTest() {
int i; int i;
s.staticFunc(i); s.staticFunc(i);
} }
void lambdaArgTest()
{
const auto foo1 = [](int &) {};
const auto foo2 = [](int) {};
int val;
foo1(val);
foo2(val);
[](int &) {}(val);
[](int) {}(val);
}

View File

@@ -144,7 +144,7 @@ MakeInstallCommand CMakeProject::makeInstallCommand(const Target *target,
if (bc) if (bc)
buildDirectory = bc->buildDirectory(); buildDirectory = bc->buildDirectory();
cmd.arguments << "--build" << buildDirectory.onDevice(cmd.command).mapToDevicePath() cmd.arguments << "--build" << buildDirectory.onDevice(cmd.command).path()
<< "--target" << installTarget << config; << "--target" << installTarget << config;
cmd.environment.set("DESTDIR", QDir::toNativeSeparators(installRoot)); cmd.environment.set("DESTDIR", QDir::toNativeSeparators(installRoot));

View File

@@ -69,6 +69,7 @@ static QString clangdSettingsKey() { return QLatin1String("ClangdSettings"); }
static QString useClangdKey() { return QLatin1String("UseClangd"); } static QString useClangdKey() { return QLatin1String("UseClangd"); }
static QString clangdPathKey() { return QLatin1String("ClangdPath"); } static QString clangdPathKey() { return QLatin1String("ClangdPath"); }
static QString clangdIndexingKey() { return QLatin1String("ClangdIndexing"); } static QString clangdIndexingKey() { return QLatin1String("ClangdIndexing"); }
static QString clangdHeaderInsertionKey() { return QLatin1String("ClangdHeaderInsertion"); }
static QString clangdThreadLimitKey() { return QLatin1String("ClangdThreadLimit"); } static QString clangdThreadLimitKey() { return QLatin1String("ClangdThreadLimit"); }
static QString clangdDocumentThresholdKey() { return QLatin1String("ClangdDocumentThreshold"); } static QString clangdDocumentThresholdKey() { return QLatin1String("ClangdDocumentThreshold"); }
static QString clangdUseGlobalSettingsKey() { return QLatin1String("useGlobalSettings"); } static QString clangdUseGlobalSettingsKey() { return QLatin1String("useGlobalSettings"); }
@@ -405,6 +406,7 @@ QVariantMap ClangdSettings::Data::toMap() const
if (executableFilePath != fallbackClangdFilePath()) if (executableFilePath != fallbackClangdFilePath())
map.insert(clangdPathKey(), executableFilePath.toString()); map.insert(clangdPathKey(), executableFilePath.toString());
map.insert(clangdIndexingKey(), enableIndexing); map.insert(clangdIndexingKey(), enableIndexing);
map.insert(clangdHeaderInsertionKey(), autoIncludeHeaders);
map.insert(clangdThreadLimitKey(), workerThreadLimit); map.insert(clangdThreadLimitKey(), workerThreadLimit);
map.insert(clangdDocumentThresholdKey(), documentUpdateThreshold); map.insert(clangdDocumentThresholdKey(), documentUpdateThreshold);
return map; return map;
@@ -415,6 +417,7 @@ void ClangdSettings::Data::fromMap(const QVariantMap &map)
useClangd = map.value(useClangdKey(), false).toBool(); useClangd = map.value(useClangdKey(), false).toBool();
executableFilePath = FilePath::fromString(map.value(clangdPathKey()).toString()); executableFilePath = FilePath::fromString(map.value(clangdPathKey()).toString());
enableIndexing = map.value(clangdIndexingKey(), true).toBool(); enableIndexing = map.value(clangdIndexingKey(), true).toBool();
autoIncludeHeaders = map.value(clangdHeaderInsertionKey(), false).toBool();
workerThreadLimit = map.value(clangdThreadLimitKey(), 0).toInt(); workerThreadLimit = map.value(clangdThreadLimitKey(), 0).toInt();
documentUpdateThreshold = map.value(clangdDocumentThresholdKey(), 500).toInt(); documentUpdateThreshold = map.value(clangdDocumentThresholdKey(), 500).toInt();
} }

View File

@@ -110,6 +110,7 @@ public:
int workerThreadLimit = 0; int workerThreadLimit = 0;
bool useClangd = false; bool useClangd = false;
bool enableIndexing = true; bool enableIndexing = true;
bool autoIncludeHeaders = false;
int documentUpdateThreshold = 500; int documentUpdateThreshold = 500;
}; };
@@ -121,6 +122,7 @@ public:
static void setDefaultClangdPath(const Utils::FilePath &filePath); static void setDefaultClangdPath(const Utils::FilePath &filePath);
Utils::FilePath clangdFilePath() const; Utils::FilePath clangdFilePath() const;
bool indexingEnabled() const { return m_data.enableIndexing; } bool indexingEnabled() const { return m_data.enableIndexing; }
bool autoIncludeHeaders() const { return m_data.autoIncludeHeaders; }
int workerThreadLimit() const { return m_data.workerThreadLimit; } int workerThreadLimit() const { return m_data.workerThreadLimit; }
int documentUpdateThreshold() const { return m_data.documentUpdateThreshold; } int documentUpdateThreshold() const { return m_data.documentUpdateThreshold; }
@@ -150,6 +152,7 @@ inline bool operator==(const ClangdSettings::Data &s1, const ClangdSettings::Dat
&& s1.executableFilePath == s2.executableFilePath && s1.executableFilePath == s2.executableFilePath
&& s1.workerThreadLimit == s2.workerThreadLimit && s1.workerThreadLimit == s2.workerThreadLimit
&& s1.enableIndexing == s2.enableIndexing && s1.enableIndexing == s2.enableIndexing
&& s1.autoIncludeHeaders == s2.autoIncludeHeaders
&& s1.documentUpdateThreshold == s2.documentUpdateThreshold; && s1.documentUpdateThreshold == s2.documentUpdateThreshold;
} }
inline bool operator!=(const ClangdSettings::Data &s1, const ClangdSettings::Data &s2) inline bool operator!=(const ClangdSettings::Data &s1, const ClangdSettings::Data &s2)

View File

@@ -197,6 +197,7 @@ class ClangdSettingsWidget::Private
public: public:
QCheckBox useClangdCheckBox; QCheckBox useClangdCheckBox;
QCheckBox indexingCheckBox; QCheckBox indexingCheckBox;
QCheckBox autoIncludeHeadersCheckBox;
QSpinBox threadLimitSpinBox; QSpinBox threadLimitSpinBox;
QSpinBox documentUpdateThreshold; QSpinBox documentUpdateThreshold;
Utils::PathChooser clangdChooser; Utils::PathChooser clangdChooser;
@@ -217,6 +218,9 @@ ClangdSettingsWidget::ClangdSettingsWidget(const ClangdSettings::Data &settingsD
"If background indexing is enabled, global symbol searches will yield\n" "If background indexing is enabled, global symbol searches will yield\n"
"more accurate results, at the cost of additional CPU load when\n" "more accurate results, at the cost of additional CPU load when\n"
"the project is first opened.")); "the project is first opened."));
d->autoIncludeHeadersCheckBox.setChecked(settings.autoIncludeHeaders());
d->autoIncludeHeadersCheckBox.setToolTip(tr(
"Controls whether clangd may insert header files as part of symbol completion."));
d->threadLimitSpinBox.setValue(settings.workerThreadLimit()); d->threadLimitSpinBox.setValue(settings.workerThreadLimit());
d->threadLimitSpinBox.setSpecialValueText("Automatic"); d->threadLimitSpinBox.setSpecialValueText("Automatic");
d->documentUpdateThreshold.setMinimum(50); d->documentUpdateThreshold.setMinimum(50);
@@ -237,6 +241,8 @@ ClangdSettingsWidget::ClangdSettingsWidget(const ClangdSettings::Data &settingsD
formLayout->addRow(QString(), &d->versionWarningLabel); formLayout->addRow(QString(), &d->versionWarningLabel);
const auto indexingLabel = new QLabel(tr("Enable background indexing:")); const auto indexingLabel = new QLabel(tr("Enable background indexing:"));
formLayout->addRow(indexingLabel, &d->indexingCheckBox); formLayout->addRow(indexingLabel, &d->indexingCheckBox);
const auto autoIncludeHeadersLabel = new QLabel(tr("Insert header files on completion:"));
formLayout->addRow(autoIncludeHeadersLabel, &d->autoIncludeHeadersCheckBox);
const auto threadLimitLayout = new QHBoxLayout; const auto threadLimitLayout = new QHBoxLayout;
threadLimitLayout->addWidget(&d->threadLimitSpinBox); threadLimitLayout->addWidget(&d->threadLimitSpinBox);
threadLimitLayout->addStretch(1); threadLimitLayout->addStretch(1);
@@ -255,6 +261,8 @@ ClangdSettingsWidget::ClangdSettingsWidget(const ClangdSettings::Data &settingsD
d->clangdChooser.setEnabled(checked); d->clangdChooser.setEnabled(checked);
indexingLabel->setEnabled(checked); indexingLabel->setEnabled(checked);
d->indexingCheckBox.setEnabled(checked); d->indexingCheckBox.setEnabled(checked);
autoIncludeHeadersLabel->setEnabled(checked);
d->autoIncludeHeadersCheckBox.setEnabled(checked);
d->threadLimitSpinBox.setEnabled(checked); d->threadLimitSpinBox.setEnabled(checked);
d->versionWarningLabel.setEnabled(checked); d->versionWarningLabel.setEnabled(checked);
}; };
@@ -312,6 +320,8 @@ ClangdSettingsWidget::ClangdSettingsWidget(const ClangdSettings::Data &settingsD
this, &ClangdSettingsWidget::settingsDataChanged); this, &ClangdSettingsWidget::settingsDataChanged);
connect(&d->indexingCheckBox, &QCheckBox::toggled, connect(&d->indexingCheckBox, &QCheckBox::toggled,
this, &ClangdSettingsWidget::settingsDataChanged); this, &ClangdSettingsWidget::settingsDataChanged);
connect(&d->autoIncludeHeadersCheckBox, &QCheckBox::toggled,
this, &ClangdSettingsWidget::settingsDataChanged);
connect(&d->threadLimitSpinBox, qOverload<int>(&QSpinBox::valueChanged), connect(&d->threadLimitSpinBox, qOverload<int>(&QSpinBox::valueChanged),
this, &ClangdSettingsWidget::settingsDataChanged); this, &ClangdSettingsWidget::settingsDataChanged);
connect(&d->clangdChooser, &Utils::PathChooser::pathChanged, connect(&d->clangdChooser, &Utils::PathChooser::pathChanged,
@@ -329,6 +339,7 @@ ClangdSettings::Data ClangdSettingsWidget::settingsData() const
data.useClangd = d->useClangdCheckBox.isChecked(); data.useClangd = d->useClangdCheckBox.isChecked();
data.executableFilePath = d->clangdChooser.filePath(); data.executableFilePath = d->clangdChooser.filePath();
data.enableIndexing = d->indexingCheckBox.isChecked(); data.enableIndexing = d->indexingCheckBox.isChecked();
data.autoIncludeHeaders = d->autoIncludeHeadersCheckBox.isChecked();
data.workerThreadLimit = d->threadLimitSpinBox.value(); data.workerThreadLimit = d->threadLimitSpinBox.value();
data.documentUpdateThreshold = d->documentUpdateThreshold.value(); data.documentUpdateThreshold = d->documentUpdateThreshold.value();
return data; return data;

View File

@@ -4707,6 +4707,43 @@ N::S N::foo(const S &s)
QuickFixOperationTest(testDocuments, &factory); QuickFixOperationTest(testDocuments, &factory);
} }
void QuickfixTest::testInsertDefFromDeclAliasTemplateAsReturnType()
{
QList<TestDocumentPtr> testDocuments;
QByteArray original;
QByteArray expected;
// Header File
original = R"(
struct foo {
struct foo2 {
template <typename T> using MyType = T;
MyType<int> @bar();
};
};
)";
expected = original;
testDocuments << CppTestDocument::create("file.h", original, expected);
// Source File
original = R"(
#include "file.h"
)";
expected = R"(
#include "file.h"
foo::foo2::MyType<int> foo::foo2::bar()
{
}
)";
testDocuments << CppTestDocument::create("file.cpp", original, expected);
InsertDefFromDecl factory;
QuickFixOperationTest(testDocuments, &factory);
}
void QuickfixTest::testInsertDefsFromDecls_data() void QuickfixTest::testInsertDefsFromDecls_data()
{ {
QTest::addColumn<QByteArrayList>("headers"); QTest::addColumn<QByteArrayList>("headers");

View File

@@ -155,6 +155,7 @@ private slots:
void testInsertDefFromDeclTemplateFunction(); void testInsertDefFromDeclTemplateFunction();
void testInsertDefFromDeclNotTriggeredForFriendFunc(); void testInsertDefFromDeclNotTriggeredForFriendFunc();
void testInsertDefFromDeclMinimalFunctionParameterType(); void testInsertDefFromDeclMinimalFunctionParameterType();
void testInsertDefFromDeclAliasTemplateAsReturnType();
void testInsertDefsFromDecls_data(); void testInsertDefsFromDecls_data();
void testInsertDefsFromDecls(); void testInsertDefsFromDecls();

View File

@@ -25,32 +25,10 @@
#include "customexecutablerunconfiguration.h" #include "customexecutablerunconfiguration.h"
#include "abi.h"
#include "buildconfiguration.h"
#include "devicesupport/devicemanager.h" #include "devicesupport/devicemanager.h"
#include "environmentaspect.h"
#include "localenvironmentaspect.h" #include "localenvironmentaspect.h"
#include "project.h"
#include "runcontrol.h"
#include "target.h" #include "target.h"
#include <coreplugin/icore.h>
#include <utils/detailswidget.h>
#include <utils/pathchooser.h>
#include <utils/stringutils.h>
#include <utils/variablechooser.h>
#include <QDialog>
#include <QDialogButtonBox>
#include <QDir>
#include <QFormLayout>
#include <QKeyEvent>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QVBoxLayout>
using namespace Utils; using namespace Utils;
namespace ProjectExplorer { namespace ProjectExplorer {
@@ -86,9 +64,9 @@ CustomExecutableRunConfiguration::CustomExecutableRunConfiguration(Target *targe
setDefaultDisplayName(defaultDisplayName()); setDefaultDisplayName(defaultDisplayName());
} }
QString CustomExecutableRunConfiguration::rawExecutable() const FilePath CustomExecutableRunConfiguration::executable() const
{ {
return aspect<ExecutableAspect>()->executable().toString(); return aspect<ExecutableAspect>()->executable();
} }
bool CustomExecutableRunConfiguration::isEnabled() const bool CustomExecutableRunConfiguration::isEnabled() const
@@ -116,16 +94,15 @@ Runnable CustomExecutableRunConfiguration::runnable() const
QString CustomExecutableRunConfiguration::defaultDisplayName() const QString CustomExecutableRunConfiguration::defaultDisplayName() const
{ {
if (rawExecutable().isEmpty()) if (executable().isEmpty())
return tr("Custom Executable"); return tr("Custom Executable");
else return tr("Run %1").arg(executable().toUserOutput());
return tr("Run %1").arg(QDir::toNativeSeparators(rawExecutable()));
} }
Tasks CustomExecutableRunConfiguration::checkForIssues() const Tasks CustomExecutableRunConfiguration::checkForIssues() const
{ {
Tasks tasks; Tasks tasks;
if (rawExecutable().isEmpty()) { if (executable().isEmpty()) {
tasks << createConfigurationIssue(tr("You need to set an executable in the custom run " tasks << createConfigurationIssue(tr("You need to set an executable in the custom run "
"configuration.")); "configuration."));
} }

View File

@@ -46,7 +46,7 @@ private:
Tasks checkForIssues() const override; Tasks checkForIssues() const override;
void configurationDialogFinished(); void configurationDialogFinished();
QString rawExecutable() const; Utils::FilePath executable() const;
}; };
class CustomExecutableRunConfigurationFactory : public FixedRunConfigurationFactory class CustomExecutableRunConfigurationFactory : public FixedRunConfigurationFactory

View File

@@ -54,7 +54,8 @@ DesktopDeviceProcess::DesktopDeviceProcess(const QSharedPointer<const IDevice> &
void DesktopDeviceProcess::start(const Runnable &runnable) void DesktopDeviceProcess::start(const Runnable &runnable)
{ {
QTC_ASSERT(m_process.state() == QProcess::NotRunning, return); QTC_ASSERT(m_process.state() == QProcess::NotRunning, return);
m_process.setEnvironment(runnable.environment); if (runnable.environment.size())
m_process.setEnvironment(runnable.environment);
m_process.setWorkingDirectory(runnable.workingDirectory); m_process.setWorkingDirectory(runnable.workingDirectory);
m_process.setCommand(runnable.command); m_process.setCommand(runnable.command);
m_process.start(); m_process.start();

View File

@@ -167,7 +167,7 @@ void PropertyEditorValue::setValue(const QVariant &value)
fixAmbigousColorNames(modelNode(), name(), &m_value); fixAmbigousColorNames(modelNode(), name(), &m_value);
fixUrl(modelNode(), name(), &m_value); fixUrl(modelNode(), name(), &m_value);
if (m_value.isValid() && !colorsEqual) if (!colorsEqual)
emit valueChangedQml(); emit valueChangedQml();
emit isExplicitChanged(); emit isExplicitChanged();

View File

@@ -225,6 +225,8 @@ private: // functions
void updateWatcher(const QString &path); void updateWatcher(const QString &path);
void updateRotationBlocks(); void updateRotationBlocks();
void maybeResetOnPropertyChange(const PropertyName &name, const ModelNode &node,
PropertyChangeFlags flags);
private: private:
QHash<QString, ModelNodePreviewImageData> m_imageDataMap; QHash<QString, ModelNodePreviewImageData> m_imageDataMap;

View File

@@ -473,8 +473,9 @@ void NodeInstanceView::propertiesAboutToBeRemoved(const QList<AbstractProperty>&
resetVerticalAnchors(property.parentModelNode()); resetVerticalAnchors(property.parentModelNode());
} else if (name == "anchors.baseline") { } else if (name == "anchors.baseline") {
resetVerticalAnchors(property.parentModelNode()); resetVerticalAnchors(property.parentModelNode());
} else if (name == "shader" && property.parentModelNode().isSubclassOf("QtQuick3D.Shader")) { } else {
m_resetTimer.start(); maybeResetOnPropertyChange(name, property.parentModelNode(),
AbstractView::EmptyPropertiesRemoved);
} }
} }
@@ -503,10 +504,14 @@ void NodeInstanceView::nodeTypeChanged(const ModelNode &, const TypeName &, int,
restartProcess(); restartProcess();
} }
void NodeInstanceView::bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags /*propertyChange*/) void NodeInstanceView::bindingPropertiesChanged(const QList<BindingProperty>& propertyList,
PropertyChangeFlags propertyChange)
{ {
QTC_ASSERT(m_nodeInstanceServer, return); QTC_ASSERT(m_nodeInstanceServer, return);
m_nodeInstanceServer->changePropertyBindings(createChangeBindingCommand(propertyList)); m_nodeInstanceServer->changePropertyBindings(createChangeBindingCommand(propertyList));
for (const auto &property : propertyList)
maybeResetOnPropertyChange(property.name(), property.parentModelNode(), propertyChange);
} }
/*! /*!
@@ -518,18 +523,15 @@ void NodeInstanceView::bindingPropertiesChanged(const QList<BindingProperty>& pr
\sa AbstractProperty, NodeInstance, ModelNode \sa AbstractProperty, NodeInstance, ModelNode
*/ */
void NodeInstanceView::variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags /*propertyChange*/) void NodeInstanceView::variantPropertiesChanged(const QList<VariantProperty>& propertyList,
PropertyChangeFlags propertyChange)
{ {
QTC_ASSERT(m_nodeInstanceServer, return); QTC_ASSERT(m_nodeInstanceServer, return);
updatePosition(propertyList); updatePosition(propertyList);
m_nodeInstanceServer->changePropertyValues(createChangeValueCommand(propertyList)); m_nodeInstanceServer->changePropertyValues(createChangeValueCommand(propertyList));
for (const auto &property : propertyList) { for (const auto &property : propertyList)
if (property.name() == "shader" && property.parentModelNode().isSubclassOf("QtQuick3D.Shader")) { maybeResetOnPropertyChange(property.name(), property.parentModelNode(), propertyChange);
m_resetTimer.start();
break;
}
}
} }
/*! /*!
Notifies the view that the property parent of the model node \a node has Notifies the view that the property parent of the model node \a node has
@@ -1908,4 +1910,22 @@ void NodeInstanceView::updateRotationBlocks()
} }
} }
void NodeInstanceView::maybeResetOnPropertyChange(const PropertyName &name, const ModelNode &node,
PropertyChangeFlags flags)
{
bool reset = false;
if (flags & AbstractView::PropertiesAdded
&& name == "model" && (node.isSubclassOf("QtQuick.Repeater")
|| node.isSubclassOf("QtQuick3D.Repeater3D"))) {
// TODO: This is a workaround for QTBUG-97583 (2D) and QTBUG-97586 (3D):
// Reset puppet when repeater model is first added, if there is already a delegate
if (node.hasProperty("delegate"))
reset = true;
} else if (name == "shader" && node.isSubclassOf("QtQuick3D.Shader")) {
reset = true;
}
if (reset)
resetPuppet();
}
} }

View File

@@ -32,9 +32,9 @@
#include <projectexplorer/task.h> #include <projectexplorer/task.h>
#include <QDateTime> #include <QDateTime>
#include <QFileInfo>
using namespace ProjectExplorer; using namespace ProjectExplorer;
using namespace Utils;
namespace RemoteLinux { namespace RemoteLinux {
namespace Internal { namespace Internal {
@@ -42,8 +42,8 @@ namespace Internal {
class AbstractPackagingStepPrivate class AbstractPackagingStepPrivate
{ {
public: public:
QString cachedPackageFilePath; FilePath cachedPackageFilePath;
QString cachedPackageDirectory; FilePath cachedPackageDirectory;
bool deploymentDataModified = false; bool deploymentDataModified = false;
}; };
@@ -67,37 +67,37 @@ AbstractPackagingStep::~AbstractPackagingStep()
delete d; delete d;
} }
QString AbstractPackagingStep::cachedPackageFilePath() const FilePath AbstractPackagingStep::cachedPackageFilePath() const
{ {
return d->cachedPackageFilePath; return d->cachedPackageFilePath;
} }
QString AbstractPackagingStep::packageFilePath() const FilePath AbstractPackagingStep::packageFilePath() const
{ {
if (packageDirectory().isEmpty()) if (packageDirectory().isEmpty())
return QString(); return {};
return packageDirectory() + QLatin1Char('/') + packageFileName(); return packageDirectory().pathAppended(packageFileName());
} }
QString AbstractPackagingStep::cachedPackageDirectory() const FilePath AbstractPackagingStep::cachedPackageDirectory() const
{ {
return d->cachedPackageDirectory; return d->cachedPackageDirectory;
} }
QString AbstractPackagingStep::packageDirectory() const FilePath AbstractPackagingStep::packageDirectory() const
{ {
return buildDirectory().toString(); return buildDirectory();
} }
bool AbstractPackagingStep::isPackagingNeeded() const bool AbstractPackagingStep::isPackagingNeeded() const
{ {
QFileInfo packageInfo(packageFilePath()); const FilePath packagePath = packageFilePath();
if (!packageInfo.exists() || d->deploymentDataModified) if (!packagePath.exists() || d->deploymentDataModified)
return true; return true;
const DeploymentData &dd = target()->deploymentData(); const DeploymentData &dd = target()->deploymentData();
for (int i = 0; i < dd.fileCount(); ++i) { for (int i = 0; i < dd.fileCount(); ++i) {
if (dd.fileAt(i).localFilePath().isNewerThan(packageInfo.lastModified())) if (dd.fileAt(i).localFilePath().isNewerThan(packagePath.lastModified()))
return true; return true;
} }

View File

@@ -41,8 +41,8 @@ public:
explicit AbstractPackagingStep(ProjectExplorer::BuildStepList *bsl, Utils::Id id); explicit AbstractPackagingStep(ProjectExplorer::BuildStepList *bsl, Utils::Id id);
~AbstractPackagingStep() override; ~AbstractPackagingStep() override;
QString packageFilePath() const; Utils::FilePath packageFilePath() const;
QString cachedPackageFilePath() const; Utils::FilePath cachedPackageFilePath() const;
bool init() override; bool init() override;
signals: signals:
@@ -54,8 +54,8 @@ protected:
void raiseError(const QString &errorMessage); void raiseError(const QString &errorMessage);
void raiseWarning(const QString &warningMessage); void raiseWarning(const QString &warningMessage);
QString cachedPackageDirectory() const; Utils::FilePath cachedPackageDirectory() const;
QString packageDirectory() const; Utils::FilePath packageDirectory() const;
virtual bool isPackagingNeeded() const; virtual bool isPackagingNeeded() const;

View File

@@ -71,9 +71,9 @@ AbstractUploadAndInstallPackageService::~AbstractUploadAndInstallPackageService(
delete d; delete d;
} }
void AbstractUploadAndInstallPackageService::setPackageFilePath(const QString &filePath) void AbstractUploadAndInstallPackageService::setPackageFilePath(const FilePath &filePath)
{ {
d->packageFilePath = FilePath::fromString(filePath); d->packageFilePath = filePath;
} }
QString AbstractUploadAndInstallPackageService::uploadDir() const QString AbstractUploadAndInstallPackageService::uploadDir() const

View File

@@ -38,7 +38,7 @@ class REMOTELINUX_EXPORT AbstractUploadAndInstallPackageService : public Abstrac
Q_OBJECT Q_OBJECT
public: public:
void setPackageFilePath(const QString &filePath); void setPackageFilePath(const Utils::FilePath &filePath);
protected: protected:
AbstractUploadAndInstallPackageService(); AbstractUploadAndInstallPackageService();

View File

@@ -87,11 +87,11 @@ TarPackageCreationStep::TarPackageCreationStep(BuildStepList *bsl, Utils::Id id)
m_incrementalDeploymentAspect->setSettingsKey(IncrementalDeploymentKey); m_incrementalDeploymentAspect->setSettingsKey(IncrementalDeploymentKey);
setSummaryUpdater([this] { setSummaryUpdater([this] {
QString path = packageFilePath(); FilePath path = packageFilePath();
if (path.isEmpty()) if (path.isEmpty())
return QString("<font color=\"red\">" + tr("Tarball creation not possible.") return QString("<font color=\"red\">" + tr("Tarball creation not possible.")
+ "</font>"); + "</font>");
return QString("<b>" + tr("Create tarball:") + "</b> " + path); return QString("<b>" + tr("Create tarball:") + "</b> " + path.toUserOutput());
}); });
} }
@@ -148,11 +148,12 @@ bool TarPackageCreationStep::doPackage()
} }
// TODO: Optimization: Only package changed files // TODO: Optimization: Only package changed files
QFile tarFile(cachedPackageFilePath()); const FilePath tarFilePath = cachedPackageFilePath();
QFile tarFile(tarFilePath.toString());
if (!tarFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) { if (!tarFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
raiseError(tr("Error: tar file %1 cannot be opened (%2).") raiseError(tr("Error: tar file %1 cannot be opened (%2).")
.arg(QDir::toNativeSeparators(cachedPackageFilePath()), tarFile.errorString())); .arg(tarFilePath.toUserOutput(), tarFile.errorString()));
return false; return false;
} }
@@ -311,7 +312,7 @@ bool TarPackageCreationStep::writeHeader(QFile &tarFile, const QFileInfo &fileIn
header.chksum[sizeof header.chksum-1] = 0; header.chksum[sizeof header.chksum-1] = 0;
if (!tarFile.write(reinterpret_cast<char *>(&header), sizeof header)) { if (!tarFile.write(reinterpret_cast<char *>(&header), sizeof header)) {
raiseError(tr("Error writing tar file \"%1\": %2") raiseError(tr("Error writing tar file \"%1\": %2")
.arg(QDir::toNativeSeparators(cachedPackageFilePath()), tarFile.errorString())); .arg(cachedPackageFilePath().toUserOutput(), tarFile.errorString()));
return false; return false;
} }
return true; return true;

View File

@@ -129,16 +129,17 @@ void UpdateInfoPlugin::startCheckForUpdates()
{ {
stopCheckForUpdates(); stopCheckForUpdates();
Utils::Environment env = Utils::Environment::systemEnvironment(); d->m_checkUpdatesCommand = new ShellCommand({}, Utils::Environment::systemEnvironment());
env.set("QT_LOGGING_RULES", "*=false");
d->m_checkUpdatesCommand = new ShellCommand({}, env);
d->m_checkUpdatesCommand->setDisplayName(tr("Checking for Updates")); d->m_checkUpdatesCommand->setDisplayName(tr("Checking for Updates"));
connect(d->m_checkUpdatesCommand, &ShellCommand::stdOutText, this, &UpdateInfoPlugin::collectCheckForUpdatesOutput); connect(d->m_checkUpdatesCommand, &ShellCommand::stdOutText, this, &UpdateInfoPlugin::collectCheckForUpdatesOutput);
connect(d->m_checkUpdatesCommand, &ShellCommand::finished, this, &UpdateInfoPlugin::checkForUpdatesFinished); connect(d->m_checkUpdatesCommand, &ShellCommand::finished, this, &UpdateInfoPlugin::checkForUpdatesFinished);
d->m_checkUpdatesCommand->addJob({Utils::FilePath::fromString(d->m_maintenanceTool), {"--checkupdates"}}, d->m_checkUpdatesCommand->addJob({Utils::FilePath::fromString(d->m_maintenanceTool),
{"ch", "-g", "*=false,ifw.package.*=true"}},
60 * 3, // 3 minutes timeout 60 * 3, // 3 minutes timeout
/*workingDirectory=*/{}, /*workingDirectory=*/{},
[](int /*exitCode*/) { return Utils::QtcProcess::FinishedWithSuccess; }); [](int /*exitCode*/) {
return Utils::QtcProcess::FinishedWithSuccess;
});
d->m_checkUpdatesCommand->execute(); d->m_checkUpdatesCommand->execute();
d->m_progress = d->m_checkUpdatesCommand->futureProgress(); d->m_progress = d->m_checkUpdatesCommand->futureProgress();
if (d->m_progress) { if (d->m_progress) {

View File

@@ -252,8 +252,7 @@ isEmpty(LLVM_VERSION) {
# It is not intended for cross compiler linking. # It is not intended for cross compiler linking.
LLVM_CXXFLAGS *= $$system($$llvm_config --cxxflags, lines) LLVM_CXXFLAGS *= $$system($$llvm_config --cxxflags, lines)
LLVM_CXXFLAGS ~= s,-fno-exceptions, LLVM_CXXFLAGS ~= s,-fno-exceptions,
LLVM_CXXFLAGS ~= s,-std=c++11, LLVM_CXXFLAGS ~= s,-std.c\+\+..,
LLVM_CXXFLAGS ~= s,-std=c++0x,
LLVM_CXXFLAGS ~= s,-O\S*, LLVM_CXXFLAGS ~= s,-O\S*,
LLVM_CXXFLAGS ~= s,/O\S*, LLVM_CXXFLAGS ~= s,/O\S*,
LLVM_CXXFLAGS ~= s,/W4, LLVM_CXXFLAGS ~= s,/W4,

View File

@@ -96,7 +96,7 @@
:New.comboBox_QComboBox {name='comboBox' type='QComboBox' visible='1' window=':New_Core::Internal::NewDialog'} :New.comboBox_QComboBox {name='comboBox' type='QComboBox' visible='1' window=':New_Core::Internal::NewDialog'}
:New.frame_QFrame {name='frame' type='QFrame' visible='1' window=':New_Core::Internal::NewDialog'} :New.frame_QFrame {name='frame' type='QFrame' visible='1' window=':New_Core::Internal::NewDialog'}
:New.templateCategoryView_QTreeView {name='templateCategoryView' type='QTreeView' visible='1' window=':New_Core::Internal::NewDialog'} :New.templateCategoryView_QTreeView {name='templateCategoryView' type='QTreeView' visible='1' window=':New_Core::Internal::NewDialog'}
:New_Core::Internal::NewDialog {name='Core__Internal__NewDialog' type='Core::Internal::NewDialog' visible='1' windowTitle?='New*'} :New_Core::Internal::NewDialog {name='Core__Internal__NewDialog' type='Core::Internal::NewDialogWidget' visible='1' windowTitle?='New*'}
:New_ProjectExplorer::JsonWizard {type='ProjectExplorer::JsonWizard' unnamed='1' visible='1'} :New_ProjectExplorer::JsonWizard {type='ProjectExplorer::JsonWizard' unnamed='1' visible='1'}
:Next_QPushButton {text~='(Next.*|Continue)' type='QPushButton' visible='1'} :Next_QPushButton {text~='(Next.*|Continue)' type='QPushButton' visible='1'}
:No valid kits found._QLabel {text?='*No suitable kits found.*' type='QLabel' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :No valid kits found._QLabel {text?='*No suitable kits found.*' type='QLabel' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
@@ -154,7 +154,7 @@
:Qt Creator_Core::Internal::NavComboBox {type='Core::Internal::NavComboBox' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator_Core::Internal::NavComboBox {type='Core::Internal::NavComboBox' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:Qt Creator_Core::Internal::ProgressBar {type='Core::Internal::ProgressBar' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator_Core::Internal::ProgressBar {type='Core::Internal::ProgressBar' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:Qt Creator_Core::OutputWindow {type='Core::OutputWindow' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator_Core::OutputWindow {type='Core::OutputWindow' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:Qt Creator_CppEditor::Internal::CPPEditorWidget {type='CppEditor::Internal::CppEditorWidget' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator_CppEditor::Internal::CPPEditorWidget {type='CppEditor::CppEditorWidget' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:Qt Creator_DiffEditor::Internal::DescriptionEditorWidget {type='DiffEditor::Internal::DescriptionEditorWidget' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator_DiffEditor::Internal::DescriptionEditorWidget {type='DiffEditor::Internal::DescriptionEditorWidget' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:Qt Creator_DiffEditor::SideDiffEditorWidget {type='DiffEditor::Internal::SideDiffEditorWidget' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator_DiffEditor::SideDiffEditorWidget {type='DiffEditor::Internal::SideDiffEditorWidget' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:Qt Creator_DiffEditor::SideDiffEditorWidget2 {occurrence='2' type='DiffEditor::Internal::SideDiffEditorWidget' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator_DiffEditor::SideDiffEditorWidget2 {occurrence='2' type='DiffEditor::Internal::SideDiffEditorWidget' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}

View File

@@ -276,11 +276,12 @@ def createProject_Qt_Console(path, projectName, checks = True, buildSystem = Non
if checks: if checks:
__verifyFileCreation__(path, expectedFiles) __verifyFileCreation__(path, expectedFiles)
def createNewQtQuickApplication(workingDir, projectName=None, def createNewQtQuickApplication(workingDir, projectName=None,
targets=Targets.desktopTargetClasses(), minimumQtVersion="5.12", targets=Targets.desktopTargetClasses(), minimumQtVersion="5.12",
template="Qt Quick Application - Empty", fromWelcome=False, template="Qt Quick Application", fromWelcome=False,
buildSystem=None): buildSystem=None):
available = __createProjectOrFileSelectType__(" Application (Qt Quick)", template, fromWelcome) available = __createProjectOrFileSelectType__(" Application (Qt)", template, fromWelcome)
projectName = __createProjectSetNameAndPath__(workingDir, projectName) projectName = __createProjectSetNameAndPath__(workingDir, projectName)
__handleBuildSystem__(buildSystem) __handleBuildSystem__(buildSystem)
requiredQt = __createProjectHandleQtQuickSelection__(minimumQtVersion) requiredQt = __createProjectHandleQtQuickSelection__(minimumQtVersion)

View File

@@ -172,6 +172,7 @@ def cleanUpUserFiles(pathsToProFiles=None):
doneWithoutErrors = False doneWithoutErrors = False
return doneWithoutErrors return doneWithoutErrors
def invokeMenuItem(menu, item, *subItems): def invokeMenuItem(menu, item, *subItems):
if platform.system() == "Darwin": if platform.system() == "Darwin":
try: try:
@@ -191,10 +192,9 @@ def invokeMenuItem(menu, item, *subItems):
activateItem(itemObject) activateItem(itemObject)
numberedPrefix = "(&\\d \| )?" numberedPrefix = "(&\\d \| )?"
for subItem in subItems: for subItem in subItems:
sub = itemObject.menu()
waitFor("sub.visible", 1000)
# we might have numbered sub items (e.g. "Recent Files") - these have this special prefix # we might have numbered sub items (e.g. "Recent Files") - these have this special prefix
if subItem.startswith(numberedPrefix): if subItem.startswith(numberedPrefix):
# TODO: Find fix for Qt 6
actions = sub.actions() actions = sub.actions()
triggered = False triggered = False
for i in range(actions.count()): for i in range(actions.count()):
@@ -211,9 +211,10 @@ def invokeMenuItem(menu, item, *subItems):
"Function arguments: '%s', '%s', %s" % (menu, item, str(subItems))) "Function arguments: '%s', '%s', %s" % (menu, item, str(subItems)))
break # we failed to trigger - no need to process subItems further break # we failed to trigger - no need to process subItems further
else: else:
itemObject = waitForObjectItem(sub, subItem) itemObject = waitForObjectItem(itemObject, subItem)
activateItem(itemObject) activateItem(itemObject)
def logApplicationOutput(): def logApplicationOutput():
# make sure application output is shown # make sure application output is shown
ensureChecked(":Qt Creator_AppOutput_Core::Internal::OutputPaneToggleButton") ensureChecked(":Qt Creator_AppOutput_Core::Internal::OutputPaneToggleButton")