diff --git a/doc/qtcreatordev/config/qtcreator-developer.qdocconf b/doc/qtcreatordev/config/qtcreator-developer.qdocconf index 417b1ffd426..99b00d54fa8 100644 --- a/doc/qtcreatordev/config/qtcreator-developer.qdocconf +++ b/doc/qtcreatordev/config/qtcreator-developer.qdocconf @@ -16,6 +16,7 @@ headerdirs = . \ ../src \ ../../../src/libs/aggregation \ ../../../src/libs/extensionsystem \ + ../../../src/libs/solutions/tasking \ ../../../src/libs/utils \ ../../../src/plugins/coreplugin @@ -23,6 +24,7 @@ sourcedirs = . \ ../src \ ../../../src/libs/aggregation \ ../../../src/libs/extensionsystem \ + ../../../src/libs/solutions/tasking \ ../../../src/libs/utils \ ../../../src/plugins/coreplugin diff --git a/doc/qtcreatordev/src/qtcreator-module.qdoc b/doc/qtcreatordev/src/qtcreator-module.qdoc index 6a6b1a62f10..18a56103353 100644 --- a/doc/qtcreatordev/src/qtcreator-module.qdoc +++ b/doc/qtcreatordev/src/qtcreator-module.qdoc @@ -34,6 +34,11 @@ for plugins and basic mechanisms for plugin interaction like an object pool. + \row + \li \l{Tasking} + \li A solution containing a TaskTree and other classes for writing + declarative trees of asynchronous task flows. + \row \li \l{Utils} \li Useful classes that are reused in a lot of places in Qt Creator code. diff --git a/src/libs/extensionsystem/pluginmanager.cpp b/src/libs/extensionsystem/pluginmanager.cpp index 3ee99510552..ae2dbf8903b 100644 --- a/src/libs/extensionsystem/pluginmanager.cpp +++ b/src/libs/extensionsystem/pluginmanager.cpp @@ -1034,6 +1034,7 @@ void PluginManagerPrivate::readSettings() */ void PluginManagerPrivate::stopAll() { + m_isShuttingDown = true; if (delayedInitializeTimer && delayedInitializeTimer->isActive()) { delayedInitializeTimer->stop(); delete delayedInitializeTimer; @@ -1839,6 +1840,11 @@ bool PluginManager::isInitializationDone() return d->m_isInitializationDone; } +bool PluginManager::isShuttingDown() +{ + return d->m_isShuttingDown; +} + /*! Retrieves one object with \a name from the object pool. \sa addObject() diff --git a/src/libs/extensionsystem/pluginmanager.h b/src/libs/extensionsystem/pluginmanager.h index a56cb7ba9d4..ecd0ee70b73 100644 --- a/src/libs/extensionsystem/pluginmanager.h +++ b/src/libs/extensionsystem/pluginmanager.h @@ -129,6 +129,7 @@ public: static QString platformName(); static bool isInitializationDone(); + static bool isShuttingDown(); static void remoteArguments(const QString &serializedArguments, QObject *socket); static void shutdown(); diff --git a/src/libs/extensionsystem/pluginmanager_p.h b/src/libs/extensionsystem/pluginmanager_p.h index 86c3a6c3624..c7a4291a6b7 100644 --- a/src/libs/extensionsystem/pluginmanager_p.h +++ b/src/libs/extensionsystem/pluginmanager_p.h @@ -124,6 +124,7 @@ public: bool m_isInitializationDone = false; bool enableCrashCheck = true; + bool m_isShuttingDown = false; QHash> m_scenarios; QString m_requestedScenario; diff --git a/src/libs/solutions/tasking/tasktree.cpp b/src/libs/solutions/tasking/tasktree.cpp index 4e9cab7bb90..6d3e7eb95bc 100644 --- a/src/libs/solutions/tasking/tasktree.cpp +++ b/src/libs/solutions/tasking/tasktree.cpp @@ -724,7 +724,16 @@ void TaskNode::invokeEndHandler(bool success) } /*! - \class TaskTree + \namespace Tasking + \inmodule QtCreator + \brief The Tasking namespace contains a general purpose TaskTree solution. + + The Tasking namespace depends on Qt only, and doesn't depend on any \QC + specific code. +*/ + +/*! + \class Tasking::TaskTree \inheaderfile solutions/tasking/tasktree.h \inmodule QtCreator \ingroup mainclasses @@ -1180,8 +1189,7 @@ void TaskNode::invokeEndHandler(bool success) 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. + If all child tasks finish successfully, the group finishes with success. \row \li continueOnError \li Similar to stopOnError, but in case any child finishes with @@ -1194,8 +1202,7 @@ void TaskNode::invokeEndHandler(bool success) 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. + If all tasks finish successfully, the group finishes with success. \row \li stopOnDone \li If a task finishes with success, the group: @@ -1203,8 +1210,7 @@ void TaskNode::invokeEndHandler(bool success) \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. + If all tasks finish with an error, the group finishes with an error. \row \li continueOnDone \li Similar to stopOnDone, but in case any child finishes @@ -1217,22 +1223,22 @@ void TaskNode::invokeEndHandler(bool success) 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. + If all tasks finish with an error, the group finishes with an error. \row \li stopOnFinished \li The group starts as many tasks as it can. When a task finishes the group stops and reports the task's result. - When the group is empty, it finishes immediately with success. Useful only in parallel mode. In sequential mode, only the first task is started, and when finished, the group finishes too, so the other tasks are ignored. \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. + tasks finish, the group finishes with success. \endtable + When the group is empty, it finishes immediately with success, + regardless of its workflow policy. 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. diff --git a/src/libs/utils/ansiescapecodehandler.cpp b/src/libs/utils/ansiescapecodehandler.cpp index 0909a3d2c6f..91f13d9a25e 100644 --- a/src/libs/utils/ansiescapecodehandler.cpp +++ b/src/libs/utils/ansiescapecodehandler.cpp @@ -9,6 +9,7 @@ namespace Utils { /*! \class Utils::AnsiEscapeCodeHandler + \inmodule QtCreator \brief The AnsiEscapeCodeHandler class parses text and extracts ANSI escape codes from it. diff --git a/src/libs/utils/aspects.cpp b/src/libs/utils/aspects.cpp index 7baa9ba38ce..7d509a21076 100644 --- a/src/libs/utils/aspects.cpp +++ b/src/libs/utils/aspects.cpp @@ -2328,6 +2328,7 @@ void IntegersAspect::setDefaultValue(const QList &value) /*! \class Utils::TextDisplay + \inmodule QtCreator \brief A text display is a phony aspect with the sole purpose of providing some text display using an Utils::InfoLabel in places where otherwise diff --git a/src/libs/utils/checkablemessagebox.cpp b/src/libs/utils/checkablemessagebox.cpp index d09c2941752..3c57a736670 100644 --- a/src/libs/utils/checkablemessagebox.cpp +++ b/src/libs/utils/checkablemessagebox.cpp @@ -18,6 +18,7 @@ /*! \class Utils::CheckableMessageBox + \inmodule QtCreator \brief The CheckableMessageBox class implements a message box suitable for questions with a diff --git a/src/libs/utils/classnamevalidatinglineedit.cpp b/src/libs/utils/classnamevalidatinglineedit.cpp index 01235d57e32..3515abef023 100644 --- a/src/libs/utils/classnamevalidatinglineedit.cpp +++ b/src/libs/utils/classnamevalidatinglineedit.cpp @@ -10,6 +10,7 @@ /*! \class Utils::ClassNameValidatingLineEdit + \inmodule QtCreator \brief The ClassNameValidatingLineEdit class implements a line edit that validates a C++ class name and emits a signal diff --git a/src/libs/utils/commandline.cpp b/src/libs/utils/commandline.cpp index 103049ae246..b259aaf7e64 100644 --- a/src/libs/utils/commandline.cpp +++ b/src/libs/utils/commandline.cpp @@ -41,6 +41,7 @@ namespace Utils { /*! \class Utils::ProcessArgs + \inmodule QtCreator \brief The ProcessArgs class provides functionality for dealing with shell-quoted process arguments. @@ -217,7 +218,7 @@ static QStringList doSplitArgsWin(const QString &args, ProcessArgs::SplitError * If \a err is not NULL, stores a status code at the pointer target. For more information, see \l SplitError. - If \env is not NULL, performs variable substitution with the + If \a env is not NULL, performs variable substitution with the given environment. Returns a list of unquoted words or an empty list if an error occurred. @@ -253,7 +254,6 @@ static QStringList doSplitArgsWin(const QString &args, ProcessArgs::SplitError * \c{foo " bar}. */ - static QStringList splitArgsWin(const QString &_args, bool abortOnMeta, ProcessArgs::SplitError *err, const Environment *env, const QString *pwd) @@ -1398,6 +1398,7 @@ QString ProcessArgs::toString() const /*! \class Utils::CommandLine + \inmodule QtCreator \brief The CommandLine class represents a command line of a QProcess or similar utility. diff --git a/src/libs/utils/completingtextedit.cpp b/src/libs/utils/completingtextedit.cpp index 66d1e7e49f5..0fbdd2068bc 100644 --- a/src/libs/utils/completingtextedit.cpp +++ b/src/libs/utils/completingtextedit.cpp @@ -13,7 +13,9 @@ static bool isEndOfWordChar(const QChar &c) return !c.isLetterOrNumber() && c.category() != QChar::Punctuation_Connector; } -/*! \class Utils::CompletingTextEdit +/*! + \class Utils::CompletingTextEdit + \inmodule QtCreator \brief The CompletingTextEdit class is a QTextEdit with auto-completion support. diff --git a/src/libs/utils/detailswidget.cpp b/src/libs/utils/detailswidget.cpp index 420ed11b40f..ec7a3d22ebb 100644 --- a/src/libs/utils/detailswidget.cpp +++ b/src/libs/utils/detailswidget.cpp @@ -20,6 +20,7 @@ /*! \class Utils::DetailsWidget + \inmodule QtCreator \brief The DetailsWidget class implements a button to expand a \e Details area. diff --git a/src/libs/utils/deviceshell.cpp b/src/libs/utils/deviceshell.cpp index f6474721ace..ae983b6f482 100644 --- a/src/libs/utils/deviceshell.cpp +++ b/src/libs/utils/deviceshell.cpp @@ -14,10 +14,10 @@ Q_LOGGING_CATEGORY(deviceShellLog, "qtc.utils.deviceshell", QtWarningMsg) namespace Utils { -/*! +/* * The multiplex script waits for input via stdin. * - * To start a command, a message is send with + * To start a command, a message is sent with * the format " "" \n" * To stop the script, simply send "exit\n" via stdin * diff --git a/src/libs/utils/elidinglabel.cpp b/src/libs/utils/elidinglabel.cpp index cf74d5f3d92..0b328a82b16 100644 --- a/src/libs/utils/elidinglabel.cpp +++ b/src/libs/utils/elidinglabel.cpp @@ -9,6 +9,7 @@ /*! \class Utils::ElidingLabel + \inmodule QtCreator \brief The ElidingLabel class is a label suitable for displaying elided text. diff --git a/src/libs/utils/faketooltip.cpp b/src/libs/utils/faketooltip.cpp index 571d2027639..c94ce528e02 100644 --- a/src/libs/utils/faketooltip.cpp +++ b/src/libs/utils/faketooltip.cpp @@ -8,6 +8,7 @@ /*! \class Utils::FakeToolTip + \inmodule QtCreator \brief The FakeToolTip class is a widget that pretends to be a tooltip. diff --git a/src/libs/utils/fancylineedit.cpp b/src/libs/utils/fancylineedit.cpp index 443845e7801..ae931ec1ca0 100644 --- a/src/libs/utils/fancylineedit.cpp +++ b/src/libs/utils/fancylineedit.cpp @@ -26,6 +26,7 @@ /*! \class Utils::FancyLineEdit + \inmodule QtCreator \brief The FancyLineEdit class is an enhanced line edit with several opt-in features. diff --git a/src/libs/utils/fancymainwindow.cpp b/src/libs/utils/fancymainwindow.cpp index a19fc6c3c76..323e2508eba 100644 --- a/src/libs/utils/fancymainwindow.cpp +++ b/src/libs/utils/fancymainwindow.cpp @@ -311,7 +311,9 @@ void DockWidget::handleToplevelChanged(bool floating) -/*! \class Utils::FancyMainWindow +/*! + \class Utils::FancyMainWindow + \inmodule QtCreator \brief The FancyMainWindow class is a MainWindow with dock widgets and additional "lock" functionality diff --git a/src/libs/utils/fileinprojectfinder.cpp b/src/libs/utils/fileinprojectfinder.cpp index 6ee3c34becd..6ec36212eb0 100644 --- a/src/libs/utils/fileinprojectfinder.cpp +++ b/src/libs/utils/fileinprojectfinder.cpp @@ -40,6 +40,7 @@ static bool checkPath(const FilePath &candidate, int matchLength, /*! \class Utils::FileInProjectFinder + \inmodule QtCreator \brief The FileInProjectFinder class is a helper class to find the \e original file in the project directory for a given file URL. diff --git a/src/libs/utils/filenamevalidatinglineedit.cpp b/src/libs/utils/filenamevalidatinglineedit.cpp index 58112ceb6c0..5602e72d1a1 100644 --- a/src/libs/utils/filenamevalidatinglineedit.cpp +++ b/src/libs/utils/filenamevalidatinglineedit.cpp @@ -10,6 +10,7 @@ /*! \class Utils::FileNameValidatingLineEdit + \inmodule QtCreator \brief The FileNameValidatingLineEdit class is a control that lets the user choose a (base) file name, based on a QLineEdit. diff --git a/src/libs/utils/filepath.cpp b/src/libs/utils/filepath.cpp index 5681837582a..9ec738fdf26 100644 --- a/src/libs/utils/filepath.cpp +++ b/src/libs/utils/filepath.cpp @@ -37,7 +37,9 @@ static DeviceFileHooks s_deviceHooks; inline bool isWindowsDriveLetter(QChar ch); -/*! \class Utils::FilePath +/*! + \class Utils::FilePath + \inmodule QtCreator \brief The FilePath class is an abstraction for handles to objects in a (possibly remote) file system, similar to a URL or, in the local @@ -710,20 +712,39 @@ bool FilePath::isSameFile(const FilePath &other) const return false; } -static FilePaths appendExeExtensions(const Environment &env, const FilePath &executable) +static FilePaths appendExeExtensions(const FilePath &executable, + FilePath::MatchScope matchScope) { - FilePaths execs = {executable}; - if (executable.osType() == OsTypeWindows) { - // Check all the executable extensions on windows: - // PATHEXT is only used if the executable has no extension - if (executable.suffixView().isEmpty()) { - const QStringList extensions = env.expandedValueForKey("PATHEXT").split(';'); - - for (const QString &ext : extensions) - execs << executable.stringAppended(ext.toLower()); + FilePaths result = {executable}; + const QStringView suffix = executable.suffixView(); + if (executable.osType() == OsTypeWindows && suffix.isEmpty()) { + switch (matchScope) { + case FilePath::ExactMatchOnly: + break; + case FilePath::WithExeSuffix: + result.append(executable.stringAppended(".exe")); + break; + case FilePath::WithBatSuffix: + result.append(executable.stringAppended(".bat")); + break; + case FilePath::WithExeOrBatSuffix: + result.append(executable.stringAppended(".exe")); + result.append(executable.stringAppended(".bat")); + break; + case FilePath::WithAnySuffix: { + // Check all the executable extensions on windows: + // PATHEXT is only used if the executable has no extension + static const QStringList extensions = Environment::systemEnvironment() + .expandedValueForKey("PATHEXT").split(';'); + for (const QString &ext : extensions) + result.append(executable.stringAppended(ext.toLower())); + break; + } + default: + break; } } - return execs; + return result; } bool FilePath::isSameExecutable(const FilePath &other) const @@ -734,9 +755,8 @@ bool FilePath::isSameExecutable(const FilePath &other) const if (!isSameDevice(other)) return false; - const Environment env = other.deviceEnvironment(); - const FilePaths exe1List = appendExeExtensions(env, *this); - const FilePaths exe2List = appendExeExtensions(env, other); + const FilePaths exe1List = appendExeExtensions(*this, WithAnySuffix); + const FilePaths exe2List = appendExeExtensions(other, WithAnySuffix); for (const FilePath &f1 : exe1List) { for (const FilePath &f2 : exe2List) { if (f1.isSameFile(f2)) @@ -1478,32 +1498,63 @@ FilePath FilePath::withNewPath(const QString &newPath) const assert(fullPath == FilePath::fromUrl("docker://123/usr/bin/make")) \endcode */ -FilePath FilePath::searchInDirectories(const FilePaths &dirs, const FilePathPredicate &filter) const + +FilePath FilePath::searchInDirectories(const FilePaths &dirs, + const FilePathPredicate &filter, + const MatchScope &matchScope) const { - if (isAbsolutePath()) - return *this; - return deviceEnvironment().searchInDirectories(path(), dirs, filter); + if (isEmpty()) + return {}; + + const FilePaths execs = appendExeExtensions(*this, matchScope); + + if (isAbsolutePath()) { + for (const FilePath &filePath : execs) { + if (filePath.isExecutableFile() && (!filter || filter(filePath))) + return filePath; + } + return {}; + } + + QSet alreadyCheckedDirectories; + + for (const FilePath &dir : dirs) { + // Compare the initial size of the set with the size after insertion to check + // if the directory was already checked. + const int initialCount = alreadyCheckedDirectories.count(); + alreadyCheckedDirectories.insert(dir); + const bool wasAlreadyChecked = alreadyCheckedDirectories.count() == initialCount; + + if (dir.isEmpty() || wasAlreadyChecked) + continue; + + for (const FilePath &exe : execs) { + const FilePath filePath = dir / exe.path(); + if (filePath.isExecutableFile() && (!filter || filter(filePath))) + return filePath; + } + } + + return {}; } FilePath FilePath::searchInPath(const FilePaths &additionalDirs, PathAmending amending, - const FilePathPredicate &filter) const + const FilePathPredicate &filter, + const MatchScope &matchScope) const { if (isAbsolutePath()) return *this; - FilePaths directories = deviceEnvironment().path(); - if (needsDevice()) { - directories = Utils::transform(directories, [this](const FilePath &filePath) { - return withNewPath(filePath.path()); - }); - } + + FilePaths directories = devicePathEnvironmentVariable(); + if (!additionalDirs.isEmpty()) { if (amending == AppendToPath) directories.append(additionalDirs); else directories = additionalDirs + directories; } - return searchInDirectories(directories, filter); + return searchInDirectories(directories, filter, matchScope); } Environment FilePath::deviceEnvironment() const @@ -1515,6 +1566,16 @@ Environment FilePath::deviceEnvironment() const return Environment::systemEnvironment(); } +FilePaths FilePath::devicePathEnvironmentVariable() const +{ + FilePaths result = deviceEnvironment().path(); + if (needsDevice()) { + for (FilePath &dir : result) + dir.setParts(this->scheme(), this->host(), dir.path()); + } + return result; +} + QString FilePath::formatFilePaths(const FilePaths &files, const QString &separator) { const QStringList nativeFiles = transform(files, &FilePath::toUserOutput); diff --git a/src/libs/utils/filepath.h b/src/libs/utils/filepath.h index 142542b7343..2a41c6c615b 100644 --- a/src/libs/utils/filepath.h +++ b/src/libs/utils/filepath.h @@ -161,9 +161,8 @@ public: [[nodiscard]] FilePath withExecutableSuffix() const; [[nodiscard]] FilePath relativeChildPath(const FilePath &parent) const; [[nodiscard]] FilePath relativePathFrom(const FilePath &anchor) const; - [[nodiscard]] FilePath searchInDirectories(const FilePaths &dirs, - const FilePathPredicate &filter = {}) const; [[nodiscard]] Environment deviceEnvironment() const; + [[nodiscard]] FilePaths devicePathEnvironmentVariable() const; [[nodiscard]] FilePath withNewPath(const QString &newPath) const; [[nodiscard]] FilePath withNewMappedPath(const FilePath &newPath) const; @@ -183,12 +182,17 @@ public: const FileFilter &filter); enum PathAmending { AppendToPath, PrependToPath }; - [[nodiscard]] FilePath searchInPath(const FilePaths &additionalDirs = {}, - PathAmending = AppendToPath, - const FilePathPredicate &filter = {}) const; - enum MatchScope { ExactMatchOnly, WithExeSuffix, WithBatSuffix, WithExeOrBatSuffix, WithAnySuffix }; + + [[nodiscard]] FilePath searchInDirectories(const FilePaths &dirs, + const FilePathPredicate &filter = {}, + const MatchScope &matchScope = {}) const; + [[nodiscard]] FilePath searchInPath(const FilePaths &additionalDirs = {}, + PathAmending = AppendToPath, + const FilePathPredicate &filter = {}, + const MatchScope &matchScope = {}) const; + std::optional refersToExecutableFile(MatchScope considerScript) const; [[nodiscard]] expected_str tmpDir() const; diff --git a/src/libs/utils/filesystemwatcher.cpp b/src/libs/utils/filesystemwatcher.cpp index d1c2e003116..9a4d7b56930 100644 --- a/src/libs/utils/filesystemwatcher.cpp +++ b/src/libs/utils/filesystemwatcher.cpp @@ -28,6 +28,7 @@ static inline quint64 getFileLimit() /*! \class Utils::FileSystemWatcher + \inmodule QtCreator \brief The FileSystemWatcher class is a file watcher that internally uses a centralized QFileSystemWatcher and enforces limits on Mac OS. diff --git a/src/libs/utils/fileutils.cpp b/src/libs/utils/fileutils.cpp index 98d190e2966..a6cbebf3681 100644 --- a/src/libs/utils/fileutils.cpp +++ b/src/libs/utils/fileutils.cpp @@ -259,7 +259,9 @@ TempFileSaver::~TempFileSaver() QFile::remove(m_filePath.toString()); } -/*! \class Utils::FileUtils +/*! + \class Utils::FileUtils + \inmodule QtCreator \brief The FileUtils class contains file and directory related convenience functions. diff --git a/src/libs/utils/filewizardpage.cpp b/src/libs/utils/filewizardpage.cpp index cc1f83b6969..a883f960566 100644 --- a/src/libs/utils/filewizardpage.cpp +++ b/src/libs/utils/filewizardpage.cpp @@ -8,6 +8,7 @@ /*! \class Utils::FileWizardPage + \inmodule QtCreator \brief The FileWizardPage class is a standard wizard page for a single file letting the user choose name diff --git a/src/libs/utils/futuresynchronizer.cpp b/src/libs/utils/futuresynchronizer.cpp index baef71f4ef3..da3347f35e3 100644 --- a/src/libs/utils/futuresynchronizer.cpp +++ b/src/libs/utils/futuresynchronizer.cpp @@ -3,7 +3,9 @@ #include "futuresynchronizer.h" -/*! \class Utils::FutureSynchronizer +/*! + \class Utils::FutureSynchronizer + \inmodule QtCreator \brief The FutureSynchronizer is an enhanced version of QFutureSynchronizer. */ diff --git a/src/libs/utils/guard.cpp b/src/libs/utils/guard.cpp index a70faf2c405..0273e7c9b8d 100644 --- a/src/libs/utils/guard.cpp +++ b/src/libs/utils/guard.cpp @@ -4,7 +4,9 @@ #include "guard.h" #include "qtcassert.h" -/*! \class Utils::Guard +/*! + \class Utils::Guard + \inmodule QtCreator \brief The Guard class implements a recursive guard with locking mechanism. diff --git a/src/libs/utils/headerviewstretcher.cpp b/src/libs/utils/headerviewstretcher.cpp index 3bc5c1d515c..2c0dd00ca02 100644 --- a/src/libs/utils/headerviewstretcher.cpp +++ b/src/libs/utils/headerviewstretcher.cpp @@ -10,6 +10,7 @@ using namespace Utils; /*! \class Utils::HeaderViewStretcher + \inmodule QtCreator \brief The HeaderViewStretcher class fixes QHeaderView to resize all columns to contents, except one diff --git a/src/libs/utils/itemviews.cpp b/src/libs/utils/itemviews.cpp index 8af7eba5a18..27f7cbb4281 100644 --- a/src/libs/utils/itemviews.cpp +++ b/src/libs/utils/itemviews.cpp @@ -5,6 +5,7 @@ /*! \class Utils::TreeView + \inmodule QtCreator \brief The TreeView adds setActivationMode to QTreeView to allow for single click/double click behavior on @@ -15,6 +16,7 @@ /*! \class Utils::TreeWidget + \inmodule QtCreator \brief The TreeWidget adds setActivationMode to QTreeWidget to allow for single click/double click behavior on @@ -25,6 +27,7 @@ /*! \class Utils::ListView + \inmodule QtCreator \brief The ListView adds setActivationMode to QListView to allow for single click/double click behavior on @@ -35,6 +38,7 @@ /*! \class Utils::ListWidget + \inmodule QtCreator \brief The ListWidget adds setActivationMode to QListWidget to allow for single click/double click behavior on diff --git a/src/libs/utils/layoutbuilder.cpp b/src/libs/utils/layoutbuilder.cpp index 43dd68c7905..017a147897e 100644 --- a/src/libs/utils/layoutbuilder.cpp +++ b/src/libs/utils/layoutbuilder.cpp @@ -175,6 +175,14 @@ private: int m_vSpace; }; +/*! + \namespace Layouting + \inmodule QtCreator + + \brief The Layouting namespace contains classes for use with layout builders. +*/ + + /*! \class Layouting::LayoutItem \inmodule QtCreator @@ -469,18 +477,18 @@ void doAddWidget(LayoutBuilder &builder, QWidget *widget) \class Layouting::Space \inmodule QtCreator - \brief The Layouting::Space class represents some empty space in a layout. + \brief The Space class represents some empty space in a layout. */ /*! \class Layouting::Stretch \inmodule QtCreator - \brief The Layouting::Stretch class represents some stretch in a layout. + \brief The Stretch class represents some stretch in a layout. */ /*! - \class LayoutBuilder + \class Layouting::LayoutBuilder \inmodule QtCreator \brief The LayoutBuilder class provides a convenient way to fill \c QFormLayout diff --git a/src/libs/utils/macroexpander.cpp b/src/libs/utils/macroexpander.cpp index 644268d7cf4..43d23d2d190 100644 --- a/src/libs/utils/macroexpander.cpp +++ b/src/libs/utils/macroexpander.cpp @@ -104,6 +104,7 @@ using namespace Internal; /*! \class Utils::MacroExpander + \inmodule QtCreator \brief The MacroExpander class manages \QC wide variables, that a user can enter into many string settings. The variables are replaced by an actual value when the string is used, similar to how environment variables are expanded by a shell. diff --git a/src/libs/utils/navigationtreeview.cpp b/src/libs/utils/navigationtreeview.cpp index 8394388f17d..7a6bd4be234 100644 --- a/src/libs/utils/navigationtreeview.cpp +++ b/src/libs/utils/navigationtreeview.cpp @@ -9,6 +9,7 @@ /*! \class Utils::NavigationTreeView + \inmodule QtCreator \brief The NavigationTreeView class implements a general TreeView for any sidebar widget. diff --git a/src/libs/utils/optionpushbutton.cpp b/src/libs/utils/optionpushbutton.cpp index f98f9ee5a33..c3993fef4b0 100644 --- a/src/libs/utils/optionpushbutton.cpp +++ b/src/libs/utils/optionpushbutton.cpp @@ -11,6 +11,7 @@ namespace Utils { /*! \class Utils::OptionPushButton + \inmodule QtCreator \brief The OptionPushButton class implements a QPushButton for which the menu is only opened if the user presses the menu indicator. diff --git a/src/libs/utils/parameteraction.cpp b/src/libs/utils/parameteraction.cpp index 13efd9fa013..a77154b41f2 100644 --- a/src/libs/utils/parameteraction.cpp +++ b/src/libs/utils/parameteraction.cpp @@ -5,6 +5,7 @@ /*! \class Utils::ParameterAction + \inmodule QtCreator \brief The ParameterAction class is intended for actions that act on a 'current', string-type parameter (typically a file name), for example 'Save file %1'. diff --git a/src/libs/utils/pathlisteditor.cpp b/src/libs/utils/pathlisteditor.cpp index fc7beb75977..f2349b275fd 100644 --- a/src/libs/utils/pathlisteditor.cpp +++ b/src/libs/utils/pathlisteditor.cpp @@ -16,6 +16,7 @@ /*! \class Utils::PathListEditor + \inmodule QtCreator \brief The PathListEditor class is a control that lets the user edit a list of (directory) paths diff --git a/src/libs/utils/persistentsettings.cpp b/src/libs/utils/persistentsettings.cpp index 1db834bff7f..2daf2934c51 100644 --- a/src/libs/utils/persistentsettings.cpp +++ b/src/libs/utils/persistentsettings.cpp @@ -50,6 +50,7 @@ static QRect stringToRectangle(const QString &v) /*! \class Utils::PersistentSettingsReader + \inmodule QtCreator \brief The PersistentSettingsReader class reads a QVariantMap of arbitrary, nested data structures from an XML file. @@ -349,6 +350,7 @@ FilePath PersistentSettingsReader::filePath() /*! \class Utils::PersistentSettingsWriter + \inmodule QtCreator \brief The PersistentSettingsWriter class serializes a QVariantMap of arbitrary, nested data structures to an XML file. diff --git a/src/libs/utils/port.cpp b/src/libs/utils/port.cpp index c41a65335db..7ddd3ea0da4 100644 --- a/src/libs/utils/port.cpp +++ b/src/libs/utils/port.cpp @@ -10,7 +10,9 @@ #include -/*! \class Utils::Port +/*! + \class Utils::Port + \inmodule QtCreator \brief The Port class implements a wrapper around a 16 bit port number to be used in conjunction with IP addresses. diff --git a/src/libs/utils/process.cpp b/src/libs/utils/process.cpp index f25bc3d3fde..9a798ec11cf 100644 --- a/src/libs/utils/process.cpp +++ b/src/libs/utils/process.cpp @@ -1086,6 +1086,7 @@ ProcessResult ProcessPrivate::interpretExitCode(int exitCode) /*! \class Utils::Process + \inmodule QtCreator \brief The Process class provides functionality for with processes. @@ -1596,6 +1597,7 @@ QString Process::readAllStandardError() /*! \class Utils::SynchronousProcess + \inmodule QtCreator \brief The SynchronousProcess class runs a synchronous process in its own event loop that blocks only user input events. Thus, it allows for the GUI to diff --git a/src/libs/utils/processhandle.cpp b/src/libs/utils/processhandle.cpp index 686b1157adf..06850457d37 100644 --- a/src/libs/utils/processhandle.cpp +++ b/src/libs/utils/processhandle.cpp @@ -7,6 +7,7 @@ namespace Utils { /*! \class Utils::ProcessHandle + \inmodule QtCreator \brief The ProcessHandle class is a helper class to describe a process. Encapsulates parameters of a running process, local (PID) or remote (to be diff --git a/src/libs/utils/projectintropage.cpp b/src/libs/utils/projectintropage.cpp index cb7018943d1..dba9a801e4b 100644 --- a/src/libs/utils/projectintropage.cpp +++ b/src/libs/utils/projectintropage.cpp @@ -22,6 +22,7 @@ /*! \class Utils::ProjectIntroPage + \inmodule QtCreator \brief The ProjectIntroPage class is the standard wizard page for a project, letting the user choose its name diff --git a/src/libs/utils/statuslabel.cpp b/src/libs/utils/statuslabel.cpp index 32db235b66c..26d5a5b3614 100644 --- a/src/libs/utils/statuslabel.cpp +++ b/src/libs/utils/statuslabel.cpp @@ -7,6 +7,7 @@ /*! \class Utils::StatusLabel + \inmodule QtCreator \brief The StatusLabel class displays messages for a while with a timeout. */ diff --git a/src/libs/utils/textfieldcheckbox.cpp b/src/libs/utils/textfieldcheckbox.cpp index 5dae8538ae6..a00f840422a 100644 --- a/src/libs/utils/textfieldcheckbox.cpp +++ b/src/libs/utils/textfieldcheckbox.cpp @@ -7,6 +7,7 @@ namespace Utils { /*! \class Utils::TextFieldCheckBox + \inmodule QtCreator \brief The TextFieldCheckBox class is a aheckbox that plays with \c QWizard::registerField. diff --git a/src/libs/utils/textfieldcombobox.cpp b/src/libs/utils/textfieldcombobox.cpp index 5d72f523a57..790358a1df9 100644 --- a/src/libs/utils/textfieldcombobox.cpp +++ b/src/libs/utils/textfieldcombobox.cpp @@ -9,6 +9,7 @@ namespace Utils { /*! \class Utils::TextFieldComboBox + \inmodule QtCreator \brief The TextFieldComboBox class is a non-editable combo box for text editing purposes that plays with \c QWizard::registerField (providing a settable 'text' property). diff --git a/src/libs/utils/textfileformat.cpp b/src/libs/utils/textfileformat.cpp index 28fb243abf7..094c6d0d72f 100644 --- a/src/libs/utils/textfileformat.cpp +++ b/src/libs/utils/textfileformat.cpp @@ -33,6 +33,7 @@ QDebug operator<<(QDebug d, const TextFileFormat &format) /*! \class Utils::TextFileFormat + \inmodule QtCreator \brief The TextFileFormat class describes the format of a text file and provides autodetection. diff --git a/src/libs/utils/treemodel.cpp b/src/libs/utils/treemodel.cpp index 344a77d837c..53477b53c97 100644 --- a/src/libs/utils/treemodel.cpp +++ b/src/libs/utils/treemodel.cpp @@ -895,6 +895,7 @@ void TreeItem::propagateModel(BaseTreeModel *m) /*! \class Utils::TreeModel + \inmodule QtCreator \brief The TreeModel class is a convienience base class for models to use in a QTreeView. diff --git a/src/libs/utils/utils.qdoc b/src/libs/utils/utils.qdoc index c0717043314..bc9f843498c 100644 --- a/src/libs/utils/utils.qdoc +++ b/src/libs/utils/utils.qdoc @@ -3,7 +3,8 @@ /*! \namespace Utils + \inmodule QtCreator - The Utils namespace contains a collection of utility classes and functions for use by all + \brief The Utils namespace contains a collection of utility classes and functions for use by all plugins. */ diff --git a/src/libs/utils/wizard.cpp b/src/libs/utils/wizard.cpp index 9fca25eaead..ce37d80705e 100644 --- a/src/libs/utils/wizard.cpp +++ b/src/libs/utils/wizard.cpp @@ -23,7 +23,9 @@ #include -/*! \class Utils::Wizard +/*! + \class Utils::Wizard + \inmodule QtCreator \brief The Wizard class implements a wizard with a progress bar on the left. diff --git a/src/libs/utils/wizardpage.cpp b/src/libs/utils/wizardpage.cpp index 740f46e8fc9..c4730b70115 100644 --- a/src/libs/utils/wizardpage.cpp +++ b/src/libs/utils/wizardpage.cpp @@ -5,7 +5,9 @@ #include "wizard.h" -/*! \class Utils::WizardPage +/*! + \class Utils::WizardPage + \inmodule QtCreator \brief QWizardPage with a couple of improvements. diff --git a/src/plugins/coreplugin/locator/ilocatorfilter.cpp b/src/plugins/coreplugin/locator/ilocatorfilter.cpp index 930b2c918d9..f277884cce3 100644 --- a/src/plugins/coreplugin/locator/ilocatorfilter.cpp +++ b/src/plugins/coreplugin/locator/ilocatorfilter.cpp @@ -1268,6 +1268,7 @@ LocatorFilterEntries LocatorFileCachePrivate::generate(const QFuture &futu /*! \class Core::LocatorFileCache + \inmodule QtCreator \brief The LocatorFileCache class encapsulates all the responsibilities needed for implementing a cache for file filters. diff --git a/src/plugins/coreplugin/locator/locator.cpp b/src/plugins/coreplugin/locator/locator.cpp index fb9f50c3b1f..55b82920329 100644 --- a/src/plugins/coreplugin/locator/locator.cpp +++ b/src/plugins/coreplugin/locator/locator.cpp @@ -26,6 +26,8 @@ #include "../settingsdatabase.h" #include "../statusbarmanager.h" +#include + #include #include #include @@ -147,7 +149,6 @@ bool Locator::delayedInitialize() void Locator::aboutToShutdown() { - m_shuttingDown = true; m_refreshTimer.stop(); m_taskTree.reset(); } @@ -373,7 +374,7 @@ void Locator::setUseCenteredPopupForShortcut(bool center) void Locator::refresh(const QList &filters) { - if (m_shuttingDown) + if (ExtensionSystem::PluginManager::isShuttingDown()) return; m_taskTree.reset(); // Superfluous, just for clarity. The next reset() below is enough. diff --git a/src/plugins/coreplugin/locator/locator.h b/src/plugins/coreplugin/locator/locator.h index 3e73054153c..45d4b650508 100644 --- a/src/plugins/coreplugin/locator/locator.h +++ b/src/plugins/coreplugin/locator/locator.h @@ -67,7 +67,6 @@ private: bool useCenteredPopup = false; }; - bool m_shuttingDown = false; bool m_settingsInitialized = false; Settings m_settings; QList m_filters; diff --git a/src/plugins/coreplugin/progressmanager/processprogress.cpp b/src/plugins/coreplugin/progressmanager/processprogress.cpp index 57b9dcbbfb2..9aeebf4ecf0 100644 --- a/src/plugins/coreplugin/progressmanager/processprogress.cpp +++ b/src/plugins/coreplugin/progressmanager/processprogress.cpp @@ -70,6 +70,7 @@ void ProcessProgressPrivate::parseProgress(const QString &inputText) /*! \class Core::ProcessProgress + \inmodule QtCreator \brief The ProcessProgress class is responsible for showing progress of the running process. diff --git a/src/plugins/coreplugin/progressmanager/taskprogress.cpp b/src/plugins/coreplugin/progressmanager/taskprogress.cpp index c82ec339c51..5ee5feb24a8 100644 --- a/src/plugins/coreplugin/progressmanager/taskprogress.cpp +++ b/src/plugins/coreplugin/progressmanager/taskprogress.cpp @@ -91,6 +91,7 @@ void TaskProgressPrivate::updateProgress() /*! \class Core::TaskProgress + \inmodule QtCreator \brief The TaskProgress class is responsible for showing progress of the running task tree. diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 87ae84dd8d6..7ccc808b08f 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -686,7 +686,6 @@ public: EngineManager m_engineManager; QTimer m_shutdownTimer; - bool m_shuttingDown = false; Console m_console; // ensure Debugger Console is created before settings are taken into account DebuggerSettings m_debuggerSettings; @@ -1392,7 +1391,7 @@ static QVariant configValue(const QString &name) void DebuggerPluginPrivate::updatePresetState() { - if (m_shuttingDown) + if (PluginManager::isShuttingDown()) return; Project *startupProject = ProjectManager::startupProject(); @@ -1996,8 +1995,6 @@ void DebuggerPluginPrivate::dumpLog() void DebuggerPluginPrivate::aboutToShutdown() { - m_shuttingDown = true; - disconnect(ProjectManager::instance(), &ProjectManager::startupProjectChanged, this, nullptr); m_shutdownTimer.setInterval(0); @@ -2081,7 +2078,7 @@ QWidget *addSearch(BaseTreeView *treeView) void openTextEditor(const QString &titlePattern0, const QString &contents) { - if (dd->m_shuttingDown) + if (PluginManager::isShuttingDown()) return; QString titlePattern = titlePattern0; IEditor *editor = EditorManager::openEditorWithContents( diff --git a/src/plugins/emacskeys/emacskeysplugin.cpp b/src/plugins/emacskeys/emacskeysplugin.cpp index acb2be5b892..4f1fa8c2c82 100644 --- a/src/plugins/emacskeys/emacskeysplugin.cpp +++ b/src/plugins/emacskeys/emacskeysplugin.cpp @@ -135,11 +135,6 @@ void EmacsKeysPlugin::extensionsInitialized() { } -ExtensionSystem::IPlugin::ShutdownFlag EmacsKeysPlugin::aboutToShutdown() -{ - return SynchronousShutdown; -} - void EmacsKeysPlugin::editorAboutToClose(IEditor *editor) { auto w = qobject_cast(editor->widget()); diff --git a/src/plugins/emacskeys/emacskeysplugin.h b/src/plugins/emacskeys/emacskeysplugin.h index b0acb078cc0..ab124b47ce3 100644 --- a/src/plugins/emacskeys/emacskeysplugin.h +++ b/src/plugins/emacskeys/emacskeysplugin.h @@ -57,7 +57,6 @@ public: void initialize() override; void extensionsInitialized() override; - ShutdownFlag aboutToShutdown() override; private: void editorAboutToClose(Core::IEditor *editor); diff --git a/src/plugins/fossil/fossilclient.cpp b/src/plugins/fossil/fossilclient.cpp index 915121710aa..f7bb29f2aea 100644 --- a/src/plugins/fossil/fossilclient.cpp +++ b/src/plugins/fossil/fossilclient.cpp @@ -107,12 +107,9 @@ class FossilLogConfig : public VcsBaseEditorConfig Q_OBJECT public: - FossilLogConfig(FossilClient *client, QToolBar *toolBar) : - VcsBaseEditorConfig(toolBar), - m_client(client) + FossilLogConfig(QToolBar *toolBar) + : VcsBaseEditorConfig(toolBar) { - QTC_ASSERT(client, return); - addReloadButton(); addLineageComboBox(); addVerboseToggleButton(); @@ -192,9 +189,6 @@ public: } return args; } - -private: - FossilClient *m_client; }; unsigned FossilClient::makeVersionNumber(int major, int minor, int patch) @@ -1169,7 +1163,7 @@ VcsBaseEditorConfig *FossilClient::createLogCurrentFileEditor(VcsBaseEditorWidge VcsBaseEditorConfig *FossilClient::createLogEditor(VcsBaseEditorWidget *editor) { - return new FossilLogConfig(this, editor->toolBar()); + return new FossilLogConfig(editor->toolBar()); } } // namespace Internal diff --git a/src/plugins/languageclient/client.cpp b/src/plugins/languageclient/client.cpp index 77b2cbfdee5..5b0fbfa304f 100644 --- a/src/plugins/languageclient/client.cpp +++ b/src/plugins/languageclient/client.cpp @@ -28,6 +28,8 @@ #include #include +#include + #include #include #include @@ -194,7 +196,7 @@ public: // temporary container needed since m_resetAssistProvider is changed in resetAssistProviders for (TextDocument *document : m_resetAssistProvider.keys()) resetAssistProviders(document); - if (!LanguageClientManager::isShuttingDown()) { + if (!ExtensionSystem::PluginManager::isShuttingDown()) { // prevent accessing deleted editors on Creator shutdown const QList &editors = Core::DocumentModel::editorsForOpenedDocuments(); for (Core::IEditor *editor : editors) { diff --git a/src/plugins/languageclient/languageclientmanager.cpp b/src/plugins/languageclient/languageclientmanager.cpp index 4de4a0de46e..4c8fa425303 100644 --- a/src/plugins/languageclient/languageclientmanager.cpp +++ b/src/plugins/languageclient/languageclientmanager.cpp @@ -14,6 +14,8 @@ #include #include +#include + #include #include @@ -32,6 +34,7 @@ #include +using namespace ExtensionSystem; using namespace LanguageServerProtocol; namespace LanguageClient { @@ -39,7 +42,6 @@ namespace LanguageClient { static Q_LOGGING_CATEGORY(Log, "qtc.languageclient.manager", QtWarningMsg) static LanguageClientManager *managerInstance = nullptr; -static bool g_shuttingDown = false; class LanguageClientManagerPrivate { @@ -139,7 +141,7 @@ void LanguageClientManager::clientStarted(Client *client) QTC_ASSERT(client, return); if (client->state() != Client::Uninitialized) // do not proceed if we already received an error return; - if (g_shuttingDown) { + if (PluginManager::isShuttingDown()) { clientFinished(client); return; } @@ -165,7 +167,7 @@ void LanguageClientManager::clientFinished(Client *client) && client->state() != Client::ShutdownRequested; if (unexpectedFinish) { - if (!g_shuttingDown) { + if (!PluginManager::isShuttingDown()) { const QList &clientDocs = managerInstance->m_clientForDocument.keys(client); if (client->reset()) { @@ -187,7 +189,7 @@ void LanguageClientManager::clientFinished(Client *client) } } deleteClient(client); - if (g_shuttingDown && managerInstance->m_clients.isEmpty()) + if (PluginManager::isShuttingDown() && managerInstance->m_clients.isEmpty()) emit managerInstance->shutdownFinished(); } @@ -236,17 +238,14 @@ void LanguageClientManager::deleteClient(Client *client) for (QList &clients : managerInstance->m_clientsForSetting) clients.removeAll(client); client->deleteLater(); - if (!g_shuttingDown) + if (!PluginManager::isShuttingDown()) emit instance()->clientRemoved(client); } void LanguageClientManager::shutdown() { QTC_ASSERT(managerInstance, return); - if (g_shuttingDown) - return; qCDebug(Log) << "shutdown manager"; - g_shuttingDown = true; const auto clients = managerInstance->clients(); for (Client *client : clients) shutdownClient(client); @@ -258,11 +257,6 @@ void LanguageClientManager::shutdown() }); } -bool LanguageClientManager::isShuttingDown() -{ - return g_shuttingDown; -} - LanguageClientManager *LanguageClientManager::instance() { return managerInstance; diff --git a/src/plugins/languageclient/languageclientmanager.h b/src/plugins/languageclient/languageclientmanager.h index fdbbec98b6f..e29d87a0f23 100644 --- a/src/plugins/languageclient/languageclientmanager.h +++ b/src/plugins/languageclient/languageclientmanager.h @@ -48,7 +48,6 @@ public: static void deleteClient(Client *client); static void shutdown(); - static bool isShuttingDown(); static LanguageClientManager *instance(); diff --git a/src/plugins/projectexplorer/makestep.cpp b/src/plugins/projectexplorer/makestep.cpp index b3b9c934868..56b04b4b7f6 100644 --- a/src/plugins/projectexplorer/makestep.cpp +++ b/src/plugins/projectexplorer/makestep.cpp @@ -22,9 +22,6 @@ #include #include -#include -#include -#include #include #include diff --git a/src/plugins/projectexplorer/makestep.h b/src/plugins/projectexplorer/makestep.h index 73c4e9b7e79..2f12894ea61 100644 --- a/src/plugins/projectexplorer/makestep.h +++ b/src/plugins/projectexplorer/makestep.h @@ -73,7 +73,6 @@ private: QStringList jobArguments() const; Utils::MultiSelectionAspect *m_buildTargetsAspect = nullptr; - QStringList m_availableTargets; // FIXME: Unused, remove in 4.15. Utils::StringAspect *m_makeCommandAspect = nullptr; Utils::StringAspect *m_userArgumentsAspect = nullptr; Utils::IntegerAspect *m_userJobCountAspect = nullptr; diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index 1244dbd1ba2..d1ad20fe57c 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -177,6 +177,7 @@ */ using namespace Core; +using namespace ExtensionSystem; using namespace ProjectExplorer::Internal; using namespace Utils; @@ -600,7 +601,6 @@ public: BuildPropertiesSettings m_buildPropertiesSettings; QList m_customParsers; bool m_shouldHaveRunConfiguration = false; - bool m_shuttingDown = false; Id m_runMode = Constants::NO_RUN_MODE; ToolChainManager *m_toolChainManager = nullptr; @@ -1632,11 +1632,11 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er connect(ICore::instance(), &ICore::saveSettingsRequested, dd, &ProjectExplorerPluginPrivate::savePersistentSettings); connect(EditorManager::instance(), &EditorManager::autoSaved, this, [] { - if (!dd->m_shuttingDown && !SessionManager::loadingSession()) - ProjectManager::save(); + if (!PluginManager::isShuttingDown() && !SessionManager::loadingSession()) + SessionManager::saveSession(); }); connect(qApp, &QApplication::applicationStateChanged, this, [](Qt::ApplicationState state) { - if (!dd->m_shuttingDown && state == Qt::ApplicationActive) + if (!PluginManager::isShuttingDown() && state == Qt::ApplicationActive) dd->updateWelcomePage(); }); @@ -2173,7 +2173,7 @@ void ProjectExplorerPluginPrivate::updateRunWithoutDeployMenu() m_runWithoutDeployAction->setVisible(m_projectExplorerSettings.deployBeforeRun); } -ExtensionSystem::IPlugin::ShutdownFlag ProjectExplorerPlugin::aboutToShutdown() +IPlugin::ShutdownFlag ProjectExplorerPlugin::aboutToShutdown() { disconnect(ModeManager::instance(), &ModeManager::currentModeChanged, dd, &ProjectExplorerPluginPrivate::currentModeChanged); @@ -2181,8 +2181,6 @@ ExtensionSystem::IPlugin::ShutdownFlag ProjectExplorerPlugin::aboutToShutdown() ToolChainManager::aboutToShutdown(); ProjectManager::closeAllProjects(); - dd->m_shuttingDown = true; - // Attempt to synchronously shutdown all run controls. // If that fails, fall back to asynchronous shutdown (Debugger run controls // might shutdown asynchronously). @@ -2212,7 +2210,7 @@ void ProjectExplorerPlugin::openNewProjectDialog() void ProjectExplorerPluginPrivate::showSessionManager() { - ProjectManager::save(); + SessionManager::saveSession(); SessionDialog sessionDialog(ICore::dialogParent()); sessionDialog.setAutoLoadSession(sb_d->isAutoRestoreLastSession()); sessionDialog.exec(); @@ -2251,14 +2249,14 @@ bool ProjectExplorerPluginPrivate::closeAllFilesInProject(const Project *project void ProjectExplorerPluginPrivate::savePersistentSettings() { - if (dd->m_shuttingDown) + if (PluginManager::isShuttingDown()) return; if (!SessionManager::loadingSession()) { for (Project *pro : ProjectManager::projects()) pro->saveSettings(); - ProjectManager::save(); + SessionManager::saveSession(); } QtcSettings *s = ICore::settings(); @@ -2560,7 +2558,7 @@ void ProjectExplorerPluginPrivate::checkForShutdown() { --m_activeRunControlCount; QTC_ASSERT(m_activeRunControlCount >= 0, m_activeRunControlCount = 0); - if (m_shuttingDown && m_activeRunControlCount == 0) + if (PluginManager::isShuttingDown() && m_activeRunControlCount == 0) emit m_instance->asynchronousShutdownFinished(); } diff --git a/src/plugins/projectexplorer/projectmanager.cpp b/src/plugins/projectexplorer/projectmanager.cpp index ccfa95a289a..ff5b214b10a 100644 --- a/src/plugins/projectexplorer/projectmanager.cpp +++ b/src/plugins/projectexplorer/projectmanager.cpp @@ -53,6 +53,7 @@ class ProjectManagerPrivate { public: void loadSession(); + void saveSession(); void restoreDependencies(); void restoreStartupProject(); void restoreProjects(const FilePaths &fileList); @@ -109,6 +110,9 @@ ProjectManager::ProjectManager() connect(SessionManager::instance(), &SessionManager::aboutToLoadSession, this, [] { d->loadSession(); }); + connect(SessionManager::instance(), &SessionManager::aboutToSaveSession, this, [] { + d->saveSession(); + }); } ProjectManager::~ProjectManager() @@ -315,87 +319,38 @@ void ProjectManager::removeProject(Project *project) removeProjects({project}); } -bool ProjectManager::save() +void ProjectManagerPrivate::saveSession() { - emit SessionManager::instance()->aboutToSaveSession(); + // save the startup project + if (d->m_startupProject) + SessionManager::setSessionValue("StartupProject", + m_startupProject->projectFilePath().toSettings()); - const FilePath filePath = SessionManager::sessionNameToFileName(sb_d->m_sessionName); - QVariantMap data; - - // See the explanation at loadSession() for how we handle the implicit default session. - if (SessionManager::isDefaultVirgin()) { - if (filePath.exists()) { - PersistentSettingsReader reader; - if (!reader.load(filePath)) { - QMessageBox::warning(ICore::dialogParent(), Tr::tr("Error while saving session"), - Tr::tr("Could not save session %1").arg(filePath.toUserOutput())); - return false; - } - data = reader.restoreValues(); - } - } else { - // save the startup project - if (d->m_startupProject) - data.insert("StartupProject", d->m_startupProject->projectFilePath().toSettings()); - - const QColor c = StyleHelper::requestedBaseColor(); - if (c.isValid()) { - QString tmp = QString::fromLatin1("#%1%2%3") - .arg(c.red(), 2, 16, QLatin1Char('0')) - .arg(c.green(), 2, 16, QLatin1Char('0')) - .arg(c.blue(), 2, 16, QLatin1Char('0')); - data.insert(QLatin1String("Color"), tmp); - } - - FilePaths projectFiles = Utils::transform(projects(), &Project::projectFilePath); - // Restore information on projects that failed to load: - // don't read projects to the list, which the user loaded - for (const FilePath &failed : std::as_const(d->m_failedProjects)) { - if (!projectFiles.contains(failed)) - projectFiles << failed; - } - - data.insert("ProjectList", Utils::transform(projectFiles, - &FilePath::toString)); - data.insert("CascadeSetActive", d->m_casadeSetActive); - - QVariantMap depMap; - auto i = d->m_depMap.constBegin(); - while (i != d->m_depMap.constEnd()) { - QString key = i.key().toString(); - QStringList values; - const FilePaths valueList = i.value(); - for (const FilePath &value : valueList) - values << value.toString(); - depMap.insert(key, values); - ++i; - } - data.insert(QLatin1String("ProjectDependencies"), QVariant(depMap)); - data.insert(QLatin1String("EditorSettings"), EditorManager::saveState().toBase64()); + FilePaths projectFiles = Utils::transform(m_projects, &Project::projectFilePath); + // Restore information on projects that failed to load: + // don't read projects to the list, which the user loaded + for (const FilePath &failed : std::as_const(m_failedProjects)) { + if (!projectFiles.contains(failed)) + projectFiles << failed; } - const auto end = sb_d->m_values.constEnd(); - QStringList keys; - for (auto it = sb_d->m_values.constBegin(); it != end; ++it) { - data.insert(QLatin1String("value-") + it.key(), it.value()); - keys << it.key(); - } - data.insert(QLatin1String("valueKeys"), keys); + SessionManager::setSessionValue("ProjectList", + Utils::transform(projectFiles, + &FilePath::toString)); + SessionManager::setSessionValue("CascadeSetActive", m_casadeSetActive); - if (!sb_d->m_writer || sb_d->m_writer->fileName() != filePath) { - delete sb_d->m_writer; - sb_d->m_writer = new PersistentSettingsWriter(filePath, "QtCreatorSession"); + QVariantMap depMap; + auto i = m_depMap.constBegin(); + while (i != m_depMap.constEnd()) { + QString key = i.key().toString(); + QStringList values; + const FilePaths valueList = i.value(); + for (const FilePath &value : valueList) + values << value.toString(); + depMap.insert(key, values); + ++i; } - const bool result = sb_d->m_writer->save(data, ICore::dialogParent()); - if (result) { - if (!SessionManager::isDefaultVirgin()) - sb_d->m_sessionDateTimes.insert(SessionManager::activeSession(), QDateTime::currentDateTime()); - } else { - QMessageBox::warning(ICore::dialogParent(), Tr::tr("Error while saving session"), - Tr::tr("Could not save session to file %1").arg(sb_d->m_writer->fileName().toUserOutput())); - } - - return result; + SessionManager::setSessionValue(QLatin1String("ProjectDependencies"), QVariant(depMap)); } /*! diff --git a/src/plugins/projectexplorer/projectmanager.h b/src/plugins/projectexplorer/projectmanager.h index 7f515869013..f49cc96e54c 100644 --- a/src/plugins/projectexplorer/projectmanager.h +++ b/src/plugins/projectexplorer/projectmanager.h @@ -47,7 +47,6 @@ public: }); } - static bool save(); static void closeAllProjects(); static void addProject(Project *project); diff --git a/src/plugins/projectexplorer/session.cpp b/src/plugins/projectexplorer/session.cpp index 5edd7b4f9d6..ccedbb885fe 100644 --- a/src/plugins/projectexplorer/session.cpp +++ b/src/plugins/projectexplorer/session.cpp @@ -7,7 +7,6 @@ #include "projectexplorer.h" #include "projectexplorertr.h" -#include "projectmanager.h" #include #include @@ -514,7 +513,7 @@ bool SessionManager::loadSession(const QString &session, bool initial) // Allow everyone to set something in the session and before saving emit SessionManager::instance()->aboutToUnloadSession(sb_d->m_sessionName); - if (!ProjectManager::save()) { + if (!saveSession()) { sb_d->m_loadingSession = false; return false; } @@ -571,4 +570,67 @@ bool SessionManager::loadSession(const QString &session, bool initial) return true; } +bool SessionManager::saveSession() +{ + emit SessionManager::instance()->aboutToSaveSession(); + + const FilePath filePath = SessionManager::sessionNameToFileName(sb_d->m_sessionName); + QVariantMap data; + + // See the explanation at loadSession() for how we handle the implicit default session. + if (SessionManager::isDefaultVirgin()) { + if (filePath.exists()) { + PersistentSettingsReader reader; + if (!reader.load(filePath)) { + QMessageBox::warning(ICore::dialogParent(), + Tr::tr("Error while saving session"), + Tr::tr("Could not save session %1") + .arg(filePath.toUserOutput())); + return false; + } + data = reader.restoreValues(); + } + } else { + const QColor c = StyleHelper::requestedBaseColor(); + if (c.isValid()) { + QString tmp = QString::fromLatin1("#%1%2%3") + .arg(c.red(), 2, 16, QLatin1Char('0')) + .arg(c.green(), 2, 16, QLatin1Char('0')) + .arg(c.blue(), 2, 16, QLatin1Char('0')); + setSessionValue("Color", tmp); + } + setSessionValue("EditorSettings", EditorManager::saveState().toBase64()); + + const auto end = sb_d->m_sessionValues.constEnd(); + for (auto it = sb_d->m_sessionValues.constBegin(); it != end; ++it) + data.insert(it.key(), it.value()); + } + + const auto end = sb_d->m_values.constEnd(); + QStringList keys; + for (auto it = sb_d->m_values.constBegin(); it != end; ++it) { + data.insert("value-" + it.key(), it.value()); + keys << it.key(); + } + data.insert("valueKeys", keys); + + if (!sb_d->m_writer || sb_d->m_writer->fileName() != filePath) { + delete sb_d->m_writer; + sb_d->m_writer = new PersistentSettingsWriter(filePath, "QtCreatorSession"); + } + const bool result = sb_d->m_writer->save(data, ICore::dialogParent()); + if (result) { + if (!SessionManager::isDefaultVirgin()) + sb_d->m_sessionDateTimes.insert(SessionManager::activeSession(), + QDateTime::currentDateTime()); + } else { + QMessageBox::warning(ICore::dialogParent(), + Tr::tr("Error while saving session"), + Tr::tr("Could not save session to file %1") + .arg(sb_d->m_writer->fileName().toUserOutput())); + } + + return result; +} + } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/session.h b/src/plugins/projectexplorer/session.h index b40e687d648..8f2da70bd24 100644 --- a/src/plugins/projectexplorer/session.h +++ b/src/plugins/projectexplorer/session.h @@ -64,6 +64,7 @@ public: static void addSessionLoadingSteps(int steps); static bool loadSession(const QString &session, bool initial = false); + static bool saveSession(); signals: void startupSessionRestored(); diff --git a/src/plugins/qmljseditor/qmljseditorplugin.cpp b/src/plugins/qmljseditor/qmljseditorplugin.cpp index 884670c4faf..d695989825d 100644 --- a/src/plugins/qmljseditor/qmljseditorplugin.cpp +++ b/src/plugins/qmljseditor/qmljseditorplugin.cpp @@ -210,11 +210,6 @@ void QmlJSEditorPlugin::extensionsInitialized() QmllsSettingsManager::instance()->setupAutoupdate(); } -ExtensionSystem::IPlugin::ShutdownFlag QmlJSEditorPlugin::aboutToShutdown() -{ - return IPlugin::aboutToShutdown(); -} - Utils::JsonSchemaManager *QmlJSEditorPlugin::jsonManager() { return &m_instance->d->m_jsonManager; diff --git a/src/plugins/qmljseditor/qmljseditorplugin.h b/src/plugins/qmljseditor/qmljseditorplugin.h index cc1b63fe68a..aa653ac6cb0 100644 --- a/src/plugins/qmljseditor/qmljseditorplugin.h +++ b/src/plugins/qmljseditor/qmljseditorplugin.h @@ -29,7 +29,6 @@ public: private: void initialize() final; void extensionsInitialized() final; - ShutdownFlag aboutToShutdown() final; class QmlJSEditorPluginPrivate *d = nullptr; }; diff --git a/src/shared/qbs b/src/shared/qbs index 03e717b06ed..dc4da2ef8aa 160000 --- a/src/shared/qbs +++ b/src/shared/qbs @@ -1 +1 @@ -Subproject commit 03e717b06ed5c0864618e763f08f91d9fc94b733 +Subproject commit dc4da2ef8aaf63ab837da0aa7689a5b18e34ace8 diff --git a/tests/auto/solutions/tasking/tst_tasking.cpp b/tests/auto/solutions/tasking/tst_tasking.cpp index fb8e575322f..7da3177b8a8 100644 --- a/tests/auto/solutions/tasking/tst_tasking.cpp +++ b/tests/auto/solutions/tasking/tst_tasking.cpp @@ -631,6 +631,115 @@ void tst_Tasking::testTree_data() QTest::newRow("SequentialError") << TestData{storage, root, log, 5, OnDone::Failure}; } + { + const auto constructEmptyWorkflow = [=](WorkflowPolicy policy) { + return Group { + Storage(storage), + workflowPolicy(policy), + onGroupDone(groupDone(0)), + onGroupError(groupError(0)) + }; + }; + + const Log log = {{0, Handler::GroupDone}}; + + const Group root1 = constructEmptyWorkflow(WorkflowPolicy::StopOnError); + QTest::newRow("EmptyStopOnError") << TestData{storage, root1, log, 0, OnDone::Success}; + + const Group root2 = constructEmptyWorkflow(WorkflowPolicy::ContinueOnError); + QTest::newRow("EmptyContinueOnError") << TestData{storage, root2, log, 0, OnDone::Success}; + + const Group root3 = constructEmptyWorkflow(WorkflowPolicy::StopOnDone); + QTest::newRow("EmptyStopOnDone") << TestData{storage, root3, log, 0, OnDone::Success}; + + const Group root4 = constructEmptyWorkflow(WorkflowPolicy::ContinueOnDone); + QTest::newRow("EmptyContinueOnDone") << TestData{storage, root4, log, 0, OnDone::Success}; + + const Group root5 = constructEmptyWorkflow(WorkflowPolicy::StopOnFinished); + QTest::newRow("EmptyStopOnFinished") << TestData{storage, root5, log, 0, OnDone::Success}; + + const Group root6 = constructEmptyWorkflow(WorkflowPolicy::Optional); + QTest::newRow("EmptyOptional") << TestData{storage, root6, log, 0, OnDone::Success}; + } + + { + const auto constructDoneWorkflow = [=](WorkflowPolicy policy) { + return Group { + Storage(storage), + workflowPolicy(policy), + Test(setupTask(1), logDone, logError), + onGroupDone(groupDone(0)), + onGroupError(groupError(0)) + }; + }; + + const Log log = { + {1, Handler::Setup}, + {1, Handler::Done}, + {0, Handler::GroupDone} + }; + + const Group root1 = constructDoneWorkflow(WorkflowPolicy::StopOnError); + QTest::newRow("DoneStopOnError") << TestData{storage, root1, log, 1, OnDone::Success}; + + const Group root2 = constructDoneWorkflow(WorkflowPolicy::ContinueOnError); + QTest::newRow("DoneContinueOnError") << TestData{storage, root2, log, 1, OnDone::Success}; + + const Group root3 = constructDoneWorkflow(WorkflowPolicy::StopOnDone); + QTest::newRow("DoneStopOnDone") << TestData{storage, root3, log, 1, OnDone::Success}; + + const Group root4 = constructDoneWorkflow(WorkflowPolicy::ContinueOnDone); + QTest::newRow("DoneContinueOnDone") << TestData{storage, root4, log, 1, OnDone::Success}; + + const Group root5 = constructDoneWorkflow(WorkflowPolicy::StopOnFinished); + QTest::newRow("DoneStopOnFinished") << TestData{storage, root5, log, 1, OnDone::Success}; + + const Group root6 = constructDoneWorkflow(WorkflowPolicy::Optional); + QTest::newRow("DoneOptional") << TestData{storage, root6, log, 1, OnDone::Success}; + } + + { + const auto constructErrorWorkflow = [=](WorkflowPolicy policy) { + return Group { + Storage(storage), + workflowPolicy(policy), + Test(setupFailingTask(1), logDone, logError), + onGroupDone(groupDone(0)), + onGroupError(groupError(0)) + }; + }; + + const Log log = { + {1, Handler::Setup}, + {1, Handler::Error}, + {0, Handler::GroupError} + }; + + const Log optionalLog = { + {1, Handler::Setup}, + {1, Handler::Error}, + {0, Handler::GroupDone} + }; + + const Group root1 = constructErrorWorkflow(WorkflowPolicy::StopOnError); + QTest::newRow("ErrorStopOnError") << TestData{storage, root1, log, 1, OnDone::Failure}; + + const Group root2 = constructErrorWorkflow(WorkflowPolicy::ContinueOnError); + QTest::newRow("ErrorContinueOnError") << TestData{storage, root2, log, 1, OnDone::Failure}; + + const Group root3 = constructErrorWorkflow(WorkflowPolicy::StopOnDone); + QTest::newRow("ErrorStopOnDone") << TestData{storage, root3, log, 1, OnDone::Failure}; + + const Group root4 = constructErrorWorkflow(WorkflowPolicy::ContinueOnDone); + QTest::newRow("ErrorContinueOnDone") << TestData{storage, root4, log, 1, OnDone::Failure}; + + const Group root5 = constructErrorWorkflow(WorkflowPolicy::StopOnFinished); + QTest::newRow("ErrorStopOnFinished") << TestData{storage, root5, log, 1, OnDone::Failure}; + + const Group root6 = constructErrorWorkflow(WorkflowPolicy::Optional); + QTest::newRow("ErrorOptional") << TestData{storage, root6, optionalLog, 1, OnDone::Success}; + } + { const Group root = constructSimpleSequence(WorkflowPolicy::StopOnError); const Log log {