aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dist/changelog/changes-10.0.0.md237
-rw-r--r--src/libs/utils/tasktree.cpp745
-rw-r--r--src/plugins/mcusupport/mcuabstractpackage.h1
-rw-r--r--src/plugins/mcusupport/mcupackage.cpp5
-rw-r--r--src/plugins/mcusupport/mcupackage.h1
-rw-r--r--src/plugins/mcusupport/mcusupportoptionspage.cpp3
-rw-r--r--src/plugins/mcusupport/test/packagemock.h1
-rw-r--r--src/tools/cplusplus-ast2png/cplusplus-ast2png.cpp6
8 files changed, 957 insertions, 42 deletions
diff --git a/dist/changelog/changes-10.0.0.md b/dist/changelog/changes-10.0.0.md
new file mode 100644
index 0000000000..a049b07baf
--- /dev/null
+++ b/dist/changelog/changes-10.0.0.md
@@ -0,0 +1,237 @@
+Qt Creator 10
+=============
+
+Qt Creator version 10 contains bug fixes and new features.
+
+The most important changes are listed in this document. For a complete list of
+changes, see the Git log for the Qt Creator sources that you can check out from
+the public Git repository. For example:
+
+ git clone git://code.qt.io/qt-creator/qt-creator.git
+ git log --cherry-pick --pretty=oneline origin/9.0..v10.0.0
+
+General
+-------
+
+* Added support for temporarily dragging progress details out of the way
+ (QTCREATORBUG-28078)
+
+Editing
+-------
+
+* Added `Follow Symbol` for `http(s)` string literals (QTCREATORBUG-14967)
+* Added environment expansion to file system locator filter (QTCREATORBUG-242)
+* Added `Temporarily hide inline annotations` for types of annotations
+* Improved cursor visibility with indentation visualization (QTCREATORBUG-28645)
+* Fixed editor scrolling when pressing backspace (QTCREATORBUG-28316)
+* Fixed performance of rendering many search results (QTCREATORBUG-21056)
+
+### C++
+
+* Added renaming of includes when renaming `.ui` files (QTCREATORBUG-14259)
+* Added option for ignoring files for indexing (QTCREATORBUG-28313)
+* Added `Tools > C++ > Find Unused Functions`, and `Find Unused C/C++ Functions`
+ to the project context menu (QTCREATORBUG-6772)
+* Added automatic refactoring of C++ code when `.ui` files are renamed
+ (QTCREATORBUG-1179)
+* Fixed text codec when rewriting headers as part of renaming
+ (QTCREATORBUG-28164)
+* Fixed color of whitespace visualization in string literals
+ (QTCREATORBUG-26693, QTCREATORBUG-28284)
+* Fixed `Move Definition` for template functions (QTCREATORBUG-28186)
+* Clangd
+ * Made temporary disabling of global indexing possibly by cancelling in the
+ progress indicator
+ * Added support for highlighting angle brackets
+* Built-in
+ * Added support for spaceship operator (QTCREATORBUG-27503)
+ * Fixed handling of `= default` (QTCREATORBUG-28102)
+* Clang Format
+ * Enabled by default
+ * Added project setting for `Clang Format` (QTCREATORBUG-28188)
+
+### Language Server Protocol
+
+* Added `Restart` action to menu in editor tool bar
+* Added `Call Hierarchy` (QTCREATORBUG-11660)
+
+### QML
+
+* Added experimental support for QML language server
+* Added color preview tooltip (QTCREATORBUG-28446)
+* Added option for applying `qmlformat` on file save (QTCREATORBUG-28192,
+ QTCREATORBUG-26602)
+* Added `Follow Symbol` for QRC paths in string literals (QTCREATORBUG-28087)
+* Adapted wizard to new features in Qt 6.4 and Qt 6.5 (QTBUG-47996)
+* Fixed freeze when closing file (QTCREATORBUG-28206)
+* Fixed that `QtObject` was not recognized (QTCREATORBUG-28287,
+ QTCREATORBUG-28375)
+
+### Python
+
+* Added interpreter selector to editor toolbar (PYSIDE-2154)
+
+Projects
+--------
+
+* Added `Build > Run Generator` for exporting projects to other build systems
+ (QTCREATORBUG-28149)
+* Added option for browsing remote file system for remote builds and targets
+* Added support for opening remote terminal
+* Fixed that wizards did not create target directories (QTCREATORBUG-28346)
+* Fixed that absolute paths could be shown when relative paths would be
+ preferable (QTCREATORBUG-288)
+
+### CMake
+
+* Added deployment method with `cmake --install` (QTCREATORBUG-25880)
+* Added option for using `clang-format` for CMake files
+ ([clang-format Documentation](https://cmake-format.readthedocs.io/en/latest/))
+* Added option for showing advanced configure items by default
+* Moved `Autorun CMake` to global settings
+* Changed environment for running CMake to be based on build environment by
+ default (QTCREATORBUG-28513)
+* Fixed that `Package manager auto setup` created dependency of project build to
+ Qt Creator installation
+
+### Qbs
+
+* Updated code model to Qt 6.5
+* Added `Profile` build variant (QTCREATORBUG-27206)
+* Fixed that generated files were not made known to the code model
+
+### Python
+
+* Removed wizard for dynamically loaded `.ui` projects (QTCREATORBUG-25807)
+
+### Qt Quick UI Prototype
+
+* Added support for running on remote Linux devices
+
+Debugging
+---------
+
+### C++
+
+* Added pretty printers for `variant`, `optional` and `tuple` from `libcpp`
+ (QTCREATORBUG-25865)
+* Fixed highlighting in disassembly view
+* Fixed skipping `std::function` details when stepping
+
+Analyzer
+--------
+
+### Clang
+
+* Split `Clang-Tidy and Clazy` into separate `Clang-Tidy` and `Clazy` analyzers
+
+Version Control Systems
+-----------------------
+
+* Moved support for `Fossil` SCM into mainline repository
+* Removed settings for prompting to submit (QTCREATORBUG-22233)
+* Added links to file names in diff output (QTCREATORBUG-27309)
+* Fixed blame on symbolic links (QTCREATORBUG-20792)
+* Fixed saving of files before applying action on chunks (QTCREATORBUG-22506)
+* Fixed line ending preservation when reverting chunks (QTCREATORBUG-12690)
+
+### Git
+
+* Improved tracking of external changes (QTCREATORBUG-21089)
+* Added editor annotation for blame information (instant blame), with setting
+ (opt-out), and action to show it manually for the current line
+ (QTCREATORBUG-23299)
+
+Test Integration
+----------------
+
+* Improved `Run` and `Debug Test Under Cursor` (QTCREATORBUG-28496)
+* Improved number of files that are scanned for tests
+* Improved output handling (QTCREATORBUG-28706)
+* Made expensive checking for tests in derived `TestCase` objects optional
+
+Platforms
+---------
+
+### macOS
+
+* Changed kits to prefer Xcode toolchain over the wrappers in `/bin`
+
+### Android
+
+* Removed service management from manifest editor (QTCREATORBUG-28024)
+
+### Remote Linux
+
+* Fixed that opening file dialog unnecessarily queried for password for remote
+ devices
+
+### Docker
+
+* Added support for remote code model via remote Clangd
+* Added support for loading and attaching to core dumps from remote devices
+* Added support for using Clang Format on remote files
+* Added option to enable necessary capabilities for docker devices to allow lldb
+ debugging
+* Fixed issue with space in file paths (QTCREATORBUG-28476)
+* Fixed that auto-detection controls were shown for devices registered by the
+ installer
+
+Credits for these changes go to:
+--------------------------------
+Aleksei German
+Alessandro Portale
+Alexander Pershin
+Ali Kianian
+Amr Essam
+Andre Hartmann
+André Pönitz
+Antti Määttä
+Artem Sokolovskii
+Artur Shepilko
+Assam Boudjelthia
+BogDan Vatra
+Burak Hancerli
+Christian Kandeler
+Christian Stenger
+Cristian Adam
+Cristián Maureira-Fredes
+David Schulz
+Dmitry Bravikov
+Eike Ziller
+Fabian Kosmale
+Fawzi Mohamed
+Henning Gruendl
+Jaroslaw Kobus
+Jussi Witick
+Kai Köhne
+Knud Dollereder
+Knut Petter Svendsen
+Leena Miettinen
+Łukasz Wojniłowicz
+Mahmoud Badri
+Marc Mutz
+Marco Bubke
+Marcus Tillmanns
+Mats Honkamaa
+Miikka Heikkinen
+Mikhail Khachayants
+Orgad Shaneh
+Oswald Buddenhagen
+Philip Van Hoof
+Pranta Dastider
+Robert Löhning
+Sami Shalayel
+Samuel Ghinet
+Sergey Levin
+Sivert Krøvel
+Tasuku Suzuki
+Thiago Macieira
+Thomas Hartmann
+Tim Jenssen
+Tomáš Juřena
+Topi Reinio
+Ulf Hermann
+Vikas Pachdha
+Xavier Besson
+Yasser Grimes
diff --git a/src/libs/utils/tasktree.cpp b/src/libs/utils/tasktree.cpp
index 1cd4fd3f01..f99b20d761 100644
--- a/src/libs/utils/tasktree.cpp
+++ b/src/libs/utils/tasktree.cpp
@@ -589,46 +589,715 @@ void TaskNode::invokeEndHandler(bool success)
/*!
\class Utils::TaskTree
-
- \brief The TaskTree class is responsible for running async task tree structure defined in a
+ \inheaderfile utils/tasktree.h
+ \inmodule QtCreator
+ \ingroup mainclasses
+ \brief The TaskTree class runs an async task tree structure defined in a
declarative way.
- The Tasking namespace (similar to Layouting) is designer for building declarative task
- tree structure. The examples of tasks that can be used inside TaskTree are e.g. QtcProcess,
- FileTransfer, AsyncTask<>. It's extensible, so any possible asynchronous task may be
- integrated and used inside TaskTree. TaskTree enables to form sophisticated mixtures of
- parallel or sequential flow of tasks in tree form.
-
- The TaskTree consist of Group root element. The Group can have nested Group elements.
- The Group may also contain any number of tasks, e.g. Process, FileTransfer,
- AsyncTask<ReturnType>.
-
- Each Group can contain various other elements describing the processing flow.
-
- The execute mode elements of a Group specify how direct children of a Group will be executed.
- The "sequential" element of a Group means all tasks in a group will be executed in chain,
- so after the previous task finished, the next will be started. This is the default Group
- behavior. The "parallel" element of a Group means that all tasks in a Group will be started
- simultaneously. When having nested Groups hierarchy, we may mix execute modes freely
- and each Group will be executed according to its own execute mode.
- The "sequential" mode may be very useful in cases when result data from one task is need to
- be passed as an input data to the other task - sequential mode guarantees that the next
- task will be started only after the previous task has already finished.
-
- There are many possible "workflow" behaviors for the Group. E.g. "stopOnError",
- the default Group workflow behavior, means that whenever any direct child of a Group
- finished with error, we immediately stop processing other tasks in this group
- (in parallel case) by canceling them and immediately finish the Group with error.
-
- The user of TaskTree specifies how to setup his tasks (by providing TaskSetupHandlers)
- and how to collect output data from the finished tasks (by providing TaskEndHandlers).
- The user don't need to create tasks manually - TaskTree will create them when it's needed
- and destroy when they are not used anymore.
-
- Whenever a Group elemenent is being started, the Group's OnGroupSetup handler is being called.
- Just after the handler finishes, all Group's children are executed (either in parallel or
- in sequence). When all Group's children finished, one of Group's OnGroupDone or OnGroupError
- is being executed, depending on results of children execution and Group's workflow policy.
+ Use the Tasking namespace to build extensible, declarative task tree
+ structures that contain possibly asynchronous tasks, such as QtcProcess,
+ FileTransfer, or AsyncTask<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.
+
+ \section1 Root Element and Tasks
+
+ The TaskTree has a mandatory Group root element, which may contain
+ any number of tasks of various types, such as Process, FileTransfer,
+ or AsyncTask<ReturnType>:
+
+ \code
+ using namespace Utils;
+ using namespace Tasking;
+
+ const Group root {
+ Process(...),
+ Async<int>(...),
+ Transfer(...)
+ };
+
+ TaskTree *taskTree = new TaskTree(root);
+ connect(taskTree, &TaskTree::done, ...); // a successfully finished handler
+ connect(taskTree, &TaskTree::errorOccurred, ...); // an erroneously finished handler
+ taskTree->start();
+ \endcode
+
+ The task tree above has a top level element of the Group type that contains
+ tasks of the type QtcProcess, FileTransfer, and AsyncTask<int>.
+ After taskTree->start() is called, the tasks are run in a chain, starting
+ with Process. When Process finishes successfully, the Async<int> task is
+ started. Finally, when the asynchronous task finishes successfully, the
+ FileTransfer task is started.
+
+ When the last running task finishes with success, the task tree is considered
+ to have run successfully and the TaskTree::done() signal is emitted.
+ When a task finishes with an error, the execution of the task tree is stopped
+ and the remaining tasks are skipped. The task tree finishes with an error and
+ sends the TaskTree::errorOccurred() signal.
+
+ \section1 Groups
+
+ The parent of the Group sees it as a single task. Like other tasks,
+ the group can be started and it can finish with success or an error.
+ The Group elements can be nested to create a tree structure:
+
+ \code
+ const Group root {
+ Group {
+ parallel,
+ Process(...),
+ Async<int>(...)
+ },
+ Transfer(...)
+ };
+ \endcode
+
+ The example above differs from the first example in that the root element has
+ a subgroup that contains the Process and Async<int> tasks. The subgroup is a
+ sibling element of the Transfer task 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 Process and Async<int> tasks 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
+ Transfer task 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 (Process or Async<int>), the
+ following scenarios can take place:
+
+ \table
+ \header
+ \li Scenario 1
+ \li Scenario 2
+ \row
+ \li Root Group starts
+ \li Root Group starts
+ \row
+ \li Sub Group starts
+ \li Sub Group starts
+ \row
+ \li Process starts
+ \li Process starts
+ \row
+ \li Async<int> starts
+ \li Async<int> starts
+ \row
+ \li ...
+ \li ...
+ \row
+ \li \b {Process finishes}
+ \li \b {Async<int> finishes}
+ \row
+ \li ...
+ \li ...
+ \row
+ \li \b {Async<int> finishes}
+ \li \b {Process finishes}
+ \row
+ \li Sub Group finishes
+ \li Sub Group finishes
+ \row
+ \li Transfer starts
+ \li Transfer starts
+ \row
+ \li ...
+ \li ...
+ \row
+ \li Transfer finishes
+ \li Transfer finishes
+ \row
+ \li Root Group finishes
+ \li Root Group finishes
+ \endtable
+
+ The differences between the scenarios are marked with bold. Three dots mean
+ that an unspecified amount of time passes between previous and next events
+ (a task or tasks continue to run). No dots between events
+ means that they occur synchronously.
+
+ 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 Process finishes with an error while Async<int> is still being executed,
+ Async<int> is automatically stopped, the subgroup finishes with an error,
+ Transfer is skipped, and the tree finishes with an error.
+
+ \section1 Task Types
+
+ Each task type is associated with its corresponding task class that executes
+ the task. For example, a Process task inside a task tree is associated with
+ the QtcProcess class that executes the process. The associated objects are
+ automatically created, started, and destructed exclusively by the task tree
+ at the appropriate time.
+
+ If a root group consists of five sequential Process tasks, and the task tree
+ executes the group, it creates an instance of QtcProcess for the first
+ Process task and starts it. If the QtcProcess instance finishes successfully,
+ the task tree destructs it and creates a new QtcProcess instance for the
+ second Process, and so on. If the first task finishes with an error, the task
+ tree stops creating QtcProcess instances, and the root group finishes with an
+ error.
+
+ The following table shows examples of task types and their corresponding task
+ classes:
+
+ \table
+ \header
+ \li Task Type (Tasking Namespace)
+ \li Associated Task Class
+ \li Brief Description
+ \row
+ \li Process
+ \li Utils::QtcProcess
+ \li Starts processes.
+ \row
+ \li Async<ReturnType>
+ \li Utils::AsyncTask<ReturnType>
+ \li Starts asynchronous tasks; run in separate thread.
+ \row
+ \li Tree
+ \li Utils::TaskTree
+ \li Starts a nested task tree.
+ \row
+ \li Transfer
+ \li ProjectExplorer::FileTransfer
+ \li Starts file transfer between different devices.
+ \endtable
+
+ \section1 Task Handlers
+
+ Use Task handlers to set up a task for execution and to enable reading
+ the output data from the task when it finishes with success or an error.
+
+ \section2 Task Start Handler
+
+ When a corresponding task class object is created and before it's started,
+ the task tree invokes a mandatory user-provided setup handler. The setup
+ handler should always take a \e reference to the associated task class object:
+
+ \code
+ const auto onSetup = [](QtcProcess &process) {
+ process.setCommand({"sleep", {"3"}});
+ };
+ const Group root {
+ Process(onSetup)
+ };
+ \endcode
+
+ You can modify the passed QtcProcess in the setup handler, so that the task
+ tree can start the process according to your configuration.
+ You do not need to call \e {process.start();} in the setup handler,
+ as the task tree calls it when needed. The setup handler is mandatory
+ and must be the first argument of the task's constructor.
+
+ Optionally, the setup handler may return a TaskAction. The returned
+ TaskAction influences the further start behavior of a given task. The
+ possible values are:
+
+ \table
+ \header
+ \li TaskAction Value
+ \li Brief Description
+ \row
+ \li Continue
+ \li The task is started normally. This is the default behavior when the
+ setup handler doesn't return TaskAction (that is, its return type is
+ void).
+ \row
+ \li StopWithDone
+ \li The task won't be started and it will report success to its parent.
+ \row
+ \li StopWithError
+ \li The task won't be started and it will report an error to its parent.
+ \endtable
+
+ This is useful for running a task only when a condition is met and the data
+ needed to evaluate this condition is not known until previously started tasks
+ finish. This way, the setup handler dynamically decides whether to start the
+ corresponding task normally or skip it and report success or an error.
+ For more information about inter-task data exchange, see \l Storage.
+
+ \section2 Task's Done and Error Handlers
+
+ When a running task finishes, the task tree invokes an optionally provided
+ done or error handler. Both handlers should always take a \e {const reference}
+ to the associated task class object:
+
+ \code
+ const auto onSetup = [](QtcProcess &process) {
+ process.setCommand({"sleep", {"3"}});
+ };
+ const auto onDone = [](const QtcProcess &process) {
+ qDebug() << "Success" << process.cleanedStdOut();
+ };
+ const auto onError = [](const QtcProcess &process) {
+ qDebug() << "Failure" << process.cleanedStdErr();
+ };
+ const Group root {
+ Process(onSetup, onDone, onError)
+ };
+ \endcode
+
+ The done and error handlers may collect output data from QtcProcess, and store it
+ for further processing or perform additional actions. The done handler is optional.
+ When used, it must be the second argument of the task constructor.
+ The error handler must always be the third argument.
+ You can omit the handlers or substitute the ones that you do not need with curly braces ({}).
+
+ \note If the task setup handler returns StopWithDone or StopWithError,
+ neither the done nor error handler is invoked.
+
+ \section1 Group Handlers
+
+ Similarly to task handlers, group handlers enable you to set up a group to
+ execute and to apply more actions when the whole group finishes with
+ success or an error.
+
+ \section2 Group's Start Handler
+
+ The task tree invokes the group start handler before it starts the child
+ tasks. The group handler doesn't take any arguments:
+
+ \code
+ const auto onGroupSetup = [] {
+ qDebug() << "Entering the group";
+ };
+ const Group root {
+ OnGroupSetup(onGroupSetup),
+ Process(...)
+ };
+ \endcode
+
+ The group setup handler is optional. To define a group setup handler, add an
+ OnGroupSetup element to a group. The argument of OnGroupSetup is a user
+ handler. If you add more than one OnGroupSetup element to a group, an assert
+ is triggered at runtime that includes an error message.
+
+ Like the task start handler, the group start handler may return TaskAction.
+ The returned TaskAction value affects the start behavior of the
+ whole group. If you do not specify a group start handler or its return type
+ is void, the default group's action is TaskAction::Continue, so that all
+ tasks are started normally. Otherwise, when the start handler returns
+ TaskAction::StopWithDone or TaskAction::StopWithError, the tasks are not
+ started (they are skipped) and the group itself reports success or failure,
+ depending on the returned value, respectively.
+
+ \code
+ const Group root {
+ OnGroupSetup([] { qDebug() << "Root setup"; }),
+ Group {
+ OnGroupSetup([] { qDebug() << "Group 1 setup"; return TaskAction::Continue; }),
+ Process(...) // Process 1
+ },
+ Group {
+ OnGroupSetup([] { qDebug() << "Group 2 setup"; return TaskAction::StopWithDone; }),
+ Process(...) // Process 2
+ },
+ Group {
+ OnGroupSetup([] { qDebug() << "Group 3 setup"; return TaskAction::StopWithError; }),
+ Process(...) // Process 3
+ },
+ Process(...) // Process 4
+ };
+ \endcode
+
+ In the above example, all subgroups of a root group define their setup handlers.
+ The following scenario assumes that all started processes finish with success:
+
+ \table
+ \header
+ \li Scenario
+ \li Comment
+ \row
+ \li Root Group starts
+ \li Doesn't return TaskAction, so its tasks are executed.
+ \row
+ \li Group 1 starts
+ \li Returns Continue, so its tasks are executed.
+ \row
+ \li Process 1 starts
+ \li
+ \row
+ \li ...
+ \li ...
+ \row
+ \li Process 1 finishes (success)
+ \li
+ \row
+ \li Group 1 finishes (success)
+ \li
+ \row
+ \li Group 2 starts
+ \li Returns StopWithDone, so Process 2 is skipped and Group 2 reports
+ success.
+ \row
+ \li Group 2 finishes (success)
+ \li
+ \row
+ \li Group 3 starts
+ \li Returns StopWithError, so Process 3 is skipped and Group 3 reports
+ an error.
+ \row
+ \li Group 3 finishes (error)
+ \li
+ \row
+ \li Root Group finishes (error)
+ \li Group 3, which is a direct child of the root group, finished with an
+ error, so the root group stops executing, skips Process 4, which has
+ not started yet, and reports an error.
+ \endtable
+
+ \section2 Groups's Done and Error Handlers
+
+ A Group's done or error handler is executed after the successful or failed
+ execution of its tasks, respectively. The final value reported by the
+ group depends on its \l {Workflow Policy}. The handlers can apply other
+ necessary actions. The done and error handlers are defined inside the
+ OnGroupDone and OnGroupError elements of a group, respectively. They do not
+ take arguments:
+
+ \code
+ const Group root {
+ OnGroupSetup([] { qDebug() << "Root setup"; }),
+ Process(...),
+ OnGroupDone([] { qDebug() << "Root finished with success"; }),
+ OnGroupError([] { qDebug() << "Root finished with error"; })
+ };
+ \endcode
+
+ The group done and error handlers are optional. If you add more than one
+ OnGroupDone or OnGroupError each to a group, an assert is triggered at
+ runtime that includes an error message.
+
+ \note Even if the group setup handler returns StopWithDone or StopWithError,
+ one of the task's done or error handlers is invoked. This behavior differs
+ from that of task handlers and might change in the future.
+
+ \section1 Other Group Elements
+
+ A group can contain other elements that describe the processing flow, such as
+ the execution mode or workflow policy. It can also contain storage elements
+ that are responsible for collecting and sharing custom common data gathered
+ during group execution.
+
+ \section2 Execution Mode
+
+ The execution mode element in a Group specifies how the direct child tasks of
+ the Group are started.
+
+ \table
+ \header
+ \li Execution Mode
+ \li Description
+ \row
+ \li sequential
+ \li Default. When a Group has no execution mode, it runs in the
+ sequential mode. All the direct child tasks of a group are started
+ in a chain, so that when one task finishes, the next one starts.
+ This enables you to pass the results from the previous task
+ as input to the next task before it starts. This mode guarantees
+ that the next task is started only after the previous task finishes.
+ \row
+ \li parallel
+ \li All the direct child tasks of a group are started after the group is
+ started, without waiting for the previous tasks to finish. In this
+ mode, all tasks run simultaneously.
+ \row
+ \li ParallelLimit(int limit)
+ \li In this mode, a limited number of direct child tasks run simultaneously.
+ The \e limit defines the maximum number of tasks running in parallel
+ in a group. When the group is started, the first batch tasks is
+ started (the number of tasks in batch equals to passed limit, at most),
+ while the others are kept waiting. When a running task finishes,
+ the group starts the next remaining one, so that the \e limit
+ of simultaneously running tasks inside a group isn't exceeded.
+ This repeats on every child task's finish until all child tasks are started.
+ This enables you to limit the maximum number of tasks that
+ run simultaneously, for example if running too many processes might
+ block the machine for a long time. The value 1 means \e sequential
+ execution. The value 0 means unlimited and equals \e parallel.
+ \endtable
+
+ In all execution modes, a group starts tasks in the oder in which they appear.
+
+ If a child of a group is also a group (in a nested tree), the child group
+ runs its tasks according to its own execution mode.
+
+ \section2 Workflow Policy
+
+ The workflow policy element in a Group specifies how the group should behave
+ when its direct child tasks finish:
+
+ \table
+ \header
+ \li Workflow Policy
+ \li Description
+ \row
+ \li stopOnError
+ \li Default. If a task finishes with an error, the group:
+ \list 1
+ \li Stops the running tasks (if any - for example, in parallel
+ mode).
+ \li Skips executing tasks it has not started (for example, in the
+ sequential mode).
+ \li Immediately finishes with an error.
+ \endlist
+ If all child tasks finish successfully or the group is empty, the group
+ finishes with success.
+ \row
+ \li continueOnError
+ \li Similar to stopOnError, but in case any child finishes with
+ an error, the execution continues until all tasks finish,
+ and the group reports an error afterwards, even when some other
+ tasks in group finished with success.
+ If a task finishes with an error, the group:
+ \list 1
+ \li Continues executing the tasks that are running or have not
+ started yet.
+ \li Finishes with an error when all tasks finish.
+ \endlist
+ If all tasks finish successfully or the group is empty, the group
+ finishes with success.
+ \row
+ \li stopOnDone
+ \li If a task finishes with success, the group:
+ \list 1
+ \li Stops running tasks and skips those that it has not started.
+ \li Immediately finishes with success.
+ \endlist
+ If all tasks finish with an error or the group is empty, the group
+ finishes with an error.
+ \row
+ \li continueOnDone
+ \li Similar to stopOnDone, but in case any child finishes
+ successfully, the execution continues until all tasks finish,
+ and the group reports success afterwards, even when some other
+ tasks in group finished with an error.
+ If a task finishes with success, the group:
+ \list 1
+ \li Continues executing the tasks that are running or have not
+ started yet.
+ \li Finishes with success when all tasks finish.
+ \endlist
+ If all tasks finish with an error or the group is empty, the group
+ finishes with an error.
+ \row
+ \li optional
+ \li The group executes all tasks and ignores their return state. If all
+ tasks finish or the group is empty, the group finishes with success.
+ \endtable
+
+ If a child of a group is also a group (in a nested tree), the child group
+ runs its tasks according to its own workflow policy.
+
+ \section2 Storage
+
+ Use the Storage element to exchange information between tasks. Especially,
+ in the sequential execution mode, when a task needs data from another task
+ before it can start. For example, a task tree that copies data by reading
+ it from a source and writing it to a destination might look as follows:
+
+ \code
+ static QByteArray load(const FilePath &fileName) { ... }
+ static void save(const FilePath &fileName, const QByteArray &array) { ... }
+
+ static TaskItem diffRecipe(const FilePath &source, const FilePath &destination)
+ {
+ struct CopyStorage { // [1] custom inter-task struct
+ QByteArray content; // [2] custom inter-task data
+ };
+
+ // [3] instance of custom inter-task struct manageable by task tree
+ const TreeStorage<CopyStorage> storage;
+
+ const auto onLoaderSetup = [source](Async<QByteArray> &async) {
+ async.setAsyncCallData(&load, source);
+ };
+ // [4] runtime: task tree activates the instance from [5] before invoking handler
+ const auto onLoaderDone = [storage](const Async<QByteArray> &async) {
+ storage->content = async.result();
+ };
+
+ // [4] runtime: task tree activates the instance from [5] before invoking handler
+ const auto onSaverSetup = [storage, destination](Async<void> &async) {
+ async.setAsyncCallData(&save, destination, storage->content);
+ };
+ const auto onSaverDone = [](const Async<void> &async) {
+ qDebug() << "Save done successfully";
+ };
+
+ const Group root {
+ // [5] runtime: task tree creates an instance of CopyStorage when root is entered
+ Storage(storage),
+ Async<QByteArray>(onLoaderSetup, onLoaderDone),
+ Async<void>(onSaverSetup, onSaverDone)
+ };
+ return root;
+ }
+ \endcode
+
+ In the example above, the inter-task data consists of a QByteArray content
+ variable [2] enclosed in a CopyStorage custom struct [1]. If the loader
+ finishes successfully, it stores the data in a CopyStorage::content
+ variable. The saver then uses the variable to configure the saving task.
+
+ To enable a task tree to manage the CopyStorage struct, an instance of
+ TreeStorage<CopyStorage> is created [3]. If a copy of this object is
+ inserted as group's child task [5], an instance of CopyStorage struct is
+ created dynamically when the task tree enters this group. When the task
+ tree leaves this group, the existing instance of CopyStorage struct is
+ destructed as it's no longer needed.
+
+ If several task trees that hold a copy of the common TreeStorage<CopyStorage>
+ instance run simultaneously, each task tree contains its own copy of the
+ CopyStorage struct.
+
+ You can access CopyStorage from any handler in the group with a storage object.
+ This includes all handlers of all descendant tasks of the group with
+ a storage object. To access the custom struct in a handler, pass the
+ copy of the TreeStorage<CopyStorage> object to the handler (for example, in
+ a lambda capture) [4].
+
+ When the task tree invokes a handler in a subtree containing the storage [5],
+ the task tree activates its own CopyStorage instance inside the
+ TreeStorage<CopyStorage> object. Therefore, the CopyStorage struct may be
+ accessed only from within the handler body. To access the currently active
+ CopyStorage from within TreeStorage<CopyStorage>, use the TreeStorage::operator->()
+ or TreeStorage::activeStorage() method.
+
+ The following list summarizes how to employ a Storage object into the task
+ tree:
+ \list 1
+ \li Define the custom structure MyStorage with custom data [1], [2]
+ \li Create an instance of TreeStorage<MyStorage> storage [3]
+ \li Pass the TreeStorage<MyStorage> instance to handlers [4]
+ \li Insert the TreeStorage<MyStorage> instance into a group [5]
+ \endlist
+
+ \note The current implementation assumes that all running task trees
+ containing copies of the same TreeStorage run in the same thread. Otherwise,
+ the behavior is undefined.
+
+ \section1 TaskTree
+
+ TaskTree executes the tree structure of asynchronous tasks according to the
+ recipe described by the Group root element.
+
+ As TaskTree is also an asynchronous task, it can be a part of another TaskTree.
+ To place a nested TaskTree inside another TaskTree, insert the Tasking::Tree
+ element into other tree's Group element.
+
+ TaskTree reports progress of completed tasks when running. The progress value
+ is increased when a task finishes or is skipped or stopped.
+ When TaskTree is finished and the TaskTree::done() or TaskTree::errorOccurred()
+ signal is emitted, the current value of the progress equals the maximum
+ progress value. Maximum progress equals the total number of tasks in a tree.
+ A nested TaskTree is counted as a single task, and its child tasks are not
+ counted in the top level tree. Groups themselves are not counted as tasks,
+ but their tasks are counted.
+
+ To set additional initial data for the running tree, modify the storage
+ instances in a tree when it creates them by installing a storage setup
+ handler:
+
+ \code
+ TreeStorage<CopyStorage> storage;
+ Group root = ...; // storage placed inside root's group and inside handlers
+ TaskTree taskTree(root);
+ auto initStorage = [](CopyStorage *storage){
+ storage->content = "initial content";
+ };
+ taskTree.onStorageSetup(storage, initStorage);
+ taskTree.start();
+ \endcode
+
+ When the running task tree creates a CopyStorage instance, and before any
+ handler inside a tree is called, the task tree calls the initStorage handler,
+ to enable setting up initial data of the storage, unique to this particular
+ run of taskTree.
+
+ Similarly, to collect some additional result data from the running tree,
+ read it from storage instances in the tree when they are about to be
+ destroyed. To do this, install a storage done handler:
+
+ \code
+ TreeStorage<CopyStorage> storage;
+ Group root = ...; // storage placed inside root's group and inside handlers
+ TaskTree taskTree(root);
+ auto collectStorage = [](CopyStorage *storage){
+ qDebug() << "final content" << storage->content;
+ };
+ taskTree.onStorageDone(storage, collectStorage);
+ taskTree.start();
+ \endcode
+
+ When the running task tree is about to destroy a CopyStorage instance, the
+ task tree calls the collectStorage handler, to enable reading the final data
+ from the storage, unique to this particular run of taskTree.
+
+ \section1 Task Adapters
+
+ To extend a TaskTree with new a task type, implement a simple adapter class
+ derived from the TaskAdapter class template. The following class is an
+ adapter for a single shot timer, which may be considered as a new
+ asynchronous task:
+
+ \code
+ class TimeoutAdapter : public Utils::Tasking::TaskAdapter<QTimer>
+ {
+ public:
+ TimeoutAdapter() {
+ task()->setSingleShot(true);
+ task()->setInterval(1000);
+ connect(task(), &QTimer::timeout, this, [this] { emit done(true); });
+ }
+ void start() final { task()->start(); }
+ };
+
+ QTC_DECLARE_CUSTOM_TASK(Timeout, TimeoutAdapter);
+ \endcode
+
+ You must derive the custom adapter from the TaskAdapter class template
+ instantiated with a template parameter of the class implementing a running
+ task. The code above uses QTimer to run the task. This class appears
+ later as an argument to the task's handlers. The instance of this class
+ parameter automatically becomes a member of the TaskAdapter template, and is
+ accessible through the TaskAdapter::task() method. The constructor
+ of TimeoutAdapter initially configures the QTimer object and connects
+ to the QTimer::timeout signal. When the signal is triggered, TimeoutAdapter
+ emits the done(true) signal to inform the task tree that the task finished
+ successfully. If it emits done(false), the task finished with an error.
+ The TaskAdapter::start() method starts the timer.
+
+ To make QTimer accessible inside TaskTree under the \e Timeout name,
+ register it with QTC_DECLARE_CUSTOM_TASK(Timeout, TimeoutAdapter). Timeout
+ becomes a new task type inside Utils::Tasking namespace, using TimeoutAdapter.
+
+ The new task type is now registered, and you can use it in TaskTree:
+
+ \code
+ const auto onTimeoutSetup = [](QTimer &task) {
+ task.setInterval(2000);
+ };
+ const auto onTimeoutDone = [](const QTimer &task) {
+ qDebug() << "timeout triggered";
+ };
+
+ const Group root {
+ Timeout(onTimeoutSetup, onTimeoutDone)
+ };
+ \endcode
+
+ When a task tree containing the root from the above example is started, it
+ prints a debug message within two seconds and then finishes successfully.
+
+ \note The class implementing the running task should have a default constructor,
+ and objects of this class should be freely destructible. It should be allowed
+ to destroy a running object, preferably without waiting for the running task
+ to finish (that is, safe non-blocking destructor of a running task).
*/
TaskTree::TaskTree()
diff --git a/src/plugins/mcusupport/mcuabstractpackage.h b/src/plugins/mcusupport/mcuabstractpackage.h
index 248c91287d..33e9e62bd3 100644
--- a/src/plugins/mcusupport/mcuabstractpackage.h
+++ b/src/plugins/mcusupport/mcuabstractpackage.h
@@ -47,6 +47,7 @@ public:
virtual bool isValidStatus() const = 0;
virtual bool writeToSettings() const = 0;
+ virtual void readFromSettings() = 0;
virtual QWidget *widget() = 0;
virtual const McuPackageVersionDetector *getVersionDetector() const = 0;
diff --git a/src/plugins/mcusupport/mcupackage.cpp b/src/plugins/mcusupport/mcupackage.cpp
index 287c89b93e..6feaf728a6 100644
--- a/src/plugins/mcusupport/mcupackage.cpp
+++ b/src/plugins/mcusupport/mcupackage.cpp
@@ -244,6 +244,11 @@ bool McuPackage::writeToSettings() const
return settingsHandler->write(m_settingsKey, m_path, m_defaultPath);
}
+void McuPackage::readFromSettings()
+{
+ setPath(settingsHandler->getPath(m_settingsKey, QSettings::UserScope, m_defaultPath));
+}
+
QWidget *McuPackage::widget()
{
auto *widget = new QWidget;
diff --git a/src/plugins/mcusupport/mcupackage.h b/src/plugins/mcusupport/mcupackage.h
index 4cf4606e9f..1bd3b26fb4 100644
--- a/src/plugins/mcusupport/mcupackage.h
+++ b/src/plugins/mcusupport/mcupackage.h
@@ -66,6 +66,7 @@ public:
QString statusText() const override;
bool writeToSettings() const override;
+ void readFromSettings() override;
QWidget *widget() override;
const McuPackageVersionDetector *getVersionDetector() const override;
diff --git a/src/plugins/mcusupport/mcusupportoptionspage.cpp b/src/plugins/mcusupport/mcusupportoptionspage.cpp
index 7a8a7d046c..c24785c0db 100644
--- a/src/plugins/mcusupport/mcusupportoptionspage.cpp
+++ b/src/plugins/mcusupport/mcusupportoptionspage.cpp
@@ -90,6 +90,9 @@ McuSupportOptionsWidget::McuSupportOptionsWidget(McuSupportOptions &options,
m_qtForMCUsSdkGroupBox = new QGroupBox(Tr::tr("Qt for MCUs SDK"));
m_qtForMCUsSdkGroupBox->setFlat(true);
auto *layout = new QVBoxLayout(m_qtForMCUsSdkGroupBox);
+ // Re-read the qtForMCUs package from settings to discard un-applied changes from previous sessions
+ m_options.qtForMCUsSdkPackage->readFromSettings();
+
layout->addWidget(m_options.qtForMCUsSdkPackage->widget());
mainLayout->addWidget(m_qtForMCUsSdkGroupBox);
}
diff --git a/src/plugins/mcusupport/test/packagemock.h b/src/plugins/mcusupport/test/packagemock.h
index fb4f73601f..1e62fb7764 100644
--- a/src/plugins/mcusupport/test/packagemock.h
+++ b/src/plugins/mcusupport/test/packagemock.h
@@ -29,6 +29,7 @@ public:
MOCK_METHOD(QString, environmentVariableName, (), (const));
MOCK_METHOD(bool, isAddToSystemPath, (), (const));
MOCK_METHOD(bool, writeToSettings, (), (const));
+ MOCK_METHOD(void, readFromSettings, ());
MOCK_METHOD(QStringList, versions, (), (const));
MOCK_METHOD(QWidget *, widget, ());
diff --git a/src/tools/cplusplus-ast2png/cplusplus-ast2png.cpp b/src/tools/cplusplus-ast2png/cplusplus-ast2png.cpp
index 36fb7533e5..5fe89323a9 100644
--- a/src/tools/cplusplus-ast2png/cplusplus-ast2png.cpp
+++ b/src/tools/cplusplus-ast2png/cplusplus-ast2png.cpp
@@ -511,11 +511,9 @@ int main(int argc, char *argv[])
}
// Process options & arguments
- const bool helpRequested = args.contains(QLatin1String("-h"))
- || args.contains(QLatin1String("-help"));
- if (helpRequested) {
+ if (args.contains(QLatin1String("-h")) || args.contains(QLatin1String("-help"))) {
printUsage();
- return helpRequested ? EXIT_SUCCESS : EXIT_FAILURE;
+ return EXIT_SUCCESS;
}
if (args.contains(QLatin1String("-v"))) {