Merge "Merge remote-tracking branch 'origin/5.0'"

This commit is contained in:
The Qt Project
2021-08-26 11:07:04 +00:00
114 changed files with 1832 additions and 633 deletions
+7 -2
View File
@@ -213,9 +213,14 @@ While the plugin builds without it, it might not be fully functional.
Note that the plugin is disabled by default.
## Third-party Components
# Licenses and Attributions
Qt Creator includes the following third-party components,
Qt Creator is available under commercial licenses from The Qt Company,
and under the GNU General Public License version 3,
annotated with The Qt Company GPL Exception 1.0.
See [LICENSE.GPL-EXCEPT](LICENSE.GPL-EXCEPT) for the details.
Qt Creator furthermore includes the following third-party components,
we thank the authors who made this possible:
### YAML Parser yaml-cpp (MIT License)
+20
View File
@@ -22,6 +22,7 @@ Editing
* Added menu item and shortcut for editing bookmark comments
(QTCREATORBUG-25696)
* Fixed folding for Markdown (QTCREATORBUG-25882)
* Fixed completion tooltip on secondary display (QTCREATORBUG-26053)
### C++
@@ -49,6 +50,7 @@ Editing
* Fixed reformatting of functions with default values (QTCREATORBUG-23009)
* Fixed wrong warning for types with same name but different namespace
(QTCREATORBUG-24615)
* Fixed `Tools > External > Qt Quick > QML Utility` (QTCREATORBUG-26137)
### Language Client
@@ -56,12 +58,18 @@ Editing
* Added support for snippets (QTCREATORBUG-22406)
* Fixed completion results for language servers that do not filter results
themselves
* Fixed that empty responses could be sent (QTCREATORBUG-26116)
### Beautifier
* Fixed issue with `clang-format` and multi-byte characters (QTCREATORBUG-21812,
QTCREATORBUG-23131)
### Designer
* Fixed `Go to Slot` if UI class is referred to as `UI_<class>`
(QTCREATORBUG-26013)
Projects
--------
@@ -76,6 +84,8 @@ Projects
* Fixed missing update of run configuration environment (QTCREATORBUG-25947)
* Fixed that user files were unnecessarily saved with new time stamp
(QTCREATORBUG-25921)
* Fixed that toolchain setting was fixed for auto-detected kits
(QTCREATORBUG-25839)
* Reduced UI freeze after loading projects (QTCREATORBUG-25783)
### CMake
@@ -83,10 +93,15 @@ Projects
* Removed option `Auto-create build directories`, making this the default
behavior (QTCREATORBUG-25532)
* Added CMake output to right side of `Projects` mode (QTCREATORBUG-25522)
* Added CMake option `QT_CREATOR_SKIP_PACKAGE_MANAGER_SETUP` for skipping Qt
Creator's package manager auto-setup
* Fixed `Jump to File` for file names with special characters
(QTCREATORBUG-25572)
* Fixed updating of available targets (QTCREATORBUG-24914, QTCREATORBUG-25906)
* Fixed persistence of CMake tool options (QTCREATORBUG-25911)
* Fixed build library search path for CMake 3.20 and later (QTCREATORBUG-26110)
* Fixed code model issues with MSVC and CMake 3.20 and later
(QTCREATORBUG-26146)
### Qbs
@@ -144,6 +159,11 @@ Platforms
* Fixed detection of `_prepare_apk_dir` target for CMake projects
(QTCREATORBUG-25216)
### Remote Linux
* Fixed update of temporary local installation when build path is changed
(QTCREATORBUG-26103)
### QNX
* Fixed device configuration
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 65 KiB

@@ -38,9 +38,9 @@
the components available on MCUs are displayed in \l Library >
\uicontrol Components. Only a subset of properties is supported for the
supported components. The properties that are not available on MCUs are
marked in the \l Properties view by enclosing them in square brackets.
marked in the \l Properties view with strikethrough text.
\image qmldesigner-mcu-support.png "Components and Image properties supported for MCUs"
\image qmldesigner-mcu-support.png "Components and Text properties supported for MCUs"
For more information about the supported components and their properties,
see \l{Qt for MCUs - All QML Types}.
@@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -93,174 +93,151 @@
\section1 Selecting Project Type
You can use wizards to create following types of projects:
\list
\li Application (Qt Quick)
\list
\li Qt Quick Application - Empty
Create an empty \l{Qt Quick} application that uses Qt Quick 2
types.
You can build the application and deploy it to desktop,
embedded, and mobile target platforms.
\li Qt Quick Application - Scroll, Stack, or Swipe
Create a Qt Quick application that uses \l{Qt Quick Controls} to
implement a scrollable list (requires Qt 5.9 or later) or a set
of pages with a stack-based or swipe-based navigation model
(requires Qt 5.7 or later).
\endlist
\li Application (Qt)
\list
The following table lists the wizard templates for creating projects.
\table
\header
\li Category
\li Wizard Template
\li Purpose
\row
\li Application (Qt for MCU)
\li MCU Support Application
\li Creates an application that uses a subset of Qt QML and
Qt Quick Controls types (as supported by Qt for MCUs) that
you can deploy, run, and debug on MCU boards. For more
information, see \l {Connecting MCUs}.
\row
\li {1,2} Application (Qt)
\li Qt Widgets Application
Use \QD forms to design a Qt widget based user interface for the
desktop and C++ to implement the application logic
\li Uses \QD forms to design a Qt widget based user interface for
the desktop and C++ to implement the application logic.
\row
\li Qt Console Application
Use a single main.cpp file
\endlist
\li Application (Qt for Python)
\list
\li Qt for Python Application - Empty, Window, Window (UI file), or
Qt Quick Application (Empty)
Create a \l{https://doc.qt.io/qtforpython/index.html}
\li Uses a single main.cpp file.
\row
\li {1,4} Application (Qt Quick)
\li Qt Quick Application - Empty
\li Creates a Qt Quick 2 application project that can contain both
QML and C++ code. You can build the application and deploy it
to desktop, embedded, and mobile target platforms.
\row
\li Qt Quick Application - Scroll
\li Uses the \l{ScrollView} component to implement a scrollable
list view (requires Qt 5.9 or later).
\row
\li Qt Quick Application - Stack
\li Uses the \l{StackView} component to implement a set of pages
with a stack-based navigation model (requires Qt 5.7 or later).
\row
\li Qt Quick Application - Swipe
\li Uses the \l{SwipeView} component to implement a set of pages
with a swipe-based navigation model (requires Qt 5.7 or later).
\row
\li {1,4} Application (Qt for Python)
\li Qt for Python - Empty
\li Creates a \l{https://doc.qt.io/qtforpython/index.html}
{Qt for Python} application that contains only the main
code for a QApplication or an empty window with or without
a widget-based UI. Alternatively, you can create an empty
Qt Quick Application.
\endlist
\li Application (Qt for MCU)
\list
\li MCU Support Application
Creates an application that uses a subset of Qt QML and
Qt Quick Controls types (as supported by Qt for MCUs) that
you can deploy, run, and debug on MCU boards. For more
information, see \l {Connecting MCUs}.
\endlist
\li Libraries
\list
code for a QApplication.
\row
\li Qt for Python - Window
\li Creates a Qt for Python application that contains an empty
window.
\row
\li Qt for Python - Window (UI file)
\li Creates a Qt for Python application that contains an empty
window with a widget-based UI.
\row
\li Qt for Python - Qt Quick Application
\li Creates a Python project that contains an empty Qt Quick
Application.
\row
\li {1,3} Library
\li C++ Library
Shared or static C++ library based on qmake
\li A shared or static C++ library based on qmake.
\row
\li Qt Quick 2 Extension Plugin
C++ plugin that makes it possible to offer extensions that can
be loaded dynamically into Qt Quick 2 applications by using the
QQmlEngine class
\li Creates a C++ plugin that makes it possible to offer extensions
that can be loaded dynamically into Qt Quick 2 applications
by using the QQmlEngine class.
\row
\li \QC Plugin
\endlist
\li Other Projects
\list
\li Auto Test Project
Projects with boilerplate code for a Qt or Google test. For more
information, see \l {Creating Tests}.
\li Creates a \QC plugin.
\row
\li {1,6} Other Project
\li Qt Custom Designer Widget
\li Creates a custom \QD widget or widget collection.
\row
\li Qt Quick UI Prototype
\li Creates a \l{Creating Qt Quick UI Projects}{Qt Quick UI project}
with a single QML file that contains the main view. You can
preview Qt Quick 2 UI projects in the
\l{Validating with Target Hardware}{QML Scene preview tool}.
You do not need to build them, because they do not contain any
C++ code.
Use a single QML file that contains the main view. You can
review \l{Creating Qt Quick UI Projects}{Qt Quick UI prototypes}
in a \l{Previewing QML Files}{preview tool} and you need not
build them. Qt Quick UI prototypes cannot be deployed to embedded
or mobile target platforms. For those platforms, create a
Qt Quick application instead.
\li Qt Custom Designer Widgets
Custom \QD widget or widget collection
\li Empty qmake Project
Empty qmake project that is based on qmake but does not use any
default classes
Use this template only if you are prototyping. You cannot create
a full application by using this template.
Qt Quick UI projects cannot be deployed to embedded or mobile
target platforms. For those platforms, create a Qt Quick
application instead.
\row
\li Auto Test Project
\li Creates a project with boilerplate code for a Qt or Google
test. For more information, see \l {Creating Tests}.
\row
\li Subdirs Project
Subprojects that enable you to structure your qmake projects as
a tree hierarchy
\li Creates a subproject that enables you to structure your qmake
projects as a tree hierarchy.
\row
\li Empty qmake Project
\li Creates an empty qmake project that is based on qmake but does
not use any default classes.
\row
\li Code Snippet
Creates a qmake project from a code snippet. When fixing bug
\li Creates a qmake project from a code snippet. When fixing bug
reports that contain a code snippet, you can place the code
snippet into a project to compile and check it.
\endlist
\li Non-Qt Projects
\list
\li Plain C or C++ Application
Plain C or C++ application that uses qmake, Qbs, or CMake but does
not use the Qt library
\li Nim or Nimble Applications (experimental)
Nim or Nimble application that uses Nimble, but does not use
the Qt library
For more information, see \l {Setting Up Nimble}.
\endlist
\li Import Project
\list
\li Project from version control
Import a project from a supported version control system. For more
information on how version control systems are integrated in
\QC, see \l{Using Version Control Systems}
\li Import as qmake Project
Import an existing project that does not use any of the supported
build systems: qmake, Qbs, CMake, or Autotools. The wizard creates
a qmake .pro file, which enables you to use \QC as a code editor and
as a launcher for debugging and analysis tools. However, if you want
to build the project, you might need to edit the generated .pro
file.
\li Import Existing Project
Import an existing project that does not use any of the supported
build systems: qmake, Qbs, CMake, or Autotools. This enables you to
use \QC as a code editor
\endlist
\endlist
\row
\li {1,4} Non-Qt Project
\li Plain C Application
\li Creates a plain C application that uses qmake, Qbs, or CMake
but does not use the Qt library.
\row
\li Plain C++ Application
\li Creates a plain C++ application that uses qmake, Qbs, or CMake
but does not use the Qt library.
\row
\li Nim Application (experimental)
\li Creates a Nim application that uses Nimble, but does not use the
Qt library. For more information, see \l {Setting Up Nimble}.
\row
\li Nimble Application (experimental)
\li Creates a Nimble application that uses Nimble, but does not use
the Qt library. For more information, see
\l {Setting Up Nimble}.
\row
\li {1,3} Import Project
\li Project from version control
\li Imports a project from a supported version control system, such
as Bazaar, CVS, Git, Mercurial, or Subversion. For
more information on how version control systems are integrated
in \QC, see \l{Using Version Control Systems}.
\row
\li Import as qmake or CMake Project (Limited Functionality)
\li Imports an existing project that does not use any of the
supported build systems: qmake, Qbs, CMake, or Autotools. The
template creates a project file, which enables you to use
\QC as a code editor and as a launcher for debugging and
analysis tools. However, if you want to build the project,
you might need to edit the generated project file.
\row
\li Import Existing Project
\li Imports an existing project that does not use any of the
supported build systems: qmake, Qbs, CMake, or Autotools.
This enables you to use \QC as a code editor.
\endtable
To create a new project, select \uicontrol File > \uicontrol{New File or Project} and
select the type of your project. The contents of the wizard dialogs depend
@@ -278,93 +255,118 @@
\section1 Adding Files to Projects
You can use wizards also to add individual files to your projects.
You can create the following types of files:
The following table lists the wizard templates for creating files.
\list
\li C/C++
C or C++ source and header files
\li Qt
\list
\li Qt item model source and header files that you can use to create
classes derived from QAbstractItemModel, QAbstractTableModel, or
QAbstractListModel.
\li \QD forms and \QD form classes, which specify parts of user
interfaces in Qt widget based projects
\li Qt resource files, which allow you to store binary files in the
application executable
\li QML files, which specify items in Qt Quick projects.
\uicontrol {QML File (Qt Quick 2)} creates a QML file that imports
Qt Quick 2.0, and \uicontrol {Qt Quick UI File} creates a
\l{UI Files}{UI file} (\e .ui.qml) and the corresponding
implementation file (\e .qml).
\li JavaScript files that you can use to write the application logic in
Qt Quick projects
\endlist
\li Models and state charts
\list
\li Universal Modeling Language (UML) style models with structured
diagrams. However, the model editor uses a variant of UML and
\table
\header
\li Category
\li Wizard Template
\li Purpose
\row
\li {1,3} C/C++
\li C++ Class
\li C++ header and source file for a new class that you can add to
a C++ project.
\row
\li C/C++ Source File
\li C++ source file that you can add to a C++ project.
\row
\li C/C++ Header File
\li C++ header file that you can add to a C++ project.
\row
\li {1,3} Modeling
\li State Chart
\li State Chart XML (SCXML) file that contains boilerplate
code for state machines. You can use the classes in the
\l {Qt SCXML} module to embed state machines created from
the files in Qt applications.
\row
\li Model
\li Universal Modeling Language (UML) style model with a structured
diagram. However, the model editor uses a variant of UML and
provides only a subset of properties for specifying the
appearance of model elements. For more information, see
\l {Modeling}.
\li State Chart XML (SCXML) files that contain boilerplate code for
state machines. You can use the classes in the \l {Qt SCXML}
module to embed state machines created from the files in Qt
applications.
\endlist
\li GLSL
GLSL files that define fragment and vertex shaders in both Qt Quick
projects and Qt widget based projects
\li General
\list
\li Empty files
\li Scratch buffers that use temporary files. You can create this
type of files for temporarily storing information that you do
not intend to save
\endlist
\li Java
Java class files that you can use to create Java classes.
\li Python
Python class and source files that you can use to create Python
classes and scripts with UTF-8 encoding.
\li Nim (experimental)
\list
\li Nim script files.
\li Nim source files with UTF-8 encoding.
\endlist
\endlist
\row
\li Scratch Model
\li Scratch model using a temporary file.
\row
\li {1,7} Qt
\li Qt Item Model
\li Source and header files that you can use to create classes
derived from QAbstractItemModel, QAbstractTableModel, or
QAbstractListModel.
\row
\li \QD Form Class
\li \QD form and a matching class for implementing a UI based
on Qt widgets.
\row
\li \QD Form
\li \QD form for Qt widget based projects. This is useful
if you already have an existing class for the UI logic.
\row
\li Qt Resource File
\li Resource file for storing binary files in the application
executable.
\row
\li QML File (Qt Quick 2)
\li QML file that imports Qt Quick 2.0 for use in Qt Quick projects.
\row
\li Qt Quick UI File
\li \l{UI Files}{UI file} (\e .ui.qml) and the corresponding
implementation file (\e .qml) for use in Qt Quick projects.
\row
\li JS File
\li JavaScript file that you can use to write the application logic
in Qt Quick projects.
\row
\li {1,4} GLSL
\li Fragment Shader (OpenGL/ES 2.0)
\li Fragment shader that generates the final pixel colors for
triangles, points, and lines rendered with OpenGL. You can use
it in both Qt Quick projects and Qt widget based projects.
\row
\li Vertex Shader (OpenGL/ES 2.0)
\li Vertex shader that transforms the positions, normals, and
texture coordinates of triangles, points, and lines rendered
with OpenGL. You can use it in both Qt Quick projects and Qt
widget based projects.
\row
\li Fragment Shader (Desktop OpenGL)
\li Fragment shader for use in both Qt Quick projects and Qt
widget based projects.
\row
\li Vertex Shader (Desktop OpenGL)
\li Vertex shader for use in both Qt Quick projects and Qt
widget based projects.
\row
\li {1,2} General
\li Empty File
\li Empty file that you can save with any filename extensio.
\row
\li Scratch Buffer
\li Scratch buffer that uses temporary files. You can
create this type of files for temporarily storing information
that you do not intend to save
\row
\li Java
\li Java File
\li Java class files that you can use to create Java classes.
\row
\li {1,2} Python
\li Python Class
\li Python class file.
\row
\li Python File
\li Python script file using UTF-8 encoding.
\row
\li {1,2} Nim (experimental)
\li Nim Script File
\li Empty Nim script file using UTF-8 encoding.
\row
\li Nim File
\li Empty Nim source file using UTF-8 encoding.
\endtable
\section2 Creating C++ Classes
+1
View File
@@ -132,6 +132,7 @@
\li \l{Animations}
\li \l{3D Views}
\li \l{Group}
\li \l{Skeletal Animation}
\li \l{3D Models}
\li \l{Materials and Shaders}
\li \l{Textures}
@@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -38,55 +38,59 @@
\image qmldesigner-new-project.png "New File or Project dialog"
When you create a new Qt Quick project from scratch, you have the following
options:
The following table lists the wizard templates for creating a new
Qt Quick project from scratch.
\list
\li \uicontrol {Application (Qt Quick)}:
\table
\header
\li Category
\li Wizard Template
\li Purpose
\row
\li {1,4} Application (Qt Quick)
\li Qt Quick Application - Empty
\li Creates a Qt Quick 2 application project that can contain both
QML and C++ code. You can build the application and deploy it
to desktop, embedded, and mobile target platforms.
\row
\li Qt Quick Application - Scroll
\li Uses the \l{ScrollView} component to implement a scrollable
list view (requires Qt 5.9 or later).
\row
\li Qt Quick Application - Stack
\li Uses the \l{StackView} component to implement a set of pages
with a stack-based navigation model (requires Qt 5.7 or later).
\row
\li Qt Quick Application - Swipe
\li Uses the \l{SwipeView} component to implement a set of pages
with a swipe-based navigation model (requires Qt 5.7 or later).
\row
\li Application (Qt for Python)
\li Qt for Python - Qt Quick Application
\li Creates a Python project that contains an empty Qt Quick
Application.
\row
\li Other Project
\li Qt Quick UI Prototype
\li Creates a \l{Creating Qt Quick UI Projects}{Qt Quick UI project}
with a single QML file that contains the main view. You can
preview Qt Quick 2 UI projects in the
\l{Validating with Target Hardware}{QML Scene preview tool}.
You do not need to build them, because they do not contain any
C++ code.
\list
Use this template only if you are prototyping. You cannot create
a full application by using this template.
\li \uicontrol {Qt Quick Application - Empty} creates a Qt Quick 2
application project that can contain both QML and C++ code. You can
build the application and deploy it to desktop, embedded, and mobile
target platforms.
\li \uicontrol {Qt Quick Application - Scroll} uses the
\l{ScrollView} component to implement a scrollable list view
(requires Qt 5.9 or later).
\li \uicontrol {Qt Quick Application - Stack} uses the
\l{StackView} component to implement a set of pages with a stack-based
navigation model (requires Qt 5.7 or later).
\li \uicontrol {Qt Quick Application - Swipe} uses the
\l{SwipeView} component to implement a set of pages with a swipe-based
navigation model (requires Qt 5.7 or later).
\endlist
\li \uicontrol {Application (Qt for Python)} >
\uicontrol {Qt for Python - Qt Quick Application - Empty} creates a
Python project that contains an empty Qt Quick Application.
\li \uicontrol {Other Project} > \uicontrol {Qt Quick UI Prototype}
creates a \l{Creating Qt Quick UI Projects}{Qt Quick UI project}
with a single QML file that
contains the main view. You can review Qt Quick 2 UI projects in the
\l{Previewing QML Files}{QML Scene preview tool}. You do not need to
build them, because they do not contain any C++ code.
Use this only if you are prototyping. You cannot create a full application
with this.
Qt Quick UI projects cannot be deployed to embedded or mobile
target platforms. For those platforms, create a Qt Quick application
instead.
\li \uicontrol Library > \uicontrol {Qt Quick 2 Extension Plugin}
creates C++ plugins that make it possible to offer extensions that
can be loaded dynamically into Qt Quick 2 applications.
\endlist
Qt Quick UI projects cannot be deployed to embedded or mobile
target platforms. For those platforms, create a Qt Quick
application instead.
\row
\li Library
\li Qt Quick 2 Extension Plugin
\li Creates C++ plugins that make it possible to offer extensions
that can be loaded dynamically into Qt Quick 2 applications.
\endtable
\note The SDK for a particular target platform might install additional
templates for that platform. For example, the QNX templates are installed
@@ -70,6 +70,7 @@
\list
\li \l {3D Views}
\li \l {Group}
\li \l {Skeletal Animation}
\li \l {3D Models}
\li \l {Materials and Shaders}
\li \l {Textures}
@@ -71,6 +71,7 @@
\li \l Animations
\li \l{3D Views}
\li \l{Group}
\li \l{Skeletal Animation}
\li \l{3D Models}
\li \l{Materials and Shaders}
\li \l{Textures}
@@ -195,15 +195,32 @@
\uicontrol {Distribute spacing} field to determine whether
it is distributed evenly within a target area or at
specified distances, calculated from a starting point.
You can select the orientation in which the components are distributed
evenly within the target area: horizontally along the x axis or vertically
along the y axis.
Alternatively, you can distribute spacing in pixels by selecting one of the
starting point buttons: top-left or bottom-right edge of the target area,
or its center. Note that some components might end up outside the target
area.
starting point buttons: top/left or bottom/right edge of the target area or
item, or its center. The edge to use depends on whether the items are
distributed horizontally or vertically:
\list
\li Select \inlineimage icons/distribute-origin-top-left.png
and \inlineimage icons/distribute-spacing-horizontal.png
to use the left edge of the target area or item as the starting
point.
\li Select \inlineimage icons/distribute-origin-top-left.png
and \inlineimage icons/distribute-spacing-vertical.png
to use the top edge.
\li Select \inlineimage icons/distribute-origin-bottom-right.png
and \inlineimage icons/distribute-spacing-horizontal.png
to use the right edge.
\li Select \inlineimage icons/distribute-origin-bottom-right.png
and \inlineimage icons/distribute-spacing-vertical.png
to use the bottom edge.
\endlist
\note Some components might end up outside the target area.
In the \uicontrol {Pixel spacing} field, you can set the space between
components in pixels. You can disable the distribution of spacing in
@@ -273,16 +290,18 @@
\li Disables the distribution of spacing in pixels.
\row
\li \inlineimage icons/distribute-origin-top-left.png
\li Sets the top-left corner of the target area as the starting point
for distributing spacing in pixels.
\li Sets the top or left edge of the target area or item as the
starting point for distributing spacing in pixels depending on
the distribution orientation.
\row
\li \inlineimage icons/distribute-origin-center.png
\li Sets the center of the target area as the starting point
for distributing spacing in pixels.
\row
\li \inlineimage icons/distribute-origin-bottom-right.png
\li Sets the bottom-right corner of the target area as the starting
point for distributing spacing in pixels.
\li Sets the bottom or right edge of the target area or item as the
starting point for distributing spacing in pixels, depending on
the distribution orientation.
\endtable
\section2 Using Positioners
@@ -0,0 +1,41 @@
# GitHub Actions & Workflows
The `build_cmake.yml` in this directory adds a [GitHub action][1] and workflow that builds
your plugin anytime you push commits to GitHub on Windows, Linux and macOS.
The build artifacts can be downloaded from GitHub and be installed into an existing Qt Creator
installation.
When you push a tag, the workflow also creates a new release on GitHub.
## Keeping it up to date
Near the top of the file you find a section starting with `env:`.
The value for `QT_VERSION` specifies the Qt version to use for building the plugin.
The value for `QT_CREATOR_VERSION` specifies the Qt Creator version to use for building the plugin.
The value for `QT_CREATOR_SNAPSHOT` can either be `NO` or `latest` or the build ID of a specific
snapshot build for the Qt Creator version that you specified.
You need to keep these values updated for different versions of your plugin, and take care
that the Qt version and Qt Creator version you specify are compatible.
## What it does
The build job consists of several steps:
* Install required packages on the build host
* Download, unpack and install the binary for the Qt version
* Download and unpack the binary for the Qt Creator version
* Build the plugin and upload the plugin libraries to GitHub
* If a tag is pushed, create a release on GitHub for the tag, including zipped plugin libraries
for download
## Limitations
If your plugin requires additional resources besides the plugin library, you need to adapt the
script accordingly.
[1]: https://help.github.com/en/actions/automating-your-workflow-with-github-actions/about-github-actions
@@ -0,0 +1,322 @@
name: Build plugin
on: [push]
env:
PLUGIN_NAME: Example
QT_VERSION: 6.2.0
QT_CREATOR_VERSION: 5.0.0
QT_CREATOR_SNAPSHOT: NO
CMAKE_VERSION: 3.18.3
NINJA_VERSION: 1.10.1
jobs:
build:
name: ${{ matrix.config.name }}
runs-on: ${{ matrix.config.os }}
strategy:
matrix:
config:
- {
name: "Windows Latest MSVC", artifact: "Windows-x64",
os: windows-latest,
cc: "cl", cxx: "cl",
environment_script: "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Auxiliary/Build/vcvars64.bat",
}
- {
name: "Ubuntu Latest GCC", artifact: "Linux-x64",
os: ubuntu-latest,
cc: "gcc", cxx: "g++"
}
- {
name: "macOS Latest Clang", artifact: "macOS-x64",
os: macos-latest,
cc: "clang", cxx: "clang++"
}
steps:
- uses: actions/checkout@v1
- name: Download Ninja and CMake
shell: cmake -P {0}
run: |
set(cmake_version "$ENV{CMAKE_VERSION}")
set(ninja_version "$ENV{NINJA_VERSION}")
if ("${{ runner.os }}" STREQUAL "Windows")
set(ninja_suffix "win.zip")
set(cmake_suffix "win64-x64.zip")
set(cmake_dir "cmake-${cmake_version}-win64-x64/bin")
elseif ("${{ runner.os }}" STREQUAL "Linux")
set(ninja_suffix "linux.zip")
set(cmake_suffix "Linux-x86_64.tar.gz")
set(cmake_dir "cmake-${cmake_version}-Linux-x86_64/bin")
elseif ("${{ runner.os }}" STREQUAL "macOS")
set(ninja_suffix "mac.zip")
set(cmake_suffix "Darwin-x86_64.tar.gz")
set(cmake_dir "cmake-${cmake_version}-Darwin-x86_64/CMake.app/Contents/bin")
endif()
set(ninja_url "https://github.com/ninja-build/ninja/releases/download/v${ninja_version}/ninja-${ninja_suffix}")
file(DOWNLOAD "${ninja_url}" ./ninja.zip SHOW_PROGRESS)
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf ./ninja.zip)
set(cmake_url "https://github.com/Kitware/CMake/releases/download/v${cmake_version}/cmake-${cmake_version}-${cmake_suffix}")
file(DOWNLOAD "${cmake_url}" ./cmake.zip SHOW_PROGRESS)
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf ./cmake.zip)
# Add to PATH environment variable
file(TO_CMAKE_PATH "$ENV{GITHUB_WORKSPACE}/${cmake_dir}" cmake_dir)
set(path_separator ":")
if ("${{ runner.os }}" STREQUAL "Windows")
set(path_separator ";")
endif()
file(APPEND "$ENV{GITHUB_PATH}" "$ENV{GITHUB_WORKSPACE}${path_separator}${cmake_dir}")
if (NOT "${{ runner.os }}" STREQUAL "Windows")
execute_process(
COMMAND chmod +x ninja
COMMAND chmod +x ${cmake_dir}/cmake
)
endif()
- name: Install system libs
shell: cmake -P {0}
run: |
if ("${{ runner.os }}" STREQUAL "Linux")
execute_process(
COMMAND sudo apt update
)
execute_process(
COMMAND sudo apt install libgl1-mesa-dev
RESULT_VARIABLE result
)
if (NOT result EQUAL 0)
message(FATAL_ERROR "Failed to install dependencies")
endif()
endif()
- name: Download Qt
id: qt
shell: cmake -P {0}
run: |
set(qt_version "$ENV{QT_VERSION}")
string(REPLACE "." "" qt_version_dotless "${qt_version}")
if ("${{ runner.os }}" STREQUAL "Windows")
set(url_os "windows_x86")
set(qt_package_arch_suffix "win64_msvc2019_64")
set(qt_dir_prefix "${qt_version}/msvc2019_64")
set(qt_package_suffix "-Windows-Windows_10-MSVC2019-Windows-Windows_10-X86_64")
elseif ("${{ runner.os }}" STREQUAL "Linux")
set(url_os "linux_x64")
set(qt_package_arch_suffix "gcc_64")
set(qt_dir_prefix "${qt_version}/gcc_64")
set(qt_package_suffix "-Linux-RHEL_7_6-GCC-Linux-RHEL_7_6-X86_64")
elseif ("${{ runner.os }}" STREQUAL "macOS")
set(url_os "mac_x64")
set(qt_package_arch_suffix "clang_64")
set(qt_dir_prefix "${qt_version}/clang_64")
set(qt_package_suffix "-MacOS-MacOS_10_13-Clang-MacOS-MacOS_10_13-X86_64")
endif()
set(qt_base_url "https://download.qt.io/online/qtsdkrepository/${url_os}/desktop/qt5_${qt_version_dotless}")
file(DOWNLOAD "${qt_base_url}/Updates.xml" ./Updates.xml SHOW_PROGRESS)
file(READ ./Updates.xml updates_xml)
string(REGEX MATCH "<Name>qt.qt5.*<Version>([0-9+-.]+)</Version>" updates_xml_output "${updates_xml}")
set(qt_package_version ${CMAKE_MATCH_1})
file(MAKE_DIRECTORY qt5)
# Save the path for other steps
file(TO_CMAKE_PATH "$ENV{GITHUB_WORKSPACE}/qt5/${qt_dir_prefix}" qt_dir)
message("::set-output name=qt_dir::${qt_dir}")
message("Downloading Qt to ${qt_dir}")
function(downloadAndExtract url archive)
message("Downloading ${url}")
file(DOWNLOAD "${url}" ./${archive} SHOW_PROGRESS)
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf ../${archive} WORKING_DIRECTORY qt5)
endfunction()
foreach(package qtbase qtdeclarative)
downloadAndExtract(
"${qt_base_url}/qt.qt5.${qt_version_dotless}.${qt_package_arch_suffix}/${qt_package_version}${package}${qt_package_suffix}.7z"
${package}.7z
)
endforeach()
# uic depends on libicu56.so
if ("${{ runner.os }}" STREQUAL "Linux")
downloadAndExtract(
"${qt_base_url}/qt.qt5.${qt_version_dotless}.${qt_package_arch_suffix}/${qt_package_version}icu-linux-Rhel7.2-x64.7z"
icu.7z
)
endif()
- name: Download Qt Creator
id: qt_creator
shell: cmake -P {0}
run: |
string(REGEX MATCH "([0-9]+.[0-9]+).[0-9]+" outvar "$ENV{QT_CREATOR_VERSION}")
set(qtc_base_url "https://download.qt.io/official_releases/qtcreator/${CMAKE_MATCH_1}/$ENV{QT_CREATOR_VERSION}/installer_source")
set(qtc_snapshot "$ENV{QT_CREATOR_SNAPSHOT}")
if (qtc_snapshot)
set(qtc_base_url "https://download.qt.io/snapshots/qtcreator/${CMAKE_MATCH_1}/$ENV{QT_CREATOR_VERSION}/installer_source/${qtc_snapshot}")
endif()
if ("${{ runner.os }}" STREQUAL "Windows")
set(qtc_platform "windows_x64")
elseif ("${{ runner.os }}" STREQUAL "Linux")
set(qtc_platform "linux_x64")
elseif ("${{ runner.os }}" STREQUAL "macOS")
set(qtc_platform "mac_x64")
endif()
file(TO_CMAKE_PATH "$ENV{GITHUB_WORKSPACE}/qtcreator" qtc_dir)
# Save the path for other steps
message("::set-output name=qtc_dir::${qtc_dir}")
file(MAKE_DIRECTORY qtcreator)
message("Downloading Qt Creator from ${qtc_base_url}/${qtc_platform}")
foreach(package qtcreator qtcreator_dev)
file(DOWNLOAD
"${qtc_base_url}/${qtc_platform}/${package}.7z" ./${package}.7z SHOW_PROGRESS)
execute_process(COMMAND
${CMAKE_COMMAND} -E tar xvf ../${package}.7z WORKING_DIRECTORY qtcreator)
endforeach()
- name: Build
shell: cmake -P {0}
run: |
set(ENV{CC} ${{ matrix.config.cc }})
set(ENV{CXX} ${{ matrix.config.cxx }})
set(ENV{MACOSX_DEPLOYMENT_TARGET} "10.13")
if ("${{ runner.os }}" STREQUAL "Windows" AND NOT "x${{ matrix.config.environment_script }}" STREQUAL "x")
execute_process(
COMMAND "${{ matrix.config.environment_script }}" && set
OUTPUT_FILE environment_script_output.txt
)
file(STRINGS environment_script_output.txt output_lines)
foreach(line IN LISTS output_lines)
if (line MATCHES "^([a-zA-Z0-9_-]+)=(.*)$")
set(ENV{${CMAKE_MATCH_1}} "${CMAKE_MATCH_2}")
endif()
endforeach()
endif()
set(ENV{NINJA_STATUS} "[%f/%t %o/sec] ")
set(build_plugin_py "scripts/build_plugin.py")
foreach(dir "share/qtcreator/scripts" "Qt Creator.app/Contents/Resources/scripts" "Contents/Resources/scripts")
if(EXISTS "${{ steps.qt_creator.outputs.qtc_dir }}/${dir}/build_plugin.py")
set(build_plugin_py "${dir}/build_plugin.py")
break()
endif()
endforeach()
execute_process(
COMMAND python
-u
"${{ steps.qt_creator.outputs.qtc_dir }}/${build_plugin_py}"
--name "$ENV{PLUGIN_NAME}-$ENV{QT_CREATOR_VERSION}-${{ matrix.config.artifact }}"
--src .
--build build
--qt-path "${{ steps.qt.outputs.qt_dir }}"
--qtc-path "${{ steps.qt_creator.outputs.qtc_dir }}"
--output-path "$ENV{GITHUB_WORKSPACE}"
RESULT_VARIABLE result
)
if (NOT result EQUAL 0)
string(REGEX MATCH "FAILED:.*$" error_message "${output}")
string(REPLACE "\n" "%0A" error_message "${error_message}")
message("::error::${error_message}")
message(FATAL_ERROR "Build failed")
endif()
- uses: actions/upload-artifact@v2
id: upload_artifact
with:
path: ./${{ env.PLUGIN_NAME }}-${{ env.QT_CREATOR_VERSION }}-${{ matrix.config.artifact }}.7z
name: ${{ env.PLUGIN_NAME}}-${{ env.QT_CREATOR_VERSION }}-${{ matrix.config.artifact }}.7z
release:
if: contains(github.ref, 'tags/v')
runs-on: ubuntu-latest
needs: build
steps:
- name: Create Release
id: create_release
uses: actions/create-release@v1.0.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: Release ${{ github.ref }}
draft: false
prerelease: false
- name: Store Release url
run: |
echo "${{ steps.create_release.outputs.upload_url }}" > ./upload_url
- uses: actions/upload-artifact@v1
with:
path: ./upload_url
name: upload_url
publish:
if: contains(github.ref, 'tags/v')
name: ${{ matrix.config.name }}
runs-on: ${{ matrix.config.os }}
strategy:
matrix:
config:
- {
name: "Windows Latest x64", artifact: "Windows-x64.7z",
os: ubuntu-latest
}
- {
name: "Linux Latest x64", artifact: "Linux-x64.7z",
os: ubuntu-latest
}
- {
name: "macOS Latest x64", artifact: "macOS-x64.7z",
os: macos-latest
}
needs: release
steps:
- name: Download artifact
uses: actions/download-artifact@v1
with:
name: ${{ env.PLUGIN_NAME }}-${{ env.QT_CREATOR_VERSION }}-${{ matrix.config.artifact }}
path: ./
- name: Download URL
uses: actions/download-artifact@v1
with:
name: upload_url
path: ./
- id: set_upload_url
run: |
upload_url=`cat ./upload_url`
echo ::set-output name=upload_url::$upload_url
- name: Upload to Release
id: upload_to_release
uses: actions/upload-release-asset@v1.0.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.set_upload_url.outputs.upload_url }}
asset_path: ./${{ env.PLUGIN_NAME }}-${{ env.QT_CREATOR_VERSION }}-${{ matrix.config.artifact }}
asset_name: ${{ env.PLUGIN_NAME }}-${{ env.QT_CREATOR_VERSION }}-${{ matrix.config.artifact }}
asset_content_type: application/x-7z-compressed
@@ -0,0 +1,73 @@
# This file is used to ignore files which are generated
# ----------------------------------------------------------------------------
*~
*.autosave
*.a
*.core
*.moc
*.o
*.obj
*.orig
*.rej
*.so
*.so.*
*_pch.h.cpp
*_resource.rc
*.qm
.#*
*.*#
core
!core/
tags
.DS_Store
.directory
*.debug
Makefile*
*.prl
*.app
moc_*.cpp
ui_*.h
qrc_*.cpp
Thumbs.db
*.res
*.rc
/.qmake.cache
/.qmake.stash
# qtcreator generated files
*.pro.user*
# xemacs temporary files
*.flc
# Vim temporary files
.*.swp
# Visual Studio generated files
*.ib_pdb_index
*.idb
*.ilk
*.pdb
*.sln
*.suo
*.vcproj
*vcproj.*.*.user
*.ncb
*.sdf
*.opensdf
*.vcxproj
*vcxproj.*
# MinGW generated files
*.Debug
*.Release
# Python byte code
*.pyc
# Binaries
# --------
*.dll
*.exe
@@ -0,0 +1,40 @@
cmake_minimum_required(VERSION 3.10)
#! [1]
# Remove when sharing with others.
list(APPEND CMAKE_PREFIX_PATH "/Users/example/qt-creator/build")
#! [1]
#! [2]
project(Example)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_CXX_STANDARD 17)
#! [2]
#! [3]
find_package(QtCreator COMPONENTS Core REQUIRED)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets REQUIRED)
set(QtX Qt${QT_VERSION_MAJOR})
#! [3]
#! [4]
add_qtc_plugin(Example
PLUGIN_DEPENDS
QtCreator::Core
DEPENDS
${QtX}::Widgets
QtCreator::ExtensionSystem
QtCreator::Utils
SOURCES
.github/workflows/build_cmake.yml
.github/workflows/README.md
README.md
example.cpp
example.h
example_global.h
exampleconstants.h
)
#! [4]
@@ -5,12 +5,11 @@
\"CompatVersion\" : \"0.0.1\",
//! [1]
//! [2]
\"Vendor\" : \"My Company\",
\"Copyright\" : \"(C) My Company\",
\"License\" : \"BSD\",
\"Category\" : \"Examples\",
\"Description\" : \"Minimal plugin example.\",
\"Url\" : \"http://www.mycompany.com\",
\"Vendor\" : \"MyCompany\",
\"Copyright\" : \"(C) MyCompany\",
\"License\" : \"Put short license information here\",
\"Description\" : \"Put a short description of your plugin here\",
\"Url\" : \"https://www.mycompany.com\",
//! [2]
//! [3]
$$dependencyList
@@ -0,0 +1,36 @@
# Example
## How to Build
Create a build directory and run
cmake -DCMAKE_PREFIX_PATH=<path_to_qtcreator> -DCMAKE_BUILD_TYPE=RelWithDebInfo <path_to_plugin_source>
cmake --build .
where `<path_to_qtcreator>` is the relative or absolute path to a Qt Creator build directory, or to a
combined binary and development package (Windows / Linux), or to the `Qt Creator.app/Contents/Resources/`
directory of a combined binary and development package (macOS), and `<path_to_plugin_source>` is the
relative or absolute path to this plugin directory.
## How to Run
Run a compatible Qt Creator with the additional command line argument
-pluginpath <path_to_plugin>
where `<path_to_plugin>` is the path to the resulting plugin library in the build directory
(`<plugin_build>/lib/qtcreator/plugins` on Windows and Linux,
`<plugin_build>/Qt Creator.app/Contents/PlugIns` on macOS).
You might want to add `-temporarycleansettings` (or `-tcs`) to ensure that the opened Qt Creator
instance cannot mess with your user-global Qt Creator settings.
When building and running the plugin from Qt Creator, you can use
-pluginpath "%{buildDir}/lib/qtcreator/plugins" -tcs
on Windows and Linux, or
-pluginpath "%{buildDir}/Qt Creator.app/Contents/PlugIns" -tcs
for the `Command line arguments` field in the run settings.
@@ -1,4 +1,4 @@
#include "exampleplugin.h"
#include "example.h"
#include "exampleconstants.h"
#include <coreplugin/icore.h>
@@ -13,8 +13,6 @@
#include <QMainWindow>
#include <QMenu>
#include <QtPlugin>
namespace Example {
namespace Internal {
@@ -42,9 +40,9 @@ bool ExamplePlugin::initialize(const QStringList &arguments, QString *errorStrin
Q_UNUSED(errorString)
//! [add action]
QAction *action = new QAction(tr("Example Action"), this);
auto action = new QAction(tr("Example Action"), this);
Core::Command *cmd = Core::ActionManager::registerAction(action, Constants::ACTION_ID,
Core::Context(Core::Constants::C_GLOBAL));
Core::Context(Core::Constants::C_GLOBAL));
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Alt+Meta+A")));
connect(action, &QAction::triggered, this, &ExamplePlugin::triggerAction);
//! [add action]
@@ -1,59 +0,0 @@
#! [1]
DEFINES += EXAMPLE_LIBRARY
#! [1]
# Example files
#! [2]
SOURCES += exampleplugin.cpp
HEADERS += exampleplugin.h \
example_global.h \
exampleconstants.h
#! [2]
# Qt Creator linking
#! [3]
## set the QTC_SOURCE environment variable to override the setting here
QTCREATOR_SOURCES = $$(QTC_SOURCE)
isEmpty(QTCREATOR_SOURCES):QTCREATOR_SOURCES=/Users/example/qtcreator-src
## set the QTC_BUILD environment variable to override the setting here
IDE_BUILD_TREE = $$(QTC_BUILD)
isEmpty(IDE_BUILD_TREE):IDE_BUILD_TREE=/Users/example/qtcreator-build
#! [3]
#! [4]
## uncomment to build plugin into user config directory
## <localappdata>/plugins/<ideversion>
## where <localappdata> is e.g.
## "%LOCALAPPDATA%\QtProject\qtcreator" on Windows Vista and later
## "$XDG_DATA_HOME/data/QtProject/qtcreator" or "~/.local/share/data/QtProject/qtcreator" on Linux
## "~/Library/Application Support/QtProject/Qt Creator" on Mac
# USE_USER_DESTDIR = yes
#! [4]
#! [5]
###### If the plugin can be depended upon by other plugins, this code needs to be outsourced to
###### <dirname>_dependencies.pri, where <dirname> is the name of the directory containing the
###### plugin's sources.
QTC_PLUGIN_NAME = Example
QTC_LIB_DEPENDS += \
# nothing here at this time
QTC_PLUGIN_DEPENDS += \
coreplugin
QTC_PLUGIN_RECOMMENDS += \
# optional plugin dependencies. nothing here at this time
###### End _dependencies.pri contents ######
#! [5]
#![6]
include($$QTCREATOR_SOURCES/src/qtcreatorplugin.pri)
#![6]
@@ -1,9 +1,32 @@
/****************************************************************************
**
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <QtGlobal>
#if defined(EXAMPLE_LIBRARY)
# define EXAMPLESHARED_EXPORT Q_DECL_EXPORT
# define EXAMPLE_EXPORT Q_DECL_EXPORT
#else
# define EXAMPLESHARED_EXPORT Q_DECL_IMPORT
# define EXAMPLE_EXPORT Q_DECL_IMPORT
#endif
@@ -1,3 +1,28 @@
/****************************************************************************
**
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
namespace Example {
@@ -6,5 +31,6 @@ namespace Constants {
const char ACTION_ID[] = "Example.Action";
const char MENU_ID[] = "Example.Menu";
} // namespace Example
} // namespace Constants
} // namespace Example
Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 18 KiB

+1 -1
View File
@@ -983,7 +983,7 @@
\li \c{#include <stdthing>}
\li \c{#include <system.h>}
\endlist
\li Enclose headers from other plugins in square brackets (<>) rather than
\li Enclose headers from other plugins in angle brackets (<>) rather than
quotation marks ("") to make it easier to spot external dependencies in
the sources.
\li Add empty lines between long blocks of \e peer headers and try to
+74 -93
View File
@@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -61,9 +61,8 @@
\li Give your project a name and specify in which path this project will
be created. The actual plugin's name can be different from the
project name. You will choose that name later in the wizard.
Continue to the next page.
The \uicontrol {Plugin Information} dialog opens.
\li Continue to the \uicontrol {Plugin Information} dialog.
\image firstplugin-pluginsetup.png "Specify Your Plugin Details"
@@ -74,7 +73,7 @@
\li The values of the following fields are mainly informational, and
are shown in the detailed view in \QC's plugin overview
(\uicontrol Help > \uicontrol {About Plugins}, or
\uicontrol {Qt Creator} > \uicontrol {About Plugins} on Mac).
\uicontrol {\QC} > \uicontrol {About Plugins} on \macos).
\list
\li \uicontrol {Vendor name} is a short one-word name of the
@@ -94,33 +93,19 @@
it.
\endlist
\li Set the \uicontrol {Qt Creator sources} and
\uicontrol{Qt Creator build} fields to the source and build
directory of the \QC instance you want to use to test your plugin
with, respectively. If you don't do that correctly you will get
compile errors for your plugin, and your plugin might not show up in
\QC at all.
\li Set the \uicontrol{\QC build} field to the build directory
of the \QC instance you want to use to test your plugin with. If
you don't do that correctly, you will get compile errors for your
plugin, and your plugin might not show up in \QC at all.
\li In the \uicontrol {Deploy into} list, select
\uicontrol {Qt Creator build}. This sets your \c {.pro} file up to
deploy your plugin directly into your \QC build's plugin directory
(requires you to have write permissions there). The other option,
\uicontrol {Local user settings}, sets your \c {.pro} file up to
deploy your plugin into \QC's user plugin path (for example
\c {~/.config/QtProject/qtcreator/plugins} on Unix systems). We
choose \uicontrol {Qt Creator build} because we use a self-compiled
\QC, and want the plugin to be only loaded by that \QC
instance. Continue to the next page.
The \uicontrol {Translation File} dialog opens.
\li Continue to the \uicontrol {Translation File} dialog.
\image firstplugin-translation-file.png "Choose a language to localize your plugin to"
\li Select a language to localize your plugin to. This sets up
translation support for the selected language. Continue to the
next page.
translation support for the selected language.
The \uicontrol {Kit Selection} dialog opens.
\li Continue to the \uicontrol {Kit Selection} dialog.
\image firstplugin-kitselection.png "Choose the kit to build and run your project with"
@@ -129,9 +114,9 @@
version that is compatible with the Qt version that your \QC was
built with (in the best case the exact same build). If you use an
incompatible Qt version to build your plugin, you will get errors
while \QC tries to load your plugin. Continue to the next page.
while \QC tries to load your plugin.
The \uicontrol {Project Management} dialog opens.
\li Continue to the \uicontrol {Project Management} dialog.
\image firstplugin-summary.png "Summary of Created Files"
@@ -142,7 +127,7 @@
\section1 Building and Running the Plugin
If you passed the correct \QC source and build paths in the project wizard,
If you passed the correct \QC build path in the project wizard,
your plugin should just build fine when pressing the build button. Before
running the project, select \uicontrol {Build & Run} > \uicontrol Run to
specify run settings:
@@ -150,9 +135,12 @@
\image firstplugin-runsettings.png "Specify the Executable to Run"
Select the path to the \QC executable from the build that you specified in
the \uicontrol {Qt Creator build} setting in the project wizard and click
\uicontrol OK. \QC starts up, and you can verify that your plugin
successfully loaded by looking for a menu entry \uicontrol Tools >
the \uicontrol {\QC build} field in the project wizard and set the value
of the \uicontrol {Command line arguments} field to
\c {-pluginpath %{buildDir}}.
When you click \uicontrol OK, \QC starts up, and you can verify that your
plugin is successfully loaded by looking for a menu entry \uicontrol Tools >
\uicontrol Example and by looking for the plugin in the \uicontrol Help >
\uicontrol {About Plugins} dialog.
@@ -167,17 +155,20 @@
\li File
\li Role
\row
\li \c {README.md}
\li Describes how to build and run the plugin.
\row
\li \c {Example.json.in}
\li Plugin meta data template. QMake creates an \c {Example.json}
\li Plugin meta data template. CMake creates an \c {Example.json}
from this file, which is compiled into the plugin as meta data.
The meta data is read by \QC to find out about the plugin.
\row
\li \c {example.pro}
\li \c {CMakeLists.txt}
\li Project file, used by QMake to generate a Makefile that then is used to
build the plugin.
\li Project file, used by CMake to generate build files and build the plugin.
\row
\li \c {example_global.h}
@@ -193,7 +184,7 @@
\li C++ header and source files that define the plugin class that will be
instantiated and run by \QC's plugin manager.
\row
\li \c{build_qmake.yml}
\li \c{build_cmake.yml}
\li Adds a
\l {https://help.github.com/en/actions/automating-your-workflow-with-github-actions/about-github-actions}
@@ -202,71 +193,61 @@
information, see \c {.github\workflow\README.md}.
\endtable
\section1 qmake Project
\section1 CMake Project
The qmake project file \c {example.pro} defines how your plugin should be
The CMake project file \c {CMakeLists.txt} defines how your plugin should be
compiled. \QC plugins need to have a specific setup there, in addition to
telling qmake which files need to be compiled (or handled by \c moc or
telling CMake which files need to be compiled (or handled by \c moc or
\c uic). Let us have a look at what the project wizard generated for you in
detail.
\snippet exampleplugin/example.pro 1
\snippet exampleplugin/CMakeLists.txt 1
The first section of the .pro file lets the compiler pass an
\c EXAMPLE_LIBRARY define to the compiled code, which is used in the
\c {example_global.h} header, but is not really of interest for now. You
should not need to change that section of the \c {.pro} file.
The \c{list(APPEND ...)} call tells CMake to include the \QC build path that
you specified in the wizard in its search path for dependencies. Since this
contains an absolute path on your local machine, you should remove this line
when sharing the project with others.
\snippet exampleplugin/example.pro 2
Without this line, you need to explicitly add the path to the \QC
build to \c {CMAKE_PREFIX_PATH} when configuring your plugin with CMake.
This section tells qmake about the files of your project that it should let
compile or otherwise handle. You need to expand that section with any files
you add to the project.
\snippet exampleplugin/CMakeLists.txt 2
\snippet exampleplugin/example.pro 3
This section does some standard setup for Qt/CMake projects. Besides
setting a project name and a C++ standard to use, it turns on automatic
detection of files that need to be run through \c {moc}, \c {rcc} or \c
{uic}.
To compile and deploy your plugin, the project needs access to the \QC
sources and build. This section contains the logic that looks for the
information about the location of the sources and build in the
\c {QTC_SOURCE} and \c {QTC_BUILD} environment variables. If these are not
defined, it uses the defaults you set in the project wizard.
\snippet exampleplugin/CMakeLists.txt 3
So, if someone else opens your plugin project on their machine, they do not
need to edit the .pro file, but instead they should set the \c {QTC_SOURCE}
and \c {QTC_BUILD} environment variables correctly for the plugin's build
environment.
This section tells CMake to locate \QC and Qt. If your plugin requires
additional Qt modules, you need to add them to the corresponding
\c {find_package} call in this section.
You should not need to change this section, except perhaps to adapt the
defaults.
To find \QC and Qt, the paths to the \QC and Qt installation must be
present in the \c {CMAKE_PREFIX_PATH} when you configure your plugin
with CMake.
\snippet exampleplugin/example.pro 4
\snippet exampleplugin/CMakeLists.txt 4
\QC plugins can either be installed into the \QC installation's plugin
directory (requires write access there), or to a user specific plugin
directory. The \c USE_USER_DESTDIR switch in the .pro file defines which
method is used for building the plugin (which is independent from what you
can later use for distributing your plugin to other users).
The \c {add_qtc_plugin} call creates a target for your plugin with the
specified name.
\snippet exampleplugin/example.pro 5
In the \c {PLUGIN_DEPENDS} sub-section, you need to specify \QC plugins that
your plugin depends on. Valid values are a plugin's name prefixed with
\c {QtCreator::}.
This section defines the name and dependencies of your plugin. The
\c {QTC_PLUGIN_NAME} variable defines the name of your plugin, and the name
of the dynamic library that is created for it. The \c {QTC_LIB_DEPENDS}
variable is a list of library names of the \QC utility libraries that your
plugin depends on. Typical values would be \c aggregation,
\c extensionsystem and \c utils. The \c {QTC_PLUGIN_DEPENDS} variable
defines the \QC plugins that your plugin depends on. Almost all \QC plugins
will depend on the \c coreplugin. The \c {QTC_PLUGIN_RECOMMENDS} variable
defines the \QC plugins that your plugin optionally depends on. For more
information, see \l{Optional Dependencies}.
In the \c {DEPENDS} sub-section, you need to specify libraries that your
plugin depends on. Use a Qt module name prefixed with \c {$\{QtX\}::}
to link to additional Qt modules. To link against additional \QC libraries,
prefix their name with \c {QtCreator::}. In this subsection you also
specify other libraries that your plugin depends on.
\snippet exampleplugin/example.pro 6
The included file \c{qtcreatorplugin.pri} makes sure that you build a plugin
that is suitable for use in \QC, by using the information you gave above.
For more information about qmake, and writing \c {.pro} files in general,
see the \l{qmake Manual}.
In the \c {SOURCES} sub-section, you specify all files that belong to your
plugin project. CMake sorts these into source files and header files
automatically. Other files in this section are ignored by CMake but appear
for example in the project tree that is shown in IDEs like \QC for easier
access.
\section1 Plugin Meta Data Template
@@ -301,22 +282,22 @@
\section1 Plugin Class
The files \c {exampleplugin.h} and \c {exampleplugin.cpp} define the plugin
The files \c {example.h} and \c {example.cpp} define the plugin
implementation of your little plugin. We'll concentrate on some highlights
here, and give pointers to more detailed information for the various parts.
\section2 Header File
The header file \c {exampleplugin.h} defines the interface of the plugin
The header file \c {example.h} defines the interface of the plugin
class.
\snippet exampleplugin/exampleplugin.h namespaces
\snippet exampleplugin/example.h namespaces
The plugin is defined in a \c {Example::Internal} namespace, which conforms
to the coding rules for \l{coding-rules-namespacing}{namespacing}
in \QC sources.
\snippet exampleplugin/exampleplugin.h base class
\snippet exampleplugin/example.h base class
All \QC plugins must be derived from \l{ExtensionSystem::IPlugin} and
are QObjects. The \c {Q_PLUGIN_METADATA} macro is necessary to create a
@@ -325,13 +306,13 @@
\c FILE must point to the plugin's meta data file as described in
\l{Plugin Meta Data}.
\snippet exampleplugin/exampleplugin.h plugin functions
\snippet exampleplugin/example.h plugin functions
The base class defines basic functions that are called during the life cycle
of a plugin, which are here implemented for your new plugin. These functions
and their roles are described in detail in \l{Plugin Life Cycle}.
\snippet exampleplugin/exampleplugin.h slot
\snippet exampleplugin/example.h slot
The plugin has an additional custom slot, that is used to pop up a dialog
when the user chooses the menu item that this plugin adds.
@@ -353,7 +334,7 @@
For more information about implementing the plugin interface, see the
\l{ExtensionSystem::IPlugin} API documentation and \l{Plugin Life Cycle}.
\snippet exampleplugin/exampleplugin.cpp add action
\snippet exampleplugin/example.cpp add action
This part of the code creates a new \c QAction, registers it as a new
\c Command in the action manager, and connects it to the plugin's slot. The
@@ -362,12 +343,12 @@
be directed to different plugins under different circumstances, as well as a
few other things.
\snippet exampleplugin/exampleplugin.cpp add menu
\snippet exampleplugin/example.cpp add menu
Here a new menu item is created, the created command added to it, and the
menu added to the \uicontrol Tools menu in the menu bar.
\snippet exampleplugin/exampleplugin.cpp slot implementation
\snippet exampleplugin/example.cpp slot implementation
This part defines the code that is called when the menu item is triggered.
It uses the Qt API to open a message box that displays informative text and
Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

@@ -89,6 +89,7 @@
\li \l Animations
\li \l{3D Views}
\li \l{Group}
\li \l{Skeletal Animation}
\li \l{3D Models}
\li \l{Materials and Shaders}
\li \l{Textures}
@@ -32,8 +32,19 @@
\title 3D Materials
\QDS provides a set of pregenerated Qt Quick 3D materials that can be used
to create good-looking \l {3D Models}{models} quickly and easily.
\QDS provides a set of pregenerated \uicontrol {Qt Quick 3D}
materials. If the 3D materials are not displayed in \uicontrol Library,
you can add the \uicontrol QtQuick3D.Materials module to your project,
as described in \l {Adding and Removing Modules}. However, since using the
pregenerated 3D materials may cause performance issues, we advice you to
use \uicontrol {Principled Material}, \uicontrol {Default Material}, or
\uicontrol {Custom Material} instead. For more information,
see \l {Materials and Shaders} and \l {Creating Custom Materials}.
\note The \uicontrol QtQuick3D.Materials module is not available in
\uicontrol {Qt 6}. To use the pregenerated \uicontrol {Qt Quick 3D}
materials, you need to select \uicontrol {Qt 5} as the
\uicontrol {Target Qt Version} when \l {Creating Projects}{creating your project}.
To apply a 3D material to a component, you should first delete the default
material and then drag-and-drop a new material from \l Library >
@@ -46,10 +57,6 @@
\uicontrol Materials property, select the \inlineimage plus.png
icon, and choose the new material in the dropdown menu.
If the 3D materials are not displayed in \uicontrol Library, you should add
the \uicontrol QtQuick3D.Materials module to your project, as described in
\l {Adding and Removing Modules}.
Each material has its own set of properties that can be used to further
define the appearance of the material. For each material the \uicontrol
{Environment Map} property specifies whether or not
@@ -27,18 +27,19 @@
/*!
\page studio-3d-model.html
\previouspage studio-3d-node.html
\previouspage studio-skeletal-components.html
\nextpage studio-3d-materials.html
\title 3D Models
\QDS \l Library features some built-in primitive 3D models. This allows you
to add cubes, cones, cylinders, and planes (rectangles) to your scene.
The \l Library view features some built-in primitive 3D models. This allows
you to add cubes, cones, cylinders, and planes (rectangles) to your scene.
\image studio-3d-models.png
\image studio-3d-models.png "Various 3D models in 3D Editor"
A Model component loads mesh data from a file. You can modify how the
component is shaded by adding \l{3D Materials}{materials} to the model.
component is shaded by using materials. For more information, see
\l {Materials and Shaders} and \l {Creating Custom Materials}.
You can drag-and-drop a model from \uicontrol Library > \uicontrol Components
> \uicontrol {Qt Quick 3D} > \uicontrol {Qt Quick 3D} to \l {3D Editor} or
@@ -49,28 +50,66 @@
\image studio-qtquick-3d-components.png "The Qt Quick 3D section in Library"
You can change the model type in the \uicontrol Source field in the
\uicontrol Properties view. Select the \inlineimage plus.png
\section1 Model Properties
You can change the model type in \uicontrol Properties > \uicontrol Model
> \uicontrol Source field. Select the \inlineimage plus.png
button to add custom model types to the list.
\image studio-qtquick-3d-model.png "Model properties"
To use the geometry of this model when rendering to shadow maps, select the
\uicontrol {Casts shadows} check box. To allow casting shadows on the model,
select the \uicontrol {Receives shadows} check box.
To enable picking the model against the scene, select the
\uicontrol Pickable check box. Picking transforms the screen
space x and y coordinates to a ray cast towards the specified
position in scene space.
To use the geometry of this model when rendering to shadow maps, select the
\uicontrol {Casts shadows} check box. To allow casting shadows on the model,
select the \uicontrol {Receives shadows} check box.
A model can consist of several sub-meshes, each of which can have its own
material. Select the material from the list in the \uicontrol {Materials}
field. Select the \inlineimage plus.png
button to add materials to the list. For more information about materials,
see \l {Materials and Shaders}.
\section1 Tessellation
Specify a custom geometry for the model in the \uicontrol Geometry field.
The \uicontrol Source field must be empty when custom geometry is used.
To dynamically generate additional geometry for the model, select the
tiling mode in the \uicontrol {Tessellation mode} filed. Tessellation
is useful when using a displacement map with geometry, or to generate a
smoother silhouette when zooming in. You can select either a Phong or
an NPatch tessellation generator.
Set the \uicontrol Instancing property to render a number of instances of
the model as defined by the instance table.
Set the \uicontrol {Instance root} property to define the origin of the
instance's coordinate system.
Specify the \uicontrol Skeleton property to define the \uicontrol Skeleton
component used for this model. \uicontrol Skeletons are used for skeletal
animation.
Specify \uicontrol {Morph targets} to use for rendering the provided
geometry. Meshes should have at least one attribute among positions, normals,
tangent, and bitangent for the morph targets. \uicontrol {Quick 3D} supports
the maximum of eight \uicontrol {Morph targets}. Any additional targets
after the first eight will be ignored. This property is not used when the
model is shaded by a \uicontrol {Custom Material}.
Define the \uicontrol {Depth bias} property to ensure the shadows of your
model are displayed correctly.
\section1 Tessellation Properties Available in Qt 5
The properties discussed in this section are only available if you selected
\uicontrol {Qt 5} as the \uicontrol {Target Qt Version} when creating the
project.
\image studio-qtquick-3d-properties-tessellation.png "Tessellation properties"
Tessellation refers to additional geometry that resembles tiling, which you
can add to your model. To dynamically generate tessellation for the model,
select \uicontrol Linear, \uicontrol Phong, or \uicontrol NPatch as the
\uicontrol {Tessellation mode}. Tessellation is useful when using a
displacement map with geometry, or to generate a smoother silhouette
when zooming in.
Specify an edge multiplier to the tessellation generator in the
\uicontrol {Edge tessellation} field and an inner multiplier in
@@ -80,11 +119,4 @@
the tessellation generator, select the \uicontrol {Enable wireframe mode}
check box.
\section1 Adding Materials to Sub-Meshes
A model can consist of several sub-meshes, each of which can have its own
material. Select the material from the list in the \uicontrol {Materials}
field. Select the \inlineimage plus.png
button to add materials to the list. For more information about materials,
see \l {Materials and Shaders}.
*/
@@ -26,7 +26,7 @@
/*!
\page studio-3d-node.html
\previouspage quick-animations.html
\nextpage studio-3d-model.html
\nextpage studio-skeletal-components.html
\title Group
@@ -0,0 +1,76 @@
/****************************************************************************
**
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Design Studio documentation.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
**
****************************************************************************/
/*!
\page studio-skeletal-components.html
\previouspage studio-3d-node.html
\nextpage studio-3d-model.html
\title Skeletal Animation
Skeletal animation is a technique used in computer animation. In skeletal
animation, a character is represented in the form of a surface representation
(skin or mesh), and a skeleton. This portrays how the character can move,
inspired by how a physical skeleton works for vertebrates. The "bones" of the
skeleton are represented by a hierarchy of joint nodes.
The normal workflow is to use an external content creation tool to define
the skeleton and the skin (this is sometimes also referred to as rigging),
and import them to \QDS. You can then create skeletal animations using
\uicontrol Skeleton and \uicontrol Joint components available in
\uicontrol Library > \uicontrol Components > \uicontrol {Qt Quick 3D} >
\uicontrol {Qt Quick 3D}.
\section1 Skeleton
A \uicontrol Skeleton component determines a skeletal animation hierarchy
and defines how a model can be animated using skeletal animation.
It contains a hierarchy of \uicontrol Joint nodes. Each joint can be
transformed for a skinning animation.
\section1 Joint
A \uicontrol Joint defines a node in a skeletal animation hierarchy
and functions similarly to joints between bones in a human skeleton.
It is a transformable node that must be contained inside a
\uicontrol Skeleton component.
Define properties for \uicontrol Joint components in \uicontrol Properties
> \uicontrol Joint.
\image studio-3d-joint-properties.png "Joint properties in the Properties view"
Use the \uicontrol Index property to define the index of this joint.
This index value is used in the \uicontrol {Joint semantic} custom geometry
attribute.
\note The \uicontrol Index values must be unique within the same
\uicontrol Skeleton.
Use the \uicontrol {Skeleton root} property to define the \uicontrol Skeleton
that contains the \uicontrol Joint. Do note that all the \uicontrol Joints
in the \uicontrol Skeleton must have the same \uicontrol {Skeleton root}
for the animation to work properly.
*/
+12
View File
@@ -90,6 +90,18 @@ if [ -d "$sqldriversSrcDir" ]; then
fi
fi
# workaround for Qt 6.2:
# - QTBUG-94796 macdeployqt does not deploy /Contents/PlugIns/imageformats/libqsvg.dylib anymore
imageformatsDestDir="$app_path/Contents/PlugIns/imageformats"
imageformatsSrcDir="$plugin_src/imageformats"
if [ -d "$imageformatsSrcDir" ]; then
if [ ! -d "$imageformatsDestDir" ]; then
echo "- Copying sqlitedriver plugin"
mkdir -p "$imageformatsDestDir"
cp "$imageformatsSrcDir/libqsvg.dylib" "$imageformatsDestDir/libqsvg.dylib"
fi
fi
# copy Qt Quick 2 imports
imports2Dir="$app_path/Contents/Imports/qtquick2"
if [ -d "$quick2_src" ]; then
@@ -139,7 +139,7 @@ void CameraGeometry::doUpdateGeometry()
return;
}
if (!m_camera->cameraNode()) {
if (!QQuick3DObjectPrivate::get(m_camera)->spatialNode) {
// Doing explicit viewport mapping forces cameraNode creation
m_camera->mapToViewport({}, m_viewPortRect.width(), m_viewPortRect.height());
}
@@ -171,7 +171,7 @@ void CameraGeometry::fillVertexData(QByteArray &vertexData, QByteArray &indexDat
auto indexPtr = reinterpret_cast<quint16 *>(indexData.data());
QMatrix4x4 m;
QSSGRenderCamera *camera = m_camera->cameraNode();
QSSGRenderCamera *camera = static_cast<QSSGRenderCamera *>(QQuick3DObjectPrivate::get(m_camera)->spatialNode);
if (camera) {
QRectF rect = m_viewPortRect;
if (rect.isNull())
@@ -818,7 +818,8 @@ QVector3D MouseArea3D::getMousePosInPlane(const MouseArea3D *helper,
const DoubleVec3D rayPos0 = m_view3D->mapTo3DScene(mousePos1.toVec3());
DoubleVec3D rayPos1;
if (qobject_cast<QQuick3DOrthographicCamera *>(m_view3D->camera())) {
rayPos1 = rayPos0 - rayPos0.length() * DoubleVec3D(m_view3D->camera()->cameraNode()->getDirection());
if (auto cameraNode = static_cast<QSSGRenderCamera *>(QQuick3DObjectPrivate::get(m_view3D->camera())->spatialNode))
rayPos1 = rayPos0 - rayPos0.length() * DoubleVec3D(cameraNode->getDirection());
} else {
DoubleVec3D dir;
DoubleVec3D camPos = m_view3D->camera()->scenePosition();
@@ -1021,12 +1022,17 @@ QVector3D MouseArea3D::getNormal() const
QVector3D MouseArea3D::getCameraToNodeDir(QQuick3DNode *node) const
{
QVector3D dir;
if (qobject_cast<QQuick3DOrthographicCamera *>(m_view3D->camera())) {
dir = -m_view3D->camera()->cameraNode()->getDirection();
} else {
QVector3D camPos = m_view3D->camera()->scenePosition();
QVector3D nodePos = pivotScenePosition(node);
dir = (nodePos - camPos).normalized();
if (m_view3D->camera()) {
// We need to do a cast here to be compatible with Qt 5.x.
// From Qt 6.2 the type can be read from the node directly.
if (qobject_cast<QQuick3DOrthographicCamera *>(m_view3D->camera())) {
if (auto renderCamera = QQuick3DObjectPrivate::get(m_view3D->camera())->spatialNode)
dir -= static_cast<QSSGRenderCamera *>(renderCamera)->getDirection();
} else {
QVector3D camPos = m_view3D->camera()->scenePosition();
QVector3D nodePos = pivotScenePosition(node);
dir = (nodePos - camPos).normalized();
}
}
return dir;
}
@@ -933,6 +933,9 @@ void NodeInstanceServer::setInstancePropertyBinding(const PropertyBindingContain
Internal::QmlPrivateGate::createNewDynamicProperty(instance.internalInstance()->object(), engine(),
QString::fromUtf8(name));
instance.setPropertyBinding(name, expression);
if (instance.instanceId() == 0 && (name == "width" || name == "height"))
resizeCanvasToRootItem();
}
}
}
@@ -214,6 +214,7 @@ public:
virtual void handleInstanceHidden(const ServerNodeInstance &instance, bool enable, bool checkAncestors);
virtual QImage grabWindow() = 0;
virtual QImage grabItem(QQuickItem *item) = 0;
public slots:
void refreshLocalFileProperty(const QString &path);
@@ -761,7 +761,8 @@ void Qt5InformationNodeInstanceServer::updateNodesRecursive(QQuickItem *item)
const auto childItems = item->childItems();
for (QQuickItem *childItem : childItems)
updateNodesRecursive(childItem);
if (Internal::QuickItemNodeInstance::unifiedRenderPath()) {
if (Internal::QuickItemNodeInstance::unifiedRenderPathOrQt6()) {
if (item->flags() & QQuickItem::ItemHasContents)
item->update();
} else {
@@ -773,7 +774,7 @@ QQuickItem *Qt5InformationNodeInstanceServer::getContentItemForRendering(QQuickI
{
QQuickItem *contentItem = QQmlProperty::read(rootItem, "contentItem").value<QQuickItem *>();
if (contentItem) {
if (!Internal::QuickItemNodeInstance::unifiedRenderPath())
if (!Internal::QuickItemNodeInstance::unifiedRenderPathOrQt6())
designerSupport()->refFromEffectItem(contentItem, false);
QmlDesigner::Internal::QmlPrivateGate::disableNativeTextRendering(contentItem);
}
@@ -899,7 +900,7 @@ void Qt5InformationNodeInstanceServer::doRenderModelNode3DImageView()
instanceObj = instance.internalObject();
}
QSize renderSize = m_modelNodePreviewImageCommand.size();
if (Internal::QuickItemNodeInstance::unifiedRenderPath()) {
if (Internal::QuickItemNodeInstance::unifiedRenderPathOrQt6()) {
// Requested size is already adjusted for target pixel ratio, so we have to adjust
// back if ratio is not default for our window.
double ratio = m_modelNode3DImageViewData.window->devicePixelRatio();
@@ -1106,7 +1107,7 @@ Qt5InformationNodeInstanceServer::~Qt5InformationNodeInstanceServer()
if (m_editView3DData.rootItem)
QMetaObject::invokeMethod(m_editView3DData.rootItem, "aboutToShutDown", Qt::DirectConnection);
if (!Internal::QuickItemNodeInstance::unifiedRenderPath()) {
if (!Internal::QuickItemNodeInstance::unifiedRenderPathOrQt6()) {
if (m_editView3DData.contentItem)
designerSupport()->derefFromEffectItem(m_editView3DData.contentItem);
if (m_modelNode3DImageViewData.contentItem)
@@ -64,11 +64,11 @@ Qt5NodeInstanceClientProxy::Qt5NodeInstanceClientProxy(QObject *parent) :
const bool qt6 = true;
#endif
const bool unifiedRenderPath = qt6 || qEnvironmentVariableIsSet("QMLPUPPET_UNIFIED_RENDER_PATH");
const bool unifiedRenderPath = qEnvironmentVariableIsSet("QMLPUPPET_UNIFIED_RENDER_PATH");
if (unifiedRenderPath)
Internal::QuickItemNodeInstance::enableUnifiedRenderPath(true);
else
else if (!qt6)
DesignerSupport::activateDesignerWindowManager();
if (QCoreApplication::arguments().at(1) == QLatin1String("--readcapturedstream")) {
@@ -44,10 +44,13 @@
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
#include <QtGui/private/qrhi_p.h>
#include <QtQuick/private/qquickwindow_p.h>
#include <QtQuick/private/qsgrenderer_p.h>
#include <QtQuick/private/qquickitem_p.h>
#include <QtQuick/private/qquickrendercontrol_p.h>
#include <QtQuick/private/qquickrendertarget_p.h>
#include <QtQuick/private/qquickwindow_p.h>
#include <QtQuick/private/qsgcontext_p.h>
#include <QtQuick/private/qsgrenderer_p.h>
#include <QtQuick/private/qsgrhilayer_p.h>
#endif
namespace QmlDesigner {
@@ -332,6 +335,80 @@ QImage Qt5NodeInstanceServer::grabWindow()
return {};
}
QImage Qt5NodeInstanceServer::grabItem(QQuickItem *item)
{
QImage renderImage;
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
if (!m_viewData.rootItem || (m_viewData.bufferDirty && !initRhi(m_viewData)))
return {};
QQuickItemPrivate *pItem = QQuickItemPrivate::get(item);
pItem->refFromEffectItem(false);
ServerNodeInstance instance = instanceForObject(item);
const auto childInstances = instance.childItems();
// Hide immediate children that have instances and are QQuickItems so we get only
// the parent item's content, as compositing is handled on creator side.
for (const auto &childInstance : childInstances) {
QQuickItem *childItem = qobject_cast<QQuickItem *>(childInstance.internalObject());
if (childItem) {
QQuickItemPrivate *pChild = QQuickItemPrivate::get(childItem);
pChild->refFromEffectItem(true);
}
}
m_viewData.renderControl->polishItems();
m_viewData.renderControl->beginFrame();
m_viewData.renderControl->sync();
// Connection to afterRendering is necessary, as this needs to be done before
// call to endNextRhiFrame which happens inside QQuickRenderControl::render()
QMetaObject::Connection connection = QObject::connect(m_viewData.window.data(),
&QQuickWindow::afterRendering,
this, [&]() {
// To get only the single item, we need to make a layer out of it, which enables
// us to render it to a texture that we can grab to an image.
QSGRenderContext *rc = QQuickWindowPrivate::get(m_viewData.window.data())->context;
QSGLayer *layer = rc->sceneGraphContext()->createLayer(rc);
layer->setItem(pItem->itemNode());
QSizeF itemSize = QSizeF(item->width(), item->height());
layer->setRect(QRectF(0, itemSize.height(), itemSize.width(), -itemSize.height()));
const QSize minSize = rc->sceneGraphContext()->minimumFBOSize();
layer->setSize(QSize(qMax(minSize.width(), int(itemSize.width())),
qMax(minSize.height(), int(itemSize.height()))));
layer->scheduleUpdate();
if (layer->updateTexture())
renderImage = layer->toImage();
else
qWarning() << __FUNCTION__ << "Failed to update layer texture";
delete layer;
layer = nullptr;
});
m_viewData.renderControl->render();
QObject::disconnect(connection);
m_viewData.renderControl->endFrame();
// Restore visibility of immediate children that have instances and are QQuickItems
for (const auto &childInstance : childInstances) {
QQuickItem *childItem = qobject_cast<QQuickItem *>(childInstance.internalObject());
if (childItem) {
QQuickItemPrivate *pChild = QQuickItemPrivate::get(childItem);
pChild->derefFromEffectItem(true);
}
}
pItem->derefFromEffectItem(false);
#else
Q_UNUSED(item)
#endif
return renderImage;
}
void Qt5NodeInstanceServer::refreshBindings()
{
DesignerSupport::refreshExpressions(context());
@@ -69,6 +69,7 @@ public:
void reparentInstances(const ReparentInstancesCommand &command) override;
QImage grabWindow() override;
QImage grabItem(QQuickItem *item) override;
protected:
void initializeView() override;
@@ -102,9 +102,6 @@ void Qt5RenderNodeInstanceServer::collectItemChangesAndSendChangeCommands()
clearChangedPropertyList();
if (Internal::QuickItemNodeInstance::unifiedRenderPath()) {
/* QQuickItem::grabToImage render path */
/* TODO implement QQuickItem::grabToImage based rendering */
/* sheduleRootItemRender(); */
if (windowDirty)
nodeInstanceClient()->pixmapChanged(createPixmapChangedCommand({rootNodeInstance()}));
} else {
@@ -171,10 +171,15 @@ void QuickItemNodeInstance::enableUnifiedRenderPath(bool unifiedRenderPath)
bool QuickItemNodeInstance::checkIfRefFromEffect(qint32 id)
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (s_unifiedRenderPath)
return false;
return (s_createEffectItem || id == 0);
#else
Q_UNUSED(id)
return false;
#endif
}
void QuickItemNodeInstance::initialize(const ObjectNodeInstance::Pointer &objectNodeInstance,
@@ -267,9 +272,13 @@ QStringList QuickItemNodeInstance::allStates() const
void QuickItemNodeInstance::updateDirtyNode(QQuickItem *item)
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (s_unifiedRenderPath)
return;
DesignerSupport::updateDirtyNode(item);
#else
Q_UNUSED(item)
#endif
}
bool QuickItemNodeInstance::unifiedRenderPath()
@@ -277,6 +286,15 @@ bool QuickItemNodeInstance::unifiedRenderPath()
return s_unifiedRenderPath;
}
bool QuickItemNodeInstance::unifiedRenderPathOrQt6()
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
return true;
#else
return s_unifiedRenderPath;
#endif
}
QRectF QuickItemNodeInstance::contentItemBoundingBox() const
{
if (contentItem()) {
@@ -415,16 +433,15 @@ QImage QuickItemNodeInstance::renderImage() const
updateDirtyNodesRecursive(quickItem());
QRectF renderBoundingRect = boundingRect();
QImage renderImage;
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QSize size = renderBoundingRect.size().toSize();
static double devicePixelRatio = qgetenv("FORMEDITOR_DEVICE_PIXEL_RATIO").toDouble();
if (size.width() * size.height() > 4000 * 4000)
size = QSize(0,0);
size *= devicePixelRatio;
QImage renderImage;
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (s_unifiedRenderPath) {
renderImage = nodeInstanceServer()->quickWindow()->grabWindow();
} else {
@@ -438,8 +455,12 @@ QImage QuickItemNodeInstance::renderImage() const
}
renderImage.setDevicePixelRatio(devicePixelRatio);
#else
renderImage = nodeInstanceServer()->grabWindow();
if (s_unifiedRenderPath)
renderImage = nodeInstanceServer()->grabWindow();
else
renderImage = nodeInstanceServer()->grabItem(quickItem());
renderImage = renderImage.copy(renderBoundingRect.toRect());
/* When grabbing an offscren window the device pixel ratio is 1 */
renderImage.setDevicePixelRatio(1);
#endif
@@ -104,6 +104,7 @@ public:
static void updateDirtyNode(QQuickItem *item);
static bool unifiedRenderPath();
static bool unifiedRenderPathOrQt6();
protected:
explicit QuickItemNodeInstance(QQuickItem*);
@@ -165,7 +165,8 @@ Item {
(assetsView.verticalScrollBarVisible ? assetsView.verticalThickness : 0)
height: img.height
color: selectedAssets[filePath] ? StudioTheme.Values.themeInteraction
: (mouseArea.containsMouse ? "#444444" : "transparent")
: (mouseArea.containsMouse ? StudioTheme.Values.themeSectionHeadBackground
: "transparent")
Row {
spacing: 5
@@ -210,7 +210,7 @@ Section {
onClicked: alignDistribute.distributeSpacing(AlignDistribute.X,
alignToComboBox.currentEnum,
keyObjectComboBox.currentText,
distanceSpinBox.realValue,
distanceSpinBox.value,
buttonRow.getDistributeDirection())
}
@@ -220,11 +220,13 @@ Section {
onClicked: alignDistribute.distributeSpacing(AlignDistribute.Y,
alignToComboBox.currentEnum,
keyObjectComboBox.currentText,
distanceSpinBox.realValue,
distanceSpinBox.value,
buttonRow.getDistributeDirection())
}
}
Spacer { implicitWidth: 8 }
StudioControls.ButtonRow {
id: buttonRow
actionIndicatorVisible: false
@@ -250,6 +252,7 @@ Section {
buttonIcon: StudioTheme.Constants.distributeOriginNone
checkable: true
StudioControls.ButtonGroup.group: group
tooltip: qsTr("Disables the distribution of spacing in pixels.")
}
AbstractButton {
@@ -257,6 +260,8 @@ Section {
buttonIcon: StudioTheme.Constants.distributeOriginTopLeft
checkable: true
StudioControls.ButtonGroup.group: group
tooltip: qsTr("Sets the left or top border of the target area or item as the " +
"starting point, depending on the distribution orientation.")
}
AbstractButton {
@@ -264,6 +269,9 @@ Section {
buttonIcon: StudioTheme.Constants.distributeOriginCenter
checkable: true
StudioControls.ButtonGroup.group: group
tooltip: qsTr("Sets the horizontal or vertical center of the target area or " +
"item as the starting point, depending on the distribution " +
"orientation.")
}
AbstractButton {
@@ -271,6 +279,8 @@ Section {
buttonIcon: StudioTheme.Constants.distributeOriginBottomRight
checkable: true
StudioControls.ButtonGroup.group: group
tooltip: qsTr("Sets the bottom or right border of the target area or item as " +
"the starting point, depending on the distribution orientation.")
}
}
}
@@ -280,12 +290,13 @@ Section {
SecondColumnLayout {
Spacer { implicitWidth: StudioTheme.Values.actionIndicatorWidth }
StudioControls.RealSpinBox {
DoubleSpinBox {
id: distanceSpinBox
implicitWidth: StudioTheme.Values.twoControlColumnWidth
actionIndicatorVisible: false
realFrom: -1000
realTo: 1000
stepSize: 1
minimumValue: -1000
maximumValue: 1000
decimals: 0
enabled: !buttonNone.checked
}
}
@@ -278,7 +278,7 @@ QtObject {
property string themeStateBackground: Theme.color(Theme.DSstateBackgroundColor)
property string themeStatePreviewOutline: Theme.color(Theme.DSstatePreviewOutline)
property string themeUnimportedModuleColor: "#e33c2e"
property string themeUnimportedModuleColor: Theme.color(Theme.DSUnimportedModuleColor)
// Taken out of Constants.js
property string themeChangedStateText: Theme.color(Theme.DSchangedStateText)
+2
View File
@@ -152,6 +152,8 @@ DStoolTipBackground=ff111111
DStoolTipOutline=ffdadada
DStoolTipText=ffdadada
DSUnimportedModuleColor=ffe33c2e
;DS controls theme END
BackgroundColorAlternate=alternateBackground
@@ -143,6 +143,8 @@ DStoolTipBackground=ff111111
DStoolTipOutline=ffdadada
DStoolTipText=ffdadada
DSUnimportedModuleColor=ffe33c2e
;DS controls theme END
BackgroundColorAlternate=ff3d3d3d
@@ -157,6 +157,8 @@ DStoolTipBackground=ff111111
DStoolTipOutline=ffdadada
DStoolTipText=ffdadada
DSUnimportedModuleColor=ffe33c2e
;DS controls theme END
BackgroundColorAlternate=alternateBackground
@@ -154,6 +154,8 @@ DStoolTipBackground=ff111111
DStoolTipOutline=ffdadada
DStoolTipText=ffdadada
DSUnimportedModuleColor=ffe33c2e
;DS controls theme END
BackgroundColorAlternate=alternateBackground
@@ -156,6 +156,8 @@ DStoolTipBackground=ff111111
DStoolTipOutline=ffdadada
DStoolTipText=ffdadada
DSUnimportedModuleColor=ffe33c2e
;DS controls theme END
BackgroundColorAlternate=alternateBackground
@@ -152,6 +152,8 @@ DStoolTipBackground=ff111111
DStoolTipOutline=ffdadada
DStoolTipText=ffdadada
DSUnimportedModuleColor=ffe33c2e
;DS controls theme END
BackgroundColorAlternate=alternateBackground
+2
View File
@@ -150,6 +150,8 @@ DStoolTipBackground=ff111111
DStoolTipOutline=ffdadada
DStoolTipText=ffdadada
DSUnimportedModuleColor=ffe33c2e
;DS controls theme END
BackgroundColorAlternate=alternateBackground
+3 -2
View File
@@ -43,8 +43,9 @@ enum class LanguageVersion : unsigned char {
CXX11,
CXX14,
CXX17,
CXX2a,
LatestCxx = CXX2a,
CXX20,
CXX2b,
LatestCxx = CXX2b,
};
enum class LanguageExtension : unsigned char {
+2 -2
View File
@@ -391,7 +391,7 @@ void ShellCommand::runSynchronous(QtcProcess &process, const FilePath &workingDi
if (d->m_progressParser)
d->m_progressParser->parseProgress(text);
if (!(d->m_flags & SuppressStdErr))
appendError(text);
emit appendError(text);
if (d->m_progressiveOutput)
emit stdErrText(text);
});
@@ -403,7 +403,7 @@ void ShellCommand::runSynchronous(QtcProcess &process, const FilePath &workingDi
if (d->m_progressParser)
d->m_progressParser->parseProgress(text);
if (d->m_flags & ShowStdOut)
append(text);
emit append(text);
if (d->m_progressiveOutput) {
emit stdOutText(text);
d->m_hadOutput = true;
+3 -1
View File
@@ -417,7 +417,9 @@ public:
DStoolTipBackground,
DStoolTipOutline,
DStoolTipText
DStoolTipText,
DSUnimportedModuleColor
};
enum Gradient {
+7 -1
View File
@@ -47,7 +47,13 @@ QUrl urlFromLocalSocket()
{
QUrl serverUrl;
serverUrl.setScheme(urlSocketScheme());
TemporaryFile file("qtcreator-freesocket");
TemporaryFile file("qtc-socket");
// see "man unix" for unix socket file name size limitations
if (file.fileName().size() > 104) {
qWarning().nospace()
<< "Socket file name \"" << file.fileName()
<< "\" is larger than 104 characters, which will not work on Darwin/macOS/Linux!";
}
if (file.open())
serverUrl.setPath(file.fileName());
return serverUrl;
+2 -2
View File
@@ -333,7 +333,7 @@ QString AndroidAvdManager::waitForAvd(const QString &avdName,
// 60 rounds of 2s sleeping, two minutes for the avd to start
QString serialNumber;
for (int i = 0; i < 60; ++i) {
if (cancelChecker())
if (cancelChecker && cancelChecker())
return QString();
serialNumber = findAvd(avdName);
if (!serialNumber.isEmpty())
@@ -365,7 +365,7 @@ bool AndroidAvdManager::waitForBooted(const QString &serialNumber,
{
// found a serial number, now wait until it's done booting...
for (int i = 0; i < 60; ++i) {
if (cancelChecker())
if (cancelChecker && cancelChecker())
return false;
if (isAvdBooted(serialNumber)) {
return true;
+2 -1
View File
@@ -176,7 +176,8 @@ AndroidBuildApkWidget::AndroidBuildApkWidget(AndroidBuildApkStep *step)
QWidget *AndroidBuildApkWidget::createApplicationGroup()
{
const int minApiSupported = AndroidManager::apiLevelRange().first;
QtSupport::BaseQtVersion *qt = QtSupport::QtKitAspect::qtVersion(m_step->target()->kit());
const int minApiSupported = AndroidManager::defaultMinimumSDK(qt);
QStringList targets = AndroidConfig::apiLevelNamesFor(AndroidConfigurations::sdkManager()->
filteredSdkPlatforms(minApiSupported));
targets.removeDuplicates();
+12 -8
View File
@@ -778,12 +778,12 @@ bool AndroidConfig::isValidNdk(const QString &ndkLocation) const
QString AndroidConfig::bestNdkPlatformMatch(int target, const BaseQtVersion *qtVersion) const
{
target = std::max(AndroidManager::apiLevelRange().first, target);
target = std::max(AndroidManager::defaultMinimumSDK(qtVersion), target);
foreach (int apiLevel, availableNdkPlatforms(qtVersion)) {
if (apiLevel <= target)
return QString::fromLatin1("android-%1").arg(apiLevel);
}
return QString("android-%1").arg(AndroidManager::apiLevelRange().first);
return QString("android-%1").arg(AndroidManager::defaultMinimumSDK(qtVersion));
}
FilePath AndroidConfig::sdkLocation() const
@@ -1291,10 +1291,7 @@ void AndroidConfigurations::updateAutomaticKitList()
Id deviceTypeId = DeviceTypeKitAspect::deviceTypeId(k);
if (k->isAutoDetected() && !k->isSdkProvided()
&& deviceTypeId == Constants::ANDROID_DEVICE_TYPE) {
if (!QtKitAspect::qtVersion(k))
KitManager::deregisterKit(k); // Remove autoDetected kits without Qt.
else
return true;
return true;
}
return false;
});
@@ -1327,6 +1324,7 @@ void AndroidConfigurations::updateAutomaticKitList()
&& tc->isValid()
&& tc->typeId() == Constants::ANDROID_TOOLCHAIN_TYPEID;
});
QList<Kit *> unhandledKits = existingKits;
for (ToolChain *tc : toolchains) {
if (tc->language() != ProjectExplorer::Constants::CXX_LANGUAGE_ID)
continue;
@@ -1381,12 +1379,18 @@ void AndroidConfigurations::updateAutomaticKitList()
k->setValueSilently(Constants::ANDROID_KIT_SDK, currentConfig().sdkLocation().toString());
};
if (existingKit)
if (existingKit) {
initializeKit(existingKit); // Update the existing kit with new data.
else
unhandledKits.removeOne(existingKit);
} else {
KitManager::registerKit(initializeKit);
}
}
}
// cleanup any mess that might have existed before, by removing all Android kits that
// existed before, but weren't re-used
for (Kit *k : unhandledKits)
KitManager::deregisterKit(k);
}
bool AndroidConfigurations::force32bitEmulator()
+7 -2
View File
@@ -399,9 +399,14 @@ void AndroidManager::setDeviceApiLevel(Target *target, int level)
target->setNamedSettings(ApiLevelKey, level);
}
QPair<int, int> AndroidManager::apiLevelRange()
int AndroidManager::defaultMinimumSDK(const QtSupport::BaseQtVersion *qtVersion)
{
return qMakePair(16, 29);
if (qtVersion && qtVersion->qtVersion() >= QtSupport::QtVersionNumber{6, 0})
return 23;
else if (qtVersion && qtVersion->qtVersion() >= QtSupport::QtVersionNumber{5, 13})
return 21;
else
return 16;
}
QString AndroidManager::androidNameForApiLevel(int x)
+2 -1
View File
@@ -31,6 +31,7 @@
#include <QObject>
#include <QVersionNumber>
#include <qtsupport/baseqtversion.h>
#include <projectexplorer/abi.h>
QT_BEGIN_NAMESPACE
@@ -87,6 +88,7 @@ public:
static int minimumSDK(const ProjectExplorer::Target *target);
static int minimumSDK(const ProjectExplorer::Kit *kit);
static int defaultMinimumSDK(const QtSupport::BaseQtVersion *qtVersion);
static QStringList applicationAbis(const ProjectExplorer::Target *target);
static QString archTriplet(const QString &abi);
@@ -100,7 +102,6 @@ public:
static QString devicePreferredAbi(const QStringList &deviceAbis, const QStringList &appAbis);
static ProjectExplorer::Abi androidAbi2Abi(const QString &androidAbi);
static QPair<int, int> apiLevelRange();
static QString androidNameForApiLevel(int x);
static void installQASIPackage(ProjectExplorer::Target *target, const Utils::FilePath &packagePath);
@@ -720,18 +720,21 @@ void AndroidManifestEditorWidget::updateInfoBar()
void AndroidManifestEditorWidget::updateSdkVersions()
{
QPair<int, int> apiLevels = AndroidManager::apiLevelRange();
for (int i = apiLevels.first; i < apiLevels.second + 1; ++i)
m_androidMinSdkVersion->addItem(tr("API %1: %2")
.arg(i)
.arg(AndroidManager::androidNameForApiLevel(i)),
i);
static const QPair<int, int> sdkPair = qMakePair(16, 31);
int minSdk = sdkPair.first;
const int targetSdk = sdkPair.second;
const Target *target = androidTarget(m_textEditorWidget->textDocument()->filePath());
if (target) {
const QtSupport::BaseQtVersion *qt = QtSupport::QtKitAspect::qtVersion(target->kit());
minSdk = AndroidManager::defaultMinimumSDK(qt);
}
for (int i = apiLevels.first; i < apiLevels.second + 1; ++i)
m_androidTargetSdkVersion->addItem(tr("API %1: %2")
.arg(i)
.arg(AndroidManager::androidNameForApiLevel(i)),
i);
for (int i = minSdk; i <= targetSdk; ++i) {
const QString apiStr = tr("API %1: %2").arg(i)
.arg(AndroidManager::androidNameForApiLevel(i));
m_androidMinSdkVersion->addItem(apiStr, i);
m_androidTargetSdkVersion->addItem(apiStr, i);
}
}
void AndroidManifestEditorWidget::updateInfoBar(const QString &errorMessage, int line, int column)
@@ -191,12 +191,14 @@ static bool isChildOf(const FilePath &path, const QStringList &prefixes)
QList<CMakeBuildTarget> generateBuildTargets(const PreprocessedData &input,
const FilePath &sourceDirectory,
const FilePath &buildDirectory)
const FilePath &buildDirectory,
bool haveLibrariesRelativeToBuildDirectory)
{
QDir sourceDir(sourceDirectory.toString());
const QList<CMakeBuildTarget> result = transform<QList>(input.targetDetails,
[&sourceDir, &sourceDirectory, &buildDirectory](const TargetDetails &t) {
[&sourceDir, &sourceDirectory, &buildDirectory,
&haveLibrariesRelativeToBuildDirectory](const TargetDetails &t) {
const FilePath currentBuildDir = buildDirectory.absoluteFilePath(t.buildDir);
CMakeBuildTarget ct;
@@ -271,7 +273,8 @@ QList<CMakeBuildTarget> generateBuildTargets(const PreprocessedData &input,
if (part.startsWith("-"))
continue;
FilePath tmp = currentBuildDir.absoluteFilePath(FilePath::fromUserInput(part));
const FilePath buildDir = haveLibrariesRelativeToBuildDirectory ? buildDirectory : currentBuildDir;
FilePath tmp = buildDir.absoluteFilePath(FilePath::fromUserInput(part));
if (f.role == "libraries")
tmp = tmp.parentDir();
@@ -707,7 +710,12 @@ FileApiQtcData extractData(FileApiData &input,
return {};
}
result.buildTargets = generateBuildTargets(data, sourceDirectory, buildDirectory);
// Ninja generator from CMake version 3.20.5 has libraries relative to build directory
const bool haveLibrariesRelativeToBuildDirectory =
input.replyFile.generator.startsWith("Ninja")
&& input.replyFile.cmakeVersion >= QVersionNumber(3, 20, 5);
result.buildTargets = generateBuildTargets(data, sourceDirectory, buildDirectory, haveLibrariesRelativeToBuildDirectory);
result.cmakeFiles = std::move(data.cmakeFiles);
result.projectParts = generateRawProjectParts(data, sourceDirectory);
@@ -147,6 +147,13 @@ static ReplyFileContents readReplyFile(const FilePath &filePath, QString &errorM
result.generator = generator.value("name").toString();
result.isMultiConfig = generator.value("multiConfig").toBool();
}
const QJsonObject version = cmakeObject.value("version").toObject();
{
int major = version.value("major").toInt();
int minor = version.value("minor").toInt();
int patch = version.value("patch").toInt();
result.cmakeVersion = QVersionNumber(major, minor, patch);
}
}
}
@@ -39,6 +39,7 @@
#include <QFutureInterface>
#include <QString>
#include <QVector>
#include <QVersionNumber>
#include <vector>
@@ -65,6 +66,7 @@ public:
QString cmakeRoot;
QVector<ReplyObject> replies;
QVersionNumber cmakeVersion;
Utils::FilePath jsonFile(const QString &kind, const Utils::FilePath &replyDir) const;
};
+2 -1
View File
@@ -164,7 +164,8 @@ QStringList CppcheckTool::additionalArguments(const CppTools::ProjectPart &part)
break;
case Version::CXX98:
case Version::CXX17:
case Version::CXX2a:
case Version::CXX20:
case Version::CXX2b:
result.push_back("--language=c++");
break;
case Version::None:
@@ -92,15 +92,15 @@ public:
filePaths << absoluteFilePath;
}
// Update Code Model
QVERIFY(parseFiles(filePaths));
// Open Editor
const QString fileName = temporaryDir.path() + QLatin1String("/file1.h");
CppEditor *editor;
QVERIFY(openCppEditor(fileName, &editor));
closeEditorAtEndOfTestCase(editor);
// Update Code Model
QVERIFY(parseFiles(filePaths));
// Test model
CppIncludeHierarchyModel model;
model.buildHierarchy(editor->document()->filePath().toString());
@@ -472,7 +472,10 @@ void CompilerOptionsBuilder::addLanguageVersionAndExtensions()
case LanguageVersion::CXX17:
option = "/std:c++17";
break;
case LanguageVersion::CXX2a:
case LanguageVersion::CXX20:
option = "/std:c++20";
break;
case LanguageVersion::CXX2b:
option = "/std:c++latest";
break;
}
@@ -517,8 +520,11 @@ void CompilerOptionsBuilder::addLanguageVersionAndExtensions()
case LanguageVersion::CXX17:
option = (gnuExtensions ? QLatin1String("-std=gnu++17") : QLatin1String("-std=c++17"));
break;
case LanguageVersion::CXX2a:
option = (gnuExtensions ? QLatin1String("-std=gnu++2a") : QLatin1String("-std=c++2a"));
case LanguageVersion::CXX20:
option = (gnuExtensions ? QLatin1String("-std=gnu++20") : QLatin1String("-std=c++20"));
break;
case LanguageVersion::CXX2b:
option = (gnuExtensions ? QLatin1String("-std=gnu++2b") : QLatin1String("-std=c++2b"));
break;
case LanguageVersion::None:
break;
@@ -868,6 +874,14 @@ void CompilerOptionsBuilder::evaluateCompilerFlags()
theOption[0] = '-';
}
// Clang-cl (as of Clang 12) frontend doesn't know about -std:c++20
// but the clang front end knows about -std=c++20
// https://github.com/llvm/llvm-project/blob/release/12.x/clang/lib/Driver/ToolChains/Clang.cpp#L5855
if (toolChain == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID ||
toolChain == ProjectExplorer::Constants::CLANG_CL_TOOLCHAIN_TYPEID) {
theOption.replace("-std:c++20", "-clang:-std=c++20");
}
m_compilerFlags.flags.append(theOption);
}
@@ -123,7 +123,8 @@ QString Utils::toString(::Utils::LanguageVersion languageVersion)
CASE_LANGUAGEVERSION(CXX11);
CASE_LANGUAGEVERSION(CXX14);
CASE_LANGUAGEVERSION(CXX17);
CASE_LANGUAGEVERSION(CXX2a);
CASE_LANGUAGEVERSION(CXX20);
CASE_LANGUAGEVERSION(CXX2b);
// no default to get a compiler warning if anything is added
}
#undef CASE_LANGUAGEVERSION
@@ -235,7 +235,7 @@ QVariant FlatModel::data(const QModelIndex &index, int role) const
}
case Qt::DecorationRole: {
if (!folderNode)
return Core::FileIconProvider::icon(node->filePath());
return node->asFileNode()->icon();
if (!project)
return folderNode->icon();
static QIcon warnIcon = Utils::Icons::WARNING.icon();
@@ -44,6 +44,7 @@
#include <utils/pointeralgorithm.h>
#include <utils/qtcassert.h>
#include <utils/stringutils.h>
#include <utils/utilsicons.h>
#include <QDir>
#include <QFileInfo>
@@ -252,6 +253,35 @@ bool Node::isEnabled() const
return parent ? parent->isEnabled() : true;
}
QIcon FileNode::icon() const
{
if (hasError())
return Utils::Icons::WARNING.icon();
if (m_icon.isNull())
m_icon = Core::FileIconProvider::icon(filePath());
return m_icon;
}
void FileNode::setIcon(const QIcon icon)
{
m_icon = icon;
}
bool FileNode::hasError() const
{
return m_hasError;
}
void FileNode::setHasError(bool error)
{
m_hasError = error;
}
void FileNode::setHasError(bool error) const
{
m_hasError = error;
}
/*!
Returns \c true if the file is automatically generated by a compile step.
*/
@@ -218,8 +218,17 @@ public:
bool supportsAction(ProjectAction action, const Node *node) const override;
QString displayName() const override;
bool hasError() const;
void setHasError(const bool error);
void setHasError(const bool error) const;
QIcon icon() const;
void setIcon(const QIcon icon);
private:
FileType m_fileType;
mutable QIcon m_icon;
mutable bool m_hasError = false;
};
// Documentation inside.
+1
View File
@@ -10,6 +10,7 @@ add_qtc_plugin(QmlDesigner
DEFINES
DESIGNER_CORE_LIBRARY
IDE_LIBRARY_BASENAME=\"${IDE_LIBRARY_BASE_PATH}\"
SHARE_QML_PATH="${CMAKE_CURRENT_SOURCE_DIR}/../../../share/qtcreator/qmldesigner"
PUBLIC_INCLUDES
"${CMAKE_CURRENT_LIST_DIR}"
"${CMAKE_CURRENT_LIST_DIR}/designercore/include"
@@ -48,6 +48,24 @@ static QString styleConfigFileName(const QString &qmlFileName)
ChangeStyleWidgetAction::ChangeStyleWidgetAction(QObject *parent) : QWidgetAction(parent)
{
// The Default style was renamed to Basic in Qt 6. In Qt 6, "Default"
// will result in a platform-specific style being chosen.
items = {
{"Basic", "Basic", {}},
{"Default", "Default", {}},
{"Fusion", "Fusion", {}},
{"Imagine", "Imagine", {}},
{"Material Light", "Material", "Light"},
{"Material Dark", "Material", "Dark"},
{"Universal Light", "Universal", "Light"},
{"Universal Dark", "Universal", "Dark"},
{"Universal System", "Universal", "System"}
};
if (Utils::HostOsInfo::isMacHost())
items.append({"macOS", "macOS", {}});
if (Utils::HostOsInfo::isWindowsHost())
items.append({"Windows", "Windows", {}});
}
void ChangeStyleWidgetAction::handleModelUpdate(const QString &style)
@@ -55,6 +73,48 @@ void ChangeStyleWidgetAction::handleModelUpdate(const QString &style)
emit modelUpdated(style);
}
const QList<StyleWidgetEntry> ChangeStyleWidgetAction::styleItems() const
{
return items;
}
void ChangeStyleWidgetAction::changeStyle(const QString &style)
{
if (style.isEmpty())
return;
const Utils::FilePath configFileName = Utils::FilePath::fromString(styleConfigFileName(qmlFileName));
if (configFileName.exists()) {
QSettings infiFile(configFileName.toString(), QSettings::IniFormat);
int contains = -1;
for (const auto &item : qAsConst(items)) {
if (item.displayName == style) {
contains = items.indexOf(item);
break;
}
}
if (contains >= 0) {
const QString styleName = items.at(contains).styleName;
const QString styleTheme = items.at(contains).styleTheme;
infiFile.setValue("Controls/Style", styleName);
if (!styleTheme.isEmpty())
infiFile.setValue((styleName + "/Theme"), styleTheme);
}
else {
infiFile.setValue("Controls/Style", style);
}
if (view)
view->resetPuppet();
}
}
const char enabledTooltip[] = QT_TRANSLATE_NOOP("ChangeStyleWidgetAction",
"Change style for Qt Quick Controls 2.");
const char disbledTooltip[] = QT_TRANSLATE_NOOP("ChangeStyleWidgetAction",
@@ -64,18 +124,10 @@ QWidget *ChangeStyleWidgetAction::createWidget(QWidget *parent)
{
auto comboBox = new QComboBox(parent);
comboBox->setToolTip(tr(enabledTooltip));
// The Default style was renamed to Basic in Qt 6. In Qt 6, "Default"
// will result in a platform-specific style being chosen.
comboBox->addItem("Basic");
comboBox->addItem("Default");
comboBox->addItem("Fusion");
comboBox->addItem("Imagine");
if (Utils::HostOsInfo::isMacHost())
comboBox->addItem("macOS");
comboBox->addItem("Material");
comboBox->addItem("Universal");
if (Utils::HostOsInfo::isWindowsHost())
comboBox->addItem("Windows");
for (const auto &item : qAsConst(items))
comboBox->addItem(item.displayName);
comboBox->setEditable(true);
comboBox->setCurrentIndex(0);
@@ -97,23 +149,8 @@ QWidget *ChangeStyleWidgetAction::createWidget(QWidget *parent)
}
});
connect(comboBox,
&QComboBox::textActivated,
this,
[this](const QString &style) {
if (style.isEmpty())
return;
const Utils::FilePath configFileName = Utils::FilePath::fromString(styleConfigFileName(qmlFileName));
if (configFileName.exists()) {
QSettings infiFile(configFileName.toString(), QSettings::IniFormat);
infiFile.setValue("Controls/Style", style);
if (view)
view->resetPuppet();
}
});
connect(comboBox, &QComboBox::textActivated,
this, &ChangeStyleWidgetAction::changeStyle);
return comboBox;
}
@@ -135,11 +172,27 @@ void ChangeStyleAction::currentContextChanged(const SelectionContext &selectionC
if (Utils::FilePath::fromString(confFileName).exists()) {
QSettings infiFile(confFileName, QSettings::IniFormat);
m_action->handleModelUpdate(infiFile.value("Controls/Style", "Basic").toString());
const QString styleName = infiFile.value("Controls/Style", "Basic").toString();
const QString styleTheme = infiFile.value(styleName + "/Theme", "").toString();
const auto items = m_action->styleItems();
QString comboBoxEntry = styleName;
for (const auto &item : items) {
if (item.styleName == styleName) {
if (!styleTheme.isEmpty() && (item.styleTheme == styleTheme)) {
comboBoxEntry.append(" ");
comboBoxEntry.append(styleTheme);
break;
}
}
}
m_action->handleModelUpdate(comboBoxEntry);
} else {
m_action->handleModelUpdate("");
}
}
}
@@ -38,6 +38,24 @@ namespace QmlDesigner {
class AbstractView;
struct StyleWidgetEntry {
QString displayName;
QString styleName;
QString styleTheme;
bool operator==(const StyleWidgetEntry &entry) const {
if (displayName != entry.displayName)
return false;
if (styleName != entry.styleName)
return false;
if (styleTheme != entry.styleTheme)
return false;
return true;
};
};
class ChangeStyleWidgetAction : public QWidgetAction
{
Q_OBJECT
@@ -46,6 +64,11 @@ public:
explicit ChangeStyleWidgetAction(QObject *parent = nullptr);
void handleModelUpdate(const QString &style);
const QList<StyleWidgetEntry> styleItems() const;
public slots:
void changeStyle(const QString &style);
protected:
QWidget *createWidget(QWidget *parent) override;
@@ -55,6 +78,8 @@ signals:
public:
QString qmlFileName;
QPointer<AbstractView> view;
QList<StyleWidgetEntry> items;
};
class ChangeStyleAction : public ActionInterface
@@ -128,7 +128,7 @@ QString Theme::replaceCssColors(const QString &input)
void Theme::setupTheme(QQmlEngine *engine)
{
static const int typeIndex = qmlRegisterSingletonType<Theme>(
"QtQuickDesignerTheme", 1, 0, "Theme", [](QQmlEngine *engine, QJSEngine *) {
"QtQuickDesignerTheme", 1, 0, "Theme", [](QQmlEngine *, QJSEngine *) {
return new Theme(Utils::creatorTheme(), nullptr);
});
Q_UNUSED(typeIndex)
@@ -79,6 +79,10 @@ namespace QmlDesigner {
static QString propertyEditorResourcesPath()
{
#ifdef SHARE_QML_PATH
if (qEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
return QLatin1String(SHARE_QML_PATH) + "/propertyEditorQmlSources";
#endif
return Core::ICore::resourcePath("qmldesigner/propertyEditorQmlSources").toString();
}
@@ -376,6 +380,10 @@ void ItemLibraryWidget::handleTabChanged(int index)
QString ItemLibraryWidget::qmlSourcesPath()
{
#ifdef SHARE_QML_PATH
if (qEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
return QLatin1String(SHARE_QML_PATH) + "/itemLibraryQmlSources";
#endif
return Core::ICore::resourcePath("qmldesigner/itemLibraryQmlSources").toString();
}
@@ -46,6 +46,10 @@
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/icore.h>
#include <projectexplorer/project.h>
#include <projectexplorer/session.h>
#include <projectexplorer/projectnodes.h>
#include <utils/algorithm.h>
#include <utils/icon.h>
#include <utils/utilsicons.h>
@@ -169,6 +173,29 @@ void NavigatorView::modelAttached(Model *model)
}
}
});
clearExplorerWarnings();
}
void NavigatorView::clearExplorerWarnings()
{
QList<ModelNode> allNodes;
addNodeAndSubModelNodesToList(rootModelNode(), allNodes);
for (ModelNode node : allNodes) {
if (node.metaInfo().isFileComponent()) {
const ProjectExplorer::FileNode *fnode = fileNodeForModelNode(node);
if (fnode)
fnode->setHasError(false);
}
}
}
void NavigatorView::addNodeAndSubModelNodesToList(const ModelNode &node, QList<ModelNode> &nodes)
{
nodes.append(node);
for (ModelNode subNode : node.allSubModelNodes()) {
addNodeAndSubModelNodesToList(subNode, nodes);
}
}
void NavigatorView::modelAboutToBeDetached(Model *model)
@@ -342,8 +369,10 @@ void NavigatorView::auxiliaryDataChanged(const ModelNode &modelNode,
void NavigatorView::instanceErrorChanged(const QVector<ModelNode> &errorNodeList)
{
for (const ModelNode &modelNode : errorNodeList)
for (const ModelNode &modelNode : errorNodeList) {
m_currentModelInterface->notifyDataChanged(modelNode);
propagateInstanceErrorToExplorer(modelNode);
}
}
void NavigatorView::nodeOrderChanged(const NodeListProperty &listProperty)
@@ -374,6 +403,52 @@ QAbstractItemModel *NavigatorView::currentModel() const
return treeWidget()->model();
}
const ProjectExplorer::FileNode *NavigatorView::fileNodeForModelNode(const ModelNode &node) const
{
QString filename = node.metaInfo().componentFileName();
Utils::FilePath filePath = Utils::FilePath::fromString(filename);
ProjectExplorer::Project *currentProject = ProjectExplorer::SessionManager::projectForFile(
filePath);
if (!currentProject) {
filePath = Utils::FilePath::fromString(node.model()->fileUrl().toLocalFile());
/* If the component does not belong to the project then we can fallback to the current file */
currentProject = ProjectExplorer::SessionManager::projectForFile(filePath);
}
if (!currentProject)
return nullptr;
return currentProject->nodeForFilePath(filePath)->asFileNode();
}
const ProjectExplorer::FileNode *NavigatorView::fileNodeForIndex(const QModelIndex &index) const
{
if (index.isValid() && currentModel()->data(index, Qt::UserRole).isValid()) {
ModelNode node = modelNodeForIndex(index);
if (node.metaInfo().isFileComponent()) {
return fileNodeForModelNode(node);
}
}
return nullptr;
}
void NavigatorView::propagateInstanceErrorToExplorer(const ModelNode &modelNode) {
QModelIndex index = indexForModelNode(modelNode);;
do {
const ProjectExplorer::FileNode *fnode = fileNodeForIndex(index);
if (fnode) {
fnode->setHasError(true);
return;
}
else {
index = index.parent();
}
} while (index.isValid());
}
void NavigatorView::leftButtonClicked()
{
if (selectedModelNodes().count() > 1)
@@ -28,6 +28,7 @@
#include "navigatormodelinterface.h"
#include <abstractview.h>
#include <projectexplorer/projectnodes.h>
#include <QPointer>
#include <QHash>
@@ -108,6 +109,7 @@ private:
void changeToComponent(const QModelIndex &index);
QModelIndex indexForModelNode(const ModelNode &modelNode) const;
QAbstractItemModel *currentModel() const;
void propagateInstanceErrorToExplorer(const ModelNode &modelNode);
void leftButtonClicked();
void rightButtonClicked();
@@ -123,6 +125,10 @@ protected: //functions
void expandAncestors(const QModelIndex &index);
void reparentAndCatch(NodeAbstractProperty property, const ModelNode &modelNode);
void setupWidget();
void addNodeAndSubModelNodesToList(const ModelNode &node, QList<ModelNode> &nodes);
void clearExplorerWarnings();
const ProjectExplorer::FileNode *fileNodeForModelNode(const ModelNode &node) const;
const ProjectExplorer::FileNode *fileNodeForIndex(const QModelIndex &index) const;
private:
bool m_blockSelectionChangedSignal;
@@ -47,8 +47,9 @@
#include <QApplication>
#include <QDir>
#include <QFileInfo>
#include <QVector3D>
#include <QVector2D>
#include <QVector3D>
#include <QVector4D>
#include <QLoggingCategory>
@@ -343,6 +344,18 @@ void PropertyEditorQmlBackend::setValue(const QmlObjectNode & , const PropertyNa
if (propertyValue)
propertyValue->setValue(QVariant(vecValue[i]));
}
} else if (value.type() == QVariant::Vector4D) {
const char *suffix[4] = {"_x", "_y", "_z", "_w"};
auto vecValue = value.value<QVector4D>();
for (int i = 0; i < 4; ++i) {
PropertyName subPropName(name.size() + 2, '\0');
subPropName.replace(0, name.size(), name);
subPropName.replace(name.size(), 2, suffix[i]);
auto propertyValue = qobject_cast<PropertyEditorValue *>(
variantToQObject(m_backendValuesPropertyMap.value(QString::fromUtf8(subPropName))));
if (propertyValue)
propertyValue->setValue(QVariant(vecValue[i]));
}
} else {
PropertyName propertyName = name;
propertyName.replace('.', '_');
@@ -532,6 +545,10 @@ void PropertyEditorQmlBackend::initialSetup(const TypeName &typeName, const QUrl
QString PropertyEditorQmlBackend::propertyEditorResourcesPath()
{
#ifdef SHARE_QML_PATH
if (qEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
return QLatin1String(SHARE_QML_PATH) + "/propertyEditorQmlSources";
#endif
return Core::ICore::resourcePath("qmldesigner/propertyEditorQmlSources").toString();
}
@@ -227,14 +227,21 @@ void PropertyEditorView::changeValue(const QString &name)
removePropertyFromModel(propertyName);
} else {
// QVector*D(0, 0, 0) detects as null variant though it is valid value
if (castedValue.isValid() && (!castedValue.isNull()
|| castedValue.type() == QVariant::Vector2D
|| castedValue.type() == QVariant::Vector3D)) {
if (castedValue.isValid()
&& (!castedValue.isNull() || castedValue.type() == QVariant::Vector2D
|| castedValue.type() == QVariant::Vector3D
|| castedValue.type() == QVariant::Vector4D)) {
commitVariantValueToModel(propertyName, castedValue);
}
}
}
static bool isTrueFalseLiteral(const QString &expression)
{
return (expression.compare("false", Qt::CaseInsensitive) == 0)
|| (expression.compare("true", Qt::CaseInsensitive) == 0);
}
void PropertyEditorView::changeExpression(const QString &propertyName)
{
PropertyName name = propertyName.toUtf8();
@@ -267,9 +274,8 @@ void PropertyEditorView::changeExpression(const QString &propertyName)
return;
}
} else if (qmlObjectNode->modelNode().metaInfo().propertyTypeName(name) == "bool") {
if (value->expression().compare(QLatin1String("false"), Qt::CaseInsensitive) == 0
|| value->expression().compare(QLatin1String("true"), Qt::CaseInsensitive) == 0) {
if (value->expression().compare(QLatin1String("true"), Qt::CaseInsensitive) == 0)
if (isTrueFalseLiteral(value->expression())) {
if (value->expression().compare("true", Qt::CaseInsensitive) == 0)
qmlObjectNode->setVariantProperty(name, true);
else
qmlObjectNode->setVariantProperty(name, false);
@@ -289,6 +295,19 @@ void PropertyEditorView::changeExpression(const QString &propertyName)
qmlObjectNode->setVariantProperty(name, realValue);
return;
}
} else if (qmlObjectNode->modelNode().metaInfo().propertyTypeName(name) == "QVariant") {
bool ok;
qreal realValue = value->expression().toDouble(&ok);
if (ok) {
qmlObjectNode->setVariantProperty(name, realValue);
return;
} else if (isTrueFalseLiteral(value->expression())) {
if (value->expression().compare("true", Qt::CaseInsensitive) == 0)
qmlObjectNode->setVariantProperty(name, true);
else
qmlObjectNode->setVariantProperty(name, false);
return;
}
}
}
@@ -894,7 +894,8 @@ QmlItemNode QmlAnchorBindingProxy::targetIdToNode(const QString &id) const
QString QmlAnchorBindingProxy::idForNode(const QmlItemNode &qmlItemNode) const
{
QTC_ASSERT(qmlItemNode.modelNode().isValid(), return {});
if (!qmlItemNode.modelNode().isValid())
return {};
if (!qmlItemNode.isValid())
return qmlItemNode.id();
@@ -58,6 +58,10 @@ namespace QmlDesigner {
static QString propertyEditorResourcesPath()
{
#ifdef SHARE_QML_PATH
if (qEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
return QLatin1String(SHARE_QML_PATH) + "/propertyEditorQmlSources";
#endif
return Core::ICore::resourcePath("qmldesigner/propertyEditorQmlSources").toString();
}
@@ -122,6 +126,10 @@ StatesEditorWidget::~StatesEditorWidget() = default;
QString StatesEditorWidget::qmlSourcesPath()
{
#ifdef SHARE_QML_PATH
if (qEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
return QLatin1String(SHARE_QML_PATH) + "/statesEditorQmlSources";
#endif
return Core::ICore::resourcePath("qmldesigner/statesEditorQmlSources").toString();
}
@@ -32,8 +32,9 @@
#include <QDebug>
#include <QPainter>
#include <QVector3D>
#include <QVector2D>
#include <QVector3D>
#include <QVector4D>
QT_BEGIN_NAMESPACE
void qt_blurImage(QPainter *painter, QImage &blurImage, qreal radius, bool quality, bool alphaOnly, int transposed = 0);
@@ -352,6 +353,28 @@ QVariant NodeInstance::property(const PropertyName &name) const
break;
}
return QVariant(subValue);
} else if (varValue.type() == QVariant::Vector4D) {
auto value = varValue.value<QVector4D>();
char subProp = name.right(1)[0];
float subValue = 0.f;
switch (subProp) {
case 'x':
subValue = value.x();
break;
case 'y':
subValue = value.y();
break;
case 'z':
subValue = value.z();
break;
case 'w':
subValue = value.w();
break;
default:
subValue = 0.f;
break;
}
return QVariant(subValue);
}
}
}
@@ -443,6 +466,24 @@ void NodeInstance::setProperty(const PropertyName &name, const QVariant &value)
update = true;
}
newValueVar = newValue;
} else if (oldValue.type() == QVariant::Vector4D) {
QVector4D newValue;
if (oldValue.type() == QVariant::Vector4D)
newValue = oldValue.value<QVector4D>();
if (name.endsWith(".x")) {
newValue.setX(value.toFloat());
update = true;
} else if (name.endsWith(".y")) {
newValue.setY(value.toFloat());
update = true;
} else if (name.endsWith(".z")) {
newValue.setZ(value.toFloat());
update = true;
} else if (name.endsWith(".w")) {
newValue.setW(value.toFloat());
update = true;
}
newValueVar = newValue;
}
if (update) {
d->propertyValues.insert(parentPropName, newValueVar);

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