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 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
|
||||
-------
|
||||
|
||||
* Added a `Terminal` view (QTCREATORBUG-8511)
|
||||
([Documentation](https://doc-snapshots.qt.io/qtcreator-11.0/creator-output-panes.html#terminal))
|
||||
* 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 more spacious `Relaxed` toolbar style to `Preferences > Environment >
|
||||
Interface`
|
||||
* 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
|
||||
(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
|
||||
* Improved performance
|
||||
* 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
|
||||
* Fixed the saving of hardlinked files (QTCREATORBUG-19651)
|
||||
* Fixed an issue of copy and paste with multiple cursors (QTCREATORBUG-29117)
|
||||
* Fixed the saving of hardlinked files
|
||||
([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++
|
||||
|
||||
* 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
|
||||
(QTCREATORBUG-28869)
|
||||
* Added the option to create class members from assignments (QTCREATORBUG-1918)
|
||||
([QTCREATORBUG-28869](https://bugreports.qt.io/browse/QTCREATORBUG-28869))
|
||||
* 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
|
||||
(QTCREATORBUG-13894)
|
||||
([QTCREATORBUG-13894](https://bugreports.qt.io/browse/QTCREATORBUG-13894))
|
||||
* Fixed the handling of C++20 keywords and concepts
|
||||
* 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
|
||||
|
||||
* Added experimental support for GitHub Copilot
|
||||
([GitHub documentation](https://github.com/features/copilot))
|
||||
([Qt Creator documentation](https://doc-snapshots.qt.io/qtcreator-11.0/creator-copilot.html))
|
||||
* Added missing actions for opening the `Call Hierarchy` (QTCREATORBUG-28839,
|
||||
QTCREATORBUG-28842)
|
||||
* Added missing actions for opening the `Call Hierarchy`
|
||||
([QTCREATORBUG-28839](https://bugreports.qt.io/browse/QTCREATORBUG-28839),
|
||||
[QTCREATORBUG-28842](https://bugreports.qt.io/browse/QTCREATORBUG-28842))
|
||||
|
||||
### QML
|
||||
|
||||
* Fixed the reformatting in the presence of JavaScript directives and function
|
||||
return type annotations (QTCREATORBUG-29001, QTCREATORBUG-29046)
|
||||
* Fixed that reformatting changed `of` to `in` (QTCREATORBUG-29123)
|
||||
* Fixed the completion for Qt Quick Controls (QTCREATORBUG-28648)
|
||||
return type annotations
|
||||
([QTCREATORBUG-29001](https://bugreports.qt.io/browse/QTCREATORBUG-29001),
|
||||
[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
|
||||
|
||||
* Added the option to create a virtual environment (`venv`) to the Python
|
||||
interpreter selector and the wizard (PYSIDE-2152)
|
||||
|
||||
### Markdown
|
||||
|
||||
* Added a Markdown editor with preview (QTCREATORBUG-27883)
|
||||
* Added a wizard for Markdown files (QTCREATORBUG-29056)
|
||||
interpreter selector and the wizard
|
||||
([PYSIDE-2152](https://bugreports.qt.io/browse/PYSIDE-2152))
|
||||
|
||||
Projects
|
||||
--------
|
||||
|
||||
* Made it possible to add devices without going through the wizard
|
||||
* Added support for moving files to a different directory when renaming
|
||||
(QTCREATORBUG-15981)
|
||||
([QTCREATORBUG-15981](https://bugreports.qt.io/browse/QTCREATORBUG-15981))
|
||||
|
||||
### CMake
|
||||
|
||||
* Implemented adding files to the project (QTCREATORBUG-25922,
|
||||
QTCREATORBUG-26006, QTCREATORBUG-27213, QTCREATORBUG-27538,
|
||||
QTCREATORBUG-28493, QTCREATORBUG-28904, QTCREATORBUG-28985,
|
||||
QTCREATORBUG-29006)
|
||||
* Implemented adding files to the project
|
||||
([QTCREATORBUG-25922](https://bugreports.qt.io/browse/QTCREATORBUG-25922),
|
||||
[QTCREATORBUG-26006](https://bugreports.qt.io/browse/QTCREATORBUG-26006),
|
||||
[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
|
||||
(QTCREATORBUG-29075)
|
||||
([QTCREATORBUG-29075](https://bugreports.qt.io/browse/QTCREATORBUG-29075))
|
||||
|
||||
### Python
|
||||
|
||||
* 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
|
||||
---------
|
||||
|
||||
* 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++
|
||||
|
||||
@@ -114,16 +177,20 @@ Debugging
|
||||
(`Preferences > Debugger > Locals & Expressions > Default array size`)
|
||||
* CDB
|
||||
* 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
|
||||
* 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
|
||||
|
||||
* 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
|
||||
`Qt Quick > QML/JS Editing` (QTCREATORBUG-29095)
|
||||
`Qt Quick > QML/JS Editing`
|
||||
([QTCREATORBUG-29095](https://bugreports.qt.io/browse/QTCREATORBUG-29095))
|
||||
|
||||
Analyzer
|
||||
--------
|
||||
@@ -131,11 +198,8 @@ Analyzer
|
||||
### Clang
|
||||
|
||||
* Fixed that a `.clang-tidy` file in the project directory was not used by
|
||||
default (QTCREATORBUG-28852)
|
||||
|
||||
### Axivion
|
||||
|
||||
* Added experimental support
|
||||
default
|
||||
([QTCREATORBUG-28852](https://bugreports.qt.io/browse/QTCREATORBUG-28852))
|
||||
|
||||
Version Control Systems
|
||||
-----------------------
|
||||
@@ -143,7 +207,8 @@ Version Control Systems
|
||||
### Git
|
||||
|
||||
* 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
|
||||
|
||||
Platforms
|
||||
@@ -151,7 +216,8 @@ Platforms
|
||||
|
||||
### 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
|
||||
|
||||
@@ -159,14 +225,16 @@ Platforms
|
||||
|
||||
### 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
|
||||
(QTCREATORBUG-28880)
|
||||
([QTCREATORBUG-28880](https://bugreports.qt.io/browse/QTCREATORBUG-28880))
|
||||
|
||||
### QNX
|
||||
|
||||
* 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:
|
||||
--------------------------------
|
||||
|
||||
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
|
||||
|
||||
If \QC does not automatically detect a device you connected with USB, you can
|
||||
use a wizard to create either a network connection or a USB connection to
|
||||
it.
|
||||
If \QC does not automatically detect a device you connected with USB, select
|
||||
\uicontrol Edit > \uicontrol Preferences > \uicontrol Devices >
|
||||
\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
|
||||
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 >
|
||||
\uicontrol Devices > \uicontrol Devices.
|
||||
|
||||
\image qtcreator-boot2qt-device-configurations.png {Devices dialog}
|
||||
|
||||
To reboot the selected device, select \uicontrol {Reboot Device}.
|
||||
|
||||
To restore the default application to the device, select
|
||||
@@ -122,6 +126,10 @@
|
||||
parameters that have sensible default values. One of
|
||||
these is the SSH port number, which is available in
|
||||
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
|
||||
\li Select \uicontrol Edit > \uicontrol Preferences > \uicontrol Kits >
|
||||
\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
|
||||
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 >
|
||||
\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.
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
any number of tasks of various types, such as ProcessTask, FileTransferTask,
|
||||
or AsyncTask<ReturnType>:
|
||||
or ConcurrentCallTask<ReturnType>:
|
||||
|
||||
\code
|
||||
using namespace Tasking;
|
||||
|
||||
const Group root {
|
||||
ProcessTask(...),
|
||||
AsyncTask<int>(...),
|
||||
ConcurrentCallTask<int>(...),
|
||||
FileTransferTask(...)
|
||||
};
|
||||
|
||||
@@ -1149,10 +1149,10 @@ void TaskNode::invokeEndHandler(bool success)
|
||||
\endcode
|
||||
|
||||
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
|
||||
with ProcessTask. When the ProcessTask finishes successfully, the AsyncTask<int> task is
|
||||
started. Finally, when the asynchronous task finishes successfully, the
|
||||
with ProcessTask. When the ProcessTask finishes successfully, the ConcurrentCallTask<int>
|
||||
task is started. Finally, when the asynchronous task finishes successfully, the
|
||||
FileTransferTask task is started.
|
||||
|
||||
When the last running task finishes with success, the task tree is considered
|
||||
@@ -1172,26 +1172,26 @@ void TaskNode::invokeEndHandler(bool success)
|
||||
Group {
|
||||
parallel,
|
||||
ProcessTask(...),
|
||||
AsyncTask<int>(...)
|
||||
ConcurrentCallTask<int>(...)
|
||||
},
|
||||
FileTransferTask(...)
|
||||
};
|
||||
\endcode
|
||||
|
||||
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
|
||||
additional \e parallel element that instructs its Group to execute its tasks
|
||||
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
|
||||
\e parallel element, its direct child tasks are run in sequence. Thus, the
|
||||
FileTransferTask starts when the whole subgroup finishes. The group is
|
||||
considered as finished when all its tasks have finished. The order in which
|
||||
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:
|
||||
|
||||
\table
|
||||
@@ -1208,19 +1208,19 @@ void TaskNode::invokeEndHandler(bool success)
|
||||
\li ProcessTask starts
|
||||
\li ProcessTask starts
|
||||
\row
|
||||
\li AsyncTask<int> starts
|
||||
\li AsyncTask<int> starts
|
||||
\li ConcurrentCallTask<int> starts
|
||||
\li ConcurrentCallTask<int> starts
|
||||
\row
|
||||
\li ...
|
||||
\li ...
|
||||
\row
|
||||
\li \b {ProcessTask finishes}
|
||||
\li \b {AsyncTask<int> finishes}
|
||||
\li \b {ConcurrentCallTask<int> finishes}
|
||||
\row
|
||||
\li ...
|
||||
\li ...
|
||||
\row
|
||||
\li \b {AsyncTask<int> finishes}
|
||||
\li \b {ConcurrentCallTask<int> finishes}
|
||||
\li \b {ProcessTask finishes}
|
||||
\row
|
||||
\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
|
||||
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,
|
||||
the AsyncTask<int> is automatically stopped, the subgroup finishes with an error,
|
||||
when ProcessTask finishes with an error while ConcurrentCallTask<int> is still being executed,
|
||||
the ConcurrentCallTask<int> is automatically stopped, the subgroup finishes with an error,
|
||||
the FileTransferTask is skipped, and the tree finishes with an error.
|
||||
|
||||
\section1 Task Types
|
||||
@@ -1277,11 +1277,11 @@ void TaskNode::invokeEndHandler(bool success)
|
||||
\row
|
||||
\li ProcessTask
|
||||
\li Utils::Process
|
||||
\li Starts processes.
|
||||
\li Starts process.
|
||||
\row
|
||||
\li AsyncTask<ReturnType>
|
||||
\li Utils::Async<ReturnType>
|
||||
\li Starts asynchronous tasks; run in separate thread.
|
||||
\li ConcurrentCallTask<ReturnType>
|
||||
\li Tasking::ConcurrentCall<ReturnType>
|
||||
\li Starts asynchronous task, runs in separate thread.
|
||||
\row
|
||||
\li TaskTreeTask
|
||||
\li Utils::TaskTree
|
||||
@@ -1540,7 +1540,7 @@ void TaskNode::invokeEndHandler(bool success)
|
||||
static QByteArray load(const QString &fileName) { ... }
|
||||
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
|
||||
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
|
||||
const TreeStorage<CopyStorage> storage;
|
||||
|
||||
const auto onLoaderSetup = [source](Async<QByteArray> &async) {
|
||||
const auto onLoaderSetup = [source](ConcurrentCall<QByteArray> &async) {
|
||||
async.setConcurrentCallData(&load, source);
|
||||
};
|
||||
// [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
|
||||
};
|
||||
|
||||
// [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
|
||||
async.setConcurrentCallData(&save, destination, content);
|
||||
};
|
||||
const auto onSaverDone = [](const Async<void> &async) {
|
||||
const auto onSaverDone = [](const ConcurrentCall<void> &async) {
|
||||
qDebug() << "Save done successfully";
|
||||
};
|
||||
|
||||
const Group root {
|
||||
// [7] runtime: task tree creates an instance of CopyStorage when root is entered
|
||||
Storage(storage),
|
||||
AsyncTask<QByteArray>(onLoaderSetup, onLoaderDone),
|
||||
AsyncTask<void>(onSaverSetup, onSaverDone)
|
||||
ConcurrentCallTask<QByteArray>(onLoaderSetup, onLoaderDone),
|
||||
ConcurrentCallTask<void>(onSaverSetup, onSaverDone)
|
||||
};
|
||||
return root;
|
||||
}
|
||||
@@ -1650,7 +1650,7 @@ void TaskNode::invokeEndHandler(bool success)
|
||||
|
||||
\code
|
||||
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);
|
||||
auto initStorage = [](CopyStorage *storage){
|
||||
storage->content = "initial content";
|
||||
@@ -1670,7 +1670,7 @@ void TaskNode::invokeEndHandler(bool success)
|
||||
|
||||
\code
|
||||
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);
|
||||
auto collectStorage = [](CopyStorage *storage){
|
||||
qDebug() << "final content" << storage->content;
|
||||
@@ -1758,7 +1758,7 @@ TaskTree::TaskTree(const Group &recipe) : TaskTree()
|
||||
TaskTree::~TaskTree()
|
||||
{
|
||||
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?
|
||||
delete d;
|
||||
}
|
||||
|
||||
@@ -2346,16 +2346,12 @@ void IntegersAspect::setDefaultValue(const QList<int> &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
|
||||
type \a type.
|
||||
*/
|
||||
TextDisplay::TextDisplay(const QString &message, InfoLabel::InfoType type)
|
||||
: d(new Internal::TextDisplayPrivate)
|
||||
TextDisplay::TextDisplay(AspectContainer *container, const QString &message, InfoLabel::InfoType type)
|
||||
: BaseAspect(container), d(new Internal::TextDisplayPrivate)
|
||||
{
|
||||
d->m_message = message;
|
||||
d->m_type = type;
|
||||
|
||||
@@ -610,8 +610,8 @@ class QTCREATOR_UTILS_EXPORT TextDisplay : public BaseAspect
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TextDisplay(AspectContainer *container);
|
||||
TextDisplay(const QString &message = {},
|
||||
explicit TextDisplay(AspectContainer *container,
|
||||
const QString &message = {},
|
||||
InfoLabel::InfoType type = InfoLabel::None);
|
||||
~TextDisplay() override;
|
||||
|
||||
|
||||
@@ -545,11 +545,11 @@ IconButton::IconButton(QWidget *parent)
|
||||
|
||||
void IconButton::paintEvent(QPaintEvent *)
|
||||
{
|
||||
QWindow *window = this->window()->windowHandle();
|
||||
const QPixmap iconPixmap = icon().pixmap(window, sizeHint(),
|
||||
const qreal pixelRatio = window()->windowHandle()->devicePixelRatio();
|
||||
const QPixmap iconPixmap = icon().pixmap(sizeHint(), pixelRatio,
|
||||
isEnabled() ? QIcon::Normal : QIcon::Disabled);
|
||||
QStylePainter painter(this);
|
||||
QRect pixmapRect(QPoint(), iconPixmap.size() / window->devicePixelRatio());
|
||||
QRect pixmapRect(QPoint(), iconPixmap.size() / pixelRatio);
|
||||
pixmapRect.moveCenter(rect().center());
|
||||
|
||||
if (m_autoHide)
|
||||
|
||||
@@ -65,7 +65,7 @@ QString JsonValue::kindToString(JsonValue::Kind kind)
|
||||
|
||||
JsonValue *JsonValue::build(const QVariant &variant, JsonMemoryPool *pool)
|
||||
{
|
||||
switch (variant.type()) {
|
||||
switch (variant.typeId()) {
|
||||
|
||||
case QVariant::List: {
|
||||
auto newValue = new (pool) JsonArrayValue;
|
||||
|
||||
@@ -216,6 +216,13 @@ void DefaultImpl::start()
|
||||
return;
|
||||
if (!ensureProgramExists(program))
|
||||
return;
|
||||
|
||||
if (m_setup.m_runAsRoot && !HostOsInfo::isWindowsHost()) {
|
||||
arguments.prepend(program);
|
||||
arguments.prepend("-A");
|
||||
program = "sudo";
|
||||
}
|
||||
|
||||
s_start.measureAndRun(&DefaultImpl::doDefaultStart, this, program, arguments);
|
||||
}
|
||||
|
||||
@@ -766,15 +773,6 @@ public:
|
||||
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;
|
||||
std::unique_ptr<ProcessBlockingInterface> m_blockingInterface;
|
||||
std::unique_ptr<ProcessInterface> m_process;
|
||||
@@ -1217,7 +1215,6 @@ void Process::start()
|
||||
d->setProcessInterface(processImpl);
|
||||
d->m_state = QProcess::Starting;
|
||||
d->m_process->m_setup = d->m_setup;
|
||||
d->m_process->m_setup.m_commandLine = d->fullCommandLine();
|
||||
d->emitGuardedSignal(&Process::starting);
|
||||
d->m_process->start();
|
||||
}
|
||||
|
||||
@@ -10,8 +10,10 @@
|
||||
#include <QTime>
|
||||
#include <QWidget>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QPainter;
|
||||
class QStyleOption;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Utils {
|
||||
/*
|
||||
|
||||
@@ -385,6 +385,22 @@ void TerminalInterface::start()
|
||||
ProcessSetupData stubSetupData = m_setup;
|
||||
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(
|
||||
d->stubCreator,
|
||||
[stubSetupData, this] { d->stubCreator->startStubProcess(stubSetupData); },
|
||||
|
||||
@@ -7,9 +7,12 @@
|
||||
|
||||
#include <QScrollBar>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QAbstractScrollArea;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Utils {
|
||||
|
||||
class ScrollAreaPrivate;
|
||||
class ScrollBarPrivate;
|
||||
|
||||
|
||||
@@ -191,7 +191,7 @@ void AndroidConfig::load(const QSettings &settings)
|
||||
{
|
||||
// user settings
|
||||
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());
|
||||
m_emulatorArgs = emulatorArgs.toString();
|
||||
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()
|
||||
{
|
||||
QString error;
|
||||
int errorLine;
|
||||
int errorColumn;
|
||||
QDomDocument doc;
|
||||
if (doc.setContent(m_textEditorWidget->toPlainText(), &error, &errorLine, &errorColumn)) {
|
||||
if (checkDocument(doc, &error, &errorLine, &errorColumn)) {
|
||||
QDomDocument::ParseResult result = doc.setContent(m_textEditorWidget->toPlainText());
|
||||
if (result) {
|
||||
if (checkDocument(doc, &result)) {
|
||||
if (activePage() != Source)
|
||||
syncToWidgets(doc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// some error occurred
|
||||
updateInfoBar(error, errorLine, errorColumn);
|
||||
updateInfoBar(result.errorMessage, result.errorLine, result.errorColumn);
|
||||
setActivePage(Source);
|
||||
}
|
||||
|
||||
@@ -591,39 +610,19 @@ TextEditor::TextEditorWidget *AndroidManifestEditorWidget::textEditorWidget() co
|
||||
bool AndroidManifestEditorWidget::syncToWidgets()
|
||||
{
|
||||
QDomDocument doc;
|
||||
QString errorMessage;
|
||||
int errorLine, errorColumn;
|
||||
if (doc.setContent(m_textEditorWidget->toPlainText(), &errorMessage, &errorLine, &errorColumn)) {
|
||||
if (checkDocument(doc, &errorMessage, &errorLine, &errorColumn)) {
|
||||
QDomDocument::ParseResult result = doc.setContent(m_textEditorWidget->toPlainText());
|
||||
if (result) {
|
||||
if (checkDocument(doc, &result)) {
|
||||
hideInfoBar();
|
||||
syncToWidgets(doc);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
updateInfoBar(errorMessage, errorLine, errorColumn);
|
||||
updateInfoBar(result.errorMessage, result.errorLine, result.errorColumn);
|
||||
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()
|
||||
{
|
||||
m_timerParseCheck.start();
|
||||
@@ -641,16 +640,15 @@ void AndroidManifestEditorWidget::updateInfoBar()
|
||||
return;
|
||||
}
|
||||
QDomDocument doc;
|
||||
int errorLine, errorColumn;
|
||||
QString errorMessage;
|
||||
if (doc.setContent(m_textEditorWidget->toPlainText(), &errorMessage, &errorLine, &errorColumn)) {
|
||||
if (checkDocument(doc, &errorMessage, &errorLine, &errorColumn)) {
|
||||
QDomDocument::ParseResult result = doc.setContent(m_textEditorWidget->toPlainText());
|
||||
if (result) {
|
||||
if (checkDocument(doc, &result)) {
|
||||
hideInfoBar();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
updateInfoBar(errorMessage, errorLine, errorColumn);
|
||||
updateInfoBar(result.errorMessage, result.errorLine, result.errorColumn);
|
||||
}
|
||||
|
||||
void AndroidManifestEditorWidget::updateSdkVersions()
|
||||
@@ -888,9 +886,9 @@ void AndroidManifestEditorWidget::syncToEditor()
|
||||
m_dirty = false;
|
||||
}
|
||||
|
||||
namespace {
|
||||
QXmlStreamAttributes modifyXmlStreamAttributes(const QXmlStreamAttributes &input, const QStringList &keys,
|
||||
const QStringList &values, const QStringList &remove = QStringList())
|
||||
static QXmlStreamAttributes modifyXmlStreamAttributes(
|
||||
const QXmlStreamAttributes &input, const QStringList &keys,
|
||||
const QStringList &values, const QStringList &remove = {})
|
||||
{
|
||||
Q_ASSERT(keys.size() == values.size());
|
||||
QXmlStreamAttributes result;
|
||||
@@ -903,8 +901,7 @@ QXmlStreamAttributes modifyXmlStreamAttributes(const QXmlStreamAttributes &input
|
||||
if (index == -1)
|
||||
result.push_back(attribute);
|
||||
else
|
||||
result.push_back(QXmlStreamAttribute(name,
|
||||
values.at(index)));
|
||||
result.push_back(QXmlStreamAttribute(name, values.at(index)));
|
||||
}
|
||||
|
||||
for (int i = 0; i < keys.size(); ++i) {
|
||||
@@ -913,7 +910,6 @@ QXmlStreamAttributes modifyXmlStreamAttributes(const QXmlStreamAttributes &input
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} // end namespace
|
||||
|
||||
void AndroidManifestEditorWidget::parseManifest(QXmlStreamReader &reader, QXmlStreamWriter &writer)
|
||||
{
|
||||
|
||||
@@ -14,14 +14,11 @@
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QCheckBox;
|
||||
class QDomDocument;
|
||||
class QDomElement;
|
||||
class QComboBox;
|
||||
class QPushButton;
|
||||
class QLabel;
|
||||
class QLineEdit;
|
||||
class QListView;
|
||||
class QSpinBox;
|
||||
class QToolButton;
|
||||
class QXmlStreamReader;
|
||||
class QXmlStreamWriter;
|
||||
QT_END_NAMESPACE
|
||||
@@ -108,9 +105,6 @@ private:
|
||||
void syncToEditor();
|
||||
void updateAfterFileLoad();
|
||||
|
||||
bool checkDocument(const QDomDocument &doc, QString *errorMessage,
|
||||
int *errorLine, int *errorColumn);
|
||||
|
||||
void updateInfoBar(const QString &errorMessage, int line, int column);
|
||||
void hideInfoBar();
|
||||
|
||||
|
||||
@@ -280,7 +280,7 @@ AndroidRunnerWorker::AndroidRunnerWorker(RunWorker *runner, const QString &packa
|
||||
m_beforeStartAdbCommands.append(QString("shell %1").arg(shellCmd));
|
||||
|
||||
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);
|
||||
for (const QString &shellCmd : commands)
|
||||
m_afterFinishAdbCommands.append(QString("shell %1").arg(shellCmd));
|
||||
|
||||
@@ -455,7 +455,7 @@ void TestRunner::runTestsHelper()
|
||||
connect(m_taskTree.get(), &TaskTree::errorOccurred, this, &TestRunner::onFinished);
|
||||
|
||||
auto progress = new TaskProgress(m_taskTree.get());
|
||||
progress->setDisplayName(tr("Running Tests"));
|
||||
progress->setDisplayName(Tr::tr("Running Tests"));
|
||||
progress->setAutoStopOnCancel(false);
|
||||
progress->setHalfLifeTimePerTask(10000); // 10 seconds
|
||||
connect(progress, &TaskProgress::canceled, this, [this, progress] {
|
||||
|
||||
@@ -77,10 +77,10 @@ void ArtisticStyleSettings::createDocumentationFile() const
|
||||
if (process.result() != ProcessResult::FinishedWithSuccess)
|
||||
return;
|
||||
|
||||
if (!documentationFilePath.exists())
|
||||
documentationFilePath.parentDir().ensureWritableDir();
|
||||
|
||||
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))
|
||||
return;
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <QVersionNumber>
|
||||
|
||||
using namespace TextEditor;
|
||||
using namespace Utils;
|
||||
|
||||
namespace Beautifier::Internal {
|
||||
|
||||
@@ -72,7 +73,7 @@ void Uncrustify::updateActions(Core::IEditor *editor)
|
||||
|
||||
void Uncrustify::formatFile()
|
||||
{
|
||||
const QString cfgFileName = configurationFile();
|
||||
const FilePath cfgFileName = configurationFile();
|
||||
if (cfgFileName.isEmpty()) {
|
||||
BeautifierPlugin::showError(BeautifierPlugin::msgCannotGetConfigurationFile(
|
||||
Tr::tr(Constants::UNCRUSTIFY_DISPLAY_NAME)));
|
||||
@@ -83,7 +84,7 @@ void Uncrustify::formatFile()
|
||||
|
||||
void Uncrustify::formatSelectedText()
|
||||
{
|
||||
const QString cfgFileName = configurationFile();
|
||||
const FilePath cfgFileName = configurationFile();
|
||||
if (cfgFileName.isEmpty()) {
|
||||
BeautifierPlugin::showError(BeautifierPlugin::msgCannotGetConfigurationFile(
|
||||
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())
|
||||
return m_settings.styleFileName(m_settings.customStyle());
|
||||
return FilePath::fromUserInput(m_settings.styleFileName(m_settings.customStyle()));
|
||||
|
||||
if (m_settings.useOtherFiles()) {
|
||||
if (const ProjectExplorer::Project *project
|
||||
= ProjectExplorer::ProjectTree::currentProject()) {
|
||||
const Utils::FilePaths files = project->files(
|
||||
[](const ProjectExplorer::Node *n) { return n->filePath().endsWith("cfg"); });
|
||||
for (const Utils::FilePath &file : files) {
|
||||
const QFileInfo fi = file.toFileInfo();
|
||||
if (fi.isReadable() && fi.fileName() == "uncrustify.cfg")
|
||||
return file.toString();
|
||||
}
|
||||
using namespace ProjectExplorer;
|
||||
if (const Project *project = ProjectTree::currentProject()) {
|
||||
const FilePaths files = project->files([](const Node *n) {
|
||||
const FilePath fp = n->filePath();
|
||||
return fp.fileName() == "uncrustify.cfg" && fp.isReadableFile();
|
||||
});
|
||||
if (!files.isEmpty())
|
||||
return files.first();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_settings.useSpecificConfigFile()) {
|
||||
const Utils::FilePath file = m_settings.specificConfigFile();
|
||||
const FilePath file = m_settings.specificConfigFile();
|
||||
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 QString();
|
||||
if (m_settings.useHomeFile()) {
|
||||
const FilePath file = FileUtils::homePath() / "uncrustify.cfg";
|
||||
if (file.exists())
|
||||
return file;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
Command Uncrustify::command() const
|
||||
{
|
||||
const QString cfgFile = configurationFile();
|
||||
const FilePath cfgFile = configurationFile();
|
||||
return cfgFile.isEmpty() ? Command() : command(cfgFile, false);
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ bool Uncrustify::isApplicable(const Core::IDocument *document) const
|
||||
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.setExecutable(m_settings.command());
|
||||
@@ -173,7 +173,7 @@ Command Uncrustify::command(const QString &cfgFile, bool fragment) const
|
||||
if (fragment)
|
||||
command.addOption("--frag");
|
||||
command.addOption("-c");
|
||||
command.addOption(cfgFile);
|
||||
command.addOption(cfgFile.path());
|
||||
return command;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,8 +22,8 @@ public:
|
||||
private:
|
||||
void formatFile();
|
||||
void formatSelectedText();
|
||||
QString configurationFile() const;
|
||||
TextEditor::Command command(const QString &cfgFile, bool fragment = false) const;
|
||||
Utils::FilePath configurationFile() const;
|
||||
TextEditor::Command command(const Utils::FilePath &cfgFile, bool fragment = false) const;
|
||||
|
||||
QAction *m_formatFile = nullptr;
|
||||
QAction *m_formatRange = nullptr;
|
||||
|
||||
@@ -207,7 +207,7 @@ void ClangFormatConfigWidget::createStyleFileIfNeeded(bool isGlobal)
|
||||
if (configFile.exists())
|
||||
return;
|
||||
|
||||
QDir().mkpath(path.toString());
|
||||
path.ensureWritableDir();
|
||||
if (!isGlobal) {
|
||||
FilePath possibleProjectConfig = d->project->rootProjectDirectory()
|
||||
/ Constants::SETTINGS_FILE_NAME;
|
||||
@@ -218,11 +218,8 @@ void ClangFormatConfigWidget::createStyleFileIfNeeded(bool isGlobal)
|
||||
}
|
||||
}
|
||||
|
||||
std::fstream newStyleFile(configFile.toString().toStdString(), std::fstream::out);
|
||||
if (newStyleFile.is_open()) {
|
||||
newStyleFile << clang::format::configurationAsText(constructStyle());
|
||||
newStyleFile.close();
|
||||
}
|
||||
const std::string config = clang::format::configurationAsText(constructStyle());
|
||||
configFile.writeFileContents(QByteArray::fromStdString(config));
|
||||
}
|
||||
|
||||
void ClangFormatConfigWidget::showOrHideWidgets()
|
||||
|
||||
@@ -1465,8 +1465,10 @@ void MainWindow::changeLog()
|
||||
return;
|
||||
const FilePath file = versionedFiles.at(index).second;
|
||||
QString contents = QString::fromUtf8(file.fileContents().value_or(QByteArray()));
|
||||
static const QRegularExpression bugexpr("(QT(CREATOR)?BUG-[0-9]+)");
|
||||
contents.replace(bugexpr, "[\\1](https://bugreports.qt.io/browse/\\1)");
|
||||
// (?<![[\/]) == don't replace if it is preceded by "[" or "/"
|
||||
// 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/_-]*)");
|
||||
QList<QRegularExpressionMatch> matches;
|
||||
for (const QRegularExpressionMatch &m : docexpr.globalMatch(contents))
|
||||
|
||||
@@ -42,12 +42,12 @@ ProjectInfo::ConstPtr ProjectInfoGenerator::generate(const QPromise<ProjectInfo:
|
||||
});
|
||||
};
|
||||
if (m_cToolchainMissing) {
|
||||
showWarning(Tr::tr(
|
||||
"The project contains C source files, but the currently active kit "
|
||||
showWarning(
|
||||
::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."));
|
||||
}
|
||||
if (m_cxxToolchainMissing) {
|
||||
showWarning(Tr::tr(
|
||||
showWarning(::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."));
|
||||
}
|
||||
|
||||
@@ -1107,7 +1107,7 @@ QVariant BreakpointItem::data(int column, int role) const
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void BreakpointItem::addToCommand(DebuggerCommand *cmd) const
|
||||
void BreakpointItem::addToCommand(DebuggerCommand *cmd, BreakpointPathUsage defaultPathUsage) const
|
||||
{
|
||||
QTC_ASSERT(m_globalBreakpoint, return);
|
||||
const BreakpointParameters &requested = requestedParameters();
|
||||
@@ -1120,10 +1120,19 @@ void BreakpointItem::addToCommand(DebuggerCommand *cmd) const
|
||||
cmd->arg("function", requested.functionName);
|
||||
cmd->arg("oneshot", requested.oneShot);
|
||||
cmd->arg("enabled", requested.enabled);
|
||||
cmd->arg("file", requested.fileName.path());
|
||||
cmd->arg("line", requested.textPosition.line);
|
||||
cmd->arg("address", requested.address);
|
||||
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)
|
||||
|
||||
@@ -107,7 +107,9 @@ public:
|
||||
int markerLineNumber() 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);
|
||||
|
||||
int modelId() const;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <coreplugin/icore.h>
|
||||
|
||||
#include <projectexplorer/runconfiguration.h>
|
||||
#include <projectexplorer/runconfigurationaspects.h>
|
||||
|
||||
#include <utils/environment.h>
|
||||
#include <utils/hostosinfo.h>
|
||||
@@ -172,9 +173,18 @@ void TerminalRunner::start()
|
||||
QTC_ASSERT(!m_stubProc, reportFailure({}); return);
|
||||
Runnable stub = m_stubRunnable();
|
||||
|
||||
bool runAsRoot = false;
|
||||
if (auto runAsRootAspect = runControl()->aspect<RunAsRootAspect>())
|
||||
runAsRoot = runAsRootAspect->value;
|
||||
|
||||
m_stubProc = new Process(this);
|
||||
m_stubProc->setTerminalMode(TerminalMode::Debug);
|
||||
|
||||
if (runAsRoot) {
|
||||
m_stubProc->setRunAsRoot(runAsRoot);
|
||||
RunControl::provideAskPassEntry(stub.environment);
|
||||
}
|
||||
|
||||
connect(m_stubProc, &Process::started,
|
||||
this, &TerminalRunner::stubStarted);
|
||||
connect(m_stubProc, &Process::done,
|
||||
|
||||
@@ -647,7 +647,7 @@ ActionContainer *FormEditorData::createPreviewStyleMenu(QActionGroup *actionGrou
|
||||
QString name = menuId;
|
||||
name += dot;
|
||||
const QVariant data = a->data();
|
||||
const bool isDeviceProfile = data.type() == QVariant::Int;
|
||||
const bool isDeviceProfile = data.typeId() == QVariant::Int;
|
||||
if (isDeviceProfile) {
|
||||
name += deviceProfilePrefix;
|
||||
name += dot;
|
||||
|
||||
@@ -50,6 +50,39 @@ public:
|
||||
BuildConsoleBuildStep(BuildStepList *buildStepList, Id id);
|
||||
|
||||
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)
|
||||
@@ -57,32 +90,20 @@ BuildConsoleBuildStep::BuildConsoleBuildStep(BuildStepList *buildStepList, Id id
|
||||
{
|
||||
setDisplayName(Tr::tr("IncrediBuild for Windows"));
|
||||
|
||||
addAspect<TextDisplay>("<b>" + Tr::tr("Target and Configuration"));
|
||||
commandBuilder.setSettingsKey("IncrediBuild.BuildConsole.CommandBuilder");
|
||||
|
||||
auto commandBuilder = addAspect<CommandBuilderAspect>(this);
|
||||
commandBuilder->setSettingsKey("IncrediBuild.BuildConsole.CommandBuilder");
|
||||
|
||||
addAspect<TextDisplay>("<i>" + Tr::tr("Enter the appropriate arguments to your build command."));
|
||||
addAspect<TextDisplay>("<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)"));
|
||||
|
||||
auto keepJobNum = addAspect<BoolAspect>();
|
||||
keepJobNum->setSettingsKey("IncrediBuild.BuildConsole.KeepJobNum");
|
||||
keepJobNum->setLabel(Tr::tr("Keep original jobs number:"));
|
||||
keepJobNum->setToolTip(Tr::tr("Forces IncrediBuild to not override the -j command line switch, "
|
||||
keepJobNum.setSettingsKey("IncrediBuild.BuildConsole.KeepJobNum");
|
||||
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"));
|
||||
|
||||
auto profileXml = addAspect<FilePathAspect>();
|
||||
profileXml->setSettingsKey("IncrediBuild.BuildConsole.ProfileXml");
|
||||
profileXml->setLabelText(Tr::tr("Profile.xml:"));
|
||||
profileXml->setExpectedKind(PathChooser::Kind::File);
|
||||
profileXml->setBaseFileName(PathChooser::homePath());
|
||||
profileXml->setHistoryCompleter("IncrediBuild.BuildConsole.ProfileXml.History");
|
||||
profileXml->setToolTip(Tr::tr("Defines how Automatic "
|
||||
profileXml.setSettingsKey("IncrediBuild.BuildConsole.ProfileXml");
|
||||
profileXml.setLabelText(Tr::tr("Profile.xml:"));
|
||||
profileXml.setExpectedKind(PathChooser::Kind::File);
|
||||
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, "
|
||||
@@ -91,199 +112,176 @@ BuildConsoleBuildStep::BuildConsoleBuildStep(BuildStepList *buildStepList, Id id
|
||||
"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 "
|
||||
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 "
|
||||
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);
|
||||
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 "
|
||||
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())
|
||||
maxWinVer->addOption(version);
|
||||
maxWinVer.addOption(version);
|
||||
|
||||
auto minWinVer = addAspect<SelectionAspect>();
|
||||
minWinVer->setSettingsKey("IncrediBuild.BuildConsole.MinWinVer");
|
||||
minWinVer->setDisplayName(Tr::tr("Oldest allowed helper machine OS:"));
|
||||
minWinVer->setDisplayStyle(SelectionAspect::DisplayStyle::ComboBox);
|
||||
minWinVer->setToolTip(Tr::tr("Specifies the oldest operating system installed on a helper "
|
||||
minWinVer.setSettingsKey("IncrediBuild.BuildConsole.MinWinVer");
|
||||
minWinVer.setDisplayName(Tr::tr("Oldest allowed helper machine OS:"));
|
||||
minWinVer.setDisplayStyle(SelectionAspect::DisplayStyle::ComboBox);
|
||||
minWinVer.setToolTip(Tr::tr("Specifies the oldest operating system installed on a helper "
|
||||
"machine to be allowed to participate as helper in the build."));
|
||||
for (const QString &version : supportedWindowsVersions())
|
||||
minWinVer->addOption(version);
|
||||
minWinVer.addOption(version);
|
||||
|
||||
addAspect<TextDisplay>("<b>" + Tr::tr("Output and Logging"));
|
||||
|
||||
auto title = addAspect<StringAspect>();
|
||||
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 "
|
||||
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 monFile = addAspect<FilePathAspect>();
|
||||
monFile->setSettingsKey("IncrediBuild.BuildConsole.MonFile");
|
||||
monFile->setLabelText(Tr::tr("Save IncrediBuild monitor file:"));
|
||||
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 "
|
||||
monFile.setSettingsKey("IncrediBuild.BuildConsole.MonFile");
|
||||
monFile.setLabelText(Tr::tr("Save IncrediBuild monitor file:"));
|
||||
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>();
|
||||
suppressStdOut->setSettingsKey("IncrediBuild.BuildConsole.SuppressStdOut");
|
||||
suppressStdOut->setLabel(Tr::tr("Suppress STDOUT:"));
|
||||
suppressStdOut->setToolTip(Tr::tr("Does not write anything to the standard output."));
|
||||
suppressStdOut.setSettingsKey("IncrediBuild.BuildConsole.SuppressStdOut");
|
||||
suppressStdOut.setLabel(Tr::tr("Suppress STDOUT:"));
|
||||
suppressStdOut.setToolTip(Tr::tr("Does not write anything to the standard output."));
|
||||
|
||||
auto logFile = addAspect<FilePathAspect>();
|
||||
logFile->setSettingsKey("IncrediBuild.BuildConsole.LogFile");
|
||||
logFile->setLabelText(Tr::tr("Output Log file:"));
|
||||
logFile->setExpectedKind(PathChooser::Kind::SaveFile);
|
||||
logFile->setBaseFileName(PathChooser::homePath());
|
||||
logFile->setHistoryCompleter(QLatin1String("IncrediBuild.BuildConsole.LogFile.History"));
|
||||
logFile->setToolTip(Tr::tr("Writes build output to a file."));
|
||||
logFile.setSettingsKey("IncrediBuild.BuildConsole.LogFile");
|
||||
logFile.setLabelText(Tr::tr("Output Log file:"));
|
||||
logFile.setExpectedKind(PathChooser::Kind::SaveFile);
|
||||
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>();
|
||||
showCmd->setSettingsKey("IncrediBuild.BuildConsole.ShowCmd");
|
||||
showCmd->setLabel(Tr::tr("Show Commands in output:"));
|
||||
showCmd->setToolTip(Tr::tr("Shows, for each file built, the command-line used by IncrediBuild "
|
||||
showCmd.setSettingsKey("IncrediBuild.BuildConsole.ShowCmd");
|
||||
showCmd.setLabel(Tr::tr("Show Commands in output:"));
|
||||
showCmd.setToolTip(Tr::tr("Shows, for each file built, the command-line used by IncrediBuild "
|
||||
"to build the file."));
|
||||
|
||||
auto showAgents = addAspect<BoolAspect>();
|
||||
showAgents->setSettingsKey("IncrediBuild.BuildConsole.ShowAgents");
|
||||
showAgents->setLabel(Tr::tr("Show Agents in output:"));
|
||||
showAgents->setToolTip(Tr::tr("Shows the Agent used to build each file."));
|
||||
showAgents.setSettingsKey("IncrediBuild.BuildConsole.ShowAgents");
|
||||
showAgents.setLabel(Tr::tr("Show Agents in output:"));
|
||||
showAgents.setToolTip(Tr::tr("Shows the Agent used to build each file."));
|
||||
|
||||
auto showTime = addAspect<BoolAspect>();
|
||||
showTime->setSettingsKey("IncrediBuild.BuildConsole.ShowTime");
|
||||
showTime->setLabel(Tr::tr("Show Time in output:"));
|
||||
showTime->setToolTip(Tr::tr("Shows the Start and Finish time for each file built."));
|
||||
showTime.setSettingsKey("IncrediBuild.BuildConsole.ShowTime");
|
||||
showTime.setLabel(Tr::tr("Show Time in output:"));
|
||||
showTime.setToolTip(Tr::tr("Shows the Start and Finish time for each file built."));
|
||||
|
||||
auto hideHeader = addAspect<BoolAspect>();
|
||||
hideHeader->setSettingsKey("IncrediBuild.BuildConsole.HideHeader");
|
||||
hideHeader->setLabel(Tr::tr("Hide IncrediBuild Header in output:"));
|
||||
hideHeader->setToolTip(Tr::tr("Suppresses IncrediBuild's header in the build output"));
|
||||
hideHeader.setSettingsKey("IncrediBuild.BuildConsole.HideHeader");
|
||||
hideHeader.setLabel(Tr::tr("Hide IncrediBuild Header in output:"));
|
||||
hideHeader.setToolTip(Tr::tr("Suppresses IncrediBuild's header in the build output"));
|
||||
|
||||
auto logLevel = addAspect<SelectionAspect>();
|
||||
logLevel->setSettingsKey("IncrediBuild.BuildConsole.LogLevel");
|
||||
logLevel->setDisplayName(Tr::tr("Internal IncrediBuild logging level:"));
|
||||
logLevel->setDisplayStyle(SelectionAspect::DisplayStyle::ComboBox);
|
||||
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. "
|
||||
logLevel.setSettingsKey("IncrediBuild.BuildConsole.LogLevel");
|
||||
logLevel.setDisplayName(Tr::tr("Internal IncrediBuild logging level:"));
|
||||
logLevel.setDisplayStyle(SelectionAspect::DisplayStyle::ComboBox);
|
||||
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"));
|
||||
setEnv.setSettingsKey("IncrediBuild.BuildConsole.SetEnv");
|
||||
setEnv.setLabelText(Tr::tr("Set an Environment Variable:"));
|
||||
setEnv.setDisplayStyle(StringAspect::LineEditDisplay);
|
||||
setEnv.setToolTip(Tr::tr("Sets or overrides environment variables for the context of the build."));
|
||||
|
||||
auto setEnv = addAspect<StringAspect>();
|
||||
setEnv->setSettingsKey("IncrediBuild.BuildConsole.SetEnv");
|
||||
setEnv->setLabelText(Tr::tr("Set an Environment Variable:"));
|
||||
setEnv->setDisplayStyle(StringAspect::LineEditDisplay);
|
||||
setEnv->setToolTip(Tr::tr("Sets or overrides environment variables for the context of the build."));
|
||||
|
||||
auto stopOnError = addAspect<BoolAspect>();
|
||||
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 "
|
||||
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 additionalArguments = addAspect<StringAspect>();
|
||||
additionalArguments->setSettingsKey("IncrediBuild.BuildConsole.AdditionalArguments");
|
||||
additionalArguments->setLabelText(Tr::tr("Additional Arguments:"));
|
||||
additionalArguments->setDisplayStyle(StringAspect::LineEditDisplay);
|
||||
additionalArguments->setToolTip(Tr::tr("Add additional buildconsole arguments manually. "
|
||||
additionalArguments.setSettingsKey("IncrediBuild.BuildConsole.AdditionalArguments");
|
||||
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>();
|
||||
openMonitor->setSettingsKey("IncrediBuild.BuildConsole.OpenMonitor");
|
||||
openMonitor->setLabel(Tr::tr("Open Build Monitor:"));
|
||||
openMonitor->setToolTip(Tr::tr("Opens Build Monitor once the build starts."));
|
||||
openMonitor.setSettingsKey("IncrediBuild.BuildConsole.OpenMonitor");
|
||||
openMonitor.setLabel(Tr::tr("Open Build Monitor:"));
|
||||
openMonitor.setToolTip(Tr::tr("Opens Build Monitor once the build starts."));
|
||||
|
||||
setCommandLineProvider([=] {
|
||||
QStringList args;
|
||||
setCommandLineProvider([this] {
|
||||
CommandLine cmd("BuildConsole.exe");
|
||||
|
||||
QString cmd("/Command= %1");
|
||||
cmd = cmd.arg(commandBuilder->fullCommandFlag(keepJobNum->value()));
|
||||
args.append(cmd);
|
||||
cmd.addArgs(QString("/Command=%1").arg(commandBuilder.fullCommandFlag(keepJobNum())), CommandLine::Raw);
|
||||
|
||||
if (!profileXml->value().isEmpty())
|
||||
args.append("/Profile=" + profileXml->value());
|
||||
if (!profileXml().isEmpty())
|
||||
cmd.addArg(QString("/Profile=%1").arg(profileXml().path()));
|
||||
|
||||
args.append(QString("/AvoidLocal=%1").arg(avoidLocal->value() ? QString("ON") : QString("OFF")));
|
||||
cmd.addArg(QString("/AvoidLocal=%1").arg(avoidLocal() ? QString("ON") : QString("OFF")));
|
||||
|
||||
if (maxCpu->value() > 0)
|
||||
args.append(QString("/MaxCPUs=%1").arg(maxCpu->value()));
|
||||
if (maxCpu() > 0)
|
||||
cmd.addArg(QString("/MaxCPUs=%1").arg(maxCpu()));
|
||||
|
||||
if (!maxWinVer->stringValue().isEmpty())
|
||||
args.append(QString("/MaxWinVer=%1").arg(normalizeWinVerArgument(maxWinVer->stringValue())));
|
||||
if (!maxWinVer.stringValue().isEmpty())
|
||||
cmd.addArg(QString("/MaxWinVer=%1").arg(normalizeWinVerArgument(maxWinVer.stringValue())));
|
||||
|
||||
if (!minWinVer->stringValue().isEmpty())
|
||||
args.append(QString("/MinWinVer=%1").arg(normalizeWinVerArgument(minWinVer->stringValue())));
|
||||
if (!minWinVer.stringValue().isEmpty())
|
||||
cmd.addArg(QString("/MinWinVer=%1").arg(normalizeWinVerArgument(minWinVer.stringValue())));
|
||||
|
||||
if (!title->value().isEmpty())
|
||||
args.append(QString("/Title=" + title->value()));
|
||||
if (!title().isEmpty())
|
||||
cmd.addArg("/Title=" + title());
|
||||
|
||||
if (!monFile->value().isEmpty())
|
||||
args.append(QString("/Mon=" + monFile->value()));
|
||||
if (!monFile().isEmpty())
|
||||
cmd.addArg("/Mon=" + monFile().path());
|
||||
|
||||
if (suppressStdOut->value())
|
||||
args.append("/Silent");
|
||||
if (suppressStdOut())
|
||||
cmd.addArg("/Silent");
|
||||
|
||||
if (!logFile->value().isEmpty())
|
||||
args.append(QString("/Log=" + logFile->value()));
|
||||
if (!logFile().isEmpty())
|
||||
cmd.addArg("/Log=" + logFile().path());
|
||||
|
||||
if (showCmd->value())
|
||||
args.append("/ShowCmd");
|
||||
if (showCmd())
|
||||
cmd.addArg("/ShowCmd");
|
||||
|
||||
if (showAgents->value())
|
||||
args.append("/ShowAgent");
|
||||
if (showAgents())
|
||||
cmd.addArg("/ShowAgent");
|
||||
|
||||
if (showAgents->value())
|
||||
args.append("/ShowTime");
|
||||
if (showAgents())
|
||||
cmd.addArg("/ShowTime");
|
||||
|
||||
if (hideHeader->value())
|
||||
args.append("/NoLogo");
|
||||
if (hideHeader())
|
||||
cmd.addArg("/NoLogo");
|
||||
|
||||
if (!logLevel->stringValue().isEmpty())
|
||||
args.append(QString("/LogLevel=" + logLevel->stringValue()));
|
||||
if (!logLevel.stringValue().isEmpty())
|
||||
cmd.addArg("/LogLevel=" + logLevel.stringValue());
|
||||
|
||||
if (!setEnv->value().isEmpty())
|
||||
args.append(QString("/SetEnv=" + setEnv->value()));
|
||||
if (!setEnv().isEmpty())
|
||||
cmd.addArg("/SetEnv=" + setEnv());
|
||||
|
||||
if (stopOnError->value())
|
||||
args.append("/StopOnErrors");
|
||||
if (stopOnError())
|
||||
cmd.addArg("/StopOnErrors");
|
||||
|
||||
if (!additionalArguments->value().isEmpty())
|
||||
args.append(additionalArguments->value());
|
||||
if (!additionalArguments().isEmpty())
|
||||
cmd.addArgs(additionalArguments(), CommandLine::Raw);
|
||||
|
||||
if (openMonitor->value())
|
||||
args.append("/OpenMonitor");
|
||||
if (openMonitor())
|
||||
cmd.addArg("/OpenMonitor");
|
||||
|
||||
return CommandLine("BuildConsole.exe", args);
|
||||
return cmd;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,21 @@ public:
|
||||
IBConsoleBuildStep(BuildStepList *buildStepList, Id id);
|
||||
|
||||
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)
|
||||
@@ -35,52 +50,38 @@ IBConsoleBuildStep::IBConsoleBuildStep(BuildStepList *buildStepList, Id id)
|
||||
{
|
||||
setDisplayName(Tr::tr("IncrediBuild for Linux"));
|
||||
|
||||
addAspect<TextDisplay>("<b>" + Tr::tr("Target and Configuration"));
|
||||
commandBuilder.setSettingsKey("IncrediBuild.IBConsole.CommandBuilder");
|
||||
|
||||
auto commandBuilder = addAspect<CommandBuilderAspect>(this);
|
||||
commandBuilder->setSettingsKey("IncrediBuild.IBConsole.CommandBuilder");
|
||||
|
||||
addAspect<TextDisplay>("<i>" + Tr::tr("Enter the appropriate arguments to your build command."));
|
||||
addAspect<TextDisplay>("<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)"));
|
||||
|
||||
auto keepJobNum = addAspect<BoolAspect>();
|
||||
keepJobNum->setSettingsKey("IncrediBuild.IBConsole.KeepJobNum");
|
||||
keepJobNum->setLabel(Tr::tr("Keep original jobs number:"));
|
||||
keepJobNum->setToolTip(Tr::tr("Forces IncrediBuild to not override the -j command line switch, "
|
||||
keepJobNum.setSettingsKey("IncrediBuild.IBConsole.KeepJobNum");
|
||||
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"));
|
||||
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 nice = addAspect<IntegerAspect>();
|
||||
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);
|
||||
forceRemote.setSettingsKey("IncrediBuild.IBConsole.Alternate");
|
||||
forceRemote.setLabel(Tr::tr("Force remote:"));
|
||||
|
||||
auto forceRemote = addAspect<BoolAspect>();
|
||||
forceRemote->setSettingsKey("IncrediBuild.IBConsole.Alternate");
|
||||
forceRemote->setLabel(Tr::tr("Force remote:"));
|
||||
alternate.setSettingsKey("IncrediBuild.IBConsole.ForceRemote");
|
||||
alternate.setLabel(Tr::tr("Alternate tasks preference:"));
|
||||
|
||||
auto alternate = addAspect<BoolAspect>();
|
||||
alternate->setSettingsKey("IncrediBuild.IBConsole.ForceRemote");
|
||||
alternate->setLabel(Tr::tr("Alternate tasks preference:"));
|
||||
|
||||
setCommandLineProvider([=] {
|
||||
setCommandLineProvider([this] {
|
||||
QStringList args;
|
||||
|
||||
if (nice->value() != 0)
|
||||
args.append(QString("--nice %1 ").arg(nice->value()));
|
||||
if (nice() != 0)
|
||||
args.append(QString("--nice %1 ").arg(nice()));
|
||||
|
||||
if (alternate->value())
|
||||
if (alternate())
|
||||
args.append("--alternate");
|
||||
|
||||
if (forceRemote->value())
|
||||
if (forceRemote())
|
||||
args.append("--force-remote");
|
||||
|
||||
args.append(commandBuilder->fullCommandFlag(keepJobNum->value()));
|
||||
args.append(commandBuilder.fullCommandFlag(keepJobNum()));
|
||||
|
||||
return CommandLine("ib_console", args);
|
||||
});
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <QAction>
|
||||
#include <QApplication>
|
||||
#include <QComboBox>
|
||||
#include <QDialog>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QElapsedTimer>
|
||||
@@ -334,7 +335,7 @@ private:
|
||||
QTabWidget * const m_tabWidget;
|
||||
|
||||
enum class TabIndex { Log, Capabilities, Custom };
|
||||
QListWidget *m_clients = nullptr;
|
||||
QComboBox *m_clients = nullptr;
|
||||
};
|
||||
|
||||
void LspInspector::show(const QString &defaultClient)
|
||||
@@ -401,34 +402,34 @@ LspInspectorWidget::LspInspectorWidget(LspInspector *inspector)
|
||||
this, &LspInspectorWidget::updateCapabilities);
|
||||
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 mainSplitter = new Core::MiniSplitter;
|
||||
mainSplitter->setOrientation(Qt::Horizontal);
|
||||
mainSplitter->addWidget(m_clients);
|
||||
mainSplitter->addWidget(m_tabWidget);
|
||||
mainSplitter->setStretchFactor(0, 0);
|
||||
mainSplitter->setStretchFactor(1, 1);
|
||||
|
||||
m_clients = new QComboBox;
|
||||
m_clients->addItem(Tr::tr("<Select>"));
|
||||
m_clients->addItems(inspector->clients());
|
||||
QHBoxLayout *hbox = new QHBoxLayout;
|
||||
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 LspCapabilitiesWidget, Tr::tr("Capabilities"));
|
||||
mainLayout->addWidget(mainSplitter);
|
||||
mainLayout->addWidget(m_tabWidget);
|
||||
|
||||
auto buttonBox = new QDialogButtonBox(this);
|
||||
buttonBox->setStandardButtons(QDialogButtonBox::Save | QDialogButtonBox::Close);
|
||||
const auto clearButton = buttonBox->addButton(Tr::tr("Clear"), QDialogButtonBox::ResetRole);
|
||||
connect(clearButton, &QPushButton::clicked, this, [this] {
|
||||
m_inspector->clear();
|
||||
if (m_clients->currentItem())
|
||||
currentClientChanged(m_clients->currentItem()->text());
|
||||
if (m_clients->currentIndex() != 0)
|
||||
currentClientChanged(m_clients->currentText());
|
||||
});
|
||||
mainLayout->addWidget(buttonBox);
|
||||
setLayout(mainLayout);
|
||||
|
||||
connect(m_clients,
|
||||
&QListWidget::currentTextChanged,
|
||||
&QComboBox::currentTextChanged,
|
||||
this,
|
||||
&LspInspectorWidget::currentClientChanged);
|
||||
|
||||
@@ -442,31 +443,26 @@ LspInspectorWidget::LspInspectorWidget(LspInspector *inspector)
|
||||
|
||||
void LspInspectorWidget::selectClient(const QString &clientName)
|
||||
{
|
||||
auto items = m_clients->findItems(clientName, Qt::MatchExactly);
|
||||
if (items.isEmpty())
|
||||
return;
|
||||
m_clients->setCurrentItem(items.first());
|
||||
const int index = m_clients->findText(clientName, Qt::MatchExactly);
|
||||
if (index >= 0)
|
||||
m_clients->setCurrentIndex(index);
|
||||
}
|
||||
|
||||
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);
|
||||
if (const QListWidgetItem *currentItem = m_clients->currentItem();
|
||||
currentItem && currentItem->text() == clientName) {
|
||||
if (m_clients->currentText() == clientName)
|
||||
log()->addMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
if (const QListWidgetItem *currentItem = m_clients->currentItem();
|
||||
currentItem && clientName == currentItem->text()) {
|
||||
if (m_clients->currentText() == clientName)
|
||||
capabilities()->setCapabilities(m_inspector->capabilities(clientName));
|
||||
}
|
||||
}
|
||||
|
||||
void LspInspectorWidget::currentClientChanged(const QString &clientName)
|
||||
{
|
||||
|
||||
@@ -21,5 +21,9 @@
|
||||
<file>wizards/qmlproject/component.qml.tpl</file>
|
||||
<file>wizards/qmlproject/wizard.json</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>
|
||||
</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.
|
||||
// importPaths: ["imports/CustomModule"] // Alternative API for importing modules.
|
||||
// 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 */
|
||||
MCU.Config {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"version": 1,
|
||||
"supportedProjectTypes": [ "CMakeProjectManager.CMakeProject" ],
|
||||
"id": "M.McuSupportApplication",
|
||||
"id": "M.McuSupportApplicationExample",
|
||||
"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.",
|
||||
"trDisplayName": "Qt for MCUs Application",
|
||||
"trDisplayName": "Qt for MCUs Example Application",
|
||||
"trDisplayCategory": "QmlProject Application (Qt for MCUs)",
|
||||
"icon": "../icon.png",
|
||||
"iconKind": "Themed",
|
||||
|
||||
@@ -165,7 +165,7 @@ QWidget *BuildStep::createConfigWidget()
|
||||
Layouting::Form form;
|
||||
for (BaseAspect *aspect : std::as_const(*this)) {
|
||||
if (aspect->isVisible())
|
||||
form.addItem(aspect);
|
||||
form.addItems({aspect, Layouting::br()});
|
||||
}
|
||||
form.addItem(Layouting::noMargin);
|
||||
auto widget = form.emerge();
|
||||
|
||||
@@ -218,14 +218,14 @@ QString JsonWizard::stringValue(const QString &n) const
|
||||
if (!v.isValid())
|
||||
return QString();
|
||||
|
||||
if (v.type() == QVariant::String) {
|
||||
if (v.typeId() == QVariant::String) {
|
||||
QString tmp = m_expander.expand(v.toString());
|
||||
if (tmp.isEmpty())
|
||||
tmp = QString::fromLatin1(""); // Make sure isNull() is *not* true.
|
||||
return tmp;
|
||||
}
|
||||
|
||||
if (v.type() == QVariant::StringList)
|
||||
if (v.typeId() == QVariant::StringList)
|
||||
return stringListToArrayString(v.toStringList(), &m_expander);
|
||||
|
||||
return v.toString();
|
||||
@@ -276,7 +276,7 @@ QVariant JsonWizard::value(const QString &n) const
|
||||
|
||||
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());
|
||||
return !(tmp.isEmpty() || tmp == QLatin1String("false"));
|
||||
}
|
||||
@@ -410,7 +410,7 @@ void JsonWizard::handleError(const QString &message)
|
||||
|
||||
QString JsonWizard::stringify(const QVariant &v) const
|
||||
{
|
||||
if (v.type() == QVariant::StringList)
|
||||
if (v.typeId() == QVariant::StringList)
|
||||
return stringListToArrayString(v.toStringList(), &m_expander);
|
||||
return Wizard::stringify(v);
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ static JsonWizardFactory::Generator parseGenerator(const QVariant &value, QStrin
|
||||
{
|
||||
JsonWizardFactory::Generator gen;
|
||||
|
||||
if (value.type() != QVariant::Map) {
|
||||
if (value.typeId() != QVariant::Map) {
|
||||
*errorMessage = Tr::tr("Generator is not a object.");
|
||||
return gen;
|
||||
}
|
||||
@@ -236,8 +236,8 @@ QVariant JsonWizardFactory::getDataValue(const QLatin1String &key, const QVarian
|
||||
{
|
||||
QVariant retVal = {};
|
||||
|
||||
if ((valueSet.contains(key) && valueSet.value(key).type() == QVariant::Map) ||
|
||||
(defaultValueSet.contains(key) && defaultValueSet.value(key).type() == QVariant::Map)) {
|
||||
if ((valueSet.contains(key) && valueSet.value(key).typeId() == QVariant::Map) ||
|
||||
(defaultValueSet.contains(key) && defaultValueSet.value(key).typeId() == QVariant::Map)) {
|
||||
retVal = mergeDataValueMaps(valueSet.value(key), defaultValueSet.value(key));
|
||||
} else {
|
||||
QVariant defaultValue = defaultValueSet.value(key, notExistValue);
|
||||
@@ -263,7 +263,7 @@ std::pair<int, QStringList> JsonWizardFactory::screenSizeInfoFromPage(const QStr
|
||||
return {};
|
||||
|
||||
const QVariant data = it->data;
|
||||
if (data.type() != QVariant::List)
|
||||
if (data.typeId() != QVariant::List)
|
||||
return {};
|
||||
|
||||
const QVariant screenFactorField = Utils::findOrDefault(data.toList(),
|
||||
@@ -272,11 +272,11 @@ std::pair<int, QStringList> JsonWizardFactory::screenSizeInfoFromPage(const QStr
|
||||
return "ScreenFactor" == m["name"];
|
||||
});
|
||||
|
||||
if (screenFactorField.type() != QVariant::Map)
|
||||
if (screenFactorField.typeId() != QVariant::Map)
|
||||
return {};
|
||||
|
||||
const QVariant screenFactorData = screenFactorField.toMap()["data"];
|
||||
if (screenFactorData.type() != QVariant::Map)
|
||||
if (screenFactorData.typeId() != QVariant::Map)
|
||||
return {};
|
||||
|
||||
const QVariantMap screenFactorDataMap = screenFactorData.toMap();
|
||||
@@ -304,7 +304,7 @@ JsonWizardFactory::Page JsonWizardFactory::parsePage(const QVariant &value, QStr
|
||||
{
|
||||
JsonWizardFactory::Page p;
|
||||
|
||||
if (value.type() != QVariant::Map) {
|
||||
if (value.typeId() != QVariant::Map) {
|
||||
*errorMessage = Tr::tr("Page is not an object.");
|
||||
return p;
|
||||
}
|
||||
@@ -351,9 +351,9 @@ JsonWizardFactory::Page JsonWizardFactory::parsePage(const QVariant &value, QStr
|
||||
|
||||
if (specifiedSubData.isNull())
|
||||
subData = defaultSubData;
|
||||
else if (specifiedSubData.type() == QVariant::Map)
|
||||
else if (specifiedSubData.typeId() == QVariant::Map)
|
||||
subData = mergeDataValueMaps(specifiedSubData.toMap(), defaultSubData.toMap());
|
||||
else if (specifiedSubData.type() == QVariant::List)
|
||||
else if (specifiedSubData.typeId() == QVariant::List)
|
||||
subData = specifiedSubData;
|
||||
|
||||
if (!factory->validateData(typeId, subData, errorMessage))
|
||||
@@ -648,9 +648,9 @@ QList<QVariant> JsonWizardFactory::objectOrList(const QVariant &data, QString *e
|
||||
QList<QVariant> result;
|
||||
if (data.isNull())
|
||||
*errorMessage = Tr::tr("key not found.");
|
||||
else if (data.type() == QVariant::Map)
|
||||
else if (data.typeId() == QVariant::Map)
|
||||
result.append(data);
|
||||
else if (data.type() == QVariant::List)
|
||||
else if (data.typeId() == QVariant::List)
|
||||
result = data.toList();
|
||||
else
|
||||
*errorMessage = Tr::tr("Expected an object or a list.");
|
||||
@@ -661,7 +661,7 @@ QString JsonWizardFactory::localizedString(const QVariant &value)
|
||||
{
|
||||
if (value.isNull())
|
||||
return QString();
|
||||
if (value.type() == QVariant::Map) {
|
||||
if (value.typeId() == QVariant::Map) {
|
||||
QVariantMap tmp = value.toMap();
|
||||
const QString locale = languageSetting().toLower();
|
||||
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)
|
||||
{
|
||||
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.");
|
||||
return false;
|
||||
}
|
||||
@@ -147,7 +147,7 @@ bool KitsPageFactory::validateData(Utils::Id typeId, const QVariant &data, QStri
|
||||
{
|
||||
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.");
|
||||
return false;
|
||||
}
|
||||
@@ -206,7 +206,7 @@ bool ProjectPageFactory::validateData(Utils::Id typeId, const QVariant &data, QS
|
||||
Q_UNUSED(errorMessage)
|
||||
|
||||
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.");
|
||||
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)
|
||||
{
|
||||
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.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -387,7 +387,7 @@ void ToolChainKitAspect::upgrade(Kit *k)
|
||||
const QVariant value = k->value(oldIdV2);
|
||||
if (value.isNull() && !oldValue.isNull()) {
|
||||
QVariantMap newValue;
|
||||
if (oldValue.type() == QVariant::Map) {
|
||||
if (oldValue.typeId() == QVariant::Map) {
|
||||
// Used between 4.1 and 4.2:
|
||||
newValue = oldValue.toMap();
|
||||
} else {
|
||||
|
||||
@@ -62,6 +62,8 @@
|
||||
using namespace Utils;
|
||||
using namespace Core;
|
||||
|
||||
namespace PE = 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);
|
||||
DocumentManager::addDocument(d->m_document.get());
|
||||
|
||||
d->m_macroExpander.setDisplayName(Tr::tr("Project"));
|
||||
d->m_macroExpander.registerVariable("Project:Name", Tr::tr("Project Name"),
|
||||
[this] { return displayName(); });
|
||||
d->m_macroExpander.setDisplayName(::PE::Tr::tr("Project"));
|
||||
d->m_macroExpander.registerVariable("Project:Name", ::PE::Tr::tr("Project Name"), [this] {
|
||||
return displayName();
|
||||
});
|
||||
|
||||
// Only set up containernode after d is set so that it will find the project directory!
|
||||
d->m_containerNode = std::make_unique<ContainerNode>(this);
|
||||
@@ -443,7 +446,7 @@ Tasks Project::projectIssues(const Kit *k) const
|
||||
{
|
||||
Tasks result;
|
||||
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 {};
|
||||
}
|
||||
|
||||
@@ -524,8 +527,8 @@ bool Project::copySteps(Target *sourceTarget, Target *newTarget)
|
||||
if (fatalError) {
|
||||
// That could be a more granular error message
|
||||
QMessageBox::critical(ICore::dialogParent(),
|
||||
Tr::tr("Incompatible Kit"),
|
||||
Tr::tr("Kit %1 is incompatible with kit %2.")
|
||||
::PE::Tr::tr("Incompatible Kit"),
|
||||
::PE::Tr::tr("Kit %1 is incompatible with kit %2.")
|
||||
.arg(sourceTarget->kit()->displayName())
|
||||
.arg(newTarget->kit()->displayName()));
|
||||
} else if (!buildconfigurationError.isEmpty()
|
||||
@@ -534,27 +537,27 @@ bool Project::copySteps(Target *sourceTarget, Target *newTarget)
|
||||
|
||||
QString error;
|
||||
if (!buildconfigurationError.isEmpty())
|
||||
error += Tr::tr("Build configurations:") + QLatin1Char('\n')
|
||||
error += ::PE::Tr::tr("Build configurations:") + QLatin1Char('\n')
|
||||
+ buildconfigurationError.join(QLatin1Char('\n'));
|
||||
|
||||
if (!deployconfigurationError.isEmpty()) {
|
||||
if (!error.isEmpty())
|
||||
error.append(QLatin1Char('\n'));
|
||||
error += Tr::tr("Deploy configurations:") + QLatin1Char('\n')
|
||||
error += ::PE::Tr::tr("Deploy configurations:") + QLatin1Char('\n')
|
||||
+ deployconfigurationError.join(QLatin1Char('\n'));
|
||||
}
|
||||
|
||||
if (!runconfigurationError.isEmpty()) {
|
||||
if (!error.isEmpty())
|
||||
error.append(QLatin1Char('\n'));
|
||||
error += Tr::tr("Run configurations:") + QLatin1Char('\n')
|
||||
error += ::PE::Tr::tr("Run configurations:") + QLatin1Char('\n')
|
||||
+ runconfigurationError.join(QLatin1Char('\n'));
|
||||
}
|
||||
|
||||
QMessageBox msgBox(ICore::dialogParent());
|
||||
msgBox.setIcon(QMessageBox::Warning);
|
||||
msgBox.setWindowTitle(Tr::tr("Partially Incompatible Kit"));
|
||||
msgBox.setText(Tr::tr("Some configurations could not be copied."));
|
||||
msgBox.setWindowTitle(::PE::Tr::tr("Partially Incompatible Kit"));
|
||||
msgBox.setText(::PE::Tr::tr("Some configurations could not be copied."));
|
||||
msgBox.setDetailedText(error);
|
||||
msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
|
||||
fatalError = msgBox.exec() != QDialog::Accepted;
|
||||
@@ -728,11 +731,11 @@ FilePath Project::projectDirectory(const FilePath &top)
|
||||
|
||||
void Project::changeRootProjectDirectory()
|
||||
{
|
||||
FilePath rootPath = FileUtils::getExistingDirectory(
|
||||
nullptr,
|
||||
Tr::tr("Select the Root Directory"),
|
||||
FilePath rootPath = FileUtils::getExistingDirectory(nullptr,
|
||||
::PE::Tr::tr("Select the Root Directory"),
|
||||
rootProjectDirectory(),
|
||||
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
|
||||
QFileDialog::ShowDirsOnly
|
||||
| QFileDialog::DontResolveSymlinks);
|
||||
if (rootPath != d->m_rootProjectDirectory) {
|
||||
d->m_rootProjectDirectory = rootPath;
|
||||
setNamedSettings(Constants::PROJECT_ROOT_PATH_KEY, d->m_rootProjectDirectory.toString());
|
||||
@@ -817,18 +820,25 @@ void Project::createTargetFromMap(const QVariantMap &map, int index)
|
||||
if (!deviceTypeId.isValid())
|
||||
deviceTypeId = Constants::DESKTOP_DEVICE_TYPE;
|
||||
const QString formerKitName = targetMap.value(Target::displayNameKey()).toString();
|
||||
k = KitManager::registerKit([deviceTypeId, &formerKitName](Kit *kit) {
|
||||
const QString kitNameSuggestion = formerKitName.contains(Tr::tr("Replacement for"))
|
||||
? formerKitName : Tr::tr("Replacement for \"%1\"").arg(formerKitName);
|
||||
k = KitManager::registerKit(
|
||||
[deviceTypeId, &formerKitName](Kit *kit) {
|
||||
const QString kitNameSuggestion
|
||||
= formerKitName.contains(::PE::Tr::tr("Replacement for"))
|
||||
? formerKitName
|
||||
: ::PE::Tr::tr("Replacement for \"%1\"").arg(formerKitName);
|
||||
const QString tempKitName = makeUniquelyNumbered(kitNameSuggestion,
|
||||
transform(KitManager::kits(), &Kit::unexpandedDisplayName));
|
||||
kit->setUnexpandedDisplayName(tempKitName);
|
||||
DeviceTypeKitAspect::setDeviceTypeId(kit, deviceTypeId);
|
||||
kit->makeReplacementKit();
|
||||
kit->setup();
|
||||
}, id);
|
||||
},
|
||||
id);
|
||||
QTC_ASSERT(k, return);
|
||||
TaskHub::addTask(BuildSystemTask(Task::Warning, Tr::tr("Project \"%1\" was configured for "
|
||||
TaskHub::addTask(BuildSystemTask(
|
||||
Task::Warning,
|
||||
::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())));
|
||||
@@ -1081,7 +1091,8 @@ QStringList Project::availableQmlPreviewTranslations(QString *errorMessage)
|
||||
const QDir languageDirectory(projectDirectory + "/i18n");
|
||||
const auto qmFiles = languageDirectory.entryList({"qml_*.qm"});
|
||||
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) {
|
||||
const int localeStartPosition = qmFile.lastIndexOf("_") + 1;
|
||||
const int localeEndPosition = qmFile.size() - QString(".qm").size();
|
||||
@@ -1167,7 +1178,7 @@ void Project::addVariablesToMacroExpander(const QByteArray &prefix,
|
||||
const QByteArray prefixWithoutColon = fullPrefix.chopped(1);
|
||||
expander->registerVariable(fullPrefix + "Name",
|
||||
//: %1 is something like "Active project"
|
||||
Tr::tr("%1: Name.").arg(descriptor),
|
||||
::PE::Tr::tr("%1: Name.").arg(descriptor),
|
||||
[projectGetter]() -> QString {
|
||||
if (const Project *const project = projectGetter())
|
||||
return project->displayName();
|
||||
@@ -1175,7 +1186,7 @@ void Project::addVariablesToMacroExpander(const QByteArray &prefix,
|
||||
});
|
||||
expander->registerFileVariables(prefixWithoutColon,
|
||||
//: %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 {
|
||||
if (const Project *const project = projectGetter())
|
||||
return project->projectFilePath();
|
||||
@@ -1183,7 +1194,7 @@ void Project::addVariablesToMacroExpander(const QByteArray &prefix,
|
||||
});
|
||||
expander->registerVariable(fullPrefix + "Kit:Name",
|
||||
//: %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 {
|
||||
if (const Target *const target = targetGetter())
|
||||
return target->kit()->displayName();
|
||||
@@ -1191,7 +1202,8 @@ void Project::addVariablesToMacroExpander(const QByteArray &prefix,
|
||||
});
|
||||
expander->registerVariable(fullPrefix + "BuildConfig:Name",
|
||||
//: %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 {
|
||||
if (const BuildConfiguration *const bc = bcGetter())
|
||||
return bc->displayName();
|
||||
@@ -1199,17 +1211,18 @@ void Project::addVariablesToMacroExpander(const QByteArray &prefix,
|
||||
});
|
||||
expander->registerVariable(fullPrefix + "BuildConfig:Type",
|
||||
//: %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 {
|
||||
const BuildConfiguration *const bc = bcGetter();
|
||||
const BuildConfiguration::BuildType type
|
||||
= bc ? bc->buildType() : BuildConfiguration::Unknown;
|
||||
return BuildConfiguration::buildTypeName(type);
|
||||
});
|
||||
expander
|
||||
->registerVariable(fullPrefix + "BuildConfig:Path",
|
||||
expander->registerVariable(fullPrefix + "BuildConfig:Path",
|
||||
//: %1 is something like "Active project"
|
||||
Tr::tr("%1: Full build path of active build configuration.").arg(descriptor),
|
||||
::PE::Tr::tr("%1: Full build path of active build configuration.")
|
||||
.arg(descriptor),
|
||||
[bcGetter]() -> QString {
|
||||
if (const BuildConfiguration *const bc = bcGetter())
|
||||
return bc->buildDirectory().toUserOutput();
|
||||
@@ -1217,7 +1230,8 @@ void Project::addVariablesToMacroExpander(const QByteArray &prefix,
|
||||
});
|
||||
expander->registerPrefix(fullPrefix + "BuildConfig:Env",
|
||||
//: %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) {
|
||||
if (BuildConfiguration *const bc = bcGetter())
|
||||
return bc->environment().expandedValueForKey(var);
|
||||
@@ -1226,7 +1240,8 @@ void Project::addVariablesToMacroExpander(const QByteArray &prefix,
|
||||
|
||||
expander->registerVariable(fullPrefix + "RunConfig:Name",
|
||||
//: %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 {
|
||||
if (const RunConfiguration *const rc = rcGetter())
|
||||
return rc->displayName();
|
||||
@@ -1234,16 +1249,18 @@ void Project::addVariablesToMacroExpander(const QByteArray &prefix,
|
||||
});
|
||||
expander->registerFileVariables(fullPrefix + "RunConfig:Executable",
|
||||
//: %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),
|
||||
[rcGetter]() -> FilePath {
|
||||
if (const RunConfiguration *const rc = rcGetter())
|
||||
return rc->commandLine().executable();
|
||||
return {};
|
||||
});
|
||||
expander->registerPrefix(fullPrefix + "RunConfig:Env",
|
||||
expander
|
||||
->registerPrefix(fullPrefix + "RunConfig:Env",
|
||||
//: %1 is something like "Active project"
|
||||
Tr::tr("%1: Variables in the environment of the active run configuration.")
|
||||
::PE::Tr::tr(
|
||||
"%1: Variables in the environment of the active run configuration.")
|
||||
.arg(descriptor),
|
||||
[rcGetter](const QString &var) {
|
||||
if (const RunConfiguration *const rc = rcGetter()) {
|
||||
@@ -1254,7 +1271,8 @@ void Project::addVariablesToMacroExpander(const QByteArray &prefix,
|
||||
});
|
||||
expander->registerVariable(fullPrefix + "RunConfig:WorkingDir",
|
||||
//: %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),
|
||||
[rcGetter] {
|
||||
if (const RunConfiguration *const rc = rcGetter()) {
|
||||
|
||||
@@ -51,11 +51,8 @@ public:
|
||||
const FilePath &newFilePath) override;
|
||||
QString name() const override { return QLatin1String("python"); }
|
||||
|
||||
bool saveRawFileList(const QStringList &rawFileList);
|
||||
bool saveRawList(const QStringList &rawList, const FilePath &filePath);
|
||||
void parse();
|
||||
QStringList processEntries(const QStringList &paths,
|
||||
QHash<QString, QString> *map = nullptr) const;
|
||||
bool save();
|
||||
|
||||
bool writePyProjectFile(const FilePath &filePath, QString &content,
|
||||
const QStringList &rawList, QString *errorMessage);
|
||||
@@ -63,12 +60,14 @@ public:
|
||||
void triggerParsing() final;
|
||||
|
||||
private:
|
||||
QStringList m_rawFileList;
|
||||
QStringList m_files;
|
||||
QStringList m_rawQmlImportPathList;
|
||||
QStringList m_qmlImportPaths;
|
||||
QHash<QString, QString> m_rawListEntries;
|
||||
QHash<QString, QString> m_rawQmlImportPathEntries;
|
||||
struct FileEntry {
|
||||
QString rawEntry;
|
||||
FilePath filePath;
|
||||
};
|
||||
QList<FileEntry> processEntries(const QStringList &paths) const;
|
||||
|
||||
QList<FileEntry> m_files;
|
||||
QList<FileEntry> m_qmlImportPaths;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -125,9 +124,9 @@ static QStringList readLines(const FilePath &projectFile)
|
||||
QSet<QString> visited = { projectFileName };
|
||||
QStringList lines = { projectFileName };
|
||||
|
||||
QFile file(projectFile.toString());
|
||||
if (file.open(QFile::ReadOnly)) {
|
||||
QTextStream stream(&file);
|
||||
const expected_str<QByteArray> contents = projectFile.fileContents();
|
||||
if (contents) {
|
||||
QTextStream stream(contents.value());
|
||||
|
||||
while (true) {
|
||||
const QString line = stream.readLine();
|
||||
@@ -145,17 +144,17 @@ static QStringList readLines(const FilePath &projectFile)
|
||||
|
||||
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);
|
||||
if (obj.contains("files")) {
|
||||
const QJsonValue files = obj.value("files");
|
||||
const QJsonArray files_array = files.toArray();
|
||||
QSet<QString> visited;
|
||||
for (const auto &file : files_array)
|
||||
visited.insert(file.toString());
|
||||
|
||||
lines.append(Utils::toList(visited));
|
||||
for (const QJsonValue &file : obj.value("files").toArray()) {
|
||||
const QString fileName = file.toString();
|
||||
if (visited.contains(fileName))
|
||||
continue;
|
||||
lines.append(fileName);
|
||||
visited.insert(fileName);
|
||||
}
|
||||
|
||||
return lines;
|
||||
@@ -226,20 +225,19 @@ void PythonBuildSystem::triggerParsing()
|
||||
QList<BuildTargetInfo> appTargets;
|
||||
|
||||
auto newRoot = std::make_unique<PythonProjectNode>(projectDirectory());
|
||||
for (const QString &f : std::as_const(m_files)) {
|
||||
const QString displayName = baseDir.relativeFilePath(f);
|
||||
const FilePath filePath = FilePath::fromString(f);
|
||||
const FileType fileType = getFileType(filePath);
|
||||
for (const FileEntry &entry: std::as_const(m_files)) {
|
||||
const QString displayName = entry.filePath.relativePathFrom(projectDirectory()).toUserOutput();
|
||||
const FileType fileType = getFileType(entry.filePath);
|
||||
|
||||
newRoot->addNestedNode(std::make_unique<PythonFileNode>(filePath, displayName, fileType));
|
||||
const MimeType mt = mimeTypeForFile(filePath, MimeMatchMode::MatchExtension);
|
||||
newRoot->addNestedNode(std::make_unique<PythonFileNode>(entry.filePath, displayName, fileType));
|
||||
const MimeType mt = mimeTypeForFile(entry.filePath, MimeMatchMode::MatchExtension);
|
||||
if (mt.matchesName(Constants::C_PY_MIMETYPE) || mt.matchesName(Constants::C_PY3_MIMETYPE)) {
|
||||
BuildTargetInfo bti;
|
||||
bti.displayName = displayName;
|
||||
bti.buildKey = f;
|
||||
bti.targetFilePath = filePath;
|
||||
bti.buildKey = entry.filePath.toString();
|
||||
bti.targetFilePath = entry.filePath;
|
||||
bti.projectFilePath = projectFilePath();
|
||||
bti.isQtcRunnable = filePath.fileName() == "main.py";
|
||||
bti.isQtcRunnable = entry.filePath.fileName() == "main.py";
|
||||
appTargets.append(bti);
|
||||
}
|
||||
}
|
||||
@@ -252,9 +250,9 @@ void PythonBuildSystem::triggerParsing()
|
||||
const auto hiddenRccFolders = project()->files(Project::HiddenRccFolders);
|
||||
auto projectInfo = modelManager->defaultProjectInfoForProject(project(), hiddenRccFolders);
|
||||
|
||||
for (const QString &importPath : std::as_const(m_qmlImportPaths)) {
|
||||
const FilePath filePath = FilePath::fromString(importPath);
|
||||
projectInfo.importPaths.maybeInsert(filePath, QmlJS::Dialect::Qml);
|
||||
for (const FileEntry &importPath : std::as_const(m_qmlImportPaths)) {
|
||||
if (!importPath.filePath.isEmpty())
|
||||
projectInfo.importPaths.maybeInsert(importPath.filePath, QmlJS::Dialect::Qml);
|
||||
}
|
||||
|
||||
modelManager->updateProjectInfo(projectInfo, project());
|
||||
@@ -265,95 +263,62 @@ void PythonBuildSystem::triggerParsing()
|
||||
emitBuildSystemUpdated();
|
||||
}
|
||||
|
||||
bool PythonBuildSystem::saveRawFileList(const QStringList &rawFileList)
|
||||
{
|
||||
const bool result = saveRawList(rawFileList, projectFilePath());
|
||||
// refresh(PythonProject::Files);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool PythonBuildSystem::saveRawList(const QStringList &rawList, const FilePath &filePath)
|
||||
bool PythonBuildSystem::save()
|
||||
{
|
||||
const FilePath filePath = projectFilePath();
|
||||
const QStringList rawList = Utils::transform(m_files, &FileEntry::rawEntry);
|
||||
const FileChangeBlocker changeGuarg(filePath);
|
||||
bool result = false;
|
||||
|
||||
QByteArray newContents;
|
||||
|
||||
// New project file
|
||||
if (filePath.endsWith(".pyproject")) {
|
||||
FileSaver saver(filePath, QIODevice::ReadOnly | QIODevice::Text);
|
||||
if (!saver.hasError()) {
|
||||
QString content = QTextStream(saver.file()).readAll();
|
||||
if (saver.finalize(ICore::dialogParent())) {
|
||||
QString errorMessage;
|
||||
result = writePyProjectFile(filePath, content, rawList, &errorMessage);
|
||||
if (!errorMessage.isEmpty())
|
||||
MessageManager::writeDisrupting(errorMessage);
|
||||
}
|
||||
expected_str<QByteArray> contents = filePath.fileContents();
|
||||
if (contents) {
|
||||
QJsonDocument doc = QJsonDocument::fromJson(*contents);
|
||||
QJsonObject project = doc.object();
|
||||
project["files"] = QJsonArray::fromStringList(rawList);
|
||||
doc.setObject(project);
|
||||
newContents = doc.toJson();
|
||||
} else {
|
||||
MessageManager::writeDisrupting(contents.error());
|
||||
}
|
||||
} else { // Old project file
|
||||
FileSaver saver(filePath, QIODevice::WriteOnly | QIODevice::Text);
|
||||
if (!saver.hasError()) {
|
||||
QTextStream stream(saver.file());
|
||||
for (const QString &filePath : rawList)
|
||||
stream << filePath << '\n';
|
||||
saver.setResult(&stream);
|
||||
result = saver.finalize(ICore::dialogParent());
|
||||
}
|
||||
newContents = rawList.join('\n').toUtf8();
|
||||
}
|
||||
|
||||
const expected_str<qint64> writeResult = filePath.writeFileContents(newContents);
|
||||
if (writeResult)
|
||||
result = true;
|
||||
else
|
||||
MessageManager::writeDisrupting(writeResult.error());
|
||||
|
||||
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 *)
|
||||
{
|
||||
QStringList newList = m_rawFileList;
|
||||
const Utils::FilePath projectDir = projectDirectory();
|
||||
|
||||
const QDir baseDir(projectDirectory().toString());
|
||||
for (const FilePath &filePath : filePaths)
|
||||
newList.append(baseDir.relativeFilePath(filePath.toString()));
|
||||
for (const FilePath &filePath : filePaths) {
|
||||
if (!projectDir.isSameDevice(filePath))
|
||||
return false;
|
||||
m_files.append(FileEntry{filePath.relativePathFrom(projectDir).toString(), filePath});
|
||||
}
|
||||
|
||||
return saveRawFileList(newList);
|
||||
return save();
|
||||
}
|
||||
|
||||
RemovedFilesFromProject PythonBuildSystem::removeFiles(Node *, const FilePaths &filePaths, FilePaths *)
|
||||
{
|
||||
QStringList newList = m_rawFileList;
|
||||
|
||||
for (const FilePath &filePath : filePaths) {
|
||||
const QHash<QString, QString>::iterator i = m_rawListEntries.find(filePath.toString());
|
||||
if (i != m_rawListEntries.end())
|
||||
newList.removeOne(i.value());
|
||||
Utils::eraseOne(m_files,
|
||||
[filePath](const FileEntry &entry) { return filePath == entry.filePath; });
|
||||
}
|
||||
|
||||
bool res = saveRawFileList(newList);
|
||||
|
||||
return res ? RemovedFilesFromProject::Ok : RemovedFilesFromProject::Error;
|
||||
return save() ? RemovedFilesFromProject::Ok : RemovedFilesFromProject::Error;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
QStringList newList = m_rawFileList;
|
||||
|
||||
const QHash<QString, QString>::iterator i = m_rawListEntries.find(oldFilePath.toString());
|
||||
if (i != m_rawListEntries.end()) {
|
||||
const int index = newList.indexOf(i.value());
|
||||
if (index != -1) {
|
||||
const QDir baseDir(projectDirectory().toString());
|
||||
newList.replace(index, baseDir.relativeFilePath(newFilePath.toString()));
|
||||
for (FileEntry &entry : m_files) {
|
||||
if (entry.filePath == oldFilePath) {
|
||||
entry.filePath = newFilePath;
|
||||
entry.rawEntry = newFilePath.relativeChildPath(projectDirectory()).toString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return saveRawFileList(newList);
|
||||
return save();
|
||||
}
|
||||
|
||||
void PythonBuildSystem::parse()
|
||||
{
|
||||
m_rawListEntries.clear();
|
||||
m_rawQmlImportPathEntries.clear();
|
||||
m_files.clear();
|
||||
m_qmlImportPaths.clear();
|
||||
|
||||
QStringList files;
|
||||
QStringList qmlImportPaths;
|
||||
|
||||
const FilePath filePath = projectFilePath();
|
||||
// The PySide project file is JSON based
|
||||
if (filePath.endsWith(".pyproject")) {
|
||||
QString errorMessage;
|
||||
m_rawFileList = readLinesJson(filePath, &errorMessage);
|
||||
files = readLinesJson(filePath, &errorMessage);
|
||||
if (!errorMessage.isEmpty())
|
||||
MessageManager::writeFlashing(errorMessage);
|
||||
|
||||
errorMessage.clear();
|
||||
m_rawQmlImportPathList = readImportPathsJson(filePath, &errorMessage);
|
||||
qmlImportPaths = readImportPathsJson(filePath, &errorMessage);
|
||||
if (!errorMessage.isEmpty())
|
||||
MessageManager::writeFlashing(errorMessage);
|
||||
} else if (filePath.endsWith(".pyqtc")) {
|
||||
// To keep compatibility with PyQt we keep the compatibility with plain
|
||||
// text files as project files.
|
||||
m_rawFileList = readLines(filePath);
|
||||
files = readLines(filePath);
|
||||
}
|
||||
|
||||
m_files = processEntries(m_rawFileList, &m_rawListEntries);
|
||||
m_qmlImportPaths = processEntries(m_rawQmlImportPathList, &m_rawQmlImportPathEntries);
|
||||
m_files = processEntries(files);
|
||||
m_qmlImportPaths = processEntries(qmlImportPaths);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expands environment variables in the given \a string when they are written
|
||||
* like $$(VARIABLE).
|
||||
*/
|
||||
static void expandEnvironmentVariables(const QProcessEnvironment &env, QString &string)
|
||||
static void expandEnvironmentVariables(const Environment &env, QString &string)
|
||||
{
|
||||
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
|
||||
* project to an absolute path.
|
||||
*
|
||||
* The \a map variable is an optional argument that will map the returned
|
||||
* absolute paths back to their original \a paths.
|
||||
* project to an absolute path for all given raw paths
|
||||
*/
|
||||
QStringList PythonBuildSystem::processEntries(const QStringList &paths,
|
||||
QHash<QString, QString> *map) const
|
||||
QList<PythonBuildSystem::FileEntry> PythonBuildSystem::processEntries(
|
||||
const QStringList &rawPaths) const
|
||||
{
|
||||
const QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
||||
const QDir projectDir(projectDirectory().toString());
|
||||
QList<FileEntry> processed;
|
||||
const FilePath projectDir = projectDirectory();
|
||||
const Environment env = projectDirectory().deviceEnvironment();
|
||||
|
||||
QFileInfo fileInfo;
|
||||
QStringList absolutePaths;
|
||||
for (const QString &path : paths) {
|
||||
QString trimmedPath = path.trimmed();
|
||||
if (trimmedPath.isEmpty())
|
||||
continue;
|
||||
|
||||
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);
|
||||
for (const QString &rawPath : rawPaths) {
|
||||
FilePath resolvedPath;
|
||||
QString path = rawPath.trimmed();
|
||||
if (!path.isEmpty()) {
|
||||
expandEnvironmentVariables(env, path);
|
||||
resolvedPath = projectDir.resolvePath(path);
|
||||
}
|
||||
processed << FileEntry{rawPath, resolvedPath};
|
||||
}
|
||||
absolutePaths.removeDuplicates();
|
||||
return absolutePaths;
|
||||
return processed;
|
||||
}
|
||||
|
||||
Project::RestoreResult PythonProject::fromMap(const QVariantMap &map, QString *errorMessage)
|
||||
|
||||
@@ -90,6 +90,7 @@ public:
|
||||
, m_executable(new PathChooser())
|
||||
{
|
||||
m_executable->setExpectedKind(PathChooser::ExistingCommand);
|
||||
m_executable->setAllowPathFromDevice(true);
|
||||
|
||||
connect(m_name, &QLineEdit::textChanged, this, &InterpreterDetailsWidget::changed);
|
||||
connect(m_executable, &PathChooser::textChanged, this, &InterpreterDetailsWidget::changed);
|
||||
|
||||
@@ -60,7 +60,7 @@ QString toJSLiteral(const QVariant &val)
|
||||
{
|
||||
if (!val.isValid())
|
||||
return QString("undefined");
|
||||
if (val.type() == QVariant::List || val.type() == QVariant::StringList) {
|
||||
if (val.typeId() == QVariant::List || val.typeId() == QVariant::StringList) {
|
||||
QString res;
|
||||
const auto list = val.toList();
|
||||
for (const QVariant &child : list) {
|
||||
@@ -71,7 +71,7 @@ QString toJSLiteral(const QVariant &val)
|
||||
res.append(']');
|
||||
return res;
|
||||
}
|
||||
if (val.type() == QVariant::Map) {
|
||||
if (val.typeId() == QVariant::Map) {
|
||||
const QVariantMap &vm = val.toMap();
|
||||
QString str("{");
|
||||
for (auto it = vm.begin(); it != vm.end(); ++it) {
|
||||
@@ -82,7 +82,7 @@ QString toJSLiteral(const QVariant &val)
|
||||
str += '}';
|
||||
return str;
|
||||
}
|
||||
if (val.type() == QVariant::Bool)
|
||||
if (val.typeId() == QVariant::Bool)
|
||||
return toJSLiteral(val.toBool());
|
||||
if (val.canConvert(QVariant::String))
|
||||
return toJSLiteral(val.toString());
|
||||
|
||||
@@ -952,7 +952,7 @@ extend_qtc_plugin(QmlDesigner
|
||||
SOURCES_PREFIX components/richtexteditor
|
||||
SOURCES
|
||||
hyperlinkdialog.cpp hyperlinkdialog.h hyperlinkdialog.ui
|
||||
richtexteditor.cpp richtexteditor.h hyperlinkdialog.ui
|
||||
richtexteditor.cpp richtexteditor.h
|
||||
richtexteditorproxy.cpp richtexteditorproxy.h
|
||||
)
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#include "bakelightsconnectionmanager.h"
|
||||
|
||||
#include "qmldesignertr.h"
|
||||
|
||||
#include <puppettocreatorcommand.h>
|
||||
|
||||
namespace QmlDesigner {
|
||||
@@ -34,10 +36,10 @@ void BakeLightsConnectionManager::dispatchCommand(const QVariant &command,
|
||||
m_progressCallback(cmd.data().toString());
|
||||
break;
|
||||
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;
|
||||
case PuppetToCreatorCommand::BakeLightsFinished:
|
||||
m_finishedCallback(tr("Baking finished!"));
|
||||
m_finishedCallback(Tr::tr("Baking finished!"));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include "richtexteditor.h"
|
||||
#include "ui_richtexteditor.h"
|
||||
#include "hyperlinkdialog.h"
|
||||
|
||||
#include <utils/layoutbuilder.h>
|
||||
#include <utils/stylehelper.h>
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <QAction>
|
||||
@@ -19,8 +21,9 @@
|
||||
#include <QTextTableFormat>
|
||||
#include <QToolButton>
|
||||
#include <QWidgetAction>
|
||||
|
||||
#include <utils/stylehelper.h>
|
||||
#include <QApplication>
|
||||
#include <QTextEdit>
|
||||
#include <QToolBar>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
@@ -89,20 +92,41 @@ static QPixmap drawColorBox(const QColor& color, const QSize& size, int borderWi
|
||||
|
||||
RichTextEditor::RichTextEditor(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, ui(new Ui::RichTextEditor)
|
||||
, m_linkDialog(new HyperlinkDialog(this))
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->textEdit->setTextInteractionFlags(Qt::TextEditorInteraction | Qt::LinksAccessibleByMouse);
|
||||
ui->tableBar->setVisible(false);
|
||||
|
||||
resize(428, 283);
|
||||
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 QString toolBarStyleSheet =
|
||||
QString("QToolBar { background-color: %1; border-width: 1px }").arg(backColor.name());
|
||||
|
||||
ui->toolBar->setStyleSheet(toolBarStyleSheet);
|
||||
ui->tableBar->setStyleSheet(toolBarStyleSheet);
|
||||
m_toolBar->setStyleSheet(toolBarStyleSheet);
|
||||
m_tableBar->setStyleSheet(toolBarStyleSheet);
|
||||
|
||||
setupEditActions();
|
||||
setupTextActions();
|
||||
@@ -113,16 +137,16 @@ RichTextEditor::RichTextEditor(QWidget *parent)
|
||||
setupFontActions();
|
||||
setupTableActions();
|
||||
|
||||
connect(ui->textEdit, &QTextEdit::currentCharFormatChanged,
|
||||
connect(m_textEdit, &QTextEdit::currentCharFormatChanged,
|
||||
this, &RichTextEditor::currentCharFormatChanged);
|
||||
connect(ui->textEdit, &QTextEdit::cursorPositionChanged,
|
||||
connect(m_textEdit, &QTextEdit::cursorPositionChanged,
|
||||
this, &RichTextEditor::cursorPositionChanged);
|
||||
connect(ui->textEdit, &QTextEdit::textChanged,
|
||||
connect(m_textEdit, &QTextEdit::textChanged,
|
||||
this, &RichTextEditor::onTextChanged);
|
||||
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();
|
||||
|
||||
charFormat.setForeground(QApplication::palette().color(QPalette::Link));
|
||||
@@ -145,7 +169,7 @@ RichTextEditor::RichTextEditor(QWidget *parent)
|
||||
m_linkDialog->hide();
|
||||
});
|
||||
|
||||
ui->textEdit->setFocus();
|
||||
m_textEdit->setFocus();
|
||||
m_linkDialog->hide();
|
||||
}
|
||||
|
||||
@@ -155,22 +179,22 @@ RichTextEditor::~RichTextEditor()
|
||||
|
||||
void RichTextEditor::setPlainText(const QString &text)
|
||||
{
|
||||
ui->textEdit->setPlainText(text);
|
||||
m_textEdit->setPlainText(text);
|
||||
}
|
||||
|
||||
QString RichTextEditor::plainText() const
|
||||
{
|
||||
return ui->textEdit->toPlainText();
|
||||
return m_textEdit->toPlainText();
|
||||
}
|
||||
|
||||
void RichTextEditor::setRichText(const QString &text)
|
||||
{
|
||||
ui->textEdit->setHtml(text);
|
||||
m_textEdit->setHtml(text);
|
||||
}
|
||||
|
||||
void RichTextEditor::setTabChangesFocus(bool change)
|
||||
{
|
||||
ui->textEdit->setTabChangesFocus(change);
|
||||
m_textEdit->setTabChangesFocus(change);
|
||||
}
|
||||
|
||||
void RichTextEditor::setImageActionVisible(bool change)
|
||||
@@ -180,7 +204,7 @@ void RichTextEditor::setImageActionVisible(bool change)
|
||||
|
||||
void RichTextEditor::setDocumentBaseUrl(const QUrl& url)
|
||||
{
|
||||
ui->textEdit->document()->setBaseUrl(url);
|
||||
m_textEdit->document()->setBaseUrl(url);
|
||||
}
|
||||
|
||||
QIcon RichTextEditor::getIcon(Theme::Icon icon)
|
||||
@@ -194,7 +218,7 @@ QIcon RichTextEditor::getIcon(Theme::Icon icon)
|
||||
|
||||
QString RichTextEditor::richText() const
|
||||
{
|
||||
return ui->textEdit->toHtml();
|
||||
return m_textEdit->toHtml();
|
||||
}
|
||||
|
||||
void RichTextEditor::currentCharFormatChanged(const QTextCharFormat &format)
|
||||
@@ -205,9 +229,9 @@ void RichTextEditor::currentCharFormatChanged(const QTextCharFormat &format)
|
||||
|
||||
void RichTextEditor::cursorPositionChanged()
|
||||
{
|
||||
alignmentChanged(ui->textEdit->alignment());
|
||||
styleChanged(ui->textEdit->textCursor());
|
||||
tableChanged(ui->textEdit->textCursor());
|
||||
alignmentChanged(m_textEdit->alignment());
|
||||
styleChanged(m_textEdit->textCursor());
|
||||
tableChanged(m_textEdit->textCursor());
|
||||
}
|
||||
|
||||
void RichTextEditor::onTextChanged() {
|
||||
@@ -216,11 +240,11 @@ void RichTextEditor::onTextChanged() {
|
||||
|
||||
void RichTextEditor::mergeFormatOnWordOrSelection(const QTextCharFormat &format)
|
||||
{
|
||||
QTextCursor cursor = ui->textEdit->textCursor();
|
||||
QTextCursor cursor = m_textEdit->textCursor();
|
||||
if (!cursor.hasSelection())
|
||||
cursor.select(QTextCursor::WordUnderCursor);
|
||||
cursor.mergeCharFormat(format);
|
||||
ui->textEdit->mergeCurrentCharFormat(format);
|
||||
m_textEdit->mergeCurrentCharFormat(format);
|
||||
}
|
||||
|
||||
void RichTextEditor::fontChanged(const QFont &f)
|
||||
@@ -243,7 +267,7 @@ void RichTextEditor::fontChanged(const QFont &f)
|
||||
|
||||
void RichTextEditor::colorChanged(const QColor &c)
|
||||
{
|
||||
QPixmap colorBox(drawColorBox(c, ui->tableBar->iconSize()));
|
||||
QPixmap colorBox(drawColorBox(c, m_tableBar->iconSize()));
|
||||
m_actionTextColor->setIcon(colorBox);
|
||||
}
|
||||
|
||||
@@ -293,7 +317,7 @@ void RichTextEditor::tableChanged(const QTextCursor &cursor)
|
||||
|
||||
if (currentTable) {
|
||||
m_actionTableSettings->setChecked(true);
|
||||
ui->tableBar->setVisible(true);
|
||||
m_tableBar->setVisible(true);
|
||||
|
||||
setTableActionsActive(true);
|
||||
}
|
||||
@@ -305,27 +329,27 @@ void RichTextEditor::tableChanged(const QTextCursor &cursor)
|
||||
void RichTextEditor::setupEditActions()
|
||||
{
|
||||
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);
|
||||
connect(ui->textEdit->document(), &QTextDocument::undoAvailable,
|
||||
connect(m_textEdit->document(), &QTextDocument::undoAvailable,
|
||||
actionUndo, &QAction::setEnabled);
|
||||
|
||||
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);
|
||||
connect(ui->textEdit->document(), &QTextDocument::redoAvailable,
|
||||
connect(m_textEdit->document(), &QTextDocument::redoAvailable,
|
||||
actionRedo, &QAction::setEnabled);
|
||||
|
||||
actionUndo->setEnabled(ui->textEdit->document()->isUndoAvailable());
|
||||
actionRedo->setEnabled(ui->textEdit->document()->isRedoAvailable());
|
||||
actionUndo->setEnabled(m_textEdit->document()->isUndoAvailable());
|
||||
actionRedo->setEnabled(m_textEdit->document()->isRedoAvailable());
|
||||
|
||||
ui->toolBar->addSeparator();
|
||||
m_toolBar->addSeparator();
|
||||
}
|
||||
|
||||
void RichTextEditor::setupTextActions()
|
||||
{
|
||||
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) {
|
||||
QTextCharFormat fmt;
|
||||
fmt.setFontWeight(checked ? QFont::Bold : QFont::Normal);
|
||||
@@ -338,7 +362,7 @@ void RichTextEditor::setupTextActions()
|
||||
m_actionTextBold->setCheckable(true);
|
||||
|
||||
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) {
|
||||
QTextCharFormat fmt;
|
||||
fmt.setFontItalic(checked);
|
||||
@@ -351,7 +375,7 @@ void RichTextEditor::setupTextActions()
|
||||
m_actionTextItalic->setCheckable(true);
|
||||
|
||||
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) {
|
||||
QTextCharFormat fmt;
|
||||
fmt.setFontUnderline(checked);
|
||||
@@ -363,7 +387,7 @@ void RichTextEditor::setupTextActions()
|
||||
m_actionTextUnderline->setFont(underline);
|
||||
m_actionTextUnderline->setCheckable(true);
|
||||
|
||||
ui->toolBar->addSeparator();
|
||||
m_toolBar->addSeparator();
|
||||
}
|
||||
|
||||
void RichTextEditor::setupImageActions()
|
||||
@@ -379,12 +403,12 @@ void RichTextEditor::setupImageActions()
|
||||
for (QString& filePath : files) {
|
||||
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);
|
||||
|
||||
setImageActionVisible(false);
|
||||
@@ -393,8 +417,8 @@ void RichTextEditor::setupImageActions()
|
||||
void RichTextEditor::setupHyperlinkActions()
|
||||
{
|
||||
const QIcon bulletIcon(getIcon(Theme::Icon::actionIconBinding));
|
||||
m_actionHyperlink = ui->toolBar->addAction(bulletIcon, tr("Hyperlink Settings"), [this]() {
|
||||
QTextCursor cursor = ui->textEdit->textCursor();
|
||||
m_actionHyperlink = m_toolBar->addAction(bulletIcon, tr("Hyperlink Settings"), [this]() {
|
||||
QTextCursor cursor = m_textEdit->textCursor();
|
||||
QTextCharFormat linkFormat = cursor.charFormat();
|
||||
if (linkFormat.isAnchor()) {
|
||||
m_linkDialog->setLink(linkFormat.anchorHref());
|
||||
@@ -410,37 +434,37 @@ void RichTextEditor::setupHyperlinkActions()
|
||||
});
|
||||
m_actionHyperlink->setCheckable(false);
|
||||
|
||||
ui->toolBar->addSeparator();
|
||||
m_toolBar->addSeparator();
|
||||
}
|
||||
|
||||
void RichTextEditor::setupAlignActions()
|
||||
{
|
||||
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->setCheckable(true);
|
||||
m_actionAlignLeft->setPriority(QAction::LowPriority);
|
||||
|
||||
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->setCheckable(true);
|
||||
m_actionAlignCenter->setPriority(QAction::LowPriority);
|
||||
|
||||
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->setCheckable(true);
|
||||
m_actionAlignRight->setPriority(QAction::LowPriority);
|
||||
|
||||
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->setCheckable(true);
|
||||
m_actionAlignJustify->setPriority(QAction::LowPriority);
|
||||
|
||||
// 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()) {
|
||||
alignGroup->addAction(m_actionAlignLeft);
|
||||
@@ -453,15 +477,15 @@ void RichTextEditor::setupAlignActions()
|
||||
}
|
||||
alignGroup->addAction(m_actionAlignJustify);
|
||||
|
||||
ui->toolBar->addActions(alignGroup->actions());
|
||||
m_toolBar->addActions(alignGroup->actions());
|
||||
|
||||
ui->toolBar->addSeparator();
|
||||
m_toolBar->addSeparator();
|
||||
}
|
||||
|
||||
void RichTextEditor::setupListActions()
|
||||
{
|
||||
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) {
|
||||
m_actionNumberedList->setChecked(false);
|
||||
textStyle(QTextListFormat::ListDisc);
|
||||
@@ -473,7 +497,7 @@ void RichTextEditor::setupListActions()
|
||||
m_actionBulletList->setCheckable(true);
|
||||
|
||||
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) {
|
||||
m_actionBulletList->setChecked(false);
|
||||
textStyle(QTextListFormat::ListDecimal);
|
||||
@@ -484,15 +508,15 @@ void RichTextEditor::setupListActions()
|
||||
});
|
||||
m_actionNumberedList->setCheckable(true);
|
||||
|
||||
ui->toolBar->addSeparator();
|
||||
m_toolBar->addSeparator();
|
||||
}
|
||||
|
||||
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]() {
|
||||
QColor col = QColorDialog::getColor(ui->textEdit->textColor(), this);
|
||||
m_actionTextColor = m_toolBar->addAction(colorBox, tr("&Color..."), [this]() {
|
||||
QColor col = QColorDialog::getColor(m_textEdit->textColor(), this);
|
||||
if (!col.isValid())
|
||||
return;
|
||||
QTextCharFormat fmt;
|
||||
@@ -505,7 +529,7 @@ void RichTextEditor::setupFontActions()
|
||||
m_fontNameAction->setInitializer([this](QFontComboBox *w) {
|
||||
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) {
|
||||
QTextCharFormat fmt;
|
||||
fmt.setFontFamily(f);
|
||||
@@ -514,7 +538,7 @@ void RichTextEditor::setupFontActions()
|
||||
});
|
||||
|
||||
m_fontNameAction->setDefaultWidget(new QFontComboBox);
|
||||
ui->toolBar->addAction(m_fontNameAction);
|
||||
m_toolBar->addAction(m_fontNameAction);
|
||||
|
||||
m_fontSizeAction = new FontWidgetActions<QComboBox>(this);
|
||||
m_fontSizeAction->setInitializer([this](QComboBox *w) {
|
||||
@@ -525,7 +549,7 @@ void RichTextEditor::setupFontActions()
|
||||
const QList<int> standardSizes = QFontDatabase::standardSizes();
|
||||
for (const int size : standardSizes)
|
||||
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) {
|
||||
qreal pointSize = p.toDouble();
|
||||
if (pointSize > 0.0) {
|
||||
@@ -537,17 +561,17 @@ void RichTextEditor::setupFontActions()
|
||||
});
|
||||
|
||||
m_fontSizeAction->setDefaultWidget(new QComboBox);
|
||||
ui->toolBar->addAction(m_fontSizeAction);
|
||||
m_toolBar->addAction(m_fontSizeAction);
|
||||
|
||||
|
||||
ui->toolBar->addSeparator();
|
||||
m_toolBar->addSeparator();
|
||||
}
|
||||
|
||||
void RichTextEditor::setupTableActions()
|
||||
{
|
||||
const QIcon tableIcon(getIcon(Theme::Icon::addTable));
|
||||
m_actionTableSettings = ui->toolBar->addAction(tableIcon, tr("&Table Settings"), [this](bool checked) {
|
||||
ui->tableBar->setVisible(checked);
|
||||
m_actionTableSettings = m_toolBar->addAction(tableIcon, tr("&Table Settings"), [this](bool checked) {
|
||||
m_tableBar->setVisible(checked);
|
||||
});
|
||||
m_actionTableSettings->setShortcut(Qt::CTRL | Qt::Key_T);
|
||||
m_actionTableSettings->setCheckable(true);
|
||||
@@ -556,8 +580,8 @@ void RichTextEditor::setupTableActions()
|
||||
//table bar:
|
||||
|
||||
const QIcon createTableIcon(getIcon(Theme::Icon::addTable));
|
||||
m_actionCreateTable = ui->tableBar->addAction(createTableIcon, tr("Create Table"), [this]() {
|
||||
QTextCursor cursor = ui->textEdit->textCursor();
|
||||
m_actionCreateTable = m_tableBar->addAction(createTableIcon, tr("Create Table"), [this]() {
|
||||
QTextCursor cursor = m_textEdit->textCursor();
|
||||
cursorEditBlock(cursor, [&] () {
|
||||
//format table cells to look a bit better:
|
||||
QTextTableFormat tableFormat;
|
||||
@@ -568,15 +592,15 @@ void RichTextEditor::setupTableActions()
|
||||
cursor.insertTable(1, 1, tableFormat);
|
||||
|
||||
//move cursor into the first cell of the table:
|
||||
ui->textEdit->setTextCursor(cursor);
|
||||
m_textEdit->setTextCursor(cursor);
|
||||
});
|
||||
});
|
||||
m_actionCreateTable->setCheckable(false);
|
||||
|
||||
const QIcon removeTableIcon(getIcon(Theme::Icon::deleteTable));
|
||||
m_actionRemoveTable = ui->tableBar->addAction(removeTableIcon, tr("Remove Table"), [this]() {
|
||||
QTextCursor cursor = ui->textEdit->textCursor();
|
||||
if (QTextTable *currentTable = ui->textEdit->textCursor().currentTable()) {
|
||||
m_actionRemoveTable = m_tableBar->addAction(removeTableIcon, tr("Remove Table"), [this]() {
|
||||
QTextCursor cursor = m_textEdit->textCursor();
|
||||
if (QTextTable *currentTable = m_textEdit->textCursor().currentTable()) {
|
||||
cursorEditBlock(cursor, [&] () {
|
||||
currentTable->removeRows(0, currentTable->rows());
|
||||
});
|
||||
@@ -584,12 +608,12 @@ void RichTextEditor::setupTableActions()
|
||||
});
|
||||
m_actionRemoveTable->setCheckable(false);
|
||||
|
||||
ui->tableBar->addSeparator();
|
||||
m_tableBar->addSeparator();
|
||||
|
||||
const QIcon addRowIcon(getIcon(Theme::Icon::addRowAfter)); //addRowAfter
|
||||
m_actionAddRow = ui->tableBar->addAction(addRowIcon, tr("Add Row"), [this]() {
|
||||
QTextCursor cursor = ui->textEdit->textCursor();
|
||||
if (QTextTable *currentTable = ui->textEdit->textCursor().currentTable()) {
|
||||
m_actionAddRow = m_tableBar->addAction(addRowIcon, tr("Add Row"), [this]() {
|
||||
QTextCursor cursor = m_textEdit->textCursor();
|
||||
if (QTextTable *currentTable = m_textEdit->textCursor().currentTable()) {
|
||||
cursorEditBlock(cursor, [&] () {
|
||||
currentTable->insertRows(currentTable->cellAt(cursor).row()+1, 1);
|
||||
});
|
||||
@@ -598,9 +622,9 @@ void RichTextEditor::setupTableActions()
|
||||
m_actionAddRow->setCheckable(false);
|
||||
|
||||
const QIcon addColumnIcon(getIcon(Theme::Icon::addColumnAfter)); //addColumnAfter
|
||||
m_actionAddColumn = ui->tableBar->addAction(addColumnIcon, tr("Add Column"), [this]() {
|
||||
QTextCursor cursor = ui->textEdit->textCursor();
|
||||
if (QTextTable *currentTable = ui->textEdit->textCursor().currentTable()) {
|
||||
m_actionAddColumn = m_tableBar->addAction(addColumnIcon, tr("Add Column"), [this]() {
|
||||
QTextCursor cursor = m_textEdit->textCursor();
|
||||
if (QTextTable *currentTable = m_textEdit->textCursor().currentTable()) {
|
||||
cursorEditBlock(cursor, [&] () {
|
||||
currentTable->insertColumns(currentTable->cellAt(cursor).column()+1, 1);
|
||||
});
|
||||
@@ -609,8 +633,8 @@ void RichTextEditor::setupTableActions()
|
||||
m_actionAddColumn->setCheckable(false);
|
||||
|
||||
const QIcon removeRowIcon(getIcon(Theme::Icon::deleteRow));
|
||||
m_actionRemoveRow = ui->tableBar->addAction(removeRowIcon, tr("Remove Row"), [this]() {
|
||||
QTextCursor cursor = ui->textEdit->textCursor();
|
||||
m_actionRemoveRow = m_tableBar->addAction(removeRowIcon, tr("Remove Row"), [this]() {
|
||||
QTextCursor cursor = m_textEdit->textCursor();
|
||||
if (QTextTable *currentTable = cursor.currentTable()) {
|
||||
cursorEditBlock(cursor, [&] () {
|
||||
currentTable->insertColumns(currentTable->cellAt(cursor).column()+1, 1);
|
||||
@@ -633,8 +657,8 @@ void RichTextEditor::setupTableActions()
|
||||
m_actionRemoveRow->setCheckable(false);
|
||||
|
||||
const QIcon removeColumnIcon(getIcon(Theme::Icon::deleteColumn));
|
||||
m_actionRemoveColumn = ui->tableBar->addAction(removeColumnIcon, tr("Remove Column"), [this]() {
|
||||
QTextCursor cursor = ui->textEdit->textCursor();
|
||||
m_actionRemoveColumn = m_tableBar->addAction(removeColumnIcon, tr("Remove Column"), [this]() {
|
||||
QTextCursor cursor = m_textEdit->textCursor();
|
||||
if (QTextTable *currentTable = cursor.currentTable()) {
|
||||
cursorEditBlock(cursor, [&] () {
|
||||
int firstRow = 0;
|
||||
@@ -654,11 +678,11 @@ void RichTextEditor::setupTableActions()
|
||||
});
|
||||
m_actionRemoveColumn->setCheckable(false);
|
||||
|
||||
ui->tableBar->addSeparator();
|
||||
m_tableBar->addSeparator();
|
||||
|
||||
const QIcon mergeCellsIcon(getIcon(Theme::Icon::mergeCells));
|
||||
m_actionMergeCells = ui->tableBar->addAction(mergeCellsIcon, tr("Merge Cells"), [this]() {
|
||||
QTextCursor cursor = ui->textEdit->textCursor();
|
||||
m_actionMergeCells = m_tableBar->addAction(mergeCellsIcon, tr("Merge Cells"), [this]() {
|
||||
QTextCursor cursor = m_textEdit->textCursor();
|
||||
if (QTextTable *currentTable = cursor.currentTable()) {
|
||||
if (cursor.hasSelection()) {
|
||||
cursorEditBlock(cursor, [&] () {
|
||||
@@ -670,8 +694,8 @@ void RichTextEditor::setupTableActions()
|
||||
m_actionMergeCells->setCheckable(false);
|
||||
|
||||
const QIcon splitRowIcon(getIcon(Theme::Icon::splitRows));
|
||||
m_actionSplitRow = ui->tableBar->addAction(splitRowIcon, tr("Split Row"), [this]() {
|
||||
QTextCursor cursor = ui->textEdit->textCursor();
|
||||
m_actionSplitRow = m_tableBar->addAction(splitRowIcon, tr("Split Row"), [this]() {
|
||||
QTextCursor cursor = m_textEdit->textCursor();
|
||||
if (QTextTable *currentTable = cursor.currentTable()) {
|
||||
cursorEditBlock(cursor, [&] () {
|
||||
currentTable->splitCell(currentTable->cellAt(cursor).row(),
|
||||
@@ -683,8 +707,8 @@ void RichTextEditor::setupTableActions()
|
||||
m_actionSplitRow->setCheckable(false);
|
||||
|
||||
const QIcon splitColumnIcon(getIcon(Theme::Icon::splitColumns));
|
||||
m_actionSplitColumn = ui->tableBar->addAction(splitColumnIcon, tr("Split Column"), [this]() {
|
||||
QTextCursor cursor = ui->textEdit->textCursor();
|
||||
m_actionSplitColumn = m_tableBar->addAction(splitColumnIcon, tr("Split Column"), [this]() {
|
||||
QTextCursor cursor = m_textEdit->textCursor();
|
||||
if (QTextTable *currentTable = cursor.currentTable()) {
|
||||
cursorEditBlock(cursor, [&] () {
|
||||
currentTable->splitCell(currentTable->cellAt(cursor).row(),
|
||||
@@ -698,7 +722,7 @@ void RichTextEditor::setupTableActions()
|
||||
|
||||
void RichTextEditor::textStyle(QTextListFormat::Style style)
|
||||
{
|
||||
QTextCursor cursor = ui->textEdit->textCursor();
|
||||
QTextCursor cursor = m_textEdit->textCursor();
|
||||
cursorEditBlock(cursor, [&] () {
|
||||
if (style != QTextListFormat::ListStyleUndefined) {
|
||||
QTextBlockFormat blockFmt = cursor.blockFormat();
|
||||
|
||||
@@ -5,21 +5,17 @@
|
||||
|
||||
#include <theme.h>
|
||||
|
||||
#include <QWidget>
|
||||
#include <QToolBar>
|
||||
#include <QList>
|
||||
#include <QTextCharFormat>
|
||||
#include <QTextList>
|
||||
#include <QFontComboBox>
|
||||
#include <QWidgetAction>
|
||||
#include <QList>
|
||||
#include <QPointer>
|
||||
#include <QTextCharFormat>
|
||||
#include <QTextEdit>
|
||||
#include <QTextList>
|
||||
#include <QToolBar>
|
||||
#include <QWidgetAction>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
namespace Ui {
|
||||
class RichTextEditor;
|
||||
}
|
||||
|
||||
template <class>
|
||||
class FontWidgetActions;
|
||||
|
||||
@@ -77,7 +73,10 @@ private:
|
||||
void setTableActionsActive(bool active); //switches between "has table/has no table" ui setup
|
||||
|
||||
private:
|
||||
QScopedPointer<Ui::RichTextEditor> ui;
|
||||
QTextEdit *m_textEdit;
|
||||
QToolBar *m_toolBar;
|
||||
QToolBar *m_tableBar;
|
||||
|
||||
QPointer<HyperlinkDialog> m_linkDialog;
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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_useCustomAnalyzer = settings->value(CUSTOM_ANALYZER, QVariant(false)).toBool();
|
||||
|
||||
m_disabledMessages = Utils::transform<QSet>(
|
||||
settings->value(DISABLED_MESSAGES,
|
||||
QVariant::fromValue(defaultDisabledMessages())).toList(),
|
||||
[](const QVariant &v){ return v.toInt(); });
|
||||
m_disabledMessagesForNonQuickUi = Utils::transform<QSet>(
|
||||
settings->value(DISABLED_MESSAGES_NONQUICKUI,
|
||||
QVariant::fromValue(defaultDisabledMessagesNonQuickUi())).toList(),
|
||||
[](const QVariant &v) { return v.toInt(); });
|
||||
m_disabledMessages = Utils::toSet(
|
||||
intListFromStringList(settings->value(DISABLED_MESSAGES,
|
||||
defaultDisabledMessagesAsString()).toStringList()));
|
||||
|
||||
m_disabledMessagesForNonQuickUi = Utils::toSet(
|
||||
intListFromStringList(settings->value(DISABLED_MESSAGES_NONQUICKUI,
|
||||
defaultDisabledNonQuickUiAsString()).toStringList()));
|
||||
|
||||
settings->endGroup();
|
||||
}
|
||||
@@ -122,12 +143,12 @@ void QmlJsEditingSettings::toSettings(QSettings *settings) const
|
||||
false);
|
||||
Utils::QtcSettings::setValueWithDefault(settings,
|
||||
DISABLED_MESSAGES,
|
||||
Utils::sorted(Utils::toList(m_disabledMessages)),
|
||||
defaultDisabledMessages());
|
||||
intListToStringList(Utils::sorted(Utils::toList(m_disabledMessages))),
|
||||
defaultDisabledMessagesAsString());
|
||||
Utils::QtcSettings::setValueWithDefault(settings,
|
||||
DISABLED_MESSAGES_NONQUICKUI,
|
||||
Utils::sorted(Utils::toList(m_disabledMessagesForNonQuickUi)),
|
||||
defaultDisabledMessagesNonQuickUi());
|
||||
intListToStringList(Utils::sorted(Utils::toList(m_disabledMessagesForNonQuickUi))),
|
||||
defaultDisabledNonQuickUiAsString());
|
||||
settings->endGroup();
|
||||
QmllsSettingsManager::instance()->checkForChanges();
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ void QuickToolBar::setProperty(const QString &propertyName, const QVariant &valu
|
||||
{
|
||||
|
||||
QString stringValue = value.toString();
|
||||
if (value.type() == QVariant::Color)
|
||||
if (value.typeId() == QVariant::Color)
|
||||
stringValue = QLatin1Char('\"') + value.toString() + QLatin1Char('\"');
|
||||
|
||||
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
|
||||
|
||||
#include "qmlbuildsystem.h"
|
||||
|
||||
#include "../qmlprojectconstants.h"
|
||||
#include "../qmlprojectmanagertr.h"
|
||||
|
||||
#include <QtCore5Compat/qtextcodec.h>
|
||||
#include <qmljs/qmljsmodelmanagerinterface.h>
|
||||
@@ -222,7 +224,7 @@ void QmlBuildSystem::parseProjectFiles()
|
||||
QString errorMessage;
|
||||
if (!reader.fetch(mainFilePath, &errorMessage)) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,7 +197,8 @@ Tasks QmlProject::projectIssues(const Kit *k) const
|
||||
if (version->type() == QtSupport::Constants::DESKTOPQT) {
|
||||
if (version->qmlRuntimeFilePath().isEmpty()) {
|
||||
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 {
|
||||
// Non-desktop Qt on a desktop device? We don't support that.
|
||||
|
||||
@@ -498,7 +498,7 @@ public:
|
||||
|
||||
auto l = new QHBoxLayout(this);
|
||||
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] {
|
||||
config->createKit(target);
|
||||
});
|
||||
|
||||
@@ -337,7 +337,7 @@ int QtKitAspect::qtVersionId(const Kit *k)
|
||||
|
||||
int id = -1;
|
||||
QVariant data = k->value(QtKitAspect::id(), -1);
|
||||
if (data.type() == QVariant::Int) {
|
||||
if (data.typeId() == QVariant::Int) {
|
||||
bool ok;
|
||||
id = data.toInt(&ok);
|
||||
if (!ok)
|
||||
|
||||
@@ -282,7 +282,7 @@ bool SquishFileGenerator::setup(const QVariant &data, QString *errorMessage)
|
||||
if (data.isNull())
|
||||
return false;
|
||||
|
||||
if (data.type() != QVariant::Map) {
|
||||
if (data.typeId() != QVariant::Map) {
|
||||
*errorMessage = Tr::tr("Key is not an object.");
|
||||
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)
|
||||
|
||||
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 (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||
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
|
||||
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