Merge remote-tracking branch 'origin/6.0'
Change-Id: Ie46e0028f0dca9f3ddc45ed8794ba6cddd97df26
@@ -1,59 +1,24 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(transitions VERSION 0.1 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Quick REQUIRED)
|
||||
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Quick REQUIRED)
|
||||
find_package(Qt6 6.2 COMPONENTS Quick REQUIRED)
|
||||
|
||||
set(PROJECT_SOURCES
|
||||
qt_add_executable(transitionsexample
|
||||
main.cpp
|
||||
qml.qrc
|
||||
)
|
||||
|
||||
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
|
||||
qt_add_executable(transitions
|
||||
MANUAL_FINALIZATION
|
||||
${PROJECT_SOURCES}
|
||||
qt_add_qml_module(transitionsexample
|
||||
URI transitions
|
||||
VERSION 1.0
|
||||
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
|
||||
target_compile_definitions(transitionsexample
|
||||
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)
|
||||
qt_import_qml_plugins(transitions)
|
||||
qt_finalize_executable(transitions)
|
||||
endif()
|
||||
target_link_libraries(transitionsexample
|
||||
PRIVATE Qt6::Quick)
|
||||
|
@@ -48,19 +48,18 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Window 2.15
|
||||
import QtQuick
|
||||
|
||||
Rectangle {
|
||||
id: page
|
||||
state: "State1"
|
||||
anchors.fill: parent
|
||||
color: "#ffffff"
|
||||
|
||||
Image {
|
||||
id: icon
|
||||
x: 20
|
||||
y: 20
|
||||
source: "images/qt-logo.png"
|
||||
fillMode: Image.PreserveAspectFit
|
||||
source: "qt-logo.png"
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
@@ -88,7 +87,6 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Rectangle {
|
||||
id: middleRightRect
|
||||
width: 55
|
||||
@@ -112,7 +110,6 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Rectangle {
|
||||
id: bottomLeftRect
|
||||
width: 55
|
||||
@@ -160,6 +157,7 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
transitions: [
|
||||
Transition {
|
||||
id: toState1
|
||||
@@ -202,7 +200,7 @@ Rectangle {
|
||||
PropertyAnimation {
|
||||
target: icon
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -215,7 +213,7 @@ Rectangle {
|
||||
PropertyAnimation {
|
||||
target: icon
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -234,7 +232,7 @@ Rectangle {
|
||||
PropertyAnimation {
|
||||
target: icon
|
||||
property: "y"
|
||||
easing.bezierCurve: [0.455,0.03,0.515,0.955,1,1]
|
||||
easing.type: Easing.InOutQuad
|
||||
duration: 2000
|
||||
}
|
||||
}
|
||||
@@ -247,7 +245,7 @@ Rectangle {
|
||||
PropertyAnimation {
|
||||
target: icon
|
||||
property: "x"
|
||||
easing.bezierCurve: [0.455,0.03,0.515,0.955,1,1]
|
||||
easing.type: Easing.InOutQuad
|
||||
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}
|
||||
}
|
||||
##^##*/
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
@@ -54,19 +54,10 @@
|
||||
|
||||
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);
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
const QUrl url(QStringLiteral("qrc:/main.qml"));
|
||||
const QUrl url(u"qrc:/transitions/main.qml"_qs);
|
||||
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
|
||||
&app, [url](QObject *obj, const QUrl &objUrl) {
|
||||
if (!obj && url == objUrl)
|
||||
|
@@ -48,24 +48,16 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Window 2.15
|
||||
import QtQuick
|
||||
|
||||
Window {
|
||||
width: 640
|
||||
height: 480
|
||||
visible: true
|
||||
title: qsTr("Hello World")
|
||||
title: qsTr("Transitions")
|
||||
|
||||
Page {
|
||||
id: page
|
||||
anchors.fill: parent
|
||||
color: "#ffffff"
|
||||
}
|
||||
}
|
||||
|
||||
/*##^##
|
||||
Designer {
|
||||
D{i:0;formeditorZoom:0.75}
|
||||
}
|
||||
##^##*/
|
||||
|
@@ -1,7 +0,0 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>main.qml</file>
|
||||
<file>images/qt-logo.png</file>
|
||||
<file>Page.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
BIN
doc/qtcreator/examples/transitions/qt-logo.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
BIN
doc/qtcreator/images/qtquick-tutorial.gif
Normal file
After Width: | Height: | Size: 94 KiB |
@@ -43,7 +43,6 @@
|
||||
\li \l{File System}
|
||||
\li \l{Open Documents}
|
||||
\endlist
|
||||
\li \l{Managing Workspaces}
|
||||
\li \l{Viewing Output}
|
||||
\endlist
|
||||
\li \l{Configuring Qt Creator}
|
||||
|
@@ -30,33 +30,29 @@
|
||||
|
||||
\title Creating a Qt Quick Application
|
||||
|
||||
This tutorial uses preset components and illustrates basic concepts of
|
||||
\l{Qt Quick}.
|
||||
For more information about the UI choices you have, see \l{User Interfaces}.
|
||||
This tutorial illustrates basic concepts of \l{Qt Quick}. For more
|
||||
information about the UI choices you have, see \l{User Interfaces}.
|
||||
|
||||
This tutorial describes how to use \QC to implement states and
|
||||
transitions. We create an application that displays a Qt logo that moves
|
||||
between three rectangles on the page when you click them.
|
||||
This tutorial describes how to use \QC to implement \l{Qt Quick States}
|
||||
{states} and \l{Animation and Transitions in Qt Quick}{transitions}
|
||||
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
|
||||
mode, see \l{Developing Qt Quick Applications}.
|
||||
\image qtquick-tutorial.gif "Transitions example"
|
||||
|
||||
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
|
||||
|
||||
\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
|
||||
the \l {Form Editor} view.
|
||||
\uicontrol Edit mode.
|
||||
|
||||
\note The visibility of Design views depends on the selected workspace.
|
||||
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
|
||||
\section1 Deploying Applications
|
||||
|
||||
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.
|
||||
@@ -64,256 +60,122 @@
|
||||
We use the \e qt-logo.png image in this tutorial, but you can also use
|
||||
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
|
||||
|
||||
\li In \uicontrol Library > \uicontrol Components >
|
||||
\uicontrol {Default Components} > \uicontrol Basic, select
|
||||
\uicontrol Rectangle and drag and drop it to \e Window in
|
||||
\uicontrol Navigator.
|
||||
|
||||
\li Select the \uicontrol Rectangle instance in \l Navigator, and enter
|
||||
\e page in the \uicontrol ID field in \l Properties.
|
||||
|
||||
\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.
|
||||
|
||||
\li Select \uicontrol File > \uicontrol {New File or Project} >
|
||||
\uicontrol {Files and Classes} > \uicontrol Qt >
|
||||
\uicontrol {QML File (Qt Quick 2)}.
|
||||
\li Select \uicontrol Choose to open the \uicontrol Location dialog.
|
||||
\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 \uicontrol Next to open the \uicontrol {Project Management}
|
||||
dialog.
|
||||
\li Select \uicontrol Finish to create \e Page.qml.
|
||||
\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.
|
||||
\QC opens \e Page.qml in the \uicontrol Edit mode. It contains a root item
|
||||
of the type \l Item that we replace with a \l Rectangle type. We give the
|
||||
type the ID \e page, anchor it to the parent item on all sides, and set
|
||||
its color to white:
|
||||
|
||||
\image qmldesigner-tutorial-topleftrect.png "Rectangle properties"
|
||||
\quotefromfile transitions/Page.qml
|
||||
\skipto import
|
||||
\printuntil color
|
||||
|
||||
\li In \uicontrol Properties, edit the properties of the Rectangle
|
||||
component instance:
|
||||
Because we develop with Qt 6, where version numbers are not used with
|
||||
modules, we remove the version number from the import statement.
|
||||
|
||||
\list a
|
||||
When you start typing the QML type name, \QC suggests available types
|
||||
and properties to \l{Completing Code}{complete the code}.
|
||||
|
||||
\li In the \uicontrol ID field, enter \e topLeftRect.
|
||||
Select the light bulb icon \inlineimage refactormarker.png
|
||||
next to the type name to open the \l{Editing Rectangles}
|
||||
{Qt Quick Toolbar for rectangles}. You can use it to specify
|
||||
rectangle properties, such as color, transparency, and gradients.
|
||||
|
||||
\li In the \uicontrol Size field, set \uicontrol W and
|
||||
\uicontrol H to values that match the image size
|
||||
(\e 55 and \e 41).
|
||||
\image qml-toolbar-rectangle.png "Qt Quick Toolbar for rectangles"
|
||||
|
||||
\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.
|
||||
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:
|
||||
|
||||
\li In the \uicontrol {Border color} field, set the border
|
||||
color to \e #808080 to make the rectangle visible on
|
||||
the background.
|
||||
\printuntil }
|
||||
|
||||
\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.
|
||||
You can use the \l{Previewing Images}{Qt Quick Toolbar for images} to
|
||||
specify image properties, such as source file and fill mode.
|
||||
|
||||
\li In the \uicontrol Margin field, select \e 20 for both anchors.
|
||||
\image qml-toolbar-image.png "Logo visible in Qt Quick Toolbar for images"
|
||||
|
||||
\image qmldesigner-tutorial-topleftrect-layout.png "Anchor margins"
|
||||
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:
|
||||
|
||||
\endlist
|
||||
\printuntil border.color
|
||||
|
||||
\li Drag and drop a \uicontrol {Mouse Area} component from the
|
||||
\uicontrol Library to \e topLeftRect in \uicontrol Navigator.
|
||||
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:
|
||||
|
||||
\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.
|
||||
\printuntil anchors.topMargin
|
||||
|
||||
\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.
|
||||
We add a \l MouseArea type to make the rectangle clickable by users:
|
||||
|
||||
\li Select \e topLeftRect1 and edit its properties:
|
||||
\printuntil anchors.fill
|
||||
|
||||
\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
|
||||
|
||||
To check your code, you can view your \e {main.qml} file in the
|
||||
\uicontrol {Text Editor} and compare it with the \e {main.qml}
|
||||
example file.
|
||||
|
||||
The UI design is now ready.
|
||||
|
||||
\image qmldesigner-tutorial-ui-ready.png "Transitions UI"
|
||||
|
||||
For more information about the views you used, see:
|
||||
|
||||
\list
|
||||
\li \l {Form Editor}
|
||||
\li \l Library
|
||||
\li \l Navigator
|
||||
\li \l Properties
|
||||
\endlist
|
||||
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
|
||||
them by \l{Adding States}{adding states} and by connecting mouse clicks
|
||||
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
|
||||
them, by adding states and by 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
|
||||
states to the Page component, where we change the values of the \c x and
|
||||
\c y properties of
|
||||
\e icon to match those of the middle right and top left rectangles. Then,
|
||||
we connect the \c onClicked signals of the mouse areas to the state changes.
|
||||
\c y properties of \e icon to match those of the middle right and top left
|
||||
rectangles. To make sure that the image is displayed within the rectangle
|
||||
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
|
||||
is scaled on different sizes of screens, we bind the values of the \c x and
|
||||
\c y properties of \e icon to those of the rectangles.
|
||||
\dots
|
||||
\skipto states:
|
||||
\printuntil ]
|
||||
|
||||
\list 1
|
||||
\li Right-click \e page in \uicontrol Navigator, and select
|
||||
\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
|
||||
Then, we connect the \c onClicked signals of the mouse areas to the state
|
||||
changes:
|
||||
|
||||
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
|
||||
functions. This is currently not supported in \uicontrol {Connections},
|
||||
so you must do it in \uicontrol {Text Editor}. For example:
|
||||
Because we develop with Qt 6, we must specify the connections as functions.
|
||||
|
||||
\code
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
\section1 Adding Page to the Main View
|
||||
|
||||
Connections {
|
||||
target: mouseArea
|
||||
function onClicked()
|
||||
{
|
||||
page.state = "State1"
|
||||
}
|
||||
}
|
||||
}
|
||||
\endcode
|
||||
We now open \e main.qml for editing and add an instance of the Page custom
|
||||
component to it:
|
||||
|
||||
For more information about the views you used, see:
|
||||
\quotefromfile transitions/main.qml
|
||||
\skipto import
|
||||
\printuntil /^\ {0}\}/
|
||||
|
||||
\list
|
||||
\li \l States
|
||||
\li \l{Setting Bindings}
|
||||
\li \l{Connecting Components to Signals}
|
||||
\endlist
|
||||
Press \key {Ctrl+R} to run the application, and click the rectangles to
|
||||
move the Qt logo from one rectangle to another.
|
||||
|
||||
\section1 Animating Transitions
|
||||
|
||||
@@ -321,56 +183,29 @@
|
||||
the image bounces back when it moves to \e middleRightRect and eases into
|
||||
\e bottomLeftRect.
|
||||
|
||||
\list 1
|
||||
\li In the \uicontrol {Transition Editor} view, click the
|
||||
\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
|
||||
We specify transitions for switching from each state to the other two
|
||||
states:
|
||||
|
||||
For more information about the views you used, see:
|
||||
\quotefromfile transitions/Page.qml
|
||||
\skipto transitions:
|
||||
\printuntil },
|
||||
|
||||
\list
|
||||
\li \l{Editing Easing Curves}
|
||||
\li \l{Transition Editor}
|
||||
\endlist
|
||||
We change the easing curve type for transitions to \e State2 from linear to
|
||||
\c Easing.OutBounce to create the bounce effect:
|
||||
|
||||
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.
|
||||
*/
|
||||
|
@@ -46,16 +46,18 @@
|
||||
\li Select \uicontrol Next (or \uicontrol Continue on \macos) to open
|
||||
the \uicontrol {Define Build System} dialog.
|
||||
|
||||
\li In the \uicontrol {Build system} field, select the build system to
|
||||
use for building and running the project: \l qmake,
|
||||
\l {Setting Up CMake}{CMake}, or \l {Setting Up Qbs}{Qbs}.
|
||||
\li In the \uicontrol {Build system} field, select \l {Setting Up CMake}
|
||||
{CMake} as the build system to use for building and running the
|
||||
project.
|
||||
|
||||
\note If you select \l qmake, the instructions for configuring the
|
||||
project won't apply.
|
||||
|
||||
\li Select \uicontrol Next to open the
|
||||
\uicontrol {Define Project Details} dialog.
|
||||
|
||||
\li In the \uicontrol {Screen resolution} field, select the initial
|
||||
size of the UI. You can easily change the screen size later
|
||||
in \l Properties.
|
||||
\li In the \uicontrol {Minimal required Qt version} field, select
|
||||
Qt 6.2.
|
||||
|
||||
\li Select \uicontrol Next to open the \uicontrol {Translation File}
|
||||
dialog.
|
||||
@@ -63,9 +65,10 @@
|
||||
\li Select \uicontrol Next to use the default settings and to open
|
||||
the \uicontrol {Kit Selection} dialog.
|
||||
|
||||
\li Select \l{glossary-buildandrun-kit}{kits} for the platforms that
|
||||
you want to build the application for. To build applications for
|
||||
mobile devices, select kits for Android ARM and iPhone OS.
|
||||
\li Select Qt 6.2 or later \l{glossary-buildandrun-kit}{kits} for the
|
||||
platforms that you want to build the application for. To build
|
||||
applications for mobile devices, select kits also for Android and
|
||||
iOS.
|
||||
|
||||
\note Kits are listed if they have been specified in \uicontrol
|
||||
Tools > \uicontrol Options > \uicontrol Kits (on Windows and Linux)
|
||||
@@ -82,8 +85,7 @@
|
||||
\endlist
|
||||
|
||||
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]
|
||||
*/
|
||||
Con
|
||||
|
@@ -26,7 +26,7 @@
|
||||
/*!
|
||||
\page creator-open-documents-view.html
|
||||
\previouspage creator-file-system-view.html
|
||||
\nextpage creator-project-managing-workspaces.html
|
||||
\nextpage creator-output-panes.html
|
||||
|
||||
\title Open Documents
|
||||
|
||||
|
@@ -93,7 +93,6 @@
|
||||
\li \l{Selecting Modes}{Mode selector}
|
||||
\li \l{Working with Sidebars}{Sidebars}
|
||||
\li \l{Browsing Project Contents}{Views}
|
||||
\li \l{Managing Workspaces}{Workspaces}
|
||||
\li \l{Viewing Output}{Output panes}
|
||||
\endlist
|
||||
|
||||
@@ -350,7 +349,7 @@
|
||||
\previouspage creator-views.html
|
||||
\nextpage creator-highlighting.html
|
||||
\else
|
||||
\previouspage creator-project-managing-workspaces.html
|
||||
\previouspage creator-open-documents-view.html
|
||||
\nextpage creator-configuring.html
|
||||
\endif
|
||||
|
||||
|
@@ -35,7 +35,12 @@
|
||||
\title Browsing Project Contents
|
||||
|
||||
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
|
||||
available in it.
|
||||
|
||||
|
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 7.8 KiB |
Before Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 6.7 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 65 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 7.1 KiB |
Before Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 48 KiB |
@@ -26,15 +26,11 @@
|
||||
/*!
|
||||
\page creator-project-managing-workspaces.html
|
||||
\previouspage creator-open-documents-view.html
|
||||
\if defined(qtdesignstudio)
|
||||
\nextpage creator-project-managing-sessions.html
|
||||
\else
|
||||
\nextpage creator-output-panes.html
|
||||
\endif
|
||||
|
||||
\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.
|
||||
|
||||
To detach views:
|
@@ -1221,7 +1221,15 @@ ValuesChangedCommand NodeInstanceServer::createValuesChangedCommand(const QVecto
|
||||
|
||||
if (instance.isValid()) {
|
||||
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,
|
||||
propertyValue, PropertyName()));
|
||||
}
|
||||
|
@@ -76,12 +76,12 @@ StudioControls.TextField {
|
||||
id: colorLogic
|
||||
backendValue: lineEdit.backendValue
|
||||
onValueFromBackendChanged: {
|
||||
if (colorLogic.valueFromBackend === undefined)
|
||||
return
|
||||
|
||||
if (writeValueManually) {
|
||||
lineEdit.text = convertColorToString(colorLogic.valueFromBackend)
|
||||
if (colorLogic.valueFromBackend === undefined) {
|
||||
lineEdit.text = ""
|
||||
} else {
|
||||
if (writeValueManually)
|
||||
lineEdit.text = convertColorToString(colorLogic.valueFromBackend)
|
||||
else
|
||||
lineEdit.text = colorLogic.valueFromBackend
|
||||
}
|
||||
__dirty = false
|
||||
|
@@ -7,17 +7,17 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(Qt6 6.2 COMPONENTS Quick REQUIRED)
|
||||
|
||||
qt_add_executable(%{ProjectName}
|
||||
qt_add_executable(%{TargetName}
|
||||
main.cpp
|
||||
)
|
||||
|
||||
qt_add_qml_module(%{ProjectName}
|
||||
qt_add_qml_module(%{TargetName}
|
||||
URI %{ProjectName}
|
||||
VERSION 1.0
|
||||
QML_FILES main.qml %{AdditionalQmlFiles}
|
||||
)
|
||||
|
||||
target_compile_definitions(%{ProjectName}
|
||||
target_compile_definitions(%{TargetName}
|
||||
PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
|
||||
target_link_libraries(%{ProjectName}
|
||||
target_link_libraries(%{TargetName}
|
||||
PRIVATE Qt6::Quick)
|
||||
|
@@ -27,7 +27,8 @@
|
||||
{ "key": "HasTranslation", "value": "%{JS: value('TsFileName') !== ''}" },
|
||||
{ "key": "SetQPAPhysicalSize", "value": "%{UseVirtualKeyboardByDefault}" },
|
||||
{ "key": "AdditionalQmlFiles", "value": "" },
|
||||
{ "key": "AdditionalQmlFilesQbs", "value": "" }
|
||||
{ "key": "AdditionalQmlFilesQbs", "value": "" },
|
||||
{ "key": "TargetName", "value": "%{JS: 'app' + value('ProjectName')}" }
|
||||
],
|
||||
|
||||
"pages":
|
||||
|
15
src/libs/3rdparty/cplusplus/Control.cpp
vendored
@@ -25,6 +25,9 @@
|
||||
#include "CoreTypes.h"
|
||||
#include "Symbols.h"
|
||||
#include "Names.h"
|
||||
|
||||
#include <QList>
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
@@ -844,3 +847,15 @@ void Control::addSymbol(Symbol *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;
|
||||
}
|
||||
|
2
src/libs/3rdparty/cplusplus/Control.h
vendored
@@ -218,6 +218,8 @@ public:
|
||||
bool hasSymbol(Symbol *symbol) const;
|
||||
void addSymbol(Symbol *symbol);
|
||||
|
||||
const Name *toName(const QList<const Name *> &names);
|
||||
|
||||
private:
|
||||
class Data;
|
||||
friend class Data;
|
||||
|
@@ -22,7 +22,6 @@ HEADERS += \
|
||||
src/lib/format_p.h \
|
||||
src/lib/htmlhighlighter.h \
|
||||
src/lib/keywordlist_p.h \
|
||||
src/lib/ksyntaxhighlighting_export.h \
|
||||
src/lib/matchresult_p.h \
|
||||
src/lib/repository.h \
|
||||
src/lib/repository_p.h \
|
||||
|
@@ -283,8 +283,21 @@ public:
|
||||
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
|
||||
@@ -317,6 +330,36 @@ public: // attributes
|
||||
SubstitutionEnvironment *env;
|
||||
RewriteType rewriteType;
|
||||
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()
|
||||
|
@@ -241,19 +241,6 @@ static bool symbolIdentical(Symbol *s1, Symbol *s2)
|
||||
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)
|
||||
{
|
||||
const QList<LookupItem> items = con->find(name);
|
||||
@@ -282,12 +269,12 @@ const Name *LookupContext::minimalName(Symbol *symbol, ClassOrNamespace *target,
|
||||
// eliminate inline namespaces
|
||||
QList<const Name *> minimal = names;
|
||||
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))
|
||||
minimal.removeAt(i);
|
||||
}
|
||||
|
||||
return toName(minimal, control);
|
||||
return control->toName(minimal);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
@@ -819,15 +819,6 @@ FilePath FilePath::symLinkTarget() const
|
||||
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
|
||||
{
|
||||
if (needsDevice()) {
|
||||
@@ -1182,11 +1173,11 @@ QString FilePath::calcRelativePath(const QString &absolutePath, const QString &a
|
||||
*/
|
||||
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;
|
||||
if (sameDevice)
|
||||
return *this;
|
||||
// TODO: converting paths between different non local devices is still unsupported
|
||||
QTC_CHECK(!needsDevice() || sameDevice);
|
||||
QTC_CHECK(!needsDevice());
|
||||
FilePath res;
|
||||
res.m_scheme = deviceTemplate.m_scheme;
|
||||
res.m_host = deviceTemplate.m_host;
|
||||
|
@@ -162,9 +162,6 @@ public:
|
||||
QDir::Filters filters = QDir::NoFilter,
|
||||
QDirIterator::IteratorFlags flags = QDirIterator::NoIteratorFlags) const;
|
||||
|
||||
[[nodiscard]] FilePath mapToGlobalPath() const;
|
||||
[[nodiscard]] QString mapToDevicePath() const;
|
||||
|
||||
// makes sure that capitalization of directories is canonical
|
||||
// on Windows and macOS. This is rarely needed.
|
||||
[[nodiscard]] FilePath normalizedPathName() const;
|
||||
@@ -194,6 +191,7 @@ private:
|
||||
friend class ::tst_fileutils;
|
||||
static QString calcRelativePath(const QString &absolutePath, const QString &absoluteAnchorPath);
|
||||
void setFromString(const QString &filepath);
|
||||
[[nodiscard]] QString mapToDevicePath() const;
|
||||
|
||||
QString m_scheme;
|
||||
QString m_host;
|
||||
|
@@ -359,49 +359,89 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
static QList<AstNode> getAstPath(const AstNode &root, const Range &range)
|
||||
class AstPathCollector
|
||||
{
|
||||
QList<AstNode> path;
|
||||
QList<AstNode> queue{root};
|
||||
bool isRoot = true;
|
||||
public:
|
||||
AstPathCollector(const AstNode &root, const Range &range) : m_root(root), m_range(range) {}
|
||||
|
||||
while (!queue.isEmpty()) {
|
||||
AstNode curNode = queue.takeFirst();
|
||||
if (!isRoot && !curNode.hasRange())
|
||||
continue;
|
||||
if (curNode.range() == range)
|
||||
return path << curNode;
|
||||
if (isRoot || curNode.range().contains(range)) {
|
||||
path << curNode;
|
||||
const auto children = curNode.children();
|
||||
QList<AstNode> collectPath()
|
||||
{
|
||||
if (!m_root.isValid())
|
||||
return {};
|
||||
visitNode(m_root, true);
|
||||
return m_done ? m_path : m_longestSubPath;
|
||||
}
|
||||
|
||||
private:
|
||||
void visitNode(const AstNode &node, bool isRoot = false)
|
||||
{
|
||||
if (!isRoot && (!node.hasRange() || !node.range().contains(m_range)))
|
||||
return;
|
||||
m_path << node;
|
||||
|
||||
class PathDropper {
|
||||
public:
|
||||
PathDropper(AstPathCollector &collector) : m_collector(collector) {};
|
||||
~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)
|
||||
break;
|
||||
if (curNode.kind() == "Function" || curNode.role() == "expression") {
|
||||
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.
|
||||
queue = *children;
|
||||
childrenToCheck = *children;
|
||||
} else {
|
||||
queue.clear();
|
||||
for (auto it = std::lower_bound(children->cbegin(), children->cend(), m_range,
|
||||
leftOfRange);
|
||||
it != children->cend() && !m_range.isLeftOf(it->range()); ++it) {
|
||||
childrenToCheck << *it;
|
||||
}
|
||||
}
|
||||
|
||||
const bool wasDone = m_done;
|
||||
for (const AstNode &child : qAsConst(childrenToCheck)) {
|
||||
visitNode(child);
|
||||
if (m_done && !wasDone)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
static const auto leftOfRange = [](const AstNode &node, const Range &range) {
|
||||
return node.range().isLeftOf(range) && !node.arcanaContains(" implicit ");
|
||||
};
|
||||
|
||||
for (auto it = std::lower_bound(children->cbegin(), children->cend(), range,
|
||||
leftOfRange);
|
||||
it != children->cend() && !range.isLeftOf(it->range()); ++it) {
|
||||
queue << *it;
|
||||
}
|
||||
}
|
||||
}
|
||||
isRoot = false;
|
||||
}
|
||||
return path;
|
||||
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)
|
||||
@@ -521,8 +561,10 @@ static BaseClientInterface *clientInterface(Project *project, const Utils::FileP
|
||||
const CppEditor::ClangdSettings settings(CppEditor::ClangdProjectSettings(project).settings());
|
||||
if (!settings.indexingEnabled())
|
||||
indexingOption += "=0";
|
||||
Utils::CommandLine cmd{settings.clangdFilePath(), {indexingOption, "--limit-results=0",
|
||||
"--clang-tidy=0"}};
|
||||
const QString headerInsertionOption = QString("--header-insertion=")
|
||||
+ (settings.autoIncludeHeaders() ? "iwyu" : "never");
|
||||
Utils::CommandLine cmd{settings.clangdFilePath(), {indexingOption, headerInsertionOption,
|
||||
"--limit-results=0", "--clang-tidy=0"}};
|
||||
if (settings.workerThreadLimit() != 0)
|
||||
cmd.addArg("-j=" + QString::number(settings.workerThreadLimit()));
|
||||
if (!jsonDbDir.isEmpty())
|
||||
@@ -2332,7 +2374,7 @@ static void semanticHighlighter(QFutureInterface<HighlightingResult> &future,
|
||||
return false;
|
||||
for (auto it = path.rbegin() + 1; it != path.rend(); ++it) {
|
||||
if (it->kind() == "Call" || it->kind() == "CXXConstruct"
|
||||
|| it->kind() == "MemberInitializer") {
|
||||
|| it->kind() == "MemberInitializer" || it->kind() == "CXXOperatorCall") {
|
||||
return true;
|
||||
}
|
||||
if (it->kind().endsWith("Cast") && it->hasConstType())
|
||||
|
@@ -1040,7 +1040,7 @@ void ClangdTestHighlighting::test_data()
|
||||
QTest::newRow("typedef as underlying type in enum declaration") << 424 << 21 << 424 << 39
|
||||
<< QList<int>{C_TYPE} << 0;
|
||||
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
|
||||
<< QList<int>{C_TYPE, C_DECLARATION} << 0;
|
||||
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;
|
||||
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("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()
|
||||
|
@@ -818,3 +818,14 @@ void staticMemberFuncTest() {
|
||||
int i;
|
||||
s.staticFunc(i);
|
||||
}
|
||||
|
||||
void lambdaArgTest()
|
||||
{
|
||||
const auto foo1 = [](int &) {};
|
||||
const auto foo2 = [](int) {};
|
||||
int val;
|
||||
foo1(val);
|
||||
foo2(val);
|
||||
[](int &) {}(val);
|
||||
[](int) {}(val);
|
||||
}
|
||||
|
@@ -144,7 +144,7 @@ MakeInstallCommand CMakeProject::makeInstallCommand(const Target *target,
|
||||
if (bc)
|
||||
buildDirectory = bc->buildDirectory();
|
||||
|
||||
cmd.arguments << "--build" << buildDirectory.onDevice(cmd.command).mapToDevicePath()
|
||||
cmd.arguments << "--build" << buildDirectory.onDevice(cmd.command).path()
|
||||
<< "--target" << installTarget << config;
|
||||
|
||||
cmd.environment.set("DESTDIR", QDir::toNativeSeparators(installRoot));
|
||||
|
@@ -69,6 +69,7 @@ static QString clangdSettingsKey() { return QLatin1String("ClangdSettings"); }
|
||||
static QString useClangdKey() { return QLatin1String("UseClangd"); }
|
||||
static QString clangdPathKey() { return QLatin1String("ClangdPath"); }
|
||||
static QString clangdIndexingKey() { return QLatin1String("ClangdIndexing"); }
|
||||
static QString clangdHeaderInsertionKey() { return QLatin1String("ClangdHeaderInsertion"); }
|
||||
static QString clangdThreadLimitKey() { return QLatin1String("ClangdThreadLimit"); }
|
||||
static QString clangdDocumentThresholdKey() { return QLatin1String("ClangdDocumentThreshold"); }
|
||||
static QString clangdUseGlobalSettingsKey() { return QLatin1String("useGlobalSettings"); }
|
||||
@@ -405,6 +406,7 @@ QVariantMap ClangdSettings::Data::toMap() const
|
||||
if (executableFilePath != fallbackClangdFilePath())
|
||||
map.insert(clangdPathKey(), executableFilePath.toString());
|
||||
map.insert(clangdIndexingKey(), enableIndexing);
|
||||
map.insert(clangdHeaderInsertionKey(), autoIncludeHeaders);
|
||||
map.insert(clangdThreadLimitKey(), workerThreadLimit);
|
||||
map.insert(clangdDocumentThresholdKey(), documentUpdateThreshold);
|
||||
return map;
|
||||
@@ -415,6 +417,7 @@ void ClangdSettings::Data::fromMap(const QVariantMap &map)
|
||||
useClangd = map.value(useClangdKey(), false).toBool();
|
||||
executableFilePath = FilePath::fromString(map.value(clangdPathKey()).toString());
|
||||
enableIndexing = map.value(clangdIndexingKey(), true).toBool();
|
||||
autoIncludeHeaders = map.value(clangdHeaderInsertionKey(), false).toBool();
|
||||
workerThreadLimit = map.value(clangdThreadLimitKey(), 0).toInt();
|
||||
documentUpdateThreshold = map.value(clangdDocumentThresholdKey(), 500).toInt();
|
||||
}
|
||||
|
@@ -110,6 +110,7 @@ public:
|
||||
int workerThreadLimit = 0;
|
||||
bool useClangd = false;
|
||||
bool enableIndexing = true;
|
||||
bool autoIncludeHeaders = false;
|
||||
int documentUpdateThreshold = 500;
|
||||
};
|
||||
|
||||
@@ -121,6 +122,7 @@ public:
|
||||
static void setDefaultClangdPath(const Utils::FilePath &filePath);
|
||||
Utils::FilePath clangdFilePath() const;
|
||||
bool indexingEnabled() const { return m_data.enableIndexing; }
|
||||
bool autoIncludeHeaders() const { return m_data.autoIncludeHeaders; }
|
||||
int workerThreadLimit() const { return m_data.workerThreadLimit; }
|
||||
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.workerThreadLimit == s2.workerThreadLimit
|
||||
&& s1.enableIndexing == s2.enableIndexing
|
||||
&& s1.autoIncludeHeaders == s2.autoIncludeHeaders
|
||||
&& s1.documentUpdateThreshold == s2.documentUpdateThreshold;
|
||||
}
|
||||
inline bool operator!=(const ClangdSettings::Data &s1, const ClangdSettings::Data &s2)
|
||||
|
@@ -197,6 +197,7 @@ class ClangdSettingsWidget::Private
|
||||
public:
|
||||
QCheckBox useClangdCheckBox;
|
||||
QCheckBox indexingCheckBox;
|
||||
QCheckBox autoIncludeHeadersCheckBox;
|
||||
QSpinBox threadLimitSpinBox;
|
||||
QSpinBox documentUpdateThreshold;
|
||||
Utils::PathChooser clangdChooser;
|
||||
@@ -217,6 +218,9 @@ ClangdSettingsWidget::ClangdSettingsWidget(const ClangdSettings::Data &settingsD
|
||||
"If background indexing is enabled, global symbol searches will yield\n"
|
||||
"more accurate results, at the cost of additional CPU load when\n"
|
||||
"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.setSpecialValueText("Automatic");
|
||||
d->documentUpdateThreshold.setMinimum(50);
|
||||
@@ -237,6 +241,8 @@ ClangdSettingsWidget::ClangdSettingsWidget(const ClangdSettings::Data &settingsD
|
||||
formLayout->addRow(QString(), &d->versionWarningLabel);
|
||||
const auto indexingLabel = new QLabel(tr("Enable background indexing:"));
|
||||
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;
|
||||
threadLimitLayout->addWidget(&d->threadLimitSpinBox);
|
||||
threadLimitLayout->addStretch(1);
|
||||
@@ -255,6 +261,8 @@ ClangdSettingsWidget::ClangdSettingsWidget(const ClangdSettings::Data &settingsD
|
||||
d->clangdChooser.setEnabled(checked);
|
||||
indexingLabel->setEnabled(checked);
|
||||
d->indexingCheckBox.setEnabled(checked);
|
||||
autoIncludeHeadersLabel->setEnabled(checked);
|
||||
d->autoIncludeHeadersCheckBox.setEnabled(checked);
|
||||
d->threadLimitSpinBox.setEnabled(checked);
|
||||
d->versionWarningLabel.setEnabled(checked);
|
||||
};
|
||||
@@ -312,6 +320,8 @@ ClangdSettingsWidget::ClangdSettingsWidget(const ClangdSettings::Data &settingsD
|
||||
this, &ClangdSettingsWidget::settingsDataChanged);
|
||||
connect(&d->indexingCheckBox, &QCheckBox::toggled,
|
||||
this, &ClangdSettingsWidget::settingsDataChanged);
|
||||
connect(&d->autoIncludeHeadersCheckBox, &QCheckBox::toggled,
|
||||
this, &ClangdSettingsWidget::settingsDataChanged);
|
||||
connect(&d->threadLimitSpinBox, qOverload<int>(&QSpinBox::valueChanged),
|
||||
this, &ClangdSettingsWidget::settingsDataChanged);
|
||||
connect(&d->clangdChooser, &Utils::PathChooser::pathChanged,
|
||||
@@ -329,6 +339,7 @@ ClangdSettings::Data ClangdSettingsWidget::settingsData() const
|
||||
data.useClangd = d->useClangdCheckBox.isChecked();
|
||||
data.executableFilePath = d->clangdChooser.filePath();
|
||||
data.enableIndexing = d->indexingCheckBox.isChecked();
|
||||
data.autoIncludeHeaders = d->autoIncludeHeadersCheckBox.isChecked();
|
||||
data.workerThreadLimit = d->threadLimitSpinBox.value();
|
||||
data.documentUpdateThreshold = d->documentUpdateThreshold.value();
|
||||
return data;
|
||||
|
@@ -4707,6 +4707,43 @@ N::S N::foo(const S &s)
|
||||
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()
|
||||
{
|
||||
QTest::addColumn<QByteArrayList>("headers");
|
||||
|
@@ -155,6 +155,7 @@ private slots:
|
||||
void testInsertDefFromDeclTemplateFunction();
|
||||
void testInsertDefFromDeclNotTriggeredForFriendFunc();
|
||||
void testInsertDefFromDeclMinimalFunctionParameterType();
|
||||
void testInsertDefFromDeclAliasTemplateAsReturnType();
|
||||
void testInsertDefsFromDecls_data();
|
||||
void testInsertDefsFromDecls();
|
||||
|
||||
|
@@ -25,32 +25,10 @@
|
||||
|
||||
#include "customexecutablerunconfiguration.h"
|
||||
|
||||
#include "abi.h"
|
||||
#include "buildconfiguration.h"
|
||||
#include "devicesupport/devicemanager.h"
|
||||
#include "environmentaspect.h"
|
||||
#include "localenvironmentaspect.h"
|
||||
#include "project.h"
|
||||
#include "runcontrol.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;
|
||||
|
||||
namespace ProjectExplorer {
|
||||
@@ -86,9 +64,9 @@ CustomExecutableRunConfiguration::CustomExecutableRunConfiguration(Target *targe
|
||||
setDefaultDisplayName(defaultDisplayName());
|
||||
}
|
||||
|
||||
QString CustomExecutableRunConfiguration::rawExecutable() const
|
||||
FilePath CustomExecutableRunConfiguration::executable() const
|
||||
{
|
||||
return aspect<ExecutableAspect>()->executable().toString();
|
||||
return aspect<ExecutableAspect>()->executable();
|
||||
}
|
||||
|
||||
bool CustomExecutableRunConfiguration::isEnabled() const
|
||||
@@ -116,16 +94,15 @@ Runnable CustomExecutableRunConfiguration::runnable() const
|
||||
|
||||
QString CustomExecutableRunConfiguration::defaultDisplayName() const
|
||||
{
|
||||
if (rawExecutable().isEmpty())
|
||||
if (executable().isEmpty())
|
||||
return tr("Custom Executable");
|
||||
else
|
||||
return tr("Run %1").arg(QDir::toNativeSeparators(rawExecutable()));
|
||||
return tr("Run %1").arg(executable().toUserOutput());
|
||||
}
|
||||
|
||||
Tasks CustomExecutableRunConfiguration::checkForIssues() const
|
||||
{
|
||||
Tasks tasks;
|
||||
if (rawExecutable().isEmpty()) {
|
||||
if (executable().isEmpty()) {
|
||||
tasks << createConfigurationIssue(tr("You need to set an executable in the custom run "
|
||||
"configuration."));
|
||||
}
|
||||
|
@@ -46,7 +46,7 @@ private:
|
||||
Tasks checkForIssues() const override;
|
||||
|
||||
void configurationDialogFinished();
|
||||
QString rawExecutable() const;
|
||||
Utils::FilePath executable() const;
|
||||
};
|
||||
|
||||
class CustomExecutableRunConfigurationFactory : public FixedRunConfigurationFactory
|
||||
|
@@ -54,6 +54,7 @@ DesktopDeviceProcess::DesktopDeviceProcess(const QSharedPointer<const IDevice> &
|
||||
void DesktopDeviceProcess::start(const Runnable &runnable)
|
||||
{
|
||||
QTC_ASSERT(m_process.state() == QProcess::NotRunning, return);
|
||||
if (runnable.environment.size())
|
||||
m_process.setEnvironment(runnable.environment);
|
||||
m_process.setWorkingDirectory(runnable.workingDirectory);
|
||||
m_process.setCommand(runnable.command);
|
||||
|
@@ -167,7 +167,7 @@ void PropertyEditorValue::setValue(const QVariant &value)
|
||||
fixAmbigousColorNames(modelNode(), name(), &m_value);
|
||||
fixUrl(modelNode(), name(), &m_value);
|
||||
|
||||
if (m_value.isValid() && !colorsEqual)
|
||||
if (!colorsEqual)
|
||||
emit valueChangedQml();
|
||||
|
||||
emit isExplicitChanged();
|
||||
|
@@ -225,6 +225,8 @@ private: // functions
|
||||
void updateWatcher(const QString &path);
|
||||
|
||||
void updateRotationBlocks();
|
||||
void maybeResetOnPropertyChange(const PropertyName &name, const ModelNode &node,
|
||||
PropertyChangeFlags flags);
|
||||
|
||||
private:
|
||||
QHash<QString, ModelNodePreviewImageData> m_imageDataMap;
|
||||
|
@@ -473,8 +473,9 @@ void NodeInstanceView::propertiesAboutToBeRemoved(const QList<AbstractProperty>&
|
||||
resetVerticalAnchors(property.parentModelNode());
|
||||
} else if (name == "anchors.baseline") {
|
||||
resetVerticalAnchors(property.parentModelNode());
|
||||
} else if (name == "shader" && property.parentModelNode().isSubclassOf("QtQuick3D.Shader")) {
|
||||
m_resetTimer.start();
|
||||
} else {
|
||||
maybeResetOnPropertyChange(name, property.parentModelNode(),
|
||||
AbstractView::EmptyPropertiesRemoved);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -503,10 +504,14 @@ void NodeInstanceView::nodeTypeChanged(const ModelNode &, const TypeName &, int,
|
||||
restartProcess();
|
||||
}
|
||||
|
||||
void NodeInstanceView::bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags /*propertyChange*/)
|
||||
void NodeInstanceView::bindingPropertiesChanged(const QList<BindingProperty>& propertyList,
|
||||
PropertyChangeFlags propertyChange)
|
||||
{
|
||||
QTC_ASSERT(m_nodeInstanceServer, return);
|
||||
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
|
||||
*/
|
||||
|
||||
void NodeInstanceView::variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags /*propertyChange*/)
|
||||
void NodeInstanceView::variantPropertiesChanged(const QList<VariantProperty>& propertyList,
|
||||
PropertyChangeFlags propertyChange)
|
||||
{
|
||||
QTC_ASSERT(m_nodeInstanceServer, return);
|
||||
updatePosition(propertyList);
|
||||
m_nodeInstanceServer->changePropertyValues(createChangeValueCommand(propertyList));
|
||||
|
||||
for (const auto &property : propertyList) {
|
||||
if (property.name() == "shader" && property.parentModelNode().isSubclassOf("QtQuick3D.Shader")) {
|
||||
m_resetTimer.start();
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (const auto &property : propertyList)
|
||||
maybeResetOnPropertyChange(property.name(), property.parentModelNode(), propertyChange);
|
||||
}
|
||||
/*!
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -32,9 +32,9 @@
|
||||
#include <projectexplorer/task.h>
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QFileInfo>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
using namespace Utils;
|
||||
|
||||
namespace RemoteLinux {
|
||||
namespace Internal {
|
||||
@@ -42,8 +42,8 @@ namespace Internal {
|
||||
class AbstractPackagingStepPrivate
|
||||
{
|
||||
public:
|
||||
QString cachedPackageFilePath;
|
||||
QString cachedPackageDirectory;
|
||||
FilePath cachedPackageFilePath;
|
||||
FilePath cachedPackageDirectory;
|
||||
bool deploymentDataModified = false;
|
||||
};
|
||||
|
||||
@@ -67,37 +67,37 @@ AbstractPackagingStep::~AbstractPackagingStep()
|
||||
delete d;
|
||||
}
|
||||
|
||||
QString AbstractPackagingStep::cachedPackageFilePath() const
|
||||
FilePath AbstractPackagingStep::cachedPackageFilePath() const
|
||||
{
|
||||
return d->cachedPackageFilePath;
|
||||
}
|
||||
|
||||
QString AbstractPackagingStep::packageFilePath() const
|
||||
FilePath AbstractPackagingStep::packageFilePath() const
|
||||
{
|
||||
if (packageDirectory().isEmpty())
|
||||
return QString();
|
||||
return packageDirectory() + QLatin1Char('/') + packageFileName();
|
||||
return {};
|
||||
return packageDirectory().pathAppended(packageFileName());
|
||||
}
|
||||
|
||||
QString AbstractPackagingStep::cachedPackageDirectory() const
|
||||
FilePath AbstractPackagingStep::cachedPackageDirectory() const
|
||||
{
|
||||
return d->cachedPackageDirectory;
|
||||
}
|
||||
|
||||
QString AbstractPackagingStep::packageDirectory() const
|
||||
FilePath AbstractPackagingStep::packageDirectory() const
|
||||
{
|
||||
return buildDirectory().toString();
|
||||
return buildDirectory();
|
||||
}
|
||||
|
||||
bool AbstractPackagingStep::isPackagingNeeded() const
|
||||
{
|
||||
QFileInfo packageInfo(packageFilePath());
|
||||
if (!packageInfo.exists() || d->deploymentDataModified)
|
||||
const FilePath packagePath = packageFilePath();
|
||||
if (!packagePath.exists() || d->deploymentDataModified)
|
||||
return true;
|
||||
|
||||
const DeploymentData &dd = target()->deploymentData();
|
||||
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;
|
||||
}
|
||||
|
||||
|
@@ -41,8 +41,8 @@ public:
|
||||
explicit AbstractPackagingStep(ProjectExplorer::BuildStepList *bsl, Utils::Id id);
|
||||
~AbstractPackagingStep() override;
|
||||
|
||||
QString packageFilePath() const;
|
||||
QString cachedPackageFilePath() const;
|
||||
Utils::FilePath packageFilePath() const;
|
||||
Utils::FilePath cachedPackageFilePath() const;
|
||||
bool init() override;
|
||||
|
||||
signals:
|
||||
@@ -54,8 +54,8 @@ protected:
|
||||
|
||||
void raiseError(const QString &errorMessage);
|
||||
void raiseWarning(const QString &warningMessage);
|
||||
QString cachedPackageDirectory() const;
|
||||
QString packageDirectory() const;
|
||||
Utils::FilePath cachedPackageDirectory() const;
|
||||
Utils::FilePath packageDirectory() const;
|
||||
|
||||
virtual bool isPackagingNeeded() const;
|
||||
|
||||
|
@@ -71,9 +71,9 @@ AbstractUploadAndInstallPackageService::~AbstractUploadAndInstallPackageService(
|
||||
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
|
||||
|
@@ -38,7 +38,7 @@ class REMOTELINUX_EXPORT AbstractUploadAndInstallPackageService : public Abstrac
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
void setPackageFilePath(const QString &filePath);
|
||||
void setPackageFilePath(const Utils::FilePath &filePath);
|
||||
|
||||
protected:
|
||||
AbstractUploadAndInstallPackageService();
|
||||
|
@@ -87,11 +87,11 @@ TarPackageCreationStep::TarPackageCreationStep(BuildStepList *bsl, Utils::Id id)
|
||||
m_incrementalDeploymentAspect->setSettingsKey(IncrementalDeploymentKey);
|
||||
|
||||
setSummaryUpdater([this] {
|
||||
QString path = packageFilePath();
|
||||
FilePath path = packageFilePath();
|
||||
if (path.isEmpty())
|
||||
return QString("<font color=\"red\">" + tr("Tarball creation not possible.")
|
||||
+ "</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
|
||||
QFile tarFile(cachedPackageFilePath());
|
||||
const FilePath tarFilePath = cachedPackageFilePath();
|
||||
QFile tarFile(tarFilePath.toString());
|
||||
|
||||
if (!tarFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||
raiseError(tr("Error: tar file %1 cannot be opened (%2).")
|
||||
.arg(QDir::toNativeSeparators(cachedPackageFilePath()), tarFile.errorString()));
|
||||
.arg(tarFilePath.toUserOutput(), tarFile.errorString()));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -311,7 +312,7 @@ bool TarPackageCreationStep::writeHeader(QFile &tarFile, const QFileInfo &fileIn
|
||||
header.chksum[sizeof header.chksum-1] = 0;
|
||||
if (!tarFile.write(reinterpret_cast<char *>(&header), sizeof header)) {
|
||||
raiseError(tr("Error writing tar file \"%1\": %2")
|
||||
.arg(QDir::toNativeSeparators(cachedPackageFilePath()), tarFile.errorString()));
|
||||
.arg(cachedPackageFilePath().toUserOutput(), tarFile.errorString()));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@@ -129,16 +129,17 @@ void UpdateInfoPlugin::startCheckForUpdates()
|
||||
{
|
||||
stopCheckForUpdates();
|
||||
|
||||
Utils::Environment env = Utils::Environment::systemEnvironment();
|
||||
env.set("QT_LOGGING_RULES", "*=false");
|
||||
d->m_checkUpdatesCommand = new ShellCommand({}, env);
|
||||
d->m_checkUpdatesCommand = new ShellCommand({}, Utils::Environment::systemEnvironment());
|
||||
d->m_checkUpdatesCommand->setDisplayName(tr("Checking for Updates"));
|
||||
connect(d->m_checkUpdatesCommand, &ShellCommand::stdOutText, this, &UpdateInfoPlugin::collectCheckForUpdatesOutput);
|
||||
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
|
||||
/*workingDirectory=*/{},
|
||||
[](int /*exitCode*/) { return Utils::QtcProcess::FinishedWithSuccess; });
|
||||
[](int /*exitCode*/) {
|
||||
return Utils::QtcProcess::FinishedWithSuccess;
|
||||
});
|
||||
d->m_checkUpdatesCommand->execute();
|
||||
d->m_progress = d->m_checkUpdatesCommand->futureProgress();
|
||||
if (d->m_progress) {
|
||||
|
@@ -252,8 +252,7 @@ isEmpty(LLVM_VERSION) {
|
||||
# It is not intended for cross compiler linking.
|
||||
LLVM_CXXFLAGS *= $$system($$llvm_config --cxxflags, lines)
|
||||
LLVM_CXXFLAGS ~= s,-fno-exceptions,
|
||||
LLVM_CXXFLAGS ~= s,-std=c++11,
|
||||
LLVM_CXXFLAGS ~= s,-std=c++0x,
|
||||
LLVM_CXXFLAGS ~= s,-std.c\+\+..,
|
||||
LLVM_CXXFLAGS ~= s,-O\S*,
|
||||
LLVM_CXXFLAGS ~= s,/O\S*,
|
||||
LLVM_CXXFLAGS ~= s,/W4,
|
||||
|
@@ -96,7 +96,7 @@
|
||||
: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.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'}
|
||||
: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'}
|
||||
@@ -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::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_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::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'}
|
||||
|
@@ -276,11 +276,12 @@ def createProject_Qt_Console(path, projectName, checks = True, buildSystem = Non
|
||||
if checks:
|
||||
__verifyFileCreation__(path, expectedFiles)
|
||||
|
||||
|
||||
def createNewQtQuickApplication(workingDir, projectName=None,
|
||||
targets=Targets.desktopTargetClasses(), minimumQtVersion="5.12",
|
||||
template="Qt Quick Application - Empty", fromWelcome=False,
|
||||
template="Qt Quick Application", fromWelcome=False,
|
||||
buildSystem=None):
|
||||
available = __createProjectOrFileSelectType__(" Application (Qt Quick)", template, fromWelcome)
|
||||
available = __createProjectOrFileSelectType__(" Application (Qt)", template, fromWelcome)
|
||||
projectName = __createProjectSetNameAndPath__(workingDir, projectName)
|
||||
__handleBuildSystem__(buildSystem)
|
||||
requiredQt = __createProjectHandleQtQuickSelection__(minimumQtVersion)
|
||||
|
@@ -172,6 +172,7 @@ def cleanUpUserFiles(pathsToProFiles=None):
|
||||
doneWithoutErrors = False
|
||||
return doneWithoutErrors
|
||||
|
||||
|
||||
def invokeMenuItem(menu, item, *subItems):
|
||||
if platform.system() == "Darwin":
|
||||
try:
|
||||
@@ -191,10 +192,9 @@ def invokeMenuItem(menu, item, *subItems):
|
||||
activateItem(itemObject)
|
||||
numberedPrefix = "(&\\d \| )?"
|
||||
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
|
||||
if subItem.startswith(numberedPrefix):
|
||||
# TODO: Find fix for Qt 6
|
||||
actions = sub.actions()
|
||||
triggered = False
|
||||
for i in range(actions.count()):
|
||||
@@ -211,9 +211,10 @@ def invokeMenuItem(menu, item, *subItems):
|
||||
"Function arguments: '%s', '%s', %s" % (menu, item, str(subItems)))
|
||||
break # we failed to trigger - no need to process subItems further
|
||||
else:
|
||||
itemObject = waitForObjectItem(sub, subItem)
|
||||
itemObject = waitForObjectItem(itemObject, subItem)
|
||||
activateItem(itemObject)
|
||||
|
||||
|
||||
def logApplicationOutput():
|
||||
# make sure application output is shown
|
||||
ensureChecked(":Qt Creator_AppOutput_Core::Internal::OutputPaneToggleButton")
|
||||
|