forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/11.0'
Conflicts: cmake/QtCreatorIDEBranding.cmake qbs/modules/qtc/qtc.qbs Change-Id: Ide0650d70d5dbd32a5492c8db24089925251af12
This commit is contained in:
188
dist/changelog/changes-11.0.0.md
vendored
188
dist/changelog/changes-11.0.0.md
vendored
@@ -10,21 +10,83 @@ the public Git repository. For example:
|
|||||||
git clone git://code.qt.io/qt-creator/qt-creator.git
|
git clone git://code.qt.io/qt-creator/qt-creator.git
|
||||||
git log --cherry-pick --pretty=oneline origin/10.0..v11.0.0
|
git log --cherry-pick --pretty=oneline origin/10.0..v11.0.0
|
||||||
|
|
||||||
|
What's new?
|
||||||
|
------------
|
||||||
|
|
||||||
|
* Markdown editor with preview
|
||||||
|
([QTCREATORBUG-27883](https://bugreports.qt.io/browse/QTCREATORBUG-27883))
|
||||||
|
* Internal terminal
|
||||||
|
([QTCREATORBUG-8511](https://bugreports.qt.io/browse/QTCREATORBUG-8511))
|
||||||
|
* Experimental support for GitHub Copilot
|
||||||
|
* Experimental support for the `vcpkg` C/C++ package manager
|
||||||
|
* Experimental support for the Axivion static analyzer
|
||||||
|
|
||||||
|
### Markdown
|
||||||
|
|
||||||
|
You can open markdown (.md) files for editing or select `File > New File >
|
||||||
|
General > Markdown File` to create a new file.
|
||||||
|
|
||||||
|
([Documentation](https://doc-snapshots.qt.io/qtcreator-11.0/creator-markdown-editor.html))
|
||||||
|
|
||||||
|
### Terminal
|
||||||
|
|
||||||
|
When you select the `Run in Terminal` check box and run an application or the
|
||||||
|
`Open Terminal` button to open a terminal, the default terminal opens in the
|
||||||
|
`Terminal` output view. It supports multiple tabs, as well as various
|
||||||
|
shells, colors, and fonts.
|
||||||
|
|
||||||
|
To use an external terminal, deselect the `Use internal terminal` check box in
|
||||||
|
`Preferences > Terminal`.
|
||||||
|
|
||||||
|
([Documentation](https://doc-snapshots.qt.io/qtcreator-11.0/creator-output-panes.html#terminal))
|
||||||
|
|
||||||
|
### Copilot
|
||||||
|
|
||||||
|
The experimental Copilot plugin integrates
|
||||||
|
[GitHub Copilot](https://github.com/features/copilot), which uses OpenAI to
|
||||||
|
suggest code in the `Edit` mode.
|
||||||
|
|
||||||
|
To set Copilot preferences, select `Preferences > Copilot`.
|
||||||
|
|
||||||
|
([Documentation](https://doc-snapshots.qt.io/qtcreator-11.0/creator-copilot.html))
|
||||||
|
|
||||||
|
### vcpkg
|
||||||
|
|
||||||
|
The experimental vcpkg plugin integrates the [vcpgk](https://vcpkg.io)
|
||||||
|
package manager for downloading and managing libraries.
|
||||||
|
|
||||||
|
Select the `vcpkg` installation location in `Preferences > CMake > Vcpkg > Path`.
|
||||||
|
|
||||||
|
To create a new `vcpkg.json` package manifest file, select `File > New File >
|
||||||
|
vcpkg`. The file is automatically added to the CMakeLists.txt file for the
|
||||||
|
project.
|
||||||
|
|
||||||
|
Edit manifest files in the manifest editor. To search for packages to add to the
|
||||||
|
file, select the `Search Package` button on the manifest editor toolbar.
|
||||||
|
|
||||||
|
([Documentation](https://doc-snapshots.qt.io/qtcreator-11.0/creator-vcpkg.html))
|
||||||
|
|
||||||
|
### Axivion
|
||||||
|
|
||||||
|
After you configure access to the [Axivion](https://www.axivion.com) Dashboard
|
||||||
|
and link a project to an Axivion project in the project settings, Qt Creator
|
||||||
|
shows annotations of the latest run in the editors and allows you to view some
|
||||||
|
details on the issues.
|
||||||
|
|
||||||
|
([Documentation](https://doc-snapshots.qt.io/qtcreator-11.0/creator-axivion.html))
|
||||||
|
|
||||||
General
|
General
|
||||||
-------
|
-------
|
||||||
|
|
||||||
* Added a `Terminal` view (QTCREATORBUG-8511)
|
* Added a more spacious `Relaxed` toolbar style to `Preferences > Environment >
|
||||||
([Documentation](https://doc-snapshots.qt.io/qtcreator-11.0/creator-output-panes.html#terminal))
|
Interface`
|
||||||
* Opt-out via `Preferences` > `Terminal` preferences
|
|
||||||
* Added support for
|
|
||||||
* different shells, colors, fonts, and multiple tabs
|
|
||||||
* opening file paths in Qt Creator with `Ctrl+click` (`Cmd+click` on
|
|
||||||
macOS)
|
|
||||||
* Added a more spacious "relaxed" toolbar style `Environment > Interface`
|
|
||||||
* Added a pin button to progress details instead of automatically resetting
|
* Added a pin button to progress details instead of automatically resetting
|
||||||
their position (QTCREATORBUG-28829)
|
their position
|
||||||
|
([QTCREATORBUG-28829](https://bugreports.qt.io/browse/QTCREATORBUG-28829))
|
||||||
* Improved the selection and navigation in the `Issues` view
|
* Improved the selection and navigation in the `Issues` view
|
||||||
(QTCREATORBUG-26128, QTCREATORBUG-27006, QTCREATORBUG-27506)
|
([QTCREATORBUG-26128](https://bugreports.qt.io/browse/QTCREATORBUG-26128),
|
||||||
|
[QTCREATORBUG-27006](https://bugreports.qt.io/browse/QTCREATORBUG-27006),
|
||||||
|
[QTCREATORBUG-27506](https://bugreports.qt.io/browse/QTCREATORBUG-27506))
|
||||||
* Locator
|
* Locator
|
||||||
* Improved performance
|
* Improved performance
|
||||||
* Added the creation of directories to the `Files in File System` filter
|
* Added the creation of directories to the `Files in File System` filter
|
||||||
@@ -35,78 +97,79 @@ Editing
|
|||||||
-------
|
-------
|
||||||
|
|
||||||
* Improved the performance of the multi-cursor support
|
* Improved the performance of the multi-cursor support
|
||||||
* Fixed the saving of hardlinked files (QTCREATORBUG-19651)
|
* Fixed the saving of hardlinked files
|
||||||
* Fixed an issue of copy and paste with multiple cursors (QTCREATORBUG-29117)
|
([QTCREATORBUG-19651](https://bugreports.qt.io/browse/QTCREATORBUG-19651))
|
||||||
|
* Fixed an issue of copy and paste with multiple cursors
|
||||||
|
([QTCREATORBUG-29117](https://bugreports.qt.io/browse/QTCREATORBUG-29117))
|
||||||
|
|
||||||
### C++
|
### C++
|
||||||
|
|
||||||
* Improved the style of forward declarations in the outline (QTCREATORBUG-312)
|
* Improved the style of forward declarations in the outline
|
||||||
|
([QTCREATORBUG-312](https://bugreports.qt.io/browse/QTCREATORBUG-312))
|
||||||
* Added highlighting for typed string literals and user-defined literals
|
* Added highlighting for typed string literals and user-defined literals
|
||||||
(QTCREATORBUG-28869)
|
([QTCREATORBUG-28869](https://bugreports.qt.io/browse/QTCREATORBUG-28869))
|
||||||
* Added the option to create class members from assignments (QTCREATORBUG-1918)
|
* Added the option to create class members from assignments
|
||||||
|
([QTCREATORBUG-1918](https://bugreports.qt.io/browse/QTCREATORBUG-1918))
|
||||||
* Fixed that locator showed both the declaration and the definition of symbols
|
* Fixed that locator showed both the declaration and the definition of symbols
|
||||||
(QTCREATORBUG-13894)
|
([QTCREATORBUG-13894](https://bugreports.qt.io/browse/QTCREATORBUG-13894))
|
||||||
* Fixed the handling of C++20 keywords and concepts
|
* Fixed the handling of C++20 keywords and concepts
|
||||||
* Built-in
|
* Built-in
|
||||||
* Fixed support for `if`-statements with initializer (QTCREATORBUG-29182)
|
* Fixed support for `if`-statements with initializer
|
||||||
|
([QTCREATORBUG-29182](https://bugreports.qt.io/browse/QTCREATORBUG-29182))
|
||||||
|
|
||||||
### Language Server Protocol
|
### Language Server Protocol
|
||||||
|
|
||||||
* Added experimental support for GitHub Copilot
|
* Added missing actions for opening the `Call Hierarchy`
|
||||||
([GitHub documentation](https://github.com/features/copilot))
|
([QTCREATORBUG-28839](https://bugreports.qt.io/browse/QTCREATORBUG-28839),
|
||||||
([Qt Creator documentation](https://doc-snapshots.qt.io/qtcreator-11.0/creator-copilot.html))
|
[QTCREATORBUG-28842](https://bugreports.qt.io/browse/QTCREATORBUG-28842))
|
||||||
* Added missing actions for opening the `Call Hierarchy` (QTCREATORBUG-28839,
|
|
||||||
QTCREATORBUG-28842)
|
|
||||||
|
|
||||||
### QML
|
### QML
|
||||||
|
|
||||||
* Fixed the reformatting in the presence of JavaScript directives and function
|
* Fixed the reformatting in the presence of JavaScript directives and function
|
||||||
return type annotations (QTCREATORBUG-29001, QTCREATORBUG-29046)
|
return type annotations
|
||||||
* Fixed that reformatting changed `of` to `in` (QTCREATORBUG-29123)
|
([QTCREATORBUG-29001](https://bugreports.qt.io/browse/QTCREATORBUG-29001),
|
||||||
* Fixed the completion for Qt Quick Controls (QTCREATORBUG-28648)
|
[QTCREATORBUG-29046](https://bugreports.qt.io/browse/QTCREATORBUG-29046))
|
||||||
|
* Fixed that reformatting changed `of` to `in`
|
||||||
|
([QTCREATORBUG-29123](https://bugreports.qt.io/browse/QTCREATORBUG-29123))
|
||||||
|
* Fixed the completion for Qt Quick Controls
|
||||||
|
([QTCREATORBUG-28648](https://bugreports.qt.io/browse/QTCREATORBUG-28648))
|
||||||
|
|
||||||
### Python
|
### Python
|
||||||
|
|
||||||
* Added the option to create a virtual environment (`venv`) to the Python
|
* Added the option to create a virtual environment (`venv`) to the Python
|
||||||
interpreter selector and the wizard (PYSIDE-2152)
|
interpreter selector and the wizard
|
||||||
|
([PYSIDE-2152](https://bugreports.qt.io/browse/PYSIDE-2152))
|
||||||
### Markdown
|
|
||||||
|
|
||||||
* Added a Markdown editor with preview (QTCREATORBUG-27883)
|
|
||||||
* Added a wizard for Markdown files (QTCREATORBUG-29056)
|
|
||||||
|
|
||||||
Projects
|
Projects
|
||||||
--------
|
--------
|
||||||
|
|
||||||
* Made it possible to add devices without going through the wizard
|
* Made it possible to add devices without going through the wizard
|
||||||
* Added support for moving files to a different directory when renaming
|
* Added support for moving files to a different directory when renaming
|
||||||
(QTCREATORBUG-15981)
|
([QTCREATORBUG-15981](https://bugreports.qt.io/browse/QTCREATORBUG-15981))
|
||||||
|
|
||||||
### CMake
|
### CMake
|
||||||
|
|
||||||
* Implemented adding files to the project (QTCREATORBUG-25922,
|
* Implemented adding files to the project
|
||||||
QTCREATORBUG-26006, QTCREATORBUG-27213, QTCREATORBUG-27538,
|
([QTCREATORBUG-25922](https://bugreports.qt.io/browse/QTCREATORBUG-25922),
|
||||||
QTCREATORBUG-28493, QTCREATORBUG-28904, QTCREATORBUG-28985,
|
[QTCREATORBUG-26006](https://bugreports.qt.io/browse/QTCREATORBUG-26006),
|
||||||
QTCREATORBUG-29006)
|
[QTCREATORBUG-27213](https://bugreports.qt.io/browse/QTCREATORBUG-27213),
|
||||||
|
[QTCREATORBUG-27538](https://bugreports.qt.io/browse/QTCREATORBUG-27538),
|
||||||
|
[QTCREATORBUG-28493](https://bugreports.qt.io/browse/QTCREATORBUG-28493),
|
||||||
|
[QTCREATORBUG-28904](https://bugreports.qt.io/browse/QTCREATORBUG-28904),
|
||||||
|
[QTCREATORBUG-28985](https://bugreports.qt.io/browse/QTCREATORBUG-28985),
|
||||||
|
[QTCREATORBUG-29006](https://bugreports.qt.io/browse/QTCREATORBUG-29006))
|
||||||
* Fixed issues with detecting a configured Qt version when importing a build
|
* Fixed issues with detecting a configured Qt version when importing a build
|
||||||
(QTCREATORBUG-29075)
|
([QTCREATORBUG-29075](https://bugreports.qt.io/browse/QTCREATORBUG-29075))
|
||||||
|
|
||||||
### Python
|
### Python
|
||||||
|
|
||||||
* Added an option for the interpreter to the wizards
|
* Added an option for the interpreter to the wizards
|
||||||
|
|
||||||
### vcpkg
|
|
||||||
|
|
||||||
* Added experimental support for `vcpkg`
|
|
||||||
([vcpgk documentation](https://vcpkg.io/en/))
|
|
||||||
* Added an option for the `vcpkg` installation location
|
|
||||||
* Added a search dialog for packages
|
|
||||||
* Added a wizard and an editor for `vcpkg.json` files
|
|
||||||
|
|
||||||
Debugging
|
Debugging
|
||||||
---------
|
---------
|
||||||
|
|
||||||
* Improved the UI for enabling and disabling debuggers (QTCREATORBUG-28627)
|
* Improved the UI for enabling and disabling debuggers
|
||||||
|
([QTCREATORBUG-28627](https://bugreports.qt.io/browse/QTCREATORBUG-28627))
|
||||||
|
|
||||||
### C++
|
### C++
|
||||||
|
|
||||||
@@ -114,16 +177,20 @@ Debugging
|
|||||||
(`Preferences > Debugger > Locals & Expressions > Default array size`)
|
(`Preferences > Debugger > Locals & Expressions > Default array size`)
|
||||||
* CDB
|
* CDB
|
||||||
* Added automatic source file mapping for Qt packages
|
* Added automatic source file mapping for Qt packages
|
||||||
* Fixed the variables view on remote Windows devices (QTCREATORBUG-29000)
|
* Fixed the variables view on remote Windows devices
|
||||||
|
([QTCREATORBUG-29000](https://bugreports.qt.io/browse/QTCREATORBUG-29000))
|
||||||
* LLDB
|
* LLDB
|
||||||
* Fixed that long lines in the application output were broken into multiple
|
* Fixed that long lines in the application output were broken into multiple
|
||||||
lines (QTCREATORBUG-29098)
|
lines
|
||||||
|
([QTCREATORBUG-29098](https://bugreports.qt.io/browse/QTCREATORBUG-29098))
|
||||||
|
|
||||||
### Qt Quick
|
### Qt Quick
|
||||||
|
|
||||||
* Improved the auto-detection if QML debugging is required (QTCREATORBUG-28627)
|
* Improved the auto-detection if QML debugging is required
|
||||||
|
([QTCREATORBUG-28627](https://bugreports.qt.io/browse/QTCREATORBUG-28627))
|
||||||
* Added an option for disabling static analyzer messages to
|
* Added an option for disabling static analyzer messages to
|
||||||
`Qt Quick > QML/JS Editing` (QTCREATORBUG-29095)
|
`Qt Quick > QML/JS Editing`
|
||||||
|
([QTCREATORBUG-29095](https://bugreports.qt.io/browse/QTCREATORBUG-29095))
|
||||||
|
|
||||||
Analyzer
|
Analyzer
|
||||||
--------
|
--------
|
||||||
@@ -131,11 +198,8 @@ Analyzer
|
|||||||
### Clang
|
### Clang
|
||||||
|
|
||||||
* Fixed that a `.clang-tidy` file in the project directory was not used by
|
* Fixed that a `.clang-tidy` file in the project directory was not used by
|
||||||
default (QTCREATORBUG-28852)
|
default
|
||||||
|
([QTCREATORBUG-28852](https://bugreports.qt.io/browse/QTCREATORBUG-28852))
|
||||||
### Axivion
|
|
||||||
|
|
||||||
* Added experimental support
|
|
||||||
|
|
||||||
Version Control Systems
|
Version Control Systems
|
||||||
-----------------------
|
-----------------------
|
||||||
@@ -143,7 +207,8 @@ Version Control Systems
|
|||||||
### Git
|
### Git
|
||||||
|
|
||||||
* Instant Blame
|
* Instant Blame
|
||||||
* Improved the performance (QTCREATORBUG-29151)
|
* Improved the performance
|
||||||
|
([QTCREATORBUG-29151](https://bugreports.qt.io/browse/QTCREATORBUG-29151))
|
||||||
* Fixed that it did not show at the end of the document
|
* Fixed that it did not show at the end of the document
|
||||||
|
|
||||||
Platforms
|
Platforms
|
||||||
@@ -151,7 +216,8 @@ Platforms
|
|||||||
|
|
||||||
### Android
|
### Android
|
||||||
|
|
||||||
* Fixed an issue with building library targets (QTCREATORBUG-26980)
|
* Fixed an issue with building library targets
|
||||||
|
([QTCREATORBUG-26980](https://bugreports.qt.io/browse/QTCREATORBUG-26980))
|
||||||
|
|
||||||
### Remote Linux
|
### Remote Linux
|
||||||
|
|
||||||
@@ -159,14 +225,16 @@ Platforms
|
|||||||
|
|
||||||
### Docker
|
### Docker
|
||||||
|
|
||||||
* Added support for `qmake` based projects (QTCREATORBUG-29140)
|
* Added support for `qmake` based projects
|
||||||
|
([QTCREATORBUG-29140](https://bugreports.qt.io/browse/QTCREATORBUG-29140))
|
||||||
* Fixed issues after deleting the Docker image for a registered Docker device
|
* Fixed issues after deleting the Docker image for a registered Docker device
|
||||||
(QTCREATORBUG-28880)
|
([QTCREATORBUG-28880](https://bugreports.qt.io/browse/QTCREATORBUG-28880))
|
||||||
|
|
||||||
### QNX
|
### QNX
|
||||||
|
|
||||||
* Added `slog2info` as a requirement for devices
|
* Added `slog2info` as a requirement for devices
|
||||||
* Fixed the support for remote working directories (QTCREATORBUG-28900)
|
* Fixed the support for remote working directories
|
||||||
|
([QTCREATORBUG-28900](https://bugreports.qt.io/browse/QTCREATORBUG-28900))
|
||||||
|
|
||||||
Credits for these changes go to:
|
Credits for these changes go to:
|
||||||
--------------------------------
|
--------------------------------
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 21 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 13 KiB |
@@ -33,9 +33,15 @@
|
|||||||
|
|
||||||
\section1 Adding Boot2Qt Devices
|
\section1 Adding Boot2Qt Devices
|
||||||
|
|
||||||
If \QC does not automatically detect a device you connected with USB, you can
|
If \QC does not automatically detect a device you connected with USB, select
|
||||||
use a wizard to create either a network connection or a USB connection to
|
\uicontrol Edit > \uicontrol Preferences > \uicontrol Devices >
|
||||||
it.
|
\uicontrol Devices > \uicontrol Add > \uicontrol {Boot2Qt Device} to create
|
||||||
|
either a network connection or a USB connection to it.
|
||||||
|
|
||||||
|
\image qtcreator-boot2qt-device-configurations.webp {Devices tab in Preferences}
|
||||||
|
|
||||||
|
To add a device without using a wizard, select \uicontrol {Boot2Qt Device} in
|
||||||
|
the pull-down menu of the \uicontrol Add button.
|
||||||
|
|
||||||
\note On Ubuntu Linux, the development user account must have access to the
|
\note On Ubuntu Linux, the development user account must have access to the
|
||||||
plugged-in devices. To grant them access to the device via USB, create a new
|
plugged-in devices. To grant them access to the device via USB, create a new
|
||||||
@@ -46,8 +52,6 @@
|
|||||||
You can edit the settings later in \uicontrol Edit > \uicontrol Preferences >
|
You can edit the settings later in \uicontrol Edit > \uicontrol Preferences >
|
||||||
\uicontrol Devices > \uicontrol Devices.
|
\uicontrol Devices > \uicontrol Devices.
|
||||||
|
|
||||||
\image qtcreator-boot2qt-device-configurations.png {Devices dialog}
|
|
||||||
|
|
||||||
To reboot the selected device, select \uicontrol {Reboot Device}.
|
To reboot the selected device, select \uicontrol {Reboot Device}.
|
||||||
|
|
||||||
To restore the default application to the device, select
|
To restore the default application to the device, select
|
||||||
@@ -122,6 +126,10 @@
|
|||||||
parameters that have sensible default values. One of
|
parameters that have sensible default values. One of
|
||||||
these is the SSH port number, which is available in
|
these is the SSH port number, which is available in
|
||||||
the variable \c %{Device:SshPort}.
|
the variable \c %{Device:SshPort}.
|
||||||
|
|
||||||
|
To add a device without using the wizard, select
|
||||||
|
\uicontrol {Boot2Qt Device} in the pull-down menu of the
|
||||||
|
\uicontrol Add button.
|
||||||
\endlist
|
\endlist
|
||||||
\li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Kits >
|
\li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Kits >
|
||||||
\uicontrol Add to add a kit for building applications for the
|
\uicontrol Add to add a kit for building applications for the
|
||||||
|
|||||||
@@ -107,6 +107,9 @@
|
|||||||
All of these parameters can be edited later, as well as additional ones that the
|
All of these parameters can be edited later, as well as additional ones that the
|
||||||
wizard does not show because there are sensible default values.
|
wizard does not show because there are sensible default values.
|
||||||
|
|
||||||
|
To add a device without using the wizard, select
|
||||||
|
\uicontrol {Add Remote Linux Device} in the pull-down
|
||||||
|
menu of the \uicontrol Add button.
|
||||||
|
|
||||||
\li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Kits >
|
\li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Kits >
|
||||||
\uicontrol Add to add a kit for building for the device. Select the
|
\uicontrol Add to add a kit for building for the device. Select the
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
{
|
{
|
||||||
"files": ["%{SrcFileName}"]
|
"files": [
|
||||||
|
"%{SrcFileName}"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
{
|
{
|
||||||
"files": ["%{SrcFileName}", "%{QmlFileName}"]
|
"files": [
|
||||||
|
"%{SrcFileName}",
|
||||||
|
"%{QmlFileName}"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
{
|
{
|
||||||
"files": ["%{SrcFileName}", "form.ui"]
|
"files": [
|
||||||
|
"%{SrcFileName}",
|
||||||
|
"form.ui"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -252,7 +252,7 @@ private:
|
|||||||
|
|
||||||
The GroupSetupHandler is used when constructing the onGroupSetup element.
|
The GroupSetupHandler is used when constructing the onGroupSetup element.
|
||||||
Any function with the above signature, when passed as a group setup handler,
|
Any function with the above signature, when passed as a group setup handler,
|
||||||
will be called by the running task tree when the group executions starts.
|
will be called by the running task tree when the group execution starts.
|
||||||
|
|
||||||
The return value of the handler instructs the running group on how to proceed
|
The return value of the handler instructs the running group on how to proceed
|
||||||
after the handler's invocation is finished. The default return value of TaskAction::Continue
|
after the handler's invocation is finished. The default return value of TaskAction::Continue
|
||||||
@@ -1123,7 +1123,7 @@ void TaskNode::invokeEndHandler(bool success)
|
|||||||
|
|
||||||
Use the Tasking namespace to build extensible, declarative task tree
|
Use the Tasking namespace to build extensible, declarative task tree
|
||||||
structures that contain possibly asynchronous tasks, such as Process,
|
structures that contain possibly asynchronous tasks, such as Process,
|
||||||
FileTransfer, or Async<ReturnType>. TaskTree structures enable you
|
FileTransfer, or ConcurrentCall<ReturnType>. TaskTree structures enable you
|
||||||
to create a sophisticated mixture of a parallel or sequential flow of tasks
|
to create a sophisticated mixture of a parallel or sequential flow of tasks
|
||||||
in the form of a tree and to run it any time later.
|
in the form of a tree and to run it any time later.
|
||||||
|
|
||||||
@@ -1131,14 +1131,14 @@ void TaskNode::invokeEndHandler(bool success)
|
|||||||
|
|
||||||
The TaskTree has a mandatory Group root element, which may contain
|
The TaskTree has a mandatory Group root element, which may contain
|
||||||
any number of tasks of various types, such as ProcessTask, FileTransferTask,
|
any number of tasks of various types, such as ProcessTask, FileTransferTask,
|
||||||
or AsyncTask<ReturnType>:
|
or ConcurrentCallTask<ReturnType>:
|
||||||
|
|
||||||
\code
|
\code
|
||||||
using namespace Tasking;
|
using namespace Tasking;
|
||||||
|
|
||||||
const Group root {
|
const Group root {
|
||||||
ProcessTask(...),
|
ProcessTask(...),
|
||||||
AsyncTask<int>(...),
|
ConcurrentCallTask<int>(...),
|
||||||
FileTransferTask(...)
|
FileTransferTask(...)
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1149,10 +1149,10 @@ void TaskNode::invokeEndHandler(bool success)
|
|||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
The task tree above has a top level element of the Group type that contains
|
The task tree above has a top level element of the Group type that contains
|
||||||
tasks of the type ProcessTask, FileTransferTask, and AsyncTask<int>.
|
tasks of the type ProcessTask, FileTransferTask, and ConcurrentCallTask<int>.
|
||||||
After taskTree->start() is called, the tasks are run in a chain, starting
|
After taskTree->start() is called, the tasks are run in a chain, starting
|
||||||
with ProcessTask. When the ProcessTask finishes successfully, the AsyncTask<int> task is
|
with ProcessTask. When the ProcessTask finishes successfully, the ConcurrentCallTask<int>
|
||||||
started. Finally, when the asynchronous task finishes successfully, the
|
task is started. Finally, when the asynchronous task finishes successfully, the
|
||||||
FileTransferTask task is started.
|
FileTransferTask task is started.
|
||||||
|
|
||||||
When the last running task finishes with success, the task tree is considered
|
When the last running task finishes with success, the task tree is considered
|
||||||
@@ -1172,26 +1172,26 @@ void TaskNode::invokeEndHandler(bool success)
|
|||||||
Group {
|
Group {
|
||||||
parallel,
|
parallel,
|
||||||
ProcessTask(...),
|
ProcessTask(...),
|
||||||
AsyncTask<int>(...)
|
ConcurrentCallTask<int>(...)
|
||||||
},
|
},
|
||||||
FileTransferTask(...)
|
FileTransferTask(...)
|
||||||
};
|
};
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
The example above differs from the first example in that the root element has
|
The example above differs from the first example in that the root element has
|
||||||
a subgroup that contains the ProcessTask and AsyncTask<int>. The subgroup is a
|
a subgroup that contains the ProcessTask and ConcurrentCallTask<int>. The subgroup is a
|
||||||
sibling element of the FileTransferTask in the root. The subgroup contains an
|
sibling element of the FileTransferTask in the root. The subgroup contains an
|
||||||
additional \e parallel element that instructs its Group to execute its tasks
|
additional \e parallel element that instructs its Group to execute its tasks
|
||||||
in parallel.
|
in parallel.
|
||||||
|
|
||||||
So, when the tree above is started, the ProcessTask and AsyncTask<int> start
|
So, when the tree above is started, the ProcessTask and ConcurrentCallTask<int> start
|
||||||
immediately and run in parallel. Since the root group doesn't contain a
|
immediately and run in parallel. Since the root group doesn't contain a
|
||||||
\e parallel element, its direct child tasks are run in sequence. Thus, the
|
\e parallel element, its direct child tasks are run in sequence. Thus, the
|
||||||
FileTransferTask starts when the whole subgroup finishes. The group is
|
FileTransferTask starts when the whole subgroup finishes. The group is
|
||||||
considered as finished when all its tasks have finished. The order in which
|
considered as finished when all its tasks have finished. The order in which
|
||||||
the tasks finish is not relevant.
|
the tasks finish is not relevant.
|
||||||
|
|
||||||
So, depending on which task lasts longer (ProcessTask or AsyncTask<int>), the
|
So, depending on which task lasts longer (ProcessTask or ConcurrentCallTask<int>), the
|
||||||
following scenarios can take place:
|
following scenarios can take place:
|
||||||
|
|
||||||
\table
|
\table
|
||||||
@@ -1208,19 +1208,19 @@ void TaskNode::invokeEndHandler(bool success)
|
|||||||
\li ProcessTask starts
|
\li ProcessTask starts
|
||||||
\li ProcessTask starts
|
\li ProcessTask starts
|
||||||
\row
|
\row
|
||||||
\li AsyncTask<int> starts
|
\li ConcurrentCallTask<int> starts
|
||||||
\li AsyncTask<int> starts
|
\li ConcurrentCallTask<int> starts
|
||||||
\row
|
\row
|
||||||
\li ...
|
\li ...
|
||||||
\li ...
|
\li ...
|
||||||
\row
|
\row
|
||||||
\li \b {ProcessTask finishes}
|
\li \b {ProcessTask finishes}
|
||||||
\li \b {AsyncTask<int> finishes}
|
\li \b {ConcurrentCallTask<int> finishes}
|
||||||
\row
|
\row
|
||||||
\li ...
|
\li ...
|
||||||
\li ...
|
\li ...
|
||||||
\row
|
\row
|
||||||
\li \b {AsyncTask<int> finishes}
|
\li \b {ConcurrentCallTask<int> finishes}
|
||||||
\li \b {ProcessTask finishes}
|
\li \b {ProcessTask finishes}
|
||||||
\row
|
\row
|
||||||
\li Sub Group finishes
|
\li Sub Group finishes
|
||||||
@@ -1246,8 +1246,8 @@ void TaskNode::invokeEndHandler(bool success)
|
|||||||
|
|
||||||
The presented scenarios assume that all tasks run successfully. If a task
|
The presented scenarios assume that all tasks run successfully. If a task
|
||||||
fails during execution, the task tree finishes with an error. In particular,
|
fails during execution, the task tree finishes with an error. In particular,
|
||||||
when ProcessTask finishes with an error while AsyncTask<int> is still being executed,
|
when ProcessTask finishes with an error while ConcurrentCallTask<int> is still being executed,
|
||||||
the AsyncTask<int> is automatically stopped, the subgroup finishes with an error,
|
the ConcurrentCallTask<int> is automatically stopped, the subgroup finishes with an error,
|
||||||
the FileTransferTask is skipped, and the tree finishes with an error.
|
the FileTransferTask is skipped, and the tree finishes with an error.
|
||||||
|
|
||||||
\section1 Task Types
|
\section1 Task Types
|
||||||
@@ -1277,11 +1277,11 @@ void TaskNode::invokeEndHandler(bool success)
|
|||||||
\row
|
\row
|
||||||
\li ProcessTask
|
\li ProcessTask
|
||||||
\li Utils::Process
|
\li Utils::Process
|
||||||
\li Starts processes.
|
\li Starts process.
|
||||||
\row
|
\row
|
||||||
\li AsyncTask<ReturnType>
|
\li ConcurrentCallTask<ReturnType>
|
||||||
\li Utils::Async<ReturnType>
|
\li Tasking::ConcurrentCall<ReturnType>
|
||||||
\li Starts asynchronous tasks; run in separate thread.
|
\li Starts asynchronous task, runs in separate thread.
|
||||||
\row
|
\row
|
||||||
\li TaskTreeTask
|
\li TaskTreeTask
|
||||||
\li Utils::TaskTree
|
\li Utils::TaskTree
|
||||||
@@ -1540,7 +1540,7 @@ void TaskNode::invokeEndHandler(bool success)
|
|||||||
static QByteArray load(const QString &fileName) { ... }
|
static QByteArray load(const QString &fileName) { ... }
|
||||||
static void save(const QString &fileName, const QByteArray &array) { ... }
|
static void save(const QString &fileName, const QByteArray &array) { ... }
|
||||||
|
|
||||||
static GroupItem copyRecipe(const QString &source, const QString &destination)
|
static Group copyRecipe(const QString &source, const QString &destination)
|
||||||
{
|
{
|
||||||
struct CopyStorage { // [1] custom inter-task struct
|
struct CopyStorage { // [1] custom inter-task struct
|
||||||
QByteArray content; // [2] custom inter-task data
|
QByteArray content; // [2] custom inter-task data
|
||||||
@@ -1549,28 +1549,28 @@ void TaskNode::invokeEndHandler(bool success)
|
|||||||
// [3] instance of custom inter-task struct manageable by task tree
|
// [3] instance of custom inter-task struct manageable by task tree
|
||||||
const TreeStorage<CopyStorage> storage;
|
const TreeStorage<CopyStorage> storage;
|
||||||
|
|
||||||
const auto onLoaderSetup = [source](Async<QByteArray> &async) {
|
const auto onLoaderSetup = [source](ConcurrentCall<QByteArray> &async) {
|
||||||
async.setConcurrentCallData(&load, source);
|
async.setConcurrentCallData(&load, source);
|
||||||
};
|
};
|
||||||
// [4] runtime: task tree activates the instance from [7] before invoking handler
|
// [4] runtime: task tree activates the instance from [7] before invoking handler
|
||||||
const auto onLoaderDone = [storage](const Async<QByteArray> &async) {
|
const auto onLoaderDone = [storage](const ConcurrentCall<QByteArray> &async) {
|
||||||
storage->content = async.result(); // [5] loader stores the result in storage
|
storage->content = async.result(); // [5] loader stores the result in storage
|
||||||
};
|
};
|
||||||
|
|
||||||
// [4] runtime: task tree activates the instance from [7] before invoking handler
|
// [4] runtime: task tree activates the instance from [7] before invoking handler
|
||||||
const auto onSaverSetup = [storage, destination](Async<void> &async) {
|
const auto onSaverSetup = [storage, destination](ConcurrentCall<void> &async) {
|
||||||
const QByteArray content = storage->content; // [6] saver takes data from storage
|
const QByteArray content = storage->content; // [6] saver takes data from storage
|
||||||
async.setConcurrentCallData(&save, destination, content);
|
async.setConcurrentCallData(&save, destination, content);
|
||||||
};
|
};
|
||||||
const auto onSaverDone = [](const Async<void> &async) {
|
const auto onSaverDone = [](const ConcurrentCall<void> &async) {
|
||||||
qDebug() << "Save done successfully";
|
qDebug() << "Save done successfully";
|
||||||
};
|
};
|
||||||
|
|
||||||
const Group root {
|
const Group root {
|
||||||
// [7] runtime: task tree creates an instance of CopyStorage when root is entered
|
// [7] runtime: task tree creates an instance of CopyStorage when root is entered
|
||||||
Storage(storage),
|
Storage(storage),
|
||||||
AsyncTask<QByteArray>(onLoaderSetup, onLoaderDone),
|
ConcurrentCallTask<QByteArray>(onLoaderSetup, onLoaderDone),
|
||||||
AsyncTask<void>(onSaverSetup, onSaverDone)
|
ConcurrentCallTask<void>(onSaverSetup, onSaverDone)
|
||||||
};
|
};
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
@@ -1650,7 +1650,7 @@ void TaskNode::invokeEndHandler(bool success)
|
|||||||
|
|
||||||
\code
|
\code
|
||||||
TreeStorage<CopyStorage> storage;
|
TreeStorage<CopyStorage> storage;
|
||||||
Group root = ...; // storage placed inside root's group and inside handlers
|
const Group root = ...; // storage placed inside root's group and inside handlers
|
||||||
TaskTree taskTree(root);
|
TaskTree taskTree(root);
|
||||||
auto initStorage = [](CopyStorage *storage){
|
auto initStorage = [](CopyStorage *storage){
|
||||||
storage->content = "initial content";
|
storage->content = "initial content";
|
||||||
@@ -1670,7 +1670,7 @@ void TaskNode::invokeEndHandler(bool success)
|
|||||||
|
|
||||||
\code
|
\code
|
||||||
TreeStorage<CopyStorage> storage;
|
TreeStorage<CopyStorage> storage;
|
||||||
Group root = ...; // storage placed inside root's group and inside handlers
|
const Group root = ...; // storage placed inside root's group and inside handlers
|
||||||
TaskTree taskTree(root);
|
TaskTree taskTree(root);
|
||||||
auto collectStorage = [](CopyStorage *storage){
|
auto collectStorage = [](CopyStorage *storage){
|
||||||
qDebug() << "final content" << storage->content;
|
qDebug() << "final content" << storage->content;
|
||||||
@@ -1758,7 +1758,7 @@ TaskTree::TaskTree(const Group &recipe) : TaskTree()
|
|||||||
TaskTree::~TaskTree()
|
TaskTree::~TaskTree()
|
||||||
{
|
{
|
||||||
QTC_ASSERT(!d->m_guard.isLocked(), qWarning("Deleting TaskTree instance directly from "
|
QTC_ASSERT(!d->m_guard.isLocked(), qWarning("Deleting TaskTree instance directly from "
|
||||||
"one of its handlers will lead to crash!"));
|
"one of its handlers will lead to a crash!"));
|
||||||
// TODO: delete storages explicitly here?
|
// TODO: delete storages explicitly here?
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2346,16 +2346,12 @@ void IntegersAspect::setDefaultValue(const QList<int> &value)
|
|||||||
A text display does not have a real value.
|
A text display does not have a real value.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TextDisplay::TextDisplay(AspectContainer *container)
|
|
||||||
: BaseAspect(container), d(new Internal::TextDisplayPrivate)
|
|
||||||
{}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Constructs a text display showing the \a message with an icon representing
|
Constructs a text display showing the \a message with an icon representing
|
||||||
type \a type.
|
type \a type.
|
||||||
*/
|
*/
|
||||||
TextDisplay::TextDisplay(const QString &message, InfoLabel::InfoType type)
|
TextDisplay::TextDisplay(AspectContainer *container, const QString &message, InfoLabel::InfoType type)
|
||||||
: d(new Internal::TextDisplayPrivate)
|
: BaseAspect(container), d(new Internal::TextDisplayPrivate)
|
||||||
{
|
{
|
||||||
d->m_message = message;
|
d->m_message = message;
|
||||||
d->m_type = type;
|
d->m_type = type;
|
||||||
|
|||||||
@@ -610,9 +610,9 @@ class QTCREATOR_UTILS_EXPORT TextDisplay : public BaseAspect
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit TextDisplay(AspectContainer *container);
|
explicit TextDisplay(AspectContainer *container,
|
||||||
TextDisplay(const QString &message = {},
|
const QString &message = {},
|
||||||
InfoLabel::InfoType type = InfoLabel::None);
|
InfoLabel::InfoType type = InfoLabel::None);
|
||||||
~TextDisplay() override;
|
~TextDisplay() override;
|
||||||
|
|
||||||
void addToLayout(Layouting::LayoutItem &parent) override;
|
void addToLayout(Layouting::LayoutItem &parent) override;
|
||||||
|
|||||||
@@ -545,11 +545,11 @@ IconButton::IconButton(QWidget *parent)
|
|||||||
|
|
||||||
void IconButton::paintEvent(QPaintEvent *)
|
void IconButton::paintEvent(QPaintEvent *)
|
||||||
{
|
{
|
||||||
QWindow *window = this->window()->windowHandle();
|
const qreal pixelRatio = window()->windowHandle()->devicePixelRatio();
|
||||||
const QPixmap iconPixmap = icon().pixmap(window, sizeHint(),
|
const QPixmap iconPixmap = icon().pixmap(sizeHint(), pixelRatio,
|
||||||
isEnabled() ? QIcon::Normal : QIcon::Disabled);
|
isEnabled() ? QIcon::Normal : QIcon::Disabled);
|
||||||
QStylePainter painter(this);
|
QStylePainter painter(this);
|
||||||
QRect pixmapRect(QPoint(), iconPixmap.size() / window->devicePixelRatio());
|
QRect pixmapRect(QPoint(), iconPixmap.size() / pixelRatio);
|
||||||
pixmapRect.moveCenter(rect().center());
|
pixmapRect.moveCenter(rect().center());
|
||||||
|
|
||||||
if (m_autoHide)
|
if (m_autoHide)
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ QString JsonValue::kindToString(JsonValue::Kind kind)
|
|||||||
|
|
||||||
JsonValue *JsonValue::build(const QVariant &variant, JsonMemoryPool *pool)
|
JsonValue *JsonValue::build(const QVariant &variant, JsonMemoryPool *pool)
|
||||||
{
|
{
|
||||||
switch (variant.type()) {
|
switch (variant.typeId()) {
|
||||||
|
|
||||||
case QVariant::List: {
|
case QVariant::List: {
|
||||||
auto newValue = new (pool) JsonArrayValue;
|
auto newValue = new (pool) JsonArrayValue;
|
||||||
|
|||||||
@@ -216,6 +216,13 @@ void DefaultImpl::start()
|
|||||||
return;
|
return;
|
||||||
if (!ensureProgramExists(program))
|
if (!ensureProgramExists(program))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (m_setup.m_runAsRoot && !HostOsInfo::isWindowsHost()) {
|
||||||
|
arguments.prepend(program);
|
||||||
|
arguments.prepend("-A");
|
||||||
|
program = "sudo";
|
||||||
|
}
|
||||||
|
|
||||||
s_start.measureAndRun(&DefaultImpl::doDefaultStart, this, program, arguments);
|
s_start.measureAndRun(&DefaultImpl::doDefaultStart, this, program, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -766,15 +773,6 @@ public:
|
|||||||
m_blockingInterface->setParent(this);
|
m_blockingInterface->setParent(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandLine fullCommandLine() const
|
|
||||||
{
|
|
||||||
if (!m_setup.m_runAsRoot || HostOsInfo::isWindowsHost())
|
|
||||||
return m_setup.m_commandLine;
|
|
||||||
CommandLine rootCommand("sudo", {"-A"});
|
|
||||||
rootCommand.addCommandLineAsArgs(m_setup.m_commandLine);
|
|
||||||
return rootCommand;
|
|
||||||
}
|
|
||||||
|
|
||||||
Process *q;
|
Process *q;
|
||||||
std::unique_ptr<ProcessBlockingInterface> m_blockingInterface;
|
std::unique_ptr<ProcessBlockingInterface> m_blockingInterface;
|
||||||
std::unique_ptr<ProcessInterface> m_process;
|
std::unique_ptr<ProcessInterface> m_process;
|
||||||
@@ -1217,7 +1215,6 @@ void Process::start()
|
|||||||
d->setProcessInterface(processImpl);
|
d->setProcessInterface(processImpl);
|
||||||
d->m_state = QProcess::Starting;
|
d->m_state = QProcess::Starting;
|
||||||
d->m_process->m_setup = d->m_setup;
|
d->m_process->m_setup = d->m_setup;
|
||||||
d->m_process->m_setup.m_commandLine = d->fullCommandLine();
|
|
||||||
d->emitGuardedSignal(&Process::starting);
|
d->emitGuardedSignal(&Process::starting);
|
||||||
d->m_process->start();
|
d->m_process->start();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,10 @@
|
|||||||
#include <QTime>
|
#include <QTime>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
class QPainter;
|
class QPainter;
|
||||||
class QStyleOption;
|
class QStyleOption;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
namespace Utils {
|
namespace Utils {
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -385,6 +385,22 @@ void TerminalInterface::start()
|
|||||||
ProcessSetupData stubSetupData = m_setup;
|
ProcessSetupData stubSetupData = m_setup;
|
||||||
stubSetupData.m_commandLine = cmd;
|
stubSetupData.m_commandLine = cmd;
|
||||||
|
|
||||||
|
if (m_setup.m_runAsRoot && !HostOsInfo::isWindowsHost()) {
|
||||||
|
CommandLine rootCommand(FilePath("sudo").searchInPath(), {"-A"});
|
||||||
|
rootCommand.addCommandLineAsArgs(cmd);
|
||||||
|
|
||||||
|
const FilePath askPassPath = FilePath::fromUserInput(QCoreApplication::applicationDirPath())
|
||||||
|
.pathAppended(QLatin1String(RELATIVE_LIBEXEC_PATH))
|
||||||
|
.pathAppended(QLatin1String("qtc-askpass"));
|
||||||
|
|
||||||
|
if (askPassPath.exists())
|
||||||
|
stubSetupData.m_environment.setFallback("SUDO_ASKPASS", askPassPath.toUserOutput());
|
||||||
|
|
||||||
|
stubSetupData.m_commandLine = rootCommand;
|
||||||
|
} else {
|
||||||
|
stubSetupData.m_commandLine = cmd;
|
||||||
|
}
|
||||||
|
|
||||||
QMetaObject::invokeMethod(
|
QMetaObject::invokeMethod(
|
||||||
d->stubCreator,
|
d->stubCreator,
|
||||||
[stubSetupData, this] { d->stubCreator->startStubProcess(stubSetupData); },
|
[stubSetupData, this] { d->stubCreator->startStubProcess(stubSetupData); },
|
||||||
|
|||||||
@@ -7,9 +7,12 @@
|
|||||||
|
|
||||||
#include <QScrollBar>
|
#include <QScrollBar>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
class QAbstractScrollArea;
|
class QAbstractScrollArea;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
namespace Utils {
|
namespace Utils {
|
||||||
|
|
||||||
class ScrollAreaPrivate;
|
class ScrollAreaPrivate;
|
||||||
class ScrollBarPrivate;
|
class ScrollBarPrivate;
|
||||||
|
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ void AndroidConfig::load(const QSettings &settings)
|
|||||||
{
|
{
|
||||||
// user settings
|
// user settings
|
||||||
QVariant emulatorArgs = settings.value(EmulatorArgsKey, QString("-netdelay none -netspeed full"));
|
QVariant emulatorArgs = settings.value(EmulatorArgsKey, QString("-netdelay none -netspeed full"));
|
||||||
if (emulatorArgs.type() == QVariant::StringList) // Changed in 8.0 from QStringList to QString.
|
if (emulatorArgs.typeId() == QVariant::StringList) // Changed in 8.0 from QStringList to QString.
|
||||||
emulatorArgs = ProcessArgs::joinArgs(emulatorArgs.toStringList());
|
emulatorArgs = ProcessArgs::joinArgs(emulatorArgs.toStringList());
|
||||||
m_emulatorArgs = emulatorArgs.toString();
|
m_emulatorArgs = emulatorArgs.toString();
|
||||||
m_sdkLocation = FilePath::fromUserInput(settings.value(SDKLocationKey).toString()).cleanPath();
|
m_sdkLocation = FilePath::fromUserInput(settings.value(SDKLocationKey).toString()).cleanPath();
|
||||||
|
|||||||
@@ -488,21 +488,40 @@ void AndroidManifestEditorWidget::focusInEvent(QFocusEvent *event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool checkDocument(const QDomDocument &doc, QDomDocument::ParseResult *result)
|
||||||
|
{
|
||||||
|
QDomElement manifest = doc.documentElement();
|
||||||
|
if (manifest.tagName() != QLatin1String("manifest")) {
|
||||||
|
result->errorMessage = ::Android::Tr::tr("The structure of the Android manifest file "
|
||||||
|
"is corrupted. Expected a top level 'manifest' node.");
|
||||||
|
result->errorLine = -1;
|
||||||
|
result->errorColumn = -1;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (manifest.firstChildElement(QLatin1String("application")).firstChildElement(QLatin1String("activity")).isNull()) {
|
||||||
|
// missing either application or activity element
|
||||||
|
result->errorMessage = ::Android::Tr::tr("The structure of the Android manifest file "
|
||||||
|
"is corrupted. Expected an 'application' and 'activity' sub node.");
|
||||||
|
result->errorLine = -1;
|
||||||
|
result->errorColumn = -1;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void AndroidManifestEditorWidget::updateAfterFileLoad()
|
void AndroidManifestEditorWidget::updateAfterFileLoad()
|
||||||
{
|
{
|
||||||
QString error;
|
|
||||||
int errorLine;
|
|
||||||
int errorColumn;
|
|
||||||
QDomDocument doc;
|
QDomDocument doc;
|
||||||
if (doc.setContent(m_textEditorWidget->toPlainText(), &error, &errorLine, &errorColumn)) {
|
QDomDocument::ParseResult result = doc.setContent(m_textEditorWidget->toPlainText());
|
||||||
if (checkDocument(doc, &error, &errorLine, &errorColumn)) {
|
if (result) {
|
||||||
|
if (checkDocument(doc, &result)) {
|
||||||
if (activePage() != Source)
|
if (activePage() != Source)
|
||||||
syncToWidgets(doc);
|
syncToWidgets(doc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// some error occurred
|
// some error occurred
|
||||||
updateInfoBar(error, errorLine, errorColumn);
|
updateInfoBar(result.errorMessage, result.errorLine, result.errorColumn);
|
||||||
setActivePage(Source);
|
setActivePage(Source);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -591,39 +610,19 @@ TextEditor::TextEditorWidget *AndroidManifestEditorWidget::textEditorWidget() co
|
|||||||
bool AndroidManifestEditorWidget::syncToWidgets()
|
bool AndroidManifestEditorWidget::syncToWidgets()
|
||||||
{
|
{
|
||||||
QDomDocument doc;
|
QDomDocument doc;
|
||||||
QString errorMessage;
|
QDomDocument::ParseResult result = doc.setContent(m_textEditorWidget->toPlainText());
|
||||||
int errorLine, errorColumn;
|
if (result) {
|
||||||
if (doc.setContent(m_textEditorWidget->toPlainText(), &errorMessage, &errorLine, &errorColumn)) {
|
if (checkDocument(doc, &result)) {
|
||||||
if (checkDocument(doc, &errorMessage, &errorLine, &errorColumn)) {
|
|
||||||
hideInfoBar();
|
hideInfoBar();
|
||||||
syncToWidgets(doc);
|
syncToWidgets(doc);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateInfoBar(errorMessage, errorLine, errorColumn);
|
updateInfoBar(result.errorMessage, result.errorLine, result.errorColumn);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AndroidManifestEditorWidget::checkDocument(const QDomDocument &doc, QString *errorMessage,
|
|
||||||
int *errorLine, int *errorColumn)
|
|
||||||
{
|
|
||||||
QDomElement manifest = doc.documentElement();
|
|
||||||
if (manifest.tagName() != QLatin1String("manifest")) {
|
|
||||||
*errorMessage = ::Android::Tr::tr("The structure of the Android manifest file is corrupted. Expected a top level 'manifest' node.");
|
|
||||||
*errorLine = -1;
|
|
||||||
*errorColumn = -1;
|
|
||||||
return false;
|
|
||||||
} else if (manifest.firstChildElement(QLatin1String("application")).firstChildElement(QLatin1String("activity")).isNull()) {
|
|
||||||
// missing either application or activity element
|
|
||||||
*errorMessage = ::Android::Tr::tr("The structure of the Android manifest file is corrupted. Expected an 'application' and 'activity' sub node.");
|
|
||||||
*errorLine = -1;
|
|
||||||
*errorColumn = -1;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AndroidManifestEditorWidget::startParseCheck()
|
void AndroidManifestEditorWidget::startParseCheck()
|
||||||
{
|
{
|
||||||
m_timerParseCheck.start();
|
m_timerParseCheck.start();
|
||||||
@@ -641,16 +640,15 @@ void AndroidManifestEditorWidget::updateInfoBar()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QDomDocument doc;
|
QDomDocument doc;
|
||||||
int errorLine, errorColumn;
|
QDomDocument::ParseResult result = doc.setContent(m_textEditorWidget->toPlainText());
|
||||||
QString errorMessage;
|
if (result) {
|
||||||
if (doc.setContent(m_textEditorWidget->toPlainText(), &errorMessage, &errorLine, &errorColumn)) {
|
if (checkDocument(doc, &result)) {
|
||||||
if (checkDocument(doc, &errorMessage, &errorLine, &errorColumn)) {
|
|
||||||
hideInfoBar();
|
hideInfoBar();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateInfoBar(errorMessage, errorLine, errorColumn);
|
updateInfoBar(result.errorMessage, result.errorLine, result.errorColumn);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidManifestEditorWidget::updateSdkVersions()
|
void AndroidManifestEditorWidget::updateSdkVersions()
|
||||||
@@ -888,9 +886,9 @@ void AndroidManifestEditorWidget::syncToEditor()
|
|||||||
m_dirty = false;
|
m_dirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
static QXmlStreamAttributes modifyXmlStreamAttributes(
|
||||||
QXmlStreamAttributes modifyXmlStreamAttributes(const QXmlStreamAttributes &input, const QStringList &keys,
|
const QXmlStreamAttributes &input, const QStringList &keys,
|
||||||
const QStringList &values, const QStringList &remove = QStringList())
|
const QStringList &values, const QStringList &remove = {})
|
||||||
{
|
{
|
||||||
Q_ASSERT(keys.size() == values.size());
|
Q_ASSERT(keys.size() == values.size());
|
||||||
QXmlStreamAttributes result;
|
QXmlStreamAttributes result;
|
||||||
@@ -903,8 +901,7 @@ QXmlStreamAttributes modifyXmlStreamAttributes(const QXmlStreamAttributes &input
|
|||||||
if (index == -1)
|
if (index == -1)
|
||||||
result.push_back(attribute);
|
result.push_back(attribute);
|
||||||
else
|
else
|
||||||
result.push_back(QXmlStreamAttribute(name,
|
result.push_back(QXmlStreamAttribute(name, values.at(index)));
|
||||||
values.at(index)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < keys.size(); ++i) {
|
for (int i = 0; i < keys.size(); ++i) {
|
||||||
@@ -913,7 +910,6 @@ QXmlStreamAttributes modifyXmlStreamAttributes(const QXmlStreamAttributes &input
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
} // end namespace
|
|
||||||
|
|
||||||
void AndroidManifestEditorWidget::parseManifest(QXmlStreamReader &reader, QXmlStreamWriter &writer)
|
void AndroidManifestEditorWidget::parseManifest(QXmlStreamReader &reader, QXmlStreamWriter &writer)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,14 +14,11 @@
|
|||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QCheckBox;
|
class QCheckBox;
|
||||||
class QDomDocument;
|
class QDomDocument;
|
||||||
class QDomElement;
|
|
||||||
class QComboBox;
|
class QComboBox;
|
||||||
class QPushButton;
|
class QPushButton;
|
||||||
class QLabel;
|
class QLabel;
|
||||||
class QLineEdit;
|
class QLineEdit;
|
||||||
class QListView;
|
class QListView;
|
||||||
class QSpinBox;
|
|
||||||
class QToolButton;
|
|
||||||
class QXmlStreamReader;
|
class QXmlStreamReader;
|
||||||
class QXmlStreamWriter;
|
class QXmlStreamWriter;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
@@ -108,9 +105,6 @@ private:
|
|||||||
void syncToEditor();
|
void syncToEditor();
|
||||||
void updateAfterFileLoad();
|
void updateAfterFileLoad();
|
||||||
|
|
||||||
bool checkDocument(const QDomDocument &doc, QString *errorMessage,
|
|
||||||
int *errorLine, int *errorColumn);
|
|
||||||
|
|
||||||
void updateInfoBar(const QString &errorMessage, int line, int column);
|
void updateInfoBar(const QString &errorMessage, int line, int column);
|
||||||
void hideInfoBar();
|
void hideInfoBar();
|
||||||
|
|
||||||
|
|||||||
@@ -280,7 +280,7 @@ AndroidRunnerWorker::AndroidRunnerWorker(RunWorker *runner, const QString &packa
|
|||||||
m_beforeStartAdbCommands.append(QString("shell %1").arg(shellCmd));
|
m_beforeStartAdbCommands.append(QString("shell %1").arg(shellCmd));
|
||||||
|
|
||||||
if (auto aspect = runControl->aspect(Constants::ANDROID_POSTFINISHSHELLCMDLIST)) {
|
if (auto aspect = runControl->aspect(Constants::ANDROID_POSTFINISHSHELLCMDLIST)) {
|
||||||
QTC_CHECK(aspect->value.type() == QVariant::String);
|
QTC_CHECK(aspect->value.typeId() == QVariant::String);
|
||||||
const QStringList commands = aspect->value.toString().split('\n', Qt::SkipEmptyParts);
|
const QStringList commands = aspect->value.toString().split('\n', Qt::SkipEmptyParts);
|
||||||
for (const QString &shellCmd : commands)
|
for (const QString &shellCmd : commands)
|
||||||
m_afterFinishAdbCommands.append(QString("shell %1").arg(shellCmd));
|
m_afterFinishAdbCommands.append(QString("shell %1").arg(shellCmd));
|
||||||
|
|||||||
@@ -455,7 +455,7 @@ void TestRunner::runTestsHelper()
|
|||||||
connect(m_taskTree.get(), &TaskTree::errorOccurred, this, &TestRunner::onFinished);
|
connect(m_taskTree.get(), &TaskTree::errorOccurred, this, &TestRunner::onFinished);
|
||||||
|
|
||||||
auto progress = new TaskProgress(m_taskTree.get());
|
auto progress = new TaskProgress(m_taskTree.get());
|
||||||
progress->setDisplayName(tr("Running Tests"));
|
progress->setDisplayName(Tr::tr("Running Tests"));
|
||||||
progress->setAutoStopOnCancel(false);
|
progress->setAutoStopOnCancel(false);
|
||||||
progress->setHalfLifeTimePerTask(10000); // 10 seconds
|
progress->setHalfLifeTimePerTask(10000); // 10 seconds
|
||||||
connect(progress, &TaskProgress::canceled, this, [this, progress] {
|
connect(progress, &TaskProgress::canceled, this, [this, progress] {
|
||||||
|
|||||||
@@ -77,10 +77,10 @@ void ArtisticStyleSettings::createDocumentationFile() const
|
|||||||
if (process.result() != ProcessResult::FinishedWithSuccess)
|
if (process.result() != ProcessResult::FinishedWithSuccess)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!documentationFilePath.exists())
|
||||||
|
documentationFilePath.parentDir().ensureWritableDir();
|
||||||
|
|
||||||
QFile file(documentationFilePath.toFSPathString());
|
QFile file(documentationFilePath.toFSPathString());
|
||||||
const QFileInfo fi(file);
|
|
||||||
if (!fi.exists())
|
|
||||||
fi.dir().mkpath(fi.absolutePath());
|
|
||||||
if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text))
|
if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
#include <QVersionNumber>
|
#include <QVersionNumber>
|
||||||
|
|
||||||
using namespace TextEditor;
|
using namespace TextEditor;
|
||||||
|
using namespace Utils;
|
||||||
|
|
||||||
namespace Beautifier::Internal {
|
namespace Beautifier::Internal {
|
||||||
|
|
||||||
@@ -72,7 +73,7 @@ void Uncrustify::updateActions(Core::IEditor *editor)
|
|||||||
|
|
||||||
void Uncrustify::formatFile()
|
void Uncrustify::formatFile()
|
||||||
{
|
{
|
||||||
const QString cfgFileName = configurationFile();
|
const FilePath cfgFileName = configurationFile();
|
||||||
if (cfgFileName.isEmpty()) {
|
if (cfgFileName.isEmpty()) {
|
||||||
BeautifierPlugin::showError(BeautifierPlugin::msgCannotGetConfigurationFile(
|
BeautifierPlugin::showError(BeautifierPlugin::msgCannotGetConfigurationFile(
|
||||||
Tr::tr(Constants::UNCRUSTIFY_DISPLAY_NAME)));
|
Tr::tr(Constants::UNCRUSTIFY_DISPLAY_NAME)));
|
||||||
@@ -83,7 +84,7 @@ void Uncrustify::formatFile()
|
|||||||
|
|
||||||
void Uncrustify::formatSelectedText()
|
void Uncrustify::formatSelectedText()
|
||||||
{
|
{
|
||||||
const QString cfgFileName = configurationFile();
|
const FilePath cfgFileName = configurationFile();
|
||||||
if (cfgFileName.isEmpty()) {
|
if (cfgFileName.isEmpty()) {
|
||||||
BeautifierPlugin::showError(BeautifierPlugin::msgCannotGetConfigurationFile(
|
BeautifierPlugin::showError(BeautifierPlugin::msgCannotGetConfigurationFile(
|
||||||
Tr::tr(Constants::UNCRUSTIFY_DISPLAY_NAME)));
|
Tr::tr(Constants::UNCRUSTIFY_DISPLAY_NAME)));
|
||||||
@@ -112,42 +113,41 @@ void Uncrustify::formatSelectedText()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Uncrustify::configurationFile() const
|
FilePath Uncrustify::configurationFile() const
|
||||||
{
|
{
|
||||||
if (m_settings.useCustomStyle())
|
if (m_settings.useCustomStyle())
|
||||||
return m_settings.styleFileName(m_settings.customStyle());
|
return FilePath::fromUserInput(m_settings.styleFileName(m_settings.customStyle()));
|
||||||
|
|
||||||
if (m_settings.useOtherFiles()) {
|
if (m_settings.useOtherFiles()) {
|
||||||
if (const ProjectExplorer::Project *project
|
using namespace ProjectExplorer;
|
||||||
= ProjectExplorer::ProjectTree::currentProject()) {
|
if (const Project *project = ProjectTree::currentProject()) {
|
||||||
const Utils::FilePaths files = project->files(
|
const FilePaths files = project->files([](const Node *n) {
|
||||||
[](const ProjectExplorer::Node *n) { return n->filePath().endsWith("cfg"); });
|
const FilePath fp = n->filePath();
|
||||||
for (const Utils::FilePath &file : files) {
|
return fp.fileName() == "uncrustify.cfg" && fp.isReadableFile();
|
||||||
const QFileInfo fi = file.toFileInfo();
|
});
|
||||||
if (fi.isReadable() && fi.fileName() == "uncrustify.cfg")
|
if (!files.isEmpty())
|
||||||
return file.toString();
|
return files.first();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_settings.useSpecificConfigFile()) {
|
if (m_settings.useSpecificConfigFile()) {
|
||||||
const Utils::FilePath file = m_settings.specificConfigFile();
|
const FilePath file = m_settings.specificConfigFile();
|
||||||
if (file.exists())
|
if (file.exists())
|
||||||
return file.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_settings.useHomeFile()) {
|
|
||||||
const QString file = QDir::home().filePath("uncrustify.cfg");
|
|
||||||
if (QFile::exists(file))
|
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
return QString();
|
if (m_settings.useHomeFile()) {
|
||||||
|
const FilePath file = FileUtils::homePath() / "uncrustify.cfg";
|
||||||
|
if (file.exists())
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Command Uncrustify::command() const
|
Command Uncrustify::command() const
|
||||||
{
|
{
|
||||||
const QString cfgFile = configurationFile();
|
const FilePath cfgFile = configurationFile();
|
||||||
return cfgFile.isEmpty() ? Command() : command(cfgFile, false);
|
return cfgFile.isEmpty() ? Command() : command(cfgFile, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,7 +156,7 @@ bool Uncrustify::isApplicable(const Core::IDocument *document) const
|
|||||||
return m_settings.isApplicable(document);
|
return m_settings.isApplicable(document);
|
||||||
}
|
}
|
||||||
|
|
||||||
Command Uncrustify::command(const QString &cfgFile, bool fragment) const
|
Command Uncrustify::command(const FilePath &cfgFile, bool fragment) const
|
||||||
{
|
{
|
||||||
Command command;
|
Command command;
|
||||||
command.setExecutable(m_settings.command());
|
command.setExecutable(m_settings.command());
|
||||||
@@ -173,7 +173,7 @@ Command Uncrustify::command(const QString &cfgFile, bool fragment) const
|
|||||||
if (fragment)
|
if (fragment)
|
||||||
command.addOption("--frag");
|
command.addOption("--frag");
|
||||||
command.addOption("-c");
|
command.addOption("-c");
|
||||||
command.addOption(cfgFile);
|
command.addOption(cfgFile.path());
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
void formatFile();
|
void formatFile();
|
||||||
void formatSelectedText();
|
void formatSelectedText();
|
||||||
QString configurationFile() const;
|
Utils::FilePath configurationFile() const;
|
||||||
TextEditor::Command command(const QString &cfgFile, bool fragment = false) const;
|
TextEditor::Command command(const Utils::FilePath &cfgFile, bool fragment = false) const;
|
||||||
|
|
||||||
QAction *m_formatFile = nullptr;
|
QAction *m_formatFile = nullptr;
|
||||||
QAction *m_formatRange = nullptr;
|
QAction *m_formatRange = nullptr;
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ void ClangFormatConfigWidget::createStyleFileIfNeeded(bool isGlobal)
|
|||||||
if (configFile.exists())
|
if (configFile.exists())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QDir().mkpath(path.toString());
|
path.ensureWritableDir();
|
||||||
if (!isGlobal) {
|
if (!isGlobal) {
|
||||||
FilePath possibleProjectConfig = d->project->rootProjectDirectory()
|
FilePath possibleProjectConfig = d->project->rootProjectDirectory()
|
||||||
/ Constants::SETTINGS_FILE_NAME;
|
/ Constants::SETTINGS_FILE_NAME;
|
||||||
@@ -218,11 +218,8 @@ void ClangFormatConfigWidget::createStyleFileIfNeeded(bool isGlobal)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::fstream newStyleFile(configFile.toString().toStdString(), std::fstream::out);
|
const std::string config = clang::format::configurationAsText(constructStyle());
|
||||||
if (newStyleFile.is_open()) {
|
configFile.writeFileContents(QByteArray::fromStdString(config));
|
||||||
newStyleFile << clang::format::configurationAsText(constructStyle());
|
|
||||||
newStyleFile.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClangFormatConfigWidget::showOrHideWidgets()
|
void ClangFormatConfigWidget::showOrHideWidgets()
|
||||||
|
|||||||
@@ -1465,8 +1465,10 @@ void MainWindow::changeLog()
|
|||||||
return;
|
return;
|
||||||
const FilePath file = versionedFiles.at(index).second;
|
const FilePath file = versionedFiles.at(index).second;
|
||||||
QString contents = QString::fromUtf8(file.fileContents().value_or(QByteArray()));
|
QString contents = QString::fromUtf8(file.fileContents().value_or(QByteArray()));
|
||||||
static const QRegularExpression bugexpr("(QT(CREATOR)?BUG-[0-9]+)");
|
// (?<![[\/]) == don't replace if it is preceded by "[" or "/"
|
||||||
contents.replace(bugexpr, "[\\1](https://bugreports.qt.io/browse/\\1)");
|
// i.e. if it already is part of a link
|
||||||
|
static const QRegularExpression bugexpr(R"((?<![[\/])((QT(CREATOR)?BUG|PYSIDE)-\d+))");
|
||||||
|
contents.replace(bugexpr, R"([\1](https://bugreports.qt.io/browse/\1))");
|
||||||
static const QRegularExpression docexpr("https://doc[.]qt[.]io/qtcreator/([.a-zA-Z/_-]*)");
|
static const QRegularExpression docexpr("https://doc[.]qt[.]io/qtcreator/([.a-zA-Z/_-]*)");
|
||||||
QList<QRegularExpressionMatch> matches;
|
QList<QRegularExpressionMatch> matches;
|
||||||
for (const QRegularExpressionMatch &m : docexpr.globalMatch(contents))
|
for (const QRegularExpressionMatch &m : docexpr.globalMatch(contents))
|
||||||
|
|||||||
@@ -42,14 +42,14 @@ ProjectInfo::ConstPtr ProjectInfoGenerator::generate(const QPromise<ProjectInfo:
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
if (m_cToolchainMissing) {
|
if (m_cToolchainMissing) {
|
||||||
showWarning(Tr::tr(
|
showWarning(
|
||||||
"The project contains C source files, but the currently active kit "
|
::CppEditor::Tr::tr("The project contains C source files, but the currently active kit "
|
||||||
"has no C compiler. The code model will not be fully functional."));
|
"has no C compiler. The code model will not be fully functional."));
|
||||||
}
|
}
|
||||||
if (m_cxxToolchainMissing) {
|
if (m_cxxToolchainMissing) {
|
||||||
showWarning(Tr::tr(
|
showWarning(::CppEditor::Tr::tr(
|
||||||
"The project contains C++ source files, but the currently active kit "
|
"The project contains C++ source files, but the currently active kit "
|
||||||
"has no C++ compiler. The code model will not be fully functional."));
|
"has no C++ compiler. The code model will not be fully functional."));
|
||||||
}
|
}
|
||||||
return projectInfo;
|
return projectInfo;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1107,7 +1107,7 @@ QVariant BreakpointItem::data(int column, int role) const
|
|||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BreakpointItem::addToCommand(DebuggerCommand *cmd) const
|
void BreakpointItem::addToCommand(DebuggerCommand *cmd, BreakpointPathUsage defaultPathUsage) const
|
||||||
{
|
{
|
||||||
QTC_ASSERT(m_globalBreakpoint, return);
|
QTC_ASSERT(m_globalBreakpoint, return);
|
||||||
const BreakpointParameters &requested = requestedParameters();
|
const BreakpointParameters &requested = requestedParameters();
|
||||||
@@ -1120,10 +1120,19 @@ void BreakpointItem::addToCommand(DebuggerCommand *cmd) const
|
|||||||
cmd->arg("function", requested.functionName);
|
cmd->arg("function", requested.functionName);
|
||||||
cmd->arg("oneshot", requested.oneShot);
|
cmd->arg("oneshot", requested.oneShot);
|
||||||
cmd->arg("enabled", requested.enabled);
|
cmd->arg("enabled", requested.enabled);
|
||||||
cmd->arg("file", requested.fileName.path());
|
|
||||||
cmd->arg("line", requested.textPosition.line);
|
cmd->arg("line", requested.textPosition.line);
|
||||||
cmd->arg("address", requested.address);
|
cmd->arg("address", requested.address);
|
||||||
cmd->arg("expression", requested.expression);
|
cmd->arg("expression", requested.expression);
|
||||||
|
|
||||||
|
BreakpointPathUsage pathUsage = (requested.pathUsage
|
||||||
|
== BreakpointPathUsage::BreakpointPathUsageEngineDefault)
|
||||||
|
? defaultPathUsage
|
||||||
|
: requested.pathUsage;
|
||||||
|
|
||||||
|
cmd->arg("file",
|
||||||
|
pathUsage == BreakpointPathUsage::BreakpointUseFullPath
|
||||||
|
? requested.fileName.path()
|
||||||
|
: requested.fileName.fileName());
|
||||||
}
|
}
|
||||||
|
|
||||||
void BreakpointItem::updateFromGdbOutput(const GdbMi &bkpt, const FilePath &fileRoot)
|
void BreakpointItem::updateFromGdbOutput(const GdbMi &bkpt, const FilePath &fileRoot)
|
||||||
|
|||||||
@@ -107,7 +107,9 @@ public:
|
|||||||
int markerLineNumber() const;
|
int markerLineNumber() const;
|
||||||
|
|
||||||
const BreakpointParameters &requestedParameters() const;
|
const BreakpointParameters &requestedParameters() const;
|
||||||
void addToCommand(DebuggerCommand *cmd) const;
|
void addToCommand(DebuggerCommand *cmd,
|
||||||
|
BreakpointPathUsage defaultPathUsage
|
||||||
|
= BreakpointPathUsage::BreakpointUseFullPath) const;
|
||||||
void updateFromGdbOutput(const GdbMi &bkpt, const Utils::FilePath &fileRoot);
|
void updateFromGdbOutput(const GdbMi &bkpt, const Utils::FilePath &fileRoot);
|
||||||
|
|
||||||
int modelId() const;
|
int modelId() const;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
|
|
||||||
#include <projectexplorer/runconfiguration.h>
|
#include <projectexplorer/runconfiguration.h>
|
||||||
|
#include <projectexplorer/runconfigurationaspects.h>
|
||||||
|
|
||||||
#include <utils/environment.h>
|
#include <utils/environment.h>
|
||||||
#include <utils/hostosinfo.h>
|
#include <utils/hostosinfo.h>
|
||||||
@@ -172,9 +173,18 @@ void TerminalRunner::start()
|
|||||||
QTC_ASSERT(!m_stubProc, reportFailure({}); return);
|
QTC_ASSERT(!m_stubProc, reportFailure({}); return);
|
||||||
Runnable stub = m_stubRunnable();
|
Runnable stub = m_stubRunnable();
|
||||||
|
|
||||||
|
bool runAsRoot = false;
|
||||||
|
if (auto runAsRootAspect = runControl()->aspect<RunAsRootAspect>())
|
||||||
|
runAsRoot = runAsRootAspect->value;
|
||||||
|
|
||||||
m_stubProc = new Process(this);
|
m_stubProc = new Process(this);
|
||||||
m_stubProc->setTerminalMode(TerminalMode::Debug);
|
m_stubProc->setTerminalMode(TerminalMode::Debug);
|
||||||
|
|
||||||
|
if (runAsRoot) {
|
||||||
|
m_stubProc->setRunAsRoot(runAsRoot);
|
||||||
|
RunControl::provideAskPassEntry(stub.environment);
|
||||||
|
}
|
||||||
|
|
||||||
connect(m_stubProc, &Process::started,
|
connect(m_stubProc, &Process::started,
|
||||||
this, &TerminalRunner::stubStarted);
|
this, &TerminalRunner::stubStarted);
|
||||||
connect(m_stubProc, &Process::done,
|
connect(m_stubProc, &Process::done,
|
||||||
|
|||||||
@@ -647,7 +647,7 @@ ActionContainer *FormEditorData::createPreviewStyleMenu(QActionGroup *actionGrou
|
|||||||
QString name = menuId;
|
QString name = menuId;
|
||||||
name += dot;
|
name += dot;
|
||||||
const QVariant data = a->data();
|
const QVariant data = a->data();
|
||||||
const bool isDeviceProfile = data.type() == QVariant::Int;
|
const bool isDeviceProfile = data.typeId() == QVariant::Int;
|
||||||
if (isDeviceProfile) {
|
if (isDeviceProfile) {
|
||||||
name += deviceProfilePrefix;
|
name += deviceProfilePrefix;
|
||||||
name += dot;
|
name += dot;
|
||||||
|
|||||||
@@ -50,6 +50,39 @@ public:
|
|||||||
BuildConsoleBuildStep(BuildStepList *buildStepList, Id id);
|
BuildConsoleBuildStep(BuildStepList *buildStepList, Id id);
|
||||||
|
|
||||||
void setupOutputFormatter(OutputFormatter *formatter) final;
|
void setupOutputFormatter(OutputFormatter *formatter) final;
|
||||||
|
|
||||||
|
TextDisplay t1{this, "<b>" + Tr::tr("Target and Configuration")};
|
||||||
|
CommandBuilderAspect commandBuilder{this};
|
||||||
|
|
||||||
|
TextDisplay t2{this, "<i>" + Tr::tr("Enter the appropriate arguments to your build command.")};
|
||||||
|
TextDisplay t3{this, "<i>" + Tr::tr("Make sure the build command's multi-job "
|
||||||
|
"parameter value is large enough "
|
||||||
|
"(such as -j200 for the JOM or Make build tools)")};
|
||||||
|
BoolAspect keepJobNum{this};
|
||||||
|
|
||||||
|
TextDisplay t4{this, "<b>" + Tr::tr("IncrediBuild Distribution Control")};
|
||||||
|
FilePathAspect profileXml{this};
|
||||||
|
BoolAspect avoidLocal{this};
|
||||||
|
IntegerAspect maxCpu{this};
|
||||||
|
SelectionAspect maxWinVer{this};
|
||||||
|
SelectionAspect minWinVer{this};
|
||||||
|
|
||||||
|
TextDisplay t5{this, "<b>" + Tr::tr("Output and Logging")};
|
||||||
|
StringAspect title{this};
|
||||||
|
FilePathAspect monFile{this};
|
||||||
|
BoolAspect suppressStdOut{this};
|
||||||
|
FilePathAspect logFile{this};
|
||||||
|
BoolAspect showCmd{this};
|
||||||
|
BoolAspect showAgents{this};
|
||||||
|
BoolAspect showTime{this};
|
||||||
|
BoolAspect hideHeader{this};
|
||||||
|
SelectionAspect logLevel{this};
|
||||||
|
|
||||||
|
TextDisplay t6{this, "<b>" + Tr::tr("Miscellaneous")};
|
||||||
|
StringAspect setEnv{this};
|
||||||
|
BoolAspect stopOnError{this};
|
||||||
|
StringAspect additionalArguments{this};
|
||||||
|
BoolAspect openMonitor{this};
|
||||||
};
|
};
|
||||||
|
|
||||||
BuildConsoleBuildStep::BuildConsoleBuildStep(BuildStepList *buildStepList, Id id)
|
BuildConsoleBuildStep::BuildConsoleBuildStep(BuildStepList *buildStepList, Id id)
|
||||||
@@ -57,233 +90,198 @@ BuildConsoleBuildStep::BuildConsoleBuildStep(BuildStepList *buildStepList, Id id
|
|||||||
{
|
{
|
||||||
setDisplayName(Tr::tr("IncrediBuild for Windows"));
|
setDisplayName(Tr::tr("IncrediBuild for Windows"));
|
||||||
|
|
||||||
addAspect<TextDisplay>("<b>" + Tr::tr("Target and Configuration"));
|
commandBuilder.setSettingsKey("IncrediBuild.BuildConsole.CommandBuilder");
|
||||||
|
|
||||||
auto commandBuilder = addAspect<CommandBuilderAspect>(this);
|
keepJobNum.setSettingsKey("IncrediBuild.BuildConsole.KeepJobNum");
|
||||||
commandBuilder->setSettingsKey("IncrediBuild.BuildConsole.CommandBuilder");
|
keepJobNum.setLabel(Tr::tr("Keep original jobs number:"));
|
||||||
|
keepJobNum.setToolTip(Tr::tr("Forces IncrediBuild to not override the -j command line switch, "
|
||||||
|
"that controls the number of parallel spawned tasks. The default "
|
||||||
|
"IncrediBuild behavior is to set it to 200."));
|
||||||
|
|
||||||
addAspect<TextDisplay>("<i>" + Tr::tr("Enter the appropriate arguments to your build command."));
|
profileXml.setSettingsKey("IncrediBuild.BuildConsole.ProfileXml");
|
||||||
addAspect<TextDisplay>("<i>" + Tr::tr("Make sure the build command's multi-job "
|
profileXml.setLabelText(Tr::tr("Profile.xml:"));
|
||||||
"parameter value is large enough "
|
profileXml.setExpectedKind(PathChooser::Kind::File);
|
||||||
"(such as -j200 for the JOM or Make build tools)"));
|
profileXml.setBaseFileName(PathChooser::homePath());
|
||||||
|
profileXml.setHistoryCompleter("IncrediBuild.BuildConsole.ProfileXml.History");
|
||||||
|
profileXml.setToolTip(Tr::tr("Defines how Automatic "
|
||||||
|
"Interception Interface should handle the various processes "
|
||||||
|
"involved in a distributed job. It is not necessary for "
|
||||||
|
"\"Visual Studio\" or \"Make and Build tools\" builds, "
|
||||||
|
"but can be used to provide configuration options if those "
|
||||||
|
"builds use additional processes that are not included in "
|
||||||
|
"those packages. It is required to configure distributable "
|
||||||
|
"processes in \"Dev Tools\" builds."));
|
||||||
|
|
||||||
auto keepJobNum = addAspect<BoolAspect>();
|
avoidLocal.setSettingsKey("IncrediBuild.BuildConsole.AvoidLocal");
|
||||||
keepJobNum->setSettingsKey("IncrediBuild.BuildConsole.KeepJobNum");
|
avoidLocal.setLabel(Tr::tr("Avoid local task execution:"));
|
||||||
keepJobNum->setLabel(Tr::tr("Keep original jobs number:"));
|
avoidLocal.setToolTip(Tr::tr("Overrides the Agent Settings dialog Avoid task execution on local "
|
||||||
keepJobNum->setToolTip(Tr::tr("Forces IncrediBuild to not override the -j command line switch, "
|
"machine when possible option. This allows to free more resources "
|
||||||
"that controls the number of parallel spawned tasks. The default "
|
"on the initiator machine and could be beneficial to distribution "
|
||||||
"IncrediBuild behavior is to set it to 200."));
|
"in scenarios where the initiating machine is bottlenecking the "
|
||||||
|
"build with High CPU usage."));
|
||||||
|
|
||||||
addAspect<TextDisplay>("<b>" + Tr::tr("IncrediBuild Distribution Control"));
|
maxCpu.setSettingsKey("IncrediBuild.BuildConsole.MaxCpu");
|
||||||
|
maxCpu.setToolTip(Tr::tr("Determines the maximum number of CPU cores that can be used in a "
|
||||||
|
"build, regardless of the number of available Agents. "
|
||||||
|
"It takes into account both local and remote cores, even if the "
|
||||||
|
"Avoid Task Execution on Local Machine option is selected."));
|
||||||
|
maxCpu.setLabel(Tr::tr("Maximum CPUs to utilize in the build:"));
|
||||||
|
maxCpu.setRange(0, 65536);
|
||||||
|
|
||||||
auto profileXml = addAspect<FilePathAspect>();
|
maxWinVer.setSettingsKey("IncrediBuild.BuildConsole.MaxWinVer");
|
||||||
profileXml->setSettingsKey("IncrediBuild.BuildConsole.ProfileXml");
|
maxWinVer.setDisplayName(Tr::tr("Newest allowed helper machine OS:"));
|
||||||
profileXml->setLabelText(Tr::tr("Profile.xml:"));
|
maxWinVer.setDisplayStyle(SelectionAspect::DisplayStyle::ComboBox);
|
||||||
profileXml->setExpectedKind(PathChooser::Kind::File);
|
maxWinVer.setToolTip(Tr::tr("Specifies the newest operating system installed on a helper "
|
||||||
profileXml->setBaseFileName(PathChooser::homePath());
|
"machine to be allowed to participate as helper in the build."));
|
||||||
profileXml->setHistoryCompleter("IncrediBuild.BuildConsole.ProfileXml.History");
|
|
||||||
profileXml->setToolTip(Tr::tr("Defines how Automatic "
|
|
||||||
"Interception Interface should handle the various processes "
|
|
||||||
"involved in a distributed job. It is not necessary for "
|
|
||||||
"\"Visual Studio\" or \"Make and Build tools\" builds, "
|
|
||||||
"but can be used to provide configuration options if those "
|
|
||||||
"builds use additional processes that are not included in "
|
|
||||||
"those packages. It is required to configure distributable "
|
|
||||||
"processes in \"Dev Tools\" builds."));
|
|
||||||
|
|
||||||
auto avoidLocal = addAspect<BoolAspect>();
|
|
||||||
avoidLocal->setSettingsKey("IncrediBuild.BuildConsole.AvoidLocal");
|
|
||||||
avoidLocal->setLabel(Tr::tr("Avoid local task execution:"));
|
|
||||||
avoidLocal->setToolTip(Tr::tr("Overrides the Agent Settings dialog Avoid task execution on local "
|
|
||||||
"machine when possible option. This allows to free more resources "
|
|
||||||
"on the initiator machine and could be beneficial to distribution "
|
|
||||||
"in scenarios where the initiating machine is bottlenecking the "
|
|
||||||
"build with High CPU usage."));
|
|
||||||
|
|
||||||
auto maxCpu = addAspect<IntegerAspect>();
|
|
||||||
maxCpu->setSettingsKey("IncrediBuild.BuildConsole.MaxCpu");
|
|
||||||
maxCpu->setToolTip(Tr::tr("Determines the maximum number of CPU cores that can be used in a "
|
|
||||||
"build, regardless of the number of available Agents. "
|
|
||||||
"It takes into account both local and remote cores, even if the "
|
|
||||||
"Avoid Task Execution on Local Machine option is selected."));
|
|
||||||
maxCpu->setLabel(Tr::tr("Maximum CPUs to utilize in the build:"));
|
|
||||||
maxCpu->setRange(0, 65536);
|
|
||||||
|
|
||||||
auto maxWinVer = addAspect<SelectionAspect>();
|
|
||||||
maxWinVer->setSettingsKey("IncrediBuild.BuildConsole.MaxWinVer");
|
|
||||||
maxWinVer->setDisplayName(Tr::tr("Newest allowed helper machine OS:"));
|
|
||||||
maxWinVer->setDisplayStyle(SelectionAspect::DisplayStyle::ComboBox);
|
|
||||||
maxWinVer->setToolTip(Tr::tr("Specifies the newest operating system installed on a helper "
|
|
||||||
"machine to be allowed to participate as helper in the build."));
|
|
||||||
for (const QString &version : supportedWindowsVersions())
|
for (const QString &version : supportedWindowsVersions())
|
||||||
maxWinVer->addOption(version);
|
maxWinVer.addOption(version);
|
||||||
|
|
||||||
auto minWinVer = addAspect<SelectionAspect>();
|
minWinVer.setSettingsKey("IncrediBuild.BuildConsole.MinWinVer");
|
||||||
minWinVer->setSettingsKey("IncrediBuild.BuildConsole.MinWinVer");
|
minWinVer.setDisplayName(Tr::tr("Oldest allowed helper machine OS:"));
|
||||||
minWinVer->setDisplayName(Tr::tr("Oldest allowed helper machine OS:"));
|
minWinVer.setDisplayStyle(SelectionAspect::DisplayStyle::ComboBox);
|
||||||
minWinVer->setDisplayStyle(SelectionAspect::DisplayStyle::ComboBox);
|
minWinVer.setToolTip(Tr::tr("Specifies the oldest operating system installed on a helper "
|
||||||
minWinVer->setToolTip(Tr::tr("Specifies the oldest operating system installed on a helper "
|
"machine to be allowed to participate as helper in the build."));
|
||||||
"machine to be allowed to participate as helper in the build."));
|
|
||||||
for (const QString &version : supportedWindowsVersions())
|
for (const QString &version : supportedWindowsVersions())
|
||||||
minWinVer->addOption(version);
|
minWinVer.addOption(version);
|
||||||
|
|
||||||
addAspect<TextDisplay>("<b>" + Tr::tr("Output and Logging"));
|
title.setSettingsKey("IncrediBuild.BuildConsole.Title");
|
||||||
|
title.setLabelText(Tr::tr("Build title:"));
|
||||||
|
title.setDisplayStyle(StringAspect::LineEditDisplay);
|
||||||
|
title.setToolTip(Tr::tr("Specifies a custom header line which will be displayed in the "
|
||||||
|
"beginning of the build output text. This title will also be used "
|
||||||
|
"for the Build History and Build Monitor displays."));
|
||||||
|
|
||||||
auto title = addAspect<StringAspect>();
|
monFile.setSettingsKey("IncrediBuild.BuildConsole.MonFile");
|
||||||
title->setSettingsKey("IncrediBuild.BuildConsole.Title");
|
monFile.setLabelText(Tr::tr("Save IncrediBuild monitor file:"));
|
||||||
title->setLabelText(Tr::tr("Build title:"));
|
monFile.setExpectedKind(PathChooser::Kind::Any);
|
||||||
title->setDisplayStyle(StringAspect::LineEditDisplay);
|
monFile.setBaseFileName(PathChooser::homePath());
|
||||||
title->setToolTip(Tr::tr("Specifies a custom header line which will be displayed in the "
|
monFile.setHistoryCompleter(QLatin1String("IncrediBuild.BuildConsole.MonFile.History"));
|
||||||
"beginning of the build output text. This title will also be used "
|
monFile.setToolTip(Tr::tr("Writes a copy of the build progress file (.ib_mon) to the specified "
|
||||||
"for the Build History and Build Monitor displays."));
|
"location. If only a folder name is given, a generated GUID will serve "
|
||||||
|
"as the file name. The full path of the saved Build Monitor will be "
|
||||||
|
"written to the end of the build output."));
|
||||||
|
|
||||||
auto monFile = addAspect<FilePathAspect>();
|
suppressStdOut.setSettingsKey("IncrediBuild.BuildConsole.SuppressStdOut");
|
||||||
monFile->setSettingsKey("IncrediBuild.BuildConsole.MonFile");
|
suppressStdOut.setLabel(Tr::tr("Suppress STDOUT:"));
|
||||||
monFile->setLabelText(Tr::tr("Save IncrediBuild monitor file:"));
|
suppressStdOut.setToolTip(Tr::tr("Does not write anything to the standard output."));
|
||||||
monFile->setExpectedKind(PathChooser::Kind::Any);
|
|
||||||
monFile->setBaseFileName(PathChooser::homePath());
|
|
||||||
monFile->setHistoryCompleter(QLatin1String("IncrediBuild.BuildConsole.MonFile.History"));
|
|
||||||
monFile->setToolTip(Tr::tr("Writes a copy of the build progress file (.ib_mon) to the specified "
|
|
||||||
"location. If only a folder name is given, a generated GUID will serve "
|
|
||||||
"as the file name. The full path of the saved Build Monitor will be "
|
|
||||||
"written to the end of the build output."));
|
|
||||||
|
|
||||||
auto suppressStdOut = addAspect<BoolAspect>();
|
logFile.setSettingsKey("IncrediBuild.BuildConsole.LogFile");
|
||||||
suppressStdOut->setSettingsKey("IncrediBuild.BuildConsole.SuppressStdOut");
|
logFile.setLabelText(Tr::tr("Output Log file:"));
|
||||||
suppressStdOut->setLabel(Tr::tr("Suppress STDOUT:"));
|
logFile.setExpectedKind(PathChooser::Kind::SaveFile);
|
||||||
suppressStdOut->setToolTip(Tr::tr("Does not write anything to the standard output."));
|
logFile.setBaseFileName(PathChooser::homePath());
|
||||||
|
logFile.setHistoryCompleter(QLatin1String("IncrediBuild.BuildConsole.LogFile.History"));
|
||||||
|
logFile.setToolTip(Tr::tr("Writes build output to a file."));
|
||||||
|
|
||||||
auto logFile = addAspect<FilePathAspect>();
|
showCmd.setSettingsKey("IncrediBuild.BuildConsole.ShowCmd");
|
||||||
logFile->setSettingsKey("IncrediBuild.BuildConsole.LogFile");
|
showCmd.setLabel(Tr::tr("Show Commands in output:"));
|
||||||
logFile->setLabelText(Tr::tr("Output Log file:"));
|
showCmd.setToolTip(Tr::tr("Shows, for each file built, the command-line used by IncrediBuild "
|
||||||
logFile->setExpectedKind(PathChooser::Kind::SaveFile);
|
"to build the file."));
|
||||||
logFile->setBaseFileName(PathChooser::homePath());
|
|
||||||
logFile->setHistoryCompleter(QLatin1String("IncrediBuild.BuildConsole.LogFile.History"));
|
|
||||||
logFile->setToolTip(Tr::tr("Writes build output to a file."));
|
|
||||||
|
|
||||||
auto showCmd = addAspect<BoolAspect>();
|
showAgents.setSettingsKey("IncrediBuild.BuildConsole.ShowAgents");
|
||||||
showCmd->setSettingsKey("IncrediBuild.BuildConsole.ShowCmd");
|
showAgents.setLabel(Tr::tr("Show Agents in output:"));
|
||||||
showCmd->setLabel(Tr::tr("Show Commands in output:"));
|
showAgents.setToolTip(Tr::tr("Shows the Agent used to build each file."));
|
||||||
showCmd->setToolTip(Tr::tr("Shows, for each file built, the command-line used by IncrediBuild "
|
|
||||||
"to build the file."));
|
|
||||||
|
|
||||||
auto showAgents = addAspect<BoolAspect>();
|
showTime.setSettingsKey("IncrediBuild.BuildConsole.ShowTime");
|
||||||
showAgents->setSettingsKey("IncrediBuild.BuildConsole.ShowAgents");
|
showTime.setLabel(Tr::tr("Show Time in output:"));
|
||||||
showAgents->setLabel(Tr::tr("Show Agents in output:"));
|
showTime.setToolTip(Tr::tr("Shows the Start and Finish time for each file built."));
|
||||||
showAgents->setToolTip(Tr::tr("Shows the Agent used to build each file."));
|
|
||||||
|
|
||||||
auto showTime = addAspect<BoolAspect>();
|
hideHeader.setSettingsKey("IncrediBuild.BuildConsole.HideHeader");
|
||||||
showTime->setSettingsKey("IncrediBuild.BuildConsole.ShowTime");
|
hideHeader.setLabel(Tr::tr("Hide IncrediBuild Header in output:"));
|
||||||
showTime->setLabel(Tr::tr("Show Time in output:"));
|
hideHeader.setToolTip(Tr::tr("Suppresses IncrediBuild's header in the build output"));
|
||||||
showTime->setToolTip(Tr::tr("Shows the Start and Finish time for each file built."));
|
|
||||||
|
|
||||||
auto hideHeader = addAspect<BoolAspect>();
|
logLevel.setSettingsKey("IncrediBuild.BuildConsole.LogLevel");
|
||||||
hideHeader->setSettingsKey("IncrediBuild.BuildConsole.HideHeader");
|
logLevel.setDisplayName(Tr::tr("Internal IncrediBuild logging level:"));
|
||||||
hideHeader->setLabel(Tr::tr("Hide IncrediBuild Header in output:"));
|
logLevel.setDisplayStyle(SelectionAspect::DisplayStyle::ComboBox);
|
||||||
hideHeader->setToolTip(Tr::tr("Suppresses IncrediBuild's header in the build output"));
|
logLevel.addOption(QString());
|
||||||
|
logLevel.addOption("Minimal");
|
||||||
|
logLevel.addOption("Extended");
|
||||||
|
logLevel.addOption("Detailed");
|
||||||
|
logLevel.setToolTip(Tr::tr("Overrides the internal Incredibuild logging level for this build. "
|
||||||
|
"Does not affect output or any user accessible logging. Used mainly "
|
||||||
|
"to troubleshoot issues with the help of IncrediBuild support"));
|
||||||
|
|
||||||
auto logLevel = addAspect<SelectionAspect>();
|
setEnv.setSettingsKey("IncrediBuild.BuildConsole.SetEnv");
|
||||||
logLevel->setSettingsKey("IncrediBuild.BuildConsole.LogLevel");
|
setEnv.setLabelText(Tr::tr("Set an Environment Variable:"));
|
||||||
logLevel->setDisplayName(Tr::tr("Internal IncrediBuild logging level:"));
|
setEnv.setDisplayStyle(StringAspect::LineEditDisplay);
|
||||||
logLevel->setDisplayStyle(SelectionAspect::DisplayStyle::ComboBox);
|
setEnv.setToolTip(Tr::tr("Sets or overrides environment variables for the context of the build."));
|
||||||
logLevel->addOption(QString());
|
|
||||||
logLevel->addOption("Minimal");
|
|
||||||
logLevel->addOption("Extended");
|
|
||||||
logLevel->addOption("Detailed");
|
|
||||||
logLevel->setToolTip(Tr::tr("Overrides the internal Incredibuild logging level for this build. "
|
|
||||||
"Does not affect output or any user accessible logging. Used mainly "
|
|
||||||
"to troubleshoot issues with the help of IncrediBuild support"));
|
|
||||||
|
|
||||||
addAspect<TextDisplay>("<b>" + Tr::tr("Miscellaneous"));
|
stopOnError.setSettingsKey("IncrediBuild.BuildConsole.StopOnError");
|
||||||
|
stopOnError.setLabel(Tr::tr("Stop on errors:"));
|
||||||
|
stopOnError.setToolTip(Tr::tr("When specified, the execution will stop as soon as an error "
|
||||||
|
"is encountered. This is the default behavior in "
|
||||||
|
"\"Visual Studio\" builds, but not the default for "
|
||||||
|
"\"Make and Build tools\" or \"Dev Tools\" builds"));
|
||||||
|
|
||||||
auto setEnv = addAspect<StringAspect>();
|
additionalArguments.setSettingsKey("IncrediBuild.BuildConsole.AdditionalArguments");
|
||||||
setEnv->setSettingsKey("IncrediBuild.BuildConsole.SetEnv");
|
additionalArguments.setLabelText(Tr::tr("Additional Arguments:"));
|
||||||
setEnv->setLabelText(Tr::tr("Set an Environment Variable:"));
|
additionalArguments.setDisplayStyle(StringAspect::LineEditDisplay);
|
||||||
setEnv->setDisplayStyle(StringAspect::LineEditDisplay);
|
additionalArguments.setToolTip(Tr::tr("Add additional buildconsole arguments manually. "
|
||||||
setEnv->setToolTip(Tr::tr("Sets or overrides environment variables for the context of the build."));
|
"The value of this field will be concatenated to the "
|
||||||
|
"final buildconsole command line"));
|
||||||
|
|
||||||
auto stopOnError = addAspect<BoolAspect>();
|
openMonitor.setSettingsKey("IncrediBuild.BuildConsole.OpenMonitor");
|
||||||
stopOnError->setSettingsKey("IncrediBuild.BuildConsole.StopOnError");
|
openMonitor.setLabel(Tr::tr("Open Build Monitor:"));
|
||||||
stopOnError->setLabel(Tr::tr("Stop on errors:"));
|
openMonitor.setToolTip(Tr::tr("Opens Build Monitor once the build starts."));
|
||||||
stopOnError->setToolTip(Tr::tr("When specified, the execution will stop as soon as an error "
|
|
||||||
"is encountered. This is the default behavior in "
|
|
||||||
"\"Visual Studio\" builds, but not the default for "
|
|
||||||
"\"Make and Build tools\" or \"Dev Tools\" builds"));
|
|
||||||
|
|
||||||
auto additionalArguments = addAspect<StringAspect>();
|
setCommandLineProvider([this] {
|
||||||
additionalArguments->setSettingsKey("IncrediBuild.BuildConsole.AdditionalArguments");
|
CommandLine cmd("BuildConsole.exe");
|
||||||
additionalArguments->setLabelText(Tr::tr("Additional Arguments:"));
|
|
||||||
additionalArguments->setDisplayStyle(StringAspect::LineEditDisplay);
|
|
||||||
additionalArguments->setToolTip(Tr::tr("Add additional buildconsole arguments manually. "
|
|
||||||
"The value of this field will be concatenated to the "
|
|
||||||
"final buildconsole command line"));
|
|
||||||
|
|
||||||
auto openMonitor = addAspect<BoolAspect>();
|
cmd.addArgs(QString("/Command=%1").arg(commandBuilder.fullCommandFlag(keepJobNum())), CommandLine::Raw);
|
||||||
openMonitor->setSettingsKey("IncrediBuild.BuildConsole.OpenMonitor");
|
|
||||||
openMonitor->setLabel(Tr::tr("Open Build Monitor:"));
|
|
||||||
openMonitor->setToolTip(Tr::tr("Opens Build Monitor once the build starts."));
|
|
||||||
|
|
||||||
setCommandLineProvider([=] {
|
if (!profileXml().isEmpty())
|
||||||
QStringList args;
|
cmd.addArg(QString("/Profile=%1").arg(profileXml().path()));
|
||||||
|
|
||||||
QString cmd("/Command= %1");
|
cmd.addArg(QString("/AvoidLocal=%1").arg(avoidLocal() ? QString("ON") : QString("OFF")));
|
||||||
cmd = cmd.arg(commandBuilder->fullCommandFlag(keepJobNum->value()));
|
|
||||||
args.append(cmd);
|
|
||||||
|
|
||||||
if (!profileXml->value().isEmpty())
|
if (maxCpu() > 0)
|
||||||
args.append("/Profile=" + profileXml->value());
|
cmd.addArg(QString("/MaxCPUs=%1").arg(maxCpu()));
|
||||||
|
|
||||||
args.append(QString("/AvoidLocal=%1").arg(avoidLocal->value() ? QString("ON") : QString("OFF")));
|
if (!maxWinVer.stringValue().isEmpty())
|
||||||
|
cmd.addArg(QString("/MaxWinVer=%1").arg(normalizeWinVerArgument(maxWinVer.stringValue())));
|
||||||
|
|
||||||
if (maxCpu->value() > 0)
|
if (!minWinVer.stringValue().isEmpty())
|
||||||
args.append(QString("/MaxCPUs=%1").arg(maxCpu->value()));
|
cmd.addArg(QString("/MinWinVer=%1").arg(normalizeWinVerArgument(minWinVer.stringValue())));
|
||||||
|
|
||||||
if (!maxWinVer->stringValue().isEmpty())
|
if (!title().isEmpty())
|
||||||
args.append(QString("/MaxWinVer=%1").arg(normalizeWinVerArgument(maxWinVer->stringValue())));
|
cmd.addArg("/Title=" + title());
|
||||||
|
|
||||||
if (!minWinVer->stringValue().isEmpty())
|
if (!monFile().isEmpty())
|
||||||
args.append(QString("/MinWinVer=%1").arg(normalizeWinVerArgument(minWinVer->stringValue())));
|
cmd.addArg("/Mon=" + monFile().path());
|
||||||
|
|
||||||
if (!title->value().isEmpty())
|
if (suppressStdOut())
|
||||||
args.append(QString("/Title=" + title->value()));
|
cmd.addArg("/Silent");
|
||||||
|
|
||||||
if (!monFile->value().isEmpty())
|
if (!logFile().isEmpty())
|
||||||
args.append(QString("/Mon=" + monFile->value()));
|
cmd.addArg("/Log=" + logFile().path());
|
||||||
|
|
||||||
if (suppressStdOut->value())
|
if (showCmd())
|
||||||
args.append("/Silent");
|
cmd.addArg("/ShowCmd");
|
||||||
|
|
||||||
if (!logFile->value().isEmpty())
|
if (showAgents())
|
||||||
args.append(QString("/Log=" + logFile->value()));
|
cmd.addArg("/ShowAgent");
|
||||||
|
|
||||||
if (showCmd->value())
|
if (showAgents())
|
||||||
args.append("/ShowCmd");
|
cmd.addArg("/ShowTime");
|
||||||
|
|
||||||
if (showAgents->value())
|
if (hideHeader())
|
||||||
args.append("/ShowAgent");
|
cmd.addArg("/NoLogo");
|
||||||
|
|
||||||
if (showAgents->value())
|
if (!logLevel.stringValue().isEmpty())
|
||||||
args.append("/ShowTime");
|
cmd.addArg("/LogLevel=" + logLevel.stringValue());
|
||||||
|
|
||||||
if (hideHeader->value())
|
if (!setEnv().isEmpty())
|
||||||
args.append("/NoLogo");
|
cmd.addArg("/SetEnv=" + setEnv());
|
||||||
|
|
||||||
if (!logLevel->stringValue().isEmpty())
|
if (stopOnError())
|
||||||
args.append(QString("/LogLevel=" + logLevel->stringValue()));
|
cmd.addArg("/StopOnErrors");
|
||||||
|
|
||||||
if (!setEnv->value().isEmpty())
|
if (!additionalArguments().isEmpty())
|
||||||
args.append(QString("/SetEnv=" + setEnv->value()));
|
cmd.addArgs(additionalArguments(), CommandLine::Raw);
|
||||||
|
|
||||||
if (stopOnError->value())
|
if (openMonitor())
|
||||||
args.append("/StopOnErrors");
|
cmd.addArg("/OpenMonitor");
|
||||||
|
|
||||||
if (!additionalArguments->value().isEmpty())
|
return cmd;
|
||||||
args.append(additionalArguments->value());
|
|
||||||
|
|
||||||
if (openMonitor->value())
|
|
||||||
args.append("/OpenMonitor");
|
|
||||||
|
|
||||||
return CommandLine("BuildConsole.exe", args);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,21 @@ public:
|
|||||||
IBConsoleBuildStep(BuildStepList *buildStepList, Id id);
|
IBConsoleBuildStep(BuildStepList *buildStepList, Id id);
|
||||||
|
|
||||||
void setupOutputFormatter(OutputFormatter *formatter) final;
|
void setupOutputFormatter(OutputFormatter *formatter) final;
|
||||||
|
|
||||||
|
TextDisplay t1{this, "<b>" + Tr::tr("Target and Configuration")};
|
||||||
|
CommandBuilderAspect commandBuilder{this};
|
||||||
|
BoolAspect keepJobNum{this};
|
||||||
|
|
||||||
|
TextDisplay t2{this, "<i>" + Tr::tr("Enter the appropriate arguments to your build command.")};
|
||||||
|
TextDisplay t3{this, "<i>" + Tr::tr("Make sure the build command's "
|
||||||
|
"multi-job parameter value is large enough (such as "
|
||||||
|
"-j200 for the JOM or Make build tools)")};
|
||||||
|
|
||||||
|
TextDisplay t4{this, "<b>" + Tr::tr("IncrediBuild Distribution Control")};
|
||||||
|
|
||||||
|
IntegerAspect nice{this};
|
||||||
|
BoolAspect forceRemote{this};
|
||||||
|
BoolAspect alternate{this};
|
||||||
};
|
};
|
||||||
|
|
||||||
IBConsoleBuildStep::IBConsoleBuildStep(BuildStepList *buildStepList, Id id)
|
IBConsoleBuildStep::IBConsoleBuildStep(BuildStepList *buildStepList, Id id)
|
||||||
@@ -35,52 +50,38 @@ IBConsoleBuildStep::IBConsoleBuildStep(BuildStepList *buildStepList, Id id)
|
|||||||
{
|
{
|
||||||
setDisplayName(Tr::tr("IncrediBuild for Linux"));
|
setDisplayName(Tr::tr("IncrediBuild for Linux"));
|
||||||
|
|
||||||
addAspect<TextDisplay>("<b>" + Tr::tr("Target and Configuration"));
|
commandBuilder.setSettingsKey("IncrediBuild.IBConsole.CommandBuilder");
|
||||||
|
|
||||||
auto commandBuilder = addAspect<CommandBuilderAspect>(this);
|
keepJobNum.setSettingsKey("IncrediBuild.IBConsole.KeepJobNum");
|
||||||
commandBuilder->setSettingsKey("IncrediBuild.IBConsole.CommandBuilder");
|
keepJobNum.setLabel(Tr::tr("Keep original jobs number:"));
|
||||||
|
keepJobNum.setToolTip(Tr::tr("Forces IncrediBuild to not override the -j command line switch, "
|
||||||
|
"that controls the number of parallel spawned tasks. The default "
|
||||||
|
"IncrediBuild behavior is to set it to 200."));
|
||||||
|
|
||||||
addAspect<TextDisplay>("<i>" + Tr::tr("Enter the appropriate arguments to your build command."));
|
nice.setSettingsKey("IncrediBuild.IBConsole.Nice");
|
||||||
addAspect<TextDisplay>("<i>" + Tr::tr("Make sure the build command's "
|
nice.setToolTip(Tr::tr("Specify nice value. Nice Value should be numeric and between -20 and 19"));
|
||||||
"multi-job parameter value is large enough (such as "
|
nice.setLabel(Tr::tr("Nice value:"));
|
||||||
"-j200 for the JOM or Make build tools)"));
|
nice.setRange(-20, 19);
|
||||||
|
|
||||||
auto keepJobNum = addAspect<BoolAspect>();
|
forceRemote.setSettingsKey("IncrediBuild.IBConsole.Alternate");
|
||||||
keepJobNum->setSettingsKey("IncrediBuild.IBConsole.KeepJobNum");
|
forceRemote.setLabel(Tr::tr("Force remote:"));
|
||||||
keepJobNum->setLabel(Tr::tr("Keep original jobs number:"));
|
|
||||||
keepJobNum->setToolTip(Tr::tr("Forces IncrediBuild to not override the -j command line switch, "
|
|
||||||
"that controls the number of parallel spawned tasks. The default "
|
|
||||||
"IncrediBuild behavior is to set it to 200."));
|
|
||||||
|
|
||||||
addAspect<TextDisplay>("<b>" + Tr::tr("IncrediBuild Distribution Control"));
|
alternate.setSettingsKey("IncrediBuild.IBConsole.ForceRemote");
|
||||||
|
alternate.setLabel(Tr::tr("Alternate tasks preference:"));
|
||||||
|
|
||||||
auto nice = addAspect<IntegerAspect>();
|
setCommandLineProvider([this] {
|
||||||
nice->setSettingsKey("IncrediBuild.IBConsole.Nice");
|
|
||||||
nice->setToolTip(Tr::tr("Specify nice value. Nice Value should be numeric and between -20 and 19"));
|
|
||||||
nice->setLabel(Tr::tr("Nice value:"));
|
|
||||||
nice->setRange(-20, 19);
|
|
||||||
|
|
||||||
auto forceRemote = addAspect<BoolAspect>();
|
|
||||||
forceRemote->setSettingsKey("IncrediBuild.IBConsole.Alternate");
|
|
||||||
forceRemote->setLabel(Tr::tr("Force remote:"));
|
|
||||||
|
|
||||||
auto alternate = addAspect<BoolAspect>();
|
|
||||||
alternate->setSettingsKey("IncrediBuild.IBConsole.ForceRemote");
|
|
||||||
alternate->setLabel(Tr::tr("Alternate tasks preference:"));
|
|
||||||
|
|
||||||
setCommandLineProvider([=] {
|
|
||||||
QStringList args;
|
QStringList args;
|
||||||
|
|
||||||
if (nice->value() != 0)
|
if (nice() != 0)
|
||||||
args.append(QString("--nice %1 ").arg(nice->value()));
|
args.append(QString("--nice %1 ").arg(nice()));
|
||||||
|
|
||||||
if (alternate->value())
|
if (alternate())
|
||||||
args.append("--alternate");
|
args.append("--alternate");
|
||||||
|
|
||||||
if (forceRemote->value())
|
if (forceRemote())
|
||||||
args.append("--force-remote");
|
args.append("--force-remote");
|
||||||
|
|
||||||
args.append(commandBuilder->fullCommandFlag(keepJobNum->value()));
|
args.append(commandBuilder.fullCommandFlag(keepJobNum()));
|
||||||
|
|
||||||
return CommandLine("ib_console", args);
|
return CommandLine("ib_console", args);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
#include <QComboBox>
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
#include <QElapsedTimer>
|
#include <QElapsedTimer>
|
||||||
@@ -334,7 +335,7 @@ private:
|
|||||||
QTabWidget * const m_tabWidget;
|
QTabWidget * const m_tabWidget;
|
||||||
|
|
||||||
enum class TabIndex { Log, Capabilities, Custom };
|
enum class TabIndex { Log, Capabilities, Custom };
|
||||||
QListWidget *m_clients = nullptr;
|
QComboBox *m_clients = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
void LspInspector::show(const QString &defaultClient)
|
void LspInspector::show(const QString &defaultClient)
|
||||||
@@ -401,34 +402,34 @@ LspInspectorWidget::LspInspectorWidget(LspInspector *inspector)
|
|||||||
this, &LspInspectorWidget::updateCapabilities);
|
this, &LspInspectorWidget::updateCapabilities);
|
||||||
connect(Core::ICore::instance(), &Core::ICore::coreAboutToClose, this, &QWidget::close);
|
connect(Core::ICore::instance(), &Core::ICore::coreAboutToClose, this, &QWidget::close);
|
||||||
|
|
||||||
m_clients = new QListWidget;
|
|
||||||
m_clients->addItems(inspector->clients());
|
|
||||||
m_clients->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::MinimumExpanding);
|
|
||||||
|
|
||||||
auto mainLayout = new QVBoxLayout;
|
auto mainLayout = new QVBoxLayout;
|
||||||
auto mainSplitter = new Core::MiniSplitter;
|
|
||||||
mainSplitter->setOrientation(Qt::Horizontal);
|
m_clients = new QComboBox;
|
||||||
mainSplitter->addWidget(m_clients);
|
m_clients->addItem(Tr::tr("<Select>"));
|
||||||
mainSplitter->addWidget(m_tabWidget);
|
m_clients->addItems(inspector->clients());
|
||||||
mainSplitter->setStretchFactor(0, 0);
|
QHBoxLayout *hbox = new QHBoxLayout;
|
||||||
mainSplitter->setStretchFactor(1, 1);
|
hbox->addWidget(new QLabel(Tr::tr("Language Server:")));
|
||||||
|
hbox->addWidget(m_clients);
|
||||||
|
hbox->addStretch();
|
||||||
|
mainLayout->addLayout(hbox);
|
||||||
|
|
||||||
m_tabWidget->addTab(new LspLogWidget, Tr::tr("Log"));
|
m_tabWidget->addTab(new LspLogWidget, Tr::tr("Log"));
|
||||||
m_tabWidget->addTab(new LspCapabilitiesWidget, Tr::tr("Capabilities"));
|
m_tabWidget->addTab(new LspCapabilitiesWidget, Tr::tr("Capabilities"));
|
||||||
mainLayout->addWidget(mainSplitter);
|
mainLayout->addWidget(m_tabWidget);
|
||||||
|
|
||||||
auto buttonBox = new QDialogButtonBox(this);
|
auto buttonBox = new QDialogButtonBox(this);
|
||||||
buttonBox->setStandardButtons(QDialogButtonBox::Save | QDialogButtonBox::Close);
|
buttonBox->setStandardButtons(QDialogButtonBox::Save | QDialogButtonBox::Close);
|
||||||
const auto clearButton = buttonBox->addButton(Tr::tr("Clear"), QDialogButtonBox::ResetRole);
|
const auto clearButton = buttonBox->addButton(Tr::tr("Clear"), QDialogButtonBox::ResetRole);
|
||||||
connect(clearButton, &QPushButton::clicked, this, [this] {
|
connect(clearButton, &QPushButton::clicked, this, [this] {
|
||||||
m_inspector->clear();
|
m_inspector->clear();
|
||||||
if (m_clients->currentItem())
|
if (m_clients->currentIndex() != 0)
|
||||||
currentClientChanged(m_clients->currentItem()->text());
|
currentClientChanged(m_clients->currentText());
|
||||||
});
|
});
|
||||||
mainLayout->addWidget(buttonBox);
|
mainLayout->addWidget(buttonBox);
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
|
|
||||||
connect(m_clients,
|
connect(m_clients,
|
||||||
&QListWidget::currentTextChanged,
|
&QComboBox::currentTextChanged,
|
||||||
this,
|
this,
|
||||||
&LspInspectorWidget::currentClientChanged);
|
&LspInspectorWidget::currentClientChanged);
|
||||||
|
|
||||||
@@ -442,30 +443,25 @@ LspInspectorWidget::LspInspectorWidget(LspInspector *inspector)
|
|||||||
|
|
||||||
void LspInspectorWidget::selectClient(const QString &clientName)
|
void LspInspectorWidget::selectClient(const QString &clientName)
|
||||||
{
|
{
|
||||||
auto items = m_clients->findItems(clientName, Qt::MatchExactly);
|
const int index = m_clients->findText(clientName, Qt::MatchExactly);
|
||||||
if (items.isEmpty())
|
if (index >= 0)
|
||||||
return;
|
m_clients->setCurrentIndex(index);
|
||||||
m_clients->setCurrentItem(items.first());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LspInspectorWidget::addMessage(const QString &clientName, const LspLogMessage &message)
|
void LspInspectorWidget::addMessage(const QString &clientName, const LspLogMessage &message)
|
||||||
{
|
{
|
||||||
if (m_clients->findItems(clientName, Qt::MatchExactly).isEmpty())
|
if (m_clients->findText(clientName, Qt::MatchExactly) < 0)
|
||||||
m_clients->addItem(clientName);
|
m_clients->addItem(clientName);
|
||||||
if (const QListWidgetItem *currentItem = m_clients->currentItem();
|
if (m_clients->currentText() == clientName)
|
||||||
currentItem && currentItem->text() == clientName) {
|
|
||||||
log()->addMessage(message);
|
log()->addMessage(message);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LspInspectorWidget::updateCapabilities(const QString &clientName)
|
void LspInspectorWidget::updateCapabilities(const QString &clientName)
|
||||||
{
|
{
|
||||||
if (m_clients->findItems(clientName, Qt::MatchExactly).isEmpty())
|
if (m_clients->findText(clientName, Qt::MatchExactly) < 0)
|
||||||
m_clients->addItem(clientName);
|
m_clients->addItem(clientName);
|
||||||
if (const QListWidgetItem *currentItem = m_clients->currentItem();
|
if (m_clients->currentText() == clientName)
|
||||||
currentItem && clientName == currentItem->text()) {
|
|
||||||
capabilities()->setCapabilities(m_inspector->capabilities(clientName));
|
capabilities()->setCapabilities(m_inspector->capabilities(clientName));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LspInspectorWidget::currentClientChanged(const QString &clientName)
|
void LspInspectorWidget::currentClientChanged(const QString &clientName)
|
||||||
|
|||||||
@@ -21,5 +21,9 @@
|
|||||||
<file>wizards/qmlproject/component.qml.tpl</file>
|
<file>wizards/qmlproject/component.qml.tpl</file>
|
||||||
<file>wizards/qmlproject/wizard.json</file>
|
<file>wizards/qmlproject/wizard.json</file>
|
||||||
<file>wizards/qmlproject/Qul.cmake</file>
|
<file>wizards/qmlproject/Qul.cmake</file>
|
||||||
|
<file>wizards/qmlproject-empty/CMakeLists.txt</file>
|
||||||
|
<file>wizards/qmlproject-empty/main.qml.tpl</file>
|
||||||
|
<file>wizards/qmlproject-empty/project.qmlproject.tpl</file>
|
||||||
|
<file>wizards/qmlproject-empty/wizard.json</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
cmake_minimum_required (VERSION 3.21.1)
|
||||||
|
|
||||||
|
project(%{CorrectedProjectName} VERSION 0.0.1 LANGUAGES C CXX ASM)
|
||||||
|
|
||||||
|
find_package(Qul)
|
||||||
|
|
||||||
|
qul_add_target(%{CorrectedProjectName} QML_PROJECT %{QmlProjectFile} GENERATE_ENTRYPOINT)
|
||||||
|
app_target_setup_os(%{CorrectedProjectName})
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import QtQuick
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
Text {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: "Qt for MCUs"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
import QmlProject 1.3
|
||||||
|
|
||||||
|
Project {
|
||||||
|
qtForMCUs: true // Required by QDS to enable/disable features Supported/Unsupported by QtMCUs projects. Currently ignored by qmlprojectexporter.
|
||||||
|
// importPaths: [] // Alternative API to ModuleFiles for importing modules.
|
||||||
|
// projectRootPath: "." // Optional root path relative to qmlproject file path.
|
||||||
|
mainFile: "%{MainQmlFile}" // The application's entrypoint
|
||||||
|
|
||||||
|
MCU.Config {
|
||||||
|
controlsStyle: "QtQuick.Controls.StyleDefault"
|
||||||
|
debugBytecode: false
|
||||||
|
debugLineDirectives: false
|
||||||
|
|
||||||
|
// maxResourceCacheSize: 0 // Set to 0 by default. Required for OnDemand resource cache policy and resource compression.
|
||||||
|
|
||||||
|
// Global settings for image properties. Can be overridden for selected resources in ImageFiles nodes.
|
||||||
|
resourceImagePixelFormat: "Automatic"
|
||||||
|
resourceCachePolicy: "NoCaching"
|
||||||
|
resourceCompression: false
|
||||||
|
|
||||||
|
// Font engine selection
|
||||||
|
fontEngine: "Static" // alternative option: "Spark".
|
||||||
|
|
||||||
|
// Font defaults for both engines
|
||||||
|
defaultFontFamily: "DejaVu Sans Mono"
|
||||||
|
defaultFontQuality: "VeryHigh"
|
||||||
|
glyphsCachePolicy: "NoCaching"
|
||||||
|
maxParagraphSize: 100
|
||||||
|
|
||||||
|
// Font properties for "Static"
|
||||||
|
addDefaultFonts: true // Set to false to disable add adding default fonts to your project.
|
||||||
|
autoGenerateGlyphs: true
|
||||||
|
|
||||||
|
// Font properties for "Spark"
|
||||||
|
// These properties are in effect only if the "Spark" font engine is used
|
||||||
|
complexTextRendering: true // Set this to false if complex scripts are not needed (Arabic scripts, Indic scripts, etc.)
|
||||||
|
fontCachePriming: false // Set to true to decrease application startup time. Only applies to fonts configured with unicode ranges (font.unicodeCoverage).
|
||||||
|
fontCacheSize: 0 // If this is needed, use a suitable number. Setting this to a sensible value will improve performance, the global default is 104800.
|
||||||
|
fontHeapSize: -1 // Set to sufficient value to improve performance. -1 means no restrictions to heap allocation.
|
||||||
|
fontHeapPrealloc: true
|
||||||
|
fontCachePrealloc: true
|
||||||
|
}
|
||||||
|
|
||||||
|
QmlFiles {
|
||||||
|
files: ["%{MainQmlFile}"]
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageFiles {
|
||||||
|
files: []
|
||||||
|
}
|
||||||
|
|
||||||
|
FontFiles {
|
||||||
|
files: []
|
||||||
|
}
|
||||||
|
|
||||||
|
TranslationFiles {
|
||||||
|
files: []
|
||||||
|
}
|
||||||
|
|
||||||
|
InterfaceFiles {
|
||||||
|
files: []
|
||||||
|
}
|
||||||
|
|
||||||
|
ModuleFiles {
|
||||||
|
files: []
|
||||||
|
// Uncomment for adding Qul modules
|
||||||
|
MCU.qulModules: [
|
||||||
|
// "Qul::Controls",
|
||||||
|
// "Qul::ControlsTemplates",
|
||||||
|
// "Qul::Shapes",
|
||||||
|
// "Qul::Timeline"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
71
src/plugins/mcusupport/wizards/qmlproject-empty/wizard.json
Normal file
71
src/plugins/mcusupport/wizards/qmlproject-empty/wizard.json
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"supportedProjectTypes": [ "CMakeProjectManager.CMakeProject" ],
|
||||||
|
"id": "M.McuSupportApplicationEmpty",
|
||||||
|
"category": "D.ApplicationMCU",
|
||||||
|
"trDescription": "Suitable for Qt for MCUs versions 2.4 and later. Creates an empty application that you can deploy, run and debug on MCU boards",
|
||||||
|
"trDisplayName": "Qt for MCUs Empty Application",
|
||||||
|
"trDisplayCategory": "QmlProject Application (Qt for MCUs)",
|
||||||
|
"icon": "../icon.png",
|
||||||
|
"iconKind": "Themed",
|
||||||
|
"enabled": true,
|
||||||
|
|
||||||
|
"options":
|
||||||
|
[
|
||||||
|
{ "key": "CorrectedProjectName", "value": "%{JS: '%{ProjectName}'.replace(/-/g, '_')}"},
|
||||||
|
{ "key": "MainQmlFile", "value": "%{CorrectedProjectName}.qml" },
|
||||||
|
{ "key": "QmlProjectFile", "value": "%{CorrectedProjectName}.qmlproject" },
|
||||||
|
{ "key": "CMakeFile", "value": "%{CorrectedProjectName}/CMakeLists.txt" }
|
||||||
|
],
|
||||||
|
|
||||||
|
"pages":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"trDisplayName": "Project Location",
|
||||||
|
"trShortTitle": "Location",
|
||||||
|
"typeId": "Project"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"trDisplayName": "Kit Selection",
|
||||||
|
"trShortTitle": "Kits",
|
||||||
|
"typeId": "Kits",
|
||||||
|
"enabled": "%{JS: !value('IsSubproject')}",
|
||||||
|
"data": {
|
||||||
|
"projectFilePath": "%{CMakeFile}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"trDisplayName": "Project Management",
|
||||||
|
"trShortTitle": "Summary",
|
||||||
|
"typeId": "Summary"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"generators":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"typeId": "File",
|
||||||
|
"data":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"source": "CMakeLists.txt",
|
||||||
|
"openAsProject": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"source": "project.qmlproject.tpl",
|
||||||
|
"target": "%{ProjectDirectory}/%{QmlProjectFile}",
|
||||||
|
"openInEditor": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"source": "main.qml.tpl",
|
||||||
|
"target": "%{ProjectDirectory}/%{MainQmlFile}",
|
||||||
|
"openInEditor": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"source": "%{IDE:ResourcePath}/templates/wizards/projects/git.ignore",
|
||||||
|
"target": ".gitignore",
|
||||||
|
"condition": "%{JS: !value('IsSubproject') && value('VersionControl') === 'G.Git'}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ Project {
|
|||||||
qtForMCUs: true // Required by QDS to enable/disable features Supported/Unsupported by QtMCUs projects. Currently ignored by qmlprojectexporter.
|
qtForMCUs: true // Required by QDS to enable/disable features Supported/Unsupported by QtMCUs projects. Currently ignored by qmlprojectexporter.
|
||||||
// importPaths: ["imports/CustomModule"] // Alternative API for importing modules.
|
// importPaths: ["imports/CustomModule"] // Alternative API for importing modules.
|
||||||
// projectRootPath: "." // Optional root path relative to qmlproject file path.
|
// projectRootPath: "." // Optional root path relative to qmlproject file path.
|
||||||
mainFile: "%{MainQmlFile}" // Required to determin which qml file is the application entrypoint, when no custom c++ entrypoint is specified.
|
mainFile: "%{MainQmlFile}" // The application's entrypoint
|
||||||
|
|
||||||
/* Global configuration */
|
/* Global configuration */
|
||||||
MCU.Config {
|
MCU.Config {
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
{
|
{
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"supportedProjectTypes": [ "CMakeProjectManager.CMakeProject" ],
|
"supportedProjectTypes": [ "CMakeProjectManager.CMakeProject" ],
|
||||||
"id": "M.McuSupportApplication",
|
"id": "M.McuSupportApplicationExample",
|
||||||
"category": "D.ApplicationMCU",
|
"category": "D.ApplicationMCU",
|
||||||
"trDescription": "Suitable for Qt for MCUs versions 2.4 and later. 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.",
|
"trDescription": "Suitable for Qt for MCUs versions 2.4 and later. 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.",
|
||||||
"trDisplayName": "Qt for MCUs Application",
|
"trDisplayName": "Qt for MCUs Example Application",
|
||||||
"trDisplayCategory": "QmlProject Application (Qt for MCUs)",
|
"trDisplayCategory": "QmlProject Application (Qt for MCUs)",
|
||||||
"icon": "../icon.png",
|
"icon": "../icon.png",
|
||||||
"iconKind": "Themed",
|
"iconKind": "Themed",
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ QWidget *BuildStep::createConfigWidget()
|
|||||||
Layouting::Form form;
|
Layouting::Form form;
|
||||||
for (BaseAspect *aspect : std::as_const(*this)) {
|
for (BaseAspect *aspect : std::as_const(*this)) {
|
||||||
if (aspect->isVisible())
|
if (aspect->isVisible())
|
||||||
form.addItem(aspect);
|
form.addItems({aspect, Layouting::br()});
|
||||||
}
|
}
|
||||||
form.addItem(Layouting::noMargin);
|
form.addItem(Layouting::noMargin);
|
||||||
auto widget = form.emerge();
|
auto widget = form.emerge();
|
||||||
|
|||||||
@@ -218,14 +218,14 @@ QString JsonWizard::stringValue(const QString &n) const
|
|||||||
if (!v.isValid())
|
if (!v.isValid())
|
||||||
return QString();
|
return QString();
|
||||||
|
|
||||||
if (v.type() == QVariant::String) {
|
if (v.typeId() == QVariant::String) {
|
||||||
QString tmp = m_expander.expand(v.toString());
|
QString tmp = m_expander.expand(v.toString());
|
||||||
if (tmp.isEmpty())
|
if (tmp.isEmpty())
|
||||||
tmp = QString::fromLatin1(""); // Make sure isNull() is *not* true.
|
tmp = QString::fromLatin1(""); // Make sure isNull() is *not* true.
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (v.type() == QVariant::StringList)
|
if (v.typeId() == QVariant::StringList)
|
||||||
return stringListToArrayString(v.toStringList(), &m_expander);
|
return stringListToArrayString(v.toStringList(), &m_expander);
|
||||||
|
|
||||||
return v.toString();
|
return v.toString();
|
||||||
@@ -276,7 +276,7 @@ QVariant JsonWizard::value(const QString &n) const
|
|||||||
|
|
||||||
bool JsonWizard::boolFromVariant(const QVariant &v, MacroExpander *expander)
|
bool JsonWizard::boolFromVariant(const QVariant &v, MacroExpander *expander)
|
||||||
{
|
{
|
||||||
if (v.type() == QVariant::String) {
|
if (v.typeId() == QVariant::String) {
|
||||||
const QString tmp = expander->expand(v.toString());
|
const QString tmp = expander->expand(v.toString());
|
||||||
return !(tmp.isEmpty() || tmp == QLatin1String("false"));
|
return !(tmp.isEmpty() || tmp == QLatin1String("false"));
|
||||||
}
|
}
|
||||||
@@ -410,7 +410,7 @@ void JsonWizard::handleError(const QString &message)
|
|||||||
|
|
||||||
QString JsonWizard::stringify(const QVariant &v) const
|
QString JsonWizard::stringify(const QVariant &v) const
|
||||||
{
|
{
|
||||||
if (v.type() == QVariant::StringList)
|
if (v.typeId() == QVariant::StringList)
|
||||||
return stringListToArrayString(v.toStringList(), &m_expander);
|
return stringListToArrayString(v.toStringList(), &m_expander);
|
||||||
return Wizard::stringify(v);
|
return Wizard::stringify(v);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ static JsonWizardFactory::Generator parseGenerator(const QVariant &value, QStrin
|
|||||||
{
|
{
|
||||||
JsonWizardFactory::Generator gen;
|
JsonWizardFactory::Generator gen;
|
||||||
|
|
||||||
if (value.type() != QVariant::Map) {
|
if (value.typeId() != QVariant::Map) {
|
||||||
*errorMessage = Tr::tr("Generator is not a object.");
|
*errorMessage = Tr::tr("Generator is not a object.");
|
||||||
return gen;
|
return gen;
|
||||||
}
|
}
|
||||||
@@ -236,8 +236,8 @@ QVariant JsonWizardFactory::getDataValue(const QLatin1String &key, const QVarian
|
|||||||
{
|
{
|
||||||
QVariant retVal = {};
|
QVariant retVal = {};
|
||||||
|
|
||||||
if ((valueSet.contains(key) && valueSet.value(key).type() == QVariant::Map) ||
|
if ((valueSet.contains(key) && valueSet.value(key).typeId() == QVariant::Map) ||
|
||||||
(defaultValueSet.contains(key) && defaultValueSet.value(key).type() == QVariant::Map)) {
|
(defaultValueSet.contains(key) && defaultValueSet.value(key).typeId() == QVariant::Map)) {
|
||||||
retVal = mergeDataValueMaps(valueSet.value(key), defaultValueSet.value(key));
|
retVal = mergeDataValueMaps(valueSet.value(key), defaultValueSet.value(key));
|
||||||
} else {
|
} else {
|
||||||
QVariant defaultValue = defaultValueSet.value(key, notExistValue);
|
QVariant defaultValue = defaultValueSet.value(key, notExistValue);
|
||||||
@@ -263,7 +263,7 @@ std::pair<int, QStringList> JsonWizardFactory::screenSizeInfoFromPage(const QStr
|
|||||||
return {};
|
return {};
|
||||||
|
|
||||||
const QVariant data = it->data;
|
const QVariant data = it->data;
|
||||||
if (data.type() != QVariant::List)
|
if (data.typeId() != QVariant::List)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
const QVariant screenFactorField = Utils::findOrDefault(data.toList(),
|
const QVariant screenFactorField = Utils::findOrDefault(data.toList(),
|
||||||
@@ -272,11 +272,11 @@ std::pair<int, QStringList> JsonWizardFactory::screenSizeInfoFromPage(const QStr
|
|||||||
return "ScreenFactor" == m["name"];
|
return "ScreenFactor" == m["name"];
|
||||||
});
|
});
|
||||||
|
|
||||||
if (screenFactorField.type() != QVariant::Map)
|
if (screenFactorField.typeId() != QVariant::Map)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
const QVariant screenFactorData = screenFactorField.toMap()["data"];
|
const QVariant screenFactorData = screenFactorField.toMap()["data"];
|
||||||
if (screenFactorData.type() != QVariant::Map)
|
if (screenFactorData.typeId() != QVariant::Map)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
const QVariantMap screenFactorDataMap = screenFactorData.toMap();
|
const QVariantMap screenFactorDataMap = screenFactorData.toMap();
|
||||||
@@ -304,7 +304,7 @@ JsonWizardFactory::Page JsonWizardFactory::parsePage(const QVariant &value, QStr
|
|||||||
{
|
{
|
||||||
JsonWizardFactory::Page p;
|
JsonWizardFactory::Page p;
|
||||||
|
|
||||||
if (value.type() != QVariant::Map) {
|
if (value.typeId() != QVariant::Map) {
|
||||||
*errorMessage = Tr::tr("Page is not an object.");
|
*errorMessage = Tr::tr("Page is not an object.");
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@@ -351,9 +351,9 @@ JsonWizardFactory::Page JsonWizardFactory::parsePage(const QVariant &value, QStr
|
|||||||
|
|
||||||
if (specifiedSubData.isNull())
|
if (specifiedSubData.isNull())
|
||||||
subData = defaultSubData;
|
subData = defaultSubData;
|
||||||
else if (specifiedSubData.type() == QVariant::Map)
|
else if (specifiedSubData.typeId() == QVariant::Map)
|
||||||
subData = mergeDataValueMaps(specifiedSubData.toMap(), defaultSubData.toMap());
|
subData = mergeDataValueMaps(specifiedSubData.toMap(), defaultSubData.toMap());
|
||||||
else if (specifiedSubData.type() == QVariant::List)
|
else if (specifiedSubData.typeId() == QVariant::List)
|
||||||
subData = specifiedSubData;
|
subData = specifiedSubData;
|
||||||
|
|
||||||
if (!factory->validateData(typeId, subData, errorMessage))
|
if (!factory->validateData(typeId, subData, errorMessage))
|
||||||
@@ -648,9 +648,9 @@ QList<QVariant> JsonWizardFactory::objectOrList(const QVariant &data, QString *e
|
|||||||
QList<QVariant> result;
|
QList<QVariant> result;
|
||||||
if (data.isNull())
|
if (data.isNull())
|
||||||
*errorMessage = Tr::tr("key not found.");
|
*errorMessage = Tr::tr("key not found.");
|
||||||
else if (data.type() == QVariant::Map)
|
else if (data.typeId() == QVariant::Map)
|
||||||
result.append(data);
|
result.append(data);
|
||||||
else if (data.type() == QVariant::List)
|
else if (data.typeId() == QVariant::List)
|
||||||
result = data.toList();
|
result = data.toList();
|
||||||
else
|
else
|
||||||
*errorMessage = Tr::tr("Expected an object or a list.");
|
*errorMessage = Tr::tr("Expected an object or a list.");
|
||||||
@@ -661,7 +661,7 @@ QString JsonWizardFactory::localizedString(const QVariant &value)
|
|||||||
{
|
{
|
||||||
if (value.isNull())
|
if (value.isNull())
|
||||||
return QString();
|
return QString();
|
||||||
if (value.type() == QVariant::Map) {
|
if (value.typeId() == QVariant::Map) {
|
||||||
QVariantMap tmp = value.toMap();
|
QVariantMap tmp = value.toMap();
|
||||||
const QString locale = languageSetting().toLower();
|
const QString locale = languageSetting().toLower();
|
||||||
QStringList locales;
|
QStringList locales;
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ Utils::WizardPage *FilePageFactory::create(JsonWizard *wizard, Utils::Id typeId,
|
|||||||
bool FilePageFactory::validateData(Utils::Id typeId, const QVariant &data, QString *errorMessage)
|
bool FilePageFactory::validateData(Utils::Id typeId, const QVariant &data, QString *errorMessage)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(canCreate(typeId), return false);
|
QTC_ASSERT(canCreate(typeId), return false);
|
||||||
if (!data.isNull() && (data.type() != QVariant::Map || !data.toMap().isEmpty())) {
|
if (!data.isNull() && (data.typeId() != QVariant::Map || !data.toMap().isEmpty())) {
|
||||||
*errorMessage = Tr::tr("\"data\" for a \"File\" page needs to be unset or an empty object.");
|
*errorMessage = Tr::tr("\"data\" for a \"File\" page needs to be unset or an empty object.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -147,7 +147,7 @@ bool KitsPageFactory::validateData(Utils::Id typeId, const QVariant &data, QStri
|
|||||||
{
|
{
|
||||||
QTC_ASSERT(canCreate(typeId), return false);
|
QTC_ASSERT(canCreate(typeId), return false);
|
||||||
|
|
||||||
if (data.isNull() || data.type() != QVariant::Map) {
|
if (data.isNull() || data.typeId() != QVariant::Map) {
|
||||||
*errorMessage = Tr::tr("\"data\" must be a JSON object for \"Kits\" pages.");
|
*errorMessage = Tr::tr("\"data\" must be a JSON object for \"Kits\" pages.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -206,7 +206,7 @@ bool ProjectPageFactory::validateData(Utils::Id typeId, const QVariant &data, QS
|
|||||||
Q_UNUSED(errorMessage)
|
Q_UNUSED(errorMessage)
|
||||||
|
|
||||||
QTC_ASSERT(canCreate(typeId), return false);
|
QTC_ASSERT(canCreate(typeId), return false);
|
||||||
if (!data.isNull() && data.type() != QVariant::Map) {
|
if (!data.isNull() && data.typeId() != QVariant::Map) {
|
||||||
*errorMessage = Tr::tr("\"data\" must be empty or a JSON object for \"Project\" pages.");
|
*errorMessage = Tr::tr("\"data\" must be empty or a JSON object for \"Project\" pages.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -252,7 +252,7 @@ Utils::WizardPage *SummaryPageFactory::create(JsonWizard *wizard, Utils::Id type
|
|||||||
bool SummaryPageFactory::validateData(Utils::Id typeId, const QVariant &data, QString *errorMessage)
|
bool SummaryPageFactory::validateData(Utils::Id typeId, const QVariant &data, QString *errorMessage)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(canCreate(typeId), return false);
|
QTC_ASSERT(canCreate(typeId), return false);
|
||||||
if (!data.isNull() && (data.type() != QVariant::Map)) {
|
if (!data.isNull() && (data.typeId() != QVariant::Map)) {
|
||||||
*errorMessage = Tr::tr("\"data\" for a \"Summary\" page can be unset or needs to be an object.");
|
*errorMessage = Tr::tr("\"data\" for a \"Summary\" page can be unset or needs to be an object.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -387,7 +387,7 @@ void ToolChainKitAspect::upgrade(Kit *k)
|
|||||||
const QVariant value = k->value(oldIdV2);
|
const QVariant value = k->value(oldIdV2);
|
||||||
if (value.isNull() && !oldValue.isNull()) {
|
if (value.isNull() && !oldValue.isNull()) {
|
||||||
QVariantMap newValue;
|
QVariantMap newValue;
|
||||||
if (oldValue.type() == QVariant::Map) {
|
if (oldValue.typeId() == QVariant::Map) {
|
||||||
// Used between 4.1 and 4.2:
|
// Used between 4.1 and 4.2:
|
||||||
newValue = oldValue.toMap();
|
newValue = oldValue.toMap();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -62,6 +62,8 @@
|
|||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
using namespace Core;
|
using namespace Core;
|
||||||
|
|
||||||
|
namespace PE = ProjectExplorer;
|
||||||
|
|
||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -207,9 +209,10 @@ Project::Project(const QString &mimeType, const FilePath &fileName)
|
|||||||
d->m_document = std::make_unique<ProjectDocument>(mimeType, fileName, this);
|
d->m_document = std::make_unique<ProjectDocument>(mimeType, fileName, this);
|
||||||
DocumentManager::addDocument(d->m_document.get());
|
DocumentManager::addDocument(d->m_document.get());
|
||||||
|
|
||||||
d->m_macroExpander.setDisplayName(Tr::tr("Project"));
|
d->m_macroExpander.setDisplayName(::PE::Tr::tr("Project"));
|
||||||
d->m_macroExpander.registerVariable("Project:Name", Tr::tr("Project Name"),
|
d->m_macroExpander.registerVariable("Project:Name", ::PE::Tr::tr("Project Name"), [this] {
|
||||||
[this] { return displayName(); });
|
return displayName();
|
||||||
|
});
|
||||||
|
|
||||||
// Only set up containernode after d is set so that it will find the project directory!
|
// Only set up containernode after d is set so that it will find the project directory!
|
||||||
d->m_containerNode = std::make_unique<ContainerNode>(this);
|
d->m_containerNode = std::make_unique<ContainerNode>(this);
|
||||||
@@ -443,7 +446,7 @@ Tasks Project::projectIssues(const Kit *k) const
|
|||||||
{
|
{
|
||||||
Tasks result;
|
Tasks result;
|
||||||
if (!k->isValid())
|
if (!k->isValid())
|
||||||
result.append(createProjectTask(Task::TaskType::Error, Tr::tr("Kit is not valid.")));
|
result.append(createProjectTask(Task::TaskType::Error, ::PE::Tr::tr("Kit is not valid.")));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -524,8 +527,8 @@ bool Project::copySteps(Target *sourceTarget, Target *newTarget)
|
|||||||
if (fatalError) {
|
if (fatalError) {
|
||||||
// That could be a more granular error message
|
// That could be a more granular error message
|
||||||
QMessageBox::critical(ICore::dialogParent(),
|
QMessageBox::critical(ICore::dialogParent(),
|
||||||
Tr::tr("Incompatible Kit"),
|
::PE::Tr::tr("Incompatible Kit"),
|
||||||
Tr::tr("Kit %1 is incompatible with kit %2.")
|
::PE::Tr::tr("Kit %1 is incompatible with kit %2.")
|
||||||
.arg(sourceTarget->kit()->displayName())
|
.arg(sourceTarget->kit()->displayName())
|
||||||
.arg(newTarget->kit()->displayName()));
|
.arg(newTarget->kit()->displayName()));
|
||||||
} else if (!buildconfigurationError.isEmpty()
|
} else if (!buildconfigurationError.isEmpty()
|
||||||
@@ -534,27 +537,27 @@ bool Project::copySteps(Target *sourceTarget, Target *newTarget)
|
|||||||
|
|
||||||
QString error;
|
QString error;
|
||||||
if (!buildconfigurationError.isEmpty())
|
if (!buildconfigurationError.isEmpty())
|
||||||
error += Tr::tr("Build configurations:") + QLatin1Char('\n')
|
error += ::PE::Tr::tr("Build configurations:") + QLatin1Char('\n')
|
||||||
+ buildconfigurationError.join(QLatin1Char('\n'));
|
+ buildconfigurationError.join(QLatin1Char('\n'));
|
||||||
|
|
||||||
if (!deployconfigurationError.isEmpty()) {
|
if (!deployconfigurationError.isEmpty()) {
|
||||||
if (!error.isEmpty())
|
if (!error.isEmpty())
|
||||||
error.append(QLatin1Char('\n'));
|
error.append(QLatin1Char('\n'));
|
||||||
error += Tr::tr("Deploy configurations:") + QLatin1Char('\n')
|
error += ::PE::Tr::tr("Deploy configurations:") + QLatin1Char('\n')
|
||||||
+ deployconfigurationError.join(QLatin1Char('\n'));
|
+ deployconfigurationError.join(QLatin1Char('\n'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!runconfigurationError.isEmpty()) {
|
if (!runconfigurationError.isEmpty()) {
|
||||||
if (!error.isEmpty())
|
if (!error.isEmpty())
|
||||||
error.append(QLatin1Char('\n'));
|
error.append(QLatin1Char('\n'));
|
||||||
error += Tr::tr("Run configurations:") + QLatin1Char('\n')
|
error += ::PE::Tr::tr("Run configurations:") + QLatin1Char('\n')
|
||||||
+ runconfigurationError.join(QLatin1Char('\n'));
|
+ runconfigurationError.join(QLatin1Char('\n'));
|
||||||
}
|
}
|
||||||
|
|
||||||
QMessageBox msgBox(ICore::dialogParent());
|
QMessageBox msgBox(ICore::dialogParent());
|
||||||
msgBox.setIcon(QMessageBox::Warning);
|
msgBox.setIcon(QMessageBox::Warning);
|
||||||
msgBox.setWindowTitle(Tr::tr("Partially Incompatible Kit"));
|
msgBox.setWindowTitle(::PE::Tr::tr("Partially Incompatible Kit"));
|
||||||
msgBox.setText(Tr::tr("Some configurations could not be copied."));
|
msgBox.setText(::PE::Tr::tr("Some configurations could not be copied."));
|
||||||
msgBox.setDetailedText(error);
|
msgBox.setDetailedText(error);
|
||||||
msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
|
msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
|
||||||
fatalError = msgBox.exec() != QDialog::Accepted;
|
fatalError = msgBox.exec() != QDialog::Accepted;
|
||||||
@@ -728,11 +731,11 @@ FilePath Project::projectDirectory(const FilePath &top)
|
|||||||
|
|
||||||
void Project::changeRootProjectDirectory()
|
void Project::changeRootProjectDirectory()
|
||||||
{
|
{
|
||||||
FilePath rootPath = FileUtils::getExistingDirectory(
|
FilePath rootPath = FileUtils::getExistingDirectory(nullptr,
|
||||||
nullptr,
|
::PE::Tr::tr("Select the Root Directory"),
|
||||||
Tr::tr("Select the Root Directory"),
|
rootProjectDirectory(),
|
||||||
rootProjectDirectory(),
|
QFileDialog::ShowDirsOnly
|
||||||
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
|
| QFileDialog::DontResolveSymlinks);
|
||||||
if (rootPath != d->m_rootProjectDirectory) {
|
if (rootPath != d->m_rootProjectDirectory) {
|
||||||
d->m_rootProjectDirectory = rootPath;
|
d->m_rootProjectDirectory = rootPath;
|
||||||
setNamedSettings(Constants::PROJECT_ROOT_PATH_KEY, d->m_rootProjectDirectory.toString());
|
setNamedSettings(Constants::PROJECT_ROOT_PATH_KEY, d->m_rootProjectDirectory.toString());
|
||||||
@@ -817,20 +820,27 @@ void Project::createTargetFromMap(const QVariantMap &map, int index)
|
|||||||
if (!deviceTypeId.isValid())
|
if (!deviceTypeId.isValid())
|
||||||
deviceTypeId = Constants::DESKTOP_DEVICE_TYPE;
|
deviceTypeId = Constants::DESKTOP_DEVICE_TYPE;
|
||||||
const QString formerKitName = targetMap.value(Target::displayNameKey()).toString();
|
const QString formerKitName = targetMap.value(Target::displayNameKey()).toString();
|
||||||
k = KitManager::registerKit([deviceTypeId, &formerKitName](Kit *kit) {
|
k = KitManager::registerKit(
|
||||||
const QString kitNameSuggestion = formerKitName.contains(Tr::tr("Replacement for"))
|
[deviceTypeId, &formerKitName](Kit *kit) {
|
||||||
? formerKitName : Tr::tr("Replacement for \"%1\"").arg(formerKitName);
|
const QString kitNameSuggestion
|
||||||
|
= formerKitName.contains(::PE::Tr::tr("Replacement for"))
|
||||||
|
? formerKitName
|
||||||
|
: ::PE::Tr::tr("Replacement for \"%1\"").arg(formerKitName);
|
||||||
const QString tempKitName = makeUniquelyNumbered(kitNameSuggestion,
|
const QString tempKitName = makeUniquelyNumbered(kitNameSuggestion,
|
||||||
transform(KitManager::kits(), &Kit::unexpandedDisplayName));
|
transform(KitManager::kits(), &Kit::unexpandedDisplayName));
|
||||||
kit->setUnexpandedDisplayName(tempKitName);
|
kit->setUnexpandedDisplayName(tempKitName);
|
||||||
DeviceTypeKitAspect::setDeviceTypeId(kit, deviceTypeId);
|
DeviceTypeKitAspect::setDeviceTypeId(kit, deviceTypeId);
|
||||||
kit->makeReplacementKit();
|
kit->makeReplacementKit();
|
||||||
kit->setup();
|
kit->setup();
|
||||||
}, id);
|
},
|
||||||
|
id);
|
||||||
QTC_ASSERT(k, return);
|
QTC_ASSERT(k, return);
|
||||||
TaskHub::addTask(BuildSystemTask(Task::Warning, Tr::tr("Project \"%1\" was configured for "
|
TaskHub::addTask(BuildSystemTask(
|
||||||
"kit \"%2\" with id %3, which does not exist anymore. The new kit \"%4\" was "
|
Task::Warning,
|
||||||
"created in its place, in an attempt not to lose custom project settings.")
|
::PE::Tr::tr(
|
||||||
|
"Project \"%1\" was configured for "
|
||||||
|
"kit \"%2\" with id %3, which does not exist anymore. The new kit \"%4\" was "
|
||||||
|
"created in its place, in an attempt not to lose custom project settings.")
|
||||||
.arg(displayName(), formerKitName, id.toString(), k->displayName())));
|
.arg(displayName(), formerKitName, id.toString(), k->displayName())));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1081,7 +1091,8 @@ QStringList Project::availableQmlPreviewTranslations(QString *errorMessage)
|
|||||||
const QDir languageDirectory(projectDirectory + "/i18n");
|
const QDir languageDirectory(projectDirectory + "/i18n");
|
||||||
const auto qmFiles = languageDirectory.entryList({"qml_*.qm"});
|
const auto qmFiles = languageDirectory.entryList({"qml_*.qm"});
|
||||||
if (qmFiles.isEmpty() && errorMessage)
|
if (qmFiles.isEmpty() && errorMessage)
|
||||||
errorMessage->append(Tr::tr("Could not find any qml_*.qm file at \"%1\"").arg(languageDirectory.absolutePath()));
|
errorMessage->append(::PE::Tr::tr("Could not find any qml_*.qm file at \"%1\"")
|
||||||
|
.arg(languageDirectory.absolutePath()));
|
||||||
return transform(qmFiles, [](const QString &qmFile) {
|
return transform(qmFiles, [](const QString &qmFile) {
|
||||||
const int localeStartPosition = qmFile.lastIndexOf("_") + 1;
|
const int localeStartPosition = qmFile.lastIndexOf("_") + 1;
|
||||||
const int localeEndPosition = qmFile.size() - QString(".qm").size();
|
const int localeEndPosition = qmFile.size() - QString(".qm").size();
|
||||||
@@ -1167,7 +1178,7 @@ void Project::addVariablesToMacroExpander(const QByteArray &prefix,
|
|||||||
const QByteArray prefixWithoutColon = fullPrefix.chopped(1);
|
const QByteArray prefixWithoutColon = fullPrefix.chopped(1);
|
||||||
expander->registerVariable(fullPrefix + "Name",
|
expander->registerVariable(fullPrefix + "Name",
|
||||||
//: %1 is something like "Active project"
|
//: %1 is something like "Active project"
|
||||||
Tr::tr("%1: Name.").arg(descriptor),
|
::PE::Tr::tr("%1: Name.").arg(descriptor),
|
||||||
[projectGetter]() -> QString {
|
[projectGetter]() -> QString {
|
||||||
if (const Project *const project = projectGetter())
|
if (const Project *const project = projectGetter())
|
||||||
return project->displayName();
|
return project->displayName();
|
||||||
@@ -1175,7 +1186,7 @@ void Project::addVariablesToMacroExpander(const QByteArray &prefix,
|
|||||||
});
|
});
|
||||||
expander->registerFileVariables(prefixWithoutColon,
|
expander->registerFileVariables(prefixWithoutColon,
|
||||||
//: %1 is something like "Active project"
|
//: %1 is something like "Active project"
|
||||||
Tr::tr("%1: Full path to main file.").arg(descriptor),
|
::PE::Tr::tr("%1: Full path to main file.").arg(descriptor),
|
||||||
[projectGetter]() -> FilePath {
|
[projectGetter]() -> FilePath {
|
||||||
if (const Project *const project = projectGetter())
|
if (const Project *const project = projectGetter())
|
||||||
return project->projectFilePath();
|
return project->projectFilePath();
|
||||||
@@ -1183,7 +1194,7 @@ void Project::addVariablesToMacroExpander(const QByteArray &prefix,
|
|||||||
});
|
});
|
||||||
expander->registerVariable(fullPrefix + "Kit:Name",
|
expander->registerVariable(fullPrefix + "Kit:Name",
|
||||||
//: %1 is something like "Active project"
|
//: %1 is something like "Active project"
|
||||||
Tr::tr("%1: The name of the active kit.").arg(descriptor),
|
::PE::Tr::tr("%1: The name of the active kit.").arg(descriptor),
|
||||||
[targetGetter]() -> QString {
|
[targetGetter]() -> QString {
|
||||||
if (const Target *const target = targetGetter())
|
if (const Target *const target = targetGetter())
|
||||||
return target->kit()->displayName();
|
return target->kit()->displayName();
|
||||||
@@ -1191,7 +1202,8 @@ void Project::addVariablesToMacroExpander(const QByteArray &prefix,
|
|||||||
});
|
});
|
||||||
expander->registerVariable(fullPrefix + "BuildConfig:Name",
|
expander->registerVariable(fullPrefix + "BuildConfig:Name",
|
||||||
//: %1 is something like "Active project"
|
//: %1 is something like "Active project"
|
||||||
Tr::tr("%1: Name of the active build configuration.").arg(descriptor),
|
::PE::Tr::tr("%1: Name of the active build configuration.")
|
||||||
|
.arg(descriptor),
|
||||||
[bcGetter]() -> QString {
|
[bcGetter]() -> QString {
|
||||||
if (const BuildConfiguration *const bc = bcGetter())
|
if (const BuildConfiguration *const bc = bcGetter())
|
||||||
return bc->displayName();
|
return bc->displayName();
|
||||||
@@ -1199,25 +1211,27 @@ void Project::addVariablesToMacroExpander(const QByteArray &prefix,
|
|||||||
});
|
});
|
||||||
expander->registerVariable(fullPrefix + "BuildConfig:Type",
|
expander->registerVariable(fullPrefix + "BuildConfig:Type",
|
||||||
//: %1 is something like "Active project"
|
//: %1 is something like "Active project"
|
||||||
Tr::tr("%1: Type of the active build configuration.").arg(descriptor),
|
::PE::Tr::tr("%1: Type of the active build configuration.")
|
||||||
|
.arg(descriptor),
|
||||||
[bcGetter]() -> QString {
|
[bcGetter]() -> QString {
|
||||||
const BuildConfiguration *const bc = bcGetter();
|
const BuildConfiguration *const bc = bcGetter();
|
||||||
const BuildConfiguration::BuildType type
|
const BuildConfiguration::BuildType type
|
||||||
= bc ? bc->buildType() : BuildConfiguration::Unknown;
|
= bc ? bc->buildType() : BuildConfiguration::Unknown;
|
||||||
return BuildConfiguration::buildTypeName(type);
|
return BuildConfiguration::buildTypeName(type);
|
||||||
});
|
});
|
||||||
expander
|
expander->registerVariable(fullPrefix + "BuildConfig:Path",
|
||||||
->registerVariable(fullPrefix + "BuildConfig:Path",
|
//: %1 is something like "Active project"
|
||||||
//: %1 is something like "Active project"
|
::PE::Tr::tr("%1: Full build path of active build configuration.")
|
||||||
Tr::tr("%1: Full build path of active build configuration.").arg(descriptor),
|
.arg(descriptor),
|
||||||
[bcGetter]() -> QString {
|
[bcGetter]() -> QString {
|
||||||
if (const BuildConfiguration *const bc = bcGetter())
|
if (const BuildConfiguration *const bc = bcGetter())
|
||||||
return bc->buildDirectory().toUserOutput();
|
return bc->buildDirectory().toUserOutput();
|
||||||
return {};
|
return {};
|
||||||
});
|
});
|
||||||
expander->registerPrefix(fullPrefix + "BuildConfig:Env",
|
expander->registerPrefix(fullPrefix + "BuildConfig:Env",
|
||||||
//: %1 is something like "Active project"
|
//: %1 is something like "Active project"
|
||||||
Tr::tr("%1: Variables in the active build environment.").arg(descriptor),
|
::PE::Tr::tr("%1: Variables in the active build environment.")
|
||||||
|
.arg(descriptor),
|
||||||
[bcGetter](const QString &var) {
|
[bcGetter](const QString &var) {
|
||||||
if (BuildConfiguration *const bc = bcGetter())
|
if (BuildConfiguration *const bc = bcGetter())
|
||||||
return bc->environment().expandedValueForKey(var);
|
return bc->environment().expandedValueForKey(var);
|
||||||
@@ -1226,7 +1240,8 @@ void Project::addVariablesToMacroExpander(const QByteArray &prefix,
|
|||||||
|
|
||||||
expander->registerVariable(fullPrefix + "RunConfig:Name",
|
expander->registerVariable(fullPrefix + "RunConfig:Name",
|
||||||
//: %1 is something like "Active project"
|
//: %1 is something like "Active project"
|
||||||
Tr::tr("%1: Name of the active run configuration.").arg(descriptor),
|
::PE::Tr::tr("%1: Name of the active run configuration.")
|
||||||
|
.arg(descriptor),
|
||||||
[rcGetter]() -> QString {
|
[rcGetter]() -> QString {
|
||||||
if (const RunConfiguration *const rc = rcGetter())
|
if (const RunConfiguration *const rc = rcGetter())
|
||||||
return rc->displayName();
|
return rc->displayName();
|
||||||
@@ -1234,27 +1249,30 @@ void Project::addVariablesToMacroExpander(const QByteArray &prefix,
|
|||||||
});
|
});
|
||||||
expander->registerFileVariables(fullPrefix + "RunConfig:Executable",
|
expander->registerFileVariables(fullPrefix + "RunConfig:Executable",
|
||||||
//: %1 is something like "Active project"
|
//: %1 is something like "Active project"
|
||||||
Tr::tr("%1: Executable of the active run configuration.")
|
::PE::Tr::tr("%1: Executable of the active run configuration.")
|
||||||
.arg(descriptor),
|
.arg(descriptor),
|
||||||
[rcGetter]() -> FilePath {
|
[rcGetter]() -> FilePath {
|
||||||
if (const RunConfiguration *const rc = rcGetter())
|
if (const RunConfiguration *const rc = rcGetter())
|
||||||
return rc->commandLine().executable();
|
return rc->commandLine().executable();
|
||||||
return {};
|
return {};
|
||||||
});
|
});
|
||||||
expander->registerPrefix(fullPrefix + "RunConfig:Env",
|
expander
|
||||||
//: %1 is something like "Active project"
|
->registerPrefix(fullPrefix + "RunConfig:Env",
|
||||||
Tr::tr("%1: Variables in the environment of the active run configuration.")
|
//: %1 is something like "Active project"
|
||||||
.arg(descriptor),
|
::PE::Tr::tr(
|
||||||
[rcGetter](const QString &var) {
|
"%1: Variables in the environment of the active run configuration.")
|
||||||
if (const RunConfiguration *const rc = rcGetter()) {
|
.arg(descriptor),
|
||||||
if (const auto envAspect = rc->aspect<EnvironmentAspect>())
|
[rcGetter](const QString &var) {
|
||||||
return envAspect->environment().expandedValueForKey(var);
|
if (const RunConfiguration *const rc = rcGetter()) {
|
||||||
}
|
if (const auto envAspect = rc->aspect<EnvironmentAspect>())
|
||||||
return QString();
|
return envAspect->environment().expandedValueForKey(var);
|
||||||
});
|
}
|
||||||
|
return QString();
|
||||||
|
});
|
||||||
expander->registerVariable(fullPrefix + "RunConfig:WorkingDir",
|
expander->registerVariable(fullPrefix + "RunConfig:WorkingDir",
|
||||||
//: %1 is something like "Active project"
|
//: %1 is something like "Active project"
|
||||||
Tr::tr("%1: Working directory of the active run configuration.")
|
::PE::Tr::tr(
|
||||||
|
"%1: Working directory of the active run configuration.")
|
||||||
.arg(descriptor),
|
.arg(descriptor),
|
||||||
[rcGetter] {
|
[rcGetter] {
|
||||||
if (const RunConfiguration *const rc = rcGetter()) {
|
if (const RunConfiguration *const rc = rcGetter()) {
|
||||||
|
|||||||
@@ -51,11 +51,8 @@ public:
|
|||||||
const FilePath &newFilePath) override;
|
const FilePath &newFilePath) override;
|
||||||
QString name() const override { return QLatin1String("python"); }
|
QString name() const override { return QLatin1String("python"); }
|
||||||
|
|
||||||
bool saveRawFileList(const QStringList &rawFileList);
|
|
||||||
bool saveRawList(const QStringList &rawList, const FilePath &filePath);
|
|
||||||
void parse();
|
void parse();
|
||||||
QStringList processEntries(const QStringList &paths,
|
bool save();
|
||||||
QHash<QString, QString> *map = nullptr) const;
|
|
||||||
|
|
||||||
bool writePyProjectFile(const FilePath &filePath, QString &content,
|
bool writePyProjectFile(const FilePath &filePath, QString &content,
|
||||||
const QStringList &rawList, QString *errorMessage);
|
const QStringList &rawList, QString *errorMessage);
|
||||||
@@ -63,12 +60,14 @@ public:
|
|||||||
void triggerParsing() final;
|
void triggerParsing() final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QStringList m_rawFileList;
|
struct FileEntry {
|
||||||
QStringList m_files;
|
QString rawEntry;
|
||||||
QStringList m_rawQmlImportPathList;
|
FilePath filePath;
|
||||||
QStringList m_qmlImportPaths;
|
};
|
||||||
QHash<QString, QString> m_rawListEntries;
|
QList<FileEntry> processEntries(const QStringList &paths) const;
|
||||||
QHash<QString, QString> m_rawQmlImportPathEntries;
|
|
||||||
|
QList<FileEntry> m_files;
|
||||||
|
QList<FileEntry> m_qmlImportPaths;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -125,9 +124,9 @@ static QStringList readLines(const FilePath &projectFile)
|
|||||||
QSet<QString> visited = { projectFileName };
|
QSet<QString> visited = { projectFileName };
|
||||||
QStringList lines = { projectFileName };
|
QStringList lines = { projectFileName };
|
||||||
|
|
||||||
QFile file(projectFile.toString());
|
const expected_str<QByteArray> contents = projectFile.fileContents();
|
||||||
if (file.open(QFile::ReadOnly)) {
|
if (contents) {
|
||||||
QTextStream stream(&file);
|
QTextStream stream(contents.value());
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
const QString line = stream.readLine();
|
const QString line = stream.readLine();
|
||||||
@@ -145,17 +144,17 @@ static QStringList readLines(const FilePath &projectFile)
|
|||||||
|
|
||||||
static QStringList readLinesJson(const FilePath &projectFile, QString *errorMessage)
|
static QStringList readLinesJson(const FilePath &projectFile, QString *errorMessage)
|
||||||
{
|
{
|
||||||
QStringList lines = { projectFile.fileName() };
|
const QString projectFileName = projectFile.fileName();
|
||||||
|
QSet<QString> visited = { projectFileName };
|
||||||
|
QStringList lines = { projectFileName };
|
||||||
|
|
||||||
const QJsonObject obj = readObjJson(projectFile, errorMessage);
|
const QJsonObject obj = readObjJson(projectFile, errorMessage);
|
||||||
if (obj.contains("files")) {
|
for (const QJsonValue &file : obj.value("files").toArray()) {
|
||||||
const QJsonValue files = obj.value("files");
|
const QString fileName = file.toString();
|
||||||
const QJsonArray files_array = files.toArray();
|
if (visited.contains(fileName))
|
||||||
QSet<QString> visited;
|
continue;
|
||||||
for (const auto &file : files_array)
|
lines.append(fileName);
|
||||||
visited.insert(file.toString());
|
visited.insert(fileName);
|
||||||
|
|
||||||
lines.append(Utils::toList(visited));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return lines;
|
return lines;
|
||||||
@@ -226,20 +225,19 @@ void PythonBuildSystem::triggerParsing()
|
|||||||
QList<BuildTargetInfo> appTargets;
|
QList<BuildTargetInfo> appTargets;
|
||||||
|
|
||||||
auto newRoot = std::make_unique<PythonProjectNode>(projectDirectory());
|
auto newRoot = std::make_unique<PythonProjectNode>(projectDirectory());
|
||||||
for (const QString &f : std::as_const(m_files)) {
|
for (const FileEntry &entry: std::as_const(m_files)) {
|
||||||
const QString displayName = baseDir.relativeFilePath(f);
|
const QString displayName = entry.filePath.relativePathFrom(projectDirectory()).toUserOutput();
|
||||||
const FilePath filePath = FilePath::fromString(f);
|
const FileType fileType = getFileType(entry.filePath);
|
||||||
const FileType fileType = getFileType(filePath);
|
|
||||||
|
|
||||||
newRoot->addNestedNode(std::make_unique<PythonFileNode>(filePath, displayName, fileType));
|
newRoot->addNestedNode(std::make_unique<PythonFileNode>(entry.filePath, displayName, fileType));
|
||||||
const MimeType mt = mimeTypeForFile(filePath, MimeMatchMode::MatchExtension);
|
const MimeType mt = mimeTypeForFile(entry.filePath, MimeMatchMode::MatchExtension);
|
||||||
if (mt.matchesName(Constants::C_PY_MIMETYPE) || mt.matchesName(Constants::C_PY3_MIMETYPE)) {
|
if (mt.matchesName(Constants::C_PY_MIMETYPE) || mt.matchesName(Constants::C_PY3_MIMETYPE)) {
|
||||||
BuildTargetInfo bti;
|
BuildTargetInfo bti;
|
||||||
bti.displayName = displayName;
|
bti.displayName = displayName;
|
||||||
bti.buildKey = f;
|
bti.buildKey = entry.filePath.toString();
|
||||||
bti.targetFilePath = filePath;
|
bti.targetFilePath = entry.filePath;
|
||||||
bti.projectFilePath = projectFilePath();
|
bti.projectFilePath = projectFilePath();
|
||||||
bti.isQtcRunnable = filePath.fileName() == "main.py";
|
bti.isQtcRunnable = entry.filePath.fileName() == "main.py";
|
||||||
appTargets.append(bti);
|
appTargets.append(bti);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -252,9 +250,9 @@ void PythonBuildSystem::triggerParsing()
|
|||||||
const auto hiddenRccFolders = project()->files(Project::HiddenRccFolders);
|
const auto hiddenRccFolders = project()->files(Project::HiddenRccFolders);
|
||||||
auto projectInfo = modelManager->defaultProjectInfoForProject(project(), hiddenRccFolders);
|
auto projectInfo = modelManager->defaultProjectInfoForProject(project(), hiddenRccFolders);
|
||||||
|
|
||||||
for (const QString &importPath : std::as_const(m_qmlImportPaths)) {
|
for (const FileEntry &importPath : std::as_const(m_qmlImportPaths)) {
|
||||||
const FilePath filePath = FilePath::fromString(importPath);
|
if (!importPath.filePath.isEmpty())
|
||||||
projectInfo.importPaths.maybeInsert(filePath, QmlJS::Dialect::Qml);
|
projectInfo.importPaths.maybeInsert(importPath.filePath, QmlJS::Dialect::Qml);
|
||||||
}
|
}
|
||||||
|
|
||||||
modelManager->updateProjectInfo(projectInfo, project());
|
modelManager->updateProjectInfo(projectInfo, project());
|
||||||
@@ -265,95 +263,62 @@ void PythonBuildSystem::triggerParsing()
|
|||||||
emitBuildSystemUpdated();
|
emitBuildSystemUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PythonBuildSystem::saveRawFileList(const QStringList &rawFileList)
|
bool PythonBuildSystem::save()
|
||||||
{
|
|
||||||
const bool result = saveRawList(rawFileList, projectFilePath());
|
|
||||||
// refresh(PythonProject::Files);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PythonBuildSystem::saveRawList(const QStringList &rawList, const FilePath &filePath)
|
|
||||||
{
|
{
|
||||||
|
const FilePath filePath = projectFilePath();
|
||||||
|
const QStringList rawList = Utils::transform(m_files, &FileEntry::rawEntry);
|
||||||
const FileChangeBlocker changeGuarg(filePath);
|
const FileChangeBlocker changeGuarg(filePath);
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
|
QByteArray newContents;
|
||||||
|
|
||||||
// New project file
|
// New project file
|
||||||
if (filePath.endsWith(".pyproject")) {
|
if (filePath.endsWith(".pyproject")) {
|
||||||
FileSaver saver(filePath, QIODevice::ReadOnly | QIODevice::Text);
|
expected_str<QByteArray> contents = filePath.fileContents();
|
||||||
if (!saver.hasError()) {
|
if (contents) {
|
||||||
QString content = QTextStream(saver.file()).readAll();
|
QJsonDocument doc = QJsonDocument::fromJson(*contents);
|
||||||
if (saver.finalize(ICore::dialogParent())) {
|
QJsonObject project = doc.object();
|
||||||
QString errorMessage;
|
project["files"] = QJsonArray::fromStringList(rawList);
|
||||||
result = writePyProjectFile(filePath, content, rawList, &errorMessage);
|
doc.setObject(project);
|
||||||
if (!errorMessage.isEmpty())
|
newContents = doc.toJson();
|
||||||
MessageManager::writeDisrupting(errorMessage);
|
} else {
|
||||||
}
|
MessageManager::writeDisrupting(contents.error());
|
||||||
}
|
}
|
||||||
} else { // Old project file
|
} else { // Old project file
|
||||||
FileSaver saver(filePath, QIODevice::WriteOnly | QIODevice::Text);
|
newContents = rawList.join('\n').toUtf8();
|
||||||
if (!saver.hasError()) {
|
|
||||||
QTextStream stream(saver.file());
|
|
||||||
for (const QString &filePath : rawList)
|
|
||||||
stream << filePath << '\n';
|
|
||||||
saver.setResult(&stream);
|
|
||||||
result = saver.finalize(ICore::dialogParent());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const expected_str<qint64> writeResult = filePath.writeFileContents(newContents);
|
||||||
|
if (writeResult)
|
||||||
|
result = true;
|
||||||
|
else
|
||||||
|
MessageManager::writeDisrupting(writeResult.error());
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PythonBuildSystem::writePyProjectFile(const FilePath &filePath, QString &content,
|
|
||||||
const QStringList &rawList, QString *errorMessage)
|
|
||||||
{
|
|
||||||
QFile file(filePath.toString());
|
|
||||||
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
|
||||||
*errorMessage = Tr::tr("Unable to open \"%1\" for writing: %2")
|
|
||||||
.arg(filePath.toUserOutput(), file.errorString());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build list of files with the current rawList for the JSON file
|
|
||||||
QString files("[");
|
|
||||||
for (const QString &f : rawList)
|
|
||||||
if (!f.endsWith(".pyproject"))
|
|
||||||
files += QString("\"%1\",").arg(f);
|
|
||||||
files = files.left(files.lastIndexOf(',')); // Removing leading comma
|
|
||||||
files += ']';
|
|
||||||
|
|
||||||
// Removing everything inside square parenthesis
|
|
||||||
// to replace it with the new list of files for the JSON file.
|
|
||||||
QRegularExpression pattern(R"(\[.*\])");
|
|
||||||
content.replace(pattern, files);
|
|
||||||
file.write(content.toUtf8());
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PythonBuildSystem::addFiles(Node *, const FilePaths &filePaths, FilePaths *)
|
bool PythonBuildSystem::addFiles(Node *, const FilePaths &filePaths, FilePaths *)
|
||||||
{
|
{
|
||||||
QStringList newList = m_rawFileList;
|
const Utils::FilePath projectDir = projectDirectory();
|
||||||
|
|
||||||
const QDir baseDir(projectDirectory().toString());
|
for (const FilePath &filePath : filePaths) {
|
||||||
for (const FilePath &filePath : filePaths)
|
if (!projectDir.isSameDevice(filePath))
|
||||||
newList.append(baseDir.relativeFilePath(filePath.toString()));
|
return false;
|
||||||
|
m_files.append(FileEntry{filePath.relativePathFrom(projectDir).toString(), filePath});
|
||||||
|
}
|
||||||
|
|
||||||
return saveRawFileList(newList);
|
return save();
|
||||||
}
|
}
|
||||||
|
|
||||||
RemovedFilesFromProject PythonBuildSystem::removeFiles(Node *, const FilePaths &filePaths, FilePaths *)
|
RemovedFilesFromProject PythonBuildSystem::removeFiles(Node *, const FilePaths &filePaths, FilePaths *)
|
||||||
{
|
{
|
||||||
QStringList newList = m_rawFileList;
|
|
||||||
|
|
||||||
for (const FilePath &filePath : filePaths) {
|
for (const FilePath &filePath : filePaths) {
|
||||||
const QHash<QString, QString>::iterator i = m_rawListEntries.find(filePath.toString());
|
Utils::eraseOne(m_files,
|
||||||
if (i != m_rawListEntries.end())
|
[filePath](const FileEntry &entry) { return filePath == entry.filePath; });
|
||||||
newList.removeOne(i.value());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool res = saveRawFileList(newList);
|
return save() ? RemovedFilesFromProject::Ok : RemovedFilesFromProject::Error;
|
||||||
|
|
||||||
return res ? RemovedFilesFromProject::Ok : RemovedFilesFromProject::Error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PythonBuildSystem::deleteFiles(Node *, const FilePaths &)
|
bool PythonBuildSystem::deleteFiles(Node *, const FilePaths &)
|
||||||
@@ -363,52 +328,52 @@ bool PythonBuildSystem::deleteFiles(Node *, const FilePaths &)
|
|||||||
|
|
||||||
bool PythonBuildSystem::renameFile(Node *, const FilePath &oldFilePath, const FilePath &newFilePath)
|
bool PythonBuildSystem::renameFile(Node *, const FilePath &oldFilePath, const FilePath &newFilePath)
|
||||||
{
|
{
|
||||||
QStringList newList = m_rawFileList;
|
for (FileEntry &entry : m_files) {
|
||||||
|
if (entry.filePath == oldFilePath) {
|
||||||
const QHash<QString, QString>::iterator i = m_rawListEntries.find(oldFilePath.toString());
|
entry.filePath = newFilePath;
|
||||||
if (i != m_rawListEntries.end()) {
|
entry.rawEntry = newFilePath.relativeChildPath(projectDirectory()).toString();
|
||||||
const int index = newList.indexOf(i.value());
|
break;
|
||||||
if (index != -1) {
|
|
||||||
const QDir baseDir(projectDirectory().toString());
|
|
||||||
newList.replace(index, baseDir.relativeFilePath(newFilePath.toString()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return saveRawFileList(newList);
|
return save();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PythonBuildSystem::parse()
|
void PythonBuildSystem::parse()
|
||||||
{
|
{
|
||||||
m_rawListEntries.clear();
|
m_files.clear();
|
||||||
m_rawQmlImportPathEntries.clear();
|
m_qmlImportPaths.clear();
|
||||||
|
|
||||||
|
QStringList files;
|
||||||
|
QStringList qmlImportPaths;
|
||||||
|
|
||||||
const FilePath filePath = projectFilePath();
|
const FilePath filePath = projectFilePath();
|
||||||
// The PySide project file is JSON based
|
// The PySide project file is JSON based
|
||||||
if (filePath.endsWith(".pyproject")) {
|
if (filePath.endsWith(".pyproject")) {
|
||||||
QString errorMessage;
|
QString errorMessage;
|
||||||
m_rawFileList = readLinesJson(filePath, &errorMessage);
|
files = readLinesJson(filePath, &errorMessage);
|
||||||
if (!errorMessage.isEmpty())
|
if (!errorMessage.isEmpty())
|
||||||
MessageManager::writeFlashing(errorMessage);
|
MessageManager::writeFlashing(errorMessage);
|
||||||
|
|
||||||
errorMessage.clear();
|
errorMessage.clear();
|
||||||
m_rawQmlImportPathList = readImportPathsJson(filePath, &errorMessage);
|
qmlImportPaths = readImportPathsJson(filePath, &errorMessage);
|
||||||
if (!errorMessage.isEmpty())
|
if (!errorMessage.isEmpty())
|
||||||
MessageManager::writeFlashing(errorMessage);
|
MessageManager::writeFlashing(errorMessage);
|
||||||
} else if (filePath.endsWith(".pyqtc")) {
|
} else if (filePath.endsWith(".pyqtc")) {
|
||||||
// To keep compatibility with PyQt we keep the compatibility with plain
|
// To keep compatibility with PyQt we keep the compatibility with plain
|
||||||
// text files as project files.
|
// text files as project files.
|
||||||
m_rawFileList = readLines(filePath);
|
files = readLines(filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_files = processEntries(m_rawFileList, &m_rawListEntries);
|
m_files = processEntries(files);
|
||||||
m_qmlImportPaths = processEntries(m_rawQmlImportPathList, &m_rawQmlImportPathEntries);
|
m_qmlImportPaths = processEntries(qmlImportPaths);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expands environment variables in the given \a string when they are written
|
* Expands environment variables in the given \a string when they are written
|
||||||
* like $$(VARIABLE).
|
* like $$(VARIABLE).
|
||||||
*/
|
*/
|
||||||
static void expandEnvironmentVariables(const QProcessEnvironment &env, QString &string)
|
static void expandEnvironmentVariables(const Environment &env, QString &string)
|
||||||
{
|
{
|
||||||
const QRegularExpression candidate("\\$\\$\\((.+)\\)");
|
const QRegularExpression candidate("\\$\\$\\((.+)\\)");
|
||||||
|
|
||||||
@@ -426,38 +391,25 @@ static void expandEnvironmentVariables(const QProcessEnvironment &env, QString &
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Expands environment variables and converts the path from relative to the
|
* Expands environment variables and converts the path from relative to the
|
||||||
* project to an absolute path.
|
* project to an absolute path for all given raw paths
|
||||||
*
|
|
||||||
* The \a map variable is an optional argument that will map the returned
|
|
||||||
* absolute paths back to their original \a paths.
|
|
||||||
*/
|
*/
|
||||||
QStringList PythonBuildSystem::processEntries(const QStringList &paths,
|
QList<PythonBuildSystem::FileEntry> PythonBuildSystem::processEntries(
|
||||||
QHash<QString, QString> *map) const
|
const QStringList &rawPaths) const
|
||||||
{
|
{
|
||||||
const QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
QList<FileEntry> processed;
|
||||||
const QDir projectDir(projectDirectory().toString());
|
const FilePath projectDir = projectDirectory();
|
||||||
|
const Environment env = projectDirectory().deviceEnvironment();
|
||||||
|
|
||||||
QFileInfo fileInfo;
|
for (const QString &rawPath : rawPaths) {
|
||||||
QStringList absolutePaths;
|
FilePath resolvedPath;
|
||||||
for (const QString &path : paths) {
|
QString path = rawPath.trimmed();
|
||||||
QString trimmedPath = path.trimmed();
|
if (!path.isEmpty()) {
|
||||||
if (trimmedPath.isEmpty())
|
expandEnvironmentVariables(env, path);
|
||||||
continue;
|
resolvedPath = projectDir.resolvePath(path);
|
||||||
|
|
||||||
expandEnvironmentVariables(env, trimmedPath);
|
|
||||||
|
|
||||||
trimmedPath = FilePath::fromUserInput(trimmedPath).toString();
|
|
||||||
|
|
||||||
fileInfo.setFile(projectDir, trimmedPath);
|
|
||||||
if (fileInfo.exists()) {
|
|
||||||
const QString absPath = fileInfo.absoluteFilePath();
|
|
||||||
absolutePaths.append(absPath);
|
|
||||||
if (map)
|
|
||||||
map->insert(absPath, trimmedPath);
|
|
||||||
}
|
}
|
||||||
|
processed << FileEntry{rawPath, resolvedPath};
|
||||||
}
|
}
|
||||||
absolutePaths.removeDuplicates();
|
return processed;
|
||||||
return absolutePaths;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Project::RestoreResult PythonProject::fromMap(const QVariantMap &map, QString *errorMessage)
|
Project::RestoreResult PythonProject::fromMap(const QVariantMap &map, QString *errorMessage)
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ public:
|
|||||||
, m_executable(new PathChooser())
|
, m_executable(new PathChooser())
|
||||||
{
|
{
|
||||||
m_executable->setExpectedKind(PathChooser::ExistingCommand);
|
m_executable->setExpectedKind(PathChooser::ExistingCommand);
|
||||||
|
m_executable->setAllowPathFromDevice(true);
|
||||||
|
|
||||||
connect(m_name, &QLineEdit::textChanged, this, &InterpreterDetailsWidget::changed);
|
connect(m_name, &QLineEdit::textChanged, this, &InterpreterDetailsWidget::changed);
|
||||||
connect(m_executable, &PathChooser::textChanged, this, &InterpreterDetailsWidget::changed);
|
connect(m_executable, &PathChooser::textChanged, this, &InterpreterDetailsWidget::changed);
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ QString toJSLiteral(const QVariant &val)
|
|||||||
{
|
{
|
||||||
if (!val.isValid())
|
if (!val.isValid())
|
||||||
return QString("undefined");
|
return QString("undefined");
|
||||||
if (val.type() == QVariant::List || val.type() == QVariant::StringList) {
|
if (val.typeId() == QVariant::List || val.typeId() == QVariant::StringList) {
|
||||||
QString res;
|
QString res;
|
||||||
const auto list = val.toList();
|
const auto list = val.toList();
|
||||||
for (const QVariant &child : list) {
|
for (const QVariant &child : list) {
|
||||||
@@ -71,7 +71,7 @@ QString toJSLiteral(const QVariant &val)
|
|||||||
res.append(']');
|
res.append(']');
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
if (val.type() == QVariant::Map) {
|
if (val.typeId() == QVariant::Map) {
|
||||||
const QVariantMap &vm = val.toMap();
|
const QVariantMap &vm = val.toMap();
|
||||||
QString str("{");
|
QString str("{");
|
||||||
for (auto it = vm.begin(); it != vm.end(); ++it) {
|
for (auto it = vm.begin(); it != vm.end(); ++it) {
|
||||||
@@ -82,7 +82,7 @@ QString toJSLiteral(const QVariant &val)
|
|||||||
str += '}';
|
str += '}';
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
if (val.type() == QVariant::Bool)
|
if (val.typeId() == QVariant::Bool)
|
||||||
return toJSLiteral(val.toBool());
|
return toJSLiteral(val.toBool());
|
||||||
if (val.canConvert(QVariant::String))
|
if (val.canConvert(QVariant::String))
|
||||||
return toJSLiteral(val.toString());
|
return toJSLiteral(val.toString());
|
||||||
|
|||||||
@@ -952,7 +952,7 @@ extend_qtc_plugin(QmlDesigner
|
|||||||
SOURCES_PREFIX components/richtexteditor
|
SOURCES_PREFIX components/richtexteditor
|
||||||
SOURCES
|
SOURCES
|
||||||
hyperlinkdialog.cpp hyperlinkdialog.h hyperlinkdialog.ui
|
hyperlinkdialog.cpp hyperlinkdialog.h hyperlinkdialog.ui
|
||||||
richtexteditor.cpp richtexteditor.h hyperlinkdialog.ui
|
richtexteditor.cpp richtexteditor.h
|
||||||
richtexteditorproxy.cpp richtexteditorproxy.h
|
richtexteditorproxy.cpp richtexteditorproxy.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#include "bakelightsconnectionmanager.h"
|
#include "bakelightsconnectionmanager.h"
|
||||||
|
|
||||||
|
#include "qmldesignertr.h"
|
||||||
|
|
||||||
#include <puppettocreatorcommand.h>
|
#include <puppettocreatorcommand.h>
|
||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
@@ -34,10 +36,10 @@ void BakeLightsConnectionManager::dispatchCommand(const QVariant &command,
|
|||||||
m_progressCallback(cmd.data().toString());
|
m_progressCallback(cmd.data().toString());
|
||||||
break;
|
break;
|
||||||
case PuppetToCreatorCommand::BakeLightsAborted:
|
case PuppetToCreatorCommand::BakeLightsAborted:
|
||||||
m_finishedCallback(tr("Baking aborted: %1").arg(cmd.data().toString()));
|
m_finishedCallback(Tr::tr("Baking aborted: %1").arg(cmd.data().toString()));
|
||||||
break;
|
break;
|
||||||
case PuppetToCreatorCommand::BakeLightsFinished:
|
case PuppetToCreatorCommand::BakeLightsFinished:
|
||||||
m_finishedCallback(tr("Baking finished!"));
|
m_finishedCallback(Tr::tr("Baking finished!"));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -2,9 +2,11 @@
|
|||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
#include "richtexteditor.h"
|
#include "richtexteditor.h"
|
||||||
#include "ui_richtexteditor.h"
|
|
||||||
#include "hyperlinkdialog.h"
|
#include "hyperlinkdialog.h"
|
||||||
|
|
||||||
|
#include <utils/layoutbuilder.h>
|
||||||
|
#include <utils/stylehelper.h>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
@@ -19,8 +21,9 @@
|
|||||||
#include <QTextTableFormat>
|
#include <QTextTableFormat>
|
||||||
#include <QToolButton>
|
#include <QToolButton>
|
||||||
#include <QWidgetAction>
|
#include <QWidgetAction>
|
||||||
|
#include <QApplication>
|
||||||
#include <utils/stylehelper.h>
|
#include <QTextEdit>
|
||||||
|
#include <QToolBar>
|
||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
@@ -89,20 +92,41 @@ static QPixmap drawColorBox(const QColor& color, const QSize& size, int borderWi
|
|||||||
|
|
||||||
RichTextEditor::RichTextEditor(QWidget *parent)
|
RichTextEditor::RichTextEditor(QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
, ui(new Ui::RichTextEditor)
|
|
||||||
, m_linkDialog(new HyperlinkDialog(this))
|
, m_linkDialog(new HyperlinkDialog(this))
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
|
||||||
ui->textEdit->setTextInteractionFlags(Qt::TextEditorInteraction | Qt::LinksAccessibleByMouse);
|
resize(428, 283);
|
||||||
ui->tableBar->setVisible(false);
|
QSizePolicy pol(QSizePolicy::Preferred, QSizePolicy::Expanding);
|
||||||
|
pol.setHorizontalStretch(0);
|
||||||
|
pol.setVerticalStretch(5);
|
||||||
|
pol.setHeightForWidth(sizePolicy().hasHeightForWidth());
|
||||||
|
setSizePolicy(pol);
|
||||||
|
|
||||||
|
m_toolBar = new QToolBar(this);
|
||||||
|
m_toolBar->setIconSize(QSize(20, 20));
|
||||||
|
|
||||||
|
m_tableBar = new QToolBar(this);
|
||||||
|
m_tableBar->setIconSize(QSize(20, 20));
|
||||||
|
|
||||||
|
m_textEdit = new QTextEdit(this);
|
||||||
|
m_textEdit->setTextInteractionFlags(Qt::TextEditorInteraction | Qt::LinksAccessibleByMouse);
|
||||||
|
|
||||||
|
using namespace Layouting;
|
||||||
|
Column {
|
||||||
|
m_toolBar,
|
||||||
|
m_tableBar,
|
||||||
|
m_textEdit
|
||||||
|
}.attachTo(this);
|
||||||
|
|
||||||
|
m_tableBar->setVisible(false);
|
||||||
|
|
||||||
const QColor backColor = Theme::getColor(Theme::DSpanelBackground);
|
const QColor backColor = Theme::getColor(Theme::DSpanelBackground);
|
||||||
|
|
||||||
const QString toolBarStyleSheet =
|
const QString toolBarStyleSheet =
|
||||||
QString("QToolBar { background-color: %1; border-width: 1px }").arg(backColor.name());
|
QString("QToolBar { background-color: %1; border-width: 1px }").arg(backColor.name());
|
||||||
|
|
||||||
ui->toolBar->setStyleSheet(toolBarStyleSheet);
|
m_toolBar->setStyleSheet(toolBarStyleSheet);
|
||||||
ui->tableBar->setStyleSheet(toolBarStyleSheet);
|
m_tableBar->setStyleSheet(toolBarStyleSheet);
|
||||||
|
|
||||||
setupEditActions();
|
setupEditActions();
|
||||||
setupTextActions();
|
setupTextActions();
|
||||||
@@ -113,16 +137,16 @@ RichTextEditor::RichTextEditor(QWidget *parent)
|
|||||||
setupFontActions();
|
setupFontActions();
|
||||||
setupTableActions();
|
setupTableActions();
|
||||||
|
|
||||||
connect(ui->textEdit, &QTextEdit::currentCharFormatChanged,
|
connect(m_textEdit, &QTextEdit::currentCharFormatChanged,
|
||||||
this, &RichTextEditor::currentCharFormatChanged);
|
this, &RichTextEditor::currentCharFormatChanged);
|
||||||
connect(ui->textEdit, &QTextEdit::cursorPositionChanged,
|
connect(m_textEdit, &QTextEdit::cursorPositionChanged,
|
||||||
this, &RichTextEditor::cursorPositionChanged);
|
this, &RichTextEditor::cursorPositionChanged);
|
||||||
connect(ui->textEdit, &QTextEdit::textChanged,
|
connect(m_textEdit, &QTextEdit::textChanged,
|
||||||
this, &RichTextEditor::onTextChanged);
|
this, &RichTextEditor::onTextChanged);
|
||||||
connect(m_linkDialog, &QDialog::accepted, [this]() {
|
connect(m_linkDialog, &QDialog::accepted, [this]() {
|
||||||
QTextCharFormat oldFormat = ui->textEdit->textCursor().charFormat();
|
QTextCharFormat oldFormat = m_textEdit->textCursor().charFormat();
|
||||||
|
|
||||||
QTextCursor tcursor = ui->textEdit->textCursor();
|
QTextCursor tcursor = m_textEdit->textCursor();
|
||||||
QTextCharFormat charFormat = tcursor.charFormat();
|
QTextCharFormat charFormat = tcursor.charFormat();
|
||||||
|
|
||||||
charFormat.setForeground(QApplication::palette().color(QPalette::Link));
|
charFormat.setForeground(QApplication::palette().color(QPalette::Link));
|
||||||
@@ -145,7 +169,7 @@ RichTextEditor::RichTextEditor(QWidget *parent)
|
|||||||
m_linkDialog->hide();
|
m_linkDialog->hide();
|
||||||
});
|
});
|
||||||
|
|
||||||
ui->textEdit->setFocus();
|
m_textEdit->setFocus();
|
||||||
m_linkDialog->hide();
|
m_linkDialog->hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,22 +179,22 @@ RichTextEditor::~RichTextEditor()
|
|||||||
|
|
||||||
void RichTextEditor::setPlainText(const QString &text)
|
void RichTextEditor::setPlainText(const QString &text)
|
||||||
{
|
{
|
||||||
ui->textEdit->setPlainText(text);
|
m_textEdit->setPlainText(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString RichTextEditor::plainText() const
|
QString RichTextEditor::plainText() const
|
||||||
{
|
{
|
||||||
return ui->textEdit->toPlainText();
|
return m_textEdit->toPlainText();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RichTextEditor::setRichText(const QString &text)
|
void RichTextEditor::setRichText(const QString &text)
|
||||||
{
|
{
|
||||||
ui->textEdit->setHtml(text);
|
m_textEdit->setHtml(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RichTextEditor::setTabChangesFocus(bool change)
|
void RichTextEditor::setTabChangesFocus(bool change)
|
||||||
{
|
{
|
||||||
ui->textEdit->setTabChangesFocus(change);
|
m_textEdit->setTabChangesFocus(change);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RichTextEditor::setImageActionVisible(bool change)
|
void RichTextEditor::setImageActionVisible(bool change)
|
||||||
@@ -180,7 +204,7 @@ void RichTextEditor::setImageActionVisible(bool change)
|
|||||||
|
|
||||||
void RichTextEditor::setDocumentBaseUrl(const QUrl& url)
|
void RichTextEditor::setDocumentBaseUrl(const QUrl& url)
|
||||||
{
|
{
|
||||||
ui->textEdit->document()->setBaseUrl(url);
|
m_textEdit->document()->setBaseUrl(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
QIcon RichTextEditor::getIcon(Theme::Icon icon)
|
QIcon RichTextEditor::getIcon(Theme::Icon icon)
|
||||||
@@ -194,7 +218,7 @@ QIcon RichTextEditor::getIcon(Theme::Icon icon)
|
|||||||
|
|
||||||
QString RichTextEditor::richText() const
|
QString RichTextEditor::richText() const
|
||||||
{
|
{
|
||||||
return ui->textEdit->toHtml();
|
return m_textEdit->toHtml();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RichTextEditor::currentCharFormatChanged(const QTextCharFormat &format)
|
void RichTextEditor::currentCharFormatChanged(const QTextCharFormat &format)
|
||||||
@@ -205,9 +229,9 @@ void RichTextEditor::currentCharFormatChanged(const QTextCharFormat &format)
|
|||||||
|
|
||||||
void RichTextEditor::cursorPositionChanged()
|
void RichTextEditor::cursorPositionChanged()
|
||||||
{
|
{
|
||||||
alignmentChanged(ui->textEdit->alignment());
|
alignmentChanged(m_textEdit->alignment());
|
||||||
styleChanged(ui->textEdit->textCursor());
|
styleChanged(m_textEdit->textCursor());
|
||||||
tableChanged(ui->textEdit->textCursor());
|
tableChanged(m_textEdit->textCursor());
|
||||||
}
|
}
|
||||||
|
|
||||||
void RichTextEditor::onTextChanged() {
|
void RichTextEditor::onTextChanged() {
|
||||||
@@ -216,11 +240,11 @@ void RichTextEditor::onTextChanged() {
|
|||||||
|
|
||||||
void RichTextEditor::mergeFormatOnWordOrSelection(const QTextCharFormat &format)
|
void RichTextEditor::mergeFormatOnWordOrSelection(const QTextCharFormat &format)
|
||||||
{
|
{
|
||||||
QTextCursor cursor = ui->textEdit->textCursor();
|
QTextCursor cursor = m_textEdit->textCursor();
|
||||||
if (!cursor.hasSelection())
|
if (!cursor.hasSelection())
|
||||||
cursor.select(QTextCursor::WordUnderCursor);
|
cursor.select(QTextCursor::WordUnderCursor);
|
||||||
cursor.mergeCharFormat(format);
|
cursor.mergeCharFormat(format);
|
||||||
ui->textEdit->mergeCurrentCharFormat(format);
|
m_textEdit->mergeCurrentCharFormat(format);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RichTextEditor::fontChanged(const QFont &f)
|
void RichTextEditor::fontChanged(const QFont &f)
|
||||||
@@ -243,7 +267,7 @@ void RichTextEditor::fontChanged(const QFont &f)
|
|||||||
|
|
||||||
void RichTextEditor::colorChanged(const QColor &c)
|
void RichTextEditor::colorChanged(const QColor &c)
|
||||||
{
|
{
|
||||||
QPixmap colorBox(drawColorBox(c, ui->tableBar->iconSize()));
|
QPixmap colorBox(drawColorBox(c, m_tableBar->iconSize()));
|
||||||
m_actionTextColor->setIcon(colorBox);
|
m_actionTextColor->setIcon(colorBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,7 +317,7 @@ void RichTextEditor::tableChanged(const QTextCursor &cursor)
|
|||||||
|
|
||||||
if (currentTable) {
|
if (currentTable) {
|
||||||
m_actionTableSettings->setChecked(true);
|
m_actionTableSettings->setChecked(true);
|
||||||
ui->tableBar->setVisible(true);
|
m_tableBar->setVisible(true);
|
||||||
|
|
||||||
setTableActionsActive(true);
|
setTableActionsActive(true);
|
||||||
}
|
}
|
||||||
@@ -305,27 +329,27 @@ void RichTextEditor::tableChanged(const QTextCursor &cursor)
|
|||||||
void RichTextEditor::setupEditActions()
|
void RichTextEditor::setupEditActions()
|
||||||
{
|
{
|
||||||
const QIcon undoIcon(getIcon(Theme::Icon::undo));
|
const QIcon undoIcon(getIcon(Theme::Icon::undo));
|
||||||
QAction *actionUndo = ui->toolBar->addAction(undoIcon, tr("&Undo"), ui->textEdit, &QTextEdit::undo);
|
QAction *actionUndo = m_toolBar->addAction(undoIcon, tr("&Undo"), m_textEdit, &QTextEdit::undo);
|
||||||
actionUndo->setShortcut(QKeySequence::Undo);
|
actionUndo->setShortcut(QKeySequence::Undo);
|
||||||
connect(ui->textEdit->document(), &QTextDocument::undoAvailable,
|
connect(m_textEdit->document(), &QTextDocument::undoAvailable,
|
||||||
actionUndo, &QAction::setEnabled);
|
actionUndo, &QAction::setEnabled);
|
||||||
|
|
||||||
const QIcon redoIcon(getIcon(Theme::Icon::redo));
|
const QIcon redoIcon(getIcon(Theme::Icon::redo));
|
||||||
QAction *actionRedo = ui->toolBar->addAction(redoIcon, tr("&Redo"), ui->textEdit, &QTextEdit::redo);
|
QAction *actionRedo = m_toolBar->addAction(redoIcon, tr("&Redo"), m_textEdit, &QTextEdit::redo);
|
||||||
actionRedo->setShortcut(QKeySequence::Redo);
|
actionRedo->setShortcut(QKeySequence::Redo);
|
||||||
connect(ui->textEdit->document(), &QTextDocument::redoAvailable,
|
connect(m_textEdit->document(), &QTextDocument::redoAvailable,
|
||||||
actionRedo, &QAction::setEnabled);
|
actionRedo, &QAction::setEnabled);
|
||||||
|
|
||||||
actionUndo->setEnabled(ui->textEdit->document()->isUndoAvailable());
|
actionUndo->setEnabled(m_textEdit->document()->isUndoAvailable());
|
||||||
actionRedo->setEnabled(ui->textEdit->document()->isRedoAvailable());
|
actionRedo->setEnabled(m_textEdit->document()->isRedoAvailable());
|
||||||
|
|
||||||
ui->toolBar->addSeparator();
|
m_toolBar->addSeparator();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RichTextEditor::setupTextActions()
|
void RichTextEditor::setupTextActions()
|
||||||
{
|
{
|
||||||
const QIcon boldIcon(getIcon(Theme::Icon::fontStyleBold));
|
const QIcon boldIcon(getIcon(Theme::Icon::fontStyleBold));
|
||||||
m_actionTextBold = ui->toolBar->addAction(boldIcon, tr("&Bold"),
|
m_actionTextBold = m_toolBar->addAction(boldIcon, tr("&Bold"),
|
||||||
[this](bool checked) {
|
[this](bool checked) {
|
||||||
QTextCharFormat fmt;
|
QTextCharFormat fmt;
|
||||||
fmt.setFontWeight(checked ? QFont::Bold : QFont::Normal);
|
fmt.setFontWeight(checked ? QFont::Bold : QFont::Normal);
|
||||||
@@ -338,7 +362,7 @@ void RichTextEditor::setupTextActions()
|
|||||||
m_actionTextBold->setCheckable(true);
|
m_actionTextBold->setCheckable(true);
|
||||||
|
|
||||||
const QIcon italicIcon(getIcon(Theme::Icon::fontStyleItalic));
|
const QIcon italicIcon(getIcon(Theme::Icon::fontStyleItalic));
|
||||||
m_actionTextItalic = ui->toolBar->addAction(italicIcon, tr("&Italic"),
|
m_actionTextItalic = m_toolBar->addAction(italicIcon, tr("&Italic"),
|
||||||
[this](bool checked) {
|
[this](bool checked) {
|
||||||
QTextCharFormat fmt;
|
QTextCharFormat fmt;
|
||||||
fmt.setFontItalic(checked);
|
fmt.setFontItalic(checked);
|
||||||
@@ -351,7 +375,7 @@ void RichTextEditor::setupTextActions()
|
|||||||
m_actionTextItalic->setCheckable(true);
|
m_actionTextItalic->setCheckable(true);
|
||||||
|
|
||||||
const QIcon underlineIcon(getIcon(Theme::Icon::fontStyleUnderline));
|
const QIcon underlineIcon(getIcon(Theme::Icon::fontStyleUnderline));
|
||||||
m_actionTextUnderline = ui->toolBar->addAction(underlineIcon, tr("&Underline"),
|
m_actionTextUnderline = m_toolBar->addAction(underlineIcon, tr("&Underline"),
|
||||||
[this](bool checked) {
|
[this](bool checked) {
|
||||||
QTextCharFormat fmt;
|
QTextCharFormat fmt;
|
||||||
fmt.setFontUnderline(checked);
|
fmt.setFontUnderline(checked);
|
||||||
@@ -363,7 +387,7 @@ void RichTextEditor::setupTextActions()
|
|||||||
m_actionTextUnderline->setFont(underline);
|
m_actionTextUnderline->setFont(underline);
|
||||||
m_actionTextUnderline->setCheckable(true);
|
m_actionTextUnderline->setCheckable(true);
|
||||||
|
|
||||||
ui->toolBar->addSeparator();
|
m_toolBar->addSeparator();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RichTextEditor::setupImageActions()
|
void RichTextEditor::setupImageActions()
|
||||||
@@ -379,12 +403,12 @@ void RichTextEditor::setupImageActions()
|
|||||||
for (QString& filePath : files) {
|
for (QString& filePath : files) {
|
||||||
emit insertingImage(filePath);
|
emit insertingImage(filePath);
|
||||||
|
|
||||||
ui->textEdit->insertHtml("<img src=\"" + filePath + "\" />");
|
m_textEdit->insertHtml("<img src=\"" + filePath + "\" />");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
m_actionImage = ui->toolBar
|
m_actionImage = m_toolBar
|
||||||
->addAction(getIcon(Theme::Icon::addFile), tr("Insert &Image"), insertImage);
|
->addAction(getIcon(Theme::Icon::addFile), tr("Insert &Image"), insertImage);
|
||||||
|
|
||||||
setImageActionVisible(false);
|
setImageActionVisible(false);
|
||||||
@@ -393,8 +417,8 @@ void RichTextEditor::setupImageActions()
|
|||||||
void RichTextEditor::setupHyperlinkActions()
|
void RichTextEditor::setupHyperlinkActions()
|
||||||
{
|
{
|
||||||
const QIcon bulletIcon(getIcon(Theme::Icon::actionIconBinding));
|
const QIcon bulletIcon(getIcon(Theme::Icon::actionIconBinding));
|
||||||
m_actionHyperlink = ui->toolBar->addAction(bulletIcon, tr("Hyperlink Settings"), [this]() {
|
m_actionHyperlink = m_toolBar->addAction(bulletIcon, tr("Hyperlink Settings"), [this]() {
|
||||||
QTextCursor cursor = ui->textEdit->textCursor();
|
QTextCursor cursor = m_textEdit->textCursor();
|
||||||
QTextCharFormat linkFormat = cursor.charFormat();
|
QTextCharFormat linkFormat = cursor.charFormat();
|
||||||
if (linkFormat.isAnchor()) {
|
if (linkFormat.isAnchor()) {
|
||||||
m_linkDialog->setLink(linkFormat.anchorHref());
|
m_linkDialog->setLink(linkFormat.anchorHref());
|
||||||
@@ -410,37 +434,37 @@ void RichTextEditor::setupHyperlinkActions()
|
|||||||
});
|
});
|
||||||
m_actionHyperlink->setCheckable(false);
|
m_actionHyperlink->setCheckable(false);
|
||||||
|
|
||||||
ui->toolBar->addSeparator();
|
m_toolBar->addSeparator();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RichTextEditor::setupAlignActions()
|
void RichTextEditor::setupAlignActions()
|
||||||
{
|
{
|
||||||
const QIcon leftIcon(getIcon(Theme::Icon::textAlignLeft));
|
const QIcon leftIcon(getIcon(Theme::Icon::textAlignLeft));
|
||||||
m_actionAlignLeft = ui->toolBar->addAction(leftIcon, tr("&Left"), [this]() { ui->textEdit->setAlignment(Qt::AlignLeft | Qt::AlignAbsolute); });
|
m_actionAlignLeft = m_toolBar->addAction(leftIcon, tr("&Left"), [this]() { m_textEdit->setAlignment(Qt::AlignLeft | Qt::AlignAbsolute); });
|
||||||
m_actionAlignLeft->setShortcut(Qt::CTRL | Qt::Key_L);
|
m_actionAlignLeft->setShortcut(Qt::CTRL | Qt::Key_L);
|
||||||
m_actionAlignLeft->setCheckable(true);
|
m_actionAlignLeft->setCheckable(true);
|
||||||
m_actionAlignLeft->setPriority(QAction::LowPriority);
|
m_actionAlignLeft->setPriority(QAction::LowPriority);
|
||||||
|
|
||||||
const QIcon centerIcon(getIcon(Theme::Icon::textAlignCenter));
|
const QIcon centerIcon(getIcon(Theme::Icon::textAlignCenter));
|
||||||
m_actionAlignCenter = ui->toolBar->addAction(centerIcon, tr("C&enter"), [this]() { ui->textEdit->setAlignment(Qt::AlignHCenter); });
|
m_actionAlignCenter = m_toolBar->addAction(centerIcon, tr("C&enter"), [this]() { m_textEdit->setAlignment(Qt::AlignHCenter); });
|
||||||
m_actionAlignCenter->setShortcut(Qt::CTRL | Qt::Key_E);
|
m_actionAlignCenter->setShortcut(Qt::CTRL | Qt::Key_E);
|
||||||
m_actionAlignCenter->setCheckable(true);
|
m_actionAlignCenter->setCheckable(true);
|
||||||
m_actionAlignCenter->setPriority(QAction::LowPriority);
|
m_actionAlignCenter->setPriority(QAction::LowPriority);
|
||||||
|
|
||||||
const QIcon rightIcon(getIcon(Theme::Icon::textAlignRight));
|
const QIcon rightIcon(getIcon(Theme::Icon::textAlignRight));
|
||||||
m_actionAlignRight = ui->toolBar->addAction(rightIcon, tr("&Right"), [this]() { ui->textEdit->setAlignment(Qt::AlignRight | Qt::AlignAbsolute); });
|
m_actionAlignRight = m_toolBar->addAction(rightIcon, tr("&Right"), [this]() { m_textEdit->setAlignment(Qt::AlignRight | Qt::AlignAbsolute); });
|
||||||
m_actionAlignRight->setShortcut(Qt::CTRL | Qt::Key_R);
|
m_actionAlignRight->setShortcut(Qt::CTRL | Qt::Key_R);
|
||||||
m_actionAlignRight->setCheckable(true);
|
m_actionAlignRight->setCheckable(true);
|
||||||
m_actionAlignRight->setPriority(QAction::LowPriority);
|
m_actionAlignRight->setPriority(QAction::LowPriority);
|
||||||
|
|
||||||
const QIcon fillIcon(getIcon(Theme::Icon::textFullJustification));
|
const QIcon fillIcon(getIcon(Theme::Icon::textFullJustification));
|
||||||
m_actionAlignJustify = ui->toolBar->addAction(fillIcon, tr("&Justify"), [this]() { ui->textEdit->setAlignment(Qt::AlignJustify); });
|
m_actionAlignJustify = m_toolBar->addAction(fillIcon, tr("&Justify"), [this]() { m_textEdit->setAlignment(Qt::AlignJustify); });
|
||||||
m_actionAlignJustify->setShortcut(Qt::CTRL | Qt::Key_J);
|
m_actionAlignJustify->setShortcut(Qt::CTRL | Qt::Key_J);
|
||||||
m_actionAlignJustify->setCheckable(true);
|
m_actionAlignJustify->setCheckable(true);
|
||||||
m_actionAlignJustify->setPriority(QAction::LowPriority);
|
m_actionAlignJustify->setPriority(QAction::LowPriority);
|
||||||
|
|
||||||
// Make sure the alignLeft is always left of the alignRight
|
// Make sure the alignLeft is always left of the alignRight
|
||||||
QActionGroup *alignGroup = new QActionGroup(ui->toolBar);
|
QActionGroup *alignGroup = new QActionGroup(m_toolBar);
|
||||||
|
|
||||||
if (QApplication::isLeftToRight()) {
|
if (QApplication::isLeftToRight()) {
|
||||||
alignGroup->addAction(m_actionAlignLeft);
|
alignGroup->addAction(m_actionAlignLeft);
|
||||||
@@ -453,15 +477,15 @@ void RichTextEditor::setupAlignActions()
|
|||||||
}
|
}
|
||||||
alignGroup->addAction(m_actionAlignJustify);
|
alignGroup->addAction(m_actionAlignJustify);
|
||||||
|
|
||||||
ui->toolBar->addActions(alignGroup->actions());
|
m_toolBar->addActions(alignGroup->actions());
|
||||||
|
|
||||||
ui->toolBar->addSeparator();
|
m_toolBar->addSeparator();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RichTextEditor::setupListActions()
|
void RichTextEditor::setupListActions()
|
||||||
{
|
{
|
||||||
const QIcon bulletIcon(getIcon(Theme::Icon::textBulletList));
|
const QIcon bulletIcon(getIcon(Theme::Icon::textBulletList));
|
||||||
m_actionBulletList = ui->toolBar->addAction(bulletIcon, tr("Bullet List"), [this](bool checked) {
|
m_actionBulletList = m_toolBar->addAction(bulletIcon, tr("Bullet List"), [this](bool checked) {
|
||||||
if (checked) {
|
if (checked) {
|
||||||
m_actionNumberedList->setChecked(false);
|
m_actionNumberedList->setChecked(false);
|
||||||
textStyle(QTextListFormat::ListDisc);
|
textStyle(QTextListFormat::ListDisc);
|
||||||
@@ -473,7 +497,7 @@ void RichTextEditor::setupListActions()
|
|||||||
m_actionBulletList->setCheckable(true);
|
m_actionBulletList->setCheckable(true);
|
||||||
|
|
||||||
const QIcon numberedIcon(getIcon(Theme::Icon::textNumberedList));
|
const QIcon numberedIcon(getIcon(Theme::Icon::textNumberedList));
|
||||||
m_actionNumberedList = ui->toolBar->addAction(numberedIcon, tr("Numbered List"), [this](bool checked) {
|
m_actionNumberedList = m_toolBar->addAction(numberedIcon, tr("Numbered List"), [this](bool checked) {
|
||||||
if (checked) {
|
if (checked) {
|
||||||
m_actionBulletList->setChecked(false);
|
m_actionBulletList->setChecked(false);
|
||||||
textStyle(QTextListFormat::ListDecimal);
|
textStyle(QTextListFormat::ListDecimal);
|
||||||
@@ -484,15 +508,15 @@ void RichTextEditor::setupListActions()
|
|||||||
});
|
});
|
||||||
m_actionNumberedList->setCheckable(true);
|
m_actionNumberedList->setCheckable(true);
|
||||||
|
|
||||||
ui->toolBar->addSeparator();
|
m_toolBar->addSeparator();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RichTextEditor::setupFontActions()
|
void RichTextEditor::setupFontActions()
|
||||||
{
|
{
|
||||||
QPixmap colorBox(drawColorBox(ui->textEdit->textColor(), ui->tableBar->iconSize()));
|
QPixmap colorBox(drawColorBox(m_textEdit->textColor(), m_tableBar->iconSize()));
|
||||||
|
|
||||||
m_actionTextColor = ui->toolBar->addAction(colorBox, tr("&Color..."), [this]() {
|
m_actionTextColor = m_toolBar->addAction(colorBox, tr("&Color..."), [this]() {
|
||||||
QColor col = QColorDialog::getColor(ui->textEdit->textColor(), this);
|
QColor col = QColorDialog::getColor(m_textEdit->textColor(), this);
|
||||||
if (!col.isValid())
|
if (!col.isValid())
|
||||||
return;
|
return;
|
||||||
QTextCharFormat fmt;
|
QTextCharFormat fmt;
|
||||||
@@ -505,7 +529,7 @@ void RichTextEditor::setupFontActions()
|
|||||||
m_fontNameAction->setInitializer([this](QFontComboBox *w) {
|
m_fontNameAction->setInitializer([this](QFontComboBox *w) {
|
||||||
if (!w) return;
|
if (!w) return;
|
||||||
|
|
||||||
w->setCurrentIndex(w->findText(ui->textEdit->currentCharFormat().font().family()));
|
w->setCurrentIndex(w->findText(m_textEdit->currentCharFormat().font().family()));
|
||||||
connect(w, &QComboBox::textActivated, [this](const QString &f) {
|
connect(w, &QComboBox::textActivated, [this](const QString &f) {
|
||||||
QTextCharFormat fmt;
|
QTextCharFormat fmt;
|
||||||
fmt.setFontFamily(f);
|
fmt.setFontFamily(f);
|
||||||
@@ -514,7 +538,7 @@ void RichTextEditor::setupFontActions()
|
|||||||
});
|
});
|
||||||
|
|
||||||
m_fontNameAction->setDefaultWidget(new QFontComboBox);
|
m_fontNameAction->setDefaultWidget(new QFontComboBox);
|
||||||
ui->toolBar->addAction(m_fontNameAction);
|
m_toolBar->addAction(m_fontNameAction);
|
||||||
|
|
||||||
m_fontSizeAction = new FontWidgetActions<QComboBox>(this);
|
m_fontSizeAction = new FontWidgetActions<QComboBox>(this);
|
||||||
m_fontSizeAction->setInitializer([this](QComboBox *w) {
|
m_fontSizeAction->setInitializer([this](QComboBox *w) {
|
||||||
@@ -525,7 +549,7 @@ void RichTextEditor::setupFontActions()
|
|||||||
const QList<int> standardSizes = QFontDatabase::standardSizes();
|
const QList<int> standardSizes = QFontDatabase::standardSizes();
|
||||||
for (const int size : standardSizes)
|
for (const int size : standardSizes)
|
||||||
w->addItem(QString::number(size));
|
w->addItem(QString::number(size));
|
||||||
w->setCurrentText(QString::number(ui->textEdit->currentCharFormat().font().pointSize()));
|
w->setCurrentText(QString::number(m_textEdit->currentCharFormat().font().pointSize()));
|
||||||
connect(w, &QComboBox::textActivated, [this](const QString &p) {
|
connect(w, &QComboBox::textActivated, [this](const QString &p) {
|
||||||
qreal pointSize = p.toDouble();
|
qreal pointSize = p.toDouble();
|
||||||
if (pointSize > 0.0) {
|
if (pointSize > 0.0) {
|
||||||
@@ -537,17 +561,17 @@ void RichTextEditor::setupFontActions()
|
|||||||
});
|
});
|
||||||
|
|
||||||
m_fontSizeAction->setDefaultWidget(new QComboBox);
|
m_fontSizeAction->setDefaultWidget(new QComboBox);
|
||||||
ui->toolBar->addAction(m_fontSizeAction);
|
m_toolBar->addAction(m_fontSizeAction);
|
||||||
|
|
||||||
|
|
||||||
ui->toolBar->addSeparator();
|
m_toolBar->addSeparator();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RichTextEditor::setupTableActions()
|
void RichTextEditor::setupTableActions()
|
||||||
{
|
{
|
||||||
const QIcon tableIcon(getIcon(Theme::Icon::addTable));
|
const QIcon tableIcon(getIcon(Theme::Icon::addTable));
|
||||||
m_actionTableSettings = ui->toolBar->addAction(tableIcon, tr("&Table Settings"), [this](bool checked) {
|
m_actionTableSettings = m_toolBar->addAction(tableIcon, tr("&Table Settings"), [this](bool checked) {
|
||||||
ui->tableBar->setVisible(checked);
|
m_tableBar->setVisible(checked);
|
||||||
});
|
});
|
||||||
m_actionTableSettings->setShortcut(Qt::CTRL | Qt::Key_T);
|
m_actionTableSettings->setShortcut(Qt::CTRL | Qt::Key_T);
|
||||||
m_actionTableSettings->setCheckable(true);
|
m_actionTableSettings->setCheckable(true);
|
||||||
@@ -556,8 +580,8 @@ void RichTextEditor::setupTableActions()
|
|||||||
//table bar:
|
//table bar:
|
||||||
|
|
||||||
const QIcon createTableIcon(getIcon(Theme::Icon::addTable));
|
const QIcon createTableIcon(getIcon(Theme::Icon::addTable));
|
||||||
m_actionCreateTable = ui->tableBar->addAction(createTableIcon, tr("Create Table"), [this]() {
|
m_actionCreateTable = m_tableBar->addAction(createTableIcon, tr("Create Table"), [this]() {
|
||||||
QTextCursor cursor = ui->textEdit->textCursor();
|
QTextCursor cursor = m_textEdit->textCursor();
|
||||||
cursorEditBlock(cursor, [&] () {
|
cursorEditBlock(cursor, [&] () {
|
||||||
//format table cells to look a bit better:
|
//format table cells to look a bit better:
|
||||||
QTextTableFormat tableFormat;
|
QTextTableFormat tableFormat;
|
||||||
@@ -568,15 +592,15 @@ void RichTextEditor::setupTableActions()
|
|||||||
cursor.insertTable(1, 1, tableFormat);
|
cursor.insertTable(1, 1, tableFormat);
|
||||||
|
|
||||||
//move cursor into the first cell of the table:
|
//move cursor into the first cell of the table:
|
||||||
ui->textEdit->setTextCursor(cursor);
|
m_textEdit->setTextCursor(cursor);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
m_actionCreateTable->setCheckable(false);
|
m_actionCreateTable->setCheckable(false);
|
||||||
|
|
||||||
const QIcon removeTableIcon(getIcon(Theme::Icon::deleteTable));
|
const QIcon removeTableIcon(getIcon(Theme::Icon::deleteTable));
|
||||||
m_actionRemoveTable = ui->tableBar->addAction(removeTableIcon, tr("Remove Table"), [this]() {
|
m_actionRemoveTable = m_tableBar->addAction(removeTableIcon, tr("Remove Table"), [this]() {
|
||||||
QTextCursor cursor = ui->textEdit->textCursor();
|
QTextCursor cursor = m_textEdit->textCursor();
|
||||||
if (QTextTable *currentTable = ui->textEdit->textCursor().currentTable()) {
|
if (QTextTable *currentTable = m_textEdit->textCursor().currentTable()) {
|
||||||
cursorEditBlock(cursor, [&] () {
|
cursorEditBlock(cursor, [&] () {
|
||||||
currentTable->removeRows(0, currentTable->rows());
|
currentTable->removeRows(0, currentTable->rows());
|
||||||
});
|
});
|
||||||
@@ -584,12 +608,12 @@ void RichTextEditor::setupTableActions()
|
|||||||
});
|
});
|
||||||
m_actionRemoveTable->setCheckable(false);
|
m_actionRemoveTable->setCheckable(false);
|
||||||
|
|
||||||
ui->tableBar->addSeparator();
|
m_tableBar->addSeparator();
|
||||||
|
|
||||||
const QIcon addRowIcon(getIcon(Theme::Icon::addRowAfter)); //addRowAfter
|
const QIcon addRowIcon(getIcon(Theme::Icon::addRowAfter)); //addRowAfter
|
||||||
m_actionAddRow = ui->tableBar->addAction(addRowIcon, tr("Add Row"), [this]() {
|
m_actionAddRow = m_tableBar->addAction(addRowIcon, tr("Add Row"), [this]() {
|
||||||
QTextCursor cursor = ui->textEdit->textCursor();
|
QTextCursor cursor = m_textEdit->textCursor();
|
||||||
if (QTextTable *currentTable = ui->textEdit->textCursor().currentTable()) {
|
if (QTextTable *currentTable = m_textEdit->textCursor().currentTable()) {
|
||||||
cursorEditBlock(cursor, [&] () {
|
cursorEditBlock(cursor, [&] () {
|
||||||
currentTable->insertRows(currentTable->cellAt(cursor).row()+1, 1);
|
currentTable->insertRows(currentTable->cellAt(cursor).row()+1, 1);
|
||||||
});
|
});
|
||||||
@@ -598,9 +622,9 @@ void RichTextEditor::setupTableActions()
|
|||||||
m_actionAddRow->setCheckable(false);
|
m_actionAddRow->setCheckable(false);
|
||||||
|
|
||||||
const QIcon addColumnIcon(getIcon(Theme::Icon::addColumnAfter)); //addColumnAfter
|
const QIcon addColumnIcon(getIcon(Theme::Icon::addColumnAfter)); //addColumnAfter
|
||||||
m_actionAddColumn = ui->tableBar->addAction(addColumnIcon, tr("Add Column"), [this]() {
|
m_actionAddColumn = m_tableBar->addAction(addColumnIcon, tr("Add Column"), [this]() {
|
||||||
QTextCursor cursor = ui->textEdit->textCursor();
|
QTextCursor cursor = m_textEdit->textCursor();
|
||||||
if (QTextTable *currentTable = ui->textEdit->textCursor().currentTable()) {
|
if (QTextTable *currentTable = m_textEdit->textCursor().currentTable()) {
|
||||||
cursorEditBlock(cursor, [&] () {
|
cursorEditBlock(cursor, [&] () {
|
||||||
currentTable->insertColumns(currentTable->cellAt(cursor).column()+1, 1);
|
currentTable->insertColumns(currentTable->cellAt(cursor).column()+1, 1);
|
||||||
});
|
});
|
||||||
@@ -609,8 +633,8 @@ void RichTextEditor::setupTableActions()
|
|||||||
m_actionAddColumn->setCheckable(false);
|
m_actionAddColumn->setCheckable(false);
|
||||||
|
|
||||||
const QIcon removeRowIcon(getIcon(Theme::Icon::deleteRow));
|
const QIcon removeRowIcon(getIcon(Theme::Icon::deleteRow));
|
||||||
m_actionRemoveRow = ui->tableBar->addAction(removeRowIcon, tr("Remove Row"), [this]() {
|
m_actionRemoveRow = m_tableBar->addAction(removeRowIcon, tr("Remove Row"), [this]() {
|
||||||
QTextCursor cursor = ui->textEdit->textCursor();
|
QTextCursor cursor = m_textEdit->textCursor();
|
||||||
if (QTextTable *currentTable = cursor.currentTable()) {
|
if (QTextTable *currentTable = cursor.currentTable()) {
|
||||||
cursorEditBlock(cursor, [&] () {
|
cursorEditBlock(cursor, [&] () {
|
||||||
currentTable->insertColumns(currentTable->cellAt(cursor).column()+1, 1);
|
currentTable->insertColumns(currentTable->cellAt(cursor).column()+1, 1);
|
||||||
@@ -633,8 +657,8 @@ void RichTextEditor::setupTableActions()
|
|||||||
m_actionRemoveRow->setCheckable(false);
|
m_actionRemoveRow->setCheckable(false);
|
||||||
|
|
||||||
const QIcon removeColumnIcon(getIcon(Theme::Icon::deleteColumn));
|
const QIcon removeColumnIcon(getIcon(Theme::Icon::deleteColumn));
|
||||||
m_actionRemoveColumn = ui->tableBar->addAction(removeColumnIcon, tr("Remove Column"), [this]() {
|
m_actionRemoveColumn = m_tableBar->addAction(removeColumnIcon, tr("Remove Column"), [this]() {
|
||||||
QTextCursor cursor = ui->textEdit->textCursor();
|
QTextCursor cursor = m_textEdit->textCursor();
|
||||||
if (QTextTable *currentTable = cursor.currentTable()) {
|
if (QTextTable *currentTable = cursor.currentTable()) {
|
||||||
cursorEditBlock(cursor, [&] () {
|
cursorEditBlock(cursor, [&] () {
|
||||||
int firstRow = 0;
|
int firstRow = 0;
|
||||||
@@ -654,11 +678,11 @@ void RichTextEditor::setupTableActions()
|
|||||||
});
|
});
|
||||||
m_actionRemoveColumn->setCheckable(false);
|
m_actionRemoveColumn->setCheckable(false);
|
||||||
|
|
||||||
ui->tableBar->addSeparator();
|
m_tableBar->addSeparator();
|
||||||
|
|
||||||
const QIcon mergeCellsIcon(getIcon(Theme::Icon::mergeCells));
|
const QIcon mergeCellsIcon(getIcon(Theme::Icon::mergeCells));
|
||||||
m_actionMergeCells = ui->tableBar->addAction(mergeCellsIcon, tr("Merge Cells"), [this]() {
|
m_actionMergeCells = m_tableBar->addAction(mergeCellsIcon, tr("Merge Cells"), [this]() {
|
||||||
QTextCursor cursor = ui->textEdit->textCursor();
|
QTextCursor cursor = m_textEdit->textCursor();
|
||||||
if (QTextTable *currentTable = cursor.currentTable()) {
|
if (QTextTable *currentTable = cursor.currentTable()) {
|
||||||
if (cursor.hasSelection()) {
|
if (cursor.hasSelection()) {
|
||||||
cursorEditBlock(cursor, [&] () {
|
cursorEditBlock(cursor, [&] () {
|
||||||
@@ -670,8 +694,8 @@ void RichTextEditor::setupTableActions()
|
|||||||
m_actionMergeCells->setCheckable(false);
|
m_actionMergeCells->setCheckable(false);
|
||||||
|
|
||||||
const QIcon splitRowIcon(getIcon(Theme::Icon::splitRows));
|
const QIcon splitRowIcon(getIcon(Theme::Icon::splitRows));
|
||||||
m_actionSplitRow = ui->tableBar->addAction(splitRowIcon, tr("Split Row"), [this]() {
|
m_actionSplitRow = m_tableBar->addAction(splitRowIcon, tr("Split Row"), [this]() {
|
||||||
QTextCursor cursor = ui->textEdit->textCursor();
|
QTextCursor cursor = m_textEdit->textCursor();
|
||||||
if (QTextTable *currentTable = cursor.currentTable()) {
|
if (QTextTable *currentTable = cursor.currentTable()) {
|
||||||
cursorEditBlock(cursor, [&] () {
|
cursorEditBlock(cursor, [&] () {
|
||||||
currentTable->splitCell(currentTable->cellAt(cursor).row(),
|
currentTable->splitCell(currentTable->cellAt(cursor).row(),
|
||||||
@@ -683,8 +707,8 @@ void RichTextEditor::setupTableActions()
|
|||||||
m_actionSplitRow->setCheckable(false);
|
m_actionSplitRow->setCheckable(false);
|
||||||
|
|
||||||
const QIcon splitColumnIcon(getIcon(Theme::Icon::splitColumns));
|
const QIcon splitColumnIcon(getIcon(Theme::Icon::splitColumns));
|
||||||
m_actionSplitColumn = ui->tableBar->addAction(splitColumnIcon, tr("Split Column"), [this]() {
|
m_actionSplitColumn = m_tableBar->addAction(splitColumnIcon, tr("Split Column"), [this]() {
|
||||||
QTextCursor cursor = ui->textEdit->textCursor();
|
QTextCursor cursor = m_textEdit->textCursor();
|
||||||
if (QTextTable *currentTable = cursor.currentTable()) {
|
if (QTextTable *currentTable = cursor.currentTable()) {
|
||||||
cursorEditBlock(cursor, [&] () {
|
cursorEditBlock(cursor, [&] () {
|
||||||
currentTable->splitCell(currentTable->cellAt(cursor).row(),
|
currentTable->splitCell(currentTable->cellAt(cursor).row(),
|
||||||
@@ -698,7 +722,7 @@ void RichTextEditor::setupTableActions()
|
|||||||
|
|
||||||
void RichTextEditor::textStyle(QTextListFormat::Style style)
|
void RichTextEditor::textStyle(QTextListFormat::Style style)
|
||||||
{
|
{
|
||||||
QTextCursor cursor = ui->textEdit->textCursor();
|
QTextCursor cursor = m_textEdit->textCursor();
|
||||||
cursorEditBlock(cursor, [&] () {
|
cursorEditBlock(cursor, [&] () {
|
||||||
if (style != QTextListFormat::ListStyleUndefined) {
|
if (style != QTextListFormat::ListStyleUndefined) {
|
||||||
QTextBlockFormat blockFmt = cursor.blockFormat();
|
QTextBlockFormat blockFmt = cursor.blockFormat();
|
||||||
|
|||||||
@@ -5,21 +5,17 @@
|
|||||||
|
|
||||||
#include <theme.h>
|
#include <theme.h>
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
#include <QToolBar>
|
|
||||||
#include <QList>
|
|
||||||
#include <QTextCharFormat>
|
|
||||||
#include <QTextList>
|
|
||||||
#include <QFontComboBox>
|
#include <QFontComboBox>
|
||||||
#include <QWidgetAction>
|
#include <QList>
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
|
#include <QTextCharFormat>
|
||||||
|
#include <QTextEdit>
|
||||||
|
#include <QTextList>
|
||||||
|
#include <QToolBar>
|
||||||
|
#include <QWidgetAction>
|
||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
namespace Ui {
|
|
||||||
class RichTextEditor;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class>
|
template <class>
|
||||||
class FontWidgetActions;
|
class FontWidgetActions;
|
||||||
|
|
||||||
@@ -77,7 +73,10 @@ private:
|
|||||||
void setTableActionsActive(bool active); //switches between "has table/has no table" ui setup
|
void setTableActionsActive(bool active); //switches between "has table/has no table" ui setup
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QScopedPointer<Ui::RichTextEditor> ui;
|
QTextEdit *m_textEdit;
|
||||||
|
QToolBar *m_toolBar;
|
||||||
|
QToolBar *m_tableBar;
|
||||||
|
|
||||||
QPointer<HyperlinkDialog> m_linkDialog;
|
QPointer<HyperlinkDialog> m_linkDialog;
|
||||||
|
|
||||||
QAction *m_actionTextBold;
|
QAction *m_actionTextBold;
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>QmlDesigner::RichTextEditor</class>
|
|
||||||
<widget class="QWidget" name="QmlDesigner::RichTextEditor">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>428</width>
|
|
||||||
<height>283</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>5</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string notr="true">Form</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QToolBar" name="toolBar">
|
|
||||||
<property name="iconSize">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QToolBar" name="tableBar">
|
|
||||||
<property name="iconSize">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QTextEdit" name="textEdit"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<resources/>
|
|
||||||
<connections/>
|
|
||||||
</ui>
|
|
||||||
@@ -67,6 +67,28 @@ void QmlJsEditingSettings::set()
|
|||||||
toSettings(Core::ICore::settings());
|
toSettings(Core::ICore::settings());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QStringList intListToStringList(const QList<int> &list)
|
||||||
|
{
|
||||||
|
return Utils::transform(list, [](int v) { return QString::number(v); });
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<int> intListFromStringList(const QStringList &list)
|
||||||
|
{
|
||||||
|
return Utils::transform<QList<int> >(list, [](const QString &v) { return v.toInt(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
static QStringList defaultDisabledMessagesAsString()
|
||||||
|
{
|
||||||
|
static const QStringList result = intListToStringList(defaultDisabledMessages());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static QStringList defaultDisabledNonQuickUiAsString()
|
||||||
|
{
|
||||||
|
static const QStringList result = intListToStringList(defaultDisabledMessagesNonQuickUi());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void QmlJsEditingSettings::fromSettings(QSettings *settings)
|
void QmlJsEditingSettings::fromSettings(QSettings *settings)
|
||||||
{
|
{
|
||||||
settings->beginGroup(QmlJSEditor::Constants::SETTINGS_CATEGORY_QML);
|
settings->beginGroup(QmlJSEditor::Constants::SETTINGS_CATEGORY_QML);
|
||||||
@@ -84,14 +106,13 @@ void QmlJsEditingSettings::fromSettings(QSettings *settings)
|
|||||||
m_useCustomFormatCommand = settings->value(CUSTOM_COMMAND, QVariant(false)).toBool();
|
m_useCustomFormatCommand = settings->value(CUSTOM_COMMAND, QVariant(false)).toBool();
|
||||||
m_useCustomAnalyzer = settings->value(CUSTOM_ANALYZER, QVariant(false)).toBool();
|
m_useCustomAnalyzer = settings->value(CUSTOM_ANALYZER, QVariant(false)).toBool();
|
||||||
|
|
||||||
m_disabledMessages = Utils::transform<QSet>(
|
m_disabledMessages = Utils::toSet(
|
||||||
settings->value(DISABLED_MESSAGES,
|
intListFromStringList(settings->value(DISABLED_MESSAGES,
|
||||||
QVariant::fromValue(defaultDisabledMessages())).toList(),
|
defaultDisabledMessagesAsString()).toStringList()));
|
||||||
[](const QVariant &v){ return v.toInt(); });
|
|
||||||
m_disabledMessagesForNonQuickUi = Utils::transform<QSet>(
|
m_disabledMessagesForNonQuickUi = Utils::toSet(
|
||||||
settings->value(DISABLED_MESSAGES_NONQUICKUI,
|
intListFromStringList(settings->value(DISABLED_MESSAGES_NONQUICKUI,
|
||||||
QVariant::fromValue(defaultDisabledMessagesNonQuickUi())).toList(),
|
defaultDisabledNonQuickUiAsString()).toStringList()));
|
||||||
[](const QVariant &v) { return v.toInt(); });
|
|
||||||
|
|
||||||
settings->endGroup();
|
settings->endGroup();
|
||||||
}
|
}
|
||||||
@@ -122,12 +143,12 @@ void QmlJsEditingSettings::toSettings(QSettings *settings) const
|
|||||||
false);
|
false);
|
||||||
Utils::QtcSettings::setValueWithDefault(settings,
|
Utils::QtcSettings::setValueWithDefault(settings,
|
||||||
DISABLED_MESSAGES,
|
DISABLED_MESSAGES,
|
||||||
Utils::sorted(Utils::toList(m_disabledMessages)),
|
intListToStringList(Utils::sorted(Utils::toList(m_disabledMessages))),
|
||||||
defaultDisabledMessages());
|
defaultDisabledMessagesAsString());
|
||||||
Utils::QtcSettings::setValueWithDefault(settings,
|
Utils::QtcSettings::setValueWithDefault(settings,
|
||||||
DISABLED_MESSAGES_NONQUICKUI,
|
DISABLED_MESSAGES_NONQUICKUI,
|
||||||
Utils::sorted(Utils::toList(m_disabledMessagesForNonQuickUi)),
|
intListToStringList(Utils::sorted(Utils::toList(m_disabledMessagesForNonQuickUi))),
|
||||||
defaultDisabledMessagesNonQuickUi());
|
defaultDisabledNonQuickUiAsString());
|
||||||
settings->endGroup();
|
settings->endGroup();
|
||||||
QmllsSettingsManager::instance()->checkForChanges();
|
QmllsSettingsManager::instance()->checkForChanges();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -255,7 +255,7 @@ void QuickToolBar::setProperty(const QString &propertyName, const QVariant &valu
|
|||||||
{
|
{
|
||||||
|
|
||||||
QString stringValue = value.toString();
|
QString stringValue = value.toString();
|
||||||
if (value.type() == QVariant::Color)
|
if (value.typeId() == QVariant::Color)
|
||||||
stringValue = QLatin1Char('\"') + value.toString() + QLatin1Char('\"');
|
stringValue = QLatin1Char('\"') + value.toString() + QLatin1Char('\"');
|
||||||
|
|
||||||
if (cast<UiObjectDefinition*>(m_node) || cast<UiObjectBinding*>(m_node)) {
|
if (cast<UiObjectDefinition*>(m_node) || cast<UiObjectBinding*>(m_node)) {
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
#include "qmlbuildsystem.h"
|
#include "qmlbuildsystem.h"
|
||||||
|
|
||||||
#include "../qmlprojectconstants.h"
|
#include "../qmlprojectconstants.h"
|
||||||
|
#include "../qmlprojectmanagertr.h"
|
||||||
|
|
||||||
#include <QtCore5Compat/qtextcodec.h>
|
#include <QtCore5Compat/qtextcodec.h>
|
||||||
#include <qmljs/qmljsmodelmanagerinterface.h>
|
#include <qmljs/qmljsmodelmanagerinterface.h>
|
||||||
@@ -222,7 +224,7 @@ void QmlBuildSystem::parseProjectFiles()
|
|||||||
QString errorMessage;
|
QString errorMessage;
|
||||||
if (!reader.fetch(mainFilePath, &errorMessage)) {
|
if (!reader.fetch(mainFilePath, &errorMessage)) {
|
||||||
Core::MessageManager::writeFlashing(
|
Core::MessageManager::writeFlashing(
|
||||||
tr("Warning while loading project file %1.").arg(projectFilePath().toUserOutput()));
|
Tr::tr("Warning while loading project file %1.").arg(projectFilePath().toUserOutput()));
|
||||||
Core::MessageManager::writeSilently(errorMessage);
|
Core::MessageManager::writeSilently(errorMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -197,7 +197,8 @@ Tasks QmlProject::projectIssues(const Kit *k) const
|
|||||||
if (version->type() == QtSupport::Constants::DESKTOPQT) {
|
if (version->type() == QtSupport::Constants::DESKTOPQT) {
|
||||||
if (version->qmlRuntimeFilePath().isEmpty()) {
|
if (version->qmlRuntimeFilePath().isEmpty()) {
|
||||||
result.append(
|
result.append(
|
||||||
createProjectTask(Task::TaskType::Error, tr("Qt version has no QML utility.")));
|
createProjectTask(Task::TaskType::Error,
|
||||||
|
Tr::tr("Qt version has no QML utility.")));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Non-desktop Qt on a desktop device? We don't support that.
|
// Non-desktop Qt on a desktop device? We don't support that.
|
||||||
|
|||||||
@@ -498,7 +498,7 @@ public:
|
|||||||
|
|
||||||
auto l = new QHBoxLayout(this);
|
auto l = new QHBoxLayout(this);
|
||||||
for (const QnxTarget &target : config->m_targets) {
|
for (const QnxTarget &target : config->m_targets) {
|
||||||
auto button = new QPushButton(tr("Create Kit for %1").arg(target.cpuDir()));
|
auto button = new QPushButton(Tr::tr("Create Kit for %1").arg(target.cpuDir()));
|
||||||
connect(button, &QPushButton::clicked, this, [config, target] {
|
connect(button, &QPushButton::clicked, this, [config, target] {
|
||||||
config->createKit(target);
|
config->createKit(target);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -337,7 +337,7 @@ int QtKitAspect::qtVersionId(const Kit *k)
|
|||||||
|
|
||||||
int id = -1;
|
int id = -1;
|
||||||
QVariant data = k->value(QtKitAspect::id(), -1);
|
QVariant data = k->value(QtKitAspect::id(), -1);
|
||||||
if (data.type() == QVariant::Int) {
|
if (data.typeId() == QVariant::Int) {
|
||||||
bool ok;
|
bool ok;
|
||||||
id = data.toInt(&ok);
|
id = data.toInt(&ok);
|
||||||
if (!ok)
|
if (!ok)
|
||||||
|
|||||||
@@ -282,7 +282,7 @@ bool SquishFileGenerator::setup(const QVariant &data, QString *errorMessage)
|
|||||||
if (data.isNull())
|
if (data.isNull())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (data.type() != QVariant::Map) {
|
if (data.typeId() != QVariant::Map) {
|
||||||
*errorMessage = Tr::tr("Key is not an object.");
|
*errorMessage = Tr::tr("Key is not an object.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
Submodule src/shared/qbs updated: 43af7ba7fa...f8335f02f2
@@ -17,6 +17,15 @@ add_executable(manual_test_debugger_gui
|
|||||||
)
|
)
|
||||||
target_link_libraries(manual_test_debugger_gui PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
|
target_link_libraries(manual_test_debugger_gui PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
|
||||||
|
|
||||||
|
if(APPLE)
|
||||||
|
# codesign in a way that allows attaching a debugger and writing core files
|
||||||
|
add_custom_command(TARGET manual_test_debugger_gui
|
||||||
|
POST_BUILD
|
||||||
|
VERBATIM
|
||||||
|
COMMAND codesign -f -s "-" --entitlements "${CMAKE_CURRENT_SOURCE_DIR}/entitlements.plist" "$<TARGET_FILE:manual_test_debugger_gui>"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (NOT QT_CREATOR_API_DEFINED)
|
if (NOT QT_CREATOR_API_DEFINED)
|
||||||
if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||||
set (CMAKE_INSTALL_PREFIX "/tmp/manual_test_debugger_gui" CACHE PATH "default install path" FORCE)
|
set (CMAKE_INSTALL_PREFIX "/tmp/manual_test_debugger_gui" CACHE PATH "default install path" FORCE)
|
||||||
|
|||||||
9
tests/manual/debugger/gui/entitlements.plist
Normal file
9
tests/manual/debugger/gui/entitlements.plist
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<!-- Allow ourselves to be debugged -->
|
||||||
|
<key>com.apple.security.get-task-allow</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -9,3 +9,5 @@ SOURCES += \
|
|||||||
|
|
||||||
HEADERS += mainwindow.h
|
HEADERS += mainwindow.h
|
||||||
FORMS += mainwindow.ui
|
FORMS += mainwindow.ui
|
||||||
|
|
||||||
|
macos: QMAKE_POST_LINK = codesign -f -s - --entitlements "$${PWD}/entitlements.plist" "$${OUT_PWD}/gui.app"
|
||||||
|
|||||||
Reference in New Issue
Block a user