From d64954b02915e9a38d800bcc7d90b92b75de9081 Mon Sep 17 00:00:00 2001 From: Cristian Adam Date: Thu, 25 May 2023 17:17:52 +0200 Subject: [PATCH 001/141] Utils: Fix QTC_STATIC_BUILD build Change-Id: I14ac8c99708aba548d1054b37e5a445f6ac1a2b7 Reviewed-by: Reviewed-by: Eike Ziller --- src/libs/utils/layoutbuilder.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libs/utils/layoutbuilder.h b/src/libs/utils/layoutbuilder.h index d716ad034c5..1f774ba1461 100644 --- a/src/libs/utils/layoutbuilder.h +++ b/src/libs/utils/layoutbuilder.h @@ -11,6 +11,8 @@ #if defined(UTILS_LIBRARY) # define QTCREATOR_UTILS_EXPORT Q_DECL_EXPORT +#elif defined(UTILS_STATIC_LIBRARY) +# define QTCREATOR_UTILS_EXPORT #else # define QTCREATOR_UTILS_EXPORT Q_DECL_IMPORT #endif From 12456ce6884f7dc016aacf00bb14a0db37cf0b6f Mon Sep 17 00:00:00 2001 From: Cristian Adam Date: Thu, 25 May 2023 17:32:29 +0200 Subject: [PATCH 002/141] Terminal: Fix build with QTC_STATIC_BUILD The `log` Q_LOGGING_CATEGORY was used in a different place, and would conflict in a static build. Change-Id: Id23722a2aca3ea9afb846d8dd75aed9972c7b16f Reviewed-by: Reviewed-by: Eike Ziller Reviewed-by: Marcus Tillmanns --- src/plugins/terminal/terminalsurface.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/terminal/terminalsurface.cpp b/src/plugins/terminal/terminalsurface.cpp index ee8e571adb3..ea994302318 100644 --- a/src/plugins/terminal/terminalsurface.cpp +++ b/src/plugins/terminal/terminalsurface.cpp @@ -12,10 +12,10 @@ #include -Q_LOGGING_CATEGORY(log, "qtc.terminal.surface", QtWarningMsg); - namespace Terminal::Internal { +Q_LOGGING_CATEGORY(log, "qtc.terminal.surface", QtWarningMsg); + QColor toQColor(const VTermColor &c) { return QColor(qRgb(c.rgb.red, c.rgb.green, c.rgb.blue)); From 38fde456a326d5890cb0288f55205695750ca208 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Tue, 30 May 2023 10:02:41 +0200 Subject: [PATCH 003/141] CppEditor: use markdown for resource image tooltips Fixes: QTCREATORBUG-29217 Change-Id: Iba3d876d988336276996aac733a6ea9b0eb45882 Reviewed-by: Eike Ziller --- src/plugins/cppeditor/resourcepreviewhoverhandler.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/cppeditor/resourcepreviewhoverhandler.cpp b/src/plugins/cppeditor/resourcepreviewhoverhandler.cpp index 0937df32ab6..8654b2c35d1 100644 --- a/src/plugins/cppeditor/resourcepreviewhoverhandler.cpp +++ b/src/plugins/cppeditor/resourcepreviewhoverhandler.cpp @@ -166,7 +166,7 @@ void ResourcePreviewHoverHandler::operateTooltip(TextEditorWidget *editorWidget, { const QString tt = makeTooltip(); if (!tt.isEmpty()) - Utils::ToolTip::show(point, tt, editorWidget); + Utils::ToolTip::show(point, tt, Qt::MarkdownText, editorWidget); else Utils::ToolTip::hide(); } @@ -180,7 +180,7 @@ QString ResourcePreviewHoverHandler::makeTooltip() const const Utils::MimeType mimeType = Utils::mimeTypeForFile(m_resPath); if (mimeType.name().startsWith("image", Qt::CaseInsensitive)) - ret += QString("
").arg(m_resPath); + ret += QString("![image](%1) \n").arg(m_resPath); ret += QString("%2") .arg(m_resPath, QDir::toNativeSeparators(m_resPath)); From 3be931d2348a610b3f40effbed84c6e6d680fc70 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Tue, 30 May 2023 12:00:59 +0200 Subject: [PATCH 004/141] Fix some unused 'this' lambda captures Change-Id: I63cb4e68d8675c7a83d90c8ccc11e646b6a5c659 Reviewed-by: Marcus Tillmanns --- src/plugins/conan/conaninstallstep.cpp | 2 +- src/plugins/terminal/terminalsettings.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/conan/conaninstallstep.cpp b/src/plugins/conan/conaninstallstep.cpp index cae573845e8..2a634190365 100644 --- a/src/plugins/conan/conaninstallstep.cpp +++ b/src/plugins/conan/conaninstallstep.cpp @@ -112,7 +112,7 @@ ConanInstallStep::ConanInstallStep(BuildStepList *bsl, Id id) return param.summary(displayName()); }); - connect(ProjectManager::instance(), &ProjectManager::projectAdded, this, [this](Project * project) { + connect(ProjectManager::instance(), &ProjectManager::projectAdded, this, [](Project * project) { connect(project, &Project::addedTarget, project, [project] (Target *target) { connectTarget(project, target); }); diff --git a/src/plugins/terminal/terminalsettings.cpp b/src/plugins/terminal/terminalsettings.cpp index 577367b6641..692af4ec9c5 100644 --- a/src/plugins/terminal/terminalsettings.cpp +++ b/src/plugins/terminal/terminalsettings.cpp @@ -483,7 +483,7 @@ TerminalSettings::TerminalSettings() auto loadThemeButton = new QPushButton(Tr::tr("Load Theme...")); auto resetTheme = new QPushButton(Tr::tr("Reset Theme")); - connect(loadThemeButton, &QPushButton::clicked, this, [this] { + connect(loadThemeButton, &QPushButton::clicked, this, [] { const FilePath path = FileUtils::getOpenFilePath( Core::ICore::dialogParent(), "Open Theme", From 78eb97fb54d1fc39b160f0768f6b37e94db2ca7c Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 30 May 2023 09:43:26 +0200 Subject: [PATCH 005/141] Git: Fix default port for gerritoptionspage.cpp We need to set the range before the value, otherwise we end up using the default maximum of 99 when setting it. Change-Id: I93de2cade3c2884dab64f04a52b2d3e3db98e1c4 Reviewed-by: Orgad Shaneh Reviewed-by: hjk --- src/plugins/git/gerrit/gerritoptionspage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/git/gerrit/gerritoptionspage.cpp b/src/plugins/git/gerrit/gerritoptionspage.cpp index 3f225d82eb1..3d77c26aa46 100644 --- a/src/plugins/git/gerrit/gerritoptionspage.cpp +++ b/src/plugins/git/gerrit/gerritoptionspage.cpp @@ -43,8 +43,8 @@ public: curlChooser->setCommandVersionArguments({"-V"}); auto portSpinBox = new QSpinBox(this); - portSpinBox->setValue(p->server.port); portSpinBox->setRange(1, 65535); + portSpinBox->setValue(p->server.port); auto httpsCheckBox = new QCheckBox(Git::Tr::tr("HTTPS")); httpsCheckBox->setChecked(p->https); From c2fcd17e91d6133cb32bc427364de2d60dc83157 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 26 May 2023 11:19:53 +0200 Subject: [PATCH 006/141] Meson: Simplify settings setup a bit Also some surrounding code. Change-Id: I9f537a4357ab76295b7cb4f6a69749a0a6b55392 Reviewed-by: Reviewed-by: Christian Stenger --- .../mesonprojectmanager/mesonbuildsystem.cpp | 2 +- .../mesonpluginconstants.h | 1 - .../mesonprojectplugin.cpp | 4 +- .../mesonprojectmanager/ninjabuildstep.cpp | 18 +++--- src/plugins/mesonprojectmanager/settings.cpp | 55 ++++++++----------- src/plugins/mesonprojectmanager/settings.h | 20 ++----- 6 files changed, 40 insertions(+), 60 deletions(-) diff --git a/src/plugins/mesonprojectmanager/mesonbuildsystem.cpp b/src/plugins/mesonprojectmanager/mesonbuildsystem.cpp index 13617fa0140..6d3e5f20c4f 100644 --- a/src/plugins/mesonprojectmanager/mesonbuildsystem.cpp +++ b/src/plugins/mesonprojectmanager/mesonbuildsystem.cpp @@ -192,7 +192,7 @@ void MesonBuildSystem::init() bool MesonBuildSystem::parseProject() { QTC_ASSERT(buildConfiguration(), return false); - if (!isSetup(buildConfiguration()->buildDirectory()) && Settings::instance()->autorunMeson.value()) + if (!isSetup(buildConfiguration()->buildDirectory()) && settings().autorunMeson()) return configure(); LEAVE_IF_BUSY(); LOCK(); diff --git a/src/plugins/mesonprojectmanager/mesonpluginconstants.h b/src/plugins/mesonprojectmanager/mesonpluginconstants.h index 995e41cbb59..108c125f502 100644 --- a/src/plugins/mesonprojectmanager/mesonpluginconstants.h +++ b/src/plugins/mesonprojectmanager/mesonpluginconstants.h @@ -18,7 +18,6 @@ const char PARAMETERS_KEY[] = "MesonProjectManager.BuildConfig.Parameters"; // Settings page namespace SettingsPage { -const char GENERAL_ID[] = "A.MesonProjectManager.SettingsPage.General"; const char TOOLS_ID[] = "Z.MesonProjectManager.SettingsPage.Tools"; const char CATEGORY[] = "Z.Meson"; } // namespace SettingsPage diff --git a/src/plugins/mesonprojectmanager/mesonprojectplugin.cpp b/src/plugins/mesonprojectmanager/mesonprojectplugin.cpp index f15f65c4afd..87beb589bbd 100644 --- a/src/plugins/mesonprojectmanager/mesonprojectplugin.cpp +++ b/src/plugins/mesonprojectmanager/mesonprojectplugin.cpp @@ -45,7 +45,7 @@ public: ~MesonProjectPluginPrivate() {} private: - GeneralSettingsPage m_generalSettingsPage; + Settings m_settings; ToolsSettingsPage m_toolslSettingsPage; ToolsSettingsAccessor m_toolsSettings; MesonToolKitAspect m_mesonKitAspect; @@ -60,7 +60,6 @@ private: void saveAll() { m_toolsSettings.saveMesonTools(MesonTools::tools(), ICore::dialogParent()); - Settings::instance()->writeSettings(ICore::settings()); } }; @@ -76,7 +75,6 @@ void MesonProjectPlugin::initialize() ProjectManager::registerProjectType(Constants::Project::MIMETYPE); FileIconProvider::registerIconOverlayForFilename(Constants::Icons::MESON, "meson.build"); FileIconProvider::registerIconOverlayForFilename(Constants::Icons::MESON, "meson_options.txt"); - Settings::instance()->readSettings(ICore::settings()); } } // MesonProjectManager::Internal diff --git a/src/plugins/mesonprojectmanager/ninjabuildstep.cpp b/src/plugins/mesonprojectmanager/ninjabuildstep.cpp index 325056d4918..ac41aeecfaa 100644 --- a/src/plugins/mesonprojectmanager/ninjabuildstep.cpp +++ b/src/plugins/mesonprojectmanager/ninjabuildstep.cpp @@ -44,7 +44,7 @@ NinjaBuildStep::NinjaBuildStep(BuildStepList *bsl, Id id) setUseEnglishOutput(); connect(target(), &ProjectExplorer::Target::parsingFinished, this, &NinjaBuildStep::update); - connect(&Settings::instance()->verboseNinja, &BaseAspect::changed, + connect(&settings().verboseNinja, &BaseAspect::changed, this, &NinjaBuildStep::commandChanged); } @@ -119,17 +119,15 @@ QWidget *NinjaBuildStep::createConfigWidget() // --verbose is only supported since // https://github.com/ninja-build/ninja/commit/bf7517505ad1def03e13bec2b4131399331bc5c4 // TODO check when to switch back to --verbose -Utils::CommandLine NinjaBuildStep::command() +CommandLine NinjaBuildStep::command() { - Utils::CommandLine cmd = [this] { - auto tool = NinjaToolKitAspect::ninjaTool(kit()); - if (tool) - return Utils::CommandLine{tool->exe()}; - return Utils::CommandLine{}; - }(); + CommandLine cmd; + if (auto tool = NinjaToolKitAspect::ninjaTool(kit())) + cmd.setExecutable(tool->exe()); + if (!m_commandArgs.isEmpty()) - cmd.addArgs(m_commandArgs, Utils::CommandLine::RawType::Raw); - if (Settings::instance()->verboseNinja.value()) + cmd.addArgs(m_commandArgs, CommandLine::RawType::Raw); + if (settings().verboseNinja()) cmd.addArg("-v"); cmd.addArg(m_targetName); return cmd; diff --git a/src/plugins/mesonprojectmanager/settings.cpp b/src/plugins/mesonprojectmanager/settings.cpp index 6a211a375a7..e1fe290bc5c 100644 --- a/src/plugins/mesonprojectmanager/settings.cpp +++ b/src/plugins/mesonprojectmanager/settings.cpp @@ -8,13 +8,26 @@ #include -namespace MesonProjectManager { -namespace Internal { +namespace MesonProjectManager::Internal { + +static Settings *s_instance; + +Settings &settings() +{ + return *s_instance; +} Settings::Settings() { + s_instance = this; + setSettingsGroup("MesonProjectManager"); - setAutoApply(false); + + setId("A.MesonProjectManager.SettingsPage.General"); + setDisplayName(Tr::tr("General")); + setDisplayCategory("Meson"); + setCategory(Constants::SettingsPage::CATEGORY); + setCategoryIconPath(Constants::Icons::MESON_BW); autorunMeson.setSettingsKey("meson.autorun"); autorunMeson.setLabelText(Tr::tr("Autorun Meson")); @@ -24,36 +37,16 @@ Settings::Settings() verboseNinja.setLabelText(Tr::tr("Ninja verbose mode")); verboseNinja.setToolTip(Tr::tr("Enables verbose mode by default when invoking Ninja.")); - registerAspect(&autorunMeson); - registerAspect(&verboseNinja); -} - -Settings *Settings::instance() -{ - static Settings m_settings; - return &m_settings; -} - -GeneralSettingsPage::GeneralSettingsPage() -{ - setId(Constants::SettingsPage::GENERAL_ID); - setDisplayName(Tr::tr("General")); - setDisplayCategory("Meson"); - setCategory(Constants::SettingsPage::CATEGORY); - setCategoryIconPath(Constants::Icons::MESON_BW); - setSettings(Settings::instance()); - - setLayouter([](QWidget *widget) { - Settings &s = *Settings::instance(); + setLayouter([this] { using namespace Layouting; - - Column { - s.autorunMeson, - s.verboseNinja, + return Column { + autorunMeson, + verboseNinja, st, - }.attachTo(widget); + }; }); + + readSettings(); } -} // namespace Internal -} // namespace MesonProjectManager +} // MesonProjectManager::Internal diff --git a/src/plugins/mesonprojectmanager/settings.h b/src/plugins/mesonprojectmanager/settings.h index 2e23d0f4482..34c2e9e97d9 100644 --- a/src/plugins/mesonprojectmanager/settings.h +++ b/src/plugins/mesonprojectmanager/settings.h @@ -7,25 +7,17 @@ #include -namespace MesonProjectManager { -namespace Internal { +namespace MesonProjectManager::Internal { -class Settings : public Utils::AspectContainer +class Settings : public Core::PagedSettings { public: Settings(); - static Settings *instance(); - - Utils::BoolAspect autorunMeson; - Utils::BoolAspect verboseNinja; + Utils::BoolAspect autorunMeson{this}; + Utils::BoolAspect verboseNinja{this}; }; -class GeneralSettingsPage final : public Core::IOptionsPage -{ -public: - GeneralSettingsPage(); -}; +Settings &settings(); -} // namespace Internal -} // namespace MesonProjectManager +} // MesonProjectManager::Internal From ba004e409f3f2dec9725317357fb0dddc987132c Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Thu, 25 May 2023 15:40:40 +0200 Subject: [PATCH 007/141] QMake: Fix build device root Fixes: QTCREATORBUG-29140 Change-Id: I85a7ea54c9006079c1c270ded0a5bd9848db1408 Reviewed-by: Reviewed-by: hjk --- src/plugins/qmakeprojectmanager/qmakeproject.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.cpp b/src/plugins/qmakeprojectmanager/qmakeproject.cpp index 1a180bf833b..d7aefb50b8b 100644 --- a/src/plugins/qmakeprojectmanager/qmakeproject.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeproject.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -1452,8 +1453,12 @@ void QmakeBuildSystem::testToolChain(ToolChain *tc, const FilePath &path) const QString QmakeBuildSystem::deviceRoot() const { - if (projectFilePath().needsDevice()) - return projectFilePath().withNewPath("/").toFSPathString(); + IDeviceConstPtr device = BuildDeviceKitAspect::device(target()->kit()); + QTC_ASSERT(device, return {}); + FilePath deviceRoot = device->rootPath(); + if (deviceRoot.needsDevice()) + return deviceRoot.toFSPathString(); + return {}; } From 98b49735440f4d36fc68b7b8503173929a4fe36d Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 26 May 2023 12:53:21 +0200 Subject: [PATCH 008/141] Beautifier: Use FilePath, not FilePathAspect for documentation file That's not meant to be saved. Change-Id: I04ab2ff1fb3abf7f01eeaa61f5bcf9792e4c637a Reviewed-by: Christian Stenger --- src/plugins/beautifier/abstractsettings.cpp | 2 +- src/plugins/beautifier/abstractsettings.h | 3 ++- .../beautifier/artisticstyle/artisticstylesettings.cpp | 6 +++--- src/plugins/beautifier/clangformat/clangformatsettings.cpp | 6 +++--- src/plugins/beautifier/uncrustify/uncrustifysettings.cpp | 6 +++--- 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/plugins/beautifier/abstractsettings.cpp b/src/plugins/beautifier/abstractsettings.cpp index 9b340cf9b37..1b4ff3aa10e 100644 --- a/src/plugins/beautifier/abstractsettings.cpp +++ b/src/plugins/beautifier/abstractsettings.cpp @@ -297,7 +297,7 @@ void AbstractSettings::read() void AbstractSettings::readDocumentation() { - const FilePath filename = documentationFilePath(); + const FilePath filename = documentationFilePath; if (filename.isEmpty()) { BeautifierPlugin::showError(Tr::tr("No documentation file specified.")); return; diff --git a/src/plugins/beautifier/abstractsettings.h b/src/plugins/beautifier/abstractsettings.h index 6b34baf58be..8e9ceea931d 100644 --- a/src/plugins/beautifier/abstractsettings.h +++ b/src/plugins/beautifier/abstractsettings.h @@ -51,7 +51,8 @@ public: Utils::FilePathAspect command{this}; Utils::StringAspect supportedMimeTypes{this}; - Utils::FilePathAspect documentationFilePath; // Intentionally not saved. + + Utils::FilePath documentationFilePath; QVersionNumber version() const; diff --git a/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp b/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp index 36bd39c3c55..415d4ab20d6 100644 --- a/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp +++ b/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp @@ -59,11 +59,11 @@ ArtisticStyleSettings::ArtisticStyleSettings() customStyle.setSettingsKey("customStyle"); - documentationFilePath.setFilePath( + documentationFilePath = Core::ICore::userResourcePath(Beautifier::Constants::SETTINGS_DIRNAME) .pathAppended(Beautifier::Constants::DOCUMENTATION_DIRNAME) .pathAppended(SETTINGS_NAME) - .stringAppended(".xml")); + .stringAppended(".xml"); read(); } @@ -77,7 +77,7 @@ void ArtisticStyleSettings::createDocumentationFile() const if (process.result() != ProcessResult::FinishedWithSuccess) return; - QFile file(documentationFilePath().toFSPathString()); + QFile file(documentationFilePath.toFSPathString()); const QFileInfo fi(file); if (!fi.exists()) fi.dir().mkpath(fi.absolutePath()); diff --git a/src/plugins/beautifier/clangformat/clangformatsettings.cpp b/src/plugins/beautifier/clangformat/clangformatsettings.cpp index 40477b6ca82..6a31667edb7 100644 --- a/src/plugins/beautifier/clangformat/clangformatsettings.cpp +++ b/src/plugins/beautifier/clangformat/clangformatsettings.cpp @@ -63,16 +63,16 @@ ClangFormatSettings::ClangFormatSettings() customStyle.setSettingsKey("customStyle"); - documentationFilePath.setFilePath(Core::ICore::userResourcePath(Constants::SETTINGS_DIRNAME) + documentationFilePath = Core::ICore::userResourcePath(Constants::SETTINGS_DIRNAME) .pathAppended(Constants::DOCUMENTATION_DIRNAME) - .pathAppended(SETTINGS_NAME).stringAppended(".xml")); + .pathAppended(SETTINGS_NAME).stringAppended(".xml"); read(); } void ClangFormatSettings::createDocumentationFile() const { - QFile file(documentationFilePath().toFSPathString()); + QFile file(documentationFilePath.toFSPathString()); const QFileInfo fi(file); if (!fi.exists()) fi.dir().mkpath(fi.absolutePath()); diff --git a/src/plugins/beautifier/uncrustify/uncrustifysettings.cpp b/src/plugins/beautifier/uncrustify/uncrustifysettings.cpp index 823471681fc..1aa9e8502c6 100644 --- a/src/plugins/beautifier/uncrustify/uncrustifysettings.cpp +++ b/src/plugins/beautifier/uncrustify/uncrustifysettings.cpp @@ -66,9 +66,9 @@ UncrustifySettings::UncrustifySettings() specificConfigFile.setExpectedKind(Utils::PathChooser::File); specificConfigFile.setPromptDialogFilter(Tr::tr("Uncrustify file (*.cfg)")); - documentationFilePath.setFilePath(Core::ICore::userResourcePath(Constants::SETTINGS_DIRNAME) + documentationFilePath = Core::ICore::userResourcePath(Constants::SETTINGS_DIRNAME) .pathAppended(Constants::DOCUMENTATION_DIRNAME) - .pathAppended(SETTINGS_NAME).stringAppended(".xml")); + .pathAppended(SETTINGS_NAME).stringAppended(".xml"); read(); } @@ -82,7 +82,7 @@ void UncrustifySettings::createDocumentationFile() const if (process.result() != ProcessResult::FinishedWithSuccess) return; - QFile file(documentationFilePath().toFSPathString()); + QFile file(documentationFilePath.toFSPathString()); const QFileInfo fi(file); if (!fi.exists()) fi.dir().mkpath(fi.absolutePath()); From aa63d5384f271ce25132065c5c30183f39a48ba4 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 26 May 2023 12:13:30 +0200 Subject: [PATCH 009/141] Meson: Merge toolsettingspagewidget file pair into toolssettingspage.cpp An implementation detail. Change-Id: I35bee5e0d27f7c6e6b8c69d1703ad21d86cc1694 Reviewed-by: Reviewed-by: Christian Stenger --- .../mesonprojectmanager/CMakeLists.txt | 2 - .../mesonprojectmanager.qbs | 2 - .../mesonprojectmanager/toolssettingspage.cpp | 117 +++++++++++++++++- .../mesonprojectmanager/toolssettingspage.h | 6 +- .../toolssettingswidget.cpp | 107 ---------------- .../mesonprojectmanager/toolssettingswidget.h | 40 ------ 6 files changed, 115 insertions(+), 159 deletions(-) delete mode 100644 src/plugins/mesonprojectmanager/toolssettingswidget.cpp delete mode 100644 src/plugins/mesonprojectmanager/toolssettingswidget.h diff --git a/src/plugins/mesonprojectmanager/CMakeLists.txt b/src/plugins/mesonprojectmanager/CMakeLists.txt index d4d7420d7b0..3c541a1219e 100644 --- a/src/plugins/mesonprojectmanager/CMakeLists.txt +++ b/src/plugins/mesonprojectmanager/CMakeLists.txt @@ -75,8 +75,6 @@ add_qtc_plugin(MesonProjectManager toolssettingsaccessor.h toolssettingspage.cpp toolssettingspage.h - toolssettingswidget.cpp - toolssettingswidget.h tooltreeitem.cpp tooltreeitem.h toolwrapper.cpp diff --git a/src/plugins/mesonprojectmanager/mesonprojectmanager.qbs b/src/plugins/mesonprojectmanager/mesonprojectmanager.qbs index 9de8b4ccde9..c721ab2d207 100644 --- a/src/plugins/mesonprojectmanager/mesonprojectmanager.qbs +++ b/src/plugins/mesonprojectmanager/mesonprojectmanager.qbs @@ -95,8 +95,6 @@ Project { "toolssettingsaccessor.h", "toolssettingspage.cpp", "toolssettingspage.h", - "toolssettingswidget.cpp", - "toolssettingswidget.h", "tooltreeitem.cpp", "tooltreeitem.h", "versionhelper.h", diff --git a/src/plugins/mesonprojectmanager/toolssettingspage.cpp b/src/plugins/mesonprojectmanager/toolssettingspage.cpp index 4ac576b365e..67ecd99aacc 100644 --- a/src/plugins/mesonprojectmanager/toolssettingspage.cpp +++ b/src/plugins/mesonprojectmanager/toolssettingspage.cpp @@ -5,10 +5,120 @@ #include "mesonpluginconstants.h" #include "mesonprojectmanagertr.h" -#include "toolssettingswidget.h" +#include "toolitemsettings.h" +#include "toolsmodel.h" +#include "tooltreeitem.h" + +#include +#include + +#include +#include +#include + +using namespace Utils; + +namespace MesonProjectManager::Internal { + +class ToolsSettingsWidget final : public Core::IOptionsPageWidget +{ +public: + ToolsSettingsWidget(); + +private: + void apply() final { m_model.apply(); } + + void cloneMesonTool(); + void removeMesonTool(); + void currentMesonToolChanged(const QModelIndex &newCurrent); + + ToolsModel m_model; + ToolItemSettings *m_itemSettings; + ToolTreeItem *m_currentItem = nullptr; + + QTreeView *m_mesonList; + DetailsWidget *m_mesonDetails; + QPushButton *m_cloneButton; + QPushButton *m_removeButton; +}; + +ToolsSettingsWidget::ToolsSettingsWidget() +{ + m_mesonList = new QTreeView; + m_mesonList->setModel(&m_model); + m_mesonList->expandAll(); + m_mesonList->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents); + m_mesonList->header()->setSectionResizeMode(1, QHeaderView::Stretch); + + m_itemSettings = new ToolItemSettings; + + m_mesonDetails = new DetailsWidget; + m_mesonDetails->setState(DetailsWidget::NoSummary); + m_mesonDetails->setVisible(false); + m_mesonDetails->setWidget(m_itemSettings); + + auto addButton = new QPushButton(Tr::tr("Add")); + + m_cloneButton = new QPushButton(Tr::tr("Clone")); + m_cloneButton->setEnabled(false); + + m_removeButton = new QPushButton(Tr::tr("Remove")); + m_removeButton->setEnabled(false); + + auto makeDefaultButton = new QPushButton(Tr::tr("Make Default")); + makeDefaultButton->setEnabled(false); + makeDefaultButton->setVisible(false); + makeDefaultButton->setToolTip(Tr::tr("Set as the default Meson executable to use " + "when creating a new kit or when no value is set.")); + + using namespace Layouting; + + Row { + Column { + m_mesonList, + m_mesonDetails + }, + Column { + addButton, + m_cloneButton, + m_removeButton, + makeDefaultButton, + st + } + }.attachTo(this); + + connect(m_mesonList->selectionModel(), &QItemSelectionModel::currentChanged, + this, &ToolsSettingsWidget::currentMesonToolChanged); + connect(m_itemSettings, &ToolItemSettings::applyChanges, &m_model, &ToolsModel::updateItem); + + connect(addButton, &QPushButton::clicked, &m_model, &ToolsModel::addMesonTool); + connect(m_cloneButton, &QPushButton::clicked, this, &ToolsSettingsWidget::cloneMesonTool); + connect(m_removeButton, &QPushButton::clicked, this, &ToolsSettingsWidget::removeMesonTool); +} + +void ToolsSettingsWidget::cloneMesonTool() +{ + if (m_currentItem) { + auto newItem = m_model.cloneMesonTool(m_currentItem); + m_mesonList->setCurrentIndex(newItem->index()); + } +} + +void ToolsSettingsWidget::removeMesonTool() +{ + if (m_currentItem) + m_model.removeMesonTool(m_currentItem); +} + +void ToolsSettingsWidget::currentMesonToolChanged(const QModelIndex &newCurrent) +{ + m_currentItem = m_model.mesoneToolTreeItem(newCurrent); + m_itemSettings->load(m_currentItem); + m_mesonDetails->setVisible(m_currentItem); + m_cloneButton->setEnabled(m_currentItem); + m_removeButton->setEnabled(m_currentItem && !m_currentItem->isAutoDetected()); +} -namespace MesonProjectManager { -namespace Internal { ToolsSettingsPage::ToolsSettingsPage() { @@ -18,5 +128,4 @@ ToolsSettingsPage::ToolsSettingsPage() setWidgetCreator([]() { return new ToolsSettingsWidget; }); } -} // namespace Internal } // namespace MesonProjectManager diff --git a/src/plugins/mesonprojectmanager/toolssettingspage.h b/src/plugins/mesonprojectmanager/toolssettingspage.h index de62b94d918..815120c30f0 100644 --- a/src/plugins/mesonprojectmanager/toolssettingspage.h +++ b/src/plugins/mesonprojectmanager/toolssettingspage.h @@ -5,8 +5,7 @@ #include -namespace MesonProjectManager { -namespace Internal { +namespace MesonProjectManager::Internal { class ToolsSettingsPage final : public Core::IOptionsPage { @@ -14,5 +13,4 @@ public: ToolsSettingsPage(); }; -} // namespace Internal -} // namespace MesonProjectManager +} // MesonProjectManager::Internal diff --git a/src/plugins/mesonprojectmanager/toolssettingswidget.cpp b/src/plugins/mesonprojectmanager/toolssettingswidget.cpp deleted file mode 100644 index ef30d79ae43..00000000000 --- a/src/plugins/mesonprojectmanager/toolssettingswidget.cpp +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (C) 2020 Alexis Jeandet. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "toolssettingswidget.h" - -#include "mesonprojectmanagertr.h" -#include "toolsmodel.h" -#include "tooltreeitem.h" - -#include -#include - -#include -#include -#include - -using namespace Utils; - -namespace MesonProjectManager::Internal { - -ToolsSettingsWidget::ToolsSettingsWidget() - : Core::IOptionsPageWidget() -{ - m_mesonList = new QTreeView; - m_mesonList->setModel(&m_model); - m_mesonList->expandAll(); - m_mesonList->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents); - m_mesonList->header()->setSectionResizeMode(1, QHeaderView::Stretch); - - m_itemSettings = new ToolItemSettings; - - m_mesonDetails = new DetailsWidget; - m_mesonDetails->setState(DetailsWidget::NoSummary); - m_mesonDetails->setVisible(false); - m_mesonDetails->setWidget(m_itemSettings); - - auto addButton = new QPushButton(Tr::tr("Add")); - - m_cloneButton = new QPushButton(Tr::tr("Clone")); - m_cloneButton->setEnabled(false); - - m_removeButton = new QPushButton(Tr::tr("Remove")); - m_removeButton->setEnabled(false); - - auto makeDefaultButton = new QPushButton(Tr::tr("Make Default")); - makeDefaultButton->setEnabled(false); - makeDefaultButton->setVisible(false); - makeDefaultButton->setToolTip(Tr::tr("Set as the default Meson executable to use " - "when creating a new kit or when no value is set.")); - - using namespace Layouting; - - Row { - Column { - m_mesonList, - m_mesonDetails - }, - Column { - addButton, - m_cloneButton, - m_removeButton, - makeDefaultButton, - st - } - }.attachTo(this); - - connect(m_mesonList->selectionModel(), &QItemSelectionModel::currentChanged, - this, &ToolsSettingsWidget::currentMesonToolChanged); - connect(m_itemSettings, &ToolItemSettings::applyChanges, &m_model, &ToolsModel::updateItem); - - connect(addButton, &QPushButton::clicked, &m_model, &ToolsModel::addMesonTool); - connect(m_cloneButton, &QPushButton::clicked, this, &ToolsSettingsWidget::cloneMesonTool); - connect(m_removeButton, &QPushButton::clicked, this, &ToolsSettingsWidget::removeMesonTool); -} - -ToolsSettingsWidget::~ToolsSettingsWidget() = default; - -void ToolsSettingsWidget::cloneMesonTool() -{ - if (m_currentItem) { - auto newItem = m_model.cloneMesonTool(m_currentItem); - m_mesonList->setCurrentIndex(newItem->index()); - } -} - -void ToolsSettingsWidget::removeMesonTool() -{ - if (m_currentItem) { - m_model.removeMesonTool(m_currentItem); - } -} - -void ToolsSettingsWidget::currentMesonToolChanged(const QModelIndex &newCurrent) -{ - m_currentItem = m_model.mesoneToolTreeItem(newCurrent); - m_itemSettings->load(m_currentItem); - m_mesonDetails->setVisible(m_currentItem); - m_cloneButton->setEnabled(m_currentItem); - m_removeButton->setEnabled(m_currentItem && !m_currentItem->isAutoDetected()); -} - -void ToolsSettingsWidget::apply() -{ - m_model.apply(); -} - -} // MesonProjectManager::Internal diff --git a/src/plugins/mesonprojectmanager/toolssettingswidget.h b/src/plugins/mesonprojectmanager/toolssettingswidget.h deleted file mode 100644 index 1c39b7460ab..00000000000 --- a/src/plugins/mesonprojectmanager/toolssettingswidget.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (C) 2020 Alexis Jeandet. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#pragma once - -#include "toolitemsettings.h" -#include "toolsmodel.h" - -#include - -namespace Utils { class DetailsWidget; } - -namespace MesonProjectManager::Internal { - -class ToolTreeItem; - -class ToolsSettingsWidget final : public Core::IOptionsPageWidget -{ -public: - explicit ToolsSettingsWidget(); - ~ToolsSettingsWidget(); - -private: - void apply() final; - - void cloneMesonTool(); - void removeMesonTool(); - void currentMesonToolChanged(const QModelIndex &newCurrent); - - ToolsModel m_model; - ToolItemSettings *m_itemSettings; - ToolTreeItem *m_currentItem = nullptr; - - QTreeView *m_mesonList; - Utils::DetailsWidget *m_mesonDetails; - QPushButton *m_cloneButton; - QPushButton *m_removeButton; -}; - -} // MesonProjectManager::Internal From 047814c6daea2d5b8afa833e5bdb7e4a32279bf6 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Tue, 30 May 2023 14:08:45 +0200 Subject: [PATCH 010/141] Utils: fix likelyContainsLink for markdown This allows us to also port the link in the resource tooltip to markdown. Change-Id: Iec0e19ff68db76290139e457694485222f0a38f3 Reviewed-by: Eike Ziller --- src/libs/utils/tooltip/tips.cpp | 12 ++++++++---- .../cppeditor/resourcepreviewhoverhandler.cpp | 4 +--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/libs/utils/tooltip/tips.cpp b/src/libs/utils/tooltip/tips.cpp index ea20c735d80..180b8f960f2 100644 --- a/src/libs/utils/tooltip/tips.cpp +++ b/src/libs/utils/tooltip/tips.cpp @@ -133,9 +133,13 @@ TextTip::TextTip(QWidget *parent) : TipLabel(parent) setWindowOpacity(style()->styleHint(QStyle::SH_ToolTipLabel_Opacity, nullptr, this) / 255.0); } -static bool likelyContainsLink(const QString &s) +static bool likelyContainsLink(const QString &s, const Qt::TextFormat &format) { - return s.contains(QLatin1String("href"), Qt::CaseInsensitive); + if (s.contains(QLatin1String("href"), Qt::CaseInsensitive)) + return true; + if (format == Qt::MarkdownText) + return s.contains("]("); + return false; } void TextTip::setContent(const QVariant &content) @@ -148,13 +152,13 @@ void TextTip::setContent(const QVariant &content) m_format = item.second; } - bool containsLink = likelyContainsLink(m_text); + bool containsLink = likelyContainsLink(m_text, m_format); setOpenExternalLinks(containsLink); } bool TextTip::isInteractive() const { - return likelyContainsLink(m_text); + return likelyContainsLink(m_text, m_format); } void TextTip::configure(const QPoint &pos) diff --git a/src/plugins/cppeditor/resourcepreviewhoverhandler.cpp b/src/plugins/cppeditor/resourcepreviewhoverhandler.cpp index 8654b2c35d1..6c282b879cc 100644 --- a/src/plugins/cppeditor/resourcepreviewhoverhandler.cpp +++ b/src/plugins/cppeditor/resourcepreviewhoverhandler.cpp @@ -181,9 +181,7 @@ QString ResourcePreviewHoverHandler::makeTooltip() const const Utils::MimeType mimeType = Utils::mimeTypeForFile(m_resPath); if (mimeType.name().startsWith("image", Qt::CaseInsensitive)) ret += QString("![image](%1) \n").arg(m_resPath); - - ret += QString("%2") - .arg(m_resPath, QDir::toNativeSeparators(m_resPath)); + ret += QString("[%1](%2)").arg(QDir::toNativeSeparators(m_resPath), m_resPath); return ret; } From 6a016ff014709257e477e7635362bd7357e8541c Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Fri, 26 May 2023 17:00:35 +0200 Subject: [PATCH 011/141] Issues pane: Fix filtering If the parent is visible, we always want to show the child as well. The previous implementation would always assume the row number to be a top-level entry, leading to seemingly random behavior if any sort of filtering was active. Amends 778d7a981995898a3afd782bfc199d032d4a80f0. Change-Id: I354c1b07929c45034a7d24b4c31f986ddd01c877 Reviewed-by: Reviewed-by: Christian Stenger --- src/plugins/projectexplorer/taskmodel.cpp | 3 ++- src/plugins/projectexplorer/taskwindow.cpp | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/projectexplorer/taskmodel.cpp b/src/plugins/projectexplorer/taskmodel.cpp index c05614a445f..80280a5595e 100644 --- a/src/plugins/projectexplorer/taskmodel.cpp +++ b/src/plugins/projectexplorer/taskmodel.cpp @@ -409,7 +409,8 @@ void TaskFilterModel::updateFilterProperties( bool TaskFilterModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { - Q_UNUSED(source_parent) + if (source_parent.isValid()) + return true; return filterAcceptsTask(taskModel()->tasks().at(source_row)); } diff --git a/src/plugins/projectexplorer/taskwindow.cpp b/src/plugins/projectexplorer/taskwindow.cpp index eb4b9de8ca5..8bb8fa98e2f 100644 --- a/src/plugins/projectexplorer/taskwindow.cpp +++ b/src/plugins/projectexplorer/taskwindow.cpp @@ -169,6 +169,7 @@ TaskWindow::TaskWindow() : d(std::make_unique()) { d->m_model = new Internal::TaskModel(this); d->m_filter = new Internal::TaskFilterModel(d->m_model); + d->m_filter->setAutoAcceptChildRows(true); auto agg = new Aggregation::Aggregate; agg->add(&d->m_treeView); From e0a81731e66f2daf47156da5bf695e973c7aa862 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Fri, 26 May 2023 10:18:39 +0200 Subject: [PATCH 012/141] TaskView: Fix scroll mode Change-Id: I9bcb3315d545d4d32e67a6766c43324d9807ef1d Reviewed-by: Reviewed-by: Christian Stenger Reviewed-by: Qt CI Bot --- src/plugins/projectexplorer/taskwindow.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/plugins/projectexplorer/taskwindow.cpp b/src/plugins/projectexplorer/taskwindow.cpp index 8bb8fa98e2f..95e15ec5eb7 100644 --- a/src/plugins/projectexplorer/taskwindow.cpp +++ b/src/plugins/projectexplorer/taskwindow.cpp @@ -92,7 +92,7 @@ namespace Internal { class TaskView : public TreeView { public: - TaskView() { setMouseTracking(true); } + TaskView(); void resizeColumns(); private: @@ -660,6 +660,12 @@ bool TaskDelegate::needsSpecialHandling(const QModelIndex &index) const return sourceIndex.internalId(); } +TaskView::TaskView() +{ + setMouseTracking(true); + setVerticalScrollMode(ScrollPerPixel); +} + void TaskView::resizeColumns() { setColumnWidth(0, width() * 0.85); From efdb67bf900d19cbd26ae31d6f24782d5d15333e Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Tue, 16 May 2023 16:07:58 +0200 Subject: [PATCH 013/141] ActionManager: Add special context that disables more specific contexts This usually is not a good idea, but might be useful for the embedded terminal widgets. Change-Id: Ifeeb47a38596ee789a503f3c7030da5a464569c5 Reviewed-by: Eike Ziller --- src/plugins/coreplugin/actionmanager/command.cpp | 6 ++++-- src/plugins/coreplugin/coreconstants.h | 5 +++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/plugins/coreplugin/actionmanager/command.cpp b/src/plugins/coreplugin/actionmanager/command.cpp index ab78bf50892..23b398791f2 100644 --- a/src/plugins/coreplugin/actionmanager/command.cpp +++ b/src/plugins/coreplugin/actionmanager/command.cpp @@ -347,8 +347,10 @@ void Internal::CommandPrivate::setCurrentContext(const Context &context) m_context = context; QAction *currentAction = nullptr; - for (int i = 0; i < m_context.size(); ++i) { - if (QAction *a = m_contextActionMap.value(m_context.at(i), nullptr)) { + for (const Id &id : std::as_const(m_context)) { + if (id == Constants::C_GLOBAL_CUTOFF) + break; + if (QAction *a = m_contextActionMap.value(id, nullptr)) { currentAction = a; break; } diff --git a/src/plugins/coreplugin/coreconstants.h b/src/plugins/coreplugin/coreconstants.h index 0b4831e51b6..513d02eb6ee 100644 --- a/src/plugins/coreplugin/coreconstants.h +++ b/src/plugins/coreplugin/coreconstants.h @@ -46,6 +46,11 @@ const char C_EDITORMANAGER[] = "Core.EditorManager"; const char C_NAVIGATION_PANE[] = "Core.NavigationPane"; const char C_PROBLEM_PANE[] = "Core.ProblemPane"; const char C_GENERAL_OUTPUT_PANE[] = "Core.GeneralOutputPane"; +// Special context that leads to all "more specific" contexts to be ignored. +// If you use Context(mycontextId, C_GLOBAL_CUTOFF) for a widget that has focus, +// mycontextId will be enabled but the contexts for all parent widgets, the manually added +// "additional" contexts, and the global context will be turned off. +const char C_GLOBAL_CUTOFF[] = "Global Cutoff"; // Default editor kind const char K_DEFAULT_TEXT_EDITOR_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("QtC::Core", "Plain Text Editor"); From ea108f48572806a6a8fb09cf9a7877a316c59253 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Thu, 25 May 2023 15:18:12 +0200 Subject: [PATCH 014/141] Editor: Adjust remaining usages of BaseTextEditor:convertPosition amends 9bb126c0d6ff46bd00950261eb3eb9205f1d3879 Change-Id: I42b96f1f7364f75da88eccd7a86fc25b9cd1499d Reviewed-by: Christian Kandeler Reviewed-by: --- src/plugins/classview/classviewmanager.cpp | 2 +- src/plugins/cmakeprojectmanager/cmakeeditor.cpp | 2 +- .../cppeditor/followsymbol_switchmethoddecldef_test.cpp | 1 + src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp | 3 +-- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/plugins/classview/classviewmanager.cpp b/src/plugins/classview/classviewmanager.cpp index 7f4eeb955c6..90c834a6216 100644 --- a/src/plugins/classview/classviewmanager.cpp +++ b/src/plugins/classview/classviewmanager.cpp @@ -378,7 +378,7 @@ void Manager::gotoLocations(const QList &list) int line; int column; textEditor->convertPosition(textEditor->position(), &line, &column); - const SymbolLocation current(filePath, line, column); + const SymbolLocation current(filePath, line, column + 1); if (auto it = locations.constFind(current), end = locations.constEnd(); it != end) { // we already are at the symbol, cycle to next location ++it; diff --git a/src/plugins/cmakeprojectmanager/cmakeeditor.cpp b/src/plugins/cmakeprojectmanager/cmakeeditor.cpp index 3411fd85b58..5193661e57b 100644 --- a/src/plugins/cmakeprojectmanager/cmakeeditor.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeeditor.cpp @@ -157,7 +157,7 @@ void CMakeEditorWidget::findLinkAt(const QTextCursor &cursor, // find the beginning of a filename QString buffer; - int beginPos = column - 1; + int beginPos = column; while (beginPos >= 0) { if (isValidFileNameChar(block, beginPos)) { buffer.prepend(block.at(beginPos)); diff --git a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp index 90ddfbdf905..31d69f7363d 100644 --- a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp +++ b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp @@ -414,6 +414,7 @@ F2TestCase::F2TestCase(CppEditorAction action, } else { currentTextEditor->convertPosition(targetTestFile->m_targetCursorPosition, &expectedLine, &expectedColumn); + ++expectedColumn; if (useClangd && (tag == "classDestructor" || tag == "fromDestructorDefinitionSymbol" || tag == "fromDestructorBody")) { --expectedColumn; // clangd goes before the ~, built-in code model after diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp b/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp index d89393909ba..61493bf05c3 100644 --- a/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp @@ -357,8 +357,7 @@ void QmakeProjectManagerPluginPrivate::addLibraryImpl(const FilePath &filePath, // add extra \n in case the last line is not empty int line, column; editor->convertPosition(endOfDoc, &line, &column); - const int positionInBlock = column - 1; - if (!editor->textAt(endOfDoc - positionInBlock, positionInBlock).simplified().isEmpty()) + if (!editor->textAt(endOfDoc - column, column).simplified().isEmpty()) snippet = QLatin1Char('\n') + snippet; editor->insert(snippet); From 7625633ff2ade17135898f560b4dc9262b887e74 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Fri, 26 May 2023 11:15:45 +0200 Subject: [PATCH 015/141] TaskTree tests: Get rid of future synchronizer The future synchronizer may abuse the subsequent test invocation as it may still have spinning threads from the previous test run. As all the started tasks should finish quickly on cancel, we drop putting the canceled futures into the synchronizer. Instead, we blocking wait for them to finish. In this way, when the subsequent test is invoked, we should expect the all available threads are ready to be used. Change-Id: I9bb022b8c0950d27cb323ff83bf18148829160b3 Reviewed-by: Qt CI Bot Reviewed-by: Marcus Tillmanns Reviewed-by: hjk Reviewed-by: --- tests/auto/solutions/tasking/tst_tasking.cpp | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/tests/auto/solutions/tasking/tst_tasking.cpp b/tests/auto/solutions/tasking/tst_tasking.cpp index 17335d29f41..7564435c497 100644 --- a/tests/auto/solutions/tasking/tst_tasking.cpp +++ b/tests/auto/solutions/tasking/tst_tasking.cpp @@ -55,8 +55,6 @@ private: int CustomStorage::s_count = 0; static const char s_taskIdProperty[] = "__taskId"; -static FutureSynchronizer *s_futureSynchronizer = nullptr; - struct TestData { TreeStorage storage; Group root; @@ -70,28 +68,13 @@ class tst_Tasking : public QObject Q_OBJECT private slots: - void initTestCase(); - void validConstructs(); // compile test void testTree_data(); void testTree(); void storageOperators(); void storageDestructor(); - - void cleanupTestCase(); }; -void tst_Tasking::initTestCase() -{ - s_futureSynchronizer = new FutureSynchronizer; -} - -void tst_Tasking::cleanupTestCase() -{ - delete s_futureSynchronizer; - s_futureSynchronizer = nullptr; -} - void tst_Tasking::validConstructs() { const Group task { @@ -208,7 +191,6 @@ auto setupBarrierAdvance(const TreeStorage &storage, const SharedBarrierType &barrier, int taskId) { return [storage, barrier, taskId](Async &async) { - async.setFutureSynchronizer(s_futureSynchronizer); async.setConcurrentCallData(reportAndSleep); async.setProperty(s_taskIdProperty, taskId); storage->m_log.append({taskId, Handler::Setup}); @@ -232,7 +214,6 @@ void tst_Tasking::testTree_data() const auto setupTaskHelper = [storage](TestTask &task, int taskId, bool success = true, std::chrono::milliseconds sleep = 0ms) { - task.setFutureSynchronizer(s_futureSynchronizer); task.setConcurrentCallData(runTask, success, sleep); task.setProperty(s_taskIdProperty, taskId); storage->m_log.append({taskId, Handler::Setup}); @@ -1668,7 +1649,6 @@ void tst_Tasking::storageDestructor() { TreeStorage storage; const auto setupSleepingTask = [](TestTask &task) { - task.setFutureSynchronizer(s_futureSynchronizer); task.setConcurrentCallData(runTask, true, 1000ms); }; const Group root { From d69c3cec7d7c9a3ef95e8bdb0f17d2345879fe3f Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Sat, 27 May 2023 17:20:40 +0200 Subject: [PATCH 016/141] TaskTree tests: De-utils-ize TaskTree tests Make the TaskTree tests dependent only on Tasking lib. Introduce simple Timeout and Delay tasks for tests. Using Timeout and Delay has a big advantage for these tests, since e.g. when scheduling two parallel tasks with the same timeout, we can expect the proper order in which they finish. With AsyncTask it wasn't possible. Now, the tests should be much more reliable and shouldn't exibit flakiness anymore. Use TickAndDone for Barrier tests. Limit the tests' execution time from ~100ms into ~30ms. Change-Id: Ifa08fd62c1a2759a877231c2220e353c1a26364f Reviewed-by: Qt CI Bot Reviewed-by: Marcus Tillmanns --- tests/auto/solutions/tasking/CMakeLists.txt | 2 +- tests/auto/solutions/tasking/tasking.qbs | 2 +- tests/auto/solutions/tasking/tst_tasking.cpp | 1050 ++++++++++-------- 3 files changed, 564 insertions(+), 490 deletions(-) diff --git a/tests/auto/solutions/tasking/CMakeLists.txt b/tests/auto/solutions/tasking/CMakeLists.txt index 534d215ccb1..a425250a5a9 100644 --- a/tests/auto/solutions/tasking/CMakeLists.txt +++ b/tests/auto/solutions/tasking/CMakeLists.txt @@ -1,4 +1,4 @@ add_qtc_test(tst_solutions_tasking - DEPENDS Utils + DEPENDS Tasking SOURCES tst_tasking.cpp ) diff --git a/tests/auto/solutions/tasking/tasking.qbs b/tests/auto/solutions/tasking/tasking.qbs index 173c1fc5752..f099edb370c 100644 --- a/tests/auto/solutions/tasking/tasking.qbs +++ b/tests/auto/solutions/tasking/tasking.qbs @@ -1,7 +1,7 @@ QtcAutotest { name: "Tasking autotest" - Depends { name: "Utils" } + Depends { name: "Tasking" } files: "tst_tasking.cpp" } diff --git a/tests/auto/solutions/tasking/tst_tasking.cpp b/tests/auto/solutions/tasking/tst_tasking.cpp index 7564435c497..e3f7a80ed5b 100644 --- a/tests/auto/solutions/tasking/tst_tasking.cpp +++ b/tests/auto/solutions/tasking/tst_tasking.cpp @@ -1,21 +1,28 @@ // Copyright (C) 2022 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 -#include - -#include +#include +#include #include -#include +using namespace std::chrono; +using namespace std::chrono_literals; -using namespace std::literals::chrono_literals; - -using namespace Utils; using namespace Tasking; -using TestTask = Async; -using Test = AsyncTask; +template +class TASKING_EXPORT DurationTaskAdapter : public TaskAdapter +{ +public: + DurationTaskAdapter() { *task() = std::chrono::milliseconds{0}; } + void start() final { QTimer::singleShot(*task(), this, [this] { emit done(SuccessOnDone); }); } +}; + +TASKING_DECLARE_TASK(SuccessTask, DurationTaskAdapter); +TASKING_DECLARE_TASK(FailingTask, DurationTaskAdapter); + +using TaskObject = milliseconds; namespace PrintableEnums { @@ -79,9 +86,9 @@ void tst_Tasking::validConstructs() { const Group task { parallel, - Test([](TestTask &) {}, [](const TestTask &) {}), - Test([](TestTask &) {}, [](const TestTask &) {}), - Test([](TestTask &) {}, [](const TestTask &) {}) + SuccessTask([](TaskObject &) {}, [](const TaskObject &) {}), + SuccessTask([](TaskObject &) {}, [](const TaskObject &) {}), + SuccessTask([](TaskObject &) {}, [](const TaskObject &) {}) }; const Group group1 { @@ -92,18 +99,18 @@ void tst_Tasking::validConstructs() parallel, Group { parallel, - Test([](TestTask &) {}, [](const TestTask &) {}), + SuccessTask([](TaskObject &) {}, [](const TaskObject &) {}), Group { parallel, - Test([](TestTask &) {}, [](const TestTask &) {}), + SuccessTask([](TaskObject &) {}, [](const TaskObject &) {}), Group { parallel, - Test([](TestTask &) {}, [](const TestTask &) {}) + SuccessTask([](TaskObject &) {}, [](const TaskObject &) {}) } }, Group { parallel, - Test([](TestTask &) {}, [](const TestTask &) {}), + SuccessTask([](TaskObject &) {}, [](const TaskObject &) {}), onGroupDone([] {}) } }, @@ -112,32 +119,32 @@ void tst_Tasking::validConstructs() onGroupError([] {}) }; - const auto setupHandler = [](TestTask &) {}; - const auto doneHandler = [](const TestTask &) {}; - const auto errorHandler = [](const TestTask &) {}; + const auto setupHandler = [](TaskObject &) {}; + const auto doneHandler = [](const TaskObject &) {}; + const auto errorHandler = [](const TaskObject &) {}; // Not fluent interface const Group task2 { parallel, - Test(setupHandler), - Test(setupHandler, doneHandler), - Test(setupHandler, doneHandler, errorHandler), + SuccessTask(setupHandler), + SuccessTask(setupHandler, doneHandler), + SuccessTask(setupHandler, doneHandler, errorHandler), // need to explicitly pass empty handler for done - Test(setupHandler, {}, errorHandler) + SuccessTask(setupHandler, {}, errorHandler) }; // Fluent interface const Group fluent { parallel, - Test().onSetup(setupHandler), - Test().onSetup(setupHandler).onDone(doneHandler), - Test().onSetup(setupHandler).onDone(doneHandler).onError(errorHandler), + SuccessTask().onSetup(setupHandler), + SuccessTask().onSetup(setupHandler).onDone(doneHandler), + SuccessTask().onSetup(setupHandler).onDone(doneHandler).onError(errorHandler), // possible to skip the empty done - Test().onSetup(setupHandler).onError(errorHandler), + SuccessTask().onSetup(setupHandler).onError(errorHandler), // possible to set handlers in a different order - Test().onError(errorHandler).onDone(doneHandler).onSetup(setupHandler), + SuccessTask().onError(errorHandler).onDone(doneHandler).onSetup(setupHandler), }; @@ -168,42 +175,53 @@ void tst_Tasking::validConstructs() #endif } -static void runTask(QPromise &promise, bool success, std::chrono::milliseconds sleep) +class TickAndDone : public QObject { - QDeadlineTimer deadline(sleep); - while (!deadline.hasExpired()) { - QThread::msleep(1); - if (promise.isCanceled()) - return; - } - if (!success) - promise.future().cancel(); -} + Q_OBJECT -static void reportAndSleep(QPromise &promise) -{ - promise.addResult(false); - QThread::msleep(5); +public: + void setInterval(const milliseconds &interval) { m_interval = interval; } + void start() { + QTimer::singleShot(0, this, [this] { + emit tick(); + QTimer::singleShot(m_interval, this, &TickAndDone::done); + }); + } + +signals: + void tick(); + void done(); + +private: + milliseconds m_interval; }; -template -auto setupBarrierAdvance(const TreeStorage &storage, - const SharedBarrierType &barrier, int taskId) +class TickAndDoneTaskAdapter : public TaskAdapter { - return [storage, barrier, taskId](Async &async) { - async.setConcurrentCallData(reportAndSleep); - async.setProperty(s_taskIdProperty, taskId); +public: + TickAndDoneTaskAdapter() { connect(task(), &TickAndDone::done, this, + [this] { emit done(true); }); } + void start() final { task()->start(); } +}; + +TASKING_DECLARE_TASK(TickAndDoneTask, TickAndDoneTaskAdapter); + +template +TaskItem createBarrierAdvance(const TreeStorage &storage, + const SharedBarrierType &barrier, int taskId) +{ + return TickAndDoneTask([storage, barrier, taskId](TickAndDone &tickAndDone) { + tickAndDone.setInterval(1ms); storage->m_log.append({taskId, Handler::Setup}); CustomStorage *currentStorage = storage.activeStorage(); Barrier *sharedBarrier = barrier->barrier(); - QObject::connect(&async, &TestTask::resultReadyAt, sharedBarrier, - [currentStorage, sharedBarrier, taskId](int index) { - Q_UNUSED(index) + QObject::connect(&tickAndDone, &TickAndDone::tick, sharedBarrier, + [currentStorage, sharedBarrier, taskId] { currentStorage->m_log.append({taskId, Handler::BarrierAdvance}); sharedBarrier->advance(); }); - }; + }); } void tst_Tasking::testTree_data() @@ -212,101 +230,91 @@ void tst_Tasking::testTree_data() TreeStorage storage; - const auto setupTaskHelper = [storage](TestTask &task, int taskId, bool success = true, - std::chrono::milliseconds sleep = 0ms) { - task.setConcurrentCallData(runTask, success, sleep); - task.setProperty(s_taskIdProperty, taskId); - storage->m_log.append({taskId, Handler::Setup}); + const auto setupTask = [storage](int taskId, milliseconds timeout) { + return [storage, taskId, timeout](TaskObject &taskObject) { + taskObject = timeout; + storage->m_log.append({taskId, Handler::Setup}); + }; }; - const auto setupTask = [setupTaskHelper](int taskId) { - return [=](TestTask &task) { setupTaskHelper(task, taskId); }; - }; - const auto setupFailingTask = [setupTaskHelper](int taskId) { - return [=](TestTask &task) { setupTaskHelper(task, taskId, false); }; - }; - const auto setupSleepingTask = [setupTaskHelper](int taskId, bool success, - std::chrono::milliseconds sleep) { - return [=](TestTask &task) { setupTaskHelper(task, taskId, success, sleep); }; - }; - const auto setupDynamicTask = [setupTaskHelper](int taskId, TaskAction action) { - return [=](TestTask &task) { - setupTaskHelper(task, taskId); + + const auto setupDynamicTask = [storage](int taskId, TaskAction action) { + return [storage, taskId, action](TaskObject &) { + storage->m_log.append({taskId, Handler::Setup}); return action; }; }; - const auto logDone = [storage](const TestTask &task) { - storage->m_log.append({task.property(s_taskIdProperty).toInt(), Handler::Done}); - }; - const auto logError = [storage](const TestTask &task) { - storage->m_log.append({task.property(s_taskIdProperty).toInt(), Handler::Error}); - }; - const auto groupSetup = [storage](int taskId) { - return [=] { storage->m_log.append({taskId, Handler::GroupSetup}); }; - }; - const auto groupDone = [storage](int taskId) { - return [=] { storage->m_log.append({taskId, Handler::GroupDone}); }; - }; - const auto groupError = [storage](int taskId) { - return [=] { storage->m_log.append({taskId, Handler::GroupError}); }; - }; - const auto setupSync = [storage](int taskId) { - return [=] { storage->m_log.append({taskId, Handler::Sync}); }; - }; - const auto setupSyncWithReturn = [storage](int taskId, bool success) { - return [=] { storage->m_log.append({taskId, Handler::Sync}); return success; }; + + const auto setupDone = [storage](int taskId) { + return [storage, taskId](const TaskObject &) { + storage->m_log.append({taskId, Handler::Done}); + }; }; - const auto constructSimpleSequence = [=](WorkflowPolicy policy) { - return Group { - Storage(storage), - workflowPolicy(policy), - Test(setupTask(1), logDone), - Test(setupFailingTask(2), logDone, logError), - Test(setupTask(3), logDone), - onGroupDone(groupDone(0)), - onGroupError(groupError(0)) + const auto setupError = [storage](int taskId) { + return [storage, taskId](const TaskObject &) { + storage->m_log.append({taskId, Handler::Error}); }; }; - const auto constructDynamicHierarchy = [=](TaskAction taskAction) { - return Group { - Storage(storage), - Group { - Test(setupTask(1), logDone) - }, - Group { - onGroupSetup([=] { return taskAction; }), - Test(setupTask(2), logDone), - Test(setupTask(3), logDone), - Test(setupTask(4), logDone) - }, - onGroupDone(groupDone(0)), - onGroupError(groupError(0)) - }; + + const auto createTask = [storage, setupTask, setupDone, setupError]( + int taskId, bool successTask, milliseconds timeout = 0ms) -> TaskItem { + if (successTask) + return SuccessTask(setupTask(taskId, timeout), setupDone(taskId), setupError(taskId)); + return FailingTask(setupTask(taskId, timeout), setupDone(taskId), setupError(taskId)); + }; + + const auto createSuccessTask = [createTask](int taskId, milliseconds timeout = 0ms) { + return createTask(taskId, true, timeout); + }; + + const auto createFailingTask = [createTask](int taskId, milliseconds timeout = 0ms) { + return createTask(taskId, false, timeout); + }; + + const auto createDynamicTask = [storage, setupDynamicTask, setupDone, setupError]( + int taskId, TaskAction action) { + return SuccessTask(setupDynamicTask(taskId, action), setupDone(taskId), setupError(taskId)); + }; + + const auto groupSetup = [storage](int taskId) { + return onGroupSetup([=] { storage->m_log.append({taskId, Handler::GroupSetup}); }); + }; + const auto groupDone = [storage](int taskId) { + return onGroupDone([=] { storage->m_log.append({taskId, Handler::GroupDone}); }); + }; + const auto groupError = [storage](int taskId) { + return onGroupError([=] { storage->m_log.append({taskId, Handler::GroupError}); }); + }; + const auto createSync = [storage](int taskId) { + return Sync([=] { storage->m_log.append({taskId, Handler::Sync}); }); + }; + const auto createSyncWithReturn = [storage](int taskId, bool success) { + return Sync([=] { storage->m_log.append({taskId, Handler::Sync}); return success; }); }; { const Group root1 { Storage(storage), - onGroupDone(groupDone(0)), - onGroupError(groupError(0)) + groupDone(0), + groupError(0) }; const Group root2 { Storage(storage), onGroupSetup([] { return TaskAction::Continue; }), - onGroupDone(groupDone(0)), - onGroupError(groupError(0)) + groupDone(0), + groupError(0) }; const Group root3 { Storage(storage), onGroupSetup([] { return TaskAction::StopWithDone; }), - onGroupDone(groupDone(0)), - onGroupError(groupError(0)) + groupDone(0), + groupError(0) }; const Group root4 { Storage(storage), onGroupSetup([] { return TaskAction::StopWithError; }), - onGroupDone(groupDone(0)), - onGroupError(groupError(0)) + groupDone(0), + groupError(0) }; const Log logDone {{0, Handler::GroupDone}}; const Log logError {{0, Handler::GroupError}}; @@ -319,8 +327,8 @@ void tst_Tasking::testTree_data() { const Group root { Storage(storage), - Test(setupDynamicTask(1, TaskAction::StopWithDone), logDone, logError), - Test(setupDynamicTask(2, TaskAction::StopWithDone), logDone, logError) + createDynamicTask(1, TaskAction::StopWithDone), + createDynamicTask(2, TaskAction::StopWithDone) }; const Log log {{1, Handler::Setup}, {2, Handler::Setup}}; QTest::newRow("DynamicTaskDone") << TestData{storage, root, log, 2, OnDone::Success}; @@ -329,8 +337,8 @@ void tst_Tasking::testTree_data() { const Group root { Storage(storage), - Test(setupDynamicTask(1, TaskAction::StopWithError), logDone, logError), - Test(setupDynamicTask(2, TaskAction::StopWithError), logDone, logError) + createDynamicTask(1, TaskAction::StopWithError), + createDynamicTask(2, TaskAction::StopWithError) }; const Log log {{1, Handler::Setup}}; QTest::newRow("DynamicTaskError") << TestData{storage, root, log, 2, OnDone::Failure}; @@ -339,10 +347,10 @@ void tst_Tasking::testTree_data() { const Group root { Storage(storage), - Test(setupDynamicTask(1, TaskAction::Continue), logDone, logError), - Test(setupDynamicTask(2, TaskAction::Continue), logDone, logError), - Test(setupDynamicTask(3, TaskAction::StopWithError), logDone, logError), - Test(setupDynamicTask(4, TaskAction::Continue), logDone, logError) + createDynamicTask(1, TaskAction::Continue), + createDynamicTask(2, TaskAction::Continue), + createDynamicTask(3, TaskAction::StopWithError), + createDynamicTask(4, TaskAction::Continue) }; const Log log { {1, Handler::Setup}, @@ -358,10 +366,10 @@ void tst_Tasking::testTree_data() const Group root { parallel, Storage(storage), - Test(setupDynamicTask(1, TaskAction::Continue), logDone, logError), - Test(setupDynamicTask(2, TaskAction::Continue), logDone, logError), - Test(setupDynamicTask(3, TaskAction::StopWithError), logDone, logError), - Test(setupDynamicTask(4, TaskAction::Continue), logDone, logError) + createDynamicTask(1, TaskAction::Continue), + createDynamicTask(2, TaskAction::Continue), + createDynamicTask(3, TaskAction::StopWithError), + createDynamicTask(4, TaskAction::Continue) }; const Log log { {1, Handler::Setup}, @@ -377,12 +385,12 @@ void tst_Tasking::testTree_data() const Group root { parallel, Storage(storage), - Test(setupDynamicTask(1, TaskAction::Continue), logDone, logError), - Test(setupDynamicTask(2, TaskAction::Continue), logDone, logError), + createDynamicTask(1, TaskAction::Continue), + createDynamicTask(2, TaskAction::Continue), Group { - Test(setupDynamicTask(3, TaskAction::StopWithError), logDone, logError) + createDynamicTask(3, TaskAction::StopWithError) }, - Test(setupDynamicTask(4, TaskAction::Continue), logDone, logError) + createDynamicTask(4, TaskAction::Continue) }; const Log log { {1, Handler::Setup}, @@ -398,16 +406,16 @@ void tst_Tasking::testTree_data() const Group root { parallel, Storage(storage), - Test(setupDynamicTask(1, TaskAction::Continue), logDone, logError), - Test(setupDynamicTask(2, TaskAction::Continue), logDone, logError), + createDynamicTask(1, TaskAction::Continue), + createDynamicTask(2, TaskAction::Continue), Group { onGroupSetup([storage] { storage->m_log.append({0, Handler::GroupSetup}); return TaskAction::StopWithError; }), - Test(setupDynamicTask(3, TaskAction::Continue), logDone, logError) + createDynamicTask(3, TaskAction::Continue) }, - Test(setupDynamicTask(4, TaskAction::Continue), logDone, logError) + createDynamicTask(4, TaskAction::Continue) }; const Log log { {1, Handler::Setup}, @@ -428,23 +436,23 @@ void tst_Tasking::testTree_data() Group { Group { Group { - Test(setupTask(5), logDone, logError), - onGroupSetup(groupSetup(5)), - onGroupDone(groupDone(5)) + createSuccessTask(5), + groupSetup(5), + groupDone(5) }, - onGroupSetup(groupSetup(4)), - onGroupDone(groupDone(4)) + groupSetup(4), + groupDone(4) }, - onGroupSetup(groupSetup(3)), - onGroupDone(groupDone(3)) + groupSetup(3), + groupDone(3) }, - onGroupSetup(groupSetup(2)), - onGroupDone(groupDone(2)) + groupSetup(2), + groupDone(2) }, - onGroupSetup(groupSetup(1)), - onGroupDone(groupDone(1)) + groupSetup(1), + groupDone(1) }, - onGroupDone(groupDone(0)) + groupDone(0) }; const Log log { {1, Handler::GroupSetup}, @@ -465,18 +473,15 @@ void tst_Tasking::testTree_data() } { - const auto logDoneAnonymously = [=](const TestTask &) { - storage->m_log.append({0, Handler::Done}); - }; const Group root { Storage(storage), parallel, - Test(setupTask(1), logDoneAnonymously), - Test(setupTask(2), logDoneAnonymously), - Test(setupTask(3), logDoneAnonymously), - Test(setupTask(4), logDoneAnonymously), - Test(setupTask(5), logDoneAnonymously), - onGroupDone(groupDone(0)) + createSuccessTask(1), + createSuccessTask(2), + createSuccessTask(3), + createSuccessTask(4), + createSuccessTask(5), + groupDone(0) }; const Log log { {1, Handler::Setup}, // Setup order is determined in parallel mode @@ -484,23 +489,23 @@ void tst_Tasking::testTree_data() {3, Handler::Setup}, {4, Handler::Setup}, {5, Handler::Setup}, - {0, Handler::Done}, // Done order isn't determined in parallel mode - {0, Handler::Done}, - {0, Handler::Done}, - {0, Handler::Done}, - {0, Handler::Done}, + {1, Handler::Done}, + {2, Handler::Done}, + {3, Handler::Done}, + {4, Handler::Done}, + {5, Handler::Done}, {0, Handler::GroupDone} }; QTest::newRow("Parallel") << TestData{storage, root, log, 5, OnDone::Success}; } { - auto setupSubTree = [=](TaskTree &taskTree) { + auto setupSubTree = [storage, createSuccessTask](TaskTree &taskTree) { const Group nestedRoot { Storage(storage), - Test(setupTask(2), logDone), - Test(setupTask(3), logDone), - Test(setupTask(4), logDone) + createSuccessTask(2), + createSuccessTask(3), + createSuccessTask(4) }; taskTree.setupRoot(nestedRoot); CustomStorage *activeStorage = storage.activeStorage(); @@ -511,28 +516,28 @@ void tst_Tasking::testTree_data() }; const Group root1 { Storage(storage), - Test(setupTask(1), logDone), - Test(setupTask(2), logDone), - Test(setupTask(3), logDone), - Test(setupTask(4), logDone), - Test(setupTask(5), logDone), - onGroupDone(groupDone(0)) + createSuccessTask(1), + createSuccessTask(2), + createSuccessTask(3), + createSuccessTask(4), + createSuccessTask(5), + groupDone(0) }; const Group root2 { Storage(storage), - Group { Test(setupTask(1), logDone) }, - Group { Test(setupTask(2), logDone) }, - Group { Test(setupTask(3), logDone) }, - Group { Test(setupTask(4), logDone) }, - Group { Test(setupTask(5), logDone) }, - onGroupDone(groupDone(0)) + Group { createSuccessTask(1) }, + Group { createSuccessTask(2) }, + Group { createSuccessTask(3) }, + Group { createSuccessTask(4) }, + Group { createSuccessTask(5) }, + groupDone(0) }; const Group root3 { Storage(storage), - Test(setupTask(1), logDone), + createSuccessTask(1), TaskTreeTask(setupSubTree), - Test(setupTask(5), logDone), - onGroupDone(groupDone(0)) + createSuccessTask(5), + groupDone(0) }; const Log log { {1, Handler::Setup}, @@ -557,26 +562,26 @@ void tst_Tasking::testTree_data() const Group root { Storage(storage), Group { - Test(setupTask(1), logDone), + createSuccessTask(1), Group { - Test(setupTask(2), logDone), + createSuccessTask(2), Group { - Test(setupTask(3), logDone), + createSuccessTask(3), Group { - Test(setupTask(4), logDone), + createSuccessTask(4), Group { - Test(setupTask(5), logDone), - onGroupDone(groupDone(5)) + createSuccessTask(5), + groupDone(5) }, - onGroupDone(groupDone(4)) + groupDone(4) }, - onGroupDone(groupDone(3)) + groupDone(3) }, - onGroupDone(groupDone(2)) + groupDone(2) }, - onGroupDone(groupDone(1)) + groupDone(1) }, - onGroupDone(groupDone(0)) + groupDone(0) }; const Log log { {1, Handler::Setup}, @@ -602,13 +607,13 @@ void tst_Tasking::testTree_data() { const Group root { Storage(storage), - Test(setupTask(1), logDone), - Test(setupTask(2), logDone), - Test(setupFailingTask(3), logDone, logError), - Test(setupTask(4), logDone), - Test(setupTask(5), logDone), - onGroupDone(groupDone(0)), - onGroupError(groupError(0)) + createSuccessTask(1), + createSuccessTask(2), + createFailingTask(3), + createSuccessTask(4), + createSuccessTask(5), + groupDone(0), + groupError(0) }; const Log log { {1, Handler::Setup}, @@ -623,44 +628,45 @@ void tst_Tasking::testTree_data() } { - const auto constructEmptyWorkflow = [=](WorkflowPolicy policy) { + const auto createRoot = [storage, groupDone, groupError](WorkflowPolicy policy) { return Group { Storage(storage), workflowPolicy(policy), - onGroupDone(groupDone(0)), - onGroupError(groupError(0)) + groupDone(0), + groupError(0) }; }; const Log log = {{0, Handler::GroupDone}}; - const Group root1 = constructEmptyWorkflow(WorkflowPolicy::StopOnError); + const Group root1 = createRoot(WorkflowPolicy::StopOnError); QTest::newRow("EmptyStopOnError") << TestData{storage, root1, log, 0, OnDone::Success}; - const Group root2 = constructEmptyWorkflow(WorkflowPolicy::ContinueOnError); + const Group root2 = createRoot(WorkflowPolicy::ContinueOnError); QTest::newRow("EmptyContinueOnError") << TestData{storage, root2, log, 0, OnDone::Success}; - const Group root3 = constructEmptyWorkflow(WorkflowPolicy::StopOnDone); + const Group root3 = createRoot(WorkflowPolicy::StopOnDone); QTest::newRow("EmptyStopOnDone") << TestData{storage, root3, log, 0, OnDone::Success}; - const Group root4 = constructEmptyWorkflow(WorkflowPolicy::ContinueOnDone); + const Group root4 = createRoot(WorkflowPolicy::ContinueOnDone); QTest::newRow("EmptyContinueOnDone") << TestData{storage, root4, log, 0, OnDone::Success}; - const Group root5 = constructEmptyWorkflow(WorkflowPolicy::StopOnFinished); + const Group root5 = createRoot(WorkflowPolicy::StopOnFinished); QTest::newRow("EmptyStopOnFinished") << TestData{storage, root5, log, 0, OnDone::Success}; - const Group root6 = constructEmptyWorkflow(WorkflowPolicy::Optional); + const Group root6 = createRoot(WorkflowPolicy::Optional); QTest::newRow("EmptyOptional") << TestData{storage, root6, log, 0, OnDone::Success}; } { - const auto constructDoneWorkflow = [=](WorkflowPolicy policy) { + const auto createRoot = [storage, createSuccessTask, groupDone, groupError]( + WorkflowPolicy policy) { return Group { Storage(storage), workflowPolicy(policy), - Test(setupTask(1), logDone, logError), - onGroupDone(groupDone(0)), - onGroupError(groupError(0)) + createSuccessTask(1), + groupDone(0), + groupError(0) }; }; @@ -670,33 +676,34 @@ void tst_Tasking::testTree_data() {0, Handler::GroupDone} }; - const Group root1 = constructDoneWorkflow(WorkflowPolicy::StopOnError); + const Group root1 = createRoot(WorkflowPolicy::StopOnError); QTest::newRow("DoneStopOnError") << TestData{storage, root1, log, 1, OnDone::Success}; - const Group root2 = constructDoneWorkflow(WorkflowPolicy::ContinueOnError); + const Group root2 = createRoot(WorkflowPolicy::ContinueOnError); QTest::newRow("DoneContinueOnError") << TestData{storage, root2, log, 1, OnDone::Success}; - const Group root3 = constructDoneWorkflow(WorkflowPolicy::StopOnDone); + const Group root3 = createRoot(WorkflowPolicy::StopOnDone); QTest::newRow("DoneStopOnDone") << TestData{storage, root3, log, 1, OnDone::Success}; - const Group root4 = constructDoneWorkflow(WorkflowPolicy::ContinueOnDone); + const Group root4 = createRoot(WorkflowPolicy::ContinueOnDone); QTest::newRow("DoneContinueOnDone") << TestData{storage, root4, log, 1, OnDone::Success}; - const Group root5 = constructDoneWorkflow(WorkflowPolicy::StopOnFinished); + const Group root5 = createRoot(WorkflowPolicy::StopOnFinished); QTest::newRow("DoneStopOnFinished") << TestData{storage, root5, log, 1, OnDone::Success}; - const Group root6 = constructDoneWorkflow(WorkflowPolicy::Optional); + const Group root6 = createRoot(WorkflowPolicy::Optional); QTest::newRow("DoneOptional") << TestData{storage, root6, log, 1, OnDone::Success}; } { - const auto constructErrorWorkflow = [=](WorkflowPolicy policy) { + const auto createRoot = [storage, createFailingTask, groupDone, groupError]( + WorkflowPolicy policy) { return Group { Storage(storage), workflowPolicy(policy), - Test(setupFailingTask(1), logDone, logError), - onGroupDone(groupDone(0)), - onGroupError(groupError(0)) + createFailingTask(1), + groupDone(0), + groupError(0) }; }; @@ -712,40 +719,51 @@ void tst_Tasking::testTree_data() {0, Handler::GroupDone} }; - const Group root1 = constructErrorWorkflow(WorkflowPolicy::StopOnError); + const Group root1 = createRoot(WorkflowPolicy::StopOnError); QTest::newRow("ErrorStopOnError") << TestData{storage, root1, log, 1, OnDone::Failure}; - const Group root2 = constructErrorWorkflow(WorkflowPolicy::ContinueOnError); + const Group root2 = createRoot(WorkflowPolicy::ContinueOnError); QTest::newRow("ErrorContinueOnError") << TestData{storage, root2, log, 1, OnDone::Failure}; - const Group root3 = constructErrorWorkflow(WorkflowPolicy::StopOnDone); + const Group root3 = createRoot(WorkflowPolicy::StopOnDone); QTest::newRow("ErrorStopOnDone") << TestData{storage, root3, log, 1, OnDone::Failure}; - const Group root4 = constructErrorWorkflow(WorkflowPolicy::ContinueOnDone); + const Group root4 = createRoot(WorkflowPolicy::ContinueOnDone); QTest::newRow("ErrorContinueOnDone") << TestData{storage, root4, log, 1, OnDone::Failure}; - const Group root5 = constructErrorWorkflow(WorkflowPolicy::StopOnFinished); + const Group root5 = createRoot(WorkflowPolicy::StopOnFinished); QTest::newRow("ErrorStopOnFinished") << TestData{storage, root5, log, 1, OnDone::Failure}; - const Group root6 = constructErrorWorkflow(WorkflowPolicy::Optional); + const Group root6 = createRoot(WorkflowPolicy::Optional); QTest::newRow("ErrorOptional") << TestData{storage, root6, optionalLog, 1, OnDone::Success}; } { - const Group root = constructSimpleSequence(WorkflowPolicy::StopOnError); - const Log log { + const auto createRoot = [storage, createSuccessTask, createFailingTask, groupDone, + groupError](WorkflowPolicy policy) { + return Group { + Storage(storage), + workflowPolicy(policy), + createSuccessTask(1), + createFailingTask(2), + createSuccessTask(3), + groupDone(0), + groupError(0) + }; + }; + + const Group root1 = createRoot(WorkflowPolicy::StopOnError); + const Log log1 { {1, Handler::Setup}, {1, Handler::Done}, {2, Handler::Setup}, {2, Handler::Error}, {0, Handler::GroupError} }; - QTest::newRow("StopOnError") << TestData{storage, root, log, 3, OnDone::Failure}; - } + QTest::newRow("StopOnError") << TestData{storage, root1, log1, 3, OnDone::Failure}; - { - const Group root = constructSimpleSequence(WorkflowPolicy::ContinueOnError); - const Log log { + const Group root2 = createRoot(WorkflowPolicy::ContinueOnError); + const Log log2 { {1, Handler::Setup}, {1, Handler::Done}, {2, Handler::Setup}, @@ -754,22 +772,18 @@ void tst_Tasking::testTree_data() {3, Handler::Done}, {0, Handler::GroupError} }; - QTest::newRow("ContinueOnError") << TestData{storage, root, log, 3, OnDone::Failure}; - } + QTest::newRow("ContinueOnError") << TestData{storage, root2, log2, 3, OnDone::Failure}; - { - const Group root = constructSimpleSequence(WorkflowPolicy::StopOnDone); - const Log log { + const Group root3 = createRoot(WorkflowPolicy::StopOnDone); + const Log log3 { {1, Handler::Setup}, {1, Handler::Done}, {0, Handler::GroupDone} }; - QTest::newRow("StopOnDone") << TestData{storage, root, log, 3, OnDone::Success}; - } + QTest::newRow("StopOnDone") << TestData{storage, root3, log3, 3, OnDone::Success}; - { - const Group root = constructSimpleSequence(WorkflowPolicy::ContinueOnDone); - const Log log { + const Group root4 = createRoot(WorkflowPolicy::ContinueOnDone); + const Log log4 { {1, Handler::Setup}, {1, Handler::Done}, {2, Handler::Setup}, @@ -778,36 +792,35 @@ void tst_Tasking::testTree_data() {3, Handler::Done}, {0, Handler::GroupDone} }; - QTest::newRow("ContinueOnDone") << TestData{storage, root, log, 3, OnDone::Success}; - } + QTest::newRow("ContinueOnDone") << TestData{storage, root4, log4, 3, OnDone::Success}; - { - const Group root = constructSimpleSequence(WorkflowPolicy::StopOnFinished); - const Log log { + const Group root5 = createRoot(WorkflowPolicy::StopOnFinished); + const Log log5 { {1, Handler::Setup}, {1, Handler::Done}, {0, Handler::GroupDone} }; - QTest::newRow("StopOnFinished") << TestData{storage, root, log, 3, OnDone::Success}; + QTest::newRow("StopOnFinished") << TestData{storage, root5, log5, 3, OnDone::Success}; } { - const auto setupRoot = [=](bool firstSuccess, bool secondSuccess) { + const auto createRoot = [storage, createTask, groupDone, groupError]( + bool firstSuccess, bool secondSuccess) { return Group { parallel, stopOnFinished, Storage(storage), - Test(setupSleepingTask(1, firstSuccess, 1000ms), logDone, logError), - Test(setupSleepingTask(2, secondSuccess, 5ms), logDone, logError), - onGroupDone(groupDone(0)), - onGroupError(groupError(0)) + createTask(1, firstSuccess, 1000ms), + createTask(2, secondSuccess, 1ms), + groupDone(0), + groupError(0) }; }; - const Group root1 = setupRoot(true, true); - const Group root2 = setupRoot(true, false); - const Group root3 = setupRoot(false, true); - const Group root4 = setupRoot(false, false); + const Group root1 = createRoot(true, true); + const Group root2 = createRoot(true, false); + const Group root3 = createRoot(false, true); + const Group root4 = createRoot(false, false); const Log success { {1, Handler::Setup}, @@ -834,10 +847,10 @@ void tst_Tasking::testTree_data() const Group root { Storage(storage), optional, - Test(setupFailingTask(1), logDone, logError), - Test(setupFailingTask(2), logDone, logError), - onGroupDone(groupDone(0)), - onGroupError(groupError(0)) + createFailingTask(1), + createFailingTask(2), + groupDone(0), + groupError(0) }; const Log log { {1, Handler::Setup}, @@ -850,28 +863,42 @@ void tst_Tasking::testTree_data() } { - const Group root = constructDynamicHierarchy(TaskAction::StopWithDone); - const Log log { + const auto createRoot = [storage, createSuccessTask, groupDone, groupError]( + TaskAction taskAction) { + return Group { + Storage(storage), + Group { + createSuccessTask(1) + }, + Group { + onGroupSetup([=] { return taskAction; }), + createSuccessTask(2), + createSuccessTask(3), + createSuccessTask(4) + }, + groupDone(0), + groupError(0) + }; + }; + + const Group root1 = createRoot(TaskAction::StopWithDone); + const Log log1 { {1, Handler::Setup}, {1, Handler::Done}, {0, Handler::GroupDone} }; - QTest::newRow("DynamicSetupDone") << TestData{storage, root, log, 4, OnDone::Success}; - } + QTest::newRow("DynamicSetupDone") << TestData{storage, root1, log1, 4, OnDone::Success}; - { - const Group root = constructDynamicHierarchy(TaskAction::StopWithError); - const Log log { + const Group root2 = createRoot(TaskAction::StopWithError); + const Log log2 { {1, Handler::Setup}, {1, Handler::Done}, {0, Handler::GroupError} }; - QTest::newRow("DynamicSetupError") << TestData{storage, root, log, 4, OnDone::Failure}; - } + QTest::newRow("DynamicSetupError") << TestData{storage, root2, log2, 4, OnDone::Failure}; - { - const Group root = constructDynamicHierarchy(TaskAction::Continue); - const Log log { + const Group root3 = createRoot(TaskAction::Continue); + const Log log3 { {1, Handler::Setup}, {1, Handler::Done}, {2, Handler::Setup}, @@ -882,7 +909,7 @@ void tst_Tasking::testTree_data() {4, Handler::Done}, {0, Handler::GroupDone} }; - QTest::newRow("DynamicSetupContinue") << TestData{storage, root, log, 4, OnDone::Success}; + QTest::newRow("DynamicSetupContinue") << TestData{storage, root3, log3, 4, OnDone::Success}; } { @@ -890,20 +917,20 @@ void tst_Tasking::testTree_data() parallelLimit(2), Storage(storage), Group { - onGroupSetup(groupSetup(1)), - Test(setupTask(1)) + groupSetup(1), + createSuccessTask(1) }, Group { - onGroupSetup(groupSetup(2)), - Test(setupTask(2)) + groupSetup(2), + createSuccessTask(2) }, Group { - onGroupSetup(groupSetup(3)), - Test(setupTask(3)) + groupSetup(3), + createSuccessTask(3) }, Group { - onGroupSetup(groupSetup(4)), - Test(setupTask(4)) + groupSetup(4), + createSuccessTask(4) } }; const Log log { @@ -911,10 +938,14 @@ void tst_Tasking::testTree_data() {1, Handler::Setup}, {2, Handler::GroupSetup}, {2, Handler::Setup}, + {1, Handler::Done}, {3, Handler::GroupSetup}, {3, Handler::Setup}, + {2, Handler::Done}, {4, Handler::GroupSetup}, - {4, Handler::Setup} + {4, Handler::Setup}, + {3, Handler::Done}, + {4, Handler::Done} }; QTest::newRow("NestedParallel") << TestData{storage, root, log, 4, OnDone::Success}; } @@ -924,24 +955,24 @@ void tst_Tasking::testTree_data() parallelLimit(2), Storage(storage), Group { - onGroupSetup(groupSetup(1)), - Test(setupTask(1)) + groupSetup(1), + createSuccessTask(1) }, Group { - onGroupSetup(groupSetup(2)), - Test(setupTask(2)) + groupSetup(2), + createSuccessTask(2) }, Group { - onGroupSetup(groupSetup(3)), - Test(setupDynamicTask(3, TaskAction::StopWithDone)) + groupSetup(3), + createDynamicTask(3, TaskAction::StopWithDone) }, Group { - onGroupSetup(groupSetup(4)), - Test(setupTask(4)) + groupSetup(4), + createSuccessTask(4) }, Group { - onGroupSetup(groupSetup(5)), - Test(setupTask(5)) + groupSetup(5), + createSuccessTask(5) } }; const Log log { @@ -949,12 +980,16 @@ void tst_Tasking::testTree_data() {1, Handler::Setup}, {2, Handler::GroupSetup}, {2, Handler::Setup}, + {1, Handler::Done}, {3, Handler::GroupSetup}, {3, Handler::Setup}, {4, Handler::GroupSetup}, {4, Handler::Setup}, + {2, Handler::Done}, {5, Handler::GroupSetup}, - {5, Handler::Setup} + {5, Handler::Setup}, + {4, Handler::Done}, + {5, Handler::Done} }; QTest::newRow("NestedParallelDone") << TestData{storage, root, log, 5, OnDone::Success}; } @@ -964,26 +999,36 @@ void tst_Tasking::testTree_data() parallelLimit(2), Storage(storage), Group { - onGroupSetup(groupSetup(1)), - Test(setupTask(1)) + groupSetup(1), + createSuccessTask(1) }, Group { - onGroupSetup(groupSetup(2)), - Test(setupTask(2)) + groupSetup(2), + createSuccessTask(2) }, Group { - onGroupSetup(groupSetup(3)), - Test(setupDynamicTask(3, TaskAction::StopWithError)) + groupSetup(3), + createDynamicTask(3, TaskAction::StopWithError) }, Group { - onGroupSetup(groupSetup(4)), - Test(setupTask(4)) + groupSetup(4), + createSuccessTask(4) }, Group { - onGroupSetup(groupSetup(5)), - Test(setupTask(5)) + groupSetup(5), + createSuccessTask(5) } }; + const Log log1 { + {1, Handler::GroupSetup}, + {1, Handler::Setup}, + {2, Handler::GroupSetup}, + {2, Handler::Setup}, + {1, Handler::Done}, + {3, Handler::GroupSetup}, + {3, Handler::Setup}, + {2, Handler::Error} + }; // Inside this test the task 2 should finish first, then synchonously: // - task 3 should exit setup with error @@ -993,26 +1038,36 @@ void tst_Tasking::testTree_data() parallelLimit(2), Storage(storage), Group { - onGroupSetup(groupSetup(1)), - Test(setupSleepingTask(1, true, 10ms)) + groupSetup(1), + createSuccessTask(1, 10ms) }, Group { - onGroupSetup(groupSetup(2)), - Test(setupTask(2)) + groupSetup(2), + createSuccessTask(2) }, Group { - onGroupSetup(groupSetup(3)), - Test(setupDynamicTask(3, TaskAction::StopWithError)) + groupSetup(3), + createDynamicTask(3, TaskAction::StopWithError) }, Group { - onGroupSetup(groupSetup(4)), - Test(setupTask(4)) + groupSetup(4), + createSuccessTask(4) }, Group { - onGroupSetup(groupSetup(5)), - Test(setupTask(5)) + groupSetup(5), + createSuccessTask(5) } }; + const Log log2 { + {1, Handler::GroupSetup}, + {1, Handler::Setup}, + {2, Handler::GroupSetup}, + {2, Handler::Setup}, + {2, Handler::Done}, + {3, Handler::GroupSetup}, + {3, Handler::Setup}, + {1, Handler::Error} + }; // This test ensures that the task 1 doesn't invoke its done handler, // being ready while sleeping in the task's 2 done handler. @@ -1028,42 +1083,46 @@ void tst_Tasking::testTree_data() Group { parallelLimit(2), Group { - onGroupSetup(groupSetup(1)), - Test(setupSleepingTask(1, true, 20ms)) + groupSetup(1), + createSuccessTask(1, 10ms) }, Group { - onGroupSetup(groupSetup(2)), - Test(setupSleepingTask(2, true, 10ms)) + groupSetup(2), + createSuccessTask(2, 1ms) }, Group { - onGroupSetup(groupSetup(3)), - Test(setupDynamicTask(3, TaskAction::StopWithError)) + groupSetup(3), + createDynamicTask(3, TaskAction::StopWithError) }, Group { - onGroupSetup(groupSetup(4)), - Test(setupTask(4)) + groupSetup(4), + createSuccessTask(4) } }, Group { - onGroupSetup(groupSetup(5)), - Test(setupTask(5)) + groupSetup(5), + createSuccessTask(5) } }; - const Log shortLog { + const Log log3 { {1, Handler::GroupSetup}, {1, Handler::Setup}, {2, Handler::GroupSetup}, {2, Handler::Setup}, + {2, Handler::Done}, {3, Handler::GroupSetup}, - {3, Handler::Setup} + {3, Handler::Setup}, + {1, Handler::Error}, + {5, Handler::GroupSetup}, + {5, Handler::Setup}, + {5, Handler::Done} }; - const Log longLog = shortLog + Log {{5, Handler::GroupSetup}, {5, Handler::Setup}}; QTest::newRow("NestedParallelError1") - << TestData{storage, root1, shortLog, 5, OnDone::Failure}; + << TestData{storage, root1, log1, 5, OnDone::Failure}; QTest::newRow("NestedParallelError2") - << TestData{storage, root2, shortLog, 5, OnDone::Failure}; + << TestData{storage, root2, log2, 5, OnDone::Failure}; QTest::newRow("NestedParallelError3") - << TestData{storage, root3, longLog, 5, OnDone::Failure}; + << TestData{storage, root3, log3, 5, OnDone::Failure}; } { @@ -1071,35 +1130,31 @@ void tst_Tasking::testTree_data() parallelLimit(2), Storage(storage), Group { - Storage(TreeStorage()), - onGroupSetup(groupSetup(1)), + groupSetup(1), Group { parallel, - Test(setupTask(1)) + createSuccessTask(1) } }, Group { - Storage(TreeStorage()), - onGroupSetup(groupSetup(2)), + groupSetup(2), Group { parallel, - Test(setupTask(2)) + createSuccessTask(2) } }, Group { - Storage(TreeStorage()), - onGroupSetup(groupSetup(3)), + groupSetup(3), Group { parallel, - Test(setupTask(3)) + createSuccessTask(3) } }, Group { - Storage(TreeStorage()), - onGroupSetup(groupSetup(4)), + groupSetup(4), Group { parallel, - Test(setupTask(4)) + createSuccessTask(4) } } }; @@ -1108,10 +1163,14 @@ void tst_Tasking::testTree_data() {1, Handler::Setup}, {2, Handler::GroupSetup}, {2, Handler::Setup}, + {1, Handler::Done}, {3, Handler::GroupSetup}, {3, Handler::Setup}, + {2, Handler::Done}, {4, Handler::GroupSetup}, - {4, Handler::Setup} + {4, Handler::Setup}, + {3, Handler::Done}, + {4, Handler::Done} }; QTest::newRow("DeeplyNestedParallel") << TestData{storage, root, log, 4, OnDone::Success}; } @@ -1121,29 +1180,24 @@ void tst_Tasking::testTree_data() parallelLimit(2), Storage(storage), Group { - Storage(TreeStorage()), - onGroupSetup(groupSetup(1)), - Group { Test(setupTask(1)) } + groupSetup(1), + Group { createSuccessTask(1) } }, Group { - Storage(TreeStorage()), - onGroupSetup(groupSetup(2)), - Group { Test(setupTask(2)) } + groupSetup(2), + Group { createSuccessTask(2) } }, Group { - Storage(TreeStorage()), - onGroupSetup(groupSetup(3)), - Group { Test(setupDynamicTask(3, TaskAction::StopWithDone)) } + groupSetup(3), + Group { createDynamicTask(3, TaskAction::StopWithDone) } }, Group { - Storage(TreeStorage()), - onGroupSetup(groupSetup(4)), - Group { Test(setupTask(4)) } + groupSetup(4), + Group { createSuccessTask(4) } }, Group { - Storage(TreeStorage()), - onGroupSetup(groupSetup(5)), - Group { Test(setupTask(5)) } + groupSetup(5), + Group { createSuccessTask(5) } } }; const Log log { @@ -1151,12 +1205,16 @@ void tst_Tasking::testTree_data() {1, Handler::Setup}, {2, Handler::GroupSetup}, {2, Handler::Setup}, + {1, Handler::Done}, {3, Handler::GroupSetup}, {3, Handler::Setup}, {4, Handler::GroupSetup}, {4, Handler::Setup}, + {2, Handler::Done}, {5, Handler::GroupSetup}, - {5, Handler::Setup} + {5, Handler::Setup}, + {4, Handler::Done}, + {5, Handler::Done} }; QTest::newRow("DeeplyNestedParallelDone") << TestData{storage, root, log, 5, OnDone::Success}; @@ -1167,29 +1225,24 @@ void tst_Tasking::testTree_data() parallelLimit(2), Storage(storage), Group { - Storage(TreeStorage()), - onGroupSetup(groupSetup(1)), - Group { Test(setupTask(1)) } + groupSetup(1), + Group { createSuccessTask(1) } }, Group { - Storage(TreeStorage()), - onGroupSetup(groupSetup(2)), - Group { Test(setupTask(2)) } + groupSetup(2), + Group { createSuccessTask(2) } }, Group { - Storage(TreeStorage()), - onGroupSetup(groupSetup(3)), - Group { Test(setupDynamicTask(3, TaskAction::StopWithError)) } + groupSetup(3), + Group { createDynamicTask(3, TaskAction::StopWithError) } }, Group { - Storage(TreeStorage()), - onGroupSetup(groupSetup(4)), - Group { Test(setupTask(4)) } + groupSetup(4), + Group { createSuccessTask(4) } }, Group { - Storage(TreeStorage()), - onGroupSetup(groupSetup(5)), - Group { Test(setupTask(5)) } + groupSetup(5), + Group { createSuccessTask(5) } } }; const Log log { @@ -1197,8 +1250,10 @@ void tst_Tasking::testTree_data() {1, Handler::Setup}, {2, Handler::GroupSetup}, {2, Handler::Setup}, + {1, Handler::Done}, {3, Handler::GroupSetup}, - {3, Handler::Setup} + {3, Handler::Setup}, + {2, Handler::Error} }; QTest::newRow("DeeplyNestedParallelError") << TestData{storage, root, log, 5, OnDone::Failure}; @@ -1207,11 +1262,11 @@ void tst_Tasking::testTree_data() { const Group root { Storage(storage), - Sync(setupSync(1)), - Sync(setupSync(2)), - Sync(setupSync(3)), - Sync(setupSync(4)), - Sync(setupSync(5)) + createSync(1), + createSync(2), + createSync(3), + createSync(4), + createSync(5) }; const Log log { {1, Handler::Sync}, @@ -1226,11 +1281,11 @@ void tst_Tasking::testTree_data() { const Group root { Storage(storage), - Sync(setupSyncWithReturn(1, true)), - Sync(setupSyncWithReturn(2, true)), - Sync(setupSyncWithReturn(3, true)), - Sync(setupSyncWithReturn(4, true)), - Sync(setupSyncWithReturn(5, true)) + createSyncWithReturn(1, true), + createSyncWithReturn(2, true), + createSyncWithReturn(3, true), + createSyncWithReturn(4, true), + createSyncWithReturn(5, true) }; const Log log { {1, Handler::Sync}, @@ -1246,11 +1301,11 @@ void tst_Tasking::testTree_data() const Group root { Storage(storage), parallel, - Sync(setupSync(1)), - Sync(setupSync(2)), - Sync(setupSync(3)), - Sync(setupSync(4)), - Sync(setupSync(5)) + createSync(1), + createSync(2), + createSync(3), + createSync(4), + createSync(5) }; const Log log { {1, Handler::Sync}, @@ -1266,11 +1321,11 @@ void tst_Tasking::testTree_data() const Group root { Storage(storage), parallel, - Sync(setupSync(1)), - Sync(setupSync(2)), - Sync(setupSyncWithReturn(3, false)), - Sync(setupSync(4)), - Sync(setupSync(5)) + createSync(1), + createSync(2), + createSyncWithReturn(3, false), + createSync(4), + createSync(5) }; const Log log { {1, Handler::Sync}, @@ -1283,18 +1338,20 @@ void tst_Tasking::testTree_data() { const Group root { Storage(storage), - Sync(setupSync(1)), - Test(setupTask(2)), - Sync(setupSync(3)), - Test(setupTask(4)), - Sync(setupSync(5)), - onGroupDone(groupDone(0)) + createSync(1), + createSuccessTask(2), + createSync(3), + createSuccessTask(4), + createSync(5), + groupDone(0) }; const Log log { {1, Handler::Sync}, {2, Handler::Setup}, + {2, Handler::Done}, {3, Handler::Sync}, {4, Handler::Setup}, + {4, Handler::Done}, {5, Handler::Sync}, {0, Handler::GroupDone} }; @@ -1304,16 +1361,17 @@ void tst_Tasking::testTree_data() { const Group root { Storage(storage), - Sync(setupSync(1)), - Test(setupTask(2)), - Sync(setupSyncWithReturn(3, false)), - Test(setupTask(4)), - Sync(setupSync(5)), - onGroupError(groupError(0)) + createSync(1), + createSuccessTask(2), + createSyncWithReturn(3, false), + createSuccessTask(4), + createSync(5), + groupError(0) }; const Log log { {1, Handler::Sync}, {2, Handler::Setup}, + {2, Handler::Done}, {3, Handler::Sync}, {0, Handler::GroupError} }; @@ -1330,12 +1388,12 @@ void tst_Tasking::testTree_data() Storage(storage), Storage(barrier), sequential, - AsyncTask(setupBarrierAdvance(storage, barrier, 1)), + createBarrierAdvance(storage, barrier, 1), Group { - onGroupSetup(groupSetup(2)), + groupSetup(2), WaitForBarrierTask(barrier), - Test(setupTask(2)), - Test(setupTask(3)) + createSuccessTask(2), + createSuccessTask(3) } }; const Log log1 { @@ -1343,7 +1401,9 @@ void tst_Tasking::testTree_data() {1, Handler::BarrierAdvance}, {2, Handler::GroupSetup}, {2, Handler::Setup}, - {3, Handler::Setup} + {2, Handler::Done}, + {3, Handler::Setup}, + {3, Handler::Done} }; // Test that barrier advance, triggered from inside the task described by @@ -1353,12 +1413,12 @@ void tst_Tasking::testTree_data() Storage(storage), Storage(barrier), parallel, - AsyncTask(setupBarrierAdvance(storage, barrier, 1)), + createBarrierAdvance(storage, barrier, 1), Group { - onGroupSetup(groupSetup(2)), + groupSetup(2), WaitForBarrierTask(barrier), - Test(setupTask(2)), - Test(setupTask(3)) + createSuccessTask(2), + createSuccessTask(3) } }; const Log log2 { @@ -1366,7 +1426,9 @@ void tst_Tasking::testTree_data() {2, Handler::GroupSetup}, {1, Handler::BarrierAdvance}, {2, Handler::Setup}, - {3, Handler::Setup} + {2, Handler::Done}, + {3, Handler::Setup}, + {3, Handler::Done} }; // Test that barrier advance, triggered from inside the task described by @@ -1384,19 +1446,21 @@ void tst_Tasking::testTree_data() Storage(barrier), parallel, Group { - onGroupSetup(groupSetup(2)), + groupSetup(2), WaitForBarrierTask(barrier), - Test(setupTask(2)), - Test(setupTask(3)) + createSuccessTask(2), + createSuccessTask(3) }, - AsyncTask(setupBarrierAdvance(storage, barrier, 1)) + createBarrierAdvance(storage, barrier, 1) }; const Log log3 { {2, Handler::GroupSetup}, {1, Handler::Setup}, {1, Handler::BarrierAdvance}, {2, Handler::Setup}, - {3, Handler::Setup} + {2, Handler::Done}, + {3, Handler::Setup}, + {3, Handler::Done} }; // Test that barrier advance, triggered from inside the task described by @@ -1406,16 +1470,16 @@ void tst_Tasking::testTree_data() Storage(storage), Storage(barrier), parallel, - AsyncTask(setupBarrierAdvance(storage, barrier, 1)), + createBarrierAdvance(storage, barrier, 1), Group { - onGroupSetup(groupSetup(2)), + groupSetup(2), WaitForBarrierTask(barrier), - Test(setupTask(4)) + createSuccessTask(4) }, Group { - onGroupSetup(groupSetup(3)), + groupSetup(3), WaitForBarrierTask(barrier), - Test(setupTask(5)) + createSuccessTask(5) } }; const Log log4 { @@ -1424,7 +1488,9 @@ void tst_Tasking::testTree_data() {3, Handler::GroupSetup}, {1, Handler::BarrierAdvance}, {4, Handler::Setup}, - {5, Handler::Setup} + {5, Handler::Setup}, + {4, Handler::Done}, + {5, Handler::Done} }; // Test two separate single barriers. @@ -1436,25 +1502,26 @@ void tst_Tasking::testTree_data() Storage(barrier), Storage(barrier2), parallel, - AsyncTask(setupBarrierAdvance(storage, barrier, 0)), - AsyncTask(setupBarrierAdvance(storage, barrier2, 0)), + createBarrierAdvance(storage, barrier, 1), + createBarrierAdvance(storage, barrier2, 2), Group { Group { parallel, - onGroupSetup(groupSetup(1)), + groupSetup(1), WaitForBarrierTask(barrier), WaitForBarrierTask(barrier2) }, - Test(setupTask(2)) + createSuccessTask(3) }, }; const Log log5 { - {0, Handler::Setup}, - {0, Handler::Setup}, + {1, Handler::Setup}, + {2, Handler::Setup}, {1, Handler::GroupSetup}, - {0, Handler::BarrierAdvance}, - {0, Handler::BarrierAdvance}, - {2, Handler::Setup} + {1, Handler::BarrierAdvance}, + {2, Handler::BarrierAdvance}, + {3, Handler::Setup}, + {3, Handler::Done} }; // Notice the different log order for each scenario. @@ -1480,13 +1547,13 @@ void tst_Tasking::testTree_data() Storage(storage), Storage(barrier), sequential, - AsyncTask(setupBarrierAdvance(storage, barrier, 1)), - AsyncTask(setupBarrierAdvance(storage, barrier, 2)), + createBarrierAdvance(storage, barrier, 1), + createBarrierAdvance(storage, barrier, 2), Group { - onGroupSetup(groupSetup(2)), + groupSetup(2), WaitForBarrierTask(barrier), - Test(setupTask(2)), - Test(setupTask(3)) + createSuccessTask(2), + createSuccessTask(3) } }; const Log log1 { @@ -1496,7 +1563,9 @@ void tst_Tasking::testTree_data() {2, Handler::BarrierAdvance}, {2, Handler::GroupSetup}, {2, Handler::Setup}, - {3, Handler::Setup} + {2, Handler::Done}, + {3, Handler::Setup}, + {3, Handler::Done} }; // Test that multi barrier advance, triggered from inside the tasks described by @@ -1506,23 +1575,25 @@ void tst_Tasking::testTree_data() Storage(storage), Storage(barrier), parallel, - AsyncTask(setupBarrierAdvance(storage, barrier, 0)), - AsyncTask(setupBarrierAdvance(storage, barrier, 0)), + createBarrierAdvance(storage, barrier, 1), + createBarrierAdvance(storage, barrier, 2), Group { - onGroupSetup(groupSetup(2)), + groupSetup(2), WaitForBarrierTask(barrier), - Test(setupTask(2)), - Test(setupTask(3)) + createSuccessTask(3), + createSuccessTask(4) } }; const Log log2 { - {0, Handler::Setup}, - {0, Handler::Setup}, - {2, Handler::GroupSetup}, - {0, Handler::BarrierAdvance}, // Barrier advances may come in different order in - {0, Handler::BarrierAdvance}, // parallel mode, that's why id = 0 (same for both). + {1, Handler::Setup}, {2, Handler::Setup}, - {3, Handler::Setup} + {2, Handler::GroupSetup}, + {1, Handler::BarrierAdvance}, + {2, Handler::BarrierAdvance}, + {3, Handler::Setup}, + {3, Handler::Done}, + {4, Handler::Setup}, + {4, Handler::Done} }; // Test that multi barrier advance, triggered from inside the tasks described by @@ -1540,22 +1611,24 @@ void tst_Tasking::testTree_data() Storage(barrier), parallel, Group { - onGroupSetup(groupSetup(2)), + groupSetup(2), WaitForBarrierTask(barrier), - Test(setupTask(2)), - Test(setupTask(3)) + createSuccessTask(3), + createSuccessTask(4) }, - AsyncTask(setupBarrierAdvance(storage, barrier, 0)), - AsyncTask(setupBarrierAdvance(storage, barrier, 0)) + createBarrierAdvance(storage, barrier, 1), + createBarrierAdvance(storage, barrier, 2) }; const Log log3 { {2, Handler::GroupSetup}, - {0, Handler::Setup}, - {0, Handler::Setup}, - {0, Handler::BarrierAdvance}, // Barrier advances may come in different order in - {0, Handler::BarrierAdvance}, // parallel mode, that's why id = 0 (same for both). + {1, Handler::Setup}, {2, Handler::Setup}, - {3, Handler::Setup} + {1, Handler::BarrierAdvance}, + {2, Handler::BarrierAdvance}, + {3, Handler::Setup}, + {3, Handler::Done}, + {4, Handler::Setup}, + {4, Handler::Done} }; // Test that multi barrier advance, triggered from inside the task described by @@ -1565,28 +1638,30 @@ void tst_Tasking::testTree_data() Storage(storage), Storage(barrier), parallel, - AsyncTask(setupBarrierAdvance(storage, barrier, 0)), - AsyncTask(setupBarrierAdvance(storage, barrier, 0)), + createBarrierAdvance(storage, barrier, 1), + createBarrierAdvance(storage, barrier, 2), Group { - onGroupSetup(groupSetup(2)), + groupSetup(2), WaitForBarrierTask(barrier), - Test(setupTask(4)) + createSuccessTask(3) }, Group { - onGroupSetup(groupSetup(3)), + groupSetup(3), WaitForBarrierTask(barrier), - Test(setupTask(5)) + createSuccessTask(4) } }; const Log log4 { - {0, Handler::Setup}, - {0, Handler::Setup}, + {1, Handler::Setup}, + {2, Handler::Setup}, {2, Handler::GroupSetup}, {3, Handler::GroupSetup}, - {0, Handler::BarrierAdvance}, - {0, Handler::BarrierAdvance}, + {1, Handler::BarrierAdvance}, + {2, Handler::BarrierAdvance}, + {3, Handler::Setup}, {4, Handler::Setup}, - {5, Handler::Setup} + {3, Handler::Done}, + {4, Handler::Done} }; // Notice the different log order for each scenario. @@ -1648,12 +1723,12 @@ void tst_Tasking::storageDestructor() QCOMPARE(CustomStorage::instanceCount(), 0); { TreeStorage storage; - const auto setupSleepingTask = [](TestTask &task) { - task.setConcurrentCallData(runTask, true, 1000ms); + const auto setupSleepingTask = [](TaskObject &taskObject) { + taskObject = 1000ms; }; const Group root { Storage(storage), - Test(setupSleepingTask) + SuccessTask(setupSleepingTask) }; TaskTree taskTree(root); @@ -1662,7 +1737,6 @@ void tst_Tasking::storageDestructor() taskTree.onStorageDone(storage, doneHandler); taskTree.start(); QCOMPARE(CustomStorage::instanceCount(), 1); - QThread::msleep(5); // Give the sleeping task a change to start } QCOMPARE(CustomStorage::instanceCount(), 0); QVERIFY(setupCalled); From cbca40401b62556753d12a354b80748c5d3d72cd Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Sun, 28 May 2023 12:42:05 +0200 Subject: [PATCH 017/141] TaskTree: Fix calling the proper group handler on stop Add tests for it. Change-Id: Ibb04b21c217196c9bbf6761851f4e1a300139a8c Reviewed-by: Marcus Tillmanns Reviewed-by: Qt CI Bot --- src/libs/solutions/tasking/tasktree.cpp | 1 + tests/auto/solutions/tasking/tst_tasking.cpp | 370 +++++++++++++++++++ 2 files changed, 371 insertions(+) diff --git a/src/libs/solutions/tasking/tasktree.cpp b/src/libs/solutions/tasking/tasktree.cpp index 071190dd9eb..a3fb9347bbb 100644 --- a/src/libs/solutions/tasking/tasktree.cpp +++ b/src/libs/solutions/tasking/tasktree.cpp @@ -893,6 +893,7 @@ void TaskNode::stop() if (!m_task) { m_container.stop(); + m_container.m_runtimeData->updateSuccessBit(false); m_container.invokeEndHandler(); return; } diff --git a/tests/auto/solutions/tasking/tst_tasking.cpp b/tests/auto/solutions/tasking/tst_tasking.cpp index e3f7a80ed5b..e86c135066c 100644 --- a/tests/auto/solutions/tasking/tst_tasking.cpp +++ b/tests/auto/solutions/tasking/tst_tasking.cpp @@ -738,6 +738,376 @@ void tst_Tasking::testTree_data() QTest::newRow("ErrorOptional") << TestData{storage, root6, optionalLog, 1, OnDone::Success}; } + { + // These tests check whether the proper root's group end handler is called + // when the group is stopped. Test it with different workflow policies. + // The root starts one short failing task together with one long task. + const auto createRoot = [storage, createSuccessTask, createFailingTask, groupDone, + groupError](WorkflowPolicy policy) { + return Group { + Storage(storage), + parallel, + workflowPolicy(policy), + createFailingTask(1, 1ms), + createSuccessTask(2, 2ms), + groupDone(0), + groupError(0) + }; + }; + + const Log errorErrorLog = { + {1, Handler::Setup}, + {2, Handler::Setup}, + {1, Handler::Error}, + {2, Handler::Error}, + {0, Handler::GroupError} + }; + + const Log errorDoneLog = { + {1, Handler::Setup}, + {2, Handler::Setup}, + {1, Handler::Error}, + {2, Handler::Done}, + {0, Handler::GroupError} + }; + + const Log doneLog = { + {1, Handler::Setup}, + {2, Handler::Setup}, + {1, Handler::Error}, + {2, Handler::Done}, + {0, Handler::GroupDone} + }; + + const Group root1 = createRoot(WorkflowPolicy::StopOnError); + QTest::newRow("StopRootWithStopOnError") + << TestData{storage, root1, errorErrorLog, 2, OnDone::Failure}; + + const Group root2 = createRoot(WorkflowPolicy::ContinueOnError); + QTest::newRow("StopRootWithContinueOnError") + << TestData{storage, root2, errorDoneLog, 2, OnDone::Failure}; + + const Group root3 = createRoot(WorkflowPolicy::StopOnDone); + QTest::newRow("StopRootWithStopOnDone") + << TestData{storage, root3, doneLog, 2, OnDone::Success}; + + const Group root4 = createRoot(WorkflowPolicy::ContinueOnDone); + QTest::newRow("StopRootWithContinueOnDone") + << TestData{storage, root4, doneLog, 2, OnDone::Success}; + + const Group root5 = createRoot(WorkflowPolicy::StopOnFinished); + QTest::newRow("StopRootWithStopOnFinished") + << TestData{storage, root5, errorErrorLog, 2, OnDone::Failure}; + + const Group root6 = createRoot(WorkflowPolicy::Optional); + QTest::newRow("StopRootWithOptional") + << TestData{storage, root6, doneLog, 2, OnDone::Success}; + } + + { + // These tests check whether the proper root's group end handler is called + // when the group is stopped. Test it with different workflow policies. + // The root starts in parallel: one very short successful task, one short failing task + // and one long task. + const auto createRoot = [storage, createSuccessTask, createFailingTask, groupDone, + groupError](WorkflowPolicy policy) { + return Group { + Storage(storage), + parallel, + workflowPolicy(policy), + createSuccessTask(1), + createFailingTask(2, 1ms), + createSuccessTask(3, 2ms), + groupDone(0), + groupError(0) + }; + }; + + const Log errorErrorLog = { + {1, Handler::Setup}, + {2, Handler::Setup}, + {3, Handler::Setup}, + {1, Handler::Done}, + {2, Handler::Error}, + {3, Handler::Error}, + {0, Handler::GroupError} + }; + + const Log errorDoneLog = { + {1, Handler::Setup}, + {2, Handler::Setup}, + {3, Handler::Setup}, + {1, Handler::Done}, + {2, Handler::Error}, + {3, Handler::Done}, + {0, Handler::GroupError} + }; + + const Log doneErrorLog = { + {1, Handler::Setup}, + {2, Handler::Setup}, + {3, Handler::Setup}, + {1, Handler::Done}, + {2, Handler::Error}, + {3, Handler::Error}, + {0, Handler::GroupDone} + }; + + const Log doneDoneLog = { + {1, Handler::Setup}, + {2, Handler::Setup}, + {3, Handler::Setup}, + {1, Handler::Done}, + {2, Handler::Error}, + {3, Handler::Done}, + {0, Handler::GroupDone} + }; + + const Group root1 = createRoot(WorkflowPolicy::StopOnError); + QTest::newRow("StopRootAfterDoneWithStopOnError") + << TestData{storage, root1, errorErrorLog, 3, OnDone::Failure}; + + const Group root2 = createRoot(WorkflowPolicy::ContinueOnError); + QTest::newRow("StopRootAfterDoneWithContinueOnError") + << TestData{storage, root2, errorDoneLog, 3, OnDone::Failure}; + + const Group root3 = createRoot(WorkflowPolicy::StopOnDone); + QTest::newRow("StopRootAfterDoneWithStopOnDone") + << TestData{storage, root3, doneErrorLog, 3, OnDone::Success}; + + const Group root4 = createRoot(WorkflowPolicy::ContinueOnDone); + QTest::newRow("StopRootAfterDoneWithContinueOnDone") + << TestData{storage, root4, doneDoneLog, 3, OnDone::Success}; + + const Group root5 = createRoot(WorkflowPolicy::StopOnFinished); + QTest::newRow("StopRootAfterDoneWithStopOnFinished") + << TestData{storage, root5, doneErrorLog, 3, OnDone::Success}; + + const Group root6 = createRoot(WorkflowPolicy::Optional); + QTest::newRow("StopRootAfterDoneWithOptional") + << TestData{storage, root6, doneDoneLog, 3, OnDone::Success}; + } + + { + // These tests check whether the proper subgroup's end handler is called + // when the group is stopped. Test it with different workflow policies. + // The subgroup starts one long task. + const auto createRoot = [storage, createSuccessTask, createFailingTask, groupDone, + groupError](WorkflowPolicy policy) { + return Group { + Storage(storage), + parallel, + Group { + workflowPolicy(policy), + createSuccessTask(1, 1000ms), + groupDone(1), + groupError(1) + }, + createFailingTask(2, 1ms), + groupDone(2), + groupError(2) + }; + }; + + const Log errorLog = { + {1, Handler::Setup}, + {2, Handler::Setup}, + {2, Handler::Error}, + {1, Handler::Error}, + {1, Handler::GroupError}, + {2, Handler::GroupError} + }; + + const Log doneLog = { + {1, Handler::Setup}, + {2, Handler::Setup}, + {2, Handler::Error}, + {1, Handler::Error}, + {1, Handler::GroupDone}, + {2, Handler::GroupError} + }; + + const Group root1 = createRoot(WorkflowPolicy::StopOnError); + QTest::newRow("StopGroupWithStopOnError") + << TestData{storage, root1, errorLog, 2, OnDone::Failure}; + + const Group root2 = createRoot(WorkflowPolicy::ContinueOnError); + QTest::newRow("StopGroupWithContinueOnError") + << TestData{storage, root2, errorLog, 2, OnDone::Failure}; + + const Group root3 = createRoot(WorkflowPolicy::StopOnDone); + QTest::newRow("StopGroupWithStopOnDone") + << TestData{storage, root3, errorLog, 2, OnDone::Failure}; + + const Group root4 = createRoot(WorkflowPolicy::ContinueOnDone); + QTest::newRow("StopGroupWithContinueOnDone") + << TestData{storage, root4, errorLog, 2, OnDone::Failure}; + + const Group root5 = createRoot(WorkflowPolicy::StopOnFinished); + QTest::newRow("StopGroupWithStopOnFinished") + << TestData{storage, root5, errorLog, 2, OnDone::Failure}; + + const Group root6 = createRoot(WorkflowPolicy::Optional); + QTest::newRow("StopGroupWithOptional") + << TestData{storage, root6, doneLog, 2, OnDone::Failure}; + } + + { + // These tests check whether the proper subgroup's end handler is called + // when the group is stopped. Test it with different workflow policies. + // The sequential subgroup starts one short successful task followed by one long task. + const auto createRoot = [storage, createSuccessTask, createFailingTask, groupDone, + groupError](WorkflowPolicy policy) { + return Group { + Storage(storage), + parallel, + Group { + workflowPolicy(policy), + createSuccessTask(1), + createSuccessTask(2, 1000ms), + groupDone(1), + groupError(1) + }, + createFailingTask(3, 1ms), + groupDone(2), + groupError(2) + }; + }; + + const Log errorLog = { + {1, Handler::Setup}, + {3, Handler::Setup}, + {1, Handler::Done}, + {2, Handler::Setup}, + {3, Handler::Error}, + {2, Handler::Error}, + {1, Handler::GroupError}, + {2, Handler::GroupError} + }; + + const Log shortDoneLog = { + {1, Handler::Setup}, + {3, Handler::Setup}, + {1, Handler::Done}, + {1, Handler::GroupDone}, + {3, Handler::Error}, + {2, Handler::GroupError} + }; + + const Log longDoneLog = { + {1, Handler::Setup}, + {3, Handler::Setup}, + {1, Handler::Done}, + {2, Handler::Setup}, + {3, Handler::Error}, + {2, Handler::Error}, + {1, Handler::GroupDone}, + {2, Handler::GroupError} + }; + + const Group root1 = createRoot(WorkflowPolicy::StopOnError); + QTest::newRow("StopGroupAfterDoneWithStopOnError") + << TestData{storage, root1, errorLog, 3, OnDone::Failure}; + + const Group root2 = createRoot(WorkflowPolicy::ContinueOnError); + QTest::newRow("StopGroupAfterDoneWithContinueOnError") + << TestData{storage, root2, errorLog, 3, OnDone::Failure}; + + const Group root3 = createRoot(WorkflowPolicy::StopOnDone); + QTest::newRow("StopGroupAfterDoneWithStopOnDone") + << TestData{storage, root3, shortDoneLog, 3, OnDone::Failure}; + + const Group root4 = createRoot(WorkflowPolicy::ContinueOnDone); + QTest::newRow("StopGroupAfterDoneWithContinueOnDone") + << TestData{storage, root4, longDoneLog, 3, OnDone::Failure}; + + const Group root5 = createRoot(WorkflowPolicy::StopOnFinished); + QTest::newRow("StopGroupAfterDoneWithStopOnFinished") + << TestData{storage, root5, shortDoneLog, 3, OnDone::Failure}; + + const Group root6 = createRoot(WorkflowPolicy::Optional); + QTest::newRow("StopGroupAfterDoneWithOptional") + << TestData{storage, root6, longDoneLog, 3, OnDone::Failure}; + } + + { + // These tests check whether the proper subgroup's end handler is called + // when the group is stopped. Test it with different workflow policies. + // The sequential subgroup starts one short failing task followed by one long task. + const auto createRoot = [storage, createSuccessTask, createFailingTask, groupDone, + groupError](WorkflowPolicy policy) { + return Group { + Storage(storage), + parallel, + Group { + workflowPolicy(policy), + createFailingTask(1), + createSuccessTask(2, 1000ms), + groupDone(1), + groupError(1) + }, + createFailingTask(3, 1ms), + groupDone(2), + groupError(2) + }; + }; + + const Log shortErrorLog = { + {1, Handler::Setup}, + {3, Handler::Setup}, + {1, Handler::Error}, + {1, Handler::GroupError}, + {3, Handler::Error}, + {2, Handler::GroupError} + }; + + const Log longErrorLog = { + {1, Handler::Setup}, + {3, Handler::Setup}, + {1, Handler::Error}, + {2, Handler::Setup}, + {3, Handler::Error}, + {2, Handler::Error}, + {1, Handler::GroupError}, + {2, Handler::GroupError} + }; + + const Log doneLog = { + {1, Handler::Setup}, + {3, Handler::Setup}, + {1, Handler::Error}, + {2, Handler::Setup}, + {3, Handler::Error}, + {2, Handler::Error}, + {1, Handler::GroupDone}, + {2, Handler::GroupError} + }; + + const Group root1 = createRoot(WorkflowPolicy::StopOnError); + QTest::newRow("StopGroupAfterErrorWithStopOnError") + << TestData{storage, root1, shortErrorLog, 3, OnDone::Failure}; + + const Group root2 = createRoot(WorkflowPolicy::ContinueOnError); + QTest::newRow("StopGroupAfterErrorWithContinueOnError") + << TestData{storage, root2, longErrorLog, 3, OnDone::Failure}; + + const Group root3 = createRoot(WorkflowPolicy::StopOnDone); + QTest::newRow("StopGroupAfterErrorWithStopOnDone") + << TestData{storage, root3, longErrorLog, 3, OnDone::Failure}; + + const Group root4 = createRoot(WorkflowPolicy::ContinueOnDone); + QTest::newRow("StopGroupAfterErrorWithContinueOnDone") + << TestData{storage, root4, longErrorLog, 3, OnDone::Failure}; + + const Group root5 = createRoot(WorkflowPolicy::StopOnFinished); + QTest::newRow("StopGroupAfterErrorWithStopOnFinished") + << TestData{storage, root5, shortErrorLog, 3, OnDone::Failure}; + + const Group root6 = createRoot(WorkflowPolicy::Optional); + QTest::newRow("StopGroupAfterErrorWithOptional") + << TestData{storage, root6, doneLog, 3, OnDone::Failure}; + } + { const auto createRoot = [storage, createSuccessTask, createFailingTask, groupDone, groupError](WorkflowPolicy policy) { From ffdb0c7dcc958aaba17abf127923e4dfe02604d3 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Fri, 26 May 2023 19:44:17 +0200 Subject: [PATCH 018/141] TaskTree: Some corrections to the copy example Use QString instead of FilePath. Rename the diffRecipe into copyRecipe. Add some code that constructs the tree, connects to its done signal and starts the tree. Change-Id: I40e1c4784c736347682071b3e3e99db599ce102a Reviewed-by: hjk Reviewed-by: Qt CI Bot --- src/libs/solutions/tasking/tasktree.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/libs/solutions/tasking/tasktree.cpp b/src/libs/solutions/tasking/tasktree.cpp index a3fb9347bbb..540342ac8ff 100644 --- a/src/libs/solutions/tasking/tasktree.cpp +++ b/src/libs/solutions/tasking/tasktree.cpp @@ -1412,10 +1412,10 @@ void TaskNode::invokeEndHandler(bool success) 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 QByteArray load(const QString &fileName) { ... } + static void save(const QString &fileName, const QByteArray &array) { ... } - static TaskItem diffRecipe(const FilePath &source, const FilePath &destination) + static TaskItem copyRecipe(const QString &source, const QString &destination) { struct CopyStorage { // [1] custom inter-task struct QByteArray content; // [2] custom inter-task data @@ -1449,6 +1449,13 @@ void TaskNode::invokeEndHandler(bool success) }; return root; } + + const QString source = ...; + const QString destination = ...; + TaskTree taskTree(copyRecipe(source, destination)); + connect(&taskTree, &TaskTree::done, + &taskTree, [] { qDebug() << "The copying finished successfully."; }); + tasktree.start(); \endcode In the example above, the inter-task data consists of a QByteArray content From 4e01ca18d10b839636c1d60c0520816526d92a7f Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Sun, 28 May 2023 17:20:55 +0200 Subject: [PATCH 019/141] TaskTree: Rename optional into finishAllAndDone Rationale: 1. More descriptive. 2. More consistent with a planned new finishAllAndError policy. 3. Limits the possibilities of making a conflict with std::optional. Change-Id: I5155630188e4b699e6c18b13a101e0e2d4fe98f2 Reviewed-by: Qt CI Bot Reviewed-by: Reviewed-by: hjk --- src/libs/solutions/tasking/tasktree.cpp | 8 ++++---- src/libs/solutions/tasking/tasktree.h | 16 ++++++++-------- src/plugins/autotest/testrunner.cpp | 4 ++-- src/plugins/clangtools/clangtoolrunner.cpp | 2 +- .../clangtools/documentclangtoolrunner.cpp | 2 +- .../coreplugin/locator/ilocatorfilter.cpp | 2 +- src/plugins/coreplugin/locator/locator.cpp | 2 +- src/plugins/diffeditor/diffeditorplugin.cpp | 2 +- src/plugins/git/gitclient.cpp | 4 ++-- src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp | 4 ++-- .../remotelinux/genericdirectuploadstep.cpp | 4 ++-- src/plugins/remotelinux/linuxdevicetester.cpp | 4 ++-- src/plugins/subversion/subversionclient.cpp | 2 +- tests/auto/solutions/tasking/tst_tasking.cpp | 18 +++++++++--------- tests/manual/tasktree/main.cpp | 2 +- tests/manual/tasktree/taskwidget.cpp | 2 +- 16 files changed, 39 insertions(+), 39 deletions(-) diff --git a/src/libs/solutions/tasking/tasktree.cpp b/src/libs/solutions/tasking/tasktree.cpp index 540342ac8ff..054647752af 100644 --- a/src/libs/solutions/tasking/tasktree.cpp +++ b/src/libs/solutions/tasking/tasktree.cpp @@ -164,7 +164,7 @@ private: Constructs a group's element holding the group done handler. The \a handler is invoked whenever the group finishes with success. Depending on the group's workflow policy, this handler may also be called - when the running group is stopped (e.g. when optional element was used). + when the running group is stopped (e.g. when finishAllAndDone element was used). When the \a handler is invoked, all of the group's child tasks are already finished. @@ -256,7 +256,7 @@ const TaskItem continueOnError = workflowPolicy(WorkflowPolicy::ContinueOnError) const TaskItem stopOnDone = workflowPolicy(WorkflowPolicy::StopOnDone); const TaskItem continueOnDone = workflowPolicy(WorkflowPolicy::ContinueOnDone); const TaskItem stopOnFinished = workflowPolicy(WorkflowPolicy::StopOnFinished); -const TaskItem optional = workflowPolicy(WorkflowPolicy::Optional); +const TaskItem finishAllAndDone = workflowPolicy(WorkflowPolicy::FinishAllAndDone); static TaskAction toTaskAction(bool success) { @@ -720,7 +720,7 @@ TaskContainer::RuntimeData::~RuntimeData() bool TaskContainer::RuntimeData::updateSuccessBit(bool success) { - if (m_constData.m_workflowPolicy == WorkflowPolicy::Optional) + if (m_constData.m_workflowPolicy == WorkflowPolicy::FinishAllAndDone) return m_successBit; if (m_constData.m_workflowPolicy == WorkflowPolicy::StopOnFinished) { m_successBit = success; @@ -1394,7 +1394,7 @@ void TaskNode::invokeEndHandler(bool success) 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 finishAllAndDone \li The group executes all tasks and ignores their return state. When all tasks finish, the group finishes with success. \endtable diff --git a/src/libs/solutions/tasking/tasktree.h b/src/libs/solutions/tasking/tasktree.h index 1754e092631..872bce2ed86 100644 --- a/src/libs/solutions/tasking/tasktree.h +++ b/src/libs/solutions/tasking/tasktree.h @@ -99,15 +99,15 @@ private: // b) On first done - continue executing all children and report done afterwards. // 3. Stops on first finished child. In sequential mode it will never run other children then the first one. // Useful only in parallel mode. -// 4. Always run all children, ignore their result and report done afterwards. +// 4. Always run all children, let them finish, ignore their results and report done afterwards. enum class WorkflowPolicy { - StopOnError, // 1a - Reports error on first child error, otherwise done (if all children were done). - ContinueOnError, // 1b - The same, but children execution continues. Reports done when no children. - StopOnDone, // 2a - Reports done on first child done, otherwise error (if all children were error). - ContinueOnDone, // 2b - The same, but children execution continues. Reports error when no children. - StopOnFinished, // 3 - Stops on first finished child and report its result. - Optional // 4 - Reports done after all children finished. + StopOnError, // 1a - Reports error on first child error, otherwise done (if all children were done). + ContinueOnError, // 1b - The same, but children execution continues. Reports done when no children. + StopOnDone, // 2a - Reports done on first child done, otherwise error (if all children were error). + ContinueOnDone, // 2b - The same, but children execution continues. Reports error when no children. + StopOnFinished, // 3 - Stops on first finished child and report its result. + FinishAllAndDone // 4 - Reports done after all children finished. }; enum class TaskAction @@ -248,7 +248,7 @@ TASKING_EXPORT extern const TaskItem continueOnError; TASKING_EXPORT extern const TaskItem stopOnDone; TASKING_EXPORT extern const TaskItem continueOnDone; TASKING_EXPORT extern const TaskItem stopOnFinished; -TASKING_EXPORT extern const TaskItem optional; +TASKING_EXPORT extern const TaskItem finishAllAndDone; class TASKING_EXPORT Storage : public TaskItem { diff --git a/src/plugins/autotest/testrunner.cpp b/src/plugins/autotest/testrunner.cpp index 206dca8da41..5c53d742e65 100644 --- a/src/plugins/autotest/testrunner.cpp +++ b/src/plugins/autotest/testrunner.cpp @@ -347,7 +347,7 @@ void TestRunner::runTestsHelper() std::unique_ptr m_outputReader; }; - QList tasks{optional}; + QList tasks{finishAllAndDone}; for (ITestConfiguration *config : m_selectedTests) { QTC_ASSERT(config, continue); @@ -442,7 +442,7 @@ void TestRunner::runTestsHelper() } }; const Group group { - optional, + finishAllAndDone, Storage(storage), onGroupSetup(onSetup), ProcessTask(onProcessSetup, onProcessDone, onProcessDone) diff --git a/src/plugins/clangtools/clangtoolrunner.cpp b/src/plugins/clangtools/clangtoolrunner.cpp index 40cbf75d47e..3e2c7a6c111 100644 --- a/src/plugins/clangtools/clangtoolrunner.cpp +++ b/src/plugins/clangtools/clangtoolrunner.cpp @@ -186,7 +186,7 @@ TaskItem clangToolTask(const AnalyzeInputData &input, Storage(storage), onGroupSetup(onSetup), Group { - optional, + finishAllAndDone, ProcessTask(onProcessSetup, onProcessDone, onProcessError) } }; diff --git a/src/plugins/clangtools/documentclangtoolrunner.cpp b/src/plugins/clangtools/documentclangtoolrunner.cpp index 178022a91a6..3de2c6d55cf 100644 --- a/src/plugins/clangtools/documentclangtoolrunner.cpp +++ b/src/plugins/clangtools/documentclangtoolrunner.cpp @@ -209,7 +209,7 @@ void DocumentClangToolRunner::run() return !m_document->isModified() || isVFSOverlaySupported(executable); }; const auto outputHandler = [this](const AnalyzeOutputData &output) { onDone(output); }; - tasks.append(Group{optional, clangToolTask(input, setupHandler, outputHandler)}); + tasks.append(Group{finishAllAndDone, clangToolTask(input, setupHandler, outputHandler)}); }; addClangTool(ClangToolType::Tidy); addClangTool(ClangToolType::Clazy); diff --git a/src/plugins/coreplugin/locator/ilocatorfilter.cpp b/src/plugins/coreplugin/locator/ilocatorfilter.cpp index f6b39996d8f..3a84a0b548b 100644 --- a/src/plugins/coreplugin/locator/ilocatorfilter.cpp +++ b/src/plugins/coreplugin/locator/ilocatorfilter.cpp @@ -470,7 +470,7 @@ void LocatorMatcher::start() for (const LocatorMatcherTask &task : std::as_const(d->m_tasks)) { const auto storage = task.storage; const Group group { - optional, + finishAllAndDone, Storage(storage), onGroupSetup(onSetup(storage, index)), onGroupDone(onDone(storage)), diff --git a/src/plugins/coreplugin/locator/locator.cpp b/src/plugins/coreplugin/locator/locator.cpp index 55b82920329..2deaef9fe09 100644 --- a/src/plugins/coreplugin/locator/locator.cpp +++ b/src/plugins/coreplugin/locator/locator.cpp @@ -388,7 +388,7 @@ void Locator::refresh(const QList &filters) continue; const Group group { - optional, + finishAllAndDone, *task, onGroupDone([this, filter] { m_refreshingFilters.removeOne(filter); }) }; diff --git a/src/plugins/diffeditor/diffeditorplugin.cpp b/src/plugins/diffeditor/diffeditorplugin.cpp index fe4c4f9a6a5..99ceef2f0ab 100644 --- a/src/plugins/diffeditor/diffeditorplugin.cpp +++ b/src/plugins/diffeditor/diffeditorplugin.cpp @@ -128,7 +128,7 @@ DiffFilesController::DiffFilesController(IDocument *document) outputList->resize(inputList.size()); using namespace std::placeholders; - QList tasks {parallel, optional}; + QList tasks {parallel, finishAllAndDone}; for (int i = 0; i < inputList.size(); ++i) { tasks.append(AsyncTask(std::bind(setupDiff, _1, inputList.at(i)), std::bind(onDiffDone, _1, i))); diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index f0427e08268..dd335dcc650 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -465,11 +465,11 @@ ShowController::ShowController(IDocument *document, const QString &id) parallel, onGroupSetup([this] { setStartupFile(VcsBase::source(this->document()).toString()); }), Group { - optional, + finishAllAndDone, ProcessTask(setupDescription, onDescriptionDone), Group { parallel, - optional, + finishAllAndDone, onGroupSetup(desciptionDetailsSetup), ProcessTask(setupBranches, onBranchesDone, onBranchesError), ProcessTask(setupPrecedes, onPrecedesDone, onPrecedesError), diff --git a/src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp b/src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp index 0b6e74dca8b..a5cc9cdad86 100644 --- a/src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp +++ b/src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp @@ -223,7 +223,7 @@ TaskItem QnxDeployQtLibrariesDialogPrivate::chmodTree() if (file.isExecutable()) filesToChmod << file; } - QList chmodList{optional, parallelLimit(MaxConcurrentStatCalls)}; + QList chmodList{finishAllAndDone, parallelLimit(MaxConcurrentStatCalls)}; for (const DeployableFile &file : std::as_const(filesToChmod)) { QTC_ASSERT(file.isValid(), continue); chmodList.append(chmodTask(file)); @@ -263,7 +263,7 @@ Group QnxDeployQtLibrariesDialogPrivate::deployRecipe() const Group root { onGroupSetup(setupHandler), Group { - optional, + finishAllAndDone, checkDirTask() }, Group { diff --git a/src/plugins/remotelinux/genericdirectuploadstep.cpp b/src/plugins/remotelinux/genericdirectuploadstep.cpp index 9179ac87519..6074eaabaaf 100644 --- a/src/plugins/remotelinux/genericdirectuploadstep.cpp +++ b/src/plugins/remotelinux/genericdirectuploadstep.cpp @@ -179,7 +179,7 @@ TaskItem GenericDirectUploadStep::statTree(const TreeStorage &sto const auto setupHandler = [=](TaskTree &tree) { UploadStorage *storagePtr = storage.activeStorage(); const QList files = filesToStat(storagePtr); - QList statList{optional, parallelLimit(MaxConcurrentStatCalls)}; + QList statList{finishAllAndDone, parallelLimit(MaxConcurrentStatCalls)}; for (const DeployableFile &file : std::as_const(files)) { QTC_ASSERT(file.isValid(), continue); statList.append(statTask(storagePtr, file, statEndHandler)); @@ -256,7 +256,7 @@ TaskItem GenericDirectUploadStep::chmodTree(const TreeStorage &st if (file.isExecutable()) filesToChmod << file; } - QList chmodList{optional, parallelLimit(MaxConcurrentStatCalls)}; + QList chmodList{finishAllAndDone, parallelLimit(MaxConcurrentStatCalls)}; for (const DeployableFile &file : std::as_const(filesToChmod)) { QTC_ASSERT(file.isValid(), continue); chmodList.append(chmodTask(file)); diff --git a/src/plugins/remotelinux/linuxdevicetester.cpp b/src/plugins/remotelinux/linuxdevicetester.cpp index ecb4296262d..37aea361123 100644 --- a/src/plugins/remotelinux/linuxdevicetester.cpp +++ b/src/plugins/remotelinux/linuxdevicetester.cpp @@ -131,7 +131,7 @@ TaskItem GenericLinuxDeviceTesterPrivate::unameTask() const emit q->errorMessage(Tr::tr("uname failed.") + '\n'); }; return Group { - optional, + finishAllAndDone, ProcessTask(setup, done, error) }; } @@ -159,7 +159,7 @@ TaskItem GenericLinuxDeviceTesterPrivate::gathererTask() const }; return Group { - optional, + finishAllAndDone, DeviceUsedPortsGathererTask(setup, done, error) }; } diff --git a/src/plugins/subversion/subversionclient.cpp b/src/plugins/subversion/subversionclient.cpp index 3146f066d6e..ac664a69b88 100644 --- a/src/plugins/subversion/subversionclient.cpp +++ b/src/plugins/subversion/subversionclient.cpp @@ -204,7 +204,7 @@ SubversionDiffEditorController::SubversionDiffEditorController(IDocument *docume Storage(diffInputStorage), parallel, Group { - optional, + finishAllAndDone, ProcessTask(setupDescription, onDescriptionDone, onDescriptionError) }, Group { diff --git a/tests/auto/solutions/tasking/tst_tasking.cpp b/tests/auto/solutions/tasking/tst_tasking.cpp index e86c135066c..9ddcbc0cbde 100644 --- a/tests/auto/solutions/tasking/tst_tasking.cpp +++ b/tests/auto/solutions/tasking/tst_tasking.cpp @@ -654,7 +654,7 @@ void tst_Tasking::testTree_data() const Group root5 = createRoot(WorkflowPolicy::StopOnFinished); QTest::newRow("EmptyStopOnFinished") << TestData{storage, root5, log, 0, OnDone::Success}; - const Group root6 = createRoot(WorkflowPolicy::Optional); + const Group root6 = createRoot(WorkflowPolicy::FinishAllAndDone); QTest::newRow("EmptyOptional") << TestData{storage, root6, log, 0, OnDone::Success}; } @@ -691,7 +691,7 @@ void tst_Tasking::testTree_data() const Group root5 = createRoot(WorkflowPolicy::StopOnFinished); QTest::newRow("DoneStopOnFinished") << TestData{storage, root5, log, 1, OnDone::Success}; - const Group root6 = createRoot(WorkflowPolicy::Optional); + const Group root6 = createRoot(WorkflowPolicy::FinishAllAndDone); QTest::newRow("DoneOptional") << TestData{storage, root6, log, 1, OnDone::Success}; } @@ -734,7 +734,7 @@ void tst_Tasking::testTree_data() const Group root5 = createRoot(WorkflowPolicy::StopOnFinished); QTest::newRow("ErrorStopOnFinished") << TestData{storage, root5, log, 1, OnDone::Failure}; - const Group root6 = createRoot(WorkflowPolicy::Optional); + const Group root6 = createRoot(WorkflowPolicy::FinishAllAndDone); QTest::newRow("ErrorOptional") << TestData{storage, root6, optionalLog, 1, OnDone::Success}; } @@ -799,7 +799,7 @@ void tst_Tasking::testTree_data() QTest::newRow("StopRootWithStopOnFinished") << TestData{storage, root5, errorErrorLog, 2, OnDone::Failure}; - const Group root6 = createRoot(WorkflowPolicy::Optional); + const Group root6 = createRoot(WorkflowPolicy::FinishAllAndDone); QTest::newRow("StopRootWithOptional") << TestData{storage, root6, doneLog, 2, OnDone::Success}; } @@ -883,7 +883,7 @@ void tst_Tasking::testTree_data() QTest::newRow("StopRootAfterDoneWithStopOnFinished") << TestData{storage, root5, doneErrorLog, 3, OnDone::Success}; - const Group root6 = createRoot(WorkflowPolicy::Optional); + const Group root6 = createRoot(WorkflowPolicy::FinishAllAndDone); QTest::newRow("StopRootAfterDoneWithOptional") << TestData{storage, root6, doneDoneLog, 3, OnDone::Success}; } @@ -947,7 +947,7 @@ void tst_Tasking::testTree_data() QTest::newRow("StopGroupWithStopOnFinished") << TestData{storage, root5, errorLog, 2, OnDone::Failure}; - const Group root6 = createRoot(WorkflowPolicy::Optional); + const Group root6 = createRoot(WorkflowPolicy::FinishAllAndDone); QTest::newRow("StopGroupWithOptional") << TestData{storage, root6, doneLog, 2, OnDone::Failure}; } @@ -1025,7 +1025,7 @@ void tst_Tasking::testTree_data() QTest::newRow("StopGroupAfterDoneWithStopOnFinished") << TestData{storage, root5, shortDoneLog, 3, OnDone::Failure}; - const Group root6 = createRoot(WorkflowPolicy::Optional); + const Group root6 = createRoot(WorkflowPolicy::FinishAllAndDone); QTest::newRow("StopGroupAfterDoneWithOptional") << TestData{storage, root6, longDoneLog, 3, OnDone::Failure}; } @@ -1103,7 +1103,7 @@ void tst_Tasking::testTree_data() QTest::newRow("StopGroupAfterErrorWithStopOnFinished") << TestData{storage, root5, shortErrorLog, 3, OnDone::Failure}; - const Group root6 = createRoot(WorkflowPolicy::Optional); + const Group root6 = createRoot(WorkflowPolicy::FinishAllAndDone); QTest::newRow("StopGroupAfterErrorWithOptional") << TestData{storage, root6, doneLog, 3, OnDone::Failure}; } @@ -1216,7 +1216,7 @@ void tst_Tasking::testTree_data() { const Group root { Storage(storage), - optional, + finishAllAndDone, createFailingTask(1), createFailingTask(2), groupDone(0), diff --git a/tests/manual/tasktree/main.cpp b/tests/manual/tasktree/main.cpp index ac5df4b0f6c..3976e3308dc 100644 --- a/tests/manual/tasktree/main.cpp +++ b/tests/manual/tasktree/main.cpp @@ -101,7 +101,7 @@ int main(int argc, char *argv[]) task_4_4->setBusyTime(3); groupTask_1->setWorkflowPolicy(Tasking::WorkflowPolicy::ContinueOnDone); - groupTask_4->setWorkflowPolicy(Tasking::WorkflowPolicy::Optional); + groupTask_4->setWorkflowPolicy(Tasking::WorkflowPolicy::FinishAllAndDone); groupTask_4_3->setExecuteMode(ExecuteMode::Parallel); groupTask_4_3->setWorkflowPolicy(Tasking::WorkflowPolicy::StopOnError); diff --git a/tests/manual/tasktree/taskwidget.cpp b/tests/manual/tasktree/taskwidget.cpp index e969dbf2d73..ddc56aa77e2 100644 --- a/tests/manual/tasktree/taskwidget.cpp +++ b/tests/manual/tasktree/taskwidget.cpp @@ -133,7 +133,7 @@ GroupWidget::GroupWidget() m_workflowCombo->addItem("Cont On Error", (int)Tasking::WorkflowPolicy::ContinueOnError); m_workflowCombo->addItem("Stop On Done", (int)Tasking::WorkflowPolicy::StopOnDone); m_workflowCombo->addItem("Cont On Done", (int)Tasking::WorkflowPolicy::ContinueOnDone); - m_workflowCombo->addItem("Optional", (int)Tasking::WorkflowPolicy::Optional); + m_workflowCombo->addItem("Optional", (int)Tasking::WorkflowPolicy::FinishAllAndDone); updateWorkflowPolicy(); connect(m_workflowCombo, &QComboBox::currentIndexChanged, this, [this](int index) { m_workflowPolicy = (Tasking::WorkflowPolicy)m_workflowCombo->itemData(index).toInt(); From 827b8ae3765a43bef8ec8193e4210fabdbc141a7 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Mon, 29 May 2023 10:24:12 +0300 Subject: [PATCH 020/141] TaskWindow: Do not jump to link on right-click Change-Id: I7474fed01d971517ca490ab611e5089c759d9177 Reviewed-by: Christian Kandeler --- src/plugins/projectexplorer/taskwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/projectexplorer/taskwindow.cpp b/src/plugins/projectexplorer/taskwindow.cpp index 95e15ec5eb7..9ae93c0bbf0 100644 --- a/src/plugins/projectexplorer/taskwindow.cpp +++ b/src/plugins/projectexplorer/taskwindow.cpp @@ -701,7 +701,7 @@ void TaskView::mouseMoveEvent(QMouseEvent *e) void TaskView::mouseReleaseEvent(QMouseEvent *e) { - if (m_clickAnchor.isEmpty()) { + if (m_clickAnchor.isEmpty() || e->button() == Qt::RightButton) { TreeView::mouseReleaseEvent(e); return; } From a35fd423647e4c240e1ba8905e215e3e3dd681bc Mon Sep 17 00:00:00 2001 From: David Schulz Date: Tue, 30 May 2023 13:48:01 +0200 Subject: [PATCH 021/141] Copilot: position copilot tooltip above cursor rect Change-Id: I37c6572000231334b90f38a2b37f5983c80174a5 Reviewed-by: Marcus Tillmanns Reviewed-by: --- src/plugins/copilot/copilothoverhandler.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/plugins/copilot/copilothoverhandler.cpp b/src/plugins/copilot/copilothoverhandler.cpp index b252cedc77d..bf4d3ece104 100644 --- a/src/plugins/copilot/copilothoverhandler.cpp +++ b/src/plugins/copilot/copilothoverhandler.cpp @@ -147,8 +147,12 @@ void CopilotHoverHandler::operateTooltip(TextEditorWidget *editorWidget, const Q auto tooltipWidget = new CopilotCompletionToolTip(suggestion->completions(), suggestion->currentCompletion(), editorWidget); - const qreal deltay = 2 * editorWidget->textDocument()->fontSettings().lineSpacing(); - ToolTip::show(point - QPoint{0, int(deltay)}, tooltipWidget, editorWidget); + + const QRect cursorRect = editorWidget->cursorRect(editorWidget->textCursor()); + QPoint pos = editorWidget->viewport()->mapToGlobal(cursorRect.topLeft()) + - Utils::ToolTip::offsetFromPosition(); + pos.ry() -= tooltipWidget->sizeHint().height(); + ToolTip::show(pos, tooltipWidget, editorWidget); } } // namespace Copilot::Internal From 7274e135f93d304c009141174f7fc044c0054f3c Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 30 May 2023 16:53:10 +0200 Subject: [PATCH 022/141] Some VCS: Use the simpler setLayouter overload for settings Change-Id: Idb4b271f5723d1a4ea1809aa41b81fbeb900eb83 Reviewed-by: Reviewed-by: Orgad Shaneh --- src/plugins/bazaar/bazaarsettings.cpp | 6 +++--- src/plugins/fossil/fossilsettings.cpp | 6 +++--- src/plugins/mercurial/mercurialsettings.cpp | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/plugins/bazaar/bazaarsettings.cpp b/src/plugins/bazaar/bazaarsettings.cpp index 344bdc6a095..dc6ef77dd48 100644 --- a/src/plugins/bazaar/bazaarsettings.cpp +++ b/src/plugins/bazaar/bazaarsettings.cpp @@ -66,10 +66,10 @@ BazaarSettings::BazaarSettings() timeout.setLabelText(Tr::tr("Timeout:")); timeout.setSuffix(Tr::tr("s")); - setLayouter([this](QWidget *widget) { + setLayouter([this] { using namespace Layouting; - Column { + return Column { Group { title(Tr::tr("Configuration")), Row { binaryPath } @@ -88,7 +88,7 @@ BazaarSettings::BazaarSettings() Row { logCount, timeout, st } }, st - }.attachTo(widget); + }; }); } diff --git a/src/plugins/fossil/fossilsettings.cpp b/src/plugins/fossil/fossilsettings.cpp index d62f48f1566..0662445b131 100644 --- a/src/plugins/fossil/fossilsettings.cpp +++ b/src/plugins/fossil/fossilsettings.cpp @@ -88,9 +88,9 @@ FossilSettings::FossilSettings() logCount.setToolTip(Tr::tr("The number of recent commit log entries to show. " "Choose 0 to see all entries.")); - setLayouter([this](QWidget *widget) { + setLayouter([this] { using namespace Layouting; - Column { + return Column { Group { title(Tr::tr("Configuration")), Row { binaryPath } @@ -117,7 +117,7 @@ FossilSettings::FossilSettings() }, }, st - }.attachTo(widget); + }; }); } diff --git a/src/plugins/mercurial/mercurialsettings.cpp b/src/plugins/mercurial/mercurialsettings.cpp index 0ced239122e..0b493e277bf 100644 --- a/src/plugins/mercurial/mercurialsettings.cpp +++ b/src/plugins/mercurial/mercurialsettings.cpp @@ -48,10 +48,10 @@ MercurialSettings::MercurialSettings() diffIgnoreBlankLines.setSettingsKey("diffIgnoreBlankLines"); - setLayouter([this](QWidget *widget) { + setLayouter([this] { using namespace Layouting; - Column { + return Column { Group { title(Tr::tr("Configuration")), Row { binaryPath } @@ -71,7 +71,7 @@ MercurialSettings::MercurialSettings() }, st - }.attachTo(widget); + }; }); } From 88fd4d7e7f6660a6e0f479efbc727ccfc5ce513d Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 24 May 2023 14:15:44 +0200 Subject: [PATCH 023/141] Nim: Use Aspects more directly in NimbleTaskStep Change-Id: I42fb8fd27b45260a62f9058c4c3e294909a72af4 Reviewed-by: Reviewed-by: Alessandro Portale --- src/plugins/nim/project/nimbletaskstep.cpp | 31 ++++++++++------------ 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/src/plugins/nim/project/nimbletaskstep.cpp b/src/plugins/nim/project/nimbletaskstep.cpp index e072b9422ee..1885a9daa15 100644 --- a/src/plugins/nim/project/nimbletaskstep.cpp +++ b/src/plugins/nim/project/nimbletaskstep.cpp @@ -47,8 +47,8 @@ private: bool validate(); - StringAspect *m_taskName = nullptr; - StringAspect *m_taskArgs = nullptr; + StringAspect m_taskName{this}; + StringAspect m_taskArgs{this}; QStandardItemModel m_tasks; bool m_selecting = false; @@ -62,19 +62,17 @@ NimbleTaskStep::NimbleTaskStep(BuildStepList *parentList, Id id) setDisplayName(display); setCommandLineProvider([this] { - QString args = m_taskName->value() + " " + m_taskArgs->value(); + QString args = m_taskName() + " " + m_taskArgs(); return CommandLine(Nim::nimblePathFromKit(target()->kit()), args, CommandLine::Raw); }); setWorkingDirectoryProvider([this] { return project()->projectDirectory(); }); - m_taskName = addAspect(); - m_taskName->setSettingsKey(Constants::C_NIMBLETASKSTEP_TASKNAME); + m_taskName.setSettingsKey(Constants::C_NIMBLETASKSTEP_TASKNAME); - m_taskArgs = addAspect(); - m_taskArgs->setSettingsKey(Constants::C_NIMBLETASKSTEP_TASKARGS); - m_taskArgs->setDisplayStyle(StringAspect::LineEditDisplay); - m_taskArgs->setLabelText(Tr::tr("Task arguments:")); + m_taskArgs.setSettingsKey(Constants::C_NIMBLETASKSTEP_TASKARGS); + m_taskArgs.setDisplayStyle(StringAspect::LineEditDisplay); + m_taskArgs.setLabelText(Tr::tr("Task arguments:")); } QWidget *NimbleTaskStep::createConfigWidget() @@ -96,15 +94,14 @@ QWidget *NimbleTaskStep::createConfigWidget() QTC_ASSERT(buildSystem, return widget); updateTaskList(); - selectTask(m_taskName->value()); + selectTask(m_taskName()); connect(&m_tasks, &QAbstractItemModel::dataChanged, this, &NimbleTaskStep::onDataChanged); connect(buildSystem, &NimbleBuildSystem::tasksChanged, this, &NimbleTaskStep::updateTaskList); setSummaryUpdater([this] { - return QString("%1: nimble %2 %3") - .arg(displayName(), m_taskName->value(), m_taskArgs->value()); + return QString("%1: nimble %2 %3").arg(displayName(), m_taskName(), m_taskArgs()); }); return widget; @@ -199,24 +196,24 @@ void NimbleTaskStep::uncheckedAllDifferentFrom(QStandardItem *toSkip) void NimbleTaskStep::setTaskName(const QString &name) { - if (m_taskName->value() == name) + if (m_taskName() == name) return; - m_taskName->setValue(name); + m_taskName.setValue(name); selectTask(name); } bool NimbleTaskStep::validate() { - if (m_taskName->value().isEmpty()) + if (m_taskName().isEmpty()) return true; auto nimbleBuildSystem = dynamic_cast(buildSystem()); QTC_ASSERT(nimbleBuildSystem, return false); - auto matchName = [this](const NimbleTask &task) { return task.name == m_taskName->value(); }; + auto matchName = [this](const NimbleTask &task) { return task.name == m_taskName(); }; if (!Utils::contains(nimbleBuildSystem->tasks(), matchName)) { emit addTask(BuildSystemTask(Task::Error, Tr::tr("Nimble task %1 not found.") - .arg(m_taskName->value()))); + .arg(m_taskName()))); emitFaultyConfigurationMessage(); return false; } From 361eb17fbf576c6f00e9bb9dbf0a129a3b725922 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Fri, 26 May 2023 15:13:41 +0200 Subject: [PATCH 024/141] FancyLineEdit: Fix placeholder text color Amends 3dcdbe9069c452e2f0eacb925aa7412e63dc4762 Using the theme's PalettePlaceholderText only works for themes that explicitly set it. Grab it from the application palette instead, which is correct for all themes. Observable by typing something into Locator and removing the typed text again. Change-Id: Iee7f900275ab7bcb37d87a2f7acddfee55fe9f79 Reviewed-by: Qt CI Bot Reviewed-by: Christian Stenger Reviewed-by: --- src/libs/utils/fancylineedit.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libs/utils/fancylineedit.cpp b/src/libs/utils/fancylineedit.cpp index ae931ec1ca0..08b480c88cf 100644 --- a/src/libs/utils/fancylineedit.cpp +++ b/src/libs/utils/fancylineedit.cpp @@ -11,6 +11,7 @@ #include "utilsicons.h" #include "utilstr.h" +#include #include #include #include @@ -126,7 +127,7 @@ FancyLineEditPrivate::FancyLineEditPrivate(FancyLineEdit *parent) : m_completionShortcut(completionShortcut()->key(), parent), m_okTextColor(creatorTheme()->color(Theme::TextColorNormal)), m_errorTextColor(creatorTheme()->color(Theme::TextColorError)), - m_placeholderTextColor(creatorTheme()->color(Theme::PalettePlaceholderText)) + m_placeholderTextColor(QApplication::palette().color(QPalette::PlaceholderText)) { m_completionShortcut.setContext(Qt::WidgetShortcut); From 0b5123cd74e024413b01b7921a5b73df610a829f Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Tue, 30 May 2023 16:28:37 +0200 Subject: [PATCH 025/141] Copilot: Fix UI text - Change an external link to point to the English language version - Fix capitalization of product names - Add a period to the end of a tooltip Change-Id: Ia46709db9911c0a3bfad252db2ffe0b3f7e5f2d7 Reviewed-by: Reviewed-by: Eike Ziller --- src/plugins/copilot/copilotsettings.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/copilot/copilotsettings.cpp b/src/plugins/copilot/copilotsettings.cpp index bac2c176afa..b8567f2feb4 100644 --- a/src/plugins/copilot/copilotsettings.cpp +++ b/src/plugins/copilot/copilotsettings.cpp @@ -53,7 +53,7 @@ CopilotSettings::CopilotSettings() nodeJsPath.setHistoryCompleter("Copilot.NodePath.History"); nodeJsPath.setDisplayName(Tr::tr("Node.js Path")); nodeJsPath.setToolTip( - Tr::tr("Select path to node.js executable. See https://nodejs.org/de/download/" + Tr::tr("Select path to node.js executable. See https://nodejs.org/en/download/" "for installation instructions.")); distPath.setExpectedKind(PathChooser::File); @@ -63,7 +63,7 @@ CopilotSettings::CopilotSettings() distPath.setHistoryCompleter("Copilot.DistPath.History"); distPath.setDisplayName(Tr::tr("Agent.js path")); distPath.setToolTip(Tr::tr( - "Select path to agent.js in copilot neovim plugin. See " + "Select path to agent.js in Copilot Neovim plugin. See " "https://github.com/github/copilot.vim#getting-started for installation instructions.")); autoComplete.setDisplayName(Tr::tr("Auto Complete")); @@ -71,7 +71,7 @@ CopilotSettings::CopilotSettings() autoComplete.setLabelText(Tr::tr("Request completions automatically")); autoComplete.setDefaultValue(true); autoComplete.setToolTip(Tr::tr("Automatically request suggestions for the current text cursor " - "position after changes to the document")); + "position after changes to the document.")); initEnableAspect(enableCopilot); } From 7f60d1c2e4d5d416cc5f8bc157303396e4ca0ef4 Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 31 May 2023 08:40:19 +0200 Subject: [PATCH 026/141] VCS: A few more simpler setLayouter calls Change-Id: Ib361740d0e33742620048680720ddafba4cdce12 Reviewed-by: Orgad Shaneh --- src/plugins/cvs/cvssettings.cpp | 6 +++--- src/plugins/perforce/perforcesettings.cpp | 9 +++++---- src/plugins/subversion/subversionsettings.cpp | 6 +++--- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/plugins/cvs/cvssettings.cpp b/src/plugins/cvs/cvssettings.cpp index e2247f7dbe0..9e1523486fa 100644 --- a/src/plugins/cvs/cvssettings.cpp +++ b/src/plugins/cvs/cvssettings.cpp @@ -59,9 +59,9 @@ CvsSettings::CvsSettings() diffIgnoreBlankLines.setSettingsKey("DiffIgnoreBlankLines"); - setLayouter([this](QWidget *widget) { + setLayouter([this] { using namespace Layouting; - Column { + return Column { Group { title(Tr::tr("Configuration")), Form { @@ -80,7 +80,7 @@ CvsSettings::CvsSettings() } }, st - }.attachTo(widget); + }; }); } diff --git a/src/plugins/perforce/perforcesettings.cpp b/src/plugins/perforce/perforcesettings.cpp index ee02465530e..47ef5a03b35 100644 --- a/src/plugins/perforce/perforcesettings.cpp +++ b/src/plugins/perforce/perforcesettings.cpp @@ -216,7 +216,7 @@ PerforceSettingsPage::PerforceSettingsPage(PerforceSettings *settings) setCategory(VcsBase::Constants::VCS_SETTINGS_CATEGORY); setSettings(settings); - setLayouter([settings](QWidget *widget) { + setLayouter([settings] { PerforceSettings &s = *settings; using namespace Layouting; @@ -224,7 +224,8 @@ PerforceSettingsPage::PerforceSettingsPage(PerforceSettings *settings) errorLabel->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); errorLabel->setFilled(true); auto testButton = new QPushButton(Tr::tr("Test")); - QObject::connect(testButton, &QPushButton::clicked, widget, [settings, errorLabel, testButton] { + QObject::connect(testButton, &QPushButton::clicked, errorLabel, + [settings, errorLabel, testButton] { testButton->setEnabled(false); auto checker = new PerforceChecker(errorLabel); checker->setUseOverideCursor(true); @@ -271,13 +272,13 @@ PerforceSettingsPage::PerforceSettingsPage(PerforceSettings *settings) } }; - Column { + return Column { config, environment, misc, Row { errorLabel, st, testButton }, st - }.attachTo(widget); + }; }); } diff --git a/src/plugins/subversion/subversionsettings.cpp b/src/plugins/subversion/subversionsettings.cpp index 092c4ee1c05..9b9225ccae7 100644 --- a/src/plugins/subversion/subversionsettings.cpp +++ b/src/plugins/subversion/subversionsettings.cpp @@ -68,10 +68,10 @@ SubversionSettings::SubversionSettings() password.setEnabled(useAuthentication()); }); - setLayouter([this](QWidget *widget) { + setLayouter([this] { using namespace Layouting; - Column { + return Column { Group { title(Tr::tr("Configuration")), Column { binaryPath } @@ -95,7 +95,7 @@ SubversionSettings::SubversionSettings() }, st - }.attachTo(widget); + }; }); } From 96ffcb8d6c75107be6910cd24c0fcfcfc9f81705 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 30 May 2023 17:15:19 +0200 Subject: [PATCH 027/141] Terminal: Remove some redundante settings page setup Amends 8b29c0637. Change-Id: Idddcaaaf84cd87a07365d178cf98a8459608c41d Reviewed-by: Reviewed-by: Marcus Tillmanns --- src/plugins/terminal/terminalsettings.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/plugins/terminal/terminalsettings.cpp b/src/plugins/terminal/terminalsettings.cpp index 692af4ec9c5..99e0de0d1f8 100644 --- a/src/plugins/terminal/terminalsettings.cpp +++ b/src/plugins/terminal/terminalsettings.cpp @@ -365,13 +365,11 @@ TerminalSettings::TerminalSettings() { s_instance = this; - setAutoApply(false); setSettingsGroup("Terminal"); setId("Terminal.General"); setDisplayName("Terminal"); setCategory("ZY.Terminal"); setDisplayCategory("Terminal"); - setSettings(&TerminalSettings::instance()); setCategoryIconPath(":/terminal/images/settingscategory_terminal.png"); enableTerminal.setSettingsKey("EnableTerminal"); From 3c7644647b7952e6ca2d8124f3d0b7dbba1b4bd7 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 31 May 2023 07:33:36 +0200 Subject: [PATCH 028/141] Copilot: Fix Qbs build Change-Id: I0fea791042e78b52fc7c89024d9424f24bbe0a12 Reviewed-by: Marcus Tillmanns --- src/plugins/copilot/copilot.qbs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/copilot/copilot.qbs b/src/plugins/copilot/copilot.qbs index cf59d954caa..714c45543d4 100644 --- a/src/plugins/copilot/copilot.qbs +++ b/src/plugins/copilot/copilot.qbs @@ -5,6 +5,7 @@ QtcPlugin { Depends { name: "Core" } Depends { name: "LanguageClient" } + Depends { name: "ProjectExplorer" } Depends { name: "TextEditor" } Depends { name: "Qt"; submodules: ["widgets", "xml", "network"] } From cc3e940f09421e6e177499dfaddef39c8a1e0f54 Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 31 May 2023 08:44:05 +0200 Subject: [PATCH 029/141] Vcpkg: Add a missing Tr:: Change-Id: Id3e7abdc7c9cfbe975dea9e099a0f088128152e4 Reviewed-by: Christian Stenger --- src/plugins/vcpkg/vcpkgsettings.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/plugins/vcpkg/vcpkgsettings.cpp b/src/plugins/vcpkg/vcpkgsettings.cpp index a450373ab52..3542ec47910 100644 --- a/src/plugins/vcpkg/vcpkgsettings.cpp +++ b/src/plugins/vcpkg/vcpkgsettings.cpp @@ -4,6 +4,7 @@ #include "vcpkgsettings.h" #include "vcpkgconstants.h" +#include "vcpkgtr.h" #include @@ -50,10 +51,10 @@ VcpkgSettings::VcpkgSettings() using namespace Layouting; return Column { Group { - title(tr("Vcpkg installation")), + title(Tr::tr("Vcpkg installation")), Form { Utils::PathChooser::label(), - Span{ 2, Row{ vcpkgRoot, websiteButton} }, + Span { 2, Row { vcpkgRoot, websiteButton } }, }, }, st, From 8241fc87b4c0dbab95ae469ff4505ddc5bdc9810 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Tue, 30 May 2023 14:20:58 +0200 Subject: [PATCH 030/141] CppEditor: Fix semantic highlighting ... for the case where the first line with semantic tokens has multiple tokens. This was not considered in the algorithm and uncovered by d6f5d07639c3d0313b758ba6fb7cc5eb57d188ef. Also improve variable names and comments. Fixes: QTCREATORBUG-29218 Change-Id: I0a1927c21edd70a3a91efc902e7e6ad2c734c91f Reviewed-by: Orgad Shaneh Reviewed-by: David Schulz --- .../texteditor/semantichighlighter.cpp | 24 +++++++------ .../highlighter/tst_highlighter.cpp | 35 +++++++++++++++++++ 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/src/plugins/texteditor/semantichighlighter.cpp b/src/plugins/texteditor/semantichighlighter.cpp index 68b1792ca84..30cb9cf729a 100644 --- a/src/plugins/texteditor/semantichighlighter.cpp +++ b/src/plugins/texteditor/semantichighlighter.cpp @@ -82,26 +82,28 @@ void SemanticHighlighter::incrementalApplyExtraAdditionalFormats(SyntaxHighlight if (to <= from) return; - const int firstResultBlockNumber = int(future.resultAt(from).line) - 1; + const int resultStartLine = future.resultAt(from).line; + int formattingStartLine = 1; - // blocks between currentBlockNumber and the last block with results will - // be cleaned of additional extra formats if they have no results - int currentBlockNumber = 0; + // Find the line on which to start formatting, where "formatting" means to either + // clear out formats from outdated document versions (if there is no current result + // on that line), or apply the format corresponding to the respective result. + // Note that if there are earlier results on the same line, we have to make sure they + // get re-applied by adapting the from variable accordingly. for (int i = from - 1; i >= 0; --i) { const HighlightingResult &result = future.resultAt(i); - const int blockNumber = int(result.line) - 1; - if (blockNumber < firstResultBlockNumber) { - // stop! found where last format stopped - currentBlockNumber = blockNumber + 1; - // add previous results for the same line to avoid undoing their formats + if (result.line == resultStartLine) { + from = i; + } else if (result.line < resultStartLine) { + formattingStartLine = result.line + 1; from = i + 1; break; } } QTextDocument *doc = highlighter->document(); - QTC_ASSERT(currentBlockNumber < doc->blockCount(), return); - QTextBlock currentBlock = doc->findBlockByNumber(currentBlockNumber); + QTC_ASSERT(formattingStartLine <= doc->blockCount(), return); + QTextBlock currentBlock = doc->findBlockByNumber(formattingStartLine - 1); std::map> formatRanges; for (int i = from; i < to; ++i) { diff --git a/tests/auto/texteditor/highlighter/tst_highlighter.cpp b/tests/auto/texteditor/highlighter/tst_highlighter.cpp index 163699c0cb1..e3f4e3dced6 100644 --- a/tests/auto/texteditor/highlighter/tst_highlighter.cpp +++ b/tests/auto/texteditor/highlighter/tst_highlighter.cpp @@ -301,6 +301,41 @@ void tst_highlighter::test_incrementalApplyAdditionalFormats() // should have no results since the new results do not contain a highlight at that position formats = emptyLineBlock.layout()->formats(); QVERIFY(formats.isEmpty()); + + // QTCREATORBUG-29218 + highlighter->clearAllExtraFormats(); + const HighlightingResults bug29218Results{HighlightingResult(1, 1, 2, 0), + HighlightingResult(1, 3, 2, 1)}; + QFutureInterface fi29218; + fi29218.reportResults(bug29218Results); + formats = firstBlock.layout()->formats(); + QVERIFY(formats.isEmpty()); + SemanticHighlighter::incrementalApplyExtraAdditionalFormats(highlighter, + fi29218.future(), + 0, + 1, + formatHash); + formats = firstBlock.layout()->formats(); + QCOMPARE(formats.size(), 1); + QCOMPARE(formats.at(0).format.fontItalic(), true); + QCOMPARE(formats.at(0).format.fontOverline(), false); + QCOMPARE(formats.at(0).start, 0); + QCOMPARE(formats.at(0).length, 2); + SemanticHighlighter::incrementalApplyExtraAdditionalFormats(highlighter, + fi29218.future(), + 1, + 2, + formatHash); + formats = firstBlock.layout()->formats(); + QCOMPARE(formats.size(), 2); + QCOMPARE(formats.at(0).format.fontItalic(), true); + QCOMPARE(formats.at(0).format.fontOverline(), false); + QCOMPARE(formats.at(0).start, 0); + QCOMPARE(formats.at(0).length, 2); + QCOMPARE(formats.at(1).format.fontItalic(), false); + QCOMPARE(formats.at(1).format.fontOverline(), true); + QCOMPARE(formats.at(1).start, 2); + QCOMPARE(formats.at(1).length, 2); } void tst_highlighter::cleanup() From 676d06d76822f8c3d4797c9401461bd984bdda07 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 30 May 2023 17:04:14 +0200 Subject: [PATCH 031/141] Use simpler IOptionPage::setLayouter overload in a few more places Change-Id: Id3745dab4363279219062462492b3a3e789776be Reviewed-by: Christian Stenger Reviewed-by: --- src/plugins/autotest/ctest/ctestsettings.cpp | 6 +++--- src/plugins/cmakeprojectmanager/cmakeformatter.cpp | 6 +++--- src/plugins/nim/settings/nimsettings.cpp | 6 +++--- src/plugins/projectexplorer/buildpropertiessettings.cpp | 6 +++--- src/plugins/qmakeprojectmanager/qmakesettings.cpp | 6 +++--- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/plugins/autotest/ctest/ctestsettings.cpp b/src/plugins/autotest/ctest/ctestsettings.cpp index e707c3edb09..a2f3e904270 100644 --- a/src/plugins/autotest/ctest/ctestsettings.cpp +++ b/src/plugins/autotest/ctest/ctestsettings.cpp @@ -20,8 +20,8 @@ CTestSettings::CTestSettings(Id settingsId) setCategory(Constants::AUTOTEST_SETTINGS_CATEGORY); setDisplayName(Tr::tr("CTest")); - setLayouter([this](QWidget *w) { - Row { Form { + setLayouter([this] { + return Row { Form { outputOnFail, br, scheduleRandom, br, stopOnFailure, br, @@ -39,7 +39,7 @@ CTestSettings::CTestSettings(Id settingsId) Row { testLoad, threshold} } } - }, st }.attachTo(w); + }, st }; }); outputOnFail.setSettingsKey("OutputOnFail"); diff --git a/src/plugins/cmakeprojectmanager/cmakeformatter.cpp b/src/plugins/cmakeprojectmanager/cmakeformatter.cpp index 295b664b9a0..dca6d47e203 100644 --- a/src/plugins/cmakeprojectmanager/cmakeformatter.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeformatter.cpp @@ -65,9 +65,9 @@ public: autoFormatMime.setDefaultValue("text/x-cmake"); autoFormatMime.setLabelText(Tr::tr("Restrict to MIME types:")); - setLayouter([this](QWidget *widget) { + setLayouter([this] { using namespace Layouting; - Column { + return Column { Row { Tr::tr("CMakeFormat command:"), command }, Space(10), Group { @@ -79,7 +79,7 @@ public: } }, st - }.attachTo(widget); + }; }); ActionContainer *menu = ActionManager::createMenu(Constants::CMAKEFORMATTER_MENU_ID); diff --git a/src/plugins/nim/settings/nimsettings.cpp b/src/plugins/nim/settings/nimsettings.cpp index fdf44ccd366..fac77109fde 100644 --- a/src/plugins/nim/settings/nimsettings.cpp +++ b/src/plugins/nim/settings/nimsettings.cpp @@ -33,15 +33,15 @@ NimSettings::NimSettings() setDisplayCategory(Tr::tr("Nim")); setCategoryIconPath(":/nim/images/settingscategory_nim.png"); - setLayouter([this](QWidget *widget) { + setLayouter([this] { using namespace Layouting; - Column { + return Column { Group { title("Nimsuggest"), Column { nimSuggestPath } }, st - }.attachTo(widget); + }; }); // code style factory diff --git a/src/plugins/projectexplorer/buildpropertiessettings.cpp b/src/plugins/projectexplorer/buildpropertiessettings.cpp index b409a2a2e2c..88c63b5f5c1 100644 --- a/src/plugins/projectexplorer/buildpropertiessettings.cpp +++ b/src/plugins/projectexplorer/buildpropertiessettings.cpp @@ -29,10 +29,10 @@ BuildPropertiesSettings::BuildPropertiesSettings() setCategory(ProjectExplorer::Constants::BUILD_AND_RUN_SETTINGS_CATEGORY); setSettings(this); - setLayouter([this](QWidget *widget) { + setLayouter([this] { using namespace Layouting; - Column { + return Column { Form { buildDirectoryTemplate, br, separateDebugInfo, br, @@ -40,7 +40,7 @@ BuildPropertiesSettings::BuildPropertiesSettings() qtQuickCompiler }, st - }.attachTo(widget); + }; }); registerAspect(&buildDirectoryTemplate); diff --git a/src/plugins/qmakeprojectmanager/qmakesettings.cpp b/src/plugins/qmakeprojectmanager/qmakesettings.cpp index 292851e444b..f920381d15e 100644 --- a/src/plugins/qmakeprojectmanager/qmakesettings.cpp +++ b/src/plugins/qmakeprojectmanager/qmakesettings.cpp @@ -51,14 +51,14 @@ QmakeSettings::QmakeSettings() ignoreSystemFunction.setFromSettingsTransformation(invertBoolVariant); ignoreSystemFunction.setToSettingsTransformation(invertBoolVariant); - setLayouter([this](QWidget *widget) { + setLayouter([this] { using namespace Layouting; - Column { + return Column { warnAgainstUnalignedBuildDir, alwaysRunQmake, ignoreSystemFunction, st - }.attachTo(widget); + }; }); readSettings(); From 227c25ef2e05e0b4f122fe96b18d75e6b70493f6 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 31 May 2023 07:55:51 +0200 Subject: [PATCH 032/141] Tests: Fix Qbs build Change-Id: I26846091123f484f1906ce04c3c7d93134f17d80 Reviewed-by: Reviewed-by: Jarek Kobus --- tests/auto/solutions/tasking/tst_tasking.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/solutions/tasking/tst_tasking.cpp b/tests/auto/solutions/tasking/tst_tasking.cpp index 9ddcbc0cbde..051b807842b 100644 --- a/tests/auto/solutions/tasking/tst_tasking.cpp +++ b/tests/auto/solutions/tasking/tst_tasking.cpp @@ -12,7 +12,7 @@ using namespace std::chrono_literals; using namespace Tasking; template -class TASKING_EXPORT DurationTaskAdapter : public TaskAdapter +class DurationTaskAdapter : public TaskAdapter { public: DurationTaskAdapter() { *task() = std::chrono::milliseconds{0}; } From e38b2cab44c5817ecde5242dd6d8ee1971266c3b Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Tue, 30 May 2023 16:49:00 +0200 Subject: [PATCH 033/141] DeviceShell: Refrain from using potentially invalidated iterators The stored container iterator, after container is modified, may be already invalidated. Avoid storing the iterators and do the search again after potential container modification. Use QHash instead of QMap for faster insertions / lookups. Amends 0135c47849bb1962fd379de210a01a918c6e8b4e Change-Id: I0a4641d3b410836a5b3b9be252059e4e37fa94e3 Reviewed-by: Marcus Tillmanns --- src/libs/utils/deviceshell.cpp | 3 ++- src/libs/utils/deviceshell.h | 5 ++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libs/utils/deviceshell.cpp b/src/libs/utils/deviceshell.cpp index ae983b6f482..f96c5da8f2d 100644 --- a/src/libs/utils/deviceshell.cpp +++ b/src/libs/utils/deviceshell.cpp @@ -104,7 +104,7 @@ RunResult DeviceShell::run(const CommandLine &cmd, const QByteArray &stdInData) QWaitCondition waiter; const int id = ++m_currentId; - const auto it = m_commandOutput.insert(id, CommandRun{{-1, {}, {}}, &waiter}); + m_commandOutput.insert(id, CommandRun{{-1, {}, {}}, &waiter}); QMetaObject::invokeMethod(m_shellProcess.get(), [this, id, cmd, stdInData] { const QString command = QString("%1 \"%2\" %3\n").arg(id) @@ -115,6 +115,7 @@ RunResult DeviceShell::run(const CommandLine &cmd, const QByteArray &stdInData) waiter.wait(&m_commandMutex); + const auto it = m_commandOutput.constFind(id); const RunResult result = *it; m_commandOutput.erase(it); diff --git a/src/libs/utils/deviceshell.h b/src/libs/utils/deviceshell.h index 052aac1838a..e5bc4ad7afe 100644 --- a/src/libs/utils/deviceshell.h +++ b/src/libs/utils/deviceshell.h @@ -7,7 +7,7 @@ #include "fileutils.h" -#include +#include #include #include #include @@ -78,8 +78,7 @@ private: int m_currentId{0}; QMutex m_commandMutex; - // QMap is used here to preserve iterators - QMap m_commandOutput; + QHash m_commandOutput; QByteArray m_commandBuffer; State m_shellScriptState = State::Unknown; From 9051e6ccaeaefb0fef5457810c2d53c613d5eef4 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 30 May 2023 17:10:28 +0200 Subject: [PATCH 034/141] Squish: Use PagedSettings for main settings Change-Id: I6314b746284e8fd032d32170bf353da544c7793f Reviewed-by: Christian Stenger Reviewed-by: --- src/plugins/squish/squishplugin.cpp | 2 -- src/plugins/squish/squishsettings.cpp | 44 ++++++++++++--------------- src/plugins/squish/squishsettings.h | 10 +----- 3 files changed, 20 insertions(+), 36 deletions(-) diff --git a/src/plugins/squish/squishplugin.cpp b/src/plugins/squish/squishplugin.cpp index c8b779aac06..caeb787de69 100644 --- a/src/plugins/squish/squishplugin.cpp +++ b/src/plugins/squish/squishplugin.cpp @@ -43,7 +43,6 @@ public: bool initializeGlobalScripts(); SquishSettings m_squishSettings; - SquishSettingsPage m_settingsPage{&m_squishSettings}; SquishTestTreeModel m_treeModel; SquishNavigationWidgetFactory m_navigationWidgetFactory; ObjectsMapEditorFactory m_objectsMapEditorFactory; @@ -57,7 +56,6 @@ SquishPluginPrivate::SquishPluginPrivate() { qRegisterMetaType("SquishResultItem*"); - m_squishSettings.readSettings(ICore::settings()); m_outputPane = SquishOutputPane::instance(); m_squishTools = new SquishTools; initializeMenuEntries(); diff --git a/src/plugins/squish/squishsettings.cpp b/src/plugins/squish/squishsettings.cpp index 23ccc22dfec..f7758a844d3 100644 --- a/src/plugins/squish/squishsettings.cpp +++ b/src/plugins/squish/squishsettings.cpp @@ -33,6 +33,12 @@ namespace Internal { SquishSettings::SquishSettings() { + setId("A.Squish.General"); + setDisplayName(Tr::tr("General")); + setCategory(Constants::SQUISH_SETTINGS_CATEGORY); + setDisplayCategory("Squish"); + setCategoryIcon(Icon({{":/squish/images/settingscategory_squish.png", + Theme::PanelTextColorDark}}, Icon::Tint)); setSettingsGroup("Squish"); setAutoApply(false); @@ -85,6 +91,19 @@ SquishSettings::SquishSettings() serverHost.setEnabled(!checked); serverPort.setEnabled(!checked); }); + + setLayouter([this] { + using namespace Layouting; + return Form { + squishPath, br, + licensePath, br, + local, serverHost, serverPort, br, + verbose, br, + minimizeIDE, br, + }; + }); + + readSettings(); } Utils::FilePath SquishSettings::scriptsPath(Language language) const @@ -101,31 +120,6 @@ Utils::FilePath SquishSettings::scriptsPath(Language language) const return scripts.isReadableDir() ? scripts : Utils::FilePath(); } -SquishSettingsPage::SquishSettingsPage(SquishSettings *settings) -{ - setId("A.Squish.General"); - setDisplayName(Tr::tr("General")); - setCategory(Constants::SQUISH_SETTINGS_CATEGORY); - setDisplayCategory("Squish"); - setCategoryIcon(Icon({{":/squish/images/settingscategory_squish.png", - Theme::PanelTextColorDark}}, Icon::Tint)); - - setSettings(settings); - - setLayouter([settings](QWidget *widget) { - SquishSettings &s = *settings; - using namespace Layouting; - - Form { - s.squishPath, br, - s.licensePath, br, - s.local, s.serverHost, s.serverPort, br, - s.verbose, br, - s.minimizeIDE, br, - }.attachTo(widget); - }); -} - SquishServerSettings::SquishServerSettings() { autTimeout.setLabel(Tr::tr("Maximum startup time:")); diff --git a/src/plugins/squish/squishsettings.h b/src/plugins/squish/squishsettings.h index 180f2eb84fe..0e25a4215e3 100644 --- a/src/plugins/squish/squishsettings.h +++ b/src/plugins/squish/squishsettings.h @@ -5,8 +5,6 @@ #include -#include - #include #include @@ -31,7 +29,7 @@ public: Utils::BoolAspect animatedCursor{this}; }; -class SquishSettings : public Utils::AspectContainer +class SquishSettings : public Core::PagedSettings { public: SquishSettings(); @@ -47,12 +45,6 @@ public: Utils::BoolAspect minimizeIDE{this}; }; -class SquishSettingsPage final : public Core::IOptionsPage -{ -public: - SquishSettingsPage(SquishSettings *settings); -}; - class SquishServerSettingsDialog : public QDialog { public: From 1a9025cdd52628c13fa7c325bf34475e3e64a3f7 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Mon, 29 May 2023 16:57:08 +0200 Subject: [PATCH 035/141] TaskTree: Add docs for Workflow Policy Transform it form TaskTree's description into WorkflowPolicy enum docs. Document global workflow policy elements and global workflowPolicy() function. Change-Id: I4af3f7ffa703bbb1a9370e2fd1f9242a68131295 Reviewed-by: Reviewed-by: Qt CI Bot Reviewed-by: Leena Miettinen --- src/libs/solutions/tasking/tasktree.cpp | 227 ++++++++++++++++-------- 1 file changed, 157 insertions(+), 70 deletions(-) diff --git a/src/libs/solutions/tasking/tasktree.cpp b/src/libs/solutions/tasking/tasktree.cpp index 054647752af..62243f373a1 100644 --- a/src/libs/solutions/tasking/tasktree.cpp +++ b/src/libs/solutions/tasking/tasktree.cpp @@ -48,6 +48,114 @@ private: \brief The TaskItem class represents the basic element for composing nested tree structures. */ +/*! + \enum Tasking::WorkflowPolicy + + This enum describes the possible behavior of the Group element when any group's child task + finishes its execution. It's also used when the running Group is stopped. + + \value StopOnError + Default. Corresponds to the stopOnError global element. + If any child task finishes with an error, the group stops and finishes with an error. + If all child tasks finished with success, the group finishes with success. + If a group is empty, it finishes with success. + \value ContinueOnError + Corresponds to the continueOnError global element. + 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 the group finished with success. + If all child tasks finish successfully, the group finishes with success. + If a group is empty, it finishes with success. + \value StopOnDone + Corresponds to the stopOnDone global element. + If any child task finishes with success, the group stops and finishes with success. + If all child tasks finished with an error, the group finishes with an error. + If a group is empty, it finishes with an error. + \value ContinueOnDone + Corresponds to the continueOnDone global element. + 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 the group finished with an error. + If all child tasks finish with an error, the group finishes with an error. + If a group is empty, it finishes with an error. + \value StopOnFinished + Corresponds to the stopOnFinished global element. + The group starts as many tasks as it can. When any task finishes, + the group stops and reports the task's result. + 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 always skipped. + If a group is empty, it finishes with an error. + \value FinishAllAndDone + Corresponds to the finishAllAndDone global element. + The group executes all tasks and ignores their return results. When all + tasks finished, the group finishes with success. + If a group is empty, it finishes with success. + \value FinishAllAndError + Corresponds to the finishAllAndError global element. + The group executes all tasks and ignores their return results. When all + tasks finished, the group finishes with an error. + If a group is empty, it finishes with an error. + + Whenever a child task's result causes the Group to stop, + i.e. in case of StopOnError, StopOnDone, or StopOnFinished policies, + the Group stops the other running child tasks (if any - for example in parallel mode), + and skips executing tasks it has not started yet (for example, in the sequential mode - + those, that are placed after the failed task). Both stopping and skipping child tasks + may happen when parallelLimit is used. + + The table below summarizes the differences between various workflow policies: + + \table + \header + \li \l WorkflowPolicy + \li Executes all child tasks + \li Result + \li Result when the group is empty + \row + \li StopOnError + \li Stops when any child task finished with an error and reports an error + \li An error when at least one child task failed, success otherwise + \li Success + \row + \li ContinueOnError + \li Yes + \li An error when at least one child task failed, success otherwise + \li Success + \row + \li StopOnDone + \li Stops when any child task finished with success and reports success + \li Success when at least one child task succeeded, an error otherwise + \li An error + \row + \li ContinueOnDone + \li Yes + \li Success when at least one child task succeeded, an error otherwise + \li An error + \row + \li StopOnFinished + \li Stops when any child task finished and reports child task's result + \li Success or an error, depending on the finished child task's result + \li An error + \row + \li FinishAllAndDone + \li Yes + \li Success + \li Success + \row + \li FinishAllAndError + \li Yes + \li An error + \li An error + \endtable + + If a child of a group is also a group, the child group runs its tasks according to its own + workflow policy. When a parent group stops the running child group because + of parent group's workflow policy, i.e. when the StopOnError, StopOnDone, or StopOnFinished + policy was used for the parent, the child group's result is reported according to the + \b Result column and to the \b {child group's workflow policy} row in the table above. +*/ + /*! \variable sequential A convenient global group's element describing the sequential execution mode. @@ -74,6 +182,43 @@ private: \sa sequential, parallelLimit */ +/*! + \variable stopOnError + A convenient global group's element describing the StopOnError workflow policy. + + This is the default workflow policy of the Group element. +*/ + +/*! + \variable continueOnError + A convenient global group's element describing the ContinueOnError workflow policy. +*/ + +/*! + \variable stopOnDone + A convenient global group's element describing the StopOnDone workflow policy. +*/ + +/*! + \variable continueOnDone + A convenient global group's element describing the ContinueOnDone workflow policy. +*/ + +/*! + \variable stopOnFinished + A convenient global group's element describing the StopOnFinished workflow policy. +*/ + +/*! + \variable finishAllAndDone + A convenient global group's element describing the FinishAllAndDone workflow policy. +*/ + +/*! + \variable finishAllAndError + A convenient global group's element describing the FinishAllAndError workflow policy. +*/ + /*! \enum Tasking::TaskAction @@ -244,6 +389,14 @@ TaskItem parallelLimit(int limit) return Group::parallelLimit(qMax(limit, 0)); } +/*! + Constructs a group's workflow policy element for a given \a policy. + + For convenience, global elements may be used instead. + + \sa stopOnError, continueOnError, stopOnDone, continueOnDone, stopOnFinished, finishAllAndDone, + finishAllAndError, WorkflowPolicy +*/ TaskItem workflowPolicy(WorkflowPolicy policy) { return Group::workflowPolicy(policy); @@ -1332,77 +1485,11 @@ void TaskNode::invokeEndHandler(bool success) \section2 Workflow Policy The workflow policy element in a Group specifies how the group should behave - when any of its \e direct child's tasks finish: + when any of its \e direct child's tasks finish. For a detailed description of possible + policies, refer to WorkflowPolicy. - \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 yet (for example, in the - sequential mode - those, that are placed after the failed task). - \li Immediately finishes with an error. - \endlist - 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 - 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, the group finishes with success. - \row - \li stopOnDone - \li If a task finishes with success, the group: - \list 1 - \li Stops the running tasks (if any - for example, in parallel - mode). - \li Skips executing tasks it has not started yet (for example, in the - sequential mode - those, that are placed after the successfully finished task). - \li Immediately finishes with success. - \endlist - 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 - 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, 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. - 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 finishAllAndDone - \li The group executes all tasks and ignores their return state. When all - tasks finish, the group finishes with success. - \endtable - - When a Group is empty, it finishes immediately with success, - regardless of its workflow policy. - If a child of a group is also a group, the child group - runs its tasks according to its own workflow policy. + If a child of a group is also a group, the child group runs its tasks + according to its own workflow policy. \section2 Storage From 43d59448735f676cd31625f14abae05d5339baad Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Wed, 31 May 2023 11:53:42 +0200 Subject: [PATCH 036/141] CoPilot: Fix a warning about an unused arg Change-Id: I8b4e552aac0931fea2af4ecc5e70a25c39871fab Reviewed-by: Marcus Tillmanns --- src/plugins/copilot/copilothoverhandler.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/copilot/copilothoverhandler.cpp b/src/plugins/copilot/copilothoverhandler.cpp index bf4d3ece104..135cbd8390f 100644 --- a/src/plugins/copilot/copilothoverhandler.cpp +++ b/src/plugins/copilot/copilothoverhandler.cpp @@ -139,6 +139,7 @@ void CopilotHoverHandler::identifyMatch(TextEditorWidget *editorWidget, void CopilotHoverHandler::operateTooltip(TextEditorWidget *editorWidget, const QPoint &point) { + Q_UNUSED(point) auto *suggestion = dynamic_cast(TextDocumentLayout::suggestion(m_block)); if (!suggestion) From ff2ed7d94b08130abef9db8ab38169e1778598f3 Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 31 May 2023 08:47:33 +0200 Subject: [PATCH 037/141] CppCheck: Move to simpler setLayouter calls Change-Id: Id0e9f1adfe730f6067ade9472db597e3a12fc2e3 Reviewed-by: Christian Stenger --- src/plugins/cppcheck/cppcheckoptions.cpp | 8 ++++---- src/plugins/cppcheck/cppcheckoptions.h | 2 +- src/plugins/cppcheck/cppcheckplugin.cpp | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/plugins/cppcheck/cppcheckoptions.cpp b/src/plugins/cppcheck/cppcheckoptions.cpp index 8392f64600c..1289ba0e0e2 100644 --- a/src/plugins/cppcheck/cppcheckoptions.cpp +++ b/src/plugins/cppcheck/cppcheckoptions.cpp @@ -108,11 +108,11 @@ CppcheckOptions::CppcheckOptions() readSettings(); } -std::function CppcheckOptions::layouter() +std::function CppcheckOptions::layouter() { - return [this](QWidget *widget) { + return [this] { using namespace Layouting; - Form { + return Form { binary, br, Tr::tr("Checks:"), Flow { warning, @@ -132,7 +132,7 @@ std::function CppcheckOptions::layouter() addIncludePaths, guessArguments } - }.attachTo(widget); + }; }; } diff --git a/src/plugins/cppcheck/cppcheckoptions.h b/src/plugins/cppcheck/cppcheckoptions.h index a6ccdd98ba0..eb3e1c7ddbf 100644 --- a/src/plugins/cppcheck/cppcheckoptions.h +++ b/src/plugins/cppcheck/cppcheckoptions.h @@ -12,7 +12,7 @@ class CppcheckOptions final : public Core::PagedSettings public: CppcheckOptions(); - std::function layouter(); + std::function layouter(); Utils::FilePathAspect binary{this}; Utils::BoolAspect warning{this}; diff --git a/src/plugins/cppcheck/cppcheckplugin.cpp b/src/plugins/cppcheck/cppcheckplugin.cpp index 890e2e3c0ad..b025762c8c6 100644 --- a/src/plugins/cppcheck/cppcheckplugin.cpp +++ b/src/plugins/cppcheck/cppcheckplugin.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -111,8 +112,7 @@ void CppcheckPluginPrivate::startManualRun() manualRunTool.updateOptions(); - auto optionsWidget = new QWidget; - options.layouter()(optionsWidget); + auto optionsWidget = options.layouter()().emerge(); ManualRunDialog dialog(optionsWidget, project); if (dialog.exec() == ManualRunDialog::Rejected) From 7bd06829c4907bdf8a9e4dcf630884f3625da7e7 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Wed, 31 May 2023 09:54:53 +0200 Subject: [PATCH 038/141] Tr/VCS: Fix various issues with translations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Inserting the name for the "commit" operation into messages relies on a certain sentence structure and doesn't work with translations. Same for "optional" error messages. Use different complete messages for the different cases instead. Avoid explicit line endings, use automatic word wrap instead. Add some quotes and full stops. Fix message with plural. Don't use %n for constant number (inline in message with assert). Improve confusing tool tip for instant blame. Change-Id: Ic8453763279753ebd5898858951acddcf311e6e4 Reviewed-by: Qt CI Bot Reviewed-by: Oswald Buddenhagen Reviewed-by: Orgad Shaneh Reviewed-by: André Hartmann --- share/qtcreator/translations/qtcreator_de.ts | 17 +++++--------- src/plugins/clearcase/clearcaseplugin.cpp | 22 +++++++++++++++++++ src/plugins/fossil/fossilcommitwidget.cpp | 4 ++-- src/plugins/fossil/pullorpushdialog.cpp | 2 +- .../fossil/wizard/projects/vcs/wizard.json | 2 +- src/plugins/git/gitclient.cpp | 2 +- src/plugins/git/gitsettings.cpp | 4 ++-- src/plugins/perforce/perforceplugin.cpp | 22 +++++++++++++++++++ src/plugins/vcsbase/submiteditorwidget.cpp | 7 +++--- src/plugins/vcsbase/vcsbaseplugin.cpp | 18 +++++++++++++++ src/plugins/vcsbase/vcsbaseplugin.h | 3 +++ src/plugins/vcsbase/vcsbasesubmiteditor.cpp | 12 +++------- 12 files changed, 84 insertions(+), 31 deletions(-) diff --git a/share/qtcreator/translations/qtcreator_de.ts b/share/qtcreator/translations/qtcreator_de.ts index 4b2e4bc008f..c6e2a4cab88 100644 --- a/share/qtcreator/translations/qtcreator_de.ts +++ b/share/qtcreator/translations/qtcreator_de.ts @@ -27194,12 +27194,8 @@ zu deaktivieren, deaktiviert auch die folgenden Plugins: Privat - Create a private check-in that is never synced. -Children of private check-ins are automatically private. -Private check-ins are not pushed to the remote repository by default. - Erstelle einen privaten Check-In, der niemals synchronisiert wird. -Kinder von privaten Check-Ins sind automatisch privat. -Private Check-Ins werden standardmäßig nicht zum entfernten Repository gepusht. + Create a private check-in that is never synced. Children of private check-ins are automatically private. Private check-ins are not pushed to the remote repository by default. + Erstelle einen privaten Check-In, der niemals synchronisiert wird. Kinder von privaten Check-Ins sind automatisch privat. Private Check-Ins werden standardmäßig nicht zum entfernten Repository gepusht. Tag names to apply; comma-separated. @@ -53204,12 +53200,9 @@ Wird ein Problem gefunden, dann wird die Anwendung angehalten und kann untersuch Hint: The second line of a commit message should be empty. Hinweis: Die zweite Zeile der Beschreibung sollte leer sein. - - <p>Writing good commit messages</p><ul><li>Avoid very short commit messages.</li><li>Consider the first line as subject (like in email) and keep it shorter than %n characters.</li><li>After an empty second line, a longer description can be added.</li><li>Describe why the change was done, not how it was done.</li></ul> - - <p>Gute Beschreibungen für Commits schreiben</p><ul><li>Vermeiden Sie sehr kurze Beschreibungen.</li><li>Betrachten Sie die erste Zeile als Betreff (wie in einer E-Mail) und halten Sie sie kürzer als ein Zeichen.</li><li>Eine längere Beschreibung kann nach einer leeren zweiten Zeile folgen.</li><li>Beschreiben Sie, weshalb die Änderung vorgenommen wurde, nicht wie sie vorgenommen wurde.</li></ul> - <p>Gute Beschreibungen für Commits schreiben</p><ul><li>Vermeiden Sie sehr kurze Beschreibungen.</li><li>Betrachten Sie die erste Zeile als Betreff (wie in einer E-Mail) und halten Sie sie kürzer als %n Zeichen.</li><li>Eine längere Beschreibung kann nach einer leeren zweiten Zeile folgen.</li><li>Beschreiben Sie, weshalb die Änderung vorgenommen wurde, nicht wie sie vorgenommen wurde.</li></ul> - + + <p>Writing good commit messages</p><ul><li>Avoid very short commit messages.</li><li>Consider the first line as a subject (like in emails) and keep it shorter than 72 characters.</li><li>After an empty second line, a longer description can be added.</li><li>Describe why the change was done, not how it was done.</li></ul> + <p>Gute Beschreibungen für Commits schreiben</p><ul><li>Vermeiden Sie sehr kurze Beschreibungen.</li><li>Betrachten Sie die erste Zeile als Betreff (wie in einer E-Mail) und halten Sie sie kürzer als 72 Zeichen.</li><li>Eine längere Beschreibung kann nach einer leeren zweiten Zeile folgen.</li><li>Beschreiben Sie, weshalb die Änderung vorgenommen wurde, nicht wie sie vorgenommen wurde.</li></ul> Update in progress diff --git a/src/plugins/clearcase/clearcaseplugin.cpp b/src/plugins/clearcase/clearcaseplugin.cpp index aa5c598c84c..943ffa194a4 100644 --- a/src/plugins/clearcase/clearcaseplugin.cpp +++ b/src/plugins/clearcase/clearcaseplugin.cpp @@ -227,6 +227,10 @@ private: Q_INVOKABLE void updateStatusActions(); QString commitDisplayName() const final; + QString commitAbortTitle() const final; + QString commitAbortMessage() const final; + QString commitErrorMessage(const QString &error) const final; + void checkOutCurrentFile(); void addCurrentFile(); void undoCheckOutCurrent(); @@ -948,9 +952,27 @@ void ClearCasePluginPrivate::updateActions(VcsBasePluginPrivate::ActionState as) QString ClearCasePluginPrivate::commitDisplayName() const { + //: Name of the "commit" action of the VCS return Tr::tr("Check In"); } +QString ClearCasePluginPrivate::commitAbortTitle() const +{ + return Tr::tr("Close Check In Editor"); +} + +QString ClearCasePluginPrivate::commitAbortMessage() const +{ + return Tr::tr("Closing this editor will abort the check in."); +} + +QString ClearCasePluginPrivate::commitErrorMessage(const QString &error) const +{ + if (error.isEmpty()) + return Tr::tr("Cannot check in."); + return Tr::tr("Cannot check in: %1.").arg(error); +} + void ClearCasePluginPrivate::checkOutCurrentFile() { const VcsBasePluginState state = currentState(); diff --git a/src/plugins/fossil/fossilcommitwidget.cpp b/src/plugins/fossil/fossilcommitwidget.cpp index 355a792bfda..72fba5ef86f 100644 --- a/src/plugins/fossil/fossilcommitwidget.cpp +++ b/src/plugins/fossil/fossilcommitwidget.cpp @@ -93,8 +93,8 @@ FossilCommitWidget::FossilCommitWidget() : m_commitPanel(new QWidget) m_invalidBranchLabel->setType(InfoLabel::Error); m_isPrivateCheckBox = new QCheckBox(Tr::tr("Private")); - m_isPrivateCheckBox->setToolTip(Tr::tr("Create a private check-in that is never synced.\n" - "Children of private check-ins are automatically private.\n" + m_isPrivateCheckBox->setToolTip("" + Tr::tr("Create a private check-in that is never synced. " + "Children of private check-ins are automatically private. " "Private check-ins are not pushed to the remote repository by default.")); m_tagsLineEdit = new QLineEdit; diff --git a/src/plugins/fossil/pullorpushdialog.cpp b/src/plugins/fossil/pullorpushdialog.cpp index 5ebf9869d3f..b6473a68b41 100644 --- a/src/plugins/fossil/pullorpushdialog.cpp +++ b/src/plugins/fossil/pullorpushdialog.cpp @@ -34,7 +34,7 @@ PullOrPushDialog::PullOrPushDialog(Mode mode, QWidget *parent) m_localPathChooser->setPromptDialogFilter(Tr::tr(Constants::FOSSIL_FILE_FILTER)); m_urlButton = new QRadioButton(Tr::tr("Specify URL:")); - m_urlButton->setToolTip(Tr::tr("For example: https://[user[:pass]@]host[:port]/[path]")); + m_urlButton->setToolTip(Tr::tr("For example: \"https://[user[:pass]@]host[:port]/[path]\".")); m_urlLineEdit = new QLineEdit; m_urlLineEdit->setEnabled(false); diff --git a/src/plugins/fossil/wizard/projects/vcs/wizard.json b/src/plugins/fossil/wizard/projects/vcs/wizard.json index 56e08b63774..7f5fb174520 100644 --- a/src/plugins/fossil/wizard/projects/vcs/wizard.json +++ b/src/plugins/fossil/wizard/projects/vcs/wizard.json @@ -86,7 +86,7 @@ { "name": "Repo", "trDisplayName": "Remote repository:", - "trToolTip": "For example: https://[user[:pass]@]host[:port]/[path]", + "trToolTip": "For example: \"https://[user[:pass]@]host[:port]/[path]\".", "type": "LineEdit", "enabled": "%{isCloneRepo}", "mandatory": false diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index dd335dcc650..935b56291ff 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -2873,7 +2873,7 @@ bool GitClient::addAndCommit(const FilePath &repositoryDirectory, GitPlugin::updateCurrentBranch(); return true; } - VcsOutputWindow::appendError(Tr::tr("Cannot commit %n files", nullptr, commitCount) + "\n"); + VcsOutputWindow::appendError(Tr::tr("Cannot commit %n file(s)", nullptr, commitCount) + "\n"); return false; } diff --git a/src/plugins/git/gitsettings.cpp b/src/plugins/git/gitsettings.cpp index 6cbec254445..4ebf7debeed 100644 --- a/src/plugins/git/gitsettings.cpp +++ b/src/plugins/git/gitsettings.cpp @@ -90,8 +90,8 @@ GitSettings::GitSettings() instantBlame.setSettingsKey("Git Instant"); instantBlame.setDefaultValue(true); instantBlame.setLabelText(Tr::tr("Add instant blame annotations to editor")); - instantBlame.setToolTip(Tr::tr("Directly annotate each line in the editor " - "when scrolling through the document.")); + instantBlame.setToolTip( + Tr::tr("Annotate the current line in the editor with Git \"blame\" output.")); graphLog.setSettingsKey("GraphLog"); diff --git a/src/plugins/perforce/perforceplugin.cpp b/src/plugins/perforce/perforceplugin.cpp index 5a7e74450dd..ae61d12d342 100644 --- a/src/plugins/perforce/perforceplugin.cpp +++ b/src/plugins/perforce/perforceplugin.cpp @@ -226,6 +226,10 @@ public: void discardCommit() override { cleanCommitMessageFile(); } QString commitDisplayName() const final; + QString commitAbortTitle() const final; + QString commitAbortMessage() const final; + QString commitErrorMessage(const QString &error) const final; + void p4Diff(const PerforceDiffParameters &p); void openCurrentFile(); @@ -1443,9 +1447,27 @@ void PerforceDiffConfig::triggerReRun() QString PerforcePluginPrivate::commitDisplayName() const { + //: Name of the "commit" action of the VCS return Tr::tr("Submit"); } +QString PerforcePluginPrivate::commitAbortTitle() const +{ + return Tr::tr("Close Submit Editor"); +} + +QString PerforcePluginPrivate::commitAbortMessage() const +{ + return Tr::tr("Closing this editor will abort the submit."); +} + +QString PerforcePluginPrivate::commitErrorMessage(const QString &error) const +{ + if (error.isEmpty()) + return Tr::tr("Cannot submit."); + return Tr::tr("Cannot submit: %1.").arg(error); +} + void PerforcePluginPrivate::p4Diff(const FilePath &workingDir, const QStringList &files) { PerforceDiffParameters p; diff --git a/src/plugins/vcsbase/submiteditorwidget.cpp b/src/plugins/vcsbase/submiteditorwidget.cpp index 63a75e7ac06..00b4200580a 100644 --- a/src/plugins/vcsbase/submiteditorwidget.cpp +++ b/src/plugins/vcsbase/submiteditorwidget.cpp @@ -619,15 +619,16 @@ void SubmitEditorWidget::verifyDescription() d->descriptionHint->setText(hints.join("
")); if (!d->descriptionHint->text().isEmpty()) { + static_assert(MaxSubjectLength == 72); // change the translated message below when changing d->descriptionHint->setToolTip( Tr::tr("

Writing good commit messages

" "
    " "
  • Avoid very short commit messages.
  • " - "
  • Consider the first line as subject (like in email) " - "and keep it shorter than %n characters.
  • " + "
  • Consider the first line as a subject (like in emails) " + "and keep it shorter than 72 characters.
  • " "
  • After an empty second line, a longer description can be added.
  • " "
  • Describe why the change was done, not how it was done.
  • " - "
", nullptr, MaxSubjectLength)); + "")); } } diff --git a/src/plugins/vcsbase/vcsbaseplugin.cpp b/src/plugins/vcsbase/vcsbaseplugin.cpp index 517ffbdf48f..b72657cdb3c 100644 --- a/src/plugins/vcsbase/vcsbaseplugin.cpp +++ b/src/plugins/vcsbase/vcsbaseplugin.cpp @@ -593,9 +593,27 @@ bool VcsBasePluginPrivate::enableMenuAction(ActionState as, QAction *menuAction) QString VcsBasePluginPrivate::commitDisplayName() const { + //: Name of the "commit" action of the VCS return Tr::tr("Commit", "name of \"commit\" action of the VCS."); } +QString VcsBasePluginPrivate::commitAbortTitle() const +{ + return Tr::tr("Close Commit Editor"); +} + +QString VcsBasePluginPrivate::commitAbortMessage() const +{ + return Tr::tr("Closing this editor will abort the commit."); +} + +QString VcsBasePluginPrivate::commitErrorMessage(const QString &error) const +{ + if (error.isEmpty()) + return Tr::tr("Cannot commit."); + return Tr::tr("Cannot commit: %1.").arg(error); +} + void VcsBasePluginPrivate::commitFromEditor() { QTC_ASSERT(m_submitEditor, return); diff --git a/src/plugins/vcsbase/vcsbaseplugin.h b/src/plugins/vcsbase/vcsbaseplugin.h index af96e12631a..5a4c9ae6b30 100644 --- a/src/plugins/vcsbase/vcsbaseplugin.h +++ b/src/plugins/vcsbase/vcsbaseplugin.h @@ -135,6 +135,9 @@ public: const QStringList &extraArgs); // Display name of the commit action virtual QString commitDisplayName() const; + virtual QString commitAbortTitle() const; + virtual QString commitAbortMessage() const; + virtual QString commitErrorMessage(const QString &error) const; void commitFromEditor(); virtual bool activateCommit() = 0; diff --git a/src/plugins/vcsbase/vcsbasesubmiteditor.cpp b/src/plugins/vcsbase/vcsbasesubmiteditor.cpp index 1895a64f4d1..5ddab0da77f 100644 --- a/src/plugins/vcsbase/vcsbasesubmiteditor.cpp +++ b/src/plugins/vcsbase/vcsbasesubmiteditor.cpp @@ -453,11 +453,7 @@ void VcsBaseSubmitEditor::accept(VcsBasePluginPrivate *plugin) QString errorMessage; const bool canCommit = checkSubmitMessage(&errorMessage) && submitWidget->canSubmit(&errorMessage); if (!canCommit) { - VcsOutputWindow::appendError( - Tr::tr("Cannot %1%2.", - "%2 is an optional error message with ': ' prefix. Don't add space in front.") - .arg(plugin->commitDisplayName().toLower(), - errorMessage.isEmpty() ? errorMessage : ": " + errorMessage)); + VcsOutputWindow::appendError(plugin->commitErrorMessage(errorMessage)); } else if (plugin->activateCommit()) { close(); } @@ -480,12 +476,10 @@ bool VcsBaseSubmitEditor::promptSubmit(VcsBasePluginPrivate *plugin) if (!submitWidget->isEnabled() || !submitWidget->isEdited()) return true; - const QString commitName = plugin->commitDisplayName(); QMessageBox mb(Core::ICore::dialogParent()); - mb.setWindowTitle(Tr::tr("Close %1 %2 Editor").arg(plugin->displayName(), commitName)); + mb.setWindowTitle(plugin->commitAbortTitle()); mb.setIcon(QMessageBox::Warning); - mb.setText(Tr::tr("Closing this editor will abort the %1.") - .arg(commitName.toLower())); + mb.setText(plugin->commitAbortMessage()); mb.setStandardButtons(QMessageBox::Close | QMessageBox::Cancel); // On Windows there is no mnemonic for Close. Set it explicitly. mb.button(QMessageBox::Close)->setText(Tr::tr("&Close")); From 58fb6f88a643dfa6e8799722f0dbf272b29a138b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20L=C3=B6hning?= Date: Fri, 26 May 2023 00:23:58 +0200 Subject: [PATCH 039/141] SquishTests: Update reading build issues Fixes tst_build_new_project, tst_CCOM02 et al. tst_tasks_handling fails which might be an actual issue, reported in: Task-number: QTCREATORBUG-29209 Change-Id: I5eae54df27d8ba8f441e5b9c4acdaa2b41716245 Reviewed-by: Christian Stenger Reviewed-by: Christian Kandeler --- src/plugins/projectexplorer/taskmodel.cpp | 2 ++ src/plugins/projectexplorer/taskmodel.h | 2 +- tests/system/objects.map | 2 +- tests/system/shared/build_utils.py | 4 ++-- tests/system/shared/suites_qtta.py | 6 +++--- tests/system/suite_editors/tst_memberoperator/test.py | 4 ++-- tests/system/suite_general/tst_opencreator_qbs/test.py | 2 +- tests/system/suite_general/tst_tasks_handling/test.py | 2 +- 8 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/plugins/projectexplorer/taskmodel.cpp b/src/plugins/projectexplorer/taskmodel.cpp index 80280a5595e..11591e707d7 100644 --- a/src/plugins/projectexplorer/taskmodel.cpp +++ b/src/plugins/projectexplorer/taskmodel.cpp @@ -273,6 +273,8 @@ QVariant TaskModel::data(const QModelIndex &index, int role) const return task.summary; case TaskModel::Description: return task.description(); + case TaskModel::Type: + return int(task.type); } return {}; } diff --git a/src/plugins/projectexplorer/taskmodel.h b/src/plugins/projectexplorer/taskmodel.h index e60d8a30a51..5fa37c02d1a 100644 --- a/src/plugins/projectexplorer/taskmodel.h +++ b/src/plugins/projectexplorer/taskmodel.h @@ -44,7 +44,7 @@ public: int sizeOfLineNumber(const QFont &font); void setFileNotFound(const QModelIndex &index, bool b); - enum Roles { Description = Qt::UserRole, }; + enum Roles { Description = Qt::UserRole, Type}; int taskCount(Utils::Id categoryId); int errorTaskCount(Utils::Id categoryId); diff --git a/tests/system/objects.map b/tests/system/objects.map index 591b671e539..883bfd02af4 100644 --- a/tests/system/objects.map +++ b/tests/system/objects.map @@ -124,7 +124,7 @@ :Qt Creator.DragDoc_QToolButton {toolTip='Drag to drag documents between splits' type='QToolButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator.Events_QDockWidget {name='QmlProfiler.Statistics.DockDockWidget' type='QDockWidget' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator.Events_QTabBar {aboveWidget=':Qt Creator.Events_QDockWidget' type='QTabBar' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} -:Qt Creator.Issues_QListView {type='QListView' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow' windowTitle='Issues'} +:Qt Creator.Issues_QListView {type='Utils::TreeView' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow' windowTitle='Issues'} :Qt Creator.Project.Menu.File_QMenu {name='Project.Menu.File' type='QMenu'} :Qt Creator.Project.Menu.Folder_QMenu {name='Project.Menu.Folder' type='QMenu' visible='1'} :Qt Creator.QML debugging and profiling:_QComboBox {leftWidget=':Qt Creator.QML debugging and profiling:_QLabel' type='QComboBox' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} diff --git a/tests/system/shared/build_utils.py b/tests/system/shared/build_utils.py index 18ae360fca0..6a2904286a3 100644 --- a/tests/system/shared/build_utils.py +++ b/tests/system/shared/build_utils.py @@ -47,7 +47,7 @@ def checkLastBuild(expectedToFail=False): test.log("checkLastBuild called without a build") return buildIssues = getBuildIssues() - types = [i[5] for i in buildIssues] + types = [i[1] for i in buildIssues] errors = types.count("1") warnings = types.count("2") gotErrors = errors != 0 @@ -89,7 +89,7 @@ def dumpBuildIssues(listModel): issueDump = [] for index in dumpIndices(listModel): issueDump.extend([[str(index.data(role).toString()) for role - in range(Qt.UserRole, Qt.UserRole + 6)]]) + in range(Qt.UserRole, Qt.UserRole + 2)]]) return issueDump diff --git a/tests/system/shared/suites_qtta.py b/tests/system/shared/suites_qtta.py index 2c63e009e83..97032ae0638 100644 --- a/tests/system/shared/suites_qtta.py +++ b/tests/system/shared/suites_qtta.py @@ -20,9 +20,9 @@ def checkSyntaxError(issuesView, expectedTextsArray, warnIfMoreIssues = True): if(warnIfMoreIssues and issuesModel.rowCount() > 1): test.warning("More than one expected issues reported") # iterate issues and check if there exists "Unexpected token" message - for description, type in zip(dumpItems(issuesModel, role=Qt.UserRole + 3), - dumpItems(issuesModel, role=Qt.UserRole + 5)): - # enum Roles { File = Qt::UserRole, Line, MovedLine, Description, FileNotFound, Type, Category, Icon, Task_t }; + for description, type in zip(dumpItems(issuesModel, role=Qt.UserRole), + dumpItems(issuesModel, role=Qt.UserRole + 1)): + # enum Roles { Description = Qt::UserRole, Type}; # check if at least one of expected texts found in issue text for expectedText in expectedTextsArray: if expectedText in description: diff --git a/tests/system/suite_editors/tst_memberoperator/test.py b/tests/system/suite_editors/tst_memberoperator/test.py index ba1f1476850..4d11465b719 100644 --- a/tests/system/suite_editors/tst_memberoperator/test.py +++ b/tests/system/suite_editors/tst_memberoperator/test.py @@ -27,11 +27,11 @@ def __noBuildIssues__(): def __syntaxErrorDetected__(): buildIssues = getBuildIssues(False) for issue in buildIssues: - if issue[3] in ["Expected ';' after expression (fix available)", + if issue[0] in ["Expected ';' after expression (fix available)", "Expected ';' at end of declaration (fix available)", "Use of undeclared identifier 'syntaxError'"]: return True - if re.match(issue[3], "Declaration of reference variable '.+' requires an initializer"): + if re.match(issue[0], "Declaration of reference variable '.+' requires an initializer"): return True return False diff --git a/tests/system/suite_general/tst_opencreator_qbs/test.py b/tests/system/suite_general/tst_opencreator_qbs/test.py index 555e1437582..ca941547c90 100644 --- a/tests/system/suite_general/tst_opencreator_qbs/test.py +++ b/tests/system/suite_general/tst_opencreator_qbs/test.py @@ -24,7 +24,7 @@ def main(): else: test.warning("Parsing project timed out") compareProjectTree(rootNodeTemplate % "Qt Creator", "projecttree_creator.tsv") - buildIssuesTexts = map(lambda i: str(i[3]), getBuildIssues()) + buildIssuesTexts = map(lambda i: str(i[0]), getBuildIssues()) deprecationWarnings = filter(lambda s: "deprecated" in s, buildIssuesTexts) if deprecationWarnings: test.warning("Creator claims that the .qbs file uses deprecated features.", diff --git a/tests/system/suite_general/tst_tasks_handling/test.py b/tests/system/suite_general/tst_tasks_handling/test.py index 053d5d24c74..8c6e2395583 100644 --- a/tests/system/suite_general/tst_tasks_handling/test.py +++ b/tests/system/suite_general/tst_tasks_handling/test.py @@ -58,7 +58,7 @@ def checkOrUncheckMyTasks(): "My Tasks")) def getBuildIssuesTypeCounts(model): - issueTypes = list(map(lambda x: x.data(Qt.UserRole + 5).toInt(), dumpIndices(model))) + issueTypes = list(map(lambda x: x.data(Qt.UserRole + 1).toInt(), dumpIndices(model))) result = [issueTypes.count(0), issueTypes.count(1), issueTypes.count(2)] if len(issueTypes) != sum(result): test.fatal("Found unexpected value(s) for TaskType...") From 1bc3cccbb444b078db2e5e0a1cd4ecd4debd0358 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 31 May 2023 12:15:48 +0200 Subject: [PATCH 040/141] Copilot: Do not try to start copilot without nodejs Avoids the attempt to start the client if nodejs cannot be found. Change-Id: I3783280120ca754291a92b3308c1192906facd08 Reviewed-by: Marcus Tillmanns --- src/plugins/copilot/authwidget.cpp | 2 +- src/plugins/copilot/copilotplugin.cpp | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/plugins/copilot/authwidget.cpp b/src/plugins/copilot/authwidget.cpp index 31b4660b680..f29e3d3a150 100644 --- a/src/plugins/copilot/authwidget.cpp +++ b/src/plugins/copilot/authwidget.cpp @@ -93,7 +93,7 @@ void AuthWidget::updateClient(const Utils::FilePath &nodeJs, const Utils::FilePa m_client = nullptr; setState(Tr::tr("Sign in"), false); m_button->setEnabled(false); - if (!nodeJs.exists() || !agent.exists()) { + if (!nodeJs.isExecutableFile() || !agent.exists()) { return; } diff --git a/src/plugins/copilot/copilotplugin.cpp b/src/plugins/copilot/copilotplugin.cpp index 43effda321c..526a6061cbe 100644 --- a/src/plugins/copilot/copilotplugin.cpp +++ b/src/plugins/copilot/copilotplugin.cpp @@ -120,6 +120,9 @@ void CopilotPlugin::extensionsInitialized() void CopilotPlugin::restartClient() { LanguageClient::LanguageClientManager::shutdownClient(m_client); + + if (!CopilotSettings::instance().nodeJsPath().isExecutableFile()) + return; m_client = new CopilotClient(CopilotSettings::instance().nodeJsPath(), CopilotSettings::instance().distPath()); } From 44e9d56c0463e35bdfede1af4f9da9dd70e13820 Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Tue, 30 May 2023 13:52:11 +0200 Subject: [PATCH 041/141] Utils: Fix macOS permissions parsing Change-Id: I5fdde04c197b5db323fc8630c4ee4b2c197d947a Reviewed-by: Marcus Tillmanns Reviewed-by: Qt CI Bot --- src/libs/utils/fileutils.cpp | 12 +++++++++--- tests/auto/utils/fileutils/tst_fileutils.cpp | 14 ++++++++++---- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/libs/utils/fileutils.cpp b/src/libs/utils/fileutils.cpp index a6cbebf3681..2cecc2810b9 100644 --- a/src/libs/utils/fileutils.cpp +++ b/src/libs/utils/fileutils.cpp @@ -629,12 +629,18 @@ FilePathInfo::FileFlags fileInfoFlagsfromStatMode(const QString &hexString, int FilePathInfo::FileFlags result; - if (mode & IRUSR) + if (mode & IRUSR) { result |= FilePathInfo::ReadOwnerPerm; - if (mode & IWUSR) + result |= FilePathInfo::ReadUserPerm; + } + if (mode & IWUSR) { result |= FilePathInfo::WriteOwnerPerm; - if (mode & IXUSR) + result |= FilePathInfo::WriteUserPerm; + } + if (mode & IXUSR) { result |= FilePathInfo::ExeOwnerPerm; + result |= FilePathInfo::ExeUserPerm; + } if (mode & IRGRP) result |= FilePathInfo::ReadGroupPerm; if (mode & IWGRP) diff --git a/tests/auto/utils/fileutils/tst_fileutils.cpp b/tests/auto/utils/fileutils/tst_fileutils.cpp index f4596cb1a5c..198abf3398b 100644 --- a/tests/auto/utils/fileutils/tst_fileutils.cpp +++ b/tests/auto/utils/fileutils/tst_fileutils.cpp @@ -136,6 +136,9 @@ void tst_fileutils::filePathInfoFromTriple_data() FilePathInfo::ReadOwnerPerm | FilePathInfo::WriteOwnerPerm | FilePathInfo::ExeOwnerPerm + | FilePathInfo::ReadUserPerm + | FilePathInfo::WriteUserPerm + | FilePathInfo::ExeUserPerm | FilePathInfo::ReadGroupPerm | FilePathInfo::ExeGroupPerm | FilePathInfo::ReadOtherPerm @@ -149,10 +152,11 @@ void tst_fileutils::filePathInfoFromTriple_data() << FilePathInfo{808104, FilePathInfo::FileFlags( FilePathInfo::ReadOwnerPerm | FilePathInfo::WriteOwnerPerm - | FilePathInfo::ExeOwnerPerm | FilePathInfo::ReadGroupPerm - | FilePathInfo::ExeGroupPerm | FilePathInfo::ReadOtherPerm - | FilePathInfo::ExeOtherPerm | FilePathInfo::FileType - | FilePathInfo::ExistsFlag), + | FilePathInfo::ExeOwnerPerm | FilePathInfo::ReadUserPerm + | FilePathInfo::WriteUserPerm | FilePathInfo::ExeUserPerm + | FilePathInfo::ReadGroupPerm | FilePathInfo::ExeGroupPerm + | FilePathInfo::ReadOtherPerm | FilePathInfo::ExeOtherPerm + | FilePathInfo::FileType | FilePathInfo::ExistsFlag), QDateTime::fromSecsSinceEpoch(1668852790)}; QTest::newRow("linux-disk") << QString("61b0 1651167746 0") @@ -160,6 +164,8 @@ void tst_fileutils::filePathInfoFromTriple_data() FilePathInfo::FileFlags( FilePathInfo::ReadOwnerPerm | FilePathInfo::WriteOwnerPerm + | FilePathInfo::ReadUserPerm + | FilePathInfo::WriteUserPerm | FilePathInfo::ReadGroupPerm | FilePathInfo::WriteGroupPerm | FilePathInfo::LocalDiskFlag From 9f1a2c4f8f3e9cbd1309c744455c5a770d534fba Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Tue, 23 May 2023 07:15:42 +0200 Subject: [PATCH 042/141] Terminal: Rework commands This rework fixes the way commands are registered in Qt Creator. Change-Id: I401f3ac7d9194dad8fceb507360ddc3633106eb4 Reviewed-by: Eike Ziller Reviewed-by: Reviewed-by: Qt CI Bot --- src/plugins/terminal/CMakeLists.txt | 3 +- src/plugins/terminal/terminal.qbs | 4 +- src/plugins/terminal/terminalcommands.cpp | 186 ---------------------- src/plugins/terminal/terminalcommands.h | 76 --------- src/plugins/terminal/terminalconstants.h | 19 +++ src/plugins/terminal/terminalicons.h | 18 +++ src/plugins/terminal/terminalpane.cpp | 167 ++++++++++--------- src/plugins/terminal/terminalpane.h | 17 ++ src/plugins/terminal/terminalplugin.cpp | 22 ++- src/plugins/terminal/terminalsearch.cpp | 10 -- src/plugins/terminal/terminalwidget.cpp | 158 ++++++++++++------ src/plugins/terminal/terminalwidget.h | 25 +++ 12 files changed, 292 insertions(+), 413 deletions(-) delete mode 100644 src/plugins/terminal/terminalcommands.cpp delete mode 100644 src/plugins/terminal/terminalcommands.h create mode 100644 src/plugins/terminal/terminalconstants.h create mode 100644 src/plugins/terminal/terminalicons.h diff --git a/src/plugins/terminal/CMakeLists.txt b/src/plugins/terminal/CMakeLists.txt index 083ffa844e6..69da526cdc0 100644 --- a/src/plugins/terminal/CMakeLists.txt +++ b/src/plugins/terminal/CMakeLists.txt @@ -10,7 +10,8 @@ add_qtc_plugin(Terminal shellintegration.cpp shellintegration.h shellmodel.cpp shellmodel.h terminal.qrc - terminalcommands.cpp terminalcommands.h + terminalconstants.h + terminalicons.h terminalpane.cpp terminalpane.h terminalplugin.cpp terminalprocessimpl.cpp terminalprocessimpl.h diff --git a/src/plugins/terminal/terminal.qbs b/src/plugins/terminal/terminal.qbs index 0fa1ba46316..c4c9de253e9 100644 --- a/src/plugins/terminal/terminal.qbs +++ b/src/plugins/terminal/terminal.qbs @@ -22,8 +22,8 @@ QtcPlugin { "shellintegration.cpp", "shellintegration.h", "terminal.qrc", - "terminalcommands.cpp", - "terminalcommands.h", + "terminalconstants.h", + "terminalicons.h" "terminalpane.cpp", "terminalpane.h", "terminalplugin.cpp", diff --git a/src/plugins/terminal/terminalcommands.cpp b/src/plugins/terminal/terminalcommands.cpp deleted file mode 100644 index 0e7cba8194c..00000000000 --- a/src/plugins/terminal/terminalcommands.cpp +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright (C) 2023 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "terminalcommands.h" -#include "terminaltr.h" - -#include -#include -#include -#include - -#include - -//#include - -using namespace Core; -using namespace Utils; - -namespace Terminal { - -constexpr char COPY[] = "Terminal.Copy"; -constexpr char PASTE[] = "Terminal.Paste"; -constexpr char COPY_LINK[] = "Terminal.CopyLink"; -constexpr char CLEARSELECTION[] = "Terminal.ClearSelection"; -constexpr char MOVECURSORWORDLEFT[] = "Terminal.MoveCursorWordLeft"; -constexpr char MOVECURSORWORDRIGHT[] = "Terminal.MoveCursorWordRight"; - -constexpr char NEWTERMINAL[] = "Terminal.NewTerminal"; -constexpr char CLOSETERMINAL[] = "Terminal.CloseTerminal"; -constexpr char NEXTTERMINAL[] = "Terminal.NextTerminal"; -constexpr char PREVTERMINAL[] = "Terminal.PrevTerminal"; -constexpr char MINMAX[] = "Terminal.MinMax"; - -TerminalCommands &TerminalCommands::instance() -{ - static TerminalCommands instance; - return instance; -} - -TerminalCommands::TerminalCommands() {} - -void TerminalCommands::init(const Core::Context &context) -{ - m_context = context; - initWidgetActions(); - initPaneActions(); - initGlobalCommands(); -} - -void TerminalCommands::registerAction(QAction &action, - const Utils::Id &id, - QList shortCuts) -{ - Command *cmd = ActionManager::instance()->registerAction(&action, id, m_context); - cmd->setKeySequences(shortCuts); - m_commands.push_back(cmd); -} - -void TerminalCommands::initWidgetActions() -{ - m_widgetActions.copy.setText(Tr::tr("Copy")); - m_widgetActions.paste.setText(Tr::tr("Paste")); - m_widgetActions.copyLink.setText(Tr::tr("Copy Link")); - m_widgetActions.clearSelection.setText(Tr::tr("Clear Selection")); - m_widgetActions.clearTerminal.setText(Tr::tr("Clear Terminal")); - m_widgetActions.moveCursorWordLeft.setText(Tr::tr("Move Cursor Word Left")); - m_widgetActions.moveCursorWordRight.setText(Tr::tr("Move Cursor Word Right")); - m_widgetActions.findNext.setText(Tr::tr("Find Next")); - m_widgetActions.findPrevious.setText(Tr::tr("Find Previous")); - - registerAction(m_widgetActions.copy, - COPY, - {QKeySequence(HostOsInfo::isMacHost() ? QLatin1String("Ctrl+C") - : QLatin1String("Ctrl+Shift+C"))}); - - registerAction(m_widgetActions.paste, - PASTE, - {QKeySequence(HostOsInfo::isMacHost() ? QLatin1String("Ctrl+V") - : QLatin1String("Ctrl+Shift+V"))}); - - registerAction(m_widgetActions.copyLink, COPY_LINK); - - registerAction(m_widgetActions.clearSelection, CLEARSELECTION); - - registerAction(m_widgetActions.moveCursorWordLeft, - MOVECURSORWORDLEFT, - {QKeySequence("Alt+Left")}); - - registerAction(m_widgetActions.moveCursorWordRight, - MOVECURSORWORDRIGHT, - {QKeySequence("Alt+Right")}); -} - -void TerminalCommands::initPaneActions() -{ - m_paneActions.newTerminal.setText(Tr::tr("New Terminal")); - m_paneActions.closeTerminal.setText(Tr::tr("Close Terminal")); - m_paneActions.nextTerminal.setText(Tr::tr("Next Terminal")); - m_paneActions.prevTerminal.setText(Tr::tr("Previous Terminal")); - m_paneActions.minMax.setText(Tr::tr("Minimize/Maximize Terminal")); - - registerAction(m_paneActions.newTerminal, - NEWTERMINAL, - {QKeySequence(HostOsInfo::isMacHost() ? QLatin1String("Ctrl+T") - : QLatin1String("Ctrl+Shift+T"))}); - - registerAction(m_paneActions.closeTerminal, - CLOSETERMINAL, - {QKeySequence(HostOsInfo::isMacHost() ? QLatin1String("Ctrl+W") - : QLatin1String("Ctrl+Shift+W"))}); - - registerAction(m_paneActions.nextTerminal, - NEXTTERMINAL, - {QKeySequence("ALT+TAB"), - QKeySequence(HostOsInfo::isMacHost() ? QLatin1String("Ctrl+Shift+[") - : QLatin1String("Ctrl+PgUp"))}); - - registerAction(m_paneActions.prevTerminal, - PREVTERMINAL, - {QKeySequence("ALT+SHIFT+TAB"), - QKeySequence(HostOsInfo::isMacHost() ? QLatin1String("Ctrl+Shift+]") - : QLatin1String("Ctrl+PgDown"))}); - - registerAction(m_paneActions.minMax, - MINMAX, - {QKeySequence(HostOsInfo::isMacHost() ? QLatin1String("Ctrl+Return") - : QLatin1String("Alt+Return"))}); -} - -void TerminalCommands::initGlobalCommands() -{ - // Global commands we still want to allow - m_commands.push_back(ActionManager::command(Constants::ZOOM_IN)); - m_commands.push_back(ActionManager::command(Constants::ZOOM_OUT)); - m_commands.push_back(ActionManager::command(Constants::EXIT)); - m_commands.push_back(ActionManager::command(Constants::OPTIONS)); -} - -bool TerminalCommands::triggerAction(QKeyEvent *event) -{ - QKeyCombination combination = event->keyCombination(); - - // On macOS, the arrow keys include the KeypadModifier, which we don't want. - if (HostOsInfo::isMacHost() && combination.keyboardModifiers() & Qt::KeypadModifier) - combination = QKeyCombination(combination.keyboardModifiers() & ~Qt::KeypadModifier, - combination.key()); - - for (const auto &command : TerminalCommands::instance().m_commands) { - if (!command->action()->isEnabled()) - continue; - - for (const auto &shortcut : command->keySequences()) { - const auto result = shortcut.matches(QKeySequence(combination)); - if (result == QKeySequence::ExactMatch) { - command->action()->trigger(); - return true; - } - } - } - - return false; -} - -QAction *TerminalCommands::openSettingsAction() -{ - return ActionManager::command("Preferences.Terminal.General")->action(); -} - -void TerminalCommands::lazyInitCommand(const Utils::Id &id) -{ - Command *cmd = ActionManager::command(id); - QTC_ASSERT(cmd, return); - m_commands.append(cmd); -} - -void TerminalCommands::lazyInitCommands() -{ - static const Utils::Id terminalPaneCmd("QtCreator.Pane.Terminal"); - lazyInitCommand(terminalPaneCmd); - lazyInitCommand(Core::Constants::FIND_IN_DOCUMENT); - lazyInitCommand(Core::Constants::FIND_NEXT); - lazyInitCommand(Core::Constants::FIND_PREVIOUS); - lazyInitCommand(Core::Constants::LOCATE); -} - -} // namespace Terminal diff --git a/src/plugins/terminal/terminalcommands.h b/src/plugins/terminal/terminalcommands.h deleted file mode 100644 index 71bc7ffe0f8..00000000000 --- a/src/plugins/terminal/terminalcommands.h +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (C) 2023 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#pragma once - -#include - -#include - -#include -#include -#include - -namespace Core { -class Command; -class Context; -} // namespace Core - -namespace Terminal { - -struct WidgetActions -{ - QAction copy; - QAction paste; - QAction copyLink; - QAction clearSelection; - QAction clearTerminal; - QAction moveCursorWordLeft; - QAction moveCursorWordRight; - QAction findNext; - QAction findPrevious; -}; - -struct PaneActions -{ - QAction newTerminal; - QAction closeTerminal; - QAction nextTerminal; - QAction prevTerminal; - QAction minMax; -}; - -class TerminalCommands -{ -public: - TerminalCommands(); - - void init(const Core::Context &context); - static TerminalCommands &instance(); - static WidgetActions &widgetActions() { return instance().m_widgetActions; } - static PaneActions &paneActions() { return instance().m_paneActions; } - - static QList shortcutsFor(QAction *action); - - static bool triggerAction(QKeyEvent *event); - - static QAction *openSettingsAction(); - - void lazyInitCommands(); - -protected: - void initWidgetActions(); - void initPaneActions(); - void initGlobalCommands(); - - void lazyInitCommand(const Utils::Id &id); - void registerAction(QAction &action, const Utils::Id &id, QList shortcuts = {}); - -private: - WidgetActions m_widgetActions; - PaneActions m_paneActions; - QList m_commands; - Core::Context m_context; -}; - -} // namespace Terminal diff --git a/src/plugins/terminal/terminalconstants.h b/src/plugins/terminal/terminalconstants.h new file mode 100644 index 00000000000..99700475e60 --- /dev/null +++ b/src/plugins/terminal/terminalconstants.h @@ -0,0 +1,19 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#pragma once + +namespace Terminal::Constants { +constexpr char NEWTERMINAL[] = "Terminal.NewTerminal"; +constexpr char NEXTTERMINAL[] = "Terminal.NextTerminal"; +constexpr char PREVTERMINAL[] = "Terminal.PrevTerminal"; +constexpr char MINMAX[] = "Terminal.MinMax"; + +constexpr char COPY[] = "Terminal.Copy"; +constexpr char PASTE[] = "Terminal.Paste"; +constexpr char CLEARSELECTION[] = "Terminal.ClearSelection"; +constexpr char MOVECURSORWORDLEFT[] = "Terminal.MoveCursorWordLeft"; +constexpr char MOVECURSORWORDRIGHT[] = "Terminal.MoveCursorWordRight"; +constexpr char CLEAR_TERMINAL[] = "Terminal.ClearTerminal"; + +} // namespace Terminal::Constants diff --git a/src/plugins/terminal/terminalicons.h b/src/plugins/terminal/terminalicons.h new file mode 100644 index 00000000000..ca503f50f96 --- /dev/null +++ b/src/plugins/terminal/terminalicons.h @@ -0,0 +1,18 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#pragma once + +#include + +namespace Terminal { + +static Utils::Icon NEW_TERMINAL_ICON( + {{":/terminal/images/terminal.png", Utils::Theme::IconsBaseColor}, + {":/utils/images/iconoverlay_add_small.png", Utils::Theme::IconsRunToolBarColor}}); + +static Utils::Icon CLOSE_TERMINAL_ICON( + {{":/terminal/images/terminal.png", Utils::Theme::IconsBaseColor}, + {":/utils/images/iconoverlay_close_small.png", Utils::Theme::IconsStopToolBarColor}}); + +} // namespace Terminal diff --git a/src/plugins/terminal/terminalpane.cpp b/src/plugins/terminal/terminalpane.cpp index 34370f22bb2..7cf0e308031 100644 --- a/src/plugins/terminal/terminalpane.cpp +++ b/src/plugins/terminal/terminalpane.cpp @@ -4,14 +4,17 @@ #include "terminalpane.h" #include "shellmodel.h" -#include "terminalcommands.h" +#include "terminalconstants.h" +#include "terminalicons.h" #include "terminalsettings.h" #include "terminaltr.h" #include "terminalwidget.h" #include +#include #include #include +#include #include #include @@ -29,15 +32,15 @@ namespace Terminal { using namespace Utils; using namespace Utils::Terminal; +using namespace Core; TerminalPane::TerminalPane(QObject *parent) - : Core::IOutputPane(parent) + : IOutputPane(parent) + , m_context("Terminal.Pane", Core::Constants::C_GLOBAL_CUTOFF) { - setupContext("Terminal.Pane", &m_tabWidget); + setupContext(m_context, &m_tabWidget); setZoomButtonsEnabled(true); - TerminalCommands::instance().init(Core::Context("Terminal.Pane")); - connect(this, &IOutputPane::zoomInRequested, this, [this] { if (currentTerminal()) currentTerminal()->zoomIn(); @@ -47,89 +50,24 @@ TerminalPane::TerminalPane(QObject *parent) currentTerminal()->zoomOut(); }); - QAction &newTerminal = TerminalCommands::instance().paneActions().newTerminal; - QAction &closeTerminal = TerminalCommands::instance().paneActions().closeTerminal; - - newTerminal.setIcon( - Icon({{":/terminal/images/terminal.png", Theme::IconsBaseColor}, - {":/utils/images/iconoverlay_add_small.png", Theme::IconsRunToolBarColor}}) - .icon()); - newTerminal.setToolTip(Tr::tr("Create a new Terminal.")); - - connect(&newTerminal, &QAction::triggered, this, [this] { openTerminal({}); }); - - closeTerminal.setIcon( - Icon({{":/terminal/images/terminal.png", Theme::IconsBaseColor}, - {":/utils/images/iconoverlay_close_small.png", Theme::IconsStopToolBarColor}}) - .icon()); - closeTerminal.setToolTip(Tr::tr("Close the current Terminal.")); - - connect(&closeTerminal, &QAction::triggered, this, [this] { - removeTab(m_tabWidget.currentIndex()); - }); + initActions(); m_newTerminalButton = new QToolButton(); - - QMenu *shellMenu = new QMenu(m_newTerminalButton); - const Internal::ShellModel *shellModel = new Internal::ShellModel(shellMenu); - connect(shellMenu, &QMenu::aboutToShow, shellMenu, [shellMenu, shellModel, pane = this] { - shellMenu->clear(); - - const auto addItems = [shellMenu, pane](const QList &items) { - for (const Internal::ShellModelItem &item : items) { - QAction *action = new QAction(item.icon, item.name, shellMenu); - - connect(action, &QAction::triggered, action, [item, pane]() { - pane->openTerminal(item.openParameters); - }); - - shellMenu->addAction(action); - } - }; - - addItems(shellModel->local()); - shellMenu->addSection(Tr::tr("Devices")); - addItems(shellModel->remote()); - }); - - newTerminal.setMenu(shellMenu); - m_newTerminalButton->setDefaultAction(&newTerminal); m_closeTerminalButton = new QToolButton(); m_closeTerminalButton->setDefaultAction(&closeTerminal); - connect(&TerminalCommands::instance().paneActions().nextTerminal, - &QAction::triggered, - this, - [this] { - if (canNavigate()) - goToNext(); - }); - connect(&TerminalCommands::instance().paneActions().prevTerminal, - &QAction::triggered, - this, - [this] { - if (canPrevious()) - goToPrev(); - }); - - connect(&TerminalCommands::instance().paneActions().minMax, &QAction::triggered, this, []() { - Core::Command *minMaxCommand = Core::ActionManager::command("Coreplugin.OutputPane.minmax"); - if (minMaxCommand) - emit minMaxCommand->action()->triggered(); - }); - m_openSettingsButton = new QToolButton(); - m_openSettingsButton->setToolTip(Tr::tr("Open Terminal Settings")); + m_openSettingsButton->setToolTip(Tr::tr("Configure...")); m_openSettingsButton->setIcon(Icons::SETTINGS_TOOLBAR.icon()); connect(m_openSettingsButton, &QToolButton::clicked, m_openSettingsButton, []() { - TerminalCommands::openSettingsAction()->trigger(); + ICore::showOptionsDialog("Terminal.General"); }); const auto updateEscButton = [this] { - m_escSettingButton->setChecked(TerminalSettings::instance().sendEscapeToTerminal.value()); + m_escSettingButton->setChecked(TerminalSettings::instance().sendEscapeToTerminal()); static const QString escKey = QKeySequence(Qt::Key_Escape).toString(QKeySequence::NativeText); static const QString shiftEsc = QKeySequence( @@ -151,7 +89,7 @@ TerminalPane::TerminalPane(QObject *parent) connect(m_escSettingButton, &QToolButton::toggled, this, [this] { TerminalSettings::instance().sendEscapeToTerminal.setValue(m_escSettingButton->isChecked()); - TerminalSettings::instance().writeSettings(Core::ICore::settings()); + TerminalSettings::instance().writeSettings(ICore::settings()); }); connect(&TerminalSettings::instance(), &TerminalSettings::applied, this, updateEscButton); @@ -242,10 +180,6 @@ QWidget *TerminalPane::outputWidget(QWidget *parent) else emit hidePage(); }); - - const auto terminalWidget = new TerminalWidget(parent); - m_tabWidget.addTab(terminalWidget, Tr::tr("Terminal")); - setupTerminalWidget(terminalWidget); } return &m_tabWidget; @@ -289,6 +223,81 @@ void TerminalPane::setupTerminalWidget(TerminalWidget *terminal) setTabText(); } +void TerminalPane::initActions() +{ + createShellMenu(); + + newTerminal.setText(Tr::tr("New Terminal")); + newTerminal.setIcon(NEW_TERMINAL_ICON.icon()); + newTerminal.setToolTip(Tr::tr("Create a new Terminal.")); + newTerminal.setMenu(&m_shellMenu); + + nextTerminal.setText(Tr::tr("Next Terminal")); + prevTerminal.setText(Tr::tr("Previous Terminal")); + + closeTerminal.setIcon(CLOSE_TERMINAL_ICON.icon()); + closeTerminal.setToolTip(Tr::tr("Close the current Terminal.")); + + using namespace Constants; + + ActionManager::registerAction(&newTerminal, NEWTERMINAL, m_context) + ->setDefaultKeySequences({QKeySequence( + HostOsInfo::isMacHost() ? QLatin1String("Ctrl+T") : QLatin1String("Ctrl+Shift+T"))}); + + ActionManager::registerAction(&nextTerminal, NEXTTERMINAL, m_context) + ->setDefaultKeySequences( + {QKeySequence("Alt+Tab"), + QKeySequence(HostOsInfo::isMacHost() ? QLatin1String("Ctrl+Shift+[") + : QLatin1String("Ctrl+PgUp"))}); + + ActionManager::registerAction(&prevTerminal, PREVTERMINAL, m_context) + ->setDefaultKeySequences( + {QKeySequence("Alt+Shift+Tab"), + QKeySequence(HostOsInfo::isMacHost() ? QLatin1String("Ctrl+Shift+]") + : QLatin1String("Ctrl+PgDown"))}); + + m_minMax = TerminalWidget::unlockGlobalAction("Coreplugin.OutputPane.minmax", m_context); + m_locate = TerminalWidget::unlockGlobalAction(Core::Constants::LOCATE, m_context); + + connect(&newTerminal, &QAction::triggered, this, [this] { openTerminal({}); }); + connect(&closeTerminal, &QAction::triggered, this, [this] { + removeTab(m_tabWidget.currentIndex()); + }); + connect(&nextTerminal, &QAction::triggered, this, [this] { + if (canNavigate()) + goToNext(); + }); + connect(&prevTerminal, &QAction::triggered, this, [this] { + if (canPrevious()) + goToPrev(); + }); +} + +void TerminalPane::createShellMenu() +{ + const Internal::ShellModel *shellModel = new Internal::ShellModel(&m_shellMenu); + + connect(&m_shellMenu, &QMenu::aboutToShow, &m_shellMenu, [shellModel, this] { + m_shellMenu.clear(); + + const auto addItems = [this](const QList &items) { + for (const Internal::ShellModelItem &item : items) { + QAction *action = new QAction(item.icon, item.name, &m_shellMenu); + + connect(action, &QAction::triggered, action, [item, this]() { + openTerminal(item.openParameters); + }); + + m_shellMenu.addAction(action); + } + }; + + addItems(shellModel->local()); + m_shellMenu.addSection(Tr::tr("Devices")); + addItems(shellModel->remote()); + }); +} + QList TerminalPane::toolBarWidgets() const { QList widgets = IOutputPane::toolBarWidgets(); diff --git a/src/plugins/terminal/terminalpane.h b/src/plugins/terminal/terminalpane.h index 6ef2d005357..21f15168f26 100644 --- a/src/plugins/terminal/terminalpane.h +++ b/src/plugins/terminal/terminalpane.h @@ -3,11 +3,14 @@ #pragma once +#include "terminalwidget.h" + #include #include #include +#include #include #include @@ -49,6 +52,8 @@ private: void removeTab(int index); void setupTerminalWidget(TerminalWidget *terminal); + void initActions(); + void createShellMenu(); private: QTabWidget m_tabWidget; @@ -58,6 +63,18 @@ private: QToolButton *m_openSettingsButton{nullptr}; QToolButton *m_escSettingButton{nullptr}; + UnlockedGlobalAction m_minMax; + UnlockedGlobalAction m_locate; + + QAction newTerminal; + QAction nextTerminal; + QAction prevTerminal; + QAction closeTerminal; + + QMenu m_shellMenu; + + Core::Context m_context; + bool m_widgetInitialized{false}; bool m_isVisible{false}; }; diff --git a/src/plugins/terminal/terminalplugin.cpp b/src/plugins/terminal/terminalplugin.cpp index 4738bf9b307..38b58b1722f 100644 --- a/src/plugins/terminal/terminalplugin.cpp +++ b/src/plugins/terminal/terminalplugin.cpp @@ -4,7 +4,7 @@ #include "terminalpane.h" #include "terminalprocessimpl.h" #include "terminalsettings.h" -#include "terminalcommands.h" +#include "terminalwidget.h" #include #include @@ -39,16 +39,15 @@ public: m_terminalPane = nullptr; } - void initialize() final - { - addManaged(); - } + void initialize() final { addManaged(); } void extensionsInitialized() final { m_terminalPane = new TerminalPane; ExtensionSystem::PluginManager::addObject(m_terminalPane); + TerminalWidget::initActions(); + auto enable = [this] { Utils::Terminal::Hooks::instance() .addCallbackSet("Internal", @@ -71,21 +70,18 @@ public: } }; - QObject::connect(&TerminalSettings::instance(), &Utils::AspectContainer::applied, this, settingsChanged); + QObject::connect(&TerminalSettings::instance(), + &Utils::AspectContainer::applied, + this, + settingsChanged); settingsChanged(); } - bool delayedInitialize() final - { - TerminalCommands::instance().lazyInitCommands(); - return true; - } - private: TerminalPane *m_terminalPane{nullptr}; }; -} // Terminal::Internal +} // namespace Terminal::Internal #include "terminalplugin.moc" diff --git a/src/plugins/terminal/terminalsearch.cpp b/src/plugins/terminal/terminalsearch.cpp index e909e75dfe6..69a412b1948 100644 --- a/src/plugins/terminal/terminalsearch.cpp +++ b/src/plugins/terminal/terminalsearch.cpp @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "terminalsearch.h" -#include "terminalcommands.h" #include #include @@ -28,15 +27,6 @@ TerminalSearch::TerminalSearch(TerminalSurface *surface) connect(surface, &TerminalSurface::invalidated, this, &TerminalSearch::updateHits); connect(&m_debounceTimer, &QTimer::timeout, this, &TerminalSearch::debouncedUpdateHits); - - connect(&TerminalCommands::widgetActions().findNext, - &QAction::triggered, - this, - &TerminalSearch::nextHit); - connect(&TerminalCommands::widgetActions().findPrevious, - &QAction::triggered, - this, - &TerminalSearch::previousHit); } void TerminalSearch::setCurrentSelection(std::optional selection) diff --git a/src/plugins/terminal/terminalwidget.cpp b/src/plugins/terminal/terminalwidget.cpp index b63e66b78dd..5027d390294 100644 --- a/src/plugins/terminal/terminalwidget.cpp +++ b/src/plugins/terminal/terminalwidget.cpp @@ -3,9 +3,10 @@ #include "terminalwidget.h" #include "glyphcache.h" -#include "terminalcommands.h" +#include "terminalconstants.h" #include "terminalsettings.h" #include "terminalsurface.h" +#include "terminaltr.h" #include @@ -20,6 +21,7 @@ #include #include #include +#include #include #include @@ -50,6 +52,7 @@ Q_LOGGING_CATEGORY(paintLog, "qtc.terminal.paint", QtWarningMsg) using namespace Utils; using namespace Utils::Terminal; +using namespace Core; namespace Terminal { @@ -69,10 +72,16 @@ static constexpr std::chrono::milliseconds minRefreshInterval = 1s / 30; TerminalWidget::TerminalWidget(QWidget *parent, const OpenTerminalParameters &openParameters) : QAbstractScrollArea(parent) + , m_context(Utils::Id("TerminalWidget_").withSuffix((size_t) this)) , m_openParameters(openParameters) , m_lastFlush(std::chrono::system_clock::now()) , m_lastDoubleClick(std::chrono::system_clock::now()) { + auto contextObj = new IContext(this); + contextObj->setWidget(this); + contextObj->setContext(m_context); + ICore::addContextObject(contextObj); + setupSurface(); setupFont(); setupColors(); @@ -245,24 +254,31 @@ void TerminalWidget::setupColors() void TerminalWidget::setupActions() { - WidgetActions &a = TerminalCommands::widgetActions(); + ActionManager::registerAction(&m_copy, Constants::COPY, m_context); + ActionManager::registerAction(&m_paste, Constants::PASTE, m_context); + ActionManager::registerAction(&m_close, Core::Constants::CLOSE, m_context); + ActionManager::registerAction(&m_clearTerminal, Constants::CLEAR_TERMINAL, m_context); + ActionManager::registerAction(&m_clearSelection, Constants::CLEARSELECTION, m_context); + ActionManager::registerAction(&m_moveCursorWordLeft, Constants::MOVECURSORWORDLEFT, m_context); + ActionManager::registerAction(&m_moveCursorWordRight, Constants::MOVECURSORWORDRIGHT, m_context); - auto ifHasFocus = [this](void (TerminalWidget::*f)()) { - return [this, f] { - if (hasFocus()) - (this->*f)(); - }; - }; + connect(&m_copy, &QAction::triggered, this, &TerminalWidget::copyToClipboard); + connect(&m_paste, &QAction::triggered, this, &TerminalWidget::pasteFromClipboard); + connect(&m_close, &QAction::triggered, this, &TerminalWidget::closeTerminal); + connect(&m_clearTerminal, &QAction::triggered, this, &TerminalWidget::clearContents); + connect(&m_clearSelection, &QAction::triggered, this, &TerminalWidget::clearSelection); + connect(&m_moveCursorWordLeft, &QAction::triggered, this, &TerminalWidget::moveCursorWordLeft); + connect(&m_moveCursorWordRight, &QAction::triggered, this, &TerminalWidget::moveCursorWordRight); - // clang-format off - connect(&a.copy, &QAction::triggered, this, ifHasFocus(&TerminalWidget::copyToClipboard)); - connect(&a.paste, &QAction::triggered, this, ifHasFocus(&TerminalWidget::pasteFromClipboard)); - connect(&a.copyLink, &QAction::triggered, this, ifHasFocus(&TerminalWidget::copyLinkToClipboard)); - connect(&a.clearSelection, &QAction::triggered, this, ifHasFocus(&TerminalWidget::clearSelection)); - connect(&a.clearTerminal, &QAction::triggered, this, ifHasFocus(&TerminalWidget::clearContents)); - connect(&a.moveCursorWordLeft, &QAction::triggered, this, ifHasFocus(&TerminalWidget::moveCursorWordLeft)); - connect(&a.moveCursorWordRight, &QAction::triggered, this, ifHasFocus(&TerminalWidget::moveCursorWordRight)); - // clang-format on + m_exit = unlockGlobalAction(Core::Constants::EXIT, m_context); + m_options = unlockGlobalAction(Core::Constants::OPTIONS, m_context); + m_settings = unlockGlobalAction("Preferences.Terminal.General", m_context); + m_findInDocument = unlockGlobalAction(Core::Constants::FIND_IN_DOCUMENT, m_context); +} + +void TerminalWidget::closeTerminal() +{ + deleteLater(); } void TerminalWidget::writeToPty(const QByteArray &data) @@ -385,8 +401,7 @@ void TerminalWidget::updateCopyState() if (!hasFocus()) return; - TerminalCommands::widgetActions().copy.setEnabled(m_selection.has_value()); - TerminalCommands::widgetActions().copyLink.setEnabled(m_linkSelection.has_value()); + m_copy.setEnabled(m_selection.has_value()); } void TerminalWidget::setFont(const QFont &font) @@ -511,6 +526,8 @@ QString TerminalWidget::textFromSelection() const Internal::CellIterator it = m_surface->iteratorAt(m_selection->start); Internal::CellIterator end = m_surface->iteratorAt(m_selection->end); + QTC_ASSERT(it.position() < end.position(), return {}); + std::u32string s; bool previousWasZero = false; for (; it != end; ++it) { @@ -1078,21 +1095,16 @@ void TerminalWidget::keyPressEvent(QKeyEvent *event) } if (m_selection) - TerminalCommands::widgetActions().clearSelection.trigger(); + m_clearSelection.trigger(); else { - QTC_ASSERT(Core::ActionManager::command(Core::Constants::S_RETURNTOEDITOR), return); - Core::ActionManager::command(Core::Constants::S_RETURNTOEDITOR)->action()->trigger(); + QAction *returnAction = ActionManager::command(Core::Constants::S_RETURNTOEDITOR) + ->actionForContext(Core::Constants::C_GLOBAL); + QTC_ASSERT(returnAction, return); + returnAction->trigger(); } return; } - auto oldSelection = m_selection; - if (TerminalCommands::triggerAction(event)) { - if (oldSelection && oldSelection == m_selection) - setSelection(std::nullopt); - return; - } - if (event->key() == Qt::Key_Control) { if (!m_linkSelection.has_value() && checkLinkAt(mapFromGlobal(QCursor::pos()))) { setCursor(Qt::PointingHandCursor); @@ -1236,7 +1248,7 @@ void TerminalWidget::mousePressEvent(QMouseEvent *event) if (m_linkSelection->link.targetFilePath.isDir()) Core::FileUtils::showInFileSystemView(m_linkSelection->link.targetFilePath); else - Core::EditorManager::openEditorAt(m_linkSelection->link); + EditorManager::openEditorAt(m_linkSelection->link); } return; } @@ -1261,13 +1273,18 @@ void TerminalWidget::mousePressEvent(QMouseEvent *event) } else if (event->button() == Qt::RightButton) { if (event->modifiers() & Qt::ShiftModifier) { QMenu *contextMenu = new QMenu(this); - contextMenu->addAction(&TerminalCommands::widgetActions().copy); - contextMenu->addAction(&TerminalCommands::widgetActions().paste); - contextMenu->addAction(&TerminalCommands::widgetActions().copyLink); + QAction *configureAction = new QAction(contextMenu); + configureAction->setText(Tr::tr("Configure...")); + connect(configureAction, &QAction::triggered, this, [] { + ICore::showOptionsDialog("Terminal.General"); + }); + + contextMenu->addAction(ActionManager::command(Constants::COPY)->action()); + contextMenu->addAction(ActionManager::command(Constants::PASTE)->action()); contextMenu->addSeparator(); - contextMenu->addAction(&TerminalCommands::widgetActions().clearTerminal); + contextMenu->addAction(ActionManager::command(Constants::CLEAR_TERMINAL)->action()); contextMenu->addSeparator(); - contextMenu->addAction(TerminalCommands::openSettingsAction()); + contextMenu->addAction(configureAction); contextMenu->popup(event->globalPos()); } else if (m_selection) { @@ -1472,11 +1489,10 @@ void TerminalWidget::showEvent(QShowEvent *event) bool TerminalWidget::event(QEvent *event) { - if (event->type() == QEvent::ShortcutOverride) { - if (hasFocus()) { - event->accept(); - return true; - } + if (event->type() == QEvent::Paint) { + QPainter p(this); + p.fillRect(QRect(QPoint(0, 0), size()), m_currentColors[ColorIndex::Background]); + return true; } if (event->type() == QEvent::KeyPress) { @@ -1490,13 +1506,63 @@ bool TerminalWidget::event(QEvent *event) return true; } - if (event->type() == QEvent::Paint) { - QPainter p(this); - p.fillRect(QRect(QPoint(0, 0), size()), m_currentColors[ColorIndex::Background]); - return true; - } - return QAbstractScrollArea::event(event); } +void TerminalWidget::initActions() +{ + Core::Context context(Utils::Id("TerminalWidget")); + + static QAction copy; + static QAction paste; + static QAction clearSelection; + static QAction clearTerminal; + static QAction moveCursorWordLeft; + static QAction moveCursorWordRight; + static QAction close; + + copy.setText(Tr::tr("Copy")); + paste.setText(Tr::tr("Paste")); + clearSelection.setText(Tr::tr("Clear Selection")); + clearTerminal.setText(Tr::tr("Clear Terminal")); + moveCursorWordLeft.setText(Tr::tr("Move Cursor Word Left")); + moveCursorWordRight.setText(Tr::tr("Move Cursor Word Right")); + close.setText(Tr::tr("Close Terminal")); + + ActionManager::registerAction(©, Constants::COPY, context) + ->setDefaultKeySequences({QKeySequence( + HostOsInfo::isMacHost() ? QLatin1String("Ctrl+C") : QLatin1String("Ctrl+Shift+C"))}); + + ActionManager::registerAction(&paste, Constants::PASTE, context) + ->setDefaultKeySequences({QKeySequence( + HostOsInfo::isMacHost() ? QLatin1String("Ctrl+V") : QLatin1String("Ctrl+Shift+V"))}); + + ActionManager::registerAction(&clearSelection, Constants::CLEARSELECTION, context); + + ActionManager::registerAction(&moveCursorWordLeft, Constants::MOVECURSORWORDLEFT, context) + ->setDefaultKeySequences({QKeySequence("Alt+Left")}); + + ActionManager::registerAction(&moveCursorWordRight, Constants::MOVECURSORWORDRIGHT, context) + ->setDefaultKeySequences({QKeySequence("Alt+Right")}); + + ActionManager::registerAction(&clearTerminal, Constants::CLEAR_TERMINAL, context); +} + +UnlockedGlobalAction TerminalWidget::unlockGlobalAction(const Utils::Id &commandId, + const Context &context) +{ + QAction *srcAction = ActionManager::command(commandId)->actionForContext( + Core::Constants::C_GLOBAL); + + ProxyAction *proxy = ProxyAction::proxyActionWithIcon(srcAction, srcAction->icon()); + ActionManager::registerAction(proxy, commandId, context); + + UnlockedGlobalAction registeredAction(proxy, [commandId](QAction *a) { + ActionManager::unregisterAction(a, commandId); + delete a; + }); + + return registeredAction; +} + } // namespace Terminal diff --git a/src/plugins/terminal/terminalwidget.h b/src/plugins/terminal/terminalwidget.h index f44a721bd31..4b82e4355a1 100644 --- a/src/plugins/terminal/terminalwidget.h +++ b/src/plugins/terminal/terminalwidget.h @@ -8,6 +8,8 @@ #include +#include + #include #include #include @@ -22,6 +24,8 @@ namespace Terminal { +using UnlockedGlobalAction = std::unique_ptr>; + class TerminalWidget : public QAbstractScrollArea { friend class CellIterator; @@ -46,6 +50,8 @@ public: void clearContents(); + void closeTerminal(); + TerminalSearch *search() { return m_search.get(); } struct Selection @@ -82,6 +88,11 @@ public: void restart(const Utils::Terminal::OpenTerminalParameters &openParameters); + static void initActions(); + + [[nodiscard]] static UnlockedGlobalAction unlockGlobalAction(const Utils::Id &commandId, + const Core::Context &context); + signals: void started(qint64 pid); void cwdChanged(const Utils::FilePath &cwd); @@ -178,6 +189,7 @@ protected: void updateCopyState(); private: + Core::Context m_context; std::unique_ptr m_process; std::unique_ptr m_surface; std::unique_ptr m_shellIntegration; @@ -226,6 +238,19 @@ private: Aggregation::Aggregate *m_aggregate{nullptr}; SearchHit m_lastSelectedHit{}; + + QAction m_copy; + QAction m_paste; + QAction m_clearSelection; + QAction m_clearTerminal; + QAction m_moveCursorWordLeft; + QAction m_moveCursorWordRight; + QAction m_close; + + UnlockedGlobalAction m_findInDocument; + UnlockedGlobalAction m_exit; + UnlockedGlobalAction m_options; + UnlockedGlobalAction m_settings; }; } // namespace Terminal From 476651e5a3e6eb0b05b6cb18c04f6b3fbf48a894 Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Thu, 25 May 2023 18:56:03 +0200 Subject: [PATCH 043/141] McuSupport: inline mcukitcreationdialog.ui Change-Id: I1c88663248dceb318f9acbabe585fbd24e794ab6 Reviewed-by: hjk Reviewed-by: --- src/plugins/mcusupport/CMakeLists.txt | 2 +- .../dialogs/mcukitcreationdialog.cpp | 86 +++++++--- .../mcusupport/dialogs/mcukitcreationdialog.h | 17 +- .../dialogs/mcukitcreationdialog.ui | 154 ------------------ src/plugins/mcusupport/mcusupport.qbs | 1 - 5 files changed, 72 insertions(+), 188 deletions(-) delete mode 100644 src/plugins/mcusupport/dialogs/mcukitcreationdialog.ui diff --git a/src/plugins/mcusupport/CMakeLists.txt b/src/plugins/mcusupport/CMakeLists.txt index b0ff6d8fc45..e2d81ae5a73 100644 --- a/src/plugins/mcusupport/CMakeLists.txt +++ b/src/plugins/mcusupport/CMakeLists.txt @@ -24,7 +24,7 @@ add_qtc_plugin(McuSupport settingshandler.cpp settingshandler.h mcuqmlprojectnode.cpp mcuqmlprojectnode.h mcubuildstep.cpp mcubuildstep.h - dialogs/mcukitcreationdialog.h dialogs/mcukitcreationdialog.cpp dialogs/mcukitcreationdialog.ui + dialogs/mcukitcreationdialog.cpp dialogs/mcukitcreationdialog.h ) add_subdirectory(test) diff --git a/src/plugins/mcusupport/dialogs/mcukitcreationdialog.cpp b/src/plugins/mcusupport/dialogs/mcukitcreationdialog.cpp index 7327f582115..9702fb77bfb 100644 --- a/src/plugins/mcusupport/dialogs/mcukitcreationdialog.cpp +++ b/src/plugins/mcusupport/dialogs/mcukitcreationdialog.cpp @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "mcukitcreationdialog.h" -#include "ui_mcukitcreationdialog.h" #include "../mcuabstractpackage.h" #include "../mcusupportconstants.h" @@ -10,11 +9,15 @@ #include #include +#include #include -#include +#include #include +#include +#include +#include #include namespace McuSupport::Internal { @@ -24,18 +27,56 @@ McuKitCreationDialog::McuKitCreationDialog(const MessagesList &messages, McuPackagePtr qtMCUPackage, QWidget *parent) : QDialog(parent) - , ui(new Ui::McuKitCreationDialog) , m_messages(messages) { - ui->setupUi(this); - ui->iconLabel->setPixmap(Utils::Icon(":/mcusupport/images/mcusupportdevice.png").pixmap()); - m_previousButton = ui->buttonBox->addButton("<", QDialogButtonBox::ActionRole); - m_nextButton = ui->buttonBox->addButton(">", QDialogButtonBox::ActionRole); - m_fixButton = ui->buttonBox->addButton(Tr::tr("Fix"), QDialogButtonBox::ActionRole); - m_helpButton = ui->buttonBox->addButton(Tr::tr("Help"), QDialogButtonBox::HelpRole); - // prevent clicking the buttons from closing the message box - m_nextButton->disconnect(); - m_previousButton->disconnect(); + resize(500, 300); + setWindowTitle(Tr::tr("Qt for MCUs Kit Creation")); + + m_iconLabel = new QLabel; + m_iconLabel->setAlignment(Qt::AlignTop); + + m_textLabel = new QLabel; + + m_informationLabel = new QLabel; + m_informationLabel->setWordWrap(true); + m_informationLabel->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + m_informationLabel->setAlignment(Qt::AlignTop); + + m_qtMCUsPathLabel = new QLabel; + + auto line = new QFrame; + line->setFrameShape(QFrame::VLine); + line->setFrameShadow(QFrame::Sunken); + + auto buttonBox = new QDialogButtonBox(Qt::Vertical); + buttonBox->setStandardButtons(QDialogButtonBox::Ignore); + + m_messageCountLabel = new QLabel; + m_messageCountLabel->setAlignment(Qt::AlignCenter); + + using namespace Layouting; + Row { + Column { + Row { + m_iconLabel, + Column { + m_textLabel, + m_informationLabel, + }, + }, + m_qtMCUsPathLabel, + }, + line, + Column { + buttonBox, + m_messageCountLabel, + }, + }.attachTo(this); + + m_previousButton = buttonBox->addButton("<", QDialogButtonBox::ActionRole); + m_nextButton = buttonBox->addButton(">", QDialogButtonBox::ActionRole); + QPushButton *fixButton = buttonBox->addButton(Tr::tr("Fix"), QDialogButtonBox::ActionRole); + QPushButton *helpButton = buttonBox->addButton(Tr::tr("Help"), QDialogButtonBox::HelpRole); if (messages.size() == 1) { m_nextButton->setVisible(false); @@ -46,20 +87,22 @@ McuKitCreationDialog::McuKitCreationDialog(const MessagesList &messages, updateMessage(1); if (qtMCUPackage->isValidStatus()) - ui->qtMCUsPathLabel->setText( + m_qtMCUsPathLabel->setText( Tr::tr("Qt for MCUs path %1").arg(qtMCUPackage->path().toUserOutput())); connect(m_nextButton, &QPushButton::clicked, [=] { updateMessage(1); }); connect(m_previousButton, &QPushButton::clicked, [=] { updateMessage(-1); }); - connect(m_fixButton, &QPushButton::clicked, [=] { + connect(fixButton, &QPushButton::clicked, [=] { // Open the MCU Options widget on the current platform settingsHandler->setInitialPlatformName(m_messages[m_currentIndex].platform); Core::ICore::showOptionsDialog(Constants::SETTINGS_ID); // reset the initial platform name settingsHandler->setInitialPlatformName(""); }); - connect(m_helpButton, &QPushButton::clicked, [] { + connect(helpButton, &QPushButton::clicked, [] { QDesktopServices::openUrl(QUrl("https://doc.qt.io/QtForMCUs/qtul-prerequisites.html")); }); + connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); + connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); } void McuKitCreationDialog::updateMessage(const int inc) @@ -67,30 +110,25 @@ void McuKitCreationDialog::updateMessage(const int inc) m_currentIndex += inc; m_nextButton->setEnabled(m_currentIndex < (m_messages.size() - 1)); m_previousButton->setEnabled(m_currentIndex > 0); - ui->textLabel->setText(QString("%1 %2 : %3") + m_textLabel->setText(QString("%1 %2 : %3") .arg(Tr::tr("Target"), (m_messages[m_currentIndex].status == McuSupportMessage::Warning ? Tr::tr("Warning") : Tr::tr("Error")), m_messages[m_currentIndex].platform)); - ui->iconLabel->setPixmap( + m_iconLabel->setPixmap( QApplication::style() ->standardIcon(m_messages[m_currentIndex].status == McuSupportMessage::Warning ? QStyle::SP_MessageBoxWarning : QStyle::SP_MessageBoxCritical) .pixmap(64, 64)); - ui->informationLabel->setText(QString("%1: %2

%3: %4") + m_informationLabel->setText(QString("%1: %2

%3: %4") .arg(Tr::tr("Package"), m_messages[m_currentIndex].packageName, Tr::tr("Status"), m_messages.at(m_currentIndex).message)); - ui->messageCountLabel->setText(QString("%1 / %2").arg(QString::number(m_currentIndex + 1), + m_messageCountLabel->setText(QString("%1 / %2").arg(QString::number(m_currentIndex + 1), QString::number(m_messages.size()))); } -McuKitCreationDialog::~McuKitCreationDialog() -{ - delete ui; -} - } // namespace McuSupport::Internal diff --git a/src/plugins/mcusupport/dialogs/mcukitcreationdialog.h b/src/plugins/mcusupport/dialogs/mcukitcreationdialog.h index 7164c6d0efb..6caae59678f 100644 --- a/src/plugins/mcusupport/dialogs/mcukitcreationdialog.h +++ b/src/plugins/mcusupport/dialogs/mcukitcreationdialog.h @@ -7,11 +7,11 @@ #include "../settingshandler.h" #include -#include -namespace Ui { -class McuKitCreationDialog; -} +QT_BEGIN_NAMESPACE +class QLabel; +class QPushButton; +QT_END_NAMESPACE namespace McuSupport::Internal { @@ -24,18 +24,19 @@ public: const SettingsHandler::Ptr &settingsHandler, McuPackagePtr qtMCUPackage, QWidget *parent = nullptr); - ~McuKitCreationDialog(); private slots: void updateMessage(const int inc); private: - Ui::McuKitCreationDialog *ui; int m_currentIndex = -1; + QLabel *m_iconLabel; + QLabel *m_textLabel; + QLabel *m_informationLabel; + QLabel *m_qtMCUsPathLabel; + QLabel *m_messageCountLabel; QPushButton *m_previousButton; QPushButton *m_nextButton; - QPushButton *m_helpButton; - QPushButton *m_fixButton; const MessagesList &m_messages; }; } // namespace McuSupport::Internal diff --git a/src/plugins/mcusupport/dialogs/mcukitcreationdialog.ui b/src/plugins/mcusupport/dialogs/mcukitcreationdialog.ui deleted file mode 100644 index f6194bbe6e3..00000000000 --- a/src/plugins/mcusupport/dialogs/mcukitcreationdialog.ui +++ /dev/null @@ -1,154 +0,0 @@ - - - McuKitCreationDialog - - - - 0 - 0 - 349 - 200 - - - - QtMCUs Kit Creation - - - true - - - - - - QtMCUs path: - - - - - - - Qt::Vertical - - - - - - - 1/3 - - - Qt::AlignCenter - - - - - - - Qt::Vertical - - - QDialogButtonBox::Ignore - - - - - - - Dialog text - - - Qt::RichText - - - true - - - - - - - - 64 - 64 - - - - - 70 - 1000 - - - - - - - false - - - Qt::AlignHCenter|Qt::AlignTop - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - TextLabel - - - Qt::RichText - - - - - - - - - - - buttonBox - accepted() - McuKitCreationDialog - accept() - - - 339 - 23 - - - 157 - 199 - - - - - buttonBox - rejected() - McuKitCreationDialog - reject() - - - 339 - 29 - - - 286 - 199 - - - - - diff --git a/src/plugins/mcusupport/mcusupport.qbs b/src/plugins/mcusupport/mcusupport.qbs index 7b686075cac..173fe55e6e8 100644 --- a/src/plugins/mcusupport/mcusupport.qbs +++ b/src/plugins/mcusupport/mcusupport.qbs @@ -58,7 +58,6 @@ QtcPlugin { "mcuhelpers.h", "settingshandler.h", "settingshandler.cpp", - "dialogs/mcukitcreationdialog.ui", "dialogs/mcukitcreationdialog.h", "dialogs/mcukitcreationdialog.cpp", ] From 95b4da9ba98f6fec624b8d8aee9fae58211668d6 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Mon, 14 Nov 2022 12:54:05 +0100 Subject: [PATCH 044/141] TextEditor: add tests for the code assistant Task-number: QTCREATORBUG-28989 Change-Id: Id76d5df589ab50c7deb96b8ad29d1f29bc368e59 Reviewed-by: Christian Stenger --- src/plugins/texteditor/CMakeLists.txt | 4 +- .../texteditor/codeassist/codeassist_test.cpp | 152 ++++++++++++++++++ .../texteditor/codeassist/codeassist_test.h | 37 +++++ src/plugins/texteditor/texteditor.qbs | 2 + src/plugins/texteditor/texteditor_test.cpp | 19 +-- src/plugins/texteditor/texteditorplugin.cpp | 8 + 6 files changed, 209 insertions(+), 13 deletions(-) create mode 100644 src/plugins/texteditor/codeassist/codeassist_test.cpp create mode 100644 src/plugins/texteditor/codeassist/codeassist_test.h diff --git a/src/plugins/texteditor/CMakeLists.txt b/src/plugins/texteditor/CMakeLists.txt index eebe8bf0bed..048cd40b1d5 100644 --- a/src/plugins/texteditor/CMakeLists.txt +++ b/src/plugins/texteditor/CMakeLists.txt @@ -113,5 +113,7 @@ add_qtc_plugin(TextEditor extend_qtc_plugin(TextEditor CONDITION WITH_TESTS - SOURCES texteditor_test.cpp + SOURCES + codeassist/codeassist_test.cpp codeassist/codeassist_test.h + texteditor_test.cpp ) diff --git a/src/plugins/texteditor/codeassist/codeassist_test.cpp b/src/plugins/texteditor/codeassist/codeassist_test.cpp new file mode 100644 index 00000000000..8b724dbe166 --- /dev/null +++ b/src/plugins/texteditor/codeassist/codeassist_test.cpp @@ -0,0 +1,152 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#ifdef WITH_TESTS + +#include "codeassist_test.h" + +#include "../texteditor.h" + +#include "assistinterface.h" +#include "assistproposaliteminterface.h" +#include "asyncprocessor.h" +#include "completionassistprovider.h" +#include "genericproposal.h" +#include "genericproposalwidget.h" + +#include +#include +#include + +#include + +namespace TextEditor::Internal { + +class TestProposalItem : public AssistProposalItemInterface +{ +public: + QString m_text = "test"; + bool m_implicitlyApplies = false; + bool m_prematurelyApplies = false; + QIcon m_icon; + QString m_detail = "detail"; + bool m_isSnippet = false; + bool m_isValid = true; + + QString text() const override { return m_text; } + bool implicitlyApplies() const override { return m_implicitlyApplies; } + bool prematurelyApplies(const QChar &) const override { return m_prematurelyApplies; } + QIcon icon() const override { return m_icon; } + QString detail() const override { return m_detail; } + bool isSnippet() const override { return m_isSnippet; } + bool isValid() const override { return m_isValid; } + quint64 hash() const override { return 0; } // used to remove duplicates +}; + +class OpenEditorItem : public TestProposalItem +{ +public: + void apply(TextDocumentManipulatorInterface &, int) const override + { + m_openedEditor = Core::EditorManager::openEditor(m_filePath, + Core::Constants::K_DEFAULT_TEXT_EDITOR_ID); + } + + mutable Core::IEditor *m_openedEditor = nullptr; + Utils::FilePath m_filePath; +}; + +class TestProposalWidget : public GenericProposalWidget +{ +public: + void showProposal(const QString &prefix) override + { + GenericProposalModelPtr proposalModel = model(); + if (proposalModel && proposalModel->size() == 1) { + emit proposalItemActivated(proposalModel->proposalItem(0)); + deleteLater(); + return; + } + GenericProposalWidget::showProposal(prefix); + } +}; + +class TestProposal : public GenericProposal +{ +public: + TestProposal(int pos, const QList &items) + : GenericProposal(pos, items) + {} + IAssistProposalWidget *createWidget() const override { return new TestProposalWidget; } +}; + +class TestProcessor : public AsyncProcessor +{ +public: + TestProcessor(const QList &items) + : m_items(items) + {} + IAssistProposal *performAsync() override + { return new TestProposal(interface()->position(), m_items); } + QList m_items; +}; + +class TestProvider : public CompletionAssistProvider +{ +public: + IAssistProcessor *createProcessor(const AssistInterface *assistInterface) const override + { + Q_UNUSED(assistInterface); + return new TestProcessor(m_items); + } + QList m_items; +}; + +void CodeAssistTests::initTestCase() +{ + Core::IEditor *editor = Core::EditorManager::openEditorWithContents( + Core::Constants::K_DEFAULT_TEXT_EDITOR_ID); + QVERIFY(editor); + m_editor = qobject_cast(editor); + QVERIFY(m_editor); + m_editorsToClose << m_editor; + m_testProvider = new TestProvider(); +} + +static Utils::FilePath createBigFile() +{ + constexpr int textChunkSize = 65536; // from utils/textfileformat.cpp + + const Utils::FilePath result = Utils::TemporaryDirectory::masterDirectoryFilePath() / "BigFile"; + QByteArray data; + data.reserve(textChunkSize); + while (data.size() < textChunkSize) + data.append("bigfile line\n"); + result.writeFileContents(data); + return result; +} + +void CodeAssistTests::testFollowSymbolBigFile() +{ + auto item = new OpenEditorItem; + item->m_filePath = createBigFile(); + m_testProvider->m_items = {item}; + auto editorWidget = m_editor->editorWidget(); + + editorWidget->invokeAssist(FollowSymbol, m_testProvider); + QSignalSpy spy(editorWidget, &TextEditorWidget::assistFinished); + QVERIFY(spy.wait(1000)); + QVERIFY(item->m_openedEditor); + m_editorsToClose << item->m_openedEditor; +} + +void CodeAssistTests::cleanupTestCase() +{ + m_testProvider->m_items.clear(); + Core::EditorManager::closeEditors(m_editorsToClose); + QVERIFY(Core::EditorManager::currentEditor() == nullptr); +} + +} // namespace TextEditor::Internal + +#endif // ifdef WITH_TESTS diff --git a/src/plugins/texteditor/codeassist/codeassist_test.h b/src/plugins/texteditor/codeassist/codeassist_test.h new file mode 100644 index 00000000000..3bf734aadfb --- /dev/null +++ b/src/plugins/texteditor/codeassist/codeassist_test.h @@ -0,0 +1,37 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#pragma once + +#ifdef WITH_TESTS + +#include + +namespace Core { class IEditor; } +namespace TextEditor { class BaseTextEditor; } + +namespace TextEditor::Internal { + +class TestProvider; + +class CodeAssistTests : public QObject +{ + Q_OBJECT +public: + +private slots: + void initTestCase(); + + void testFollowSymbolBigFile(); + + void cleanupTestCase(); + +private: + TextEditor::BaseTextEditor *m_editor = nullptr; + QList m_editorsToClose; + TestProvider *m_testProvider = nullptr; +}; + +} // namespace TextEditor::Internal + +#endif diff --git a/src/plugins/texteditor/texteditor.qbs b/src/plugins/texteditor/texteditor.qbs index 1b94811a563..071e0b5fc2a 100644 --- a/src/plugins/texteditor/texteditor.qbs +++ b/src/plugins/texteditor/texteditor.qbs @@ -224,6 +224,8 @@ Project { QtcTestFiles { files: [ + "codeassist/codeassist_test.cpp", + "codeassist/codeassist_test.h", "texteditor_test.cpp", ] } diff --git a/src/plugins/texteditor/texteditor_test.cpp b/src/plugins/texteditor/texteditor_test.cpp index e939e515681..3b88ac5efb5 100644 --- a/src/plugins/texteditor/texteditor_test.cpp +++ b/src/plugins/texteditor/texteditor_test.cpp @@ -3,20 +3,13 @@ #ifdef WITH_TESTS -#include -#include -#include +#include "tabsettings.h" +#include "texteditorplugin.h" + +#include #include -#include -#include - -#include "texteditor.h" -#include "texteditorplugin.h" -#include "textdocument.h" -#include "tabsettings.h" - -using namespace TextEditor; +namespace TextEditor { QString tabPolicyToString(TabSettings::TabPolicy policy) { @@ -149,4 +142,6 @@ void Internal::TextEditorPlugin::testIndentationClean() QCOMPARE(settings.isIndentationClean(block, indentSize), clean); } +} // namespace TextEditor + #endif // ifdef WITH_TESTS diff --git a/src/plugins/texteditor/texteditorplugin.cpp b/src/plugins/texteditor/texteditorplugin.cpp index a66ddf23c32..4d5c2268d1e 100644 --- a/src/plugins/texteditor/texteditorplugin.cpp +++ b/src/plugins/texteditor/texteditorplugin.cpp @@ -20,6 +20,10 @@ #include "texteditorsettings.h" #include "texteditortr.h" +#ifdef WITH_TESTS +#include "codeassist/codeassist_test.h" +#endif + #include #include #include @@ -142,6 +146,10 @@ void TextEditorPlugin::initialize() Tr::tr("Text", "SnippetProvider")); d->createStandardContextMenu(); + +#ifdef WITH_TESTS + addTest(); +#endif } void TextEditorPluginPrivate::extensionsInitialized() From 8b848df8583c174d48bd30ea2397b4ebd2218c1b Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 31 May 2023 09:38:24 +0200 Subject: [PATCH 045/141] WebAssembly: Use the more compact layouter function ... and delay the first update until all ui elements are present. Change-Id: Ica996c3262caed9397a951633b0971d48c7c683f Reviewed-by: Reviewed-by: Alessandro Portale --- src/plugins/webassembly/webassemblysettings.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/plugins/webassembly/webassemblysettings.cpp b/src/plugins/webassembly/webassemblysettings.cpp index 1af1d30c911..fb9293f2c84 100644 --- a/src/plugins/webassembly/webassemblysettings.cpp +++ b/src/plugins/webassembly/webassemblysettings.cpp @@ -20,6 +20,7 @@ #include #include +#include using namespace Utils; @@ -66,7 +67,7 @@ WebAssemblySettings::WebAssemblySettings() connect(this, &Utils::AspectContainer::applied, &WebAssemblyToolChain::registerToolChains); - setLayouter([this](QWidget *widget) { + setLayouter([this] { auto instruction = new QLabel( Tr::tr("Select the root directory of an installed %1. " "Ensure that the activated SDK version is compatible with the %2 " @@ -96,7 +97,7 @@ WebAssemblySettings::WebAssemblySettings() // _clang-format off using namespace Layouting; - Column { + Column col { Group { title(Tr::tr("Emscripten SDK path:")), Column { @@ -113,12 +114,17 @@ WebAssemblySettings::WebAssemblySettings() }, }, m_qtVersionDisplay, - }.attachTo(widget); + }; // _clang-format on - updateStatus(); connect(emSdk.pathChooser(), &Utils::PathChooser::textChanged, this, &WebAssemblySettings::updateStatus); + + // updateStatus() uses m_emSdkEnvGroupBox which only exists + // after this here emerges. So delay the update a bit. + QTimer::singleShot(0, this, &WebAssemblySettings::updateStatus); + + return col; }); readSettings(); @@ -131,6 +137,8 @@ void WebAssemblySettings::updateStatus() const Utils::FilePath newEmSdk = emSdk.pathChooser()->filePath(); const bool sdkValid = newEmSdk.exists() && WebAssemblyEmSdk::isValid(newEmSdk); + QTC_ASSERT(m_emSdkVersionDisplay, return); + QTC_ASSERT(m_emSdkEnvGroupBox, return); m_emSdkVersionDisplay->setVisible(sdkValid); m_emSdkEnvGroupBox->setEnabled(sdkValid); From f8a28abd783b5f1514be516715fadb19fa54867d Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 1 Jun 2023 06:43:10 +0200 Subject: [PATCH 046/141] Terminal: Fix qbs build Change-Id: I7ce36f99927fe3d4a2d344819d8082fdae8cfce4 Reviewed-by: David Schulz --- src/plugins/terminal/terminal.qbs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/terminal/terminal.qbs b/src/plugins/terminal/terminal.qbs index c4c9de253e9..300c1acf19d 100644 --- a/src/plugins/terminal/terminal.qbs +++ b/src/plugins/terminal/terminal.qbs @@ -23,7 +23,7 @@ QtcPlugin { "shellintegration.h", "terminal.qrc", "terminalconstants.h", - "terminalicons.h" + "terminalicons.h", "terminalpane.cpp", "terminalpane.h", "terminalplugin.cpp", From deb974de053fe0db33924622479cf50b5296408b Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Wed, 31 May 2023 10:04:05 +0200 Subject: [PATCH 047/141] Tr/LanguageClient: Add some comments, parametrize error message Change-Id: Ifd7354c10d18c0df093908c1a240f254c679893a Reviewed-by: David Schulz Reviewed-by: Leena Miettinen --- src/plugins/languageclient/client.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/plugins/languageclient/client.cpp b/src/plugins/languageclient/client.cpp index 9d2356a9d4d..130961ebd1b 100644 --- a/src/plugins/languageclient/client.cpp +++ b/src/plugins/languageclient/client.cpp @@ -356,6 +356,7 @@ void Client::setName(const QString &name) QString Client::name() const { if (d->m_project && !d->m_project->displayName().isEmpty()) + //: for return Tr::tr("%1 for %2").arg(d->m_displayName, d->m_project->displayName()); return d->m_displayName; } @@ -555,11 +556,17 @@ Client::State Client::state() const QString Client::stateString() const { switch (d->m_state){ + //: language client state case Uninitialized: return Tr::tr("uninitialized"); + //: language client state case InitializeRequested: return Tr::tr("initialize requested"); + //: language client state case Initialized: return Tr::tr("initialized"); + //: language client state case ShutdownRequested: return Tr::tr("shutdown requested"); + //: language client state case Shutdown: return Tr::tr("shut down"); + //: language client state case Error: return Tr::tr("error"); } return {}; @@ -1970,7 +1977,7 @@ void ClientPrivate::initializeCallback(const InitializeRequest::Response &initRe if (std::optional> error = initResponse.error()) { if (std::optional data = error->data()) { if (data->retry()) { - const QString title(Tr::tr("Language Server \"%1\" Initialize Error").arg(m_displayName)); + const QString title(Tr::tr("Language Server \"%1\" Initialization Error").arg(m_displayName)); auto result = QMessageBox::warning(Core::ICore::dialogParent(), title, error->message(), @@ -1983,7 +1990,7 @@ void ClientPrivate::initializeCallback(const InitializeRequest::Response &initRe } } } - q->setError(Tr::tr("Initialize error: ") + error->message()); + q->setError(Tr::tr("Initialization error: %1.").arg(error->message())); emit q->finished(); return; } From 0b863af8a1386d791b9eabcc1066f0563193ee91 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Wed, 31 May 2023 10:11:15 +0200 Subject: [PATCH 048/141] Tr/Python: Fix translation issues - Use parametrization - Split message that relied on sentence structure of the language Change-Id: I5c0cca684bc9c94219e740fe0292e358a91714da Reviewed-by: David Schulz Reviewed-by: Leena Miettinen Reviewed-by: --- src/plugins/python/pipsupport.cpp | 6 ++++-- src/plugins/python/pythonsettings.cpp | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/plugins/python/pipsupport.cpp b/src/plugins/python/pipsupport.cpp index 8e3f55dd11b..b420f24aa50 100644 --- a/src/plugins/python/pipsupport.cpp +++ b/src/plugins/python/pipsupport.cpp @@ -81,8 +81,10 @@ void PipInstallTask::cancel() m_process.stop(); m_process.waitForFinished(); Core::MessageManager::writeFlashing( - Tr::tr("The %1 installation was canceled by %2.") - .arg(packagesDisplayName(), m_killTimer.isActive() ? Tr::tr("user") : Tr::tr("time out"))); + m_killTimer.isActive() + ? Tr::tr("The installation of \"%1\" was canceled by timeout.").arg(packagesDisplayName()) + : Tr::tr("The installation of \"%1\" was canceled by the user.") + .arg(packagesDisplayName())); } void PipInstallTask::handleDone() diff --git a/src/plugins/python/pythonsettings.cpp b/src/plugins/python/pythonsettings.cpp index d33346b8af7..0fe6576170f 100644 --- a/src/plugins/python/pythonsettings.cpp +++ b/src/plugins/python/pythonsettings.cpp @@ -634,7 +634,8 @@ static void addPythonsFromRegistry(QList &pythons) const FilePath &executable = FilePath::fromUserInput(regVal.toString()); if (executable.exists() && !alreadyRegistered(pythons, executable)) { pythons << Interpreter{QUuid::createUuid().toString(), - name + Tr::tr(" (Windowed)"), + //: (Windowed) + Tr::tr("%1 (Windowed)").arg(name), FilePath::fromUserInput(regVal.toString())}; } } From b51188c9a9e6ec5bb4343ba70f5aae5d5e1bf553 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Thu, 1 Jun 2023 03:58:39 +0200 Subject: [PATCH 049/141] TerminalPane: Fix a warning about an unused arg Change-Id: I63d19a608c63532e0e83df929da6cb07dc896722 Reviewed-by: Marcus Tillmanns Reviewed-by: --- src/plugins/terminal/terminalpane.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/terminal/terminalpane.cpp b/src/plugins/terminal/terminalpane.cpp index 7cf0e308031..7e9cae7539e 100644 --- a/src/plugins/terminal/terminalpane.cpp +++ b/src/plugins/terminal/terminalpane.cpp @@ -163,6 +163,7 @@ TerminalWidget *TerminalPane::stoppedTerminalWithId(Id identifier) const QWidget *TerminalPane::outputWidget(QWidget *parent) { + Q_UNUSED(parent) if (!m_widgetInitialized) { m_widgetInitialized = true; m_tabWidget.setTabBarAutoHide(false); From 3c08ebbe265fbe34656b7e641300b8daabf3cffb Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Mon, 29 May 2023 11:46:20 +0200 Subject: [PATCH 050/141] TaskTree: Make enums known to the Qt meta object system Change-Id: I72d8b74460febe1d7ad7d840e25cea02cd77b308 Reviewed-by: Marcus Tillmanns Reviewed-by: Reviewed-by: Qt CI Bot --- src/libs/solutions/tasking/tasktree.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libs/solutions/tasking/tasktree.h b/src/libs/solutions/tasking/tasktree.h index 872bce2ed86..37403628a5a 100644 --- a/src/libs/solutions/tasking/tasktree.h +++ b/src/libs/solutions/tasking/tasktree.h @@ -16,6 +16,8 @@ QT_END_NAMESPACE namespace Tasking { +Q_NAMESPACE + class ExecutionContextActivator; class TaskContainer; class TaskTreePrivate; @@ -109,6 +111,7 @@ enum class WorkflowPolicy { StopOnFinished, // 3 - Stops on first finished child and report its result. FinishAllAndDone // 4 - Reports done after all children finished. }; +Q_ENUM_NS(WorkflowPolicy); enum class TaskAction { @@ -116,6 +119,7 @@ enum class TaskAction StopWithDone, StopWithError }; +Q_ENUM_NS(TaskAction); class TASKING_EXPORT TaskItem { From 8636b35e87cec7517894ca30bad8f28b12060df2 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 1 Jun 2023 09:08:50 +0200 Subject: [PATCH 051/141] RemoteLinux: Explicitly allow remote paths for device's gdbserver ... and qml runtime. Useful on Mac and Windows where there'd be a native but local chooser dialog otherwise. Change-Id: I6361c6f6067c86dd7cca15ce1dd02150136cf3f7 Reviewed-by: Tim Jenssen --- .../remotelinux/genericlinuxdeviceconfigurationwidget.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.cpp b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.cpp index ae85284ccb1..da7b6138dea 100644 --- a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.cpp +++ b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.cpp @@ -79,12 +79,14 @@ GenericLinuxDeviceConfigurationWidget::GenericLinuxDeviceConfigurationWidget( m_gdbServerLineEdit->setPlaceholderText(hint); m_gdbServerLineEdit->setToolTip(hint); m_gdbServerLineEdit->setHistoryCompleter("GdbServer"); + m_gdbServerLineEdit->setAllowPathFromDevice(true); m_qmlRuntimeLineEdit = new PathChooser(this); m_qmlRuntimeLineEdit->setExpectedKind(PathChooser::ExistingCommand); m_qmlRuntimeLineEdit->setPlaceholderText(hint); m_qmlRuntimeLineEdit->setToolTip(hint); m_qmlRuntimeLineEdit->setHistoryCompleter("QmlRuntime"); + m_qmlRuntimeLineEdit->setAllowPathFromDevice(true); m_sourceProfileCheckBox = new QCheckBox(Tr::tr("Source %1 and %2").arg("/etc/profile").arg("$HOME/.profile")); From f72a5d18325fd013ffe5dead46f8bb1abbd9f09b Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 31 May 2023 11:53:32 +0200 Subject: [PATCH 052/141] ProjectExplorer: Rename projectexplorersettingspage.cpp ... to projectexplorersettings.cpp and merge projectexplorersettingspage.h into projectexplorersettings.h. A preliminary step on the path to aspectification. Change-Id: Id482c0e8e03a2d37b07b9c1d810825afcede91b6 Reviewed-by: Reviewed-by: Qt CI Bot Reviewed-by: Christian Kandeler --- src/plugins/projectexplorer/CMakeLists.txt | 3 +-- src/plugins/projectexplorer/projectexplorer.cpp | 1 - src/plugins/projectexplorer/projectexplorer.qbs | 3 +-- ...tingspage.cpp => projectexplorersettings.cpp} | 2 +- .../projectexplorer/projectexplorersettings.h | 8 ++++++++ .../projectexplorersettingspage.h | 16 ---------------- 6 files changed, 11 insertions(+), 22 deletions(-) rename src/plugins/projectexplorer/{projectexplorersettingspage.cpp => projectexplorersettings.cpp} (99%) delete mode 100644 src/plugins/projectexplorer/projectexplorersettingspage.h diff --git a/src/plugins/projectexplorer/CMakeLists.txt b/src/plugins/projectexplorer/CMakeLists.txt index 00ea43530b9..d16e868a5cc 100644 --- a/src/plugins/projectexplorer/CMakeLists.txt +++ b/src/plugins/projectexplorer/CMakeLists.txt @@ -134,8 +134,7 @@ add_qtc_plugin(ProjectExplorer projectexplorerconstants.cpp projectexplorerconstants.h projectexplorericons.cpp projectexplorericons.h - projectexplorersettings.h - projectexplorersettingspage.cpp projectexplorersettingspage.h + projectexplorersettings.cpp projectexplorersettings.h projectexplorertr.h projectfilewizardextension.cpp projectfilewizardextension.h projectimporter.cpp projectimporter.h diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index eecf5332b00..9df791b3462 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -57,7 +57,6 @@ #include "project.h" #include "projectexplorericons.h" #include "projectexplorersettings.h" -#include "projectexplorersettingspage.h" #include "projectexplorertr.h" #include "projectfilewizardextension.h" #include "projectmanager.h" diff --git a/src/plugins/projectexplorer/projectexplorer.qbs b/src/plugins/projectexplorer/projectexplorer.qbs index 3b407825713..c955a485905 100644 --- a/src/plugins/projectexplorer/projectexplorer.qbs +++ b/src/plugins/projectexplorer/projectexplorer.qbs @@ -110,8 +110,7 @@ Project { "projectexplorerconstants.cpp", "projectexplorerconstants.h", "projectexplorericons.h", "projectexplorericons.cpp", - "projectexplorersettings.h", - "projectexplorersettingspage.cpp", "projectexplorersettingspage.h", + "projectexplorersettings.h", "projectexplorersettings.cpp", "projectexplorertr.h", "projectfilewizardextension.cpp", "projectfilewizardextension.h", "projectimporter.cpp", "projectimporter.h", diff --git a/src/plugins/projectexplorer/projectexplorersettingspage.cpp b/src/plugins/projectexplorer/projectexplorersettings.cpp similarity index 99% rename from src/plugins/projectexplorer/projectexplorersettingspage.cpp rename to src/plugins/projectexplorer/projectexplorersettings.cpp index c8bc51b9675..14f66b885bf 100644 --- a/src/plugins/projectexplorer/projectexplorersettingspage.cpp +++ b/src/plugins/projectexplorer/projectexplorersettings.cpp @@ -1,7 +1,7 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 -#include "projectexplorersettingspage.h" +#include "projectexplorersettings.h" #include "projectexplorer.h" #include "projectexplorerconstants.h" diff --git a/src/plugins/projectexplorer/projectexplorersettings.h b/src/plugins/projectexplorer/projectexplorersettings.h index bda218aef22..a65dbc2f6eb 100644 --- a/src/plugins/projectexplorer/projectexplorersettings.h +++ b/src/plugins/projectexplorer/projectexplorersettings.h @@ -4,6 +4,8 @@ #pragma once #include +#include + #include #include @@ -80,5 +82,11 @@ public: int maxCharCount = Core::Constants::DEFAULT_MAX_CHAR_COUNT; }; +class ProjectExplorerSettingsPage : public Core::IOptionsPage +{ +public: + ProjectExplorerSettingsPage(); +}; + } // namespace Internal } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/projectexplorersettingspage.h b/src/plugins/projectexplorer/projectexplorersettingspage.h deleted file mode 100644 index a924681daed..00000000000 --- a/src/plugins/projectexplorer/projectexplorersettingspage.h +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#pragma once - -#include - -namespace ProjectExplorer::Internal { - -class ProjectExplorerSettingsPage : public Core::IOptionsPage -{ -public: - ProjectExplorerSettingsPage(); -}; - -} // ProjectExplorer::Internal From 93759796984138e5fca5781e22381dcba6a51824 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 1 Jun 2023 09:51:27 +0200 Subject: [PATCH 053/141] Utils: Make PathChooser remote support configurable in aspects ... and switch is _on_ by default. Change-Id: I82e66da477dae1ee955b81babc6230b67e530d45 Reviewed-by: Tim Jenssen --- src/libs/utils/aspects.cpp | 9 +++++++++ src/libs/utils/aspects.h | 1 + 2 files changed, 10 insertions(+) diff --git a/src/libs/utils/aspects.cpp b/src/libs/utils/aspects.cpp index d3610b2c7da..bb637f31b02 100644 --- a/src/libs/utils/aspects.cpp +++ b/src/libs/utils/aspects.cpp @@ -670,6 +670,7 @@ public: // Used to block recursive editingFinished signals for example when return is pressed, and // the validation changes focus by opening a dialog bool m_blockAutoApply = false; + bool m_allowPathFromDevice = true; template void updateWidgetFromCheckStatus(StringAspect *aspect, Widget *w) { @@ -977,6 +978,13 @@ void StringAspect::setCommandVersionArguments(const QStringList &arguments) d->m_pathChooserDisplay->setCommandVersionArguments(arguments); } +void StringAspect::setAllowPathFromDevice(bool allowPathFromDevice) +{ + d->m_allowPathFromDevice = allowPathFromDevice; + if (d->m_pathChooserDisplay) + d->m_pathChooserDisplay->setAllowPathFromDevice(allowPathFromDevice); +} + /*! Sets \a elideMode as label elide mode. */ @@ -1122,6 +1130,7 @@ void StringAspect::addToLayout(LayoutItem &parent) d->m_pathChooserDisplay->setPromptDialogFilter(d->m_prompDialogFilter); d->m_pathChooserDisplay->setPromptDialogTitle(d->m_prompDialogTitle); d->m_pathChooserDisplay->setCommandVersionArguments(d->m_commandVersionArguments); + d->m_pathChooserDisplay->setAllowPathFromDevice(d->m_allowPathFromDevice); if (defaultValue() == value()) d->m_pathChooserDisplay->setDefaultValue(defaultValue()); else diff --git a/src/libs/utils/aspects.h b/src/libs/utils/aspects.h index 35e8a62b8f7..db3c036cec3 100644 --- a/src/libs/utils/aspects.h +++ b/src/libs/utils/aspects.h @@ -406,6 +406,7 @@ public: void setOpenTerminalHandler(const std::function &openTerminal); void setAutoApplyOnEditingFinished(bool applyOnEditingFinished); void setElideMode(Qt::TextElideMode elideMode); + void setAllowPathFromDevice(bool allowPathFromDevice); void validateInput(); From 5365c5de80b78e8a73cc966193e4627a048f614e Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Fri, 26 May 2023 09:50:50 +0200 Subject: [PATCH 054/141] Tr/QML Code Style: Just use "Other" for group box title "Qml JS Code Style" is wrong (consistent would probably be "QML/JS Code Style"), and since this is already with "Qt Quick > Code Style" with another group box titled "Tabs and Indentation", it is also weird (the other group box is also about the QML/JS code style). Change-Id: I61d5f273b91aebf95f0e5f5913e160195dcd7a11 Reviewed-by: Ulf Hermann Reviewed-by: hjk Reviewed-by: Leena Miettinen --- src/plugins/qmljstools/qmljscodestylesettingswidget.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/qmljstools/qmljscodestylesettingswidget.cpp b/src/plugins/qmljstools/qmljscodestylesettingswidget.cpp index 34919f6144f..9fee7205b3d 100644 --- a/src/plugins/qmljstools/qmljscodestylesettingswidget.cpp +++ b/src/plugins/qmljstools/qmljscodestylesettingswidget.cpp @@ -20,15 +20,17 @@ QmlJSCodeStyleSettingsWidget::QmlJSCodeStyleSettingsWidget(QWidget *parent) m_lineLengthSpinBox->setMaximum(999); using namespace Layouting; + // clang-format off Column { Group { - title(Tr::tr("Qml JS Code Style")), + title(Tr::tr("Other")), Form { Tr::tr("&Line length:"), m_lineLengthSpinBox, br, } }, noMargin }.attachTo(this); + // clang-format on connect(m_lineLengthSpinBox, &QSpinBox::valueChanged, this, &QmlJSCodeStyleSettingsWidget::slotSettingsChanged); From 10bf294975a7e71d8ac9d53ffde4cf03cba6dc16 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Fri, 26 May 2023 11:11:39 +0200 Subject: [PATCH 055/141] Use KiB/MiB/GiB/TiB for 1024-based units MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit That is also consistent with our file properties panel Change-Id: Ief62f8c067896a410878cfa4c36f17c6daf6fee7 Reviewed-by: Mahmoud Badri Reviewed-by: Leena Miettinen Reviewed-by: Robert Löhning --- share/qtcreator/translations/qtcreator_de.ts | 12 ++++++------ src/plugins/coreplugin/systemsettings.cpp | 3 +-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/share/qtcreator/translations/qtcreator_de.ts b/share/qtcreator/translations/qtcreator_de.ts index c6e2a4cab88..ee6e08a335c 100644 --- a/share/qtcreator/translations/qtcreator_de.ts +++ b/share/qtcreator/translations/qtcreator_de.ts @@ -18199,16 +18199,16 @@ Möchten Sie sie jetzt auschecken? Bytes
- KB - KB + KiB + KiB - GB - GB + GiB + GiB - TB - TB + TiB + TiB Enable crash reporting diff --git a/src/plugins/coreplugin/systemsettings.cpp b/src/plugins/coreplugin/systemsettings.cpp index 5d9a5fd3f9f..f6641bad08f 100644 --- a/src/plugins/coreplugin/systemsettings.cpp +++ b/src/plugins/coreplugin/systemsettings.cpp @@ -51,8 +51,7 @@ const char showCrashButtonKey[] = "ShowCrashButton"; // TODO: move to somewhere in Utils static QString formatSize(qint64 size) { - QStringList units {Tr::tr("Bytes"), Tr::tr("KB"), Tr::tr("MB"), - Tr::tr("GB"), Tr::tr("TB")}; + QStringList units{Tr::tr("Bytes"), Tr::tr("KiB"), Tr::tr("MiB"), Tr::tr("GiB"), Tr::tr("TiB")}; double outputSize = size; int i; for (i = 0; i < units.size() - 1; ++i) { From 3ca94f9c909011404f4ae04ba6ad111fe58ecdfa Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 31 May 2023 09:43:42 +0200 Subject: [PATCH 056/141] Debugger: Use simpler setLayouter function Change-Id: Ib213100fc9dd37b23d323a99007e6ed73378f347 Reviewed-by: Reviewed-by: Alessandro Portale --- src/plugins/debugger/gdb/gdboptionspage.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/debugger/gdb/gdboptionspage.cpp b/src/plugins/debugger/gdb/gdboptionspage.cpp index 3d24dd6c9cf..37008cabcd1 100644 --- a/src/plugins/debugger/gdb/gdboptionspage.cpp +++ b/src/plugins/debugger/gdb/gdboptionspage.cpp @@ -32,7 +32,7 @@ public: setCategory(Constants::DEBUGGER_SETTINGS_CATEGORY); setSettings(&debuggerSettings()->page2); - setLayouter([](QWidget *w) { + setLayouter([] { using namespace Layouting; DebuggerSettings &s = *debuggerSettings(); @@ -84,7 +84,7 @@ public: Column { s.gdbPostAttachCommands }, }; - Grid { general, extended, br, startup, attach }.attachTo(w); + return Grid { general, extended, br, startup, attach }; }); } }; From 9574122da1f18fec548cb9a53031b68a623494ad Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 31 May 2023 12:38:49 +0200 Subject: [PATCH 057/141] ProjectExplorer: Aspectify Compile output settings page Change-Id: Icc7b1917a57a96e482db7b4f0ba5c0a203f4958c Reviewed-by: Reviewed-by: Christian Kandeler --- src/plugins/projectexplorer/buildmanager.cpp | 14 +- src/plugins/projectexplorer/buildmanager.h | 9 +- .../projectexplorer/compileoutputwindow.cpp | 120 +++++++----------- .../projectexplorer/compileoutputwindow.h | 24 ++-- .../projectexplorer/projectexplorer.cpp | 1 - .../projectexplorer/projectexplorersettings.h | 8 -- 6 files changed, 62 insertions(+), 114 deletions(-) diff --git a/src/plugins/projectexplorer/buildmanager.cpp b/src/plugins/projectexplorer/buildmanager.cpp index 6284a960417..28169513cb7 100644 --- a/src/plugins/projectexplorer/buildmanager.cpp +++ b/src/plugins/projectexplorer/buildmanager.cpp @@ -442,16 +442,6 @@ int BuildManager::getErrorTaskCount() return errors; } -void BuildManager::setCompileOutputSettings(const CompileOutputSettings &settings) -{ - d->m_outputWindow->setSettings(settings); -} - -const CompileOutputSettings &BuildManager::compileOutputSettings() -{ - return d->m_outputWindow->settings(); -} - QString BuildManager::displayNameForStepId(Id stepId) { if (stepId == Constants::BUILDSTEPS_CLEAN) { @@ -853,7 +843,7 @@ bool BuildManager::buildLists(const QList bsls, const QStringLi return false; } - if (d->m_outputWindow->settings().popUp) + if (CompileOutputSettings::instance().popUp()) d->m_outputWindow->popup(IOutputPane::NoModeSwitch); startBuildQueue(); return true; @@ -866,7 +856,7 @@ void BuildManager::appendStep(BuildStep *step, const QString &name) d->m_outputWindow->popup(IOutputPane::NoModeSwitch); return; } - if (d->m_outputWindow->settings().popUp) + if (CompileOutputSettings::instance().popUp()) d->m_outputWindow->popup(IOutputPane::NoModeSwitch); startBuildQueue(); } diff --git a/src/plugins/projectexplorer/buildmanager.h b/src/plugins/projectexplorer/buildmanager.h index d7d2c91562a..d9478db4093 100644 --- a/src/plugins/projectexplorer/buildmanager.h +++ b/src/plugins/projectexplorer/buildmanager.h @@ -10,12 +10,10 @@ #include namespace ProjectExplorer { -class RunConfiguration; -namespace Internal { class CompileOutputSettings; } - -class Task; class Project; +class RunConfiguration; +class Task; enum class BuildForRunConfigStatus { Building, NotBuilding, BuildFailed }; enum class ConfigSelection { All, Active }; @@ -66,9 +64,6 @@ public: static int getErrorTaskCount(); - static void setCompileOutputSettings(const Internal::CompileOutputSettings &settings); - static const Internal::CompileOutputSettings &compileOutputSettings(); - static QString displayNameForStepId(Utils::Id stepId); public slots: diff --git a/src/plugins/projectexplorer/compileoutputwindow.cpp b/src/plugins/projectexplorer/compileoutputwindow.cpp index f345792ca83..bafc31fc14a 100644 --- a/src/plugins/projectexplorer/compileoutputwindow.cpp +++ b/src/plugins/projectexplorer/compileoutputwindow.cpp @@ -17,7 +17,9 @@ #include #include #include + #include +#include #include #include #include @@ -43,9 +45,6 @@ namespace Internal { const char SETTINGS_KEY[] = "ProjectExplorer/CompileOutput/Zoom"; const char C_COMPILE_OUTPUT[] = "ProjectExplorer.CompileOutput"; -const char POP_UP_KEY[] = "ProjectExplorer/Settings/ShowCompilerOutput"; -const char WRAP_OUTPUT_KEY[] = "ProjectExplorer/Settings/WrapBuildOutput"; -const char MAX_LINES_KEY[] = "ProjectExplorer/Settings/MaxBuildOutputLines"; const char OPTIONS_PAGE_ID[] = "C.ProjectExplorer.CompileOutputOptions"; CompileOutputWindow::CompileOutputWindow(QAction *cancelBuildAction) : @@ -101,8 +100,17 @@ CompileOutputWindow::CompileOutputWindow(QAction *cancelBuildAction) : Tr::tr("O")); ExtensionSystem::PluginManager::addObject(m_handler); setupContext(C_COMPILE_OUTPUT, m_outputWindow); - loadSettings(); updateFromSettings(); + + m_outputWindow->setWordWrapEnabled(m_settings.wrapOutput()); + m_outputWindow->setMaxCharCount(m_settings.maxCharCount()); + + connect(&m_settings.wrapOutput, &Utils::BaseAspect::changed, m_outputWindow, [this] { + m_outputWindow->setWordWrapEnabled(m_settings.wrapOutput()); + }); + connect(&m_settings.maxCharCount, &Utils::BaseAspect::changed, m_outputWindow, [this] { + m_outputWindow->setMaxCharCount(m_settings.maxCharCount()); + }); } CompileOutputWindow::~CompileOutputWindow() @@ -115,10 +123,7 @@ CompileOutputWindow::~CompileOutputWindow() void CompileOutputWindow::updateFromSettings() { - m_outputWindow->setWordWrapEnabled(m_settings.wrapOutput); - m_outputWindow->setMaxCharCount(m_settings.maxCharCount); } - bool CompileOutputWindow::hasFocus() const { return m_outputWindow->window()->focusWidget() == m_outputWindow; @@ -213,13 +218,6 @@ void CompileOutputWindow::reset() m_outputWindow->reset(); } -void CompileOutputWindow::setSettings(const CompileOutputSettings &settings) -{ - m_settings = settings; - storeSettings(); - updateFromSettings(); -} - Utils::OutputFormatter *CompileOutputWindow::outputFormatter() const { return m_outputWindow->outputFormatter(); @@ -231,75 +229,49 @@ void CompileOutputWindow::updateFilter() filterUsesRegexp(), filterIsInverted()); } -const bool kPopUpDefault = false; -const bool kWrapOutputDefault = true; +// CompileOutputSettings -void CompileOutputWindow::loadSettings() +static CompileOutputSettings *s_compileOutputSettings; + +CompileOutputSettings &CompileOutputSettings::instance() { - QSettings * const s = Core::ICore::settings(); - m_settings.popUp = s->value(POP_UP_KEY, kPopUpDefault).toBool(); - m_settings.wrapOutput = s->value(WRAP_OUTPUT_KEY, kWrapOutputDefault).toBool(); - m_settings.maxCharCount = s->value(MAX_LINES_KEY, - Core::Constants::DEFAULT_MAX_CHAR_COUNT).toInt() * 100; + return *s_compileOutputSettings; } -void CompileOutputWindow::storeSettings() const +CompileOutputSettings::CompileOutputSettings() { - Utils::QtcSettings *const s = Core::ICore::settings(); - s->setValueWithDefault(POP_UP_KEY, m_settings.popUp, kPopUpDefault); - s->setValueWithDefault(WRAP_OUTPUT_KEY, m_settings.wrapOutput, kWrapOutputDefault); - s->setValueWithDefault(MAX_LINES_KEY, - m_settings.maxCharCount / 100, - Core::Constants::DEFAULT_MAX_CHAR_COUNT); -} + s_compileOutputSettings = this; -class CompileOutputSettingsWidget : public Core::IOptionsPageWidget -{ -public: - CompileOutputSettingsWidget() - { - const CompileOutputSettings &settings = BuildManager::compileOutputSettings(); - m_wrapOutputCheckBox.setText(Tr::tr("Word-wrap output")); - m_wrapOutputCheckBox.setChecked(settings.wrapOutput); - m_popUpCheckBox.setText(Tr::tr("Open Compile Output when building")); - m_popUpCheckBox.setChecked(settings.popUp); - m_maxCharsBox.setMaximum(100000000); - m_maxCharsBox.setValue(settings.maxCharCount); - const auto layout = new QVBoxLayout(this); - layout->addWidget(&m_wrapOutputCheckBox); - layout->addWidget(&m_popUpCheckBox); - const auto maxCharsLayout = new QHBoxLayout; - const QString msg = Tr::tr("Limit output to %1 characters"); - const QStringList parts = msg.split("%1") << QString() << QString(); - maxCharsLayout->addWidget(new QLabel(parts.at(0).trimmed())); - maxCharsLayout->addWidget(&m_maxCharsBox); - maxCharsLayout->addWidget(new QLabel(parts.at(1).trimmed())); - maxCharsLayout->addStretch(1); - layout->addLayout(maxCharsLayout); - layout->addStretch(1); - } - - void apply() final - { - CompileOutputSettings s; - s.wrapOutput = m_wrapOutputCheckBox.isChecked(); - s.popUp = m_popUpCheckBox.isChecked(); - s.maxCharCount = m_maxCharsBox.value(); - BuildManager::setCompileOutputSettings(s); - } - -private: - QCheckBox m_wrapOutputCheckBox; - QCheckBox m_popUpCheckBox; - QSpinBox m_maxCharsBox; -}; - -CompileOutputSettingsPage::CompileOutputSettingsPage() -{ setId(OPTIONS_PAGE_ID); setDisplayName(Tr::tr("Compile Output")); setCategory(Constants::BUILD_AND_RUN_SETTINGS_CATEGORY); - setWidgetCreator([] { return new CompileOutputSettingsWidget; }); + + wrapOutput.setSettingsKey("ProjectExplorer/Settings/WrapBuildOutput"); + wrapOutput.setDefaultValue(true); + wrapOutput.setLabelText(Tr::tr("Word-wrap output")); + + popUp.setSettingsKey("ProjectExplorer/Settings/ShowCompilerOutput"); + popUp.setLabelText(Tr::tr("Open Compile Output when building")); + + maxCharCount.setSettingsKey("ProjectExplorer/Settings/MaxBuildOutputLines"); + maxCharCount.setRange(1, Core::Constants::DEFAULT_MAX_CHAR_COUNT); + maxCharCount.setDefaultValue(Core::Constants::DEFAULT_MAX_CHAR_COUNT); + maxCharCount.setToSettingsTransformation([](const QVariant &v) { return v.toInt() / 100; }); + maxCharCount.setFromSettingsTransformation([](const QVariant &v) { return v.toInt() * 100; }); + + setLayouter([this] { + using namespace Layouting; + const QString msg = Tr::tr("Limit output to %1 characters"); + const QStringList parts = msg.split("%1") << QString() << QString(); + return Column { + wrapOutput, + popUp, + Row { parts.at(0), maxCharCount, parts.at(1), st }, + st + }; + }); + + readSettings(); } } // Internal diff --git a/src/plugins/projectexplorer/compileoutputwindow.h b/src/plugins/projectexplorer/compileoutputwindow.h index e1f000de9ae..89c7b749f2e 100644 --- a/src/plugins/projectexplorer/compileoutputwindow.h +++ b/src/plugins/projectexplorer/compileoutputwindow.h @@ -26,6 +26,18 @@ namespace Internal { class ShowOutputTaskHandler; class CompileOutputTextEdit; +class CompileOutputSettings final : public Core::PagedSettings +{ +public: + CompileOutputSettings(); + + static CompileOutputSettings &instance(); + + Utils::BoolAspect popUp{this}; + Utils::BoolAspect wrapOutput{this}; + Utils::IntegerAspect maxCharCount{this}; +}; + class CompileOutputWindow final : public Core::IOutputPane { Q_OBJECT @@ -57,19 +69,13 @@ public: void flush(); void reset(); - const CompileOutputSettings &settings() const { return m_settings; } - void setSettings(const CompileOutputSettings &settings); - Utils::OutputFormatter *outputFormatter() const; private: void updateFilter() override; const QList outputWindows() const override { return {m_outputWindow}; } - void loadSettings(); - void storeSettings() const; void updateFromSettings(); - Core::OutputWindow *m_outputWindow; ShowOutputTaskHandler *m_handler; QToolButton *m_cancelBuildButton; @@ -77,11 +83,5 @@ private: CompileOutputSettings m_settings; }; -class CompileOutputSettingsPage final : public Core::IOptionsPage -{ -public: - CompileOutputSettingsPage(); -}; - } // namespace Internal } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index 9df791b3462..d313cb433de 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -666,7 +666,6 @@ public: // Settings pages ProjectExplorerSettingsPage m_projectExplorerSettingsPage; AppOutputSettingsPage m_appOutputSettingsPage; - CompileOutputSettingsPage m_compileOutputSettingsPage; DeviceSettingsPage m_deviceSettingsPage; SshSettingsPage m_sshSettingsPage; CustomParsersSettingsPage m_customParsersSettingsPage; diff --git a/src/plugins/projectexplorer/projectexplorersettings.h b/src/plugins/projectexplorer/projectexplorersettings.h index a65dbc2f6eb..48cc85c414b 100644 --- a/src/plugins/projectexplorer/projectexplorersettings.h +++ b/src/plugins/projectexplorer/projectexplorersettings.h @@ -74,14 +74,6 @@ public: int maxCharCount = Core::Constants::DEFAULT_MAX_CHAR_COUNT; }; -class CompileOutputSettings -{ -public: - bool popUp = false; - bool wrapOutput = false; - int maxCharCount = Core::Constants::DEFAULT_MAX_CHAR_COUNT; -}; - class ProjectExplorerSettingsPage : public Core::IOptionsPage { public: From a17fe325c08673787b10a9cb7622a0ef3262ff1d Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Thu, 1 Jun 2023 10:35:28 +0200 Subject: [PATCH 058/141] RemoteLinux: set a default QmlRunCommand If there is no device qmlRunCommand even though it is a remote device QmlProjectRunConfiguration uses a desktop path and on windows that results in wrong file separators -> "\usr\bin\appcontroller ..." Task-number: QDS-9994 Change-Id: I054addf86922b50bc2e2f620d536953b72ee3331 Reviewed-by: Tim Jenssen --- src/plugins/remotelinux/linuxdevice.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/remotelinux/linuxdevice.cpp b/src/plugins/remotelinux/linuxdevice.cpp index 59af192eaa2..cc44dddb3c4 100644 --- a/src/plugins/remotelinux/linuxdevice.cpp +++ b/src/plugins/remotelinux/linuxdevice.cpp @@ -978,6 +978,7 @@ LinuxDevice::LinuxDevice() addDeviceAction({Tr::tr("Open Remote Shell"), [](const IDevice::Ptr &device, QWidget *) { device->openTerminal(Environment(), FilePath()); }}); + setQmlRunCommand(filePath("qml")); } void LinuxDevice::_setOsType(Utils::OsType osType) From 1e09ac087a635f8207399d6851767214b75e0fb4 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Wed, 31 May 2023 23:44:43 +0200 Subject: [PATCH 059/141] SilverSearcher: Limit the number of calls to nextLine() It's a preparation step for the incremental parsing. Change-Id: I98268abd6d3e0210f218663a6c2bb701c3bfc070 Reviewed-by: Orgad Shaneh Reviewed-by: Qt CI Bot --- src/plugins/silversearcher/silversearcheroutputparser.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/plugins/silversearcher/silversearcheroutputparser.cpp b/src/plugins/silversearcher/silversearcheroutputparser.cpp index 65d773d0c68..e9e16fa077e 100644 --- a/src/plugins/silversearcher/silversearcheroutputparser.cpp +++ b/src/plugins/silversearcher/silversearcheroutputparser.cpp @@ -112,8 +112,10 @@ SearchResultItems parse(const QString &output, const std::optional Date: Wed, 31 May 2023 23:49:11 +0200 Subject: [PATCH 060/141] SilverSearcher: Use the text editor font for the results This looks more consistent with the results reported by the internal engine. Change-Id: I1f5a405bcfd7b32c01ef6d4db0324985e657f6a3 Reviewed-by: Qt CI Bot Reviewed-by: Orgad Shaneh --- src/plugins/silversearcher/outputparser_test.cpp | 1 + src/plugins/silversearcher/silversearcheroutputparser.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/plugins/silversearcher/outputparser_test.cpp b/src/plugins/silversearcher/outputparser_test.cpp index 4aaacf37e68..e517e7e851d 100644 --- a/src/plugins/silversearcher/outputparser_test.cpp +++ b/src/plugins/silversearcher/outputparser_test.cpp @@ -18,6 +18,7 @@ SearchResultItem searchResult(const FilePath &fileName, const QString &matchingL result.setFilePath(fileName); result.setLineText(matchingLine); result.setMainRange(lineNumber, matchStart, matchLength); + result.setUseTextEditorFont(true); return result; } diff --git a/src/plugins/silversearcher/silversearcheroutputparser.cpp b/src/plugins/silversearcher/silversearcheroutputparser.cpp index e9e16fa077e..1cd1538830e 100644 --- a/src/plugins/silversearcher/silversearcheroutputparser.cpp +++ b/src/plugins/silversearcher/silversearcheroutputparser.cpp @@ -128,6 +128,7 @@ SearchResultItems parse(const QString &output, const std::optional &hit : hits) { item.setMainRange(lineNumber, hit.first, hit.second); item.setUserData( From 5c5624007beac1b69eae873d25e4c41644f380c3 Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 31 May 2023 08:49:34 +0200 Subject: [PATCH 061/141] FakeVim: Use PagedSettings for main settings Change-Id: I5029ae42ca5c3ec426d37a818150677186dd55ea Reviewed-by: Alessandro Portale --- src/plugins/fakevim/fakevimactions.cpp | 148 +++++++++++++++++++++++-- src/plugins/fakevim/fakevimactions.h | 4 +- src/plugins/fakevim/fakevimplugin.cpp | 130 +--------------------- 3 files changed, 144 insertions(+), 138 deletions(-) diff --git a/src/plugins/fakevim/fakevimactions.cpp b/src/plugins/fakevim/fakevimactions.cpp index dc051d81040..b753939c056 100644 --- a/src/plugins/fakevim/fakevimactions.cpp +++ b/src/plugins/fakevim/fakevimactions.cpp @@ -10,6 +10,13 @@ // Qt Creator. The idea is to keep this file here in a "clean" state that // allows easy reuse with any QTextEdit or QPlainTextEdit derived class. +#ifndef FAKEVIM_STANDALONE +#include +#include +#include +#include +#endif + #include #include #include @@ -62,13 +69,31 @@ QString FvBaseAspect::settingsKey() const void setAutoApply(bool ) {} #endif + +static FakeVimSettings *s_settings; + +FakeVimSettings *fakeVimSettings() +{ + return s_settings; +} + FakeVimSettings::FakeVimSettings() { - setAutoApply(false); + s_settings = this; #ifndef FAKEVIM_STANDALONE + const char SETTINGS_CATEGORY[] = "D.FakeVim"; + const char SETTINGS_ID[] = "A.FakeVim.General"; + + setId(SETTINGS_ID); + setDisplayName(Tr::tr("General")); + setCategory(SETTINGS_CATEGORY); + setDisplayCategory(Tr::tr("FakeVim")); + setCategoryIconPath(":/fakevim/images/settingscategory_fakevim.png"); + setup(&useFakeVim, false, "UseFakeVim", {}, Tr::tr("Use FakeVim")); #endif + // Specific FakeVim settings setup(&readVimRc, false, "ReadVimRc", {}, Tr::tr("Read .vimrc from location:")); setup(&vimRcPath, QString(), "VimRcPath", {}, {}); // Tr::tr("Path to .vimrc") @@ -135,6 +160,121 @@ FakeVimSettings::FakeVimSettings() "%USERPROFILE%\\_vimrc on Windows, ~/.vimrc otherwise.")); vimRcPath.setPlaceHolderText(Tr::tr("Default: %1").arg(vimrcDefault)); vimRcPath.setDisplayStyle(FvStringAspect::PathChooserDisplay); + + setLayouter([this] { + using namespace Layouting; + using namespace TextEditor; + + Row bools { + Column { + autoIndent, + smartIndent, + expandTab, + smartTab, + hlSearch, + showCmd, + startOfLine, + passKeys, + blinkingCursor + }, + Column { + incSearch, + useCoreSearch, + ignoreCase, + smartCase, + wrapScan, + showMarks, + passControlKey, + relativeNumber, + tildeOp + } + }; + + Row ints { shiftWidth, tabStop, scrollOff, st }; + + vimRcPath.setEnabler(&readVimRc); + + Column strings { + backspace, + isKeyword, + Row {readVimRc, vimRcPath} + }; + + return Column { + useFakeVim, + + Group { + title(Tr::tr("Vim Behavior")), + Column { + bools, + ints, + strings + } + }, + + Group { + title(Tr::tr("Plugin Emulation")), + Column { + emulateVimCommentary, + emulateReplaceWithRegister, + emulateArgTextObj, + emulateExchange, + emulateSurround + } + }, + + Row { + PushButton { + text(Tr::tr("Copy Text Editor Settings")), + onClicked([this] { + TabSettings ts = TextEditorSettings::codeStyle()->tabSettings(); + TypingSettings tps = TextEditorSettings::typingSettings(); + expandTab.setValue(ts.m_tabPolicy != TabSettings::TabsOnlyTabPolicy); + tabStop.setValue(ts.m_tabSize); + shiftWidth.setValue(ts.m_indentSize); + smartTab.setValue(tps.m_smartBackspaceBehavior + == TypingSettings::BackspaceFollowsPreviousIndents); + autoIndent.setValue(true); + smartIndent.setValue(tps.m_autoIndent); + incSearch.setValue(true); + }), + }, + PushButton { + text(Tr::tr("Set Qt Style")), + onClicked([this] { + expandTab.setVolatileValue(true); + tabStop.setVolatileValue(4); + shiftWidth.setVolatileValue(4); + smartTab.setVolatileValue(true); + autoIndent.setVolatileValue(true); + smartIndent.setVolatileValue(true); + incSearch.setVolatileValue(true); + backspace.setVolatileValue(QString("indent,eol,start")); + passKeys.setVolatileValue(true); + }), + }, + PushButton { + text(Tr::tr("Set Plain Style")), + onClicked([this] { + expandTab.setVolatileValue(false); + tabStop.setVolatileValue(8); + shiftWidth.setVolatileValue(8); + smartTab.setVolatileValue(false); + autoIndent.setVolatileValue(false); + smartIndent.setVolatileValue(false); + incSearch.setVolatileValue(false); + backspace.setVolatileValue(QString()); + passKeys.setVolatileValue(false); + }), + }, + st + }, + st + }; + }); + + readSettings(); + #endif } @@ -187,11 +327,5 @@ void FakeVimSettings::setup(FvBaseAspect *aspect, m_nameToAspect[shortName] = aspect; } -FakeVimSettings *fakeVimSettings() -{ - static FakeVimSettings s; - return &s; -} - } // namespace Internal } // namespace FakeVim diff --git a/src/plugins/fakevim/fakevimactions.h b/src/plugins/fakevim/fakevimactions.h index 582630e83d1..2f3f72f6951 100644 --- a/src/plugins/fakevim/fakevimactions.h +++ b/src/plugins/fakevim/fakevimactions.h @@ -4,7 +4,7 @@ #pragma once #ifndef FAKEVIM_STANDALONE -# include +# include #endif #include @@ -68,7 +68,7 @@ public: #else -using FvAspectContainer = Utils::AspectContainer; +using FvAspectContainer = Core::PagedSettings; using FvBaseAspect = Utils::BaseAspect; using FvBoolAspect = Utils::BoolAspect; using FvIntegerAspect = Utils::IntegerAspect; diff --git a/src/plugins/fakevim/fakevimplugin.cpp b/src/plugins/fakevim/fakevimplugin.cpp index 49354921325..c0e908ed573 100644 --- a/src/plugins/fakevim/fakevimplugin.cpp +++ b/src/plugins/fakevim/fakevimplugin.cpp @@ -340,134 +340,6 @@ private: using ExCommandMap = QMap; using UserCommandMap = QMap; -static void layoutPage(QWidget *widget) -{ - using namespace Layouting; - FakeVimSettings &s = *fakeVimSettings(); - - Row bools { - Column { - s.autoIndent, - s.smartIndent, - s.expandTab, - s.smartTab, - s.hlSearch, - s.showCmd, - s.startOfLine, - s.passKeys, - s.blinkingCursor - }, - Column { - s.incSearch, - s.useCoreSearch, - s.ignoreCase, - s.smartCase, - s.wrapScan, - s.showMarks, - s.passControlKey, - s.relativeNumber, - s.tildeOp - } - }; - - Row ints { s.shiftWidth, s.tabStop, s.scrollOff, st }; - - Column strings { - s.backspace, - s.isKeyword, - Row {s.readVimRc, s.vimRcPath} - }; - - Column { - s.useFakeVim, - - Group { - title(Tr::tr("Vim Behavior")), - Column { - bools, - ints, - strings - } - }, - - Group { - title(Tr::tr("Plugin Emulation")), - Column { - s.emulateVimCommentary, - s.emulateReplaceWithRegister, - s.emulateArgTextObj, - s.emulateExchange, - s.emulateSurround - } - }, - - Row { - PushButton { - text(Tr::tr("Copy Text Editor Settings")), - onClicked([&s] { - TabSettings ts = TextEditorSettings::codeStyle()->tabSettings(); - TypingSettings tps = TextEditorSettings::typingSettings(); - s.expandTab.setValue(ts.m_tabPolicy != TabSettings::TabsOnlyTabPolicy); - s.tabStop.setValue(ts.m_tabSize); - s.shiftWidth.setValue(ts.m_indentSize); - s.smartTab.setValue(tps.m_smartBackspaceBehavior - == TypingSettings::BackspaceFollowsPreviousIndents); - s.autoIndent.setValue(true); - s.smartIndent.setValue(tps.m_autoIndent); - s.incSearch.setValue(true); - }), - }, - PushButton { - text(Tr::tr("Set Qt Style")), - onClicked([&s] { - s.expandTab.setVolatileValue(true); - s.tabStop.setVolatileValue(4); - s.shiftWidth.setVolatileValue(4); - s.smartTab.setVolatileValue(true); - s.autoIndent.setVolatileValue(true); - s.smartIndent.setVolatileValue(true); - s.incSearch.setVolatileValue(true); - s.backspace.setVolatileValue(QString("indent,eol,start")); - s.passKeys.setVolatileValue(true); - }), - }, - PushButton { - text(Tr::tr("Set Plain Style")), - onClicked([&s] { - s.expandTab.setVolatileValue(false); - s.tabStop.setVolatileValue(8); - s.shiftWidth.setVolatileValue(8); - s.smartTab.setVolatileValue(false); - s.autoIndent.setVolatileValue(false); - s.smartIndent.setVolatileValue(false); - s.incSearch.setVolatileValue(false); - s.backspace.setVolatileValue(QString()); - s.passKeys.setVolatileValue(false); - }), - }, - st - }, - st - - }.attachTo(widget); - - s.vimRcPath.setEnabler(&s.readVimRc); -} - -class FakeVimOptionPage : public IOptionsPage -{ -public: - FakeVimOptionPage() - { - setId(SETTINGS_ID); - setDisplayName(Tr::tr("General")); - setCategory(SETTINGS_CATEGORY); - setDisplayCategory(Tr::tr("FakeVim")); - setCategoryIconPath(":/fakevim/images/settingscategory_fakevim.png"); - setLayouter(&layoutPage); - setSettings(fakeVimSettings()); - } -}; /////////////////////////////////////////////////////////////////////// // @@ -1107,7 +979,7 @@ IAssistProcessor *FakeVimCompletionAssistProvider::createProcessor(const AssistI class FakeVimPluginRunData { public: - FakeVimOptionPage optionsPage; + FakeVimSettings settings; FakeVimExCommandsPage exCommandsPage; FakeVimUserCommandsPage userCommandsPage; From a3bb39d3c37aebd63af5cf908a177cb69292460e Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Thu, 1 Jun 2023 00:54:51 +0200 Subject: [PATCH 062/141] SilverSearcher: Do some cleanup Remove unneeded includes. Code style corrections. Make global functions in cpp static. Fix const correctness. Fix nameFiltersAsRegExp variable name. Remove unneeded d'tor. Change-Id: Ia8aef3701bc8853905a3661242b33351ce319004 Reviewed-by: Reviewed-by: Qt CI Bot Reviewed-by: Orgad Shaneh --- .../findinfilessilversearcher.cpp | 64 +++++++------------ .../findinfilessilversearcher.h | 6 +- 2 files changed, 27 insertions(+), 43 deletions(-) diff --git a/src/plugins/silversearcher/findinfilessilversearcher.cpp b/src/plugins/silversearcher/findinfilessilversearcher.cpp index 52e9f08a956..a9105e4f4ba 100644 --- a/src/plugins/silversearcher/findinfilessilversearcher.cpp +++ b/src/plugins/silversearcher/findinfilessilversearcher.cpp @@ -3,12 +3,8 @@ #include "findinfilessilversearcher.h" -#include #include -#include #include -#include -#include #include #include @@ -25,11 +21,8 @@ using namespace TextEditor; using namespace Utils; namespace { -const QLatin1String silverSearcherName("Silver Searcher"); - -const QString metacharacters = "+()^$.{}[]|\\"; - -const QString SearchOptionsString = "SearchOptionsString"; +const QLatin1String s_metaCharacters = QLatin1String("+()^$.{}[]|\\"); +const QLatin1String s_searchOptionsString = QLatin1String("SearchOptionsString"); class SilverSearcherSearchOptions { @@ -37,43 +30,37 @@ public: QString searchOptions; }; -QString convertWildcardToRegex(const QString &wildcard) +static QString convertWildcardToRegex(const QString &wildcard) { QString regex; const int wildcardSize = wildcard.size(); regex.append('^'); for (int i = 0; i < wildcardSize; ++i) { const QChar ch = wildcard[i]; - if (ch == '*') { + if (ch == '*') regex.append(".*"); - } else if (ch == '?') { + else if (ch == '?') regex.append('.'); - } else if (metacharacters.indexOf(ch) != -1) { - regex.append('\\'); + else if (s_metaCharacters.indexOf(ch) != -1) + regex.append('\\' + ch); + else regex.append(ch); - } else { - regex.append(ch); - } } regex.append('$'); - return regex; } -bool isSilverSearcherAvailable() +static bool isSilverSearcherAvailable() { Process silverSearcherProcess; silverSearcherProcess.setCommand({"ag", {"--version"}}); silverSearcherProcess.start(); - if (silverSearcherProcess.waitForFinished(1000)) { - if (silverSearcherProcess.cleanedStdOut().contains("ag version")) - return true; - } - - return false; + return silverSearcherProcess.waitForFinished(1000) + && silverSearcherProcess.cleanedStdOut().contains("ag version"); } -void runSilverSeacher(QPromise &promise, FileFindParameters parameters) +static void runSilverSeacher(QPromise &promise, + const FileFindParameters ¶meters) { const FilePath directory = FilePath::fromUserInput(parameters.additionalParameters.toString()); QStringList arguments = {"--parallel", "--ackmate"}; @@ -92,15 +79,15 @@ void runSilverSeacher(QPromise &promise, FileFindParameters p for (const QString &filter : std::as_const(parameters.exclusionFilters)) arguments << "--ignore" << filter; - QString nameFiltersAsRegex; + QString nameFiltersAsRegExp; for (const QString &filter : std::as_const(parameters.nameFilters)) - nameFiltersAsRegex += QString("(%1)|").arg(convertWildcardToRegex(filter)); - nameFiltersAsRegex.remove(nameFiltersAsRegex.length() - 1, 1); + nameFiltersAsRegExp += QString("(%1)|").arg(convertWildcardToRegex(filter)); + nameFiltersAsRegExp.remove(nameFiltersAsRegExp.length() - 1, 1); - arguments << "-G" << nameFiltersAsRegex; + arguments << "-G" << nameFiltersAsRegExp; - SilverSearcherSearchOptions params = parameters.searchEngineParameters - .value(); + const SilverSearcherSearchOptions params = parameters.searchEngineParameters + .value(); if (!params.searchOptions.isEmpty()) arguments << params.searchOptions.split(' '); @@ -150,6 +137,7 @@ FindInFilesSilverSearcher::FindInFilesSilverSearcher(QObject *parent) QTC_ASSERT(findInFiles, return); findInFiles->addSearchEngine(this); + // TODO: Make disabled by default and run isSilverSearcherAvailable asynchronously setEnabled(isSilverSearcherAvailable()); if (!isEnabled()) { QLabel *label = new QLabel(Tr::tr("Silver Searcher is not available on the system.")); @@ -158,10 +146,6 @@ FindInFilesSilverSearcher::FindInFilesSilverSearcher(QObject *parent) } } -FindInFilesSilverSearcher::~FindInFilesSilverSearcher() -{ -} - QVariant FindInFilesSilverSearcher::parameters() const { SilverSearcherSearchOptions silverSearcherSearchOptions; @@ -171,12 +155,12 @@ QVariant FindInFilesSilverSearcher::parameters() const QString FindInFilesSilverSearcher::title() const { - return silverSearcherName; + return "Silver Searcher"; } QString FindInFilesSilverSearcher::toolTip() const { - return QString(); + return {}; } QWidget *FindInFilesSilverSearcher::widget() const @@ -186,7 +170,7 @@ QWidget *FindInFilesSilverSearcher::widget() const void FindInFilesSilverSearcher::writeSettings(QSettings *settings) const { - settings->setValue(SearchOptionsString, m_searchOptionsLineEdit->text()); + settings->setValue(s_searchOptionsString, m_searchOptionsLineEdit->text()); } QFuture FindInFilesSilverSearcher::executeSearch( @@ -203,7 +187,7 @@ IEditor *FindInFilesSilverSearcher::openEditor(const SearchResultItem & /*item*/ void FindInFilesSilverSearcher::readSettings(QSettings *settings) { - m_searchOptionsLineEdit->setText(settings->value(SearchOptionsString).toString()); + m_searchOptionsLineEdit->setText(settings->value(s_searchOptionsString).toString()); } } // namespace SilverSearcher diff --git a/src/plugins/silversearcher/findinfilessilversearcher.h b/src/plugins/silversearcher/findinfilessilversearcher.h index 85b35192b8e..bc5e224c21f 100644 --- a/src/plugins/silversearcher/findinfilessilversearcher.h +++ b/src/plugins/silversearcher/findinfilessilversearcher.h @@ -3,10 +3,9 @@ #pragma once -#include #include -#include +#include #include @@ -14,6 +13,8 @@ QT_BEGIN_NAMESPACE class QLineEdit; QT_END_NAMESPACE +namespace Core { class IFindSupport; } + namespace SilverSearcher { class FindInFilesSilverSearcher : public TextEditor::SearchEngine @@ -22,7 +23,6 @@ class FindInFilesSilverSearcher : public TextEditor::SearchEngine public: explicit FindInFilesSilverSearcher(QObject *parent); - ~FindInFilesSilverSearcher() override; // TextEditor::FileFindExtension QString title() const override; From 5e8795b35382e0c95634c75f411bd9e1e0db8cd4 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Thu, 1 Jun 2023 01:09:26 +0200 Subject: [PATCH 063/141] SilverSearcher: Rename output into input The passed text is an output from the ag command, but, as seen from the parser point of view, that's the input data for the parser. Change-Id: Ic5d42406fd5ff1f52969fde3c2d44aaa34b9133b Reviewed-by: Orgad Shaneh --- .../silversearcher/outputparser_test.cpp | 6 +-- .../silversearcheroutputparser.cpp | 38 +++++++++---------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/plugins/silversearcher/outputparser_test.cpp b/src/plugins/silversearcher/outputparser_test.cpp index e517e7e851d..74a82323363 100644 --- a/src/plugins/silversearcher/outputparser_test.cpp +++ b/src/plugins/silversearcher/outputparser_test.cpp @@ -24,7 +24,7 @@ SearchResultItem searchResult(const FilePath &fileName, const QString &matchingL void OutputParserTest::test_data() { - QTest::addColumn("parserOutput"); + QTest::addColumn("input"); QTest::addColumn("results"); QTest::addRow("nothing") << QString("\n") << SearchResultItems(); @@ -59,9 +59,9 @@ void OutputParserTest::test_data() void OutputParserTest::test() { - QFETCH(QString, parserOutput); + QFETCH(QString, input); QFETCH(SearchResultItems, results); - const SearchResultItems items = SilverSearcher::parse(parserOutput); + const SearchResultItems items = SilverSearcher::parse(input); QCOMPARE(items, results); } diff --git a/src/plugins/silversearcher/silversearcheroutputparser.cpp b/src/plugins/silversearcher/silversearcheroutputparser.cpp index 1cd1538830e..811a4e1bfd5 100644 --- a/src/plugins/silversearcher/silversearcheroutputparser.cpp +++ b/src/plugins/silversearcher/silversearcheroutputparser.cpp @@ -19,16 +19,16 @@ namespace SilverSearcher { 10;8 2,35 2:PropertyAbstractContainer::PropertyAbstractContainer() */ -static QStringView nextLine(QStringView *remainingOutput) +static QStringView nextLine(QStringView *remainingInput) { - const int newLinePos = remainingOutput->indexOf('\n'); + const int newLinePos = remainingInput->indexOf('\n'); if (newLinePos < 0) { - QStringView ret = *remainingOutput; - *remainingOutput = QStringView(); + QStringView ret = *remainingInput; + *remainingInput = QStringView(); return ret; } - QStringView ret = remainingOutput->left(newLinePos); - *remainingOutput = remainingOutput->mid(newLinePos + 1); + QStringView ret = remainingInput->left(newLinePos); + *remainingInput = remainingInput->mid(newLinePos + 1); return ret; } @@ -45,16 +45,16 @@ static bool parseNumber(QStringView numberString, int *number) return ok; } -static bool parseLineNumber(QStringView *remainingOutput, int *lineNumber) +static bool parseLineNumber(QStringView *remainingInput, int *lineNumber) { - const int lineNumberDelimiterPos = remainingOutput->indexOf(';'); + const int lineNumberDelimiterPos = remainingInput->indexOf(';'); if (lineNumberDelimiterPos < 0) return false; - if (!parseNumber(remainingOutput->left(lineNumberDelimiterPos), lineNumber)) + if (!parseNumber(remainingInput->left(lineNumberDelimiterPos), lineNumber)) return false; - *remainingOutput = remainingOutput->mid(lineNumberDelimiterPos + 1); + *remainingInput = remainingInput->mid(lineNumberDelimiterPos + 1); return true; } @@ -76,13 +76,13 @@ static bool parseLineHit(QStringView hitString, QPair *hit) return true; } -static bool parseLineHits(QStringView *remainingOutput, QList> *hits) +static bool parseLineHits(QStringView *remainingInput, QList> *hits) { - const int hitsDelimiterPos = remainingOutput->indexOf(':'); + const int hitsDelimiterPos = remainingInput->indexOf(':'); if (hitsDelimiterPos < 0) return false; - const QStringView hitsString = remainingOutput->left(hitsDelimiterPos); + const QStringView hitsString = remainingInput->left(hitsDelimiterPos); const QList hitStrings = hitsString.split(',', Qt::SkipEmptyParts); for (const auto hitString : hitStrings) { QPair hit; @@ -90,20 +90,20 @@ static bool parseLineHits(QStringView *remainingOutput, QList> * return false; hits->append(hit); } - *remainingOutput = remainingOutput->mid(hitsDelimiterPos + 1); + *remainingInput = remainingInput->mid(hitsDelimiterPos + 1); return true; } -SearchResultItems parse(const QString &output, const std::optional ®Exp) +SearchResultItems parse(const QString &input, const std::optional ®Exp) { SearchResultItems items; - QStringView remainingOutput(output); + QStringView remainingInput(input); while (true) { - if (remainingOutput.isEmpty()) + if (remainingInput.isEmpty()) break; - const QStringView filePathLine = nextLine(&remainingOutput); + const QStringView filePathLine = nextLine(&remainingInput); if (filePathLine.isEmpty()) continue; @@ -113,7 +113,7 @@ SearchResultItems parse(const QString &output, const std::optional Date: Thu, 1 Jun 2023 01:26:40 +0200 Subject: [PATCH 064/141] SilverSearcher: Rename some files Make naming more consistent. Change-Id: Ic6ca72e5d048e5e452df6ead2b7da8f3c1cd0282 Reviewed-by: Reviewed-by: Orgad Shaneh --- src/plugins/silversearcher/CMakeLists.txt | 4 ++-- src/plugins/silversearcher/findinfilessilversearcher.cpp | 5 ++--- src/plugins/silversearcher/silversearcher.qbs | 6 +++--- ...versearcheroutputparser.cpp => silversearcherparser.cpp} | 2 +- ...{silversearcheroutputparser.h => silversearcherparser.h} | 0 ...{outputparser_test.cpp => silversearcherparser_test.cpp} | 4 ++-- .../{outputparser_test.h => silversearcherparser_test.h} | 0 src/plugins/silversearcher/silversearcherplugin.cpp | 4 ++-- 8 files changed, 12 insertions(+), 13 deletions(-) rename src/plugins/silversearcher/{silversearcheroutputparser.cpp => silversearcherparser.cpp} (99%) rename src/plugins/silversearcher/{silversearcheroutputparser.h => silversearcherparser.h} (100%) rename src/plugins/silversearcher/{outputparser_test.cpp => silversearcherparser_test.cpp} (97%) rename src/plugins/silversearcher/{outputparser_test.h => silversearcherparser_test.h} (100%) diff --git a/src/plugins/silversearcher/CMakeLists.txt b/src/plugins/silversearcher/CMakeLists.txt index 7cc12ebb294..2af582d4a3e 100644 --- a/src/plugins/silversearcher/CMakeLists.txt +++ b/src/plugins/silversearcher/CMakeLists.txt @@ -2,12 +2,12 @@ add_qtc_plugin(SilverSearcher PLUGIN_DEPENDS Core TextEditor SOURCES findinfilessilversearcher.cpp findinfilessilversearcher.h - silversearcheroutputparser.cpp silversearcheroutputparser.h + silversearcherparser.cpp silversearcherparser.h silversearcherplugin.cpp silversearcherplugin.h silversearchertr.h ) extend_qtc_plugin(SilverSearcher CONDITION WITH_TESTS SOURCES - outputparser_test.cpp outputparser_test.h + silversearcherparser_test.cpp silversearcherparser_test.h ) diff --git a/src/plugins/silversearcher/findinfilessilversearcher.cpp b/src/plugins/silversearcher/findinfilessilversearcher.cpp index a9105e4f4ba..43397a03f6d 100644 --- a/src/plugins/silversearcher/findinfilessilversearcher.cpp +++ b/src/plugins/silversearcher/findinfilessilversearcher.cpp @@ -2,15 +2,14 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "findinfilessilversearcher.h" +#include "silversearcherparser.h" +#include "silversearchertr.h" #include #include #include #include -#include "silversearcheroutputparser.h" -#include "silversearchertr.h" - #include #include #include diff --git a/src/plugins/silversearcher/silversearcher.qbs b/src/plugins/silversearcher/silversearcher.qbs index 8cf2cd15090..08a25367aad 100644 --- a/src/plugins/silversearcher/silversearcher.qbs +++ b/src/plugins/silversearcher/silversearcher.qbs @@ -9,14 +9,14 @@ QtcPlugin { files: [ "findinfilessilversearcher.cpp", "findinfilessilversearcher.h", - "silversearcheroutputparser.cpp", "silversearcheroutputparser.h", + "silversearcherparser.cpp", "silversearcherparser.h", "silversearcherplugin.cpp", "silversearcherplugin.h", ] QtcTestFiles { files: [ - "outputparser_test.cpp", - "outputparser_test.h", + "silversearcherparser_test.cpp", + "silversearcherparser_test.h", ] } } diff --git a/src/plugins/silversearcher/silversearcheroutputparser.cpp b/src/plugins/silversearcher/silversearcherparser.cpp similarity index 99% rename from src/plugins/silversearcher/silversearcheroutputparser.cpp rename to src/plugins/silversearcher/silversearcherparser.cpp index 811a4e1bfd5..be4e9096c4c 100644 --- a/src/plugins/silversearcher/silversearcheroutputparser.cpp +++ b/src/plugins/silversearcher/silversearcherparser.cpp @@ -1,7 +1,7 @@ // Copyright (C) 2017 Przemyslaw Gorszkowski . // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 -#include "silversearcheroutputparser.h" +#include "silversearcherparser.h" using namespace Utils; diff --git a/src/plugins/silversearcher/silversearcheroutputparser.h b/src/plugins/silversearcher/silversearcherparser.h similarity index 100% rename from src/plugins/silversearcher/silversearcheroutputparser.h rename to src/plugins/silversearcher/silversearcherparser.h diff --git a/src/plugins/silversearcher/outputparser_test.cpp b/src/plugins/silversearcher/silversearcherparser_test.cpp similarity index 97% rename from src/plugins/silversearcher/outputparser_test.cpp rename to src/plugins/silversearcher/silversearcherparser_test.cpp index 74a82323363..b23002e191e 100644 --- a/src/plugins/silversearcher/outputparser_test.cpp +++ b/src/plugins/silversearcher/silversearcherparser_test.cpp @@ -1,8 +1,8 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 -#include "outputparser_test.h" -#include "silversearcheroutputparser.h" +#include "silversearcherparser.h" +#include "silversearcherparser_test.h" #include diff --git a/src/plugins/silversearcher/outputparser_test.h b/src/plugins/silversearcher/silversearcherparser_test.h similarity index 100% rename from src/plugins/silversearcher/outputparser_test.h rename to src/plugins/silversearcher/silversearcherparser_test.h diff --git a/src/plugins/silversearcher/silversearcherplugin.cpp b/src/plugins/silversearcher/silversearcherplugin.cpp index e16ed4a3498..1f143407d78 100644 --- a/src/plugins/silversearcher/silversearcherplugin.cpp +++ b/src/plugins/silversearcher/silversearcherplugin.cpp @@ -1,9 +1,9 @@ // Copyright (C) 2017 Przemyslaw Gorszkowski . // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 -#include "silversearcherplugin.h" #include "findinfilessilversearcher.h" -#include "outputparser_test.h" +#include "silversearcherparser_test.h" +#include "silversearcherplugin.h" namespace SilverSearcher::Internal { From b9e5f4b5c04261fa9fb4ecbd3981d4e0342f0b95 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Fri, 12 May 2023 08:44:30 +0200 Subject: [PATCH 065/141] Add change log for 11.0.0 Change-Id: I986a5771c2be5f4875d44b7cdb9f58c1e5fd0b17 Reviewed-by: Leena Miettinen --- dist/changelog/changes-11.0.0.md | 223 +++++++++++++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 dist/changelog/changes-11.0.0.md diff --git a/dist/changelog/changes-11.0.0.md b/dist/changelog/changes-11.0.0.md new file mode 100644 index 00000000000..5600390c091 --- /dev/null +++ b/dist/changelog/changes-11.0.0.md @@ -0,0 +1,223 @@ +Qt Creator 11 +============= + +Qt Creator version 11 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/10.0..v11.0.0 + +General +------- + +* Added a `Terminal` view (QTCREATORBUG-8511) + * Opt-out via `Preferences` > `Terminal` preferences + * Added support for + * different shells, colors, fonts, and multiple tabs + * opening file paths in Qt Creator with `Ctrl+click` (`Cmd+click` on + macOS) +* Added a more spacious "relaxed" toolbar style `Environment > Interface` +* Added a pin button to progress details instead of automatically resetting + their position (QTCREATORBUG-28829) +* Improved the selection and navigation in the `Issues` view + (QTCREATORBUG-26128, QTCREATORBUG-27006, QTCREATORBUG-27506) +* Locator + * Improved performance + * Added the creation of directories to the `Files in File System` filter + * Added device roots and browsing remote file systems to the + `Files in File System` filter + +Editing +------- + +* Improved the performance of the multi-cursor support +* Fixed the saving of hardlinked files (QTCREATORBUG-19651) +* Fixed an issue of copy and paste with multiple cursors (QTCREATORBUG-29117) + +### C++ + +* Improved the style of forward declarations in the outline (QTCREATORBUG-312) +* Added highlighting for typed string literals and user-defined literals + (QTCREATORBUG-28869) +* Added the option to create class members from assignments (QTCREATORBUG-1918) +* Fixed that locator showed both the declaration and the definition of symbols + (QTCREATORBUG-13894) +* Fixed the handling of C++20 keywords and concepts +* Built-in + * Fixed support for `if`-statements with initializer (QTCREATORBUG-29182) + +### Language Server Protocol + +* Added experimental support for GitHub Copilot + ([GitHub documentation](https://github.com/features/copilot)) +* Added missing actions for opening the `Call Hierarchy` (QTCREATORBUG-28839, + QTCREATORBUG-28842) + +### QML + +* Fixed the reformatting in the presence of JavaScript directives and function + return type annotations (QTCREATORBUG-29001, QTCREATORBUG-29046) +* Fixed that reformatting changed `of` to `in` (QTCREATORBUG-29123) +* Fixed the completion for Qt Quick Controls (QTCREATORBUG-28648) + +### Python + +* Added the option to create a virtual environment (`venv`) to the Python + interpreter selector and the wizard (PYSIDE-2152) + +### Markdown + +* Added a Markdown editor with preview (QTCREATORBUG-27883) +* Added a wizard for Markdown files (QTCREATORBUG-29056) + +Projects +-------- + +* Made it possible to add devices without going through the wizard +* Added support for moving files to a different directory when renaming + (QTCREATORBUG-15981) + +### CMake + +* Implemented adding files to the project (QTCREATORBUG-25922, + QTCREATORBUG-26006, QTCREATORBUG-27213, QTCREATORBUG-27538, + QTCREATORBUG-28493, QTCREATORBUG-28904, QTCREATORBUG-28985, + QTCREATORBUG-29006) +* Fixed issues with detecting a configured Qt version when importing a build + (QTCREATORBUG-29075) + +### Python + +* Added an option for the interpreter to the wizards + +### vcpkg + +* Added experimental support for `vcpkg` + ([vcpgk documentation](https://vcpkg.io/en/)) +* Added an option for the `vcpkg` installation location +* Added a search dialog for packages +* Added a wizard and an editor for `vcpkg.json` files + +Debugging +--------- + +* Improved the UI for enabling and disabling debuggers (QTCREATORBUG-28627) + +### C++ + +* Added an option for the default number of array elements to show + (`Preferences > Debugger > Locals & Expressions > Default array size`) +* CDB + * Added automatic source file mapping for Qt packages + * Fixed the variables view on remote Windows devices (QTCREATORBUG-29000) +* LLDB + * Fixed that long lines in the application output were broken into multiple + lines (QTCREATORBUG-29098) + +### Qt Quick + +* Improved the auto-detection if QML debugging is required (QTCREATORBUG-28627) +* Added an option for disabling static analyzer messages to + `Qt Quick > QML/JS Editing` (QTCREATORBUG-29095) + +Analyzer +-------- + +### Clang + +* Fixed that a `.clang-tidy` file in the project directory was not used by + default (QTCREATORBUG-28852) + +### Axivion + +* Added experimental support + +Version Control Systems +----------------------- + +### Git + +* Instant Blame + * Improved the performance (QTCREATORBUG-29151) + * Fixed that it did not show at the end of the document + +Platforms +--------- + +### Android + +* Fixed an issue with building library targets (QTCREATORBUG-26980) + +### Remote Linux + +* Removed the automatic sourcing of target-side shell profiles + +### Docker + +* Added support for `qmake` based projects (QTCREATORBUG-29140) +* Fixed issues after deleting the Docker image for a registered Docker device + (QTCREATORBUG-28880) + +### QNX + +* Added `slog2info` as a requirement for devices +* Fixed the support for remote working directories (QTCREATORBUG-28900) + +Credits for these changes go to: +-------------------------------- +Aleksei German +Alessandro Portale +Alexander Drozdov +Alexander Pershin +Ali Kianian +Alibek Omarov +Amr Essam +Andre Hartmann +André Pönitz +Artem Mukhin +Artem Sokolovskii +Assam Boudjelthia +Björn Schäpers +Brook Cronin +Burak Hancerli +Christian Kandeler +Christian Stenger +Cristian Adam +David Schulz +Eike Ziller +Esa Törmänen +Fabian Kosmale +Filippo Gentile +Friedemann Kleint +Henning Gruendl +Jaroslaw Kobus +Jussi Witick +Kai Köhne +Knud Dollereder +Knut Petter Svendsen +Leena Miettinen +Mahmoud Badri +Marco Bubke +Marcus Tillmanns +Martin Delille +Mats Honkamaa +Miikka Heikkinen +Mitch Curtis +Niels Weber +Orgad Shaneh +Pranta Dastider +Robert Löhning +Samuel Ghinet +Semih Yavuz +Tasuku Suzuki +Thiago Macieira +Thomas Hartmann +Tim Jenssen +Tim Jenßen +Ulf Hermann +Vikas Pachdha +Yasser Grimes +Yixue Wang From 5e9eadfc5816cc30ac221e533e416cc7ebc713af Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Sun, 28 May 2023 22:07:17 +0200 Subject: [PATCH 066/141] TaskTree: Introduce finishAllAndError workflow policy It's going to be used in timeout task. Change-Id: I2abd65b461cab445ada7a0ad5e1bbe07d1b6323b Reviewed-by: Qt CI Bot Reviewed-by: Marcus Tillmanns Reviewed-by: --- src/libs/solutions/tasking/tasktree.cpp | 8 +- src/libs/solutions/tasking/tasktree.h | 6 +- tests/auto/solutions/tasking/tst_tasking.cpp | 154 ++++++++++++------- 3 files changed, 110 insertions(+), 58 deletions(-) diff --git a/src/libs/solutions/tasking/tasktree.cpp b/src/libs/solutions/tasking/tasktree.cpp index 62243f373a1..6f2bb7ad4f5 100644 --- a/src/libs/solutions/tasking/tasktree.cpp +++ b/src/libs/solutions/tasking/tasktree.cpp @@ -404,12 +404,14 @@ TaskItem workflowPolicy(WorkflowPolicy policy) const TaskItem sequential = parallelLimit(1); const TaskItem parallel = parallelLimit(0); + const TaskItem stopOnError = workflowPolicy(WorkflowPolicy::StopOnError); const TaskItem continueOnError = workflowPolicy(WorkflowPolicy::ContinueOnError); const TaskItem stopOnDone = workflowPolicy(WorkflowPolicy::StopOnDone); const TaskItem continueOnDone = workflowPolicy(WorkflowPolicy::ContinueOnDone); const TaskItem stopOnFinished = workflowPolicy(WorkflowPolicy::StopOnFinished); const TaskItem finishAllAndDone = workflowPolicy(WorkflowPolicy::FinishAllAndDone); +const TaskItem finishAllAndError = workflowPolicy(WorkflowPolicy::FinishAllAndError); static TaskAction toTaskAction(bool success) { @@ -859,7 +861,8 @@ TaskContainer::RuntimeData::RuntimeData(const ConstData &constData) , m_storageIdList(createStorages(constData)) { m_successBit = m_constData.m_workflowPolicy != WorkflowPolicy::StopOnDone - && m_constData.m_workflowPolicy != WorkflowPolicy::ContinueOnDone; + && m_constData.m_workflowPolicy != WorkflowPolicy::ContinueOnDone + && m_constData.m_workflowPolicy != WorkflowPolicy::FinishAllAndError; } TaskContainer::RuntimeData::~RuntimeData() @@ -873,7 +876,8 @@ TaskContainer::RuntimeData::~RuntimeData() bool TaskContainer::RuntimeData::updateSuccessBit(bool success) { - if (m_constData.m_workflowPolicy == WorkflowPolicy::FinishAllAndDone) + if (m_constData.m_workflowPolicy == WorkflowPolicy::FinishAllAndDone + || m_constData.m_workflowPolicy == WorkflowPolicy::FinishAllAndError) return m_successBit; if (m_constData.m_workflowPolicy == WorkflowPolicy::StopOnFinished) { m_successBit = success; diff --git a/src/libs/solutions/tasking/tasktree.h b/src/libs/solutions/tasking/tasktree.h index 37403628a5a..c10cf495c31 100644 --- a/src/libs/solutions/tasking/tasktree.h +++ b/src/libs/solutions/tasking/tasktree.h @@ -102,6 +102,7 @@ private: // 3. Stops on first finished child. In sequential mode it will never run other children then the first one. // Useful only in parallel mode. // 4. Always run all children, let them finish, ignore their results and report done afterwards. +// 5. Always run all children, let them finish, ignore their results and report error afterwards. enum class WorkflowPolicy { StopOnError, // 1a - Reports error on first child error, otherwise done (if all children were done). @@ -109,7 +110,8 @@ enum class WorkflowPolicy { StopOnDone, // 2a - Reports done on first child done, otherwise error (if all children were error). ContinueOnDone, // 2b - The same, but children execution continues. Reports error when no children. StopOnFinished, // 3 - Stops on first finished child and report its result. - FinishAllAndDone // 4 - Reports done after all children finished. + FinishAllAndDone, // 4 - Reports done after all children finished. + FinishAllAndError // 5 - Reports error after all children finished. }; Q_ENUM_NS(WorkflowPolicy); @@ -247,12 +249,14 @@ TASKING_EXPORT TaskItem workflowPolicy(WorkflowPolicy policy); TASKING_EXPORT extern const TaskItem sequential; TASKING_EXPORT extern const TaskItem parallel; + TASKING_EXPORT extern const TaskItem stopOnError; TASKING_EXPORT extern const TaskItem continueOnError; TASKING_EXPORT extern const TaskItem stopOnDone; TASKING_EXPORT extern const TaskItem continueOnDone; TASKING_EXPORT extern const TaskItem stopOnFinished; TASKING_EXPORT extern const TaskItem finishAllAndDone; +TASKING_EXPORT extern const TaskItem finishAllAndError; class TASKING_EXPORT Storage : public TaskItem { diff --git a/tests/auto/solutions/tasking/tst_tasking.cpp b/tests/auto/solutions/tasking/tst_tasking.cpp index 051b807842b..ff760169d85 100644 --- a/tests/auto/solutions/tasking/tst_tasking.cpp +++ b/tests/auto/solutions/tasking/tst_tasking.cpp @@ -637,25 +637,36 @@ void tst_Tasking::testTree_data() }; }; - const Log log = {{0, Handler::GroupDone}}; + const Log doneLog = {{0, Handler::GroupDone}}; + const Log errorLog = {{0, Handler::GroupError}}; const Group root1 = createRoot(WorkflowPolicy::StopOnError); - QTest::newRow("EmptyStopOnError") << TestData{storage, root1, log, 0, OnDone::Success}; + QTest::newRow("EmptyStopOnError") << TestData{storage, root1, doneLog, 0, + OnDone::Success}; const Group root2 = createRoot(WorkflowPolicy::ContinueOnError); - QTest::newRow("EmptyContinueOnError") << TestData{storage, root2, log, 0, OnDone::Success}; + QTest::newRow("EmptyContinueOnError") << TestData{storage, root2, doneLog, 0, + OnDone::Success}; const Group root3 = createRoot(WorkflowPolicy::StopOnDone); - QTest::newRow("EmptyStopOnDone") << TestData{storage, root3, log, 0, OnDone::Success}; + QTest::newRow("EmptyStopOnDone") << TestData{storage, root3, doneLog, 0, + OnDone::Success}; const Group root4 = createRoot(WorkflowPolicy::ContinueOnDone); - QTest::newRow("EmptyContinueOnDone") << TestData{storage, root4, log, 0, OnDone::Success}; + QTest::newRow("EmptyContinueOnDone") << TestData{storage, root4, doneLog, 0, + OnDone::Success}; const Group root5 = createRoot(WorkflowPolicy::StopOnFinished); - QTest::newRow("EmptyStopOnFinished") << TestData{storage, root5, log, 0, OnDone::Success}; + QTest::newRow("EmptyStopOnFinished") << TestData{storage, root5, doneLog, 0, + OnDone::Success}; const Group root6 = createRoot(WorkflowPolicy::FinishAllAndDone); - QTest::newRow("EmptyOptional") << TestData{storage, root6, log, 0, OnDone::Success}; + QTest::newRow("EmptyFinishAllAndDone") << TestData{storage, root6, doneLog, 0, + OnDone::Success}; + + const Group root7 = createRoot(WorkflowPolicy::FinishAllAndError); + QTest::newRow("EmptyFinishAllAndError") << TestData{storage, root7, errorLog, 0, + OnDone::Failure}; } { @@ -670,29 +681,45 @@ void tst_Tasking::testTree_data() }; }; - const Log log = { + const Log doneLog = { {1, Handler::Setup}, {1, Handler::Done}, {0, Handler::GroupDone} }; + const Log errorLog = { + {1, Handler::Setup}, + {1, Handler::Done}, + {0, Handler::GroupError} + }; + const Group root1 = createRoot(WorkflowPolicy::StopOnError); - QTest::newRow("DoneStopOnError") << TestData{storage, root1, log, 1, OnDone::Success}; + QTest::newRow("DoneStopOnError") << TestData{storage, root1, doneLog, 1, + OnDone::Success}; const Group root2 = createRoot(WorkflowPolicy::ContinueOnError); - QTest::newRow("DoneContinueOnError") << TestData{storage, root2, log, 1, OnDone::Success}; + QTest::newRow("DoneContinueOnError") << TestData{storage, root2, doneLog, 1, + OnDone::Success}; const Group root3 = createRoot(WorkflowPolicy::StopOnDone); - QTest::newRow("DoneStopOnDone") << TestData{storage, root3, log, 1, OnDone::Success}; + QTest::newRow("DoneStopOnDone") << TestData{storage, root3, doneLog, 1, + OnDone::Success}; const Group root4 = createRoot(WorkflowPolicy::ContinueOnDone); - QTest::newRow("DoneContinueOnDone") << TestData{storage, root4, log, 1, OnDone::Success}; + QTest::newRow("DoneContinueOnDone") << TestData{storage, root4, doneLog, 1, + OnDone::Success}; const Group root5 = createRoot(WorkflowPolicy::StopOnFinished); - QTest::newRow("DoneStopOnFinished") << TestData{storage, root5, log, 1, OnDone::Success}; + QTest::newRow("DoneStopOnFinished") << TestData{storage, root5, doneLog, 1, + OnDone::Success}; const Group root6 = createRoot(WorkflowPolicy::FinishAllAndDone); - QTest::newRow("DoneOptional") << TestData{storage, root6, log, 1, OnDone::Success}; + QTest::newRow("DoneFinishAllAndDone") << TestData{storage, root6, doneLog, 1, + OnDone::Success}; + + const Group root7 = createRoot(WorkflowPolicy::FinishAllAndError); + QTest::newRow("DoneFinishAllAndError") << TestData{storage, root7, errorLog, 1, + OnDone::Failure}; } { @@ -707,35 +734,45 @@ void tst_Tasking::testTree_data() }; }; - const Log log = { - {1, Handler::Setup}, - {1, Handler::Error}, - {0, Handler::GroupError} - }; - - const Log optionalLog = { + const Log doneLog = { {1, Handler::Setup}, {1, Handler::Error}, {0, Handler::GroupDone} }; + const Log errorLog = { + {1, Handler::Setup}, + {1, Handler::Error}, + {0, Handler::GroupError} + }; + const Group root1 = createRoot(WorkflowPolicy::StopOnError); - QTest::newRow("ErrorStopOnError") << TestData{storage, root1, log, 1, OnDone::Failure}; + QTest::newRow("ErrorStopOnError") << TestData{storage, root1, errorLog, 1, + OnDone::Failure}; const Group root2 = createRoot(WorkflowPolicy::ContinueOnError); - QTest::newRow("ErrorContinueOnError") << TestData{storage, root2, log, 1, OnDone::Failure}; + QTest::newRow("ErrorContinueOnError") << TestData{storage, root2, errorLog, 1, + OnDone::Failure}; const Group root3 = createRoot(WorkflowPolicy::StopOnDone); - QTest::newRow("ErrorStopOnDone") << TestData{storage, root3, log, 1, OnDone::Failure}; + QTest::newRow("ErrorStopOnDone") << TestData{storage, root3, errorLog, 1, + OnDone::Failure}; const Group root4 = createRoot(WorkflowPolicy::ContinueOnDone); - QTest::newRow("ErrorContinueOnDone") << TestData{storage, root4, log, 1, OnDone::Failure}; + QTest::newRow("ErrorContinueOnDone") << TestData{storage, root4, errorLog, 1, + OnDone::Failure}; const Group root5 = createRoot(WorkflowPolicy::StopOnFinished); - QTest::newRow("ErrorStopOnFinished") << TestData{storage, root5, log, 1, OnDone::Failure}; + QTest::newRow("ErrorStopOnFinished") << TestData{storage, root5, errorLog, 1, + OnDone::Failure}; const Group root6 = createRoot(WorkflowPolicy::FinishAllAndDone); - QTest::newRow("ErrorOptional") << TestData{storage, root6, optionalLog, 1, OnDone::Success}; + QTest::newRow("ErrorFinishAllAndDone") << TestData{storage, root6, doneLog, 1, + OnDone::Success}; + + const Group root7 = createRoot(WorkflowPolicy::FinishAllAndError); + QTest::newRow("ErrorFinishAllAndError") << TestData{storage, root7, errorLog, 1, + OnDone::Failure}; } { @@ -800,8 +837,12 @@ void tst_Tasking::testTree_data() << TestData{storage, root5, errorErrorLog, 2, OnDone::Failure}; const Group root6 = createRoot(WorkflowPolicy::FinishAllAndDone); - QTest::newRow("StopRootWithOptional") + QTest::newRow("StopRootWithFinishAllAndDone") << TestData{storage, root6, doneLog, 2, OnDone::Success}; + + const Group root7 = createRoot(WorkflowPolicy::FinishAllAndError); + QTest::newRow("StopRootWithFinishAllAndError") + << TestData{storage, root7, errorDoneLog, 2, OnDone::Failure}; } { @@ -884,8 +925,12 @@ void tst_Tasking::testTree_data() << TestData{storage, root5, doneErrorLog, 3, OnDone::Success}; const Group root6 = createRoot(WorkflowPolicy::FinishAllAndDone); - QTest::newRow("StopRootAfterDoneWithOptional") + QTest::newRow("StopRootAfterDoneWithFinishAllAndDone") << TestData{storage, root6, doneDoneLog, 3, OnDone::Success}; + + const Group root7 = createRoot(WorkflowPolicy::FinishAllAndError); + QTest::newRow("StopRootAfterDoneWithFinishAllAndError") + << TestData{storage, root7, errorDoneLog, 3, OnDone::Failure}; } { @@ -948,8 +993,12 @@ void tst_Tasking::testTree_data() << TestData{storage, root5, errorLog, 2, OnDone::Failure}; const Group root6 = createRoot(WorkflowPolicy::FinishAllAndDone); - QTest::newRow("StopGroupWithOptional") + QTest::newRow("StopGroupWithFinishAllAndDone") << TestData{storage, root6, doneLog, 2, OnDone::Failure}; + + const Group root7 = createRoot(WorkflowPolicy::FinishAllAndError); + QTest::newRow("StopGroupWithFinishAllAndError") + << TestData{storage, root7, errorLog, 2, OnDone::Failure}; } { @@ -1026,8 +1075,12 @@ void tst_Tasking::testTree_data() << TestData{storage, root5, shortDoneLog, 3, OnDone::Failure}; const Group root6 = createRoot(WorkflowPolicy::FinishAllAndDone); - QTest::newRow("StopGroupAfterDoneWithOptional") + QTest::newRow("StopGroupAfterDoneWithFinishAllAndDone") << TestData{storage, root6, longDoneLog, 3, OnDone::Failure}; + + const Group root7 = createRoot(WorkflowPolicy::FinishAllAndError); + QTest::newRow("StopGroupAfterDoneWithFinishAllAndError") + << TestData{storage, root7, errorLog, 3, OnDone::Failure}; } { @@ -1104,8 +1157,12 @@ void tst_Tasking::testTree_data() << TestData{storage, root5, shortErrorLog, 3, OnDone::Failure}; const Group root6 = createRoot(WorkflowPolicy::FinishAllAndDone); - QTest::newRow("StopGroupAfterErrorWithOptional") + QTest::newRow("StopGroupAfterErrorWithFinishAllAndDone") << TestData{storage, root6, doneLog, 3, OnDone::Failure}; + + const Group root7 = createRoot(WorkflowPolicy::FinishAllAndError); + QTest::newRow("StopGroupAfterErrorWithFinishAllAndError") + << TestData{storage, root7, longErrorLog, 3, OnDone::Failure}; } { @@ -1133,7 +1190,7 @@ void tst_Tasking::testTree_data() QTest::newRow("StopOnError") << TestData{storage, root1, log1, 3, OnDone::Failure}; const Group root2 = createRoot(WorkflowPolicy::ContinueOnError); - const Log log2 { + const Log errorLog { {1, Handler::Setup}, {1, Handler::Done}, {2, Handler::Setup}, @@ -1142,7 +1199,7 @@ void tst_Tasking::testTree_data() {3, Handler::Done}, {0, Handler::GroupError} }; - QTest::newRow("ContinueOnError") << TestData{storage, root2, log2, 3, OnDone::Failure}; + QTest::newRow("ContinueOnError") << TestData{storage, root2, errorLog, 3, OnDone::Failure}; const Group root3 = createRoot(WorkflowPolicy::StopOnDone); const Log log3 { @@ -1153,7 +1210,7 @@ void tst_Tasking::testTree_data() QTest::newRow("StopOnDone") << TestData{storage, root3, log3, 3, OnDone::Success}; const Group root4 = createRoot(WorkflowPolicy::ContinueOnDone); - const Log log4 { + const Log doneLog { {1, Handler::Setup}, {1, Handler::Done}, {2, Handler::Setup}, @@ -1162,7 +1219,7 @@ void tst_Tasking::testTree_data() {3, Handler::Done}, {0, Handler::GroupDone} }; - QTest::newRow("ContinueOnDone") << TestData{storage, root4, log4, 3, OnDone::Success}; + QTest::newRow("ContinueOnDone") << TestData{storage, root4, doneLog, 3, OnDone::Success}; const Group root5 = createRoot(WorkflowPolicy::StopOnFinished); const Log log5 { @@ -1171,6 +1228,12 @@ void tst_Tasking::testTree_data() {0, Handler::GroupDone} }; QTest::newRow("StopOnFinished") << TestData{storage, root5, log5, 3, OnDone::Success}; + + const Group root6 = createRoot(WorkflowPolicy::FinishAllAndDone); + QTest::newRow("FinishAllAndDone") << TestData{storage, root6, doneLog, 3, OnDone::Success}; + + const Group root7 = createRoot(WorkflowPolicy::FinishAllAndError); + QTest::newRow("FinishAllAndError") << TestData{storage, root7, errorLog, 3, OnDone::Failure}; } { @@ -1213,25 +1276,6 @@ void tst_Tasking::testTree_data() QTest::newRow("StopOnFinished4") << TestData{storage, root4, failure, 2, OnDone::Failure}; } - { - const Group root { - Storage(storage), - finishAllAndDone, - createFailingTask(1), - createFailingTask(2), - groupDone(0), - groupError(0) - }; - const Log log { - {1, Handler::Setup}, - {1, Handler::Error}, - {2, Handler::Setup}, - {2, Handler::Error}, - {0, Handler::GroupDone} - }; - QTest::newRow("Optional") << TestData{storage, root, log, 2, OnDone::Success}; - } - { const auto createRoot = [storage, createSuccessTask, groupDone, groupError]( TaskAction taskAction) { From f6e7dbd4166401fa40c5bcab83893d375b42e6a9 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Sun, 28 May 2023 22:47:59 +0200 Subject: [PATCH 067/141] TaskTree: Introduce Timeout task By default, when finished, it returns success. In order to convert it into failing task, enclose it inside a Group with finishAllAndError. Reuse it in tasking tests. Task-number: QTCREATORBUG-28741 Change-Id: Ic81203203e0b139d4f9bfd553279ecb01cd303f4 Reviewed-by: Marcus Tillmanns Reviewed-by: Qt CI Bot --- src/libs/solutions/tasking/tasktree.cpp | 10 ++++ src/libs/solutions/tasking/tasktree.h | 8 +++ tests/auto/solutions/tasking/tst_tasking.cpp | 63 +++++++++----------- 3 files changed, 47 insertions(+), 34 deletions(-) diff --git a/src/libs/solutions/tasking/tasktree.cpp b/src/libs/solutions/tasking/tasktree.cpp index 6f2bb7ad4f5..7fc5c665918 100644 --- a/src/libs/solutions/tasking/tasktree.cpp +++ b/src/libs/solutions/tasking/tasktree.cpp @@ -1848,4 +1848,14 @@ void TaskTreeTaskAdapter::start() task()->start(); } +TimeoutTaskAdapter::TimeoutTaskAdapter() +{ + *task() = std::chrono::milliseconds::zero(); +} + +void TimeoutTaskAdapter::start() +{ + QTimer::singleShot(*task(), this, [this] { emit done(true); }); +} + } // namespace Tasking diff --git a/src/libs/solutions/tasking/tasktree.h b/src/libs/solutions/tasking/tasktree.h index c10cf495c31..78593aa1823 100644 --- a/src/libs/solutions/tasking/tasktree.h +++ b/src/libs/solutions/tasking/tasktree.h @@ -426,6 +426,13 @@ public: void start() final; }; +class TASKING_EXPORT TimeoutTaskAdapter : public TaskAdapter +{ +public: + TimeoutTaskAdapter(); + void start() final; +}; + } // namespace Tasking #define TASKING_DECLARE_TASK(CustomTaskName, TaskAdapterClass)\ @@ -438,3 +445,4 @@ using CustomTaskName = CustomTask>;\ } // namespace Tasking TASKING_DECLARE_TASK(TaskTreeTask, TaskTreeTaskAdapter); +TASKING_DECLARE_TASK(TimeoutTask, TimeoutTaskAdapter); diff --git a/tests/auto/solutions/tasking/tst_tasking.cpp b/tests/auto/solutions/tasking/tst_tasking.cpp index ff760169d85..b498720aa3d 100644 --- a/tests/auto/solutions/tasking/tst_tasking.cpp +++ b/tests/auto/solutions/tasking/tst_tasking.cpp @@ -3,26 +3,15 @@ #include -#include #include +using namespace Tasking; + using namespace std::chrono; using namespace std::chrono_literals; -using namespace Tasking; - -template -class DurationTaskAdapter : public TaskAdapter -{ -public: - DurationTaskAdapter() { *task() = std::chrono::milliseconds{0}; } - void start() final { QTimer::singleShot(*task(), this, [this] { emit done(SuccessOnDone); }); } -}; - -TASKING_DECLARE_TASK(SuccessTask, DurationTaskAdapter); -TASKING_DECLARE_TASK(FailingTask, DurationTaskAdapter); - using TaskObject = milliseconds; +using TestTask = TimeoutTask; namespace PrintableEnums { @@ -86,9 +75,9 @@ void tst_Tasking::validConstructs() { const Group task { parallel, - SuccessTask([](TaskObject &) {}, [](const TaskObject &) {}), - SuccessTask([](TaskObject &) {}, [](const TaskObject &) {}), - SuccessTask([](TaskObject &) {}, [](const TaskObject &) {}) + TestTask([](TaskObject &) {}, [](const TaskObject &) {}), + TestTask([](TaskObject &) {}, [](const TaskObject &) {}), + TestTask([](TaskObject &) {}, [](const TaskObject &) {}) }; const Group group1 { @@ -99,18 +88,18 @@ void tst_Tasking::validConstructs() parallel, Group { parallel, - SuccessTask([](TaskObject &) {}, [](const TaskObject &) {}), + TestTask([](TaskObject &) {}, [](const TaskObject &) {}), Group { parallel, - SuccessTask([](TaskObject &) {}, [](const TaskObject &) {}), + TestTask([](TaskObject &) {}, [](const TaskObject &) {}), Group { parallel, - SuccessTask([](TaskObject &) {}, [](const TaskObject &) {}) + TestTask([](TaskObject &) {}, [](const TaskObject &) {}) } }, Group { parallel, - SuccessTask([](TaskObject &) {}, [](const TaskObject &) {}), + TestTask([](TaskObject &) {}, [](const TaskObject &) {}), onGroupDone([] {}) } }, @@ -127,24 +116,24 @@ void tst_Tasking::validConstructs() const Group task2 { parallel, - SuccessTask(setupHandler), - SuccessTask(setupHandler, doneHandler), - SuccessTask(setupHandler, doneHandler, errorHandler), + TestTask(setupHandler), + TestTask(setupHandler, doneHandler), + TestTask(setupHandler, doneHandler, errorHandler), // need to explicitly pass empty handler for done - SuccessTask(setupHandler, {}, errorHandler) + TestTask(setupHandler, {}, errorHandler) }; // Fluent interface const Group fluent { parallel, - SuccessTask().onSetup(setupHandler), - SuccessTask().onSetup(setupHandler).onDone(doneHandler), - SuccessTask().onSetup(setupHandler).onDone(doneHandler).onError(errorHandler), + TestTask().onSetup(setupHandler), + TestTask().onSetup(setupHandler).onDone(doneHandler), + TestTask().onSetup(setupHandler).onDone(doneHandler).onError(errorHandler), // possible to skip the empty done - SuccessTask().onSetup(setupHandler).onError(errorHandler), + TestTask().onSetup(setupHandler).onError(errorHandler), // possible to set handlers in a different order - SuccessTask().onError(errorHandler).onDone(doneHandler).onSetup(setupHandler), + TestTask().onError(errorHandler).onDone(doneHandler).onSetup(setupHandler), }; @@ -259,8 +248,14 @@ void tst_Tasking::testTree_data() const auto createTask = [storage, setupTask, setupDone, setupError]( int taskId, bool successTask, milliseconds timeout = 0ms) -> TaskItem { if (successTask) - return SuccessTask(setupTask(taskId, timeout), setupDone(taskId), setupError(taskId)); - return FailingTask(setupTask(taskId, timeout), setupDone(taskId), setupError(taskId)); + return TestTask(setupTask(taskId, timeout), setupDone(taskId), setupError(taskId)); + const Group root { + finishAllAndError, + TestTask(setupTask(taskId, timeout)), + onGroupDone([storage, taskId] { storage->m_log.append({taskId, Handler::Done}); }), + onGroupError([storage, taskId] { storage->m_log.append({taskId, Handler::Error}); }) + }; + return root; }; const auto createSuccessTask = [createTask](int taskId, milliseconds timeout = 0ms) { @@ -273,7 +268,7 @@ void tst_Tasking::testTree_data() const auto createDynamicTask = [storage, setupDynamicTask, setupDone, setupError]( int taskId, TaskAction action) { - return SuccessTask(setupDynamicTask(taskId, action), setupDone(taskId), setupError(taskId)); + return TestTask(setupDynamicTask(taskId, action), setupDone(taskId), setupError(taskId)); }; const auto groupSetup = [storage](int taskId) { @@ -2142,7 +2137,7 @@ void tst_Tasking::storageDestructor() }; const Group root { Storage(storage), - SuccessTask(setupSleepingTask) + TestTask(setupSleepingTask) }; TaskTree taskTree(root); From 1599106a224fc56c472078963fc1095b110c67a6 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Wed, 31 May 2023 18:29:11 +0200 Subject: [PATCH 068/141] TaskTree: Make the TimeoutTask reliable Ensure the timeout tasks preserve the right order of their done signals. Change-Id: I62508d0710eb2324d7c347a9907a899c97d3975d Reviewed-by: Marcus Tillmanns --- src/libs/solutions/tasking/tasktree.cpp | 85 +++++++++++++++++++- src/libs/solutions/tasking/tasktree.h | 4 + tests/auto/solutions/tasking/tst_tasking.cpp | 4 +- 3 files changed, 90 insertions(+), 3 deletions(-) diff --git a/src/libs/solutions/tasking/tasktree.cpp b/src/libs/solutions/tasking/tasktree.cpp index 7fc5c665918..f5d67625a8e 100644 --- a/src/libs/solutions/tasking/tasktree.cpp +++ b/src/libs/solutions/tasking/tasktree.cpp @@ -9,6 +9,8 @@ #include #include +using namespace std::chrono; + namespace Tasking { // That's cut down qtcassert.{c,h} to avoid the dependency. @@ -1848,14 +1850,95 @@ void TaskTreeTaskAdapter::start() task()->start(); } +using TimeoutCallback = std::function; + +struct TimerData +{ + system_clock::time_point m_deadline; + QPointer m_context; + TimeoutCallback m_callback; +}; + +QMutex s_mutex; +std::atomic_int s_timerId = 0; +QHash s_timerIdToTimerData = {}; +QMultiMap s_deadlineToTimerId = {}; + +static QList prepareForActivation(int timerId) +{ + QMutexLocker lock(&s_mutex); + const auto it = s_timerIdToTimerData.constFind(timerId); + if (it == s_timerIdToTimerData.cend()) + return {}; // the timer was already activated + + const system_clock::time_point deadline = it->m_deadline; + QList toActivate; + auto itMap = s_deadlineToTimerId.cbegin(); + while (itMap != s_deadlineToTimerId.cend()) { + if (itMap.key() > deadline) + break; + + const auto it = s_timerIdToTimerData.constFind(itMap.value()); + if (it != s_timerIdToTimerData.cend()) { + toActivate.append(it.value()); + s_timerIdToTimerData.erase(it); + } + itMap = s_deadlineToTimerId.erase(itMap); + } + return toActivate; +} + +static void removeTimerId(int timerId) +{ + QMutexLocker lock(&s_mutex); + const auto it = s_timerIdToTimerData.constFind(timerId); + QTC_ASSERT(it != s_timerIdToTimerData.cend(), + qWarning("Removing active timerId failed."); return); + + const system_clock::time_point deadline = it->m_deadline; + s_timerIdToTimerData.erase(it); + + const int removedCount = s_deadlineToTimerId.remove(deadline, timerId); + QTC_ASSERT(removedCount == 1, qWarning("Removing active timerId failed."); return); +} + +static void handleTimeout(int timerId) +{ + const QList toActivate = prepareForActivation(timerId); + for (const TimerData &timerData : toActivate) { + if (timerData.m_context) + QMetaObject::invokeMethod(timerData.m_context.get(), timerData.m_callback); + } +} + +static int scheduleTimeout(milliseconds timeout, QObject *context, const TimeoutCallback &callback) +{ + const int timerId = s_timerId.fetch_add(1) + 1; + const system_clock::time_point deadline = system_clock::now() + timeout; + QTimer::singleShot(timeout, context, [timerId] { handleTimeout(timerId); }); + QMutexLocker lock(&s_mutex); + s_timerIdToTimerData.emplace(timerId, TimerData{deadline, context, callback}); + s_deadlineToTimerId.insert(deadline, timerId); + return timerId; +} + TimeoutTaskAdapter::TimeoutTaskAdapter() { *task() = std::chrono::milliseconds::zero(); } +TimeoutTaskAdapter::~TimeoutTaskAdapter() +{ + if (m_timerId) + removeTimerId(*m_timerId); +} + void TimeoutTaskAdapter::start() { - QTimer::singleShot(*task(), this, [this] { emit done(true); }); + if (*task() == milliseconds::zero()) + QTimer::singleShot(0, this, [this] { emit done(true); }); + else + m_timerId = scheduleTimeout(*task(), this, [this] { m_timerId = {}; emit done(true); }); } } // namespace Tasking diff --git a/src/libs/solutions/tasking/tasktree.h b/src/libs/solutions/tasking/tasktree.h index 78593aa1823..6962ed5cabe 100644 --- a/src/libs/solutions/tasking/tasktree.h +++ b/src/libs/solutions/tasking/tasktree.h @@ -430,7 +430,11 @@ class TASKING_EXPORT TimeoutTaskAdapter : public TaskAdapter m_timerId; }; } // namespace Tasking diff --git a/tests/auto/solutions/tasking/tst_tasking.cpp b/tests/auto/solutions/tasking/tst_tasking.cpp index b498720aa3d..cbe0048eeb4 100644 --- a/tests/auto/solutions/tasking/tst_tasking.cpp +++ b/tests/auto/solutions/tasking/tst_tasking.cpp @@ -781,7 +781,7 @@ void tst_Tasking::testTree_data() parallel, workflowPolicy(policy), createFailingTask(1, 1ms), - createSuccessTask(2, 2ms), + createSuccessTask(2, 1ms), groupDone(0), groupError(0) }; @@ -853,7 +853,7 @@ void tst_Tasking::testTree_data() workflowPolicy(policy), createSuccessTask(1), createFailingTask(2, 1ms), - createSuccessTask(3, 2ms), + createSuccessTask(3, 1ms), groupDone(0), groupError(0) }; From 619735d99dd30690bb183c5334b6a836813cf25c Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Mon, 29 May 2023 00:13:12 +0200 Subject: [PATCH 069/141] TaskTree: Introduce withTimeout() Make it available for Group or CustomTask items. Note, that when withTimeout() is used, the total number of tasks grows by one. Change-Id: Idc71737ba66b92bdc4bf17599c793b1127d22f5e Reviewed-by: Marcus Tillmanns Reviewed-by: Qt CI Bot --- src/libs/solutions/tasking/tasktree.cpp | 17 +++ src/libs/solutions/tasking/tasktree.h | 12 ++ tests/auto/solutions/tasking/tst_tasking.cpp | 115 ++++++++++++++++++- 3 files changed, 143 insertions(+), 1 deletion(-) diff --git a/src/libs/solutions/tasking/tasktree.cpp b/src/libs/solutions/tasking/tasktree.cpp index f5d67625a8e..8c6f5879144 100644 --- a/src/libs/solutions/tasking/tasktree.cpp +++ b/src/libs/solutions/tasking/tasktree.cpp @@ -567,6 +567,23 @@ void TaskItem::setTaskErrorHandler(const TaskEndHandler &handler) m_taskHandler.m_errorHandler = handler; } +TaskItem TaskItem::withTimeout(const TaskItem &item, milliseconds timeout, + const GroupEndHandler &handler) +{ + const TimeoutTask::EndHandler taskHandler = handler + ? [handler](const milliseconds &) { handler(); } : TimeoutTask::EndHandler(); + return Group { + parallel, + stopOnFinished, + Group { + finishAllAndError, + TimeoutTask([timeout](milliseconds &timeoutData) { timeoutData = timeout; }, + taskHandler) + }, + item + }; +} + class TaskTreePrivate; class TaskNode; diff --git a/src/libs/solutions/tasking/tasktree.h b/src/libs/solutions/tasking/tasktree.h index 6962ed5cabe..1d596316cae 100644 --- a/src/libs/solutions/tasking/tasktree.h +++ b/src/libs/solutions/tasking/tasktree.h @@ -187,6 +187,8 @@ protected: static TaskItem groupHandler(const GroupHandler &handler) { return TaskItem({handler}); } static TaskItem parallelLimit(int limit) { return TaskItem({{}, limit}); } static TaskItem workflowPolicy(WorkflowPolicy policy) { return TaskItem({{}, {}, policy}); } + static TaskItem withTimeout(const TaskItem &item, std::chrono::milliseconds timeout, + const GroupEndHandler &handler = {}); private: Type m_type = Type::Group; @@ -216,6 +218,11 @@ public: using TaskItem::parallelLimit; // Default: 1 (sequential). 0 means unlimited (parallel). using TaskItem::workflowPolicy; // Default: WorkflowPolicy::StopOnError. + TaskItem withTimeout(std::chrono::milliseconds timeout, + const GroupEndHandler &handler = {}) const { + return TaskItem::withTimeout(*this, timeout, handler); + } + private: template static GroupSetupHandler wrapGroupSetup(SetupHandler &&handler) @@ -329,6 +336,11 @@ public: return *this; } + TaskItem withTimeout(std::chrono::milliseconds timeout, + const GroupEndHandler &handler = {}) const { + return TaskItem::withTimeout(*this, timeout, handler); + } + private: template static TaskItem::TaskSetupHandler wrapSetup(SetupFunction &&function) { diff --git a/tests/auto/solutions/tasking/tst_tasking.cpp b/tests/auto/solutions/tasking/tst_tasking.cpp index cbe0048eeb4..e5791f0d6f1 100644 --- a/tests/auto/solutions/tasking/tst_tasking.cpp +++ b/tests/auto/solutions/tasking/tst_tasking.cpp @@ -25,7 +25,8 @@ enum class Handler { GroupDone, GroupError, Sync, - BarrierAdvance + BarrierAdvance, + Timeout }; Q_ENUM_NS(Handler); @@ -245,6 +246,12 @@ void tst_Tasking::testTree_data() }; }; + const auto setupTimeout = [storage](int taskId) { + return [storage, taskId] { + storage->m_log.append({taskId, Handler::Timeout}); + }; + }; + const auto createTask = [storage, setupTask, setupDone, setupError]( int taskId, bool successTask, milliseconds timeout = 0ms) -> TaskItem { if (successTask) @@ -2083,6 +2090,112 @@ void tst_Tasking::testTree_data() QTest::newRow("MultiBarrierParallelMultiWaitFor") << TestData{storage, root4, log4, 6, OnDone::Success}; } + + { + // Test CustomTask::withTimeout() combinations: + // 1. When the timeout has triggered or not. + // 2. With and without timeout handler. + const Group root1 { + Storage(storage), + TestTask(setupTask(1, 1000ms), setupDone(1), setupError(1)) + .withTimeout(1ms) + }; + const Log log1 { + {1, Handler::Setup}, + {1, Handler::Error} + }; + QTest::newRow("TaskErrorWithTimeout") << TestData{storage, root1, log1, 2, + OnDone::Failure}; + + const Group root2 { + Storage(storage), + TestTask(setupTask(1, 1000ms), setupDone(1), setupError(1)) + .withTimeout(1ms, setupTimeout(1)) + }; + const Log log2 { + {1, Handler::Setup}, + {1, Handler::Timeout}, + {1, Handler::Error} + }; + QTest::newRow("TaskErrorWithTimeoutHandler") << TestData{storage, root2, log2, 2, + OnDone::Failure}; + + const Group root3 { + Storage(storage), + TestTask(setupTask(1, 1ms), setupDone(1), setupError(1)) + .withTimeout(1000ms) + }; + const Log doneLog { + {1, Handler::Setup}, + {1, Handler::Done} + }; + QTest::newRow("TaskDoneWithTimeout") << TestData{storage, root3, doneLog, 2, + OnDone::Success}; + + const Group root4 { + Storage(storage), + TestTask(setupTask(1, 1ms), setupDone(1), setupError(1)) + .withTimeout(1000ms, setupTimeout(1)) + }; + QTest::newRow("TaskDoneWithTimeoutHandler") << TestData{storage, root4, doneLog, 2, + OnDone::Success}; + } + + { + // Test Group::withTimeout() combinations: + // 1. When the timeout has triggered or not. + // 2. With and without timeout handler. + const Group root1 { + Storage(storage), + Group { + createSuccessTask(1, 1000ms) + }.withTimeout(1ms) + }; + const Log log1 { + {1, Handler::Setup}, + {1, Handler::Error} + }; + QTest::newRow("GroupErrorWithTimeout") << TestData{storage, root1, log1, 2, + OnDone::Failure}; + + // Test Group::withTimeout(), passing custom handler + const Group root2 { + Storage(storage), + Group { + createSuccessTask(1, 1000ms) + }.withTimeout(1ms, setupTimeout(1)) + }; + const Log log2 { + {1, Handler::Setup}, + {1, Handler::Timeout}, + {1, Handler::Error} + }; + QTest::newRow("GroupErrorWithTimeoutHandler") << TestData{storage, root2, log2, 2, + OnDone::Failure}; + + const Group root3 { + Storage(storage), + Group { + createSuccessTask(1, 1ms) + }.withTimeout(1000ms) + }; + const Log doneLog { + {1, Handler::Setup}, + {1, Handler::Done} + }; + QTest::newRow("GroupDoneWithTimeout") << TestData{storage, root3, doneLog, 2, + OnDone::Success}; + + // Test Group::withTimeout(), passing custom handler + const Group root4 { + Storage(storage), + Group { + createSuccessTask(1, 1ms) + }.withTimeout(1000ms, setupTimeout(1)) + }; + QTest::newRow("GroupDoneWithTimeoutHandler") << TestData{storage, root4, doneLog, 2, + OnDone::Success}; + } } void tst_Tasking::testTree() From b2dadeb30c6cfbbe53426281ed5974d2788eeaee Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Mon, 29 May 2023 15:47:11 +0200 Subject: [PATCH 070/141] TaskTree: Fix the empty Group's return result Get back to the originally intended behavior for StopOnDone and ContinueOnDone workflow policies. By default, these policies report an error until at least one child task finished with success. Since the group is empty, no child finished with success, so the group should report an error. Change also the return result for the StopOnFinished policy when placed in an empty group. The policy is meant to report the finished child's result. Since no task finished, report an error in this case. Fix tests accordingly. Amends c9638ff64291351b846d28c28f077bbe70f6c1f0 Change-Id: Idc449e8c68a658755bf566df56844126167f1751 Reviewed-by: Reviewed-by: Marcus Tillmanns Reviewed-by: Qt CI Bot --- src/libs/solutions/tasking/tasktree.cpp | 36 ++++++++++++++------ tests/auto/solutions/tasking/tst_tasking.cpp | 12 +++---- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/src/libs/solutions/tasking/tasktree.cpp b/src/libs/solutions/tasking/tasktree.cpp index 8c6f5879144..60caa217ef7 100644 --- a/src/libs/solutions/tasking/tasktree.cpp +++ b/src/libs/solutions/tasking/tasktree.cpp @@ -679,8 +679,8 @@ public: const ConstData &m_constData; const QList m_storageIdList; - int m_doneCount = 0; bool m_successBit = true; + int m_doneCount = 0; Guard m_startGuard; }; @@ -875,14 +875,28 @@ void TaskContainer::RuntimeData::callStorageDoneHandlers() } } +static bool initialSuccessBit(WorkflowPolicy workflowPolicy) +{ + switch (workflowPolicy) { + case WorkflowPolicy::StopOnError: + case WorkflowPolicy::ContinueOnError: + case WorkflowPolicy::FinishAllAndDone: + return true; + case WorkflowPolicy::StopOnDone: + case WorkflowPolicy::ContinueOnDone: + case WorkflowPolicy::StopOnFinished: + case WorkflowPolicy::FinishAllAndError: + return false; + } + QTC_CHECK(false); + return false; +} + TaskContainer::RuntimeData::RuntimeData(const ConstData &constData) : m_constData(constData) , m_storageIdList(createStorages(constData)) -{ - m_successBit = m_constData.m_workflowPolicy != WorkflowPolicy::StopOnDone - && m_constData.m_workflowPolicy != WorkflowPolicy::ContinueOnDone - && m_constData.m_workflowPolicy != WorkflowPolicy::FinishAllAndError; -} + , m_successBit(initialSuccessBit(m_constData.m_workflowPolicy)) +{} TaskContainer::RuntimeData::~RuntimeData() { @@ -896,10 +910,10 @@ TaskContainer::RuntimeData::~RuntimeData() bool TaskContainer::RuntimeData::updateSuccessBit(bool success) { if (m_constData.m_workflowPolicy == WorkflowPolicy::FinishAllAndDone - || m_constData.m_workflowPolicy == WorkflowPolicy::FinishAllAndError) - return m_successBit; - if (m_constData.m_workflowPolicy == WorkflowPolicy::StopOnFinished) { - m_successBit = success; + || m_constData.m_workflowPolicy == WorkflowPolicy::FinishAllAndError + || m_constData.m_workflowPolicy == WorkflowPolicy::StopOnFinished) { + if (m_constData.m_workflowPolicy == WorkflowPolicy::StopOnFinished) + m_successBit = success; return m_successBit; } @@ -929,7 +943,7 @@ TaskAction TaskContainer::start() } if (startAction == TaskAction::Continue) { if (m_constData.m_children.isEmpty()) - startAction = TaskAction::StopWithDone; + startAction = toTaskAction(m_runtimeData->m_successBit); } return continueStart(startAction, 0); } diff --git a/tests/auto/solutions/tasking/tst_tasking.cpp b/tests/auto/solutions/tasking/tst_tasking.cpp index e5791f0d6f1..8c2173585b1 100644 --- a/tests/auto/solutions/tasking/tst_tasking.cpp +++ b/tests/auto/solutions/tasking/tst_tasking.cpp @@ -651,16 +651,16 @@ void tst_Tasking::testTree_data() OnDone::Success}; const Group root3 = createRoot(WorkflowPolicy::StopOnDone); - QTest::newRow("EmptyStopOnDone") << TestData{storage, root3, doneLog, 0, - OnDone::Success}; + QTest::newRow("EmptyStopOnDone") << TestData{storage, root3, errorLog, 0, + OnDone::Failure}; const Group root4 = createRoot(WorkflowPolicy::ContinueOnDone); - QTest::newRow("EmptyContinueOnDone") << TestData{storage, root4, doneLog, 0, - OnDone::Success}; + QTest::newRow("EmptyContinueOnDone") << TestData{storage, root4, errorLog, 0, + OnDone::Failure}; const Group root5 = createRoot(WorkflowPolicy::StopOnFinished); - QTest::newRow("EmptyStopOnFinished") << TestData{storage, root5, doneLog, 0, - OnDone::Success}; + QTest::newRow("EmptyStopOnFinished") << TestData{storage, root5, errorLog, 0, + OnDone::Failure}; const Group root6 = createRoot(WorkflowPolicy::FinishAllAndDone); QTest::newRow("EmptyFinishAllAndDone") << TestData{storage, root6, doneLog, 0, From 6f8e5c409f0a1b6fc8a655109188b29957f2bc92 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Mon, 29 May 2023 19:05:31 +0200 Subject: [PATCH 071/141] TaskTree: De-utils-ize manual test, rename it to demo Change-Id: I80a2522f7ba12ee9b63c19d66e514d7047951733 Reviewed-by: Marcus Tillmanns --- tests/manual/CMakeLists.txt | 2 +- tests/manual/manual.qbs | 2 +- tests/manual/tasking/CMakeLists.txt | 1 + tests/manual/tasking/demo/CMakeLists.txt | 11 + tests/manual/tasking/demo/demo.qbs | 18 ++ tests/manual/tasking/demo/demo.qrc | 6 + .../tasking/demo/icons/progressindicator.png | Bin 0 -> 336 bytes .../demo/icons/progressindicator@2x.png | Bin 0 -> 302 bytes .../{tasktree => tasking/demo}/main.cpp | 211 ++++++++++-------- .../manual/tasking/demo/progressindicator.cpp | 149 +++++++++++++ tests/manual/tasking/demo/progressindicator.h | 21 ++ .../{tasktree => tasking/demo}/taskwidget.cpp | 91 ++++---- .../{tasktree => tasking/demo}/taskwidget.h | 20 +- tests/manual/tasktree/CMakeLists.txt | 6 - tests/manual/tasktree/tasktree.qbs | 14 -- 15 files changed, 368 insertions(+), 184 deletions(-) create mode 100644 tests/manual/tasking/CMakeLists.txt create mode 100644 tests/manual/tasking/demo/CMakeLists.txt create mode 100644 tests/manual/tasking/demo/demo.qbs create mode 100644 tests/manual/tasking/demo/demo.qrc create mode 100644 tests/manual/tasking/demo/icons/progressindicator.png create mode 100644 tests/manual/tasking/demo/icons/progressindicator@2x.png rename tests/manual/{tasktree => tasking/demo}/main.cpp (55%) create mode 100644 tests/manual/tasking/demo/progressindicator.cpp create mode 100644 tests/manual/tasking/demo/progressindicator.h rename tests/manual/{tasktree => tasking/demo}/taskwidget.cpp (59%) rename tests/manual/{tasktree => tasking/demo}/taskwidget.h (75%) delete mode 100644 tests/manual/tasktree/CMakeLists.txt delete mode 100644 tests/manual/tasktree/tasktree.qbs diff --git a/tests/manual/CMakeLists.txt b/tests/manual/CMakeLists.txt index fb0b611f4f7..fde3cb962ea 100644 --- a/tests/manual/CMakeLists.txt +++ b/tests/manual/CMakeLists.txt @@ -17,5 +17,5 @@ add_subdirectory(proparser) # add_subdirectory(search) add_subdirectory(shootout) add_subdirectory(subdirfileiterator) -add_subdirectory(tasktree) +add_subdirectory(tasking) add_subdirectory(widgets) diff --git a/tests/manual/manual.qbs b/tests/manual/manual.qbs index 8e157a9216b..66c480c7a62 100644 --- a/tests/manual/manual.qbs +++ b/tests/manual/manual.qbs @@ -14,7 +14,7 @@ Project { "proparser/testreader.qbs", "shootout/shootout.qbs", "subdirfileiterator/subdirfileiterator.qbs", - "tasktree/tasktree.qbs", + "tasking/demo/demo.qbs", "widgets/widgets.qbs", ] } diff --git a/tests/manual/tasking/CMakeLists.txt b/tests/manual/tasking/CMakeLists.txt new file mode 100644 index 00000000000..a16f5f12201 --- /dev/null +++ b/tests/manual/tasking/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(demo) diff --git a/tests/manual/tasking/demo/CMakeLists.txt b/tests/manual/tasking/demo/CMakeLists.txt new file mode 100644 index 00000000000..bdd790cd898 --- /dev/null +++ b/tests/manual/tasking/demo/CMakeLists.txt @@ -0,0 +1,11 @@ +add_qtc_test(tst_tasking_demo + MANUALTEST + DEPENDS Tasking Qt::Widgets + SOURCES + demo.qrc + main.cpp + progressindicator.h + progressindicator.cpp + taskwidget.h + taskwidget.cpp +) diff --git a/tests/manual/tasking/demo/demo.qbs b/tests/manual/tasking/demo/demo.qbs new file mode 100644 index 00000000000..2a54143c415 --- /dev/null +++ b/tests/manual/tasking/demo/demo.qbs @@ -0,0 +1,18 @@ +import qbs.FileInfo + +QtcManualtest { + name: "Tasking demo" + type: ["application"] + + Depends { name: "Qt"; submodules: ["widgets"] } + Depends { name: "Tasking" } + + files: [ + "demo.qrc", + "main.cpp", + "progressindicator.h", + "progressindicator.cpp", + "taskwidget.h", + "taskwidget.cpp", + ] +} diff --git a/tests/manual/tasking/demo/demo.qrc b/tests/manual/tasking/demo/demo.qrc new file mode 100644 index 00000000000..5ea09fe25ec --- /dev/null +++ b/tests/manual/tasking/demo/demo.qrc @@ -0,0 +1,6 @@ + + + icons/progressindicator.png + icons/progressindicator@2x.png + + diff --git a/tests/manual/tasking/demo/icons/progressindicator.png b/tests/manual/tasking/demo/icons/progressindicator.png new file mode 100644 index 0000000000000000000000000000000000000000..c968ae8ac9f4b1e9260e02d163a13f904ac1e24a GIT binary patch literal 336 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7I14-?iy0XBj({-ZRBb+K z1_nkZPZ!4!i{7P|Y`vNt1&)23|1-dm*HK&7rg4$jwMl04G+G4$Hhhwr=OCc3IPajB zfQw08i%QbRciN9%t7*zeM5KNHf9A~@gWGwN{kKM0=qKj(DVQjS%ZXh)EP1Q=!QUra zH3HJ^AL5KMeh_+P@_&v!i~6f`9&ZWqY`I_19=Ps^m|j8WT!H+@9POSt%eHD2i2P*M ze_-=@hq>#XVBRZ5>;Gk+zH#Qr=J*xq5A@1DHaIqX-_Yn@Gu5F~cz48c?s=m1?=;-L zuakJ}xJE_qQeo5lg4TWoyPz|54WdW=Oco!II6UR6)cl!pE)xyaE_h5AzO!T=k8we0 oO3=53f_leKKEJtM^dH;y+Xj9g zwZ;er@9XEUw6NsJ)@ZN@@+-~lxDb7R#m~OUTHjdC-S(Td(eB7^p_1FL4lbFT`c?AK zJO{3i{0Bsizg1IQygl#xOp}Ax^Nz2uIw*1fSbtdX!pB}_+f8-W>K~}Ovq1Ymyu?a% zQ}c%HMd!P%@)^oASpy5j3$D%k%>LBw!5@ovJa -#include -#include -#include +#include #include -#include +#include +#include #include #include #include #include -using namespace Utils; +using namespace Tasking; -// TODO: make tasks cancellable -static void sleepInThread(QPromise &promise, int seconds, bool reportSuccess) +using namespace std::chrono; + +static QWidget *hr() { - QThread::sleep(seconds); - if (!reportSuccess) - promise.future().cancel(); + auto frame = new QFrame; + frame->setFrameShape(QFrame::HLine); + frame->setFrameShadow(QFrame::Sunken); + return frame; +} + +QWidget *taskGroup(QWidget *groupWidget, const QList &widgets) +{ + QWidget *widget = new QWidget; + QBoxLayout *layout = new QHBoxLayout(widget); + layout->setContentsMargins(0, 0, 0, 0); + layout->addWidget(groupWidget); + QGroupBox *groupBox = new QGroupBox; + QBoxLayout *subLayout = new QVBoxLayout(groupBox); + for (int i = 0; i < widgets.size(); ++i) { + if (i > 0) + subLayout->addWidget(hr()); + subLayout->addWidget(widgets.at(i)); + } + layout->addWidget(groupBox); + return widget; } int main(int argc, char *argv[]) { QApplication app(argc, argv); - setCreatorTheme(new Theme("default", &app)); - QWidget mainWidget; mainWidget.setWindowTitle("Task Tree Demo"); // Non-task GUI - QToolButton *startButton = new QToolButton(); + QToolButton *startButton = new QToolButton; startButton->setText("Start"); - QToolButton *stopButton = new QToolButton(); + QToolButton *stopButton = new QToolButton; stopButton->setText("Stop"); - QToolButton *resetButton = new QToolButton(); + QToolButton *resetButton = new QToolButton; resetButton->setText("Reset"); - QProgressBar *progressBar = new QProgressBar(); - QCheckBox *synchronizerCheckBox = new QCheckBox("Use Future Synchronizer"); - synchronizerCheckBox->setChecked(true); - QScrollArea *scrollArea = new QScrollArea(); + QProgressBar *progressBar = new QProgressBar; + QScrollArea *scrollArea = new QScrollArea; scrollArea->setWidgetResizable(true); - QWidget *scrollAreaWidget = new QWidget(); + QWidget *scrollAreaWidget = new QWidget; // Task GUI @@ -100,120 +113,124 @@ int main(int argc, char *argv[]) task_4_4->setBusyTime(6); task_4_4->setBusyTime(3); - groupTask_1->setWorkflowPolicy(Tasking::WorkflowPolicy::ContinueOnDone); - groupTask_4->setWorkflowPolicy(Tasking::WorkflowPolicy::FinishAllAndDone); + groupTask_1->setWorkflowPolicy(WorkflowPolicy::ContinueOnDone); + groupTask_4->setWorkflowPolicy(WorkflowPolicy::FinishAllAndDone); groupTask_4_3->setExecuteMode(ExecuteMode::Parallel); - groupTask_4_3->setWorkflowPolicy(Tasking::WorkflowPolicy::StopOnError); + groupTask_4_3->setWorkflowPolicy(WorkflowPolicy::StopOnError); // Task layout { - using namespace Layouting; - - Column { - TaskGroup { rootGroup, { - TaskGroup { groupTask_1, { - task_1_1, hr, - task_1_2, hr, - task_1_3, - }}, hr, - task_2, hr, - task_3, hr, - TaskGroup { groupTask_4, { - task_4_1, hr, - task_4_2, hr, - TaskGroup { groupTask_4_3, { - task_4_3_1, hr, - task_4_3_2, hr, - task_4_3_3, hr, - task_4_3_4, - }}, hr, - task_4_4, hr, - task_4_5, - }}, hr, - task_5 - }}, st - }.attachTo(scrollAreaWidget); - + QWidget *taskTree = taskGroup(rootGroup, { + taskGroup(groupTask_1, { + task_1_1, + task_1_2, + task_1_3 + }), + task_2, + task_3, + taskGroup(groupTask_4, { + task_4_1, + task_4_2, + taskGroup(groupTask_4_3, { + task_4_3_1, + task_4_3_2, + task_4_3_3, + task_4_3_4, + }), + task_4_4, + task_4_5 + }), + task_5 + }); + QBoxLayout *scrollLayout = new QVBoxLayout(scrollAreaWidget); + scrollLayout->addWidget(taskTree); + scrollLayout->addStretch(); scrollArea->setWidget(scrollAreaWidget); - Column { - Row { startButton, stopButton, resetButton, synchronizerCheckBox, progressBar }, - hr, - scrollArea - }.attachTo(&mainWidget); + QBoxLayout *mainLayout = new QVBoxLayout(&mainWidget); + QBoxLayout *subLayout = new QHBoxLayout; + subLayout->addWidget(startButton); + subLayout->addWidget(stopButton); + subLayout->addWidget(resetButton); + subLayout->addWidget(progressBar); + mainLayout->addLayout(subLayout); + mainLayout->addWidget(hr()); + mainLayout->addWidget(scrollArea); } - // Task tree creator (takes configuation from GUI) - - using namespace Tasking; + // Task tree (takes initial configuation from GUI) std::unique_ptr taskTree; - FutureSynchronizer synchronizer; + + const auto createTask = [](TaskWidget *widget) -> TaskItem { + const auto setupTask = [](TaskWidget *widget) { + return [widget](milliseconds &taskObject) { + taskObject = milliseconds{widget->busyTime() * 1000}; + widget->setState(State::Running); + }; + }; + if (widget->isSuccess()) { + return TimeoutTask(setupTask(widget), + [widget](const milliseconds &) { widget->setState(State::Done); }, + [widget](const milliseconds &) { widget->setState(State::Error); }); + } + const Group root { + finishAllAndError, + TimeoutTask(setupTask(widget)), + onGroupDone([widget] { widget->setState(State::Done); }), + onGroupError([widget] { widget->setState(State::Error); }) + }; + return root; + }; auto treeRoot = [&] { - auto taskItem = [sync = &synchronizer, synchronizerCheckBox](TaskWidget *widget) { - const auto setupHandler = [=](Async &task) { - task.setConcurrentCallData(sleepInThread, widget->busyTime(), widget->isSuccess()); - if (synchronizerCheckBox->isChecked()) - task.setFutureSynchronizer(sync); - widget->setState(State::Running); - }; - const auto doneHandler = [widget](const Async &) { - widget->setState(State::Done); - }; - const auto errorHandler = [widget](const Async &) { - widget->setState(State::Error); - }; - return AsyncTask(setupHandler, doneHandler, errorHandler); - }; - const Group root { rootGroup->executeMode(), - workflowPolicy(rootGroup->workflowPolicy()), + rootGroup->workflowPolicy(), onGroupSetup([rootGroup] { rootGroup->setState(State::Running); }), onGroupDone([rootGroup] { rootGroup->setState(State::Done); }), onGroupError([rootGroup] { rootGroup->setState(State::Error); }), Group { groupTask_1->executeMode(), - workflowPolicy(groupTask_1->workflowPolicy()), + groupTask_1->workflowPolicy(), onGroupSetup([groupTask_1] { groupTask_1->setState(State::Running); }), onGroupDone([groupTask_1] { groupTask_1->setState(State::Done); }), onGroupError([groupTask_1] { groupTask_1->setState(State::Error); }), - taskItem(task_1_1), - taskItem(task_1_2), - taskItem(task_1_3) + createTask(task_1_1), + createTask(task_1_2), + createTask(task_1_3) }, - taskItem(task_2), - taskItem(task_3), + createTask(task_2), + createTask(task_3), Group { groupTask_4->executeMode(), - workflowPolicy(groupTask_4->workflowPolicy()), + groupTask_4->workflowPolicy(), onGroupSetup([groupTask_4] { groupTask_4->setState(State::Running); }), onGroupDone([groupTask_4] { groupTask_4->setState(State::Done); }), onGroupError([groupTask_4] { groupTask_4->setState(State::Error); }), - taskItem(task_4_1), - taskItem(task_4_2), + createTask(task_4_1), + createTask(task_4_2), Group { groupTask_4_3->executeMode(), - workflowPolicy(groupTask_4_3->workflowPolicy()), + groupTask_4_3->workflowPolicy(), onGroupSetup([groupTask_4_3] { groupTask_4_3->setState(State::Running); }), onGroupDone([groupTask_4_3] { groupTask_4_3->setState(State::Done); }), onGroupError([groupTask_4_3] { groupTask_4_3->setState(State::Error); }), - taskItem(task_4_3_1), - taskItem(task_4_3_2), - taskItem(task_4_3_3), - taskItem(task_4_3_4) + createTask(task_4_3_1), + createTask(task_4_3_2), + createTask(task_4_3_3), + createTask(task_4_3_4) }, - taskItem(task_4_4), - taskItem(task_4_5) + createTask(task_4_4), + createTask(task_4_5) }, - taskItem(task_5) + createTask(task_5) }; return root; }; @@ -258,7 +275,7 @@ int main(int argc, char *argv[]) // Hack in order to show initial size minimal, but without scrollbars. // Apparently setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContentsOnFirstShow) doesn't work. - const int margin = 2; + const int margin = 4; scrollArea->setMinimumSize(scrollAreaWidget->minimumSizeHint().grownBy({0, 0, margin, margin})); QTimer::singleShot(0, scrollArea, [&] { scrollArea->setMinimumSize({0, 0}); }); diff --git a/tests/manual/tasking/demo/progressindicator.cpp b/tests/manual/tasking/demo/progressindicator.cpp new file mode 100644 index 00000000000..38f577f4ed7 --- /dev/null +++ b/tests/manual/tasking/demo/progressindicator.cpp @@ -0,0 +1,149 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "progressindicator.h" + +#include +#include +#include +#include + +class OverlayWidget : public QWidget +{ +public: + using PaintFunction = std::function; + + explicit OverlayWidget(QWidget *parent = nullptr) + { + setAttribute(Qt::WA_TransparentForMouseEvents); + if (parent) + attachToWidget(parent); + } + + void attachToWidget(QWidget *parent) + { + if (parentWidget()) + parentWidget()->removeEventFilter(this); + setParent(parent); + if (parent) { + parent->installEventFilter(this); + resizeToParent(); + raise(); + } + } + void setPaintFunction(const PaintFunction &paint) { m_paint = paint; } + +protected: + bool eventFilter(QObject *obj, QEvent *ev) override + { + if (obj == parent() && ev->type() == QEvent::Resize) + resizeToParent(); + return QWidget::eventFilter(obj, ev); + } + void paintEvent(QPaintEvent *ev) override + { + if (m_paint) { + QPainter p(this); + m_paint(this, p, ev); + } + } + +private: + void resizeToParent() { setGeometry(QRect(QPoint(0, 0), parentWidget()->size())); } + + PaintFunction m_paint; +}; + +class ProgressIndicatorPainter +{ +public: + using UpdateCallback = std::function; + + ProgressIndicatorPainter(); + virtual ~ProgressIndicatorPainter() = default; + + void setUpdateCallback(const UpdateCallback &cb) { m_callback = cb; } + + QSize size() const { return m_pixmap.size() / m_pixmap.devicePixelRatio(); } + + void paint(QPainter &painter, const QRect &rect) const; + void startAnimation() { m_timer.start(); } + void stopAnimation() { m_timer.stop(); } + +protected: + void nextAnimationStep() { m_rotation = (m_rotation + m_rotationStep + 360) % 360; } + +private: + const int m_rotationStep = 45; + int m_rotation = 0; + QTimer m_timer; + QPixmap m_pixmap; + UpdateCallback m_callback; +}; + +ProgressIndicatorPainter::ProgressIndicatorPainter() +{ + m_timer.setSingleShot(false); + QObject::connect(&m_timer, &QTimer::timeout, &m_timer, [this] { + nextAnimationStep(); + if (m_callback) + m_callback(); + }); + + m_timer.setInterval(100); + m_pixmap = QPixmap(":/icons/progressindicator.png"); +} + +void ProgressIndicatorPainter::paint(QPainter &painter, const QRect &rect) const +{ + painter.save(); + painter.setRenderHint(QPainter::SmoothPixmapTransform); + QPoint translate(rect.x() + rect.width() / 2, rect.y() + rect.height() / 2); + QTransform t; + t.translate(translate.x(), translate.y()); + t.rotate(m_rotation); + t.translate(-translate.x(), -translate.y()); + painter.setTransform(t); + QSize pixmapUserSize(m_pixmap.size() / m_pixmap.devicePixelRatio()); + painter.drawPixmap(QPoint(rect.x() + ((rect.width() - pixmapUserSize.width()) / 2), + rect.y() + ((rect.height() - pixmapUserSize.height()) / 2)), + m_pixmap); + painter.restore(); +} + +class ProgressIndicatorWidget : public OverlayWidget +{ +public: + explicit ProgressIndicatorWidget(QWidget *parent = nullptr) + : OverlayWidget(parent) + { + setPaintFunction( + [this](QWidget *w, QPainter &p, QPaintEvent *) { m_paint.paint(p, w->rect()); }); + m_paint.setUpdateCallback([this] { update(); }); + updateGeometry(); + } + + QSize sizeHint() const final { return m_paint.size(); } + +protected: + void showEvent(QShowEvent *) final { m_paint.startAnimation(); } + void hideEvent(QHideEvent *) final { m_paint.stopAnimation(); } + +private: + ProgressIndicatorPainter m_paint; +}; + +ProgressIndicator::ProgressIndicator(QWidget *parent) + : QObject(parent) + , m_widget(new ProgressIndicatorWidget(parent)) {} + + +void ProgressIndicator::show() +{ + m_widget->show(); +} + +void ProgressIndicator::hide() +{ + m_widget->hide(); +} diff --git a/tests/manual/tasking/demo/progressindicator.h b/tests/manual/tasking/demo/progressindicator.h new file mode 100644 index 00000000000..406ebc9e831 --- /dev/null +++ b/tests/manual/tasking/demo/progressindicator.h @@ -0,0 +1,21 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#ifndef PROGRESSINDICATOR_H +#define PROGRESSINDICATOR_H + +#include + +class ProgressIndicator : public QObject +{ +public: + ProgressIndicator(QWidget *parent = nullptr); + + void show(); + void hide(); + +private: + class ProgressIndicatorWidget *m_widget = nullptr; +}; + +#endif // PROGRESSINDICATOR_H diff --git a/tests/manual/tasktree/taskwidget.cpp b/tests/manual/tasking/demo/taskwidget.cpp similarity index 59% rename from tests/manual/tasktree/taskwidget.cpp rename to tests/manual/tasking/demo/taskwidget.cpp index ddc56aa77e2..6bc68db1a1b 100644 --- a/tests/manual/tasktree/taskwidget.cpp +++ b/tests/manual/tasking/demo/taskwidget.cpp @@ -1,20 +1,18 @@ -// Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +#include "progressindicator.h" #include "taskwidget.h" -#include -#include -#include - +#include #include #include #include #include +#include #include -using namespace Utils; -using namespace Layouting; +using namespace Tasking; static QString colorButtonStyleSheet(const QColor &bgColor) { @@ -37,10 +35,10 @@ static QColor stateToColor(State state) { class StateIndicator : public QLabel { public: - StateIndicator() + StateIndicator(QWidget *parent = nullptr) + : QLabel(parent) { - m_progressIndicator = new ProgressIndicator(ProgressIndicatorSize::Small); - m_progressIndicator->attachToWidget(this); + m_progressIndicator = new ProgressIndicator(this); m_progressIndicator->hide(); updateState(); } @@ -67,9 +65,7 @@ private: }; StateWidget::StateWidget() - : m_stateIndicator(new StateIndicator) -{ -} + : m_stateIndicator(new StateIndicator(this)) {} void StateWidget::setState(State state) { @@ -86,14 +82,13 @@ TaskWidget::TaskWidget() setBusyTime(1); setSuccess(true); - Row { - m_stateIndicator, - m_infoLabel, - m_spinBox, - m_checkBox, - st, - noMargin, - }.attachTo(this); + QBoxLayout *layout = new QHBoxLayout(this); + layout->addWidget(m_stateIndicator); + layout->addWidget(m_infoLabel); + layout->addWidget(m_spinBox); + layout->addWidget(m_checkBox); + layout->addStretch(); + layout->setContentsMargins(0, 0, 0, 0); } void TaskWidget::setBusyTime(int seconds) @@ -122,34 +117,32 @@ GroupWidget::GroupWidget() { m_stateIndicator->setFixedWidth(30); - m_executeCombo->addItem("Sequential", (int)ExecuteMode::Sequential); - m_executeCombo->addItem("Parallel", (int)ExecuteMode::Parallel); + m_executeCombo->addItem("Sequential", int(ExecuteMode::Sequential)); + m_executeCombo->addItem("Parallel", int(ExecuteMode::Parallel)); updateExecuteMode(); connect(m_executeCombo, &QComboBox::currentIndexChanged, this, [this](int index) { m_executeMode = (ExecuteMode)m_executeCombo->itemData(index).toInt(); }); - m_workflowCombo->addItem("Stop On Error", (int)Tasking::WorkflowPolicy::StopOnError); - m_workflowCombo->addItem("Cont On Error", (int)Tasking::WorkflowPolicy::ContinueOnError); - m_workflowCombo->addItem("Stop On Done", (int)Tasking::WorkflowPolicy::StopOnDone); - m_workflowCombo->addItem("Cont On Done", (int)Tasking::WorkflowPolicy::ContinueOnDone); - m_workflowCombo->addItem("Optional", (int)Tasking::WorkflowPolicy::FinishAllAndDone); + const QMetaEnum workflow = QMetaEnum::fromType(); + for (int i = 0; i < workflow.keyCount(); ++i) + m_workflowCombo->addItem(workflow.key(i), workflow.value(i)); + updateWorkflowPolicy(); connect(m_workflowCombo, &QComboBox::currentIndexChanged, this, [this](int index) { - m_workflowPolicy = (Tasking::WorkflowPolicy)m_workflowCombo->itemData(index).toInt(); + m_workflowPolicy = (WorkflowPolicy)m_workflowCombo->itemData(index).toInt(); }); - Row { - m_stateIndicator, - Column { - new QLabel("Execute:"), - m_executeCombo, - new QLabel("Workflow:"), - m_workflowCombo, - st, - noMargin - } - }.attachTo(this); + QBoxLayout *layout = new QHBoxLayout(this); + layout->addWidget(m_stateIndicator); + QBoxLayout *subLayout = new QVBoxLayout; + subLayout->addWidget(new QLabel("Execute Mode:")); + subLayout->addWidget(m_executeCombo); + subLayout->addWidget(new QLabel("Workflow Policy:")); + subLayout->addWidget(m_workflowCombo); + subLayout->addStretch(); + layout->addLayout(subLayout); + layout->setContentsMargins(0, 0, 0, 0); setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); } @@ -165,12 +158,12 @@ void GroupWidget::updateExecuteMode() m_executeCombo->setCurrentIndex(m_executeCombo->findData((int)m_executeMode)); } -Tasking::TaskItem GroupWidget::executeMode() const +TaskItem GroupWidget::executeMode() const { - return m_executeMode == ExecuteMode::Sequential ? Tasking::sequential : Tasking::parallel; + return m_executeMode == ExecuteMode::Sequential ? sequential : parallel; } -void GroupWidget::setWorkflowPolicy(Tasking::WorkflowPolicy policy) +void GroupWidget::setWorkflowPolicy(WorkflowPolicy policy) { m_workflowPolicy = policy; updateWorkflowPolicy(); @@ -181,13 +174,7 @@ void GroupWidget::updateWorkflowPolicy() m_workflowCombo->setCurrentIndex(m_workflowCombo->findData((int)m_workflowPolicy)); } -Tasking::WorkflowPolicy GroupWidget::workflowPolicy() const +TaskItem GroupWidget::workflowPolicy() const { - return m_workflowPolicy; + return Tasking::workflowPolicy(m_workflowPolicy); } - -void createItem(Layouting::LayoutItem *item, const TaskGroup &taskGroup) -{ - item->addItems({taskGroup.group, Group { taskGroup.items }, br}); -} - diff --git a/tests/manual/tasktree/taskwidget.h b/tests/manual/tasking/demo/taskwidget.h similarity index 75% rename from tests/manual/tasktree/taskwidget.h rename to tests/manual/tasking/demo/taskwidget.h index c425f23965f..3ce210eb0d4 100644 --- a/tests/manual/tasktree/taskwidget.h +++ b/tests/manual/tasking/demo/taskwidget.h @@ -1,9 +1,10 @@ -// Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -#include +#ifndef TASKWIDGET_H +#define TASKWIDGET_H -#include +#include #include @@ -64,7 +65,7 @@ public: Tasking::TaskItem executeMode() const; void setWorkflowPolicy(Tasking::WorkflowPolicy policy); - Tasking::WorkflowPolicy workflowPolicy() const; + Tasking::TaskItem workflowPolicy() const; private: void updateExecuteMode(); @@ -77,11 +78,4 @@ private: Tasking::WorkflowPolicy m_workflowPolicy = Tasking::WorkflowPolicy::StopOnError; }; -class TaskGroup -{ -public: - QWidget *group; - Layouting::Column items; -}; - -void createItem(Layouting::LayoutItem *item, const TaskGroup &taskGroup); +#endif // TASKWIDGET_H diff --git a/tests/manual/tasktree/CMakeLists.txt b/tests/manual/tasktree/CMakeLists.txt deleted file mode 100644 index 19bd81bfb2b..00000000000 --- a/tests/manual/tasktree/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -add_qtc_test(tst_manual_tasktree - MANUALTEST - DEPENDS Utils - SOURCES - main.cpp taskwidget.h taskwidget.cpp -) diff --git a/tests/manual/tasktree/tasktree.qbs b/tests/manual/tasktree/tasktree.qbs deleted file mode 100644 index dad8e14763c..00000000000 --- a/tests/manual/tasktree/tasktree.qbs +++ /dev/null @@ -1,14 +0,0 @@ -import qbs.FileInfo - -QtcManualtest { - name: "Manual TaskTree test" - type: ["application"] - - Depends { name: "Utils" } - - files: [ - "main.cpp", - "taskwidget.h", - "taskwidget.cpp", - ] -} From 3ee32c1a3b54542bd41df8b7bd420cb0554a9fc5 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Mon, 29 May 2023 01:10:39 +0200 Subject: [PATCH 072/141] TaskTree: Reuse withTimeout() Add static runBlocking() overloads. Replace int timeout arg with std::chrono::milliseconds. Change-Id: Id10a010f05eda8452cd7e4cd9ee46216087fc70e Reviewed-by: Reviewed-by: Marcus Tillmanns Reviewed-by: Qt CI Bot --- src/libs/solutions/tasking/tasktree.cpp | 35 +++++++++++-------- src/libs/solutions/tasking/tasktree.h | 8 +++-- src/libs/utils/filestreamer.cpp | 3 +- .../remotelinux/filesystemaccess_test.cpp | 4 +-- tests/auto/solutions/tasking/tst_tasking.cpp | 8 ++--- tests/auto/utils/async/tst_async.cpp | 9 ++--- .../tst_subdirfileiterator.cpp | 6 ++-- 7 files changed, 40 insertions(+), 33 deletions(-) diff --git a/src/libs/solutions/tasking/tasktree.cpp b/src/libs/solutions/tasking/tasktree.cpp index 60caa217ef7..f9fe58375e8 100644 --- a/src/libs/solutions/tasking/tasktree.cpp +++ b/src/libs/solutions/tasking/tasktree.cpp @@ -1791,9 +1791,16 @@ bool TaskTree::isRunning() const return d->m_root && d->m_root->isRunning(); } -bool TaskTree::runBlocking(const QFuture &future, int timeoutMs) +bool TaskTree::runBlocking() { - if (isRunning() || future.isCanceled()) + QPromise dummy; + dummy.start(); + return runBlocking(dummy.future()); +} + +bool TaskTree::runBlocking(const QFuture &future) +{ + if (future.isCanceled()) return false; bool ok = false; @@ -1812,17 +1819,7 @@ bool TaskTree::runBlocking(const QFuture &future, int timeoutMs) connect(this, &TaskTree::done, &loop, [finalize] { finalize(true); }); connect(this, &TaskTree::errorOccurred, &loop, [finalize] { finalize(false); }); - start(); - if (!isRunning()) - return ok; - - QTimer timer; - if (timeoutMs) { - timer.setSingleShot(true); - timer.setInterval(timeoutMs); - connect(&timer, &QTimer::timeout, this, &TaskTree::stop); - timer.start(); - } + QTimer::singleShot(0, this, &TaskTree::start); loop.exec(QEventLoop::ExcludeUserInputEvents); if (!ok) { @@ -1832,11 +1829,19 @@ bool TaskTree::runBlocking(const QFuture &future, int timeoutMs) return ok; } -bool TaskTree::runBlocking(int timeoutMs) +bool TaskTree::runBlocking(const Group &recipe, milliseconds timeout) { QPromise dummy; dummy.start(); - return runBlocking(dummy.future(), timeoutMs); + return TaskTree::runBlocking(recipe, dummy.future(), timeout); +} + +bool TaskTree::runBlocking(const Group &recipe, const QFuture &future, milliseconds timeout) +{ + const Group root = timeout == milliseconds::max() ? recipe + : Group { recipe.withTimeout(timeout) }; + TaskTree taskTree(root); + return taskTree.runBlocking(future); } int TaskTree::taskCount() const diff --git a/src/libs/solutions/tasking/tasktree.h b/src/libs/solutions/tasking/tasktree.h index 1d596316cae..b4119219a1b 100644 --- a/src/libs/solutions/tasking/tasktree.h +++ b/src/libs/solutions/tasking/tasktree.h @@ -390,8 +390,12 @@ public: // Helper methods. They execute a local event loop with ExcludeUserInputEvents. // The passed future is used for listening to the cancel event. // Don't use it in main thread. To be used in non-main threads or in auto tests. - bool runBlocking(const QFuture &future, int timeoutMs = 0); - bool runBlocking(int timeoutMs = 0); + bool runBlocking(); + bool runBlocking(const QFuture &future); + static bool runBlocking(const Group &recipe, + std::chrono::milliseconds timeout = std::chrono::milliseconds::max()); + static bool runBlocking(const Group &recipe, const QFuture &future, + std::chrono::milliseconds timeout = std::chrono::milliseconds::max()); int taskCount() const; int progressMaximum() const { return taskCount(); } diff --git a/src/libs/utils/filestreamer.cpp b/src/libs/utils/filestreamer.cpp index d24b61dbde3..693849b7c59 100644 --- a/src/libs/utils/filestreamer.cpp +++ b/src/libs/utils/filestreamer.cpp @@ -375,8 +375,7 @@ static void transfer(QPromise &promise, const FilePath &source, const File if (promise.isCanceled()) return; - TaskTree taskTree(transferTask(source, destination)); - if (!taskTree.runBlocking(promise.future())) + if (!TaskTree::runBlocking(transferTask(source, destination), promise.future())) promise.future().cancel(); } diff --git a/src/plugins/remotelinux/filesystemaccess_test.cpp b/src/plugins/remotelinux/filesystemaccess_test.cpp index dda6e417615..2edb78fa7b3 100644 --- a/src/plugins/remotelinux/filesystemaccess_test.cpp +++ b/src/plugins/remotelinux/filesystemaccess_test.cpp @@ -503,8 +503,8 @@ void FileSystemAccessTest::testFileStreamer() } }; - TaskTree taskTree(root); - QVERIFY(taskTree.runBlocking(10000)); + using namespace std::chrono_literals; + QVERIFY(TaskTree::runBlocking(root, 10000ms)); QVERIFY(localData); QCOMPARE(*localData, data); diff --git a/tests/auto/solutions/tasking/tst_tasking.cpp b/tests/auto/solutions/tasking/tst_tasking.cpp index 8c2173585b1..294bea71b7e 100644 --- a/tests/auto/solutions/tasking/tst_tasking.cpp +++ b/tests/auto/solutions/tasking/tst_tasking.cpp @@ -2202,15 +2202,15 @@ void tst_Tasking::testTree() { QFETCH(TestData, testData); - TaskTree taskTree(testData.root); - QCOMPARE(taskTree.taskCount(), testData.taskCount); + TaskTree taskTree({testData.root.withTimeout(1000ms)}); + QCOMPARE(taskTree.taskCount() - 1, testData.taskCount); // -1 for the timeout task above Log actualLog; const auto collectLog = [&actualLog](CustomStorage *storage) { actualLog = storage->m_log; }; taskTree.onStorageDone(testData.storage, collectLog); - const OnDone result = taskTree.runBlocking(2000) ? OnDone::Success : OnDone::Failure; + const OnDone result = taskTree.runBlocking() ? OnDone::Success : OnDone::Failure; QCOMPARE(taskTree.isRunning(), false); - QCOMPARE(taskTree.progressValue(), testData.taskCount); + QCOMPARE(taskTree.progressValue(), taskTree.progressMaximum()); QCOMPARE(actualLog, testData.expectedLog); QCOMPARE(CustomStorage::instanceCount(), 0); diff --git a/tests/auto/utils/async/tst_async.cpp b/tests/auto/utils/async/tst_async.cpp index 01c3306a3bf..5d4a81dc961 100644 --- a/tests/auto/utils/async/tst_async.cpp +++ b/tests/auto/utils/async/tst_async.cpp @@ -8,6 +8,8 @@ using namespace Utils; +using namespace std::chrono_literals; + class tst_Async : public QObject { Q_OBJECT @@ -438,8 +440,8 @@ void tst_Async::taskTree() AsyncTask(setupIntAsync, handleIntAsync), }; - TaskTree tree(root); - QVERIFY(tree.runBlocking(1000)); + + QVERIFY(TaskTree::runBlocking(root, 1000ms)); QCOMPARE(value, 16); } @@ -575,8 +577,7 @@ void tst_Async::mapReduce() QFETCH(double, sum); QFETCH(QList, results); - TaskTree tree(root); - QVERIFY(tree.runBlocking(1000)); + QVERIFY(TaskTree::runBlocking(root, 1000ms)); QCOMPARE(s_results, results); QCOMPARE(s_sum, sum); } diff --git a/tests/manual/subdirfileiterator/tst_subdirfileiterator.cpp b/tests/manual/subdirfileiterator/tst_subdirfileiterator.cpp index 66dd7737816..882a9993a26 100644 --- a/tests/manual/subdirfileiterator/tst_subdirfileiterator.cpp +++ b/tests/manual/subdirfileiterator/tst_subdirfileiterator.cpp @@ -135,8 +135,7 @@ private slots: tasks.append(AsyncTask(onSetup(parentDir.filePath(dirName), templateFile))); } - TaskTree taskTree(tasks); - QVERIFY(taskTree.runBlocking()); + QVERIFY(TaskTree::runBlocking(tasks)); } void cleanupTestCase() @@ -161,8 +160,7 @@ private slots: tasks.append(AsyncTask(onSetup(parentDir.filePath(dirName)))); } - TaskTree taskTree(tasks); - QVERIFY(taskTree.runBlocking()); + QVERIFY(TaskTree::runBlocking(tasks)); m_tempDir.reset(); Singleton::deleteAll(); From 7d40a35d9ee875b0bfb40e5f5abf5032c0f01c65 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 1 Jun 2023 09:08:16 +0200 Subject: [PATCH 073/141] Android: Use aspect as direct member in deploy step Change-Id: I7c7037ca5ca1fb1cd3fcb7ab66a30a6f62986e20 Reviewed-by: Reviewed-by: Alessandro Portale --- src/plugins/android/androiddeployqtstep.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/plugins/android/androiddeployqtstep.cpp b/src/plugins/android/androiddeployqtstep.cpp index f33ae5aa6b3..a9e9596e772 100644 --- a/src/plugins/android/androiddeployqtstep.cpp +++ b/src/plugins/android/androiddeployqtstep.cpp @@ -122,7 +122,7 @@ private: QMap m_filesToPull; QStringList m_androidABIs; - BoolAspect *m_uninstallPreviousPackage = nullptr; + BoolAspect m_uninstallPreviousPackage{this}; bool m_uninstallPreviousPackageRun = false; bool m_useAndroiddeployqt = false; bool m_askForUninstall = false; @@ -143,17 +143,16 @@ AndroidDeployQtStep::AndroidDeployQtStep(BuildStepList *parent, Id id) setImmutable(true); setUserExpanded(true); - m_uninstallPreviousPackage = addAspect(); - m_uninstallPreviousPackage->setSettingsKey(UninstallPreviousPackageKey); - m_uninstallPreviousPackage->setLabel(Tr::tr("Uninstall the existing app before deployment"), + m_uninstallPreviousPackage.setSettingsKey(UninstallPreviousPackageKey); + m_uninstallPreviousPackage.setLabel(Tr::tr("Uninstall the existing app before deployment"), BoolAspect::LabelPlacement::AtCheckBox); - m_uninstallPreviousPackage->setValue(false); + m_uninstallPreviousPackage.setValue(false); const QtSupport::QtVersion * const qt = QtSupport::QtKitAspect::qtVersion(kit()); const bool forced = qt && qt->qtVersion() < QVersionNumber(5, 4, 0); if (forced) { - m_uninstallPreviousPackage->setValue(true); - m_uninstallPreviousPackage->setEnabled(false); + m_uninstallPreviousPackage.setValue(true); + m_uninstallPreviousPackage.setEnabled(false); } connect(this, &AndroidDeployQtStep::askForUninstall, @@ -274,7 +273,7 @@ bool AndroidDeployQtStep::init() emit addOutput(Tr::tr("Deploying to %1").arg(m_serialNumber), OutputFormat::NormalMessage); - m_uninstallPreviousPackageRun = m_uninstallPreviousPackage->value(); + m_uninstallPreviousPackageRun = m_uninstallPreviousPackage(); if (m_uninstallPreviousPackageRun) m_manifestName = AndroidManager::manifestPath(target()); From 00f427f68e8a36904d2999e98d685c3540e289cd Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 31 May 2023 18:03:31 +0200 Subject: [PATCH 074/141] QmakeProjectManager: Auto-register aspects Change-Id: I61b41b0155e125173e48686d1482bb8bd94055da Reviewed-by: Christian Stenger --- src/plugins/qmakeprojectmanager/qmakesettings.cpp | 3 --- src/plugins/qmakeprojectmanager/qmakesettings.h | 6 +++--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/plugins/qmakeprojectmanager/qmakesettings.cpp b/src/plugins/qmakeprojectmanager/qmakesettings.cpp index f920381d15e..e69526901f0 100644 --- a/src/plugins/qmakeprojectmanager/qmakesettings.cpp +++ b/src/plugins/qmakeprojectmanager/qmakesettings.cpp @@ -26,7 +26,6 @@ QmakeSettings::QmakeSettings() setCategory(ProjectExplorer::Constants::BUILD_AND_RUN_SETTINGS_CATEGORY); setSettingsGroup("QmakeProjectManager"); - registerAspect(&warnAgainstUnalignedBuildDir); warnAgainstUnalignedBuildDir.setSettingsKey("WarnAgainstUnalignedBuildDir"); warnAgainstUnalignedBuildDir.setDefaultValue(HostOsInfo::isWindowsHost()); warnAgainstUnalignedBuildDir.setLabelText(Tr::tr("Warn if a project's source and " @@ -34,13 +33,11 @@ QmakeSettings::QmakeSettings() warnAgainstUnalignedBuildDir.setToolTip(Tr::tr("Qmake has subtle bugs that " "can be triggered if source and build directory are not at the same level.")); - registerAspect(&alwaysRunQmake); alwaysRunQmake.setSettingsKey("AlwaysRunQmake"); alwaysRunQmake.setLabelText(Tr::tr("Run qmake on every build")); alwaysRunQmake.setToolTip(Tr::tr("This option can help to prevent failures on " "incremental builds, but might slow them down unnecessarily in the general case.")); - registerAspect(&ignoreSystemFunction); ignoreSystemFunction.setSettingsKey("RunSystemFunction"); ignoreSystemFunction.setLabelText(Tr::tr("Ignore qmake's system() function when parsing a project")); ignoreSystemFunction.setToolTip(Tr::tr("Checking this option avoids unwanted side effects, " diff --git a/src/plugins/qmakeprojectmanager/qmakesettings.h b/src/plugins/qmakeprojectmanager/qmakesettings.h index de9a9ec0d37..9c2b277f538 100644 --- a/src/plugins/qmakeprojectmanager/qmakesettings.h +++ b/src/plugins/qmakeprojectmanager/qmakesettings.h @@ -14,9 +14,9 @@ public: bool runSystemFunction() { return !ignoreSystemFunction(); } - Utils::BoolAspect warnAgainstUnalignedBuildDir; - Utils::BoolAspect alwaysRunQmake; - Utils::BoolAspect ignoreSystemFunction; + Utils::BoolAspect warnAgainstUnalignedBuildDir{this}; + Utils::BoolAspect alwaysRunQmake{this}; + Utils::BoolAspect ignoreSystemFunction{this}; }; QmakeSettings &settings(); From 5fb623fc14d376b988a8311ee82884e98cac9556 Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 31 May 2023 17:37:30 +0200 Subject: [PATCH 075/141] Macros: Merge macrooptionswidget.{h,cpp} into macrooptionspage.cpp Change-Id: I4493d781a503dde252ae6ad4d705e378b5b0ed51 Reviewed-by: Christian Stenger --- src/plugins/macros/CMakeLists.txt | 1 - src/plugins/macros/macrooptionspage.cpp | 189 +++++++++++++++++++++- src/plugins/macros/macrooptionspage.h | 6 +- src/plugins/macros/macrooptionswidget.cpp | 166 ------------------- src/plugins/macros/macrooptionswidget.h | 55 ------- src/plugins/macros/macros.qbs | 2 - 6 files changed, 186 insertions(+), 233 deletions(-) delete mode 100644 src/plugins/macros/macrooptionswidget.cpp delete mode 100644 src/plugins/macros/macrooptionswidget.h diff --git a/src/plugins/macros/CMakeLists.txt b/src/plugins/macros/CMakeLists.txt index aef9a332ddc..588a9a330f3 100644 --- a/src/plugins/macros/CMakeLists.txt +++ b/src/plugins/macros/CMakeLists.txt @@ -9,7 +9,6 @@ add_qtc_plugin(Macros macrolocatorfilter.cpp macrolocatorfilter.h macromanager.cpp macromanager.h macrooptionspage.cpp macrooptionspage.h - macrooptionswidget.cpp macrooptionswidget.h macros.qrc macrosconstants.h macrosplugin.cpp macrosplugin.h diff --git a/src/plugins/macros/macrooptionspage.cpp b/src/plugins/macros/macrooptionspage.cpp index 6295ea94e78..616547283e0 100644 --- a/src/plugins/macros/macrooptionspage.cpp +++ b/src/plugins/macros/macrooptionspage.cpp @@ -3,15 +3,195 @@ #include "macrooptionspage.h" +#include "macro.h" #include "macromanager.h" -#include "macrooptionswidget.h" #include "macrosconstants.h" #include "macrostr.h" +#include +#include +#include +#include + #include -namespace Macros { -namespace Internal { +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Macros::Internal { + +const int NAME_ROLE = Qt::UserRole; +const int WRITE_ROLE = Qt::UserRole + 1; + +class MacroOptionsWidget final : public Core::IOptionsPageWidget +{ +public: + MacroOptionsWidget(); + + void initialize(); + + void apply() final; + +private: + void remove(); + void changeCurrentItem(QTreeWidgetItem *current); + + void createTable(); + + void changeDescription(const QString &description); + + QStringList m_macroToRemove; + bool m_changingCurrent = false; + + QMap m_macroToChange; + + QTreeWidget *m_treeWidget; + QPushButton *m_removeButton; + QGroupBox *m_macroGroup; + QLineEdit *m_description; +}; + +MacroOptionsWidget::MacroOptionsWidget() +{ + m_treeWidget = new QTreeWidget; + m_treeWidget->setTextElideMode(Qt::ElideLeft); + m_treeWidget->setUniformRowHeights(true); + m_treeWidget->setSortingEnabled(true); + m_treeWidget->setColumnCount(3); + m_treeWidget->header()->setSortIndicatorShown(true); + m_treeWidget->header()->setStretchLastSection(true); + m_treeWidget->header()->setSortIndicator(0, Qt::AscendingOrder); + m_treeWidget->setHeaderLabels({Tr::tr("Name"), Tr::tr("Description"), Tr::tr("Shortcut")}); + + m_description = new QLineEdit; + + m_removeButton = new QPushButton(Tr::tr("Remove")); + + m_macroGroup = new QGroupBox(Tr::tr("Macro"), this); + + using namespace Layouting; + + Row { + Tr::tr("Description:"), m_description + }.attachTo(m_macroGroup); + + Column { + Group { + title(Tr::tr("Preferences")), + Row { + m_treeWidget, + Column { m_removeButton, st }, + } + }, + m_macroGroup + }.attachTo(this); + + connect(m_treeWidget, &QTreeWidget::currentItemChanged, + this, &MacroOptionsWidget::changeCurrentItem); + connect(m_removeButton, &QPushButton::clicked, + this, &MacroOptionsWidget::remove); + connect(m_description, &QLineEdit::textChanged, + this, &MacroOptionsWidget::changeDescription); + + initialize(); +} + +void MacroOptionsWidget::initialize() +{ + m_macroToRemove.clear(); + m_macroToChange.clear(); + m_treeWidget->clear(); + changeCurrentItem(nullptr); + + // Create the treeview + createTable(); +} + +void MacroOptionsWidget::createTable() +{ + QDir dir(MacroManager::macrosDirectory()); + const Utils::Id base = Utils::Id(Constants::PREFIX_MACRO); + for (Macro *macro : MacroManager::macros()) { + QFileInfo fileInfo(macro->fileName()); + if (fileInfo.absoluteDir() == dir.absolutePath()) { + auto macroItem = new QTreeWidgetItem(m_treeWidget); + macroItem->setText(0, macro->displayName()); + macroItem->setText(1, macro->description()); + macroItem->setData(0, NAME_ROLE, macro->displayName()); + macroItem->setData(0, WRITE_ROLE, macro->isWritable()); + + Core::Command *command = + Core::ActionManager::command(base.withSuffix(macro->displayName())); + if (command && command->action()) { + macroItem->setText(2, + command->action()->shortcut().toString(QKeySequence::NativeText)); + } + } + } +} + +void MacroOptionsWidget::changeCurrentItem(QTreeWidgetItem *current) +{ + m_changingCurrent = true; + m_removeButton->setEnabled(current); + m_macroGroup->setEnabled(current); + if (!current) { + m_description->clear(); + } else { + m_description->setText(current->text(1)); + m_description->setEnabled(current->data(0, WRITE_ROLE).toBool()); + } + m_changingCurrent = false; +} + +void MacroOptionsWidget::remove() +{ + QTreeWidgetItem *current = m_treeWidget->currentItem(); + m_macroToRemove.append(current->data(0, NAME_ROLE).toString()); + delete current; +} + +void MacroOptionsWidget::apply() +{ + // Remove macro + for (const QString &name : std::as_const(m_macroToRemove)) { + MacroManager::instance()->deleteMacro(name); + m_macroToChange.remove(name); + } + + // Change macro + for (auto it = m_macroToChange.cbegin(), end = m_macroToChange.cend(); it != end; ++it) + MacroManager::instance()->changeMacro(it.key(), it.value()); + + // Reinitialize the page + initialize(); +} + +void MacroOptionsWidget::changeDescription(const QString &description) +{ + QTreeWidgetItem *current = m_treeWidget->currentItem(); + if (m_changingCurrent || !current) + return; + + QString macroName = current->data(0, NAME_ROLE).toString(); + m_macroToChange[macroName] = description; + current->setText(1, description); + QFont font = current->font(1); + font.setItalic(true); + current->setFont(1, font); +} MacroOptionsPage::MacroOptionsPage() { @@ -21,5 +201,4 @@ MacroOptionsPage::MacroOptionsPage() setWidgetCreator([] { return new MacroOptionsWidget; }); } -} // Internal -} // Macros +} // Macros::Internal diff --git a/src/plugins/macros/macrooptionspage.h b/src/plugins/macros/macrooptionspage.h index e9948cb1673..511b8b2b870 100644 --- a/src/plugins/macros/macrooptionspage.h +++ b/src/plugins/macros/macrooptionspage.h @@ -5,8 +5,7 @@ #include -namespace Macros { -namespace Internal { +namespace Macros::Internal { class MacroOptionsPage final : public Core::IOptionsPage { @@ -14,5 +13,4 @@ public: MacroOptionsPage(); }; -} // namespace Internal -} // namespace Macros +} // Macros::Internal diff --git a/src/plugins/macros/macrooptionswidget.cpp b/src/plugins/macros/macrooptionswidget.cpp deleted file mode 100644 index cd11ab64ef3..00000000000 --- a/src/plugins/macros/macrooptionswidget.cpp +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright (C) 2016 Nicolas Arnaud-Cormos -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "macrooptionswidget.h" - -#include "macro.h" -#include "macromanager.h" -#include "macrosconstants.h" -#include "macrostr.h" - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Macros::Internal { - -const int NAME_ROLE = Qt::UserRole; -const int WRITE_ROLE = Qt::UserRole + 1; - -MacroOptionsWidget::MacroOptionsWidget() -{ - m_treeWidget = new QTreeWidget; - m_treeWidget->setTextElideMode(Qt::ElideLeft); - m_treeWidget->setUniformRowHeights(true); - m_treeWidget->setSortingEnabled(true); - m_treeWidget->setColumnCount(3); - m_treeWidget->header()->setSortIndicatorShown(true); - m_treeWidget->header()->setStretchLastSection(true); - m_treeWidget->header()->setSortIndicator(0, Qt::AscendingOrder); - m_treeWidget->setHeaderLabels({Tr::tr("Name"), Tr::tr("Description"), Tr::tr("Shortcut")}); - - m_description = new QLineEdit; - - m_removeButton = new QPushButton(Tr::tr("Remove")); - - m_macroGroup = new QGroupBox(Tr::tr("Macro"), this); - - using namespace Layouting; - - Row { - Tr::tr("Description:"), m_description - }.attachTo(m_macroGroup); - - Column { - Group { - title(Tr::tr("Preferences")), - Row { - m_treeWidget, - Column { m_removeButton, st }, - } - }, - m_macroGroup - }.attachTo(this); - - connect(m_treeWidget, &QTreeWidget::currentItemChanged, - this, &MacroOptionsWidget::changeCurrentItem); - connect(m_removeButton, &QPushButton::clicked, - this, &MacroOptionsWidget::remove); - connect(m_description, &QLineEdit::textChanged, - this, &MacroOptionsWidget::changeDescription); - - initialize(); -} - -MacroOptionsWidget::~MacroOptionsWidget() = default; - -void MacroOptionsWidget::initialize() -{ - m_macroToRemove.clear(); - m_macroToChange.clear(); - m_treeWidget->clear(); - changeCurrentItem(nullptr); - - // Create the treeview - createTable(); -} - -void MacroOptionsWidget::createTable() -{ - QDir dir(MacroManager::macrosDirectory()); - const Utils::Id base = Utils::Id(Constants::PREFIX_MACRO); - for (Macro *macro : MacroManager::macros()) { - QFileInfo fileInfo(macro->fileName()); - if (fileInfo.absoluteDir() == dir.absolutePath()) { - auto macroItem = new QTreeWidgetItem(m_treeWidget); - macroItem->setText(0, macro->displayName()); - macroItem->setText(1, macro->description()); - macroItem->setData(0, NAME_ROLE, macro->displayName()); - macroItem->setData(0, WRITE_ROLE, macro->isWritable()); - - Core::Command *command = - Core::ActionManager::command(base.withSuffix(macro->displayName())); - if (command && command->action()) { - macroItem->setText(2, - command->action()->shortcut().toString(QKeySequence::NativeText)); - } - } - } -} - -void MacroOptionsWidget::changeCurrentItem(QTreeWidgetItem *current) -{ - m_changingCurrent = true; - m_removeButton->setEnabled(current); - m_macroGroup->setEnabled(current); - if (!current) { - m_description->clear(); - } else { - m_description->setText(current->text(1)); - m_description->setEnabled(current->data(0, WRITE_ROLE).toBool()); - } - m_changingCurrent = false; -} - -void MacroOptionsWidget::remove() -{ - QTreeWidgetItem *current = m_treeWidget->currentItem(); - m_macroToRemove.append(current->data(0, NAME_ROLE).toString()); - delete current; -} - -void MacroOptionsWidget::apply() -{ - // Remove macro - for (const QString &name : std::as_const(m_macroToRemove)) { - MacroManager::instance()->deleteMacro(name); - m_macroToChange.remove(name); - } - - // Change macro - for (auto it = m_macroToChange.cbegin(), end = m_macroToChange.cend(); it != end; ++it) - MacroManager::instance()->changeMacro(it.key(), it.value()); - - // Reinitialize the page - initialize(); -} - -void MacroOptionsWidget::changeDescription(const QString &description) -{ - QTreeWidgetItem *current = m_treeWidget->currentItem(); - if (m_changingCurrent || !current) - return; - - QString macroName = current->data(0, NAME_ROLE).toString(); - m_macroToChange[macroName] = description; - current->setText(1, description); - QFont font = current->font(1); - font.setItalic(true); - current->setFont(1, font); -} - -} // Macros::Internal diff --git a/src/plugins/macros/macrooptionswidget.h b/src/plugins/macros/macrooptionswidget.h deleted file mode 100644 index 9810da6dd18..00000000000 --- a/src/plugins/macros/macrooptionswidget.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (C) 2016 Nicolas Arnaud-Cormos -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#pragma once - -#include - -#include -#include - -QT_BEGIN_NAMESPACE -class QGroupBox; -class QLineEdit; -class QPushButton; -class QTreeWidget; -class QTreeWidgetItem; -QT_END_NAMESPACE - -namespace Macros { -namespace Internal { - -class MacroOptionsWidget final : public Core::IOptionsPageWidget -{ - Q_OBJECT - -public: - MacroOptionsWidget(); - ~MacroOptionsWidget() final; - - void initialize(); - - void apply() final; - -private: - void remove(); - void changeCurrentItem(QTreeWidgetItem *current); - - void createTable(); - - void changeDescription(const QString &description); - -private: - QStringList m_macroToRemove; - bool m_changingCurrent = false; - - QMap m_macroToChange; - - QTreeWidget *m_treeWidget; - QPushButton *m_removeButton; - QGroupBox *m_macroGroup; - QLineEdit *m_description; -}; - -} // namespace Internal -} // namespace Macros diff --git a/src/plugins/macros/macros.qbs b/src/plugins/macros/macros.qbs index f6579c7394d..c975f756d7d 100644 --- a/src/plugins/macros/macros.qbs +++ b/src/plugins/macros/macros.qbs @@ -29,8 +29,6 @@ QtcPlugin { "macromanager.h", "macrooptionspage.cpp", "macrooptionspage.h", - "macrooptionswidget.cpp", - "macrooptionswidget.h", "macros.qrc", "macrosconstants.h", "macrosplugin.cpp", From 64c48af15be4fda6f39383fbf9f589c4df1d8bc4 Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 31 May 2023 18:04:22 +0200 Subject: [PATCH 076/141] ProjectManager: Auto-register build settings aspects Add the necessary contructor to TriStateAspect, too. Change-Id: Ieb0f19cdf95f7492380d7c4e5663f455e4da3452 Reviewed-by: Christian Stenger --- src/libs/utils/aspects.cpp | 5 ++++- src/libs/utils/aspects.h | 3 ++- .../debugger/debuggerrunconfigurationaspect.cpp | 4 ++-- .../projectexplorer/buildpropertiessettings.cpp | 8 ++------ src/plugins/projectexplorer/buildpropertiessettings.h | 10 +++++----- .../qmakeprojectmanager/qmakebuildconfiguration.cpp | 3 ++- 6 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/libs/utils/aspects.cpp b/src/libs/utils/aspects.cpp index bb637f31b02..3dc5da0a4b4 100644 --- a/src/libs/utils/aspects.cpp +++ b/src/libs/utils/aspects.cpp @@ -2162,8 +2162,11 @@ void DoubleAspect::setSingleStep(double step) Its visual representation is a QComboBox with three items. */ -TriStateAspect::TriStateAspect(const QString &onString, const QString &offString, +TriStateAspect::TriStateAspect(AspectContainer *container, + const QString &onString, + const QString &offString, const QString &defaultString) + : SelectionAspect(container) { setDisplayStyle(DisplayStyle::ComboBox); setDefaultValue(TriState::Default); diff --git a/src/libs/utils/aspects.h b/src/libs/utils/aspects.h index db3c036cec3..a0ebf5a045a 100644 --- a/src/libs/utils/aspects.h +++ b/src/libs/utils/aspects.h @@ -549,7 +549,8 @@ class QTCREATOR_UTILS_EXPORT TriStateAspect : public SelectionAspect Q_OBJECT public: - TriStateAspect(const QString &onString = {}, + TriStateAspect(AspectContainer *container = nullptr, + const QString &onString = {}, const QString &offString = {}, const QString &defaultString = {}); diff --git a/src/plugins/debugger/debuggerrunconfigurationaspect.cpp b/src/plugins/debugger/debuggerrunconfigurationaspect.cpp index 4b67e82fd86..8c118f553b6 100644 --- a/src/plugins/debugger/debuggerrunconfigurationaspect.cpp +++ b/src/plugins/debugger/debuggerrunconfigurationaspect.cpp @@ -101,11 +101,11 @@ DebuggerRunConfigurationAspect::DebuggerRunConfigurationAspect(Target *target) addDataExtractor(this, &DebuggerRunConfigurationAspect::useMultiProcess, &Data::useMultiProcess); addDataExtractor(this, &DebuggerRunConfigurationAspect::overrideStartup, &Data::overrideStartup); - m_cppAspect = new TriStateAspect(Tr::tr("Enabled"), Tr::tr("Disabled"), Tr::tr("Automatic")); + m_cppAspect = new TriStateAspect(nullptr, Tr::tr("Enabled"), Tr::tr("Disabled"), Tr::tr("Automatic")); m_cppAspect->setLabelText(Tr::tr("C++ debugger:")); m_cppAspect->setSettingsKey("RunConfiguration.UseCppDebugger"); - m_qmlAspect = new TriStateAspect(Tr::tr("Enabled"), Tr::tr("Disabled"), Tr::tr("Automatic")); + m_qmlAspect = new TriStateAspect(nullptr, Tr::tr("Enabled"), Tr::tr("Disabled"), Tr::tr("Automatic")); m_qmlAspect->setLabelText(Tr::tr("QML debugger:")); m_qmlAspect->setSettingsKey("RunConfiguration.UseQmlDebugger"); diff --git a/src/plugins/projectexplorer/buildpropertiessettings.cpp b/src/plugins/projectexplorer/buildpropertiessettings.cpp index 88c63b5f5c1..6df8fdd328e 100644 --- a/src/plugins/projectexplorer/buildpropertiessettings.cpp +++ b/src/plugins/projectexplorer/buildpropertiessettings.cpp @@ -16,8 +16,8 @@ namespace ProjectExplorer { const char DEFAULT_BUILD_DIRECTORY_TEMPLATE[] = "../%{JS: Util.asciify(\"build-%{Project:Name}-%{Kit:FileSystemName}-%{BuildConfig:Name}\")}"; -BuildPropertiesSettings::BuildTriStateAspect::BuildTriStateAspect() - : TriStateAspect{Tr::tr("Enable"), Tr::tr("Disable"), Tr::tr("Use Project Default")} +BuildPropertiesSettings::BuildTriStateAspect::BuildTriStateAspect(AspectContainer *container) + : TriStateAspect(container, Tr::tr("Enable"), Tr::tr("Disable"), Tr::tr("Use Project Default")) {} BuildPropertiesSettings::BuildPropertiesSettings() @@ -43,7 +43,6 @@ BuildPropertiesSettings::BuildPropertiesSettings() }; }); - registerAspect(&buildDirectoryTemplate); buildDirectoryTemplate.setDisplayStyle(StringAspect::LineEditDisplay); buildDirectoryTemplate.setSettingsKey("Directories/BuildDirectory.TemplateV2"); buildDirectoryTemplate.setDefaultValue(DEFAULT_BUILD_DIRECTORY_TEMPLATE); @@ -51,15 +50,12 @@ BuildPropertiesSettings::BuildPropertiesSettings() buildDirectoryTemplate.setUseGlobalMacroExpander(); buildDirectoryTemplate.setUseResetButton(); - registerAspect(&separateDebugInfo); separateDebugInfo.setSettingsKey("ProjectExplorer/Settings/SeparateDebugInfo"); separateDebugInfo.setLabelText(Tr::tr("Separate debug info:")); - registerAspect(&qmlDebugging); qmlDebugging.setSettingsKey("ProjectExplorer/Settings/QmlDebugging"); qmlDebugging.setLabelText(Tr::tr("QML debugging:")); - registerAspect(&qtQuickCompiler); qtQuickCompiler.setSettingsKey("ProjectExplorer/Settings/QtQuickCompiler"); qtQuickCompiler.setLabelText(Tr::tr("Use qmlcachegen:")); diff --git a/src/plugins/projectexplorer/buildpropertiessettings.h b/src/plugins/projectexplorer/buildpropertiessettings.h index 4d028788d51..3b1b2b7c698 100644 --- a/src/plugins/projectexplorer/buildpropertiessettings.h +++ b/src/plugins/projectexplorer/buildpropertiessettings.h @@ -17,13 +17,13 @@ public: class BuildTriStateAspect : public Utils::TriStateAspect { public: - BuildTriStateAspect(); + explicit BuildTriStateAspect(AspectContainer *container); }; - Utils::StringAspect buildDirectoryTemplate; - BuildTriStateAspect separateDebugInfo; - BuildTriStateAspect qmlDebugging; - BuildTriStateAspect qtQuickCompiler; + Utils::StringAspect buildDirectoryTemplate{this}; + BuildTriStateAspect separateDebugInfo{this}; + BuildTriStateAspect qmlDebugging{this}; + BuildTriStateAspect qtQuickCompiler{this}; Utils::BoolAspect showQtSettings; QString defaultBuildDirectoryTemplate(); diff --git a/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp b/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp index 173443958db..9da9f7f65a7 100644 --- a/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp +++ b/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp @@ -57,7 +57,8 @@ class RunSystemAspect : public TriStateAspect { Q_OBJECT public: - RunSystemAspect() : TriStateAspect(Tr::tr("Run"), Tr::tr("Ignore"), Tr::tr("Use global setting")) + RunSystemAspect() + : TriStateAspect(nullptr, Tr::tr("Run"), Tr::tr("Ignore"), Tr::tr("Use global setting")) { setSettingsKey("RunSystemFunction"); setDisplayName(Tr::tr("qmake system() behavior when parsing:")); From f4eff5f76d2ecf8dfd2c7987054512c3cbd25edf Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 25 May 2023 13:22:29 +0200 Subject: [PATCH 077/141] Core: Remove IOptionPage::setLayouter overload The one producing LayoutItems it sufficient nowadays. Task-number: QTCREATORBUG-29167 Change-Id: Iba50a0cf4f16a95dbe68ca01c42bda4ac5441f75 Reviewed-by: Reviewed-by: Alessandro Portale --- src/plugins/coreplugin/dialogs/ioptionspage.cpp | 9 --------- src/plugins/coreplugin/dialogs/ioptionspage.h | 1 - 2 files changed, 10 deletions(-) diff --git a/src/plugins/coreplugin/dialogs/ioptionspage.cpp b/src/plugins/coreplugin/dialogs/ioptionspage.cpp index 1912045af53..4def6095a11 100644 --- a/src/plugins/coreplugin/dialogs/ioptionspage.cpp +++ b/src/plugins/coreplugin/dialogs/ioptionspage.cpp @@ -199,15 +199,6 @@ void IOptionsPage::setSettings(AspectContainer *settings) m_settings = settings; } -void IOptionsPage::setLayouter(const std::function &layouter) -{ - m_widgetCreator = [layouter] { - auto widget = new IOptionsPageWidget; - layouter(widget); - return widget; - }; -} - void IOptionsPage::setLayouter(const std::function &layouter) { m_widgetCreator = [layouter] { diff --git a/src/plugins/coreplugin/dialogs/ioptionspage.h b/src/plugins/coreplugin/dialogs/ioptionspage.h index a38bf863c36..f4801b7c734 100644 --- a/src/plugins/coreplugin/dialogs/ioptionspage.h +++ b/src/plugins/coreplugin/dialogs/ioptionspage.h @@ -74,7 +74,6 @@ protected: void setCategoryIcon(const Utils::Icon &categoryIcon) { m_categoryIcon = categoryIcon; } void setCategoryIconPath(const Utils::FilePath &categoryIconPath); void setSettings(Utils::AspectContainer *settings); - void setLayouter(const std::function &layouter); void setLayouter(const std::function &layouter); // Used in FontSettingsPage. FIXME? From 1afa720f2cfee575096fc7f6afc5a0760496675b Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Thu, 1 Jun 2023 13:00:52 +0300 Subject: [PATCH 078/141] FilePath: Replace Q_OS_WINDOWS with Q_OS_WIN for consistency Change-Id: Ia624c804e54fe4c5213351078a7aa9c8dec9f262 Reviewed-by: hjk --- src/libs/utils/filepath.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/utils/filepath.cpp b/src/libs/utils/filepath.cpp index ad871413a22..9059a37ecc3 100644 --- a/src/libs/utils/filepath.cpp +++ b/src/libs/utils/filepath.cpp @@ -1914,7 +1914,7 @@ FilePath FilePath::canonicalPath() const return *this; } -#ifdef Q_OS_WINDOWS +#ifdef Q_OS_WIN DWORD flagsAndAttrs = FILE_ATTRIBUTE_NORMAL; if (isDir()) flagsAndAttrs |= FILE_FLAG_BACKUP_SEMANTICS; From d81d1bc14c08645749b0d5fda1675dd20a369ad2 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Thu, 1 Jun 2023 03:20:12 +0200 Subject: [PATCH 079/141] SilverSearcher: Make the search cancellable Especially when there are lot of files, and not too much results. Change-Id: Id9e89c5d0d681e11dd8a9fb5c2373164dbeef3fd Reviewed-by: Orgad Shaneh --- .../findinfilessilversearcher.cpp | 50 ++++++++++++------- .../silversearcher/silversearcherparser.cpp | 36 ++++++++++--- .../silversearcher/silversearcherparser.h | 16 +++++- 3 files changed, 76 insertions(+), 26 deletions(-) diff --git a/src/plugins/silversearcher/findinfilessilversearcher.cpp b/src/plugins/silversearcher/findinfilessilversearcher.cpp index 43397a03f6d..b7e26d071b1 100644 --- a/src/plugins/silversearcher/findinfilessilversearcher.cpp +++ b/src/plugins/silversearcher/findinfilessilversearcher.cpp @@ -16,6 +16,7 @@ #include using namespace Core; +using namespace SilverSearcher; using namespace TextEditor; using namespace Utils; @@ -58,6 +59,21 @@ static bool isSilverSearcherAvailable() && silverSearcherProcess.cleanedStdOut().contains("ag version"); } +static std::optional regExpFromParameters(const FileFindParameters ¶meters) +{ + if (!(parameters.flags & FindRegularExpression)) + return {}; + + const QRegularExpression::PatternOptions patternOptions + = (parameters.flags & FindCaseSensitively) + ? QRegularExpression::NoPatternOption + : QRegularExpression::CaseInsensitiveOption; + QRegularExpression regExp; + regExp.setPattern(parameters.text); + regExp.setPatternOptions(patternOptions); + return regExp; +} + static void runSilverSeacher(QPromise &promise, const FileFindParameters ¶meters) { @@ -92,26 +108,26 @@ static void runSilverSeacher(QPromise &promise, arguments << "--" << parameters.text << directory.normalizedPathName().toString(); + QEventLoop loop; + Process process; process.setCommand({"ag", arguments}); + ParserState parserState; + const std::optional regExp = regExpFromParameters(parameters); + process.setStdOutCallback([&promise, &parserState, regExp](const QString &output) { + SilverSearcher::parse(promise, output, &parserState, regExp); + }); + QObject::connect(&process, &Process::done, &loop, &QEventLoop::quit); + process.start(); - if (process.waitForFinished()) { - std::optional regExp; - if (parameters.flags & FindRegularExpression) { - regExp = QRegularExpression(); - const QRegularExpression::PatternOptions patternOptions - = (parameters.flags & FindCaseSensitively) - ? QRegularExpression::NoPatternOption - : QRegularExpression::CaseInsensitiveOption; - regExp->setPattern(parameters.text); - regExp->setPatternOptions(patternOptions); - } - const SearchResultItems items = SilverSearcher::parse(process.cleanedStdOut(), regExp); - if (!items.isEmpty()) - promise.addResult(items); - } else { - promise.future().cancel(); - } + if (process.state() == QProcess::NotRunning) + return; + + QFutureWatcher watcher; + QFuture future(promise.future()); + QObject::connect(&watcher, &QFutureWatcherBase::canceled, &loop, &QEventLoop::quit); + watcher.setFuture(future); + loop.exec(QEventLoop::ExcludeUserInputEvents); } } // namespace diff --git a/src/plugins/silversearcher/silversearcherparser.cpp b/src/plugins/silversearcher/silversearcherparser.cpp index be4e9096c4c..9cdf5211a67 100644 --- a/src/plugins/silversearcher/silversearcherparser.cpp +++ b/src/plugins/silversearcher/silversearcherparser.cpp @@ -3,6 +3,8 @@ #include "silversearcherparser.h" +#include + using namespace Utils; namespace SilverSearcher { @@ -94,23 +96,28 @@ static bool parseLineHits(QStringView *remainingInput, QList> *h return true; } -SearchResultItems parse(const QString &input, const std::optional ®Exp) +void parse(QPromise &promise, const QString &input, + ParserState *parserState, const std::optional ®Exp) { + QTC_ASSERT(parserState, return); SearchResultItems items; QStringView remainingInput(input); while (true) { + if (promise.isCanceled()) + return; + if (remainingInput.isEmpty()) break; const QStringView filePathLine = nextLine(&remainingInput); - if (filePathLine.isEmpty()) + if (filePathLine.isEmpty()) { + parserState->m_lastFilePath = {}; // Clear the parser state continue; + } - if (!filePathLine.startsWith(':')) - continue; - - const FilePath filePath = FilePath::fromPathPart(filePathLine.mid(1)); + if (filePathLine.startsWith(':')) + parserState->m_lastFilePath = FilePath::fromPathPart(filePathLine.mid(1)); while (true) { QStringView hitLine = nextLine(&remainingInput); @@ -126,7 +133,7 @@ SearchResultItems parse(const QString &input, const std::optionalm_lastFilePath); item.setDisplayText(hitLine.toString()); item.setUseTextEditorFont(true); for (const QPair &hit : hits) { @@ -138,7 +145,20 @@ SearchResultItems parse(const QString &input, const std::optionalm_reportedResultsCount += items.count(); +} + +SearchResultItems parse(const QString &input, const std::optional ®Exp) +{ + QPromise promise; + promise.start(); + ParserState dummy; + SilverSearcher::parse(promise, input, &dummy, regExp); + promise.finish(); + return promise.future().resultCount() ? promise.future().result() : SearchResultItems(); } } // namespace SilverSearcher diff --git a/src/plugins/silversearcher/silversearcherparser.h b/src/plugins/silversearcher/silversearcherparser.h index f9d8502759a..1cc5ccb773c 100644 --- a/src/plugins/silversearcher/silversearcherparser.h +++ b/src/plugins/silversearcher/silversearcherparser.h @@ -5,11 +5,25 @@ #include +#include #include +namespace Utils { class FilePath; } + namespace SilverSearcher { -Utils::SearchResultItems parse(const QString &output, +class ParserState +{ +public: + Utils::FilePath m_lastFilePath; + int m_reportedResultsCount = 0; +}; + +void parse(QPromise &promise, const QString &input, + ParserState *parserState = nullptr, + const std::optional ®Exp = {}); + +Utils::SearchResultItems parse(const QString &input, const std::optional ®Exp = {}); } // namespace SilverSearcher From 333cea6ef57acf0ae5b9c85793d89f406324ad55 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Wed, 31 May 2023 10:17:50 +0200 Subject: [PATCH 080/141] CppEditor: Handle semantic highlighting results in chunks Otherwise, we will format all tokens n+1 times, where n is the number of tokens following on the same line. This is because results trickle in one by one from clangd as of d6f5d07639c3d0313b758ba6fb7cc5eb57d188ef. Change-Id: I38aa2c4a26336f76219d182113bb838e1866fb8e Reviewed-by: Qt CI Bot Reviewed-by: David Schulz Reviewed-by: --- src/plugins/cppeditor/semantichighlighter.cpp | 18 ++++++++++++++++++ src/plugins/cppeditor/semantichighlighter.h | 3 +++ 2 files changed, 21 insertions(+) diff --git a/src/plugins/cppeditor/semantichighlighter.cpp b/src/plugins/cppeditor/semantichighlighter.cpp index c04b9270aa9..156a1d40524 100644 --- a/src/plugins/cppeditor/semantichighlighter.cpp +++ b/src/plugins/cppeditor/semantichighlighter.cpp @@ -64,6 +64,7 @@ void SemanticHighlighter::run() m_revision = documentRevision(); m_seenBlocks.clear(); + m_nextResultToHandle = m_resultCount = 0; qCDebug(log) << "starting runner for document revision" << m_revision; m_watcher->setFuture(m_highlightingRunner()); } @@ -92,6 +93,21 @@ void SemanticHighlighter::onHighlighterResultAvailable(int from, int to) return; } + QTC_CHECK(from == m_resultCount); + m_resultCount = to; + if (to - m_nextResultToHandle >= 100) { + handleHighlighterResults(); + m_nextResultToHandle = to; + } +} + +void SemanticHighlighter::handleHighlighterResults() +{ + int from = m_nextResultToHandle; + const int to = m_resultCount; + if (from >= to) + return; + QElapsedTimer t; t.start(); @@ -177,6 +193,8 @@ void SemanticHighlighter::onHighlighterFinished() { QTC_ASSERT(m_watcher, return); + handleHighlighterResults(); + QElapsedTimer t; t.start(); diff --git a/src/plugins/cppeditor/semantichighlighter.h b/src/plugins/cppeditor/semantichighlighter.h index fb1a704e6c3..ea49f289a01 100644 --- a/src/plugins/cppeditor/semantichighlighter.h +++ b/src/plugins/cppeditor/semantichighlighter.h @@ -67,6 +67,7 @@ public: private: void onHighlighterResultAvailable(int from, int to); + void handleHighlighterResults(); void onHighlighterFinished(); void connectWatcher(); @@ -82,6 +83,8 @@ private: QScopedPointer> m_watcher; QHash m_formatMap; std::set m_seenBlocks; + int m_nextResultToHandle = 0; + int m_resultCount = 0; HighlightingRunner m_highlightingRunner; }; From cd70d10dce8993d9923619aa4582b5c84a46b12e Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Thu, 1 Jun 2023 13:02:25 +0200 Subject: [PATCH 081/141] SilverSearcher: Don't crash on giant output from ag Make cancel and continue button working. Make pausing above 200000 hits working. Fixes: QTCREATORBUG-29130 Change-Id: I55429ae1b4d80dacfcd7e8366133657d0c44a0d6 Reviewed-by: Qt CI Bot Reviewed-by: Orgad Shaneh --- .../findinfilessilversearcher.cpp | 45 +++++++++++++++++-- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/src/plugins/silversearcher/findinfilessilversearcher.cpp b/src/plugins/silversearcher/findinfilessilversearcher.cpp index b7e26d071b1..7d9e5f1e141 100644 --- a/src/plugins/silversearcher/findinfilessilversearcher.cpp +++ b/src/plugins/silversearcher/findinfilessilversearcher.cpp @@ -114,10 +114,31 @@ static void runSilverSeacher(QPromise &promise, process.setCommand({"ag", arguments}); ParserState parserState; const std::optional regExp = regExpFromParameters(parameters); - process.setStdOutCallback([&promise, &parserState, regExp](const QString &output) { - SilverSearcher::parse(promise, output, &parserState, regExp); + QStringList outputBuffer; + // The states transition exactly in this order: + enum State { BelowLimit, AboveLimit, Paused, Resumed }; + State state = BelowLimit; + process.setStdOutCallback([&process, &loop, &promise, &state, &outputBuffer, &parserState, + regExp](const QString &output) { + if (promise.isCanceled()) { + process.close(); + loop.quit(); + return; + } + // The SearchResultWidget is going to pause the search anyway, so start buffering + // the output. + if (state == AboveLimit || state == Paused) { + outputBuffer.append(output); + } else { + SilverSearcher::parse(promise, output, &parserState, regExp); + if (state == BelowLimit && parserState.m_reportedResultsCount > 200000) + state = AboveLimit; + } + }); + QObject::connect(&process, &Process::done, &loop, [&loop, &promise, &state] { + if (state == BelowLimit || state == Resumed || promise.isCanceled()) + loop.quit(); }); - QObject::connect(&process, &Process::done, &loop, &QEventLoop::quit); process.start(); if (process.state() == QProcess::NotRunning) @@ -125,7 +146,23 @@ static void runSilverSeacher(QPromise &promise, QFutureWatcher watcher; QFuture future(promise.future()); - QObject::connect(&watcher, &QFutureWatcherBase::canceled, &loop, &QEventLoop::quit); + QObject::connect(&watcher, &QFutureWatcherBase::canceled, &loop, [&process, &loop] { + process.close(); + loop.quit(); + }); + QObject::connect(&watcher, &QFutureWatcherBase::paused, &loop, [&state] { state = Paused; }); + QObject::connect(&watcher, &QFutureWatcherBase::resumed, &loop, + [&process, &loop, &promise, &state, &outputBuffer, &parserState, regExp] { + state = Resumed; + for (const QString &output : outputBuffer) { + if (promise.isCanceled()) { + process.close(); + loop.quit(); + } + SilverSearcher::parse(promise, output, &parserState, regExp); + } + outputBuffer.clear(); + }); watcher.setFuture(future); loop.exec(QEventLoop::ExcludeUserInputEvents); } From fd7cb1181fc1651c2836f490894d8b582724c0e7 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Thu, 1 Jun 2023 16:02:26 +0200 Subject: [PATCH 082/141] Tasking: Fix qbs build Change-Id: I0ad1232a997a98902e6e9a7972f2af8e04a6b096 Reviewed-by: Jarek Kobus Reviewed-by: Qt CI Bot --- src/libs/solutions/tasking/tasktree.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/solutions/tasking/tasktree.h b/src/libs/solutions/tasking/tasktree.h index b4119219a1b..647c680b5b0 100644 --- a/src/libs/solutions/tasking/tasktree.h +++ b/src/libs/solutions/tasking/tasktree.h @@ -16,7 +16,7 @@ QT_END_NAMESPACE namespace Tasking { -Q_NAMESPACE +Q_NAMESPACE_EXPORT(TASKING_EXPORT) class ExecutionContextActivator; class TaskContainer; From 0ccdb4a54732930006dc0a0ba5eeb150aafc4ec9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20L=C3=B6hning?= Date: Wed, 31 May 2023 23:29:10 +0200 Subject: [PATCH 083/141] German translation: Don't use title case for "Configure Project" button It looks odd and seems to be inconsistent. Change-Id: I5c0a075edc27c526aa445f31d031dd234cdc2ccd Reviewed-by: Eike Ziller Reviewed-by: Qt CI Patch Build Bot Reviewed-by: --- share/qtcreator/translations/qtcreator_de.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/qtcreator/translations/qtcreator_de.ts b/share/qtcreator/translations/qtcreator_de.ts index ee6e08a335c..f4886dc760d 100644 --- a/share/qtcreator/translations/qtcreator_de.ts +++ b/share/qtcreator/translations/qtcreator_de.ts @@ -39108,7 +39108,7 @@ Sie werden erhalten. &Configure Project - Projekt &Konfigurieren + Projekt &konfigurieren Enable Kit for Project "%1" From 629e6ab945da5afeed1fff9c203cd15f6634016f Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 1 Jun 2023 13:58:35 +0200 Subject: [PATCH 084/141] Use a few more explicit FilePathAspects Change-Id: I97431306754af3ea7a803021db7b876c31abc940 Reviewed-by: Alessandro Portale Reviewed-by: --- src/plugins/python/pythonwizardpage.cpp | 1 - src/plugins/python/pythonwizardpage.h | 2 +- src/plugins/remotelinux/makeinstallstep.cpp | 3 +-- .../remotelinux/remotelinuxcustomrunconfiguration.cpp | 3 +-- src/plugins/terminal/terminalsettings.cpp | 1 - src/plugins/terminal/terminalsettings.h | 2 +- src/plugins/vcsbase/commonvcssettings.cpp | 4 ---- src/plugins/vcsbase/commonvcssettings.h | 8 ++++---- 8 files changed, 8 insertions(+), 16 deletions(-) diff --git a/src/plugins/python/pythonwizardpage.cpp b/src/plugins/python/pythonwizardpage.cpp index d132f3550c7..bcbca5a7072 100644 --- a/src/plugins/python/pythonwizardpage.cpp +++ b/src/plugins/python/pythonwizardpage.cpp @@ -102,7 +102,6 @@ PythonWizardPage::PythonWizardPage(const QList> &pySide m_createVenv.setLabelText(Tr::tr("Create new Virtual Environment")); m_venvPath.setLabelText(Tr::tr("Path to virtual environment")); - m_venvPath.setDisplayStyle(StringAspect::PathChooserDisplay); m_venvPath.setEnabler(&m_createVenv); m_venvPath.setExpectedKind(PathChooser::Directory); diff --git a/src/plugins/python/pythonwizardpage.h b/src/plugins/python/pythonwizardpage.h index 1d605b24176..6cf8a130c59 100644 --- a/src/plugins/python/pythonwizardpage.h +++ b/src/plugins/python/pythonwizardpage.h @@ -36,7 +36,7 @@ private: ProjectExplorer::InterpreterAspect m_interpreter; Utils::SelectionAspect m_pySideVersion; Utils::BoolAspect m_createVenv; - Utils::StringAspect m_venvPath; + Utils::FilePathAspect m_venvPath; Utils::InfoLabel *m_stateLabel = nullptr; }; diff --git a/src/plugins/remotelinux/makeinstallstep.cpp b/src/plugins/remotelinux/makeinstallstep.cpp index d1be1051452..42f0467c947 100644 --- a/src/plugins/remotelinux/makeinstallstep.cpp +++ b/src/plugins/remotelinux/makeinstallstep.cpp @@ -70,10 +70,9 @@ MakeInstallStep::MakeInstallStep(BuildStepList *parent, Id id) : MakeStep(parent connect(makeAspect, &ExecutableAspect::changed, this, &MakeInstallStep::updateCommandFromAspect); - const auto installRootAspect = addAspect(); + const auto installRootAspect = addAspect(); installRootAspect->setId(InstallRootAspectId); installRootAspect->setSettingsKey(InstallRootAspectId); - installRootAspect->setDisplayStyle(StringAspect::PathChooserDisplay); installRootAspect->setExpectedKind(PathChooser::Directory); installRootAspect->setLabelText(Tr::tr("Install root:")); installRootAspect->setFilePath(rootPath); diff --git a/src/plugins/remotelinux/remotelinuxcustomrunconfiguration.cpp b/src/plugins/remotelinux/remotelinuxcustomrunconfiguration.cpp index 36e4b0bda24..fd6f75c0761 100644 --- a/src/plugins/remotelinux/remotelinuxcustomrunconfiguration.cpp +++ b/src/plugins/remotelinux/remotelinuxcustomrunconfiguration.cpp @@ -41,10 +41,9 @@ RemoteLinuxCustomRunConfiguration::RemoteLinuxCustomRunConfiguration(Target *tar exeAspect->setHistoryCompleter("RemoteLinux.CustomExecutable.History"); exeAspect->setExpectedKind(PathChooser::Any); - auto symbolsAspect = addAspect(); + auto symbolsAspect = addAspect(); symbolsAspect->setSettingsKey("RemoteLinux.CustomRunConfig.LocalExecutable"); symbolsAspect->setLabelText(Tr::tr("Local executable:")); - symbolsAspect->setDisplayStyle(SymbolFileAspect::PathChooserDisplay); addAspect(macroExpander()); addAspect(macroExpander(), envAspect); diff --git a/src/plugins/terminal/terminalsettings.cpp b/src/plugins/terminal/terminalsettings.cpp index 99e0de0d1f8..06903c4d4c5 100644 --- a/src/plugins/terminal/terminalsettings.cpp +++ b/src/plugins/terminal/terminalsettings.cpp @@ -399,7 +399,6 @@ TerminalSettings::TerminalSettings() shell.setSettingsKey("ShellPath"); shell.setLabelText(Tr::tr("Shell path:")); shell.setExpectedKind(PathChooser::ExistingCommand); - shell.setDisplayStyle(StringAspect::PathChooserDisplay); shell.setHistoryCompleter("Terminal.Shell.History"); shell.setToolTip(Tr::tr("The shell executable to be started.")); shell.setDefaultValue(defaultShell()); diff --git a/src/plugins/terminal/terminalsettings.h b/src/plugins/terminal/terminalsettings.h index 30212b0c3de..4550bbce2a2 100644 --- a/src/plugins/terminal/terminalsettings.h +++ b/src/plugins/terminal/terminalsettings.h @@ -18,7 +18,7 @@ public: Utils::StringAspect font{this}; Utils::IntegerAspect fontSize{this}; - Utils::StringAspect shell{this}; + Utils::FilePathAspect shell{this}; Utils::StringAspect shellArguments{this}; Utils::ColorAspect foregroundColor; diff --git a/src/plugins/vcsbase/commonvcssettings.cpp b/src/plugins/vcsbase/commonvcssettings.cpp index e33de123790..d286164b5b9 100644 --- a/src/plugins/vcsbase/commonvcssettings.cpp +++ b/src/plugins/vcsbase/commonvcssettings.cpp @@ -39,7 +39,6 @@ CommonVcsSettings::CommonVcsSettings() setAutoApply(false); nickNameMailMap.setSettingsKey("NickNameMailMap"); - nickNameMailMap.setDisplayStyle(StringAspect::PathChooserDisplay); nickNameMailMap.setExpectedKind(PathChooser::File); nickNameMailMap.setHistoryCompleter("Vcs.NickMap.History"); nickNameMailMap.setLabelText(Tr::tr("User/&alias configuration file:")); @@ -47,7 +46,6 @@ CommonVcsSettings::CommonVcsSettings() "'name alias '.")); nickNameFieldListFile.setSettingsKey("NickNameFieldListFile"); - nickNameFieldListFile.setDisplayStyle(StringAspect::PathChooserDisplay); nickNameFieldListFile.setExpectedKind(PathChooser::File); nickNameFieldListFile.setHistoryCompleter("Vcs.NickFields.History"); nickNameFieldListFile.setLabelText(Tr::tr("User &fields configuration file:")); @@ -55,7 +53,6 @@ CommonVcsSettings::CommonVcsSettings() "\"Reviewed-By:\" which will be added below the submit editor.")); submitMessageCheckScript.setSettingsKey("SubmitMessageCheckScript"); - submitMessageCheckScript.setDisplayStyle(StringAspect::PathChooserDisplay); submitMessageCheckScript.setExpectedKind(PathChooser::ExistingCommand); submitMessageCheckScript.setHistoryCompleter("Vcs.MessageCheckScript.History"); submitMessageCheckScript.setLabelText(Tr::tr("Submit message &check script:")); @@ -64,7 +61,6 @@ CommonVcsSettings::CommonVcsSettings() "on standard error to indicate failure.")); sshPasswordPrompt.setSettingsKey("SshPasswordPrompt"); - sshPasswordPrompt.setDisplayStyle(StringAspect::PathChooserDisplay); sshPasswordPrompt.setExpectedKind(PathChooser::ExistingCommand); sshPasswordPrompt.setHistoryCompleter("Vcs.SshPrompt.History"); sshPasswordPrompt.setDefaultValue(sshPasswordPromptDefault()); diff --git a/src/plugins/vcsbase/commonvcssettings.h b/src/plugins/vcsbase/commonvcssettings.h index 44bf03c5776..a5005f252a5 100644 --- a/src/plugins/vcsbase/commonvcssettings.h +++ b/src/plugins/vcsbase/commonvcssettings.h @@ -16,13 +16,13 @@ class CommonVcsSettings : public Utils::AspectContainer public: CommonVcsSettings(); - Utils::StringAspect nickNameMailMap{this}; - Utils::StringAspect nickNameFieldListFile{this}; + Utils::FilePathAspect nickNameMailMap{this}; + Utils::FilePathAspect nickNameFieldListFile{this}; - Utils::StringAspect submitMessageCheckScript{this}; + Utils::FilePathAspect submitMessageCheckScript{this}; // Executable run to graphically prompt for a SSH-password. - Utils::StringAspect sshPasswordPrompt{this}; + Utils::FilePathAspect sshPasswordPrompt{this}; Utils::BoolAspect lineWrap{this}; Utils::IntegerAspect lineWrapWidth{this}; From db4dd91caf7e72566b2d6f4e829a9b7cd8d1b514 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 1 Jun 2023 12:02:13 +0200 Subject: [PATCH 085/141] FakeVim: Streamline settings handling a bit Change-Id: I6ab2c1643a5236525515ded296cd854933584603 Reviewed-by: Alessandro Portale --- src/plugins/fakevim/fakevimactions.cpp | 10 ++- src/plugins/fakevim/fakevimactions.h | 8 +-- src/plugins/fakevim/fakevimhandler.cpp | 84 +++++++++++++------------- src/plugins/fakevim/fakevimplugin.cpp | 50 ++++++--------- 4 files changed, 66 insertions(+), 86 deletions(-) diff --git a/src/plugins/fakevim/fakevimactions.cpp b/src/plugins/fakevim/fakevimactions.cpp index b753939c056..916fea16097 100644 --- a/src/plugins/fakevim/fakevimactions.cpp +++ b/src/plugins/fakevim/fakevimactions.cpp @@ -25,8 +25,7 @@ using namespace Utils; -namespace FakeVim { -namespace Internal { +namespace FakeVim::Internal { #ifdef FAKEVIM_STANDALONE FvBaseAspect::FvBaseAspect() @@ -72,9 +71,9 @@ void setAutoApply(bool ) {} static FakeVimSettings *s_settings; -FakeVimSettings *fakeVimSettings() +FakeVimSettings &settings() { - return s_settings; + return *s_settings; } FakeVimSettings::FakeVimSettings() @@ -327,5 +326,4 @@ void FakeVimSettings::setup(FvBaseAspect *aspect, m_nameToAspect[shortName] = aspect; } -} // namespace Internal -} // namespace FakeVim +} // FakeVim::Internal diff --git a/src/plugins/fakevim/fakevimactions.h b/src/plugins/fakevim/fakevimactions.h index 2f3f72f6951..e3b14b0d47a 100644 --- a/src/plugins/fakevim/fakevimactions.h +++ b/src/plugins/fakevim/fakevimactions.h @@ -13,8 +13,7 @@ #include #include -namespace FakeVim { -namespace Internal { +namespace FakeVim::Internal { #ifdef FAKEVIM_STANDALONE class FvBaseAspect @@ -145,7 +144,6 @@ private: QHash m_aspectToName; }; -FakeVimSettings *fakeVimSettings(); +FakeVimSettings &settings(); -} // namespace Internal -} // namespace FakeVim +} // FakeVim::Internal diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp index 2eb052432cf..edfa315af98 100644 --- a/src/plugins/fakevim/fakevimhandler.cpp +++ b/src/plugins/fakevim/fakevimhandler.cpp @@ -408,9 +408,8 @@ static QRegularExpression vimPatternToQtPattern(const QString &needle) */ // FIXME: Option smartcase should be used only if search was typed by user. - const bool ignoreCaseOption = fakeVimSettings()->ignoreCase.value(); - const bool smartCaseOption = fakeVimSettings()->smartCase.value(); - const bool initialIgnoreCase = ignoreCaseOption + const bool smartCaseOption = settings().smartCase(); + const bool initialIgnoreCase = settings().ignoreCase() && !(smartCaseOption && needle.contains(QRegularExpression("[A-Z]"))); bool ignorecase = initialIgnoreCase; @@ -2373,7 +2372,7 @@ public: QString surroundFunction; // Used for storing the function name provided to ys{motion}f } g; - FakeVimSettings &s = *fakeVimSettings(); + FakeVimSettings &s = settings(); }; static void initSingleShotTimer(QTimer *timer, @@ -2527,7 +2526,7 @@ void FakeVimHandler::Private::leaveFakeVim(bool needUpdate) // The command might have destroyed the editor. if (m_textedit || m_plaintextedit) { - if (s.showMarks.value()) + if (s.showMarks()) updateSelection(); updateMiniBuffer(); @@ -2576,7 +2575,7 @@ bool FakeVimHandler::Private::wantsOverride(QKeyEvent *ev) // We are interested in overriding most Ctrl key combinations. if (isOnlyControlModifier(mods) - && !s.passControlKey.value() + && !s.passControlKey() && ((key >= Key_A && key <= Key_Z && key != Key_K) || key == Key_BracketLeft || key == Key_BracketRight)) { // Ctrl-K is special as it is the Core's default notion of Locator @@ -3059,7 +3058,7 @@ void FakeVimHandler::Private::stopIncrementalFind() void FakeVimHandler::Private::updateFind(bool isComplete) { - if (!isComplete && !s.incSearch.value()) + if (!isComplete && !s.incSearch()) return; g.currentMessage.clear(); @@ -3161,7 +3160,7 @@ void FakeVimHandler::Private::pushUndoState(bool overwrite) pos = firstPositionInLine(lineForPosition(pos)); else if (isVisualBlockMode()) pos = blockAt(pos).position() + qMin(columnAt(anchor()), columnAt(position())); - } else if (g.movetype == MoveLineWise && s.startOfLine.value()) { + } else if (g.movetype == MoveLineWise && s.startOfLine()) { QTextCursor tc = m_cursor; if (g.submode == ShiftLeftSubMode || g.submode == ShiftRightSubMode || g.submode == IndentSubMode) { @@ -3621,7 +3620,7 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommandMovement) return; } else if (g.submode == ExchangeSubMode) { exchangeRange(currentRange()); - } else if (g.submode == ReplaceWithRegisterSubMode && s.emulateReplaceWithRegister.value()) { + } else if (g.submode == ReplaceWithRegisterSubMode && s.emulateReplaceWithRegister()) { pushUndoState(false); beginEditBlock(); replaceWithRegister(currentRange()); @@ -3734,7 +3733,7 @@ void FakeVimHandler::Private::clearCurrentMode() void FakeVimHandler::Private::updateSelection() { QList selections = m_extraSelections; - if (s.showMarks.value()) { + if (s.showMarks()) { for (auto it = m_buffer->marks.cbegin(), end = m_buffer->marks.cend(); it != end; ++it) { QTextEdit::ExtraSelection sel; sel.cursor = m_cursor; @@ -3753,7 +3752,7 @@ void FakeVimHandler::Private::updateSelection() void FakeVimHandler::Private::updateHighlights() { - if (s.useCoreSearch.value() || !s.hlSearch.value() || g.highlightsCleared) { + if (s.useCoreSearch() || !s.hlSearch() || g.highlightsCleared) { if (m_highlighted.isEmpty()) return; m_highlighted.clear(); @@ -3800,7 +3799,7 @@ void FakeVimHandler::Private::updateMiniBuffer() } else if (!g.mapStates.isEmpty() && !g.mapStates.last().silent) { // Do not reset previous message when after running a mapped command. return; - } else if (g.mode == CommandMode && !g.currentCommand.isEmpty() && s.showCmd.value()) { + } else if (g.mode == CommandMode && !g.currentCommand.isEmpty() && s.showCmd()) { msg = g.currentCommand; messageLevel = MessageShowCmd; } else if (g.mode == CommandMode && isVisualMode()) { @@ -3907,7 +3906,7 @@ bool FakeVimHandler::Private::handleCommandSubSubMode(const Input &input) handled = selectBlockTextObject(g.subsubdata.is('i'), '{', '}'); else if (input.is('"') || input.is('\'') || input.is('`')) handled = selectQuotedStringTextObject(g.subsubdata.is('i'), input.asChar()); - else if (input.is('a') && s.emulateArgTextObj.value()) + else if (input.is('a') && s.emulateArgTextObj()) handled = selectArgumentTextObject(g.subsubdata.is('i')); else handled = false; @@ -4050,7 +4049,7 @@ bool FakeVimHandler::Private::handleMovement(const Input &input) g.subsubmode = NoSubSubMode; } else if (input.is('/') || input.is('?')) { g.lastSearchForward = input.is('/'); - if (s.useCoreSearch.value()) { + if (s.useCoreSearch()) { // re-use the core dialog. g.findPending = true; m_findStartPosition = position(); @@ -4225,7 +4224,7 @@ bool FakeVimHandler::Private::handleMovement(const Input &input) m_cursor = EDITOR(cursorForPosition(QPoint(0, EDITOR(height()) / 2))); handleStartOfLine(); } else if (input.is('n') || input.is('N')) { - if (s.useCoreSearch.value()) { + if (s.useCoreSearch()) { bool forward = (input.is('n')) ? g.lastSearchForward : !g.lastSearchForward; int pos = position(); q->findNextRequested(!forward); @@ -4314,7 +4313,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(const Input &input) handled = handleNoSubMode(input); } else if (g.submode == ExchangeSubMode) { handled = handleExchangeSubMode(input); - } else if (g.submode == ChangeSubMode && input.is('x') && s.emulateExchange.value()) { + } else if (g.submode == ChangeSubMode && input.is('x') && s.emulateExchange()) { // Exchange submode is "cx", so we need to switch over from ChangeSubMode here g.submode = ExchangeSubMode; handled = true; @@ -4324,15 +4323,15 @@ EventResult FakeVimHandler::Private::handleCommandMode(const Input &input) } else if (g.submode == AddSurroundingSubMode) { handled = handleAddSurroundingSubMode(input); } else if (g.submode == ChangeSubMode && (input.is('s') || input.is('S')) - && s.emulateSurround.value()) { + && s.emulateSurround()) { g.submode = ChangeSurroundingSubMode; g.surroundUpperCaseS = input.is('S'); handled = true; - } else if (g.submode == DeleteSubMode && input.is('s') && s.emulateSurround.value()) { + } else if (g.submode == DeleteSubMode && input.is('s') && s.emulateSurround()) { g.submode = DeleteSurroundingSubMode; handled = true; } else if (g.submode == YankSubMode && (input.is('s') || input.is('S')) - && s.emulateSurround.value()) { + && s.emulateSurround()) { g.submode = AddSurroundingSubMode; g.movetype = MoveInclusive; g.surroundUpperCaseS = input.is('S'); @@ -4341,10 +4340,9 @@ EventResult FakeVimHandler::Private::handleCommandMode(const Input &input) || g.submode == DeleteSubMode || g.submode == YankSubMode) { handled = handleChangeDeleteYankSubModes(input); - } else if (g.submode == CommentSubMode && s.emulateVimCommentary.value()) { + } else if (g.submode == CommentSubMode && s.emulateVimCommentary()) { handled = handleCommentSubMode(input); - } else if (g.submode == ReplaceWithRegisterSubMode - && s.emulateReplaceWithRegister.value()) { + } else if (g.submode == ReplaceWithRegisterSubMode && s.emulateReplaceWithRegister()) { handled = handleReplaceWithRegisterSubMode(input); } else if (g.submode == ReplaceSubMode) { handled = handleReplaceSubMode(input); @@ -4487,7 +4485,7 @@ bool FakeVimHandler::Private::handleNoSubMode(const Input &input) setTargetColumn(); } else if (input.isControl('a')) { changeNumberTextObject(count()); - } else if (g.gflag && input.is('c') && s.emulateVimCommentary.value()) { + } else if (g.gflag && input.is('c') && s.emulateVimCommentary()) { if (isVisualMode()) { pushUndoState(); @@ -4512,7 +4510,7 @@ bool FakeVimHandler::Private::handleNoSubMode(const Input &input) pushUndoState(); setAnchor(); } - } else if (g.gflag && input.is('r') && s.emulateReplaceWithRegister.value()) { + } else if (g.gflag && input.is('r') && s.emulateReplaceWithRegister()) { g.submode = ReplaceWithRegisterSubMode; if (isVisualMode()) { dotCommand = visualDotCommand() + QString::number(count()) + "gr"; @@ -4671,7 +4669,7 @@ bool FakeVimHandler::Private::handleNoSubMode(const Input &input) int repeat = count(); while (--repeat >= 0) redo(); - } else if (input.is('S') && isVisualMode() && s.emulateSurround.value()) { + } else if (input.is('S') && isVisualMode() && s.emulateSurround()) { g.submode = AddSurroundingSubMode; g.subsubmode = SurroundSubSubMode; } else if (input.is('s')) { @@ -4756,7 +4754,7 @@ bool FakeVimHandler::Private::handleNoSubMode(const Input &input) if (isVisualMode()) { leaveVisualMode(); finishMovement(); - } else if (g.gflag || (g.submode == InvertCaseSubMode && s.tildeOp.value())) { + } else if (g.gflag || (g.submode == InvertCaseSubMode && s.tildeOp())) { if (atEndOfLine()) moveLeft(); setAnchor(); @@ -5404,8 +5402,8 @@ void FakeVimHandler::Private::handleInsertMode(const Input &input) if (!handleInsertInEditor(Input(Qt::Key_Backspace, Qt::NoModifier))) { joinPreviousEditBlock(); if (!m_buffer->lastInsertion.isEmpty() - || s.backspace.value().contains("start") - || s.backspace.value().contains("2")) { + || s.backspace().contains("start") + || s.backspace().contains("2")) { const int line = cursorLine() + 1; const Column col = cursorColumn(); QString data = lineContents(line); @@ -5438,7 +5436,7 @@ void FakeVimHandler::Private::handleInsertMode(const Input &input) } else if (input.isKey(Key_Tab)) { if (q->tabPressedInInsertMode()) { m_buffer->insertState.insertingSpaces = true; - if (s.expandTab.value()) { + if (s.expandTab()) { const int ts = s.tabStop(); const int col = logicalCursorColumn(); QString str = QString(ts - col % ts, ' '); @@ -5494,7 +5492,7 @@ void FakeVimHandler::Private::insertInInsertMode(const QString &text) { joinPreviousEditBlock(); insertText(text); - if (s.smartIndent.value() && isElectricCharacter(text.at(0))) { + if (s.smartIndent() && isElectricCharacter(text.at(0))) { const QString leftText = block().text() .left(position() - 1 - block().position()); if (leftText.simplified().isEmpty()) { @@ -6265,7 +6263,7 @@ bool FakeVimHandler::Private::handleExMoveCommand(const ExCommand &cmd) if (!insertAtEnd) moveUp(1); - if (s.startOfLine.value()) + if (s.startOfLine()) moveToFirstNonBlankOnLine(); if (lastAnchor.line >= startLine && lastAnchor.line <= endLine) @@ -6794,7 +6792,7 @@ QTextCursor FakeVimHandler::Private::search(const SearchData &sd, int startPos, } if (tc.isNull()) { - if (s.wrapScan.value()) { + if (s.wrapScan()) { tc = QTextCursor(document()); tc.movePosition(sd.forward ? StartOfDocument : EndOfDocument); if (sd.forward) @@ -6954,7 +6952,7 @@ void FakeVimHandler::Private::shiftRegionRight(int repeat) std::swap(beginLine, endLine); targetPos = position(); } - if (s.startOfLine.value()) + if (s.startOfLine()) targetPos = firstPositionInLine(beginLine); const int sw = s.shiftWidth(); @@ -7106,7 +7104,7 @@ void FakeVimHandler::Private::setupCharClass() const QChar c = QLatin1Char(i); m_charClass[i] = c.isSpace() ? 0 : 1; } - const QString conf = s.isKeyword.value(); + const QString conf = s.isKeyword(); for (const QString &part : conf.split(',')) { if (part.contains('-')) { const int from = someInt(part.section('-', 0, 0)); @@ -7594,7 +7592,7 @@ void FakeVimHandler::Private::transformText(const Range &range, const Transforma void FakeVimHandler::Private::insertText(QTextCursor &tc, const QString &text) { - if (s.passKeys.value()) { + if (s.passKeys()) { if (tc.hasSelection() && text.isEmpty()) { QKeyEvent event(QEvent::KeyPress, Qt::Key_Delete, Qt::NoModifier, QString()); passEventToEditor(event, tc); @@ -7937,7 +7935,7 @@ void FakeVimHandler::Private::joinLines(int count, bool preserveSpace) moveRight(); // If the line we started from is a comment, remove the comment string from the next line - if (startingLineIsComment && s.formatOptions.value().contains('f')) { + if (startingLineIsComment && s.formatOptions().contains('f')) { if (characterAtCursor() == '/' && characterAt(position() + 1) == '/') moveRight(2); else if (characterAtCursor() == '*' || characterAtCursor() == '#') @@ -7955,7 +7953,7 @@ void FakeVimHandler::Private::joinLines(int count, bool preserveSpace) void FakeVimHandler::Private::insertNewLine() { - if (m_buffer->editBlockLevel <= 1 && s.passKeys.value()) { + if (m_buffer->editBlockLevel <= 1 && s.passKeys()) { QKeyEvent event(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier, "\n"); if (passEventToEditor(event, m_cursor)) return; @@ -7967,7 +7965,7 @@ void FakeVimHandler::Private::insertNewLine() bool FakeVimHandler::Private::handleInsertInEditor(const Input &input) { - if (m_buffer->editBlockLevel > 0 || !s.passKeys.value()) + if (m_buffer->editBlockLevel > 0 || !s.passKeys()) return false; joinPreviousEditBlock(); @@ -8712,10 +8710,10 @@ QString FakeVimHandler::Private::tabExpand(int n) const void FakeVimHandler::Private::insertAutomaticIndentation(bool goingDown, bool forceAutoIndent) { - if (!forceAutoIndent && !s.autoIndent.value() && !s.smartIndent.value()) + if (!forceAutoIndent && !s.autoIndent() && !s.smartIndent()) return; - if (s.smartIndent.value()) { + if (s.smartIndent()) { QTextBlock bl = block(); Range range(bl.position(), bl.position()); indentText(range, '\n'); @@ -8734,7 +8732,7 @@ void FakeVimHandler::Private::insertAutomaticIndentation(bool goingDown, bool fo void FakeVimHandler::Private::handleStartOfLine() { - if (s.startOfLine.value()) + if (s.startOfLine()) moveToFirstNonBlankOnLine(); } @@ -9331,7 +9329,7 @@ void FakeVimHandler::Private::getRegisterType(int *reg, bool *isClipboard, bool *reg = c.toLower().unicode(); if (c == '"') { - QStringList list = s.clipboard.value().split(','); + QStringList list = s.clipboard().split(','); clipboard = list.contains("unnamedplus"); selection = list.contains("unnamed"); } else if (c == '+') { @@ -9385,7 +9383,7 @@ void FakeVimHandler::updateGlobalMarksFilenames(const QString &oldFileName, cons bool FakeVimHandler::eventFilter(QObject *ob, QEvent *ev) { #ifndef FAKEVIM_STANDALONE - if (!fakeVimSettings()->useFakeVim.value()) + if (!settings().useFakeVim()) return QObject::eventFilter(ob, ev); #endif diff --git a/src/plugins/fakevim/fakevimplugin.cpp b/src/plugins/fakevim/fakevimplugin.cpp index c0e908ed573..54ae4ca93f8 100644 --- a/src/plugins/fakevim/fakevimplugin.cpp +++ b/src/plugins/fakevim/fakevimplugin.cpp @@ -379,7 +379,6 @@ public: int cursorPos, int anchorPos, int messageLevel); void handleExCommand(FakeVimHandler *handler, bool *handled, const ExCommand &cmd); - void writeSettings(); void readSettings(); void handleDelayedQuitAll(bool forced); @@ -1051,7 +1050,7 @@ void FakeVimPluginPrivate::initialize() Command *cmd = nullptr; - cmd = ActionManager::registerAction(fakeVimSettings()->useFakeVim.action(), + cmd = ActionManager::registerAction(settings().useFakeVim.action(), INSTALL_HANDLER, Context(Core::Constants::C_GLOBAL), true); cmd->setDefaultKeySequence(QKeySequence(useMacShortcuts ? Tr::tr("Meta+Shift+Y,Meta+Shift+Y") : Tr::tr("Alt+Y,Alt+Y"))); @@ -1089,7 +1088,7 @@ void FakeVimPluginPrivate::initialize() connect(DocumentManager::instance(), &DocumentManager::documentRenamed, this, &FakeVimPluginPrivate::documentRenamed); - FakeVimSettings &s = *fakeVimSettings(); + FakeVimSettings &s = settings(); connect(&s.useFakeVim, &FvBoolAspect::valueChanged, this, &FakeVimPluginPrivate::setUseFakeVim); connect(&s.readVimRc, &FvBaseAspect::changed, @@ -1107,7 +1106,7 @@ void FakeVimPluginPrivate::initialize() connect(this, &FakeVimPluginPrivate::delayedQuitAllRequested, this, &FakeVimPluginPrivate::handleDelayedQuitAll, Qt::QueuedConnection); - setCursorBlinking(s.blinkingCursor.value()); + setCursorBlinking(s.blinkingCursor()); } void FakeVimPluginPrivate::userActionTriggered(int key) @@ -1116,7 +1115,7 @@ void FakeVimPluginPrivate::userActionTriggered(int key) FakeVimHandler *handler = m_editorToHandler[editor].handler; if (handler) { // If disabled, enable FakeVim mode just for single user command. - bool enableFakeVim = !fakeVimSettings()->useFakeVim.value(); + bool enableFakeVim = !settings().useFakeVim(); if (enableFakeVim) setUseFakeVimInternal(true); @@ -1142,26 +1141,18 @@ void FakeVimPluginPrivate::createRelativeNumberWidget(IEditor *editor) { if (auto textEditor = TextEditorWidget::fromEditor(editor)) { auto relativeNumbers = new RelativeNumbersColumn(textEditor); - connect(&fakeVimSettings()->relativeNumber, &FvBaseAspect::changed, + connect(&settings().relativeNumber, &FvBaseAspect::changed, relativeNumbers, &QObject::deleteLater); - connect(&fakeVimSettings()->useFakeVim, &FvBaseAspect::changed, + connect(&settings().useFakeVim, &FvBaseAspect::changed, relativeNumbers, &QObject::deleteLater); relativeNumbers->show(); } } -void FakeVimPluginPrivate::writeSettings() -{ - QSettings *settings = ICore::settings(); - fakeVimSettings()->writeSettings(settings); -} - void FakeVimPluginPrivate::readSettings() { QSettings *settings = ICore::settings(); - fakeVimSettings()->readSettings(settings); - m_exCommandMap = m_defaultExCommandMap; int size = settings->beginReadArray(exCommandMapGroup); for (int i = 0; i < size; ++i) { @@ -1190,9 +1181,9 @@ void FakeVimPluginPrivate::maybeReadVimRc() //qDebug() << theFakeVimSetting(ConfigReadVimRc) // << theFakeVimSetting(ConfigReadVimRc)->value(); //qDebug() << theFakeVimSetting(ConfigShiftWidth)->value(); - if (!fakeVimSettings()->readVimRc.value()) + if (!settings().readVimRc()) return; - QString fileName = fakeVimSettings()->vimRcPath.value(); + QString fileName = settings().vimRcPath(); if (fileName.isEmpty()) { fileName = QStandardPaths::writableLocation(QStandardPaths::HomeLocation) + QLatin1String(HostOsInfo::isWindowsHost() ? "/_vimrc" : "/.vimrc"); @@ -1202,7 +1193,6 @@ void FakeVimPluginPrivate::maybeReadVimRc() QPlainTextEdit editor; FakeVimHandler handler(&editor); handler.handleCommand("source " + fileName); - //writeSettings(); //qDebug() << theFakeVimSetting(ConfigShiftWidth)->value(); } @@ -1531,9 +1521,9 @@ void FakeVimPluginPrivate::editorOpened(IEditor *editor) return; TabSettings tabSettings; - tabSettings.m_indentSize = fakeVimSettings()->shiftWidth(); - tabSettings.m_tabSize = fakeVimSettings()->tabStop(); - tabSettings.m_tabPolicy = fakeVimSettings()->expandTab() + tabSettings.m_indentSize = settings().shiftWidth(); + tabSettings.m_tabSize = settings().tabStop(); + tabSettings.m_tabPolicy = settings().expandTab() ? TabSettings::SpacesOnlyTabPolicy : TabSettings::TabsOnlyTabPolicy; tabSettings.m_continuationAlignBehavior = tew->textDocument()->tabSettings().m_continuationAlignBehavior; @@ -1757,19 +1747,15 @@ void FakeVimPluginPrivate::editorOpened(IEditor *editor) *output = proc.cleanedStdOut(); }); - connect(ICore::instance(), &ICore::saveSettingsRequested, - this, &FakeVimPluginPrivate::writeSettings); - - handler->setCurrentFileName(editor->document()->filePath().toString()); handler->installEventFilter(); // pop up the bar - if (fakeVimSettings()->useFakeVim.value()) { + if (settings().useFakeVim()) { resetCommandBuffer(); handler->setupWidget(); - if (fakeVimSettings()->relativeNumber.value()) + if (settings().relativeNumber()) createRelativeNumberWidget(editor); } } @@ -1811,8 +1797,8 @@ void FakeVimPluginPrivate::setUseFakeVim(bool on) //qDebug() << "SET USE FAKEVIM" << on; Find::setUseFakeVim(on); setUseFakeVimInternal(on); - setShowRelativeLineNumbers(fakeVimSettings()->relativeNumber.value()); - setCursorBlinking(fakeVimSettings()->blinkingCursor.value()); + setShowRelativeLineNumbers(settings().relativeNumber()); + setCursorBlinking(settings().blinkingCursor()); } void FakeVimPluginPrivate::setUseFakeVimInternal(bool on) @@ -1840,7 +1826,7 @@ void FakeVimPluginPrivate::setUseFakeVimInternal(bool on) void FakeVimPluginPrivate::setShowRelativeLineNumbers(bool on) { - if (on && fakeVimSettings()->useFakeVim.value()) { + if (on && settings().useFakeVim()) { for (auto it = m_editorToHandler.constBegin(); it != m_editorToHandler.constEnd(); ++it) createRelativeNumberWidget(it.key()); } @@ -1851,7 +1837,7 @@ void FakeVimPluginPrivate::setCursorBlinking(bool on) if (m_savedCursorFlashTime == 0) m_savedCursorFlashTime = QGuiApplication::styleHints()->cursorFlashTime(); - const bool blink = on || !fakeVimSettings()->useFakeVim.value(); + const bool blink = on || !settings().useFakeVim(); QGuiApplication::styleHints()->setCursorFlashTime(blink ? m_savedCursorFlashTime : 0); } @@ -1995,7 +1981,7 @@ void FakeVimPluginPrivate::handleDelayedQuitAll(bool forced) void FakeVimPluginPrivate::quitFakeVim() { - fakeVimSettings()->useFakeVim.setValue(false); + settings().useFakeVim.setValue(false); } void FakeVimPluginPrivate::resetCommandBuffer() From 03485af13945d45b41f34c476f73eb8c649295b5 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 1 Jun 2023 16:36:33 +0200 Subject: [PATCH 086/141] Autotools: Self-register aspect in AutogenStep Change-Id: I130ec25e6bf0bb6a45de7325834b8cc19f8c86e7 Reviewed-by: Alessandro Portale --- .../autotoolsprojectmanager/autogenstep.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/plugins/autotoolsprojectmanager/autogenstep.cpp b/src/plugins/autotoolsprojectmanager/autogenstep.cpp index c0a383205d0..090389716de 100644 --- a/src/plugins/autotoolsprojectmanager/autogenstep.cpp +++ b/src/plugins/autotoolsprojectmanager/autogenstep.cpp @@ -42,23 +42,23 @@ private: void doRun() final; bool m_runAutogen = false; + StringAspect m_arguments{this}; }; AutogenStep::AutogenStep(BuildStepList *bsl, Id id) : AbstractProcessStep(bsl, id) { - auto arguments = addAspect(); - arguments->setSettingsKey("AutotoolsProjectManager.AutogenStep.AdditionalArguments"); - arguments->setLabelText(Tr::tr("Arguments:")); - arguments->setDisplayStyle(StringAspect::LineEditDisplay); - arguments->setHistoryCompleter("AutotoolsPM.History.AutogenStepArgs"); + m_arguments.setSettingsKey("AutotoolsProjectManager.AutogenStep.AdditionalArguments"); + m_arguments.setLabelText(Tr::tr("Arguments:")); + m_arguments.setDisplayStyle(StringAspect::LineEditDisplay); + m_arguments.setHistoryCompleter("AutotoolsPM.History.AutogenStepArgs"); - connect(arguments, &BaseAspect::changed, this, [this] { m_runAutogen = true; }); + connect(&m_arguments, &BaseAspect::changed, this, [this] { m_runAutogen = true; }); setWorkingDirectoryProvider([this] { return project()->projectDirectory(); }); - setCommandLineProvider([this, arguments] { + setCommandLineProvider([this] { return CommandLine(project()->projectDirectory() / "autogen.sh", - arguments->value(), + m_arguments(), CommandLine::Raw); }); From 71d492ae133ccf55d083bc39ff980d562dfae4e6 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Thu, 1 Jun 2023 16:47:07 +0200 Subject: [PATCH 087/141] GitGrep: Use the text editor font for the results This looks more consistent with the results reported by the internal engine. Change-Id: I7a83954d230a61bb6db380d28de32ebde95ad366 Reviewed-by: Orgad Shaneh --- src/plugins/git/gitgrep.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/git/gitgrep.cpp b/src/plugins/git/gitgrep.cpp index 2161cbbf68e..e390924472b 100644 --- a/src/plugins/git/gitgrep.cpp +++ b/src/plugins/git/gitgrep.cpp @@ -111,6 +111,7 @@ public: for (const auto &match : std::as_const(matches)) { result.setMainRange(lineNumber, match.matchStart, match.matchLength); result.setUserData(match.regexpCapturedTexts); + result.setUseTextEditorFont(true); resultList->append(result); } } From 738d13cd43cfb2a47b81b5df161b638d54973c95 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Thu, 1 Jun 2023 18:24:51 +0200 Subject: [PATCH 088/141] GitGrep: Use QStringView for parsing This speeds up the parsing of big results (~2 million hits) by ~5-10%. Remove PromiseType alias. Make regexp a member field and configure it just once inside c'tor. Change-Id: Ib99597a7b8b979d49f36f2c7d146beeaa1caa380 Reviewed-by: Orgad Shaneh --- src/plugins/git/gitgrep.cpp | 75 ++++++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 27 deletions(-) diff --git a/src/plugins/git/gitgrep.cpp b/src/plugins/git/gitgrep.cpp index e390924472b..24990008cb5 100644 --- a/src/plugins/git/gitgrep.cpp +++ b/src/plugins/git/gitgrep.cpp @@ -25,7 +25,6 @@ #include #include #include -#include using namespace Core; using namespace Utils; @@ -43,10 +42,21 @@ public: QString id() const { return recurseSubmodules ? ref + ".Rec" : ref; } }; +static QStringView nextLine(QStringView *remainingInput) +{ + const int newLinePos = remainingInput->indexOf('\n'); + if (newLinePos < 0) { + QStringView ret = *remainingInput; + *remainingInput = QStringView(); + return ret; + } + QStringView ret = remainingInput->left(newLinePos); + *remainingInput = remainingInput->mid(newLinePos + 1); + return ret; +} + class GitGrepRunner { - using PromiseType = QPromise; - public: GitGrepRunner(const TextEditor::FileFindParameters ¶meters) : m_parameters(parameters) @@ -54,6 +64,14 @@ public: m_directory = FilePath::fromString(parameters.additionalParameters.toString()); m_vcsBinary = GitClient::instance()->vcsBinary(); m_environment = GitClient::instance()->processEnvironment(); + if (m_parameters.flags & FindRegularExpression) { + const QRegularExpression::PatternOptions patternOptions + = m_parameters.flags & FindCaseSensitively + ? QRegularExpression::NoPatternOption + : QRegularExpression::CaseInsensitiveOption; + m_regexp.setPattern(m_parameters.text); + m_regexp.setPatternOptions(patternOptions); + } } struct Match @@ -67,7 +85,7 @@ public: QStringList regexpCapturedTexts; }; - void processLine(const QString &line, SearchResultItems *resultList) const + void processLine(QStringView line, SearchResultItems *resultList) const { if (line.isEmpty()) return; @@ -75,23 +93,15 @@ public: static const QLatin1String resetColor("\x1b[m"); SearchResultItem result; const int lineSeparator = line.indexOf(QChar::Null); - QString filePath = line.left(lineSeparator); + QStringView filePath = line.left(lineSeparator); if (!m_ref.isEmpty() && filePath.startsWith(m_ref)) - filePath.remove(0, m_ref.length()); - result.setFilePath(m_directory.pathAppended(filePath)); + filePath = filePath.mid(m_ref.length()); + result.setFilePath(m_directory.pathAppended(filePath.toString())); const int textSeparator = line.indexOf(QChar::Null, lineSeparator + 1); const int lineNumber = line.mid(lineSeparator + 1, textSeparator - lineSeparator - 1).toInt(); - QString text = line.mid(textSeparator + 1); - QRegularExpression regexp; + QString text = line.mid(textSeparator + 1).toString(); QList matches; - if (m_parameters.flags & FindRegularExpression) { - const QRegularExpression::PatternOptions patternOptions = - (m_parameters.flags & FindCaseSensitively) - ? QRegularExpression::NoPatternOption : QRegularExpression::CaseInsensitiveOption; - regexp.setPattern(m_parameters.text); - regexp.setPatternOptions(patternOptions); - } - for (;;) { + while (true) { const int matchStart = text.indexOf(boldRed); if (matchStart == -1) break; @@ -102,7 +112,7 @@ public: Match match(matchStart, matchLength); const QString matchText = text.mid(matchTextStart, matchLength); if (m_parameters.flags & FindRegularExpression) - match.regexpCapturedTexts = regexp.match(matchText).capturedTexts(); + match.regexpCapturedTexts = m_regexp.match(matchText).capturedTexts(); matches.append(match); text = text.left(matchStart) + matchText + text.mid(matchEnd + resetColor.size()); } @@ -116,18 +126,28 @@ public: } } - void read(PromiseType &fi, const QString &text) + void read(QPromise &promise, const QString &input) { - SearchResultItems resultList; - QString t = text; - QTextStream stream(&t); - while (!stream.atEnd() && !fi.isCanceled()) - processLine(stream.readLine(), &resultList); - if (!resultList.isEmpty() && !fi.isCanceled()) - fi.addResult(resultList); + SearchResultItems items; + QStringView remainingInput(input); + while (true) { + if (promise.isCanceled()) + return; + + if (remainingInput.isEmpty()) + break; + + const QStringView line = nextLine(&remainingInput); + if (line.isEmpty()) + continue; + + processLine(line, &items); + } + if (!items.isEmpty()) + promise.addResult(items); } - void operator()(PromiseType &promise) + void operator()(QPromise &promise) { QStringList arguments = { "-c", "color.grep.match=bold red", @@ -189,6 +209,7 @@ private: QString m_ref; TextEditor::FileFindParameters m_parameters; Environment m_environment; + QRegularExpression m_regexp; }; static bool isGitDirectory(const FilePath &path) From 22f8b8f1abb70211727839d89b4282b4c19a0ab5 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 1 Jun 2023 13:35:22 +0200 Subject: [PATCH 089/141] SquishTests: Adapt to ui change MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Enable QML check box is nowadays a combo box. Change-Id: I87d94892ac02ea16d18bf78999f17065e02c5ac6 Reviewed-by: Robert Löhning --- tests/system/objects.map | 2 ++ tests/system/shared/debugger.py | 3 +-- tests/system/suite_debugger/tst_qml_js_console/test.py | 3 +-- tests/system/suite_debugger/tst_qml_locals/test.py | 3 +-- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/tests/system/objects.map b/tests/system/objects.map index 883bfd02af4..97d44b7ed26 100644 --- a/tests/system/objects.map +++ b/tests/system/objects.map @@ -62,6 +62,8 @@ :Dialog.componentNameEdit_QLineEdit {name='componentNameEdit' type='Utils::ClassNameValidatingLineEdit' visible='1' window=':Dialog_QmlJSEditor::Internal::ComponentNameDialog'} :Dialog_Debugger::Internal::SymbolPathsDialog {name='Debugger__Internal__SymbolPathsDialog' type='Debugger::Internal::SymbolPathsDialog' visible='1' windowTitle='Dialog'} :Dialog_QmlJSEditor::Internal::ComponentNameDialog {type='QmlJSEditor::Internal::ComponentNameDialog' unnamed='1' visible='1' windowTitle='Move Component into Separate File'} +:EnableQMLDebugger_ComboBox {buddy=':EnableQMLDebugger_Label' type='QComboBox' unnamed='1' visible='1'} +:EnableQMLDebugger_Label {text='QML debugger:' type='QLabel' window=':Qt Creator_Core::Internal::MainWindow'} :Events.QmlProfilerEventsTable_QmlProfiler::Internal::QmlProfilerStatisticsMainView {container=':Qt Creator.Events_QDockWidget' name='QmlProfilerEventsTable' type='QmlProfiler::Internal::QmlProfilerStatisticsMainView' visible='1'} :Failed to start application_QMessageBox {type='QMessageBox' unnamed='1' visible='1' windowTitle='Failed to start application'} :File has been removed.Close_QPushButton {text='Close' type='QPushButton' unnamed='1' visible='1' window=':File has been removed_QMessageBox'} diff --git a/tests/system/shared/debugger.py b/tests/system/shared/debugger.py index 424785b3a37..7176afc8e59 100644 --- a/tests/system/shared/debugger.py +++ b/tests/system/shared/debugger.py @@ -113,8 +113,7 @@ def doSimpleDebugging(currentKit, currentConfigName, expectedBPOrder=[], enableQ expectedLabelTexts.append("Running\.") switchViewTo(ViewConstants.PROJECTS) switchToBuildOrRunSettingsFor(currentKit, ProjectSettings.RUN) - ensureChecked(waitForObject("{container=':Qt Creator_Core::Internal::MainWindow' text='Enable QML' " - "type='QCheckBox' unnamed='1' visible='1'}"), enableQml) + selectFromCombo(":EnableQMLDebugger_ComboBox", "Enabled" if enableQml else "Disabled") switchViewTo(ViewConstants.EDIT) if not __startDebugger__(currentKit, currentConfigName): return False diff --git a/tests/system/suite_debugger/tst_qml_js_console/test.py b/tests/system/suite_debugger/tst_qml_js_console/test.py index 6580e4988a4..4760296cf69 100644 --- a/tests/system/suite_debugger/tst_qml_js_console/test.py +++ b/tests/system/suite_debugger/tst_qml_js_console/test.py @@ -114,8 +114,7 @@ def main(): # make sure QML Debugging is enabled switchViewTo(ViewConstants.PROJECTS) switchToBuildOrRunSettingsFor(Targets.getDefaultKit(), ProjectSettings.RUN) - ensureChecked("{container=':Qt Creator.scrollArea_QScrollArea' text='Enable QML' " - "type='QCheckBox' unnamed='1' visible='1'}") + selectFromCombo(":EnableQMLDebugger_ComboBox", "Enabled") switchViewTo(ViewConstants.EDIT) # start debugging clickButton(fancyDebugButton) diff --git a/tests/system/suite_debugger/tst_qml_locals/test.py b/tests/system/suite_debugger/tst_qml_locals/test.py index 70256ee2d44..37ecb515cc6 100644 --- a/tests/system/suite_debugger/tst_qml_locals/test.py +++ b/tests/system/suite_debugger/tst_qml_locals/test.py @@ -35,8 +35,7 @@ def main(): return switchViewTo(ViewConstants.PROJECTS) switchToBuildOrRunSettingsFor(Targets.getDefaultKit(), ProjectSettings.RUN) - ensureChecked("{container=':Qt Creator_Core::Internal::MainWindow' text='Enable QML' " - "type='QCheckBox' unnamed='1' visible='1'}") + selectFromCombo(":EnableQMLDebugger_ComboBox", "Enabled") switchViewTo(ViewConstants.EDIT) clickButton(fancyDebugButton) locAndExprTV = waitForObject(":Locals and Expressions_Debugger::Internal::WatchTreeView") From b0d5e41e53d2de7a9c48a33182b44bed1667ebff Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 1 Jun 2023 14:33:01 +0200 Subject: [PATCH 090/141] SquishTests: Fix selecting of Qt Quick version on wizard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I96ac34323e52507b26f7936499dade9203529315 Reviewed-by: Robert Löhning --- tests/system/shared/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/system/shared/project.py b/tests/system/shared/project.py index 2e541ddf920..6702144ea8c 100644 --- a/tests/system/shared/project.py +++ b/tests/system/shared/project.py @@ -128,7 +128,7 @@ def __createProjectHandleQtQuickSelection__(minimumQtVersion): comboBox = waitForObject("{name?='*QtVersion' type='QComboBox' visible='1'" " window=':New_ProjectExplorer::JsonWizard'}") try: - selectFromCombo(comboBox, minimumQtVersion) + selectFromCombo(comboBox, "Qt " + minimumQtVersion) except: t,v = sys.exc_info()[:2] test.fatal("Exception while trying to select Qt version", "%s: %s" % (t.__name__, str(v))) From 270972c7bb6b5936fc5a7b73107325581fbaa67c Mon Sep 17 00:00:00 2001 From: David Schulz Date: Thu, 1 Jun 2023 14:42:15 +0200 Subject: [PATCH 091/141] ClangCodeModel: report highlight results in one batch again ... with Qt 6.6 Change-Id: Ic3ebb5cee4deeebf87a0d8e0ab33bcdc1c92c3a2 Reviewed-by: Christian Kandeler Reviewed-by: --- src/plugins/clangcodemodel/clangdsemantichighlighting.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/plugins/clangcodemodel/clangdsemantichighlighting.cpp b/src/plugins/clangcodemodel/clangdsemantichighlighting.cpp index 04bcc08fa2d..e1b82ab3770 100644 --- a/src/plugins/clangcodemodel/clangdsemantichighlighting.cpp +++ b/src/plugins/clangcodemodel/clangdsemantichighlighting.cpp @@ -421,8 +421,12 @@ void doSemanticHighlighting( if (ClangdClient * const client = ClangModelManagerSupport::clientForFile(filePath)) client->setVirtualRanges(filePath, virtualRanges, docRevision); }, Qt::QueuedConnection); +#if QT_VERSION >= QT_VERSION_CHECK(6, 6, 0) + promise.addResults(results); +#else for (const HighlightingResult &r : results) promise.addResult(r); +#endif } } From f146bebbc7091d8e0f9b637bd5ca23f3ca45df7c Mon Sep 17 00:00:00 2001 From: Yasser Grimes Date: Wed, 31 May 2023 16:44:41 +0300 Subject: [PATCH 092/141] McuSupport: Simplify template integration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To simplify how users integrate their projects with Qul, Qul related template files are placed under the "qmlproject" subfolder. Task-number: QTCREATORBUG-29114 Change-Id: I984f1619547951e0518790c843987f03b7daa62a Reviewed-by: Alessandro Portale Reviewed-by: Sivert Krøvel Reviewed-by: --- src/plugins/mcusupport/mcusupport.qrc | 1 + .../wizards/qmlproject/CMakeLists.txt | 3 +-- .../mcusupport/wizards/qmlproject/Qul.cmake | 3 +++ .../mcusupport/wizards/qmlproject/wizard.json | 24 ++++++++++++------- 4 files changed, 20 insertions(+), 11 deletions(-) create mode 100644 src/plugins/mcusupport/wizards/qmlproject/Qul.cmake diff --git a/src/plugins/mcusupport/mcusupport.qrc b/src/plugins/mcusupport/mcusupport.qrc index abbfb969e3a..7aeb7b93873 100644 --- a/src/plugins/mcusupport/mcusupport.qrc +++ b/src/plugins/mcusupport/mcusupport.qrc @@ -20,5 +20,6 @@ wizards/qmlproject/module.qmlproject.tpl wizards/qmlproject/component.qml.tpl wizards/qmlproject/wizard.json + wizards/qmlproject/Qul.cmake diff --git a/src/plugins/mcusupport/wizards/qmlproject/CMakeLists.txt b/src/plugins/mcusupport/wizards/qmlproject/CMakeLists.txt index 49a4a8f949f..47eed40c785 100644 --- a/src/plugins/mcusupport/wizards/qmlproject/CMakeLists.txt +++ b/src/plugins/mcusupport/wizards/qmlproject/CMakeLists.txt @@ -4,5 +4,4 @@ project(%{CorrectedProjectName} VERSION 0.0.1 LANGUAGES C CXX ASM) find_package(Qul) -qul_add_target(%{CorrectedProjectName} QML_PROJECT %{QmlProjectFile} GENERATE_ENTRYPOINT) -app_target_setup_os(%{CorrectedProjectName}) +add_subdirectory(qmlproject) diff --git a/src/plugins/mcusupport/wizards/qmlproject/Qul.cmake b/src/plugins/mcusupport/wizards/qmlproject/Qul.cmake new file mode 100644 index 00000000000..1ece8f48d6d --- /dev/null +++ b/src/plugins/mcusupport/wizards/qmlproject/Qul.cmake @@ -0,0 +1,3 @@ + +qul_add_target(%{CorrectedProjectName} QML_PROJECT %{QmlProjectFile} GENERATE_ENTRYPOINT) +app_target_setup_os(%{CorrectedProjectName}) diff --git a/src/plugins/mcusupport/wizards/qmlproject/wizard.json b/src/plugins/mcusupport/wizards/qmlproject/wizard.json index 4fcf4f6fd31..9c1e036e910 100644 --- a/src/plugins/mcusupport/wizards/qmlproject/wizard.json +++ b/src/plugins/mcusupport/wizards/qmlproject/wizard.json @@ -12,6 +12,7 @@ "options": [ + { "key": "QmlProjectDirectory", "value": "%{ProjectDirectory}/qmlproject"}, { "key": "CorrectedProjectName", "value": "%{JS: '%{ProjectName}'.replace(/-/g, '_')}"}, { "key": "MainQmlFile", "value": "%{CorrectedProjectName}.qml" }, { "key": "QmlProjectFile", "value": "%{CorrectedProjectName}.qmlproject" }, @@ -55,49 +56,54 @@ "source": "CMakeLists.txt", "openAsProject": true }, + { + "source": "Qul.cmake", + "target": "%{QmlProjectDirectory}/CMakeLists.txt", + "openInEditor": false + }, { "source": "BackendObject.h", - "target": "%{ProjectDirectory}/src/%{InterfaceFile}", + "target": "%{QmlProjectDirectory}/src/%{InterfaceFile}", "openInEditor": true }, { "source": "component.qml.tpl", - "target": "%{ProjectDirectory}/imports/CustomModule/%{QmlComponent}", + "target": "%{QmlProjectDirectory}/imports/CustomModule/%{QmlComponent}", "openInEditor": true }, { "source": "module.qmlproject.tpl", - "target": "%{ProjectDirectory}/imports/CustomModule/%{ModuleFile}", + "target": "%{QmlProjectDirectory}/imports/CustomModule/%{ModuleFile}", "openInEditor": true }, { "source": "project.qmlproject.tpl", - "target": "%{ProjectDirectory}/%{QmlProjectFile}", + "target": "%{QmlProjectDirectory}/%{QmlProjectFile}", "openInEditor": true }, { "source": "main.qml.tpl", - "target": "%{ProjectDirectory}/%{MainQmlFile}", + "target": "%{QmlProjectDirectory}/%{MainQmlFile}", "openInEditor": true }, { "source": "../icon.png", - "target": "%{ProjectDirectory}/images/icon.png", + "target": "%{QmlProjectDirectory}/images/icon.png", "isBinary": true }, { "source": "DejaVuSansMono.ttf", - "target": "%{ProjectDirectory}/fonts/DejaVuSansMono.ttf", + "target": "%{QmlProjectDirectory}/fonts/DejaVuSansMono.ttf", "isBinary": true }, { "source": "LICENSE", - "target": "%{ProjectDirectory}/fonts/LICENSE", + "target": "%{QmlProjectDirectory}/fonts/LICENSE", "isBinary": true }, { "source": "translation.nb_NO.ts", - "target": "%{ProjectDirectory}/translations/%{TsFile}", + "target": "%{QmlProjectDirectory}/translations/%{TsFile}", "openInEditor": false }, { From 68a5cd65751ebbdfeb747916099a28e33b884b6e Mon Sep 17 00:00:00 2001 From: David Schulz Date: Wed, 31 May 2023 12:12:22 +0200 Subject: [PATCH 093/141] LanguageClient: postpone creating progressbars Some language servers are spawning progress reports for many small tasks. This can get distracting in the case where those progress bars are spawned while typing, like in the case of the python language server that creates a report for every lint that gets triggered after receiving a document change notification. So in order to reduce the amount of progress bars created from progress reports we postpone the creation of the bars. Fixes: QTCREATORBUG-29224 Change-Id: I2e658be0a26b21e41c80b444184648ba70682522 Reviewed-by: Reviewed-by: Qt CI Patch Build Bot Reviewed-by: Christian Stenger --- .../languageclient/progressmanager.cpp | 52 ++++++++++++++----- src/plugins/languageclient/progressmanager.h | 15 ++++-- 2 files changed, 50 insertions(+), 17 deletions(-) diff --git a/src/plugins/languageclient/progressmanager.cpp b/src/plugins/languageclient/progressmanager.cpp index 285080e4980..6b82d289dfc 100644 --- a/src/plugins/languageclient/progressmanager.cpp +++ b/src/plugins/languageclient/progressmanager.cpp @@ -8,6 +8,7 @@ #include #include +#include using namespace LanguageServerProtocol; @@ -81,9 +82,28 @@ void ProgressManager::beginProgress(const ProgressToken &token, const WorkDonePr auto interface = new QFutureInterface(); interface->reportStarted(); interface->setProgressRange(0, 100); // LSP always reports percentage of the task - const QString title = m_titles.value(token, begin.title()); - Core::FutureProgress *progress = Core::ProgressManager::addTask( - interface->future(), title, languageClientProgressId(token)); + ProgressItem progressItem; + progressItem.futureInterface = interface; + progressItem.title = m_titles.value(token, begin.title()); + if (LOGPROGRESS().isDebugEnabled()) + progressItem.timer.start(); + progressItem.showBarTimer = new QTimer(); + progressItem.showBarTimer->setSingleShot(true); + progressItem.showBarTimer->setInterval(750); + progressItem.showBarTimer->callOnTimeout([this, token]() { spawnProgressBar(token); }); + progressItem.showBarTimer->start(); + m_progress[token] = progressItem; + reportProgress(token, begin); +} + +void ProgressManager::spawnProgressBar(const LanguageServerProtocol::ProgressToken &token) +{ + ProgressItem &progressItem = m_progress[token]; + QTC_ASSERT(progressItem.futureInterface, return); + Core::FutureProgress *progress + = Core::ProgressManager::addTask(progressItem.futureInterface->future(), + progressItem.title, + languageClientProgressId(token)); const std::function clickHandler = m_clickHandlers.value(token); if (clickHandler) QObject::connect(progress, &Core::FutureProgress::clicked, clickHandler); @@ -92,23 +112,26 @@ void ProgressManager::beginProgress(const ProgressToken &token, const WorkDonePr QObject::connect(progress, &Core::FutureProgress::canceled, cancelHandler); else progress->setCancelEnabled(false); - m_progress[token] = {progress, interface}; - if (LOGPROGRESS().isDebugEnabled()) - m_timer[token].start(); - reportProgress(token, begin); + if (!progressItem.message.isEmpty()) { + progress->setSubtitle(progressItem.message); + progress->setSubtitleVisibleInStatusBar(true); + } + progressItem.progressInterface = progress; } void ProgressManager::reportProgress(const ProgressToken &token, const WorkDoneProgressReport &report) { - const LanguageClientProgress &progress = m_progress.value(token); + ProgressItem &progress = m_progress[token]; + const std::optional &message = report.message(); if (progress.progressInterface) { - const std::optional &message = report.message(); if (message.has_value()) { progress.progressInterface->setSubtitle(*message); const bool showSubtitle = !message->isEmpty(); progress.progressInterface->setSubtitleVisibleInStatusBar(showSubtitle); } + } else if (message.has_value()) { + progress.message = *message; } if (progress.futureInterface) { if (const std::optional &percentage = report.percentage(); percentage.has_value()) @@ -118,7 +141,7 @@ void ProgressManager::reportProgress(const ProgressToken &token, void ProgressManager::endProgress(const ProgressToken &token, const WorkDoneProgressEnd &end) { - const LanguageClientProgress &progress = m_progress.value(token); + const ProgressItem &progress = m_progress.value(token); const QString &message = end.message().value_or(QString()); if (progress.progressInterface) { if (!message.isEmpty()) { @@ -127,11 +150,11 @@ void ProgressManager::endProgress(const ProgressToken &token, const WorkDoneProg } progress.progressInterface->setSubtitle(message); progress.progressInterface->setSubtitleVisibleInStatusBar(!message.isEmpty()); - auto timer = m_timer.take(token); - if (timer.isValid()) { + if (progress.timer.isValid()) { qCDebug(LOGPROGRESS) << QString("%1 took %2") .arg(progress.progressInterface->title()) - .arg(QTime::fromMSecsSinceStartOfDay(timer.elapsed()) + .arg(QTime::fromMSecsSinceStartOfDay( + progress.timer.elapsed()) .toString(Qt::ISODateWithMs)); } } @@ -140,7 +163,8 @@ void ProgressManager::endProgress(const ProgressToken &token, const WorkDoneProg void ProgressManager::endProgressReport(const ProgressToken &token) { - const LanguageClientProgress &progress = m_progress.take(token); + ProgressItem progress = m_progress.take(token); + delete progress.showBarTimer; if (progress.futureInterface) progress.futureInterface->reportFinished(); delete progress.futureInterface; diff --git a/src/plugins/languageclient/progressmanager.h b/src/plugins/languageclient/progressmanager.h index 1e0ad781806..05b9640745d 100644 --- a/src/plugins/languageclient/progressmanager.h +++ b/src/plugins/languageclient/progressmanager.h @@ -11,6 +11,10 @@ #include #include +QT_BEGIN_NAMESPACE +class QTimer; +QT_END_NAMESPACE + namespace LanguageServerProtocol { class ProgressParams; class ProgressToken; @@ -46,15 +50,20 @@ private: const LanguageServerProtocol::WorkDoneProgressReport &report); void endProgress(const LanguageServerProtocol::ProgressToken &token, const LanguageServerProtocol::WorkDoneProgressEnd &end); + void spawnProgressBar(const LanguageServerProtocol::ProgressToken &token); - struct LanguageClientProgress { + struct ProgressItem + { QPointer progressInterface = nullptr; QFutureInterface *futureInterface = nullptr; + QElapsedTimer timer; + QTimer *showBarTimer = nullptr; + QString message; + QString title; }; - QMap m_progress; + QMap m_progress; QMap m_titles; - QMap m_timer; QMap> m_clickHandlers; QMap> m_cancelHandlers; }; From d65273aee39f33070200c4cf453e7d044d854470 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Fri, 2 Jun 2023 10:14:35 +0200 Subject: [PATCH 094/141] Update qbs submodule to HEAD of 2.1 branch Change-Id: I3d670f8192f79806161fd7871fa9e5ff8c398f22 Reviewed-by: Qt CI Bot Reviewed-by: Christian Stenger Reviewed-by: --- src/shared/qbs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/qbs b/src/shared/qbs index eaeba4a45e7..43af7ba7fa1 160000 --- a/src/shared/qbs +++ b/src/shared/qbs @@ -1 +1 @@ -Subproject commit eaeba4a45e7d95b7bb3f4fe907e862d947faf092 +Subproject commit 43af7ba7fa12de25268d2cc5582b963e360022e5 From 37b30dc7a28b2efae8a55e9ade13473caf13c26e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20L=C3=B6hning?= Date: Wed, 17 May 2023 19:06:11 +0200 Subject: [PATCH 095/141] SquishTests: Remove workaround for fixed inconsistency Task-number: QTCREATORBUG-29126 Change-Id: I2a84e606249d5ca7f68d7a73d819eee3f341216d Reviewed-by: Reviewed-by: Christian Stenger --- .../suite_general/tst_create_proj_wizard/test.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/tests/system/suite_general/tst_create_proj_wizard/test.py b/tests/system/suite_general/tst_create_proj_wizard/test.py index 643e8054fa1..dd261780646 100644 --- a/tests/system/suite_general/tst_create_proj_wizard/test.py +++ b/tests/system/suite_general/tst_create_proj_wizard/test.py @@ -54,18 +54,15 @@ def main(): with TestSection("Testing project template %s -> %s" % (category, template)): displayedPlatforms = __createProject__(category, template) if template.startswith("Qt Quick Application"): - if "(compat)" in template: # QTCREATORBUG-29126 - qtVersionsForQuick = ["Qt 5.14", "Qt 6.2"] - else: - qtVersionsForQuick = ["6.2"] + qtVersionsForQuick = ["6.2"] + if "(compat)" in template: + qtVersionsForQuick += ["5.14"] for counter, qtVersion in enumerate(qtVersionsForQuick): + def additionalFunc(displayedPlatforms, qtVersion): requiredQtVersion = __createProjectHandleQtQuickSelection__(qtVersion) - if sys.version_info.major > 2: - requiredQtVersion = requiredQtVersion.removeprefix("Qt ") - else: - requiredQtVersion = requiredQtVersion.lstrip("Qt ") __modifyAvailableTargets__(displayedPlatforms, requiredQtVersion, True) + handleBuildSystemVerifyKits(category, template, kits, displayedPlatforms, additionalFunc, qtVersion) # are there more Quick combinations - then recreate this project From 83c837049db79e3047e7fe9c3bfbc7a0d9bd6302 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20L=C3=B6hning?= Date: Thu, 1 Jun 2023 16:43:09 +0200 Subject: [PATCH 096/141] SquishTests: Make number of results constant in verifyKitCheckboxes() Before the change, we got zero results in the expected case or up to two fails on error. Change-Id: I6583844eb5473cad8190acc91db1207933dc6630 Reviewed-by: Christian Stenger --- .../suite_general/tst_create_proj_wizard/test.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/tests/system/suite_general/tst_create_proj_wizard/test.py b/tests/system/suite_general/tst_create_proj_wizard/test.py index dd261780646..8579111b02c 100644 --- a/tests/system/suite_general/tst_create_proj_wizard/test.py +++ b/tests/system/suite_general/tst_create_proj_wizard/test.py @@ -87,13 +87,15 @@ def verifyKitCheckboxes(kits, displayedPlatforms): unexpectedShownKits = availableCheckboxes.difference(displayedPlatforms) missingKits = displayedPlatforms.difference(availableCheckboxes) - test.log("Expected kits shown on 'Kit Selection' page:\n%s" % "\n".join(expectedShownKits)) - if len(unexpectedShownKits): - test.fail("Kits found on 'Kit Selection' page but not expected:\n%s" - % "\n".join(unexpectedShownKits)) - if len(missingKits): - test.fail("Expected kits missing on 'Kit Selection' page:\n%s" - % "\n".join(missingKits)) + if not test.verify(len(unexpectedShownKits) == 0 and len(missingKits) == 0, + "No missing or unexpected kits found on 'Kit Selection' page?\n" + "Found expected kits:\n%s" % "\n".join(expectedShownKits)): + if len(unexpectedShownKits): + test.log("Kits found on 'Kit Selection' page but not expected:\n%s" + % "\n".join(unexpectedShownKits)) + if len(missingKits): + test.log("Expected kits missing on 'Kit Selection' page:\n%s" + % "\n".join(missingKits)) def handleBuildSystemVerifyKits(category, template, kits, displayedPlatforms, specialHandlingFunc = None, *args): From d9e3d32a80497fbef98073b06f1eaf9bf5811587 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 1 Jun 2023 15:26:34 +0200 Subject: [PATCH 097/141] MarkdownEditor: Ensure focus is inside the editor part When loading a file it is more likely that the editable view of the document should be focused than the read only part. Change-Id: I8b7ed40a233dedf94883072be7462ebeabb78b42 Reviewed-by: Eike Ziller --- src/plugins/texteditor/markdowneditor.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/texteditor/markdowneditor.cpp b/src/plugins/texteditor/markdowneditor.cpp index 12e60f027af..9c89636df8e 100644 --- a/src/plugins/texteditor/markdowneditor.cpp +++ b/src/plugins/texteditor/markdowneditor.cpp @@ -245,6 +245,8 @@ public: if (obj == m_widget && ev->type() == QEvent::FocusIn) { if (m_splitter->focusWidget()) m_splitter->focusWidget()->setFocus(); + else if (m_textEditorWidget->isVisible()) + m_textEditorWidget->setFocus(); else m_splitter->widget(0)->setFocus(); return true; From de104fad12302f633be866b89487adfaeaa1b088 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20L=C3=B6hning?= Date: Thu, 1 Jun 2023 17:31:15 +0200 Subject: [PATCH 098/141] SquishTests: Don't try changing build system of Quick Apps They can use CMake only. Change-Id: Ibbce50290597594a98ae08d9dd7ab171137c2b7c Reviewed-by: Reviewed-by: Christian Stenger --- tests/system/shared/project.py | 7 ++++++- tests/system/suite_APTW/tst_APTW02/test.py | 2 +- tests/system/suite_general/tst_save_before_build/test.py | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/system/shared/project.py b/tests/system/shared/project.py index 6702144ea8c..d1e44102bcc 100644 --- a/tests/system/shared/project.py +++ b/tests/system/shared/project.py @@ -277,7 +277,12 @@ def createNewQtQuickApplication(workingDir, projectName=None, buildSystem=None): available = __createProjectOrFileSelectType__(" Application (Qt)", template, fromWelcome) projectName = __createProjectSetNameAndPath__(workingDir, projectName) - __handleBuildSystem__(buildSystem) + if template == "Qt Quick Application": + if buildSystem: + test.warning("Build system set explicitly for a template which can't change it.", + "Template: %s, Build System: %s" % (template, buildSystem)) + else: + __handleBuildSystem__(buildSystem) requiredQt = __createProjectHandleQtQuickSelection__(minimumQtVersion) __modifyAvailableTargets__(available, requiredQt) checkedTargets = __chooseTargets__(targets, available) diff --git a/tests/system/suite_APTW/tst_APTW02/test.py b/tests/system/suite_APTW/tst_APTW02/test.py index 716145a6401..0a5ff2bd72e 100644 --- a/tests/system/suite_APTW/tst_APTW02/test.py +++ b/tests/system/suite_APTW/tst_APTW02/test.py @@ -8,7 +8,7 @@ def main(): startQC() if not startedWithoutPluginError(): return - createNewQtQuickApplication(tempDir(), "SampleApp", buildSystem="qmake") + createNewQtQuickApplication(tempDir(), "SampleApp") # run project for debug and release and verify results runVerify() #close Qt Creator diff --git a/tests/system/suite_general/tst_save_before_build/test.py b/tests/system/suite_general/tst_save_before_build/test.py index d6b9b5f8574..87c2d56d39a 100644 --- a/tests/system/suite_general/tst_save_before_build/test.py +++ b/tests/system/suite_general/tst_save_before_build/test.py @@ -29,7 +29,7 @@ def main(): if not startedWithoutPluginError(): return verifySaveBeforeBuildChecked(False) - for buildSystem in ["CMake", "Qbs"]: + for buildSystem in ["CMake"]: projectName = "SampleApp-" + buildSystem ensureSaveBeforeBuildChecked(False) # create qt quick application From a9720c118313913f82f90738e64620bd0aa5e857 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20L=C3=B6hning?= Date: Fri, 26 May 2023 01:48:45 +0200 Subject: [PATCH 099/141] SquishTests: Don't generate tasks with empty description Creator ignores them anyway. Task-number: QTCREATORBUG-29209 Change-Id: I0ab2f96d55547ccf3112b18886518a065b19052a Reviewed-by: Reviewed-by: Christian Stenger --- tests/system/suite_general/tst_tasks_handling/test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/system/suite_general/tst_tasks_handling/test.py b/tests/system/suite_general/tst_tasks_handling/test.py index 8c6e2395583..865d22a2485 100644 --- a/tests/system/suite_general/tst_tasks_handling/test.py +++ b/tests/system/suite_general/tst_tasks_handling/test.py @@ -31,7 +31,7 @@ def generateRandomTaskType(): return 2 def generateMockTasksFile(): - descriptions = ["", "dummy information", "unknown error", "not found", "syntax error", + descriptions = ["dummy information", "unknown error", "not found", "syntax error", "missing information", "unused"] tasks = ["warn", "error", "other"] isWin = platform.system() in ('Microsoft', 'Windows') @@ -44,7 +44,7 @@ def generateMockTasksFile(): tasksType = generateRandomTaskType() tasksCount[tasksType] += 1 tData = tasks[tasksType] - dData = descriptions[random.randint(0, 6)] + dData = descriptions[random.randint(0, len(descriptions) - 1)] tFile.write("%s\t%d\t%s\t%s\n" % (fData, lData, tData, dData)) tFile.close() test.log("Wrote tasks file with %d warnings, %d errors and %d other tasks." % tuple(tasksCount)) From 04c2a32fc06a53e66f341c5a748a1ba98f192612 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Wed, 31 May 2023 11:36:38 +0200 Subject: [PATCH 100/141] ExamplesParser: Export only for tests Makes binary compatible changes easier later, if needed Change-Id: Ib3e04ac3a26068cf9f8bcc57b2dad9d0aeaaa5c3 Reviewed-by: Reviewed-by: Christian Stenger Reviewed-by: Qt CI Bot --- src/plugins/qtsupport/examplesparser.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/qtsupport/examplesparser.h b/src/plugins/qtsupport/examplesparser.h index bfe65721c22..54efaf58875 100644 --- a/src/plugins/qtsupport/examplesparser.h +++ b/src/plugins/qtsupport/examplesparser.h @@ -13,7 +13,7 @@ namespace QtSupport::Internal { enum InstructionalType { Example = 0, Demo, Tutorial }; -class QTSUPPORT_EXPORT ExampleItem : public Core::ListItem +class QTSUPPORT_TEST_EXPORT ExampleItem : public Core::ListItem { public: Utils::FilePath projectPath; @@ -31,13 +31,13 @@ public: QHash metaData; }; -QTSUPPORT_EXPORT Utils::expected_str> parseExamples( +QTSUPPORT_TEST_EXPORT Utils::expected_str> parseExamples( const Utils::FilePath &manifest, const Utils::FilePath &examplesInstallPath, const Utils::FilePath &demosInstallPath, bool examples); -QTSUPPORT_EXPORT Utils::expected_str> parseExamples( +QTSUPPORT_TEST_EXPORT Utils::expected_str> parseExamples( const QByteArray &manifestData, const Utils::FilePath &manifestPath, const Utils::FilePath &examplesInstallPath, From a5dfbe01d59cf1756a2bbeb7870fe994f1527a0a Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Thu, 1 Jun 2023 12:58:46 +0300 Subject: [PATCH 101/141] Utils: Support hardlink detection also on Windows Change-Id: I717899ef73e965438ecd28983397ffc90a7ff570 Reviewed-by: David Schulz Reviewed-by: Qt CI Patch Build Bot --- src/libs/utils/devicefileaccess.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/libs/utils/devicefileaccess.cpp b/src/libs/utils/devicefileaccess.cpp index f5bb1d20482..bd139d9b168 100644 --- a/src/libs/utils/devicefileaccess.cpp +++ b/src/libs/utils/devicefileaccess.cpp @@ -493,6 +493,20 @@ bool DesktopDeviceFileAccess::hasHardLinks(const FilePath &filePath) const if (s.st_nlink > 1) return true; } +#elif defined(Q_OS_WIN) + const HANDLE handle = CreateFile((wchar_t *) filePath.toUserOutput().utf16(), + 0, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, + NULL); + if (handle == INVALID_HANDLE_VALUE) + return false; + + FILE_STANDARD_INFO info; + if (GetFileInformationByHandleEx(handle, FileStandardInfo, &info, sizeof(info))) + return info.NumberOfLinks > 1; #else Q_UNUSED(filePath) #endif From 7a42c327320a6232ab8cb1ff280f20262cd56c7b Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Thu, 1 Jun 2023 18:59:53 +0200 Subject: [PATCH 102/141] SilverSearcher: Fix quitting the loop after resume Quit the loop after resuming when the process already finished. Amends cd70d10dce8993d9923619aa4582b5c84a46b12e Change-Id: I73d4b11bb2be47ce9cc6c6c816b60058bc2db250 Reviewed-by: Reviewed-by: Orgad Shaneh Reviewed-by: Qt CI Bot --- src/plugins/silversearcher/findinfilessilversearcher.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/silversearcher/findinfilessilversearcher.cpp b/src/plugins/silversearcher/findinfilessilversearcher.cpp index 7d9e5f1e141..313d23eda27 100644 --- a/src/plugins/silversearcher/findinfilessilversearcher.cpp +++ b/src/plugins/silversearcher/findinfilessilversearcher.cpp @@ -162,6 +162,8 @@ static void runSilverSeacher(QPromise &promise, SilverSearcher::parse(promise, output, &parserState, regExp); } outputBuffer.clear(); + if (process.state() == QProcess::NotRunning) + loop.quit(); }); watcher.setFuture(future); loop.exec(QEventLoop::ExcludeUserInputEvents); From 7b2c1fdab072d409eb6a0be5a28a1bded9dced22 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Thu, 1 Jun 2023 18:59:53 +0200 Subject: [PATCH 103/141] GitGrep: Make pause and continue working Make cancel and continue button working. Make pausing above 200000 hits working. Applied the same pattern as it was done recently inside SilverSearcher: cd70d10dce8993d9923619aa4582b5c84a46b12e. Change-Id: I5e466e2176a59301dbfd3f957012e1760bd0c20f Reviewed-by: Qt CI Bot Reviewed-by: Orgad Shaneh --- src/plugins/git/gitgrep.cpp | 75 ++++++++++++++++++++++++++++--------- 1 file changed, 58 insertions(+), 17 deletions(-) diff --git a/src/plugins/git/gitgrep.cpp b/src/plugins/git/gitgrep.cpp index 24990008cb5..fdb0f202e25 100644 --- a/src/plugins/git/gitgrep.cpp +++ b/src/plugins/git/gitgrep.cpp @@ -126,13 +126,13 @@ public: } } - void read(QPromise &promise, const QString &input) + int read(QPromise &promise, const QString &input) { SearchResultItems items; QStringView remainingInput(input); while (true) { if (promise.isCanceled()) - return; + return 0; if (remainingInput.isEmpty()) break; @@ -145,6 +145,7 @@ public: } if (!items.isEmpty()) promise.addResult(items); + return items.count(); } void operator()(QPromise &promise) @@ -181,26 +182,66 @@ public: }); arguments << "--" << filterArgs << exclusionArgs; + QEventLoop loop; + Process process; process.setEnvironment(m_environment); process.setCommand({m_vcsBinary, arguments}); process.setWorkingDirectory(m_directory); - process.setStdOutCallback([this, &promise](const QString &text) { read(promise, text); }); - process.start(); - process.waitForFinished(); + QStringList outputBuffer; + // The states transition exactly in this order: + enum State { BelowLimit, AboveLimit, Paused, Resumed }; + State state = BelowLimit; + int reportedResultsCount = 0; + process.setStdOutCallback([this, &process, &loop, &promise, &state, &reportedResultsCount, + &outputBuffer](const QString &output) { + if (promise.isCanceled()) { + process.close(); + loop.quit(); + return; + } + // The SearchResultWidget is going to pause the search anyway, so start buffering + // the output. + if (state == AboveLimit || state == Paused) { + outputBuffer.append(output); + } else { + reportedResultsCount += read(promise, output); + if (state == BelowLimit && reportedResultsCount > 200000) + state = AboveLimit; + } + }); + QObject::connect(&process, &Process::done, &loop, [&loop, &promise, &state] { + if (state == BelowLimit || state == Resumed || promise.isCanceled()) + loop.quit(); + }); - switch (process.result()) { - case ProcessResult::TerminatedAbnormally: - case ProcessResult::StartFailed: - case ProcessResult::Hang: - promise.future().cancel(); - break; - case ProcessResult::FinishedWithSuccess: - case ProcessResult::FinishedWithError: - // When no results are found, git-grep exits with non-zero status. - // Do not consider this as an error. - break; - } + process.start(); + if (process.state() == QProcess::NotRunning) + return; + + QFutureWatcher watcher; + QFuture future(promise.future()); + QObject::connect(&watcher, &QFutureWatcherBase::canceled, &loop, [&process, &loop] { + process.close(); + loop.quit(); + }); + QObject::connect(&watcher, &QFutureWatcherBase::paused, &loop, [&state] { state = Paused; }); + QObject::connect(&watcher, &QFutureWatcherBase::resumed, &loop, + [this, &process, &loop, &promise, &state, &outputBuffer] { + state = Resumed; + for (const QString &output : outputBuffer) { + if (promise.isCanceled()) { + process.close(); + loop.quit(); + } + read(promise, output); + } + outputBuffer.clear(); + if (process.state() == QProcess::NotRunning) + loop.quit(); + }); + watcher.setFuture(future); + loop.exec(QEventLoop::ExcludeUserInputEvents); } private: From 8da3575d7290be5002f06a363a622fd4ba70b803 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Thu, 1 Jun 2023 20:43:37 +0200 Subject: [PATCH 104/141] BaseFileFind: Introduce searchInProcessOutput() To be used by SilverSearcher and GitGrep. Change-Id: I16a5fa18a90e6c895658ebc9dd8fd209235e17d3 Reviewed-by: Qt CI Bot Reviewed-by: Orgad Shaneh --- src/plugins/texteditor/basefilefind.cpp | 93 +++++++++++++++++++++++++ src/plugins/texteditor/basefilefind.h | 11 +++ 2 files changed, 104 insertions(+) diff --git a/src/plugins/texteditor/basefilefind.cpp b/src/plugins/texteditor/basefilefind.cpp index 8a75a27910c..99f37d05eac 100644 --- a/src/plugins/texteditor/basefilefind.cpp +++ b/src/plugins/texteditor/basefilefind.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -38,6 +39,98 @@ using namespace Utils; using namespace Core; namespace TextEditor { + +static std::optional regExpFromParameters(const FileFindParameters ¶meters) +{ + if (!(parameters.flags & FindRegularExpression)) + return {}; + + const QRegularExpression::PatternOptions options = parameters.flags & FindCaseSensitively + ? QRegularExpression::NoPatternOption : QRegularExpression::CaseInsensitiveOption; + QRegularExpression regExp; + regExp.setPattern(parameters.text); + regExp.setPatternOptions(options); + return regExp; +} + +void searchInProcessOutput(QPromise &promise, + const FileFindParameters ¶meters, + const ProcessSetupHandler &processSetupHandler, + const ProcessOutputParser &processOutputParser) +{ + if (promise.isCanceled()) + return; + + QEventLoop loop; + + Process process; + processSetupHandler(process); + + const std::optional regExp = regExpFromParameters(parameters); + QStringList outputBuffer; + // The states transition exactly in this order: + enum State { BelowLimit, AboveLimit, Paused, Resumed }; + State state = BelowLimit; + int reportedItemsCount = 0; + QFuture future(promise.future()); + process.setStdOutCallback([&](const QString &output) { + if (promise.isCanceled()) { + process.close(); + loop.quit(); + return; + } + // The SearchResultWidget is going to pause the search anyway, so start buffering + // the output. + if (state == AboveLimit || state == Paused) { + outputBuffer.append(output); + } else { + const SearchResultItems items = processOutputParser(future, output, regExp); + if (!items.isEmpty()) + promise.addResult(items); + reportedItemsCount += items.size(); + if (state == BelowLimit && reportedItemsCount > 200000) + state = AboveLimit; + } + }); + QObject::connect(&process, &Process::done, &loop, [&loop, &promise, &state] { + if (state == BelowLimit || state == Resumed || promise.isCanceled()) + loop.quit(); + }); + + if (promise.isCanceled()) + return; + + process.start(); + if (process.state() == QProcess::NotRunning) + return; + + QFutureWatcher watcher; + QObject::connect(&watcher, &QFutureWatcherBase::canceled, &loop, [&process, &loop] { + process.close(); + loop.quit(); + }); + QObject::connect(&watcher, &QFutureWatcherBase::paused, &loop, [&state] { state = Paused; }); + QObject::connect(&watcher, &QFutureWatcherBase::resumed, &loop, [&] { + state = Resumed; + for (const QString &output : outputBuffer) { + if (promise.isCanceled()) { + process.close(); + loop.quit(); + } + const SearchResultItems items = processOutputParser(future, output, regExp); + if (!items.isEmpty()) + promise.addResult(items); + } + outputBuffer.clear(); + if (process.state() == QProcess::NotRunning) + loop.quit(); + }); + watcher.setFuture(future); + if (promise.isCanceled()) + return; + loop.exec(QEventLoop::ExcludeUserInputEvents); +} + namespace Internal { class InternalEngine : public TextEditor::SearchEngine diff --git a/src/plugins/texteditor/basefilefind.h b/src/plugins/texteditor/basefilefind.h index b564b35c0c1..c8555f03deb 100644 --- a/src/plugins/texteditor/basefilefind.h +++ b/src/plugins/texteditor/basefilefind.h @@ -20,6 +20,7 @@ class SearchResult; namespace Utils { class FileIterator; +class Process; } namespace TextEditor { @@ -41,6 +42,16 @@ public: Core::FindFlags flags; }; +using ProcessSetupHandler = std::function; +using ProcessOutputParser = std::function &, const QString &, const std::optional &)>; + +// Call it from a non-main thread only, it's a blocking invocation. +void TEXTEDITOR_EXPORT searchInProcessOutput(QPromise &promise, + const FileFindParameters ¶meters, + const ProcessSetupHandler &processSetupHandler, + const ProcessOutputParser &processOutputParser); + class BaseFileFind; class TEXTEDITOR_EXPORT SearchEngine : public QObject From 64d209c24bb618fee5e0d4ba427d656c3b71e5ff Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Thu, 1 Jun 2023 21:04:18 +0200 Subject: [PATCH 105/141] SilverSearcher: Reuse searchInProcessOutput() Change-Id: Ifc28a88c7bd0de94ea78c5f3eaaa2179b0aee600 Reviewed-by: Qt CI Bot Reviewed-by: Orgad Shaneh --- .../findinfilessilversearcher.cpp | 127 +++++------------- .../silversearcher/silversearcherparser.cpp | 31 ++--- .../silversearcher/silversearcherparser.h | 15 +-- 3 files changed, 48 insertions(+), 125 deletions(-) diff --git a/src/plugins/silversearcher/findinfilessilversearcher.cpp b/src/plugins/silversearcher/findinfilessilversearcher.cpp index 313d23eda27..6cf428bb64f 100644 --- a/src/plugins/silversearcher/findinfilessilversearcher.cpp +++ b/src/plugins/silversearcher/findinfilessilversearcher.cpp @@ -59,114 +59,51 @@ static bool isSilverSearcherAvailable() && silverSearcherProcess.cleanedStdOut().contains("ag version"); } -static std::optional regExpFromParameters(const FileFindParameters ¶meters) -{ - if (!(parameters.flags & FindRegularExpression)) - return {}; - - const QRegularExpression::PatternOptions patternOptions - = (parameters.flags & FindCaseSensitively) - ? QRegularExpression::NoPatternOption - : QRegularExpression::CaseInsensitiveOption; - QRegularExpression regExp; - regExp.setPattern(parameters.text); - regExp.setPatternOptions(patternOptions); - return regExp; -} - static void runSilverSeacher(QPromise &promise, const FileFindParameters ¶meters) { - const FilePath directory = FilePath::fromUserInput(parameters.additionalParameters.toString()); - QStringList arguments = {"--parallel", "--ackmate"}; + const auto setupProcess = [parameters](Process &process) { + const FilePath directory + = FilePath::fromUserInput(parameters.additionalParameters.toString()); + QStringList arguments = {"--parallel", "--ackmate"}; - if (parameters.flags & FindCaseSensitively) - arguments << "-s"; - else - arguments << "-i"; + if (parameters.flags & FindCaseSensitively) + arguments << "-s"; + else + arguments << "-i"; - if (parameters.flags & FindWholeWords) - arguments << "-w"; + if (parameters.flags & FindWholeWords) + arguments << "-w"; - if (!(parameters.flags & FindRegularExpression)) - arguments << "-Q"; + if (!(parameters.flags & FindRegularExpression)) + arguments << "-Q"; - for (const QString &filter : std::as_const(parameters.exclusionFilters)) - arguments << "--ignore" << filter; + for (const QString &filter : std::as_const(parameters.exclusionFilters)) + arguments << "--ignore" << filter; - QString nameFiltersAsRegExp; - for (const QString &filter : std::as_const(parameters.nameFilters)) - nameFiltersAsRegExp += QString("(%1)|").arg(convertWildcardToRegex(filter)); - nameFiltersAsRegExp.remove(nameFiltersAsRegExp.length() - 1, 1); + QString nameFiltersAsRegExp; + for (const QString &filter : std::as_const(parameters.nameFilters)) + nameFiltersAsRegExp += QString("(%1)|").arg(convertWildcardToRegex(filter)); + nameFiltersAsRegExp.remove(nameFiltersAsRegExp.length() - 1, 1); - arguments << "-G" << nameFiltersAsRegExp; + arguments << "-G" << nameFiltersAsRegExp; - const SilverSearcherSearchOptions params = parameters.searchEngineParameters - .value(); - if (!params.searchOptions.isEmpty()) - arguments << params.searchOptions.split(' '); + const SilverSearcherSearchOptions params = parameters.searchEngineParameters + .value(); + if (!params.searchOptions.isEmpty()) + arguments << params.searchOptions.split(' '); - arguments << "--" << parameters.text << directory.normalizedPathName().toString(); + arguments << "--" << parameters.text << directory.normalizedPathName().toString(); + process.setCommand({"ag", arguments}); + }; - QEventLoop loop; + FilePath lastFilePath; + const auto outputParser = [&lastFilePath](const QFuture &future, const QString &input, + const std::optional ®Exp) { + return SilverSearcher::parse(future, input, regExp, &lastFilePath); + }; - Process process; - process.setCommand({"ag", arguments}); - ParserState parserState; - const std::optional regExp = regExpFromParameters(parameters); - QStringList outputBuffer; - // The states transition exactly in this order: - enum State { BelowLimit, AboveLimit, Paused, Resumed }; - State state = BelowLimit; - process.setStdOutCallback([&process, &loop, &promise, &state, &outputBuffer, &parserState, - regExp](const QString &output) { - if (promise.isCanceled()) { - process.close(); - loop.quit(); - return; - } - // The SearchResultWidget is going to pause the search anyway, so start buffering - // the output. - if (state == AboveLimit || state == Paused) { - outputBuffer.append(output); - } else { - SilverSearcher::parse(promise, output, &parserState, regExp); - if (state == BelowLimit && parserState.m_reportedResultsCount > 200000) - state = AboveLimit; - } - }); - QObject::connect(&process, &Process::done, &loop, [&loop, &promise, &state] { - if (state == BelowLimit || state == Resumed || promise.isCanceled()) - loop.quit(); - }); - - process.start(); - if (process.state() == QProcess::NotRunning) - return; - - QFutureWatcher watcher; - QFuture future(promise.future()); - QObject::connect(&watcher, &QFutureWatcherBase::canceled, &loop, [&process, &loop] { - process.close(); - loop.quit(); - }); - QObject::connect(&watcher, &QFutureWatcherBase::paused, &loop, [&state] { state = Paused; }); - QObject::connect(&watcher, &QFutureWatcherBase::resumed, &loop, - [&process, &loop, &promise, &state, &outputBuffer, &parserState, regExp] { - state = Resumed; - for (const QString &output : outputBuffer) { - if (promise.isCanceled()) { - process.close(); - loop.quit(); - } - SilverSearcher::parse(promise, output, &parserState, regExp); - } - outputBuffer.clear(); - if (process.state() == QProcess::NotRunning) - loop.quit(); - }); - watcher.setFuture(future); - loop.exec(QEventLoop::ExcludeUserInputEvents); + TextEditor::searchInProcessOutput(promise, parameters, setupProcess, outputParser); } } // namespace diff --git a/src/plugins/silversearcher/silversearcherparser.cpp b/src/plugins/silversearcher/silversearcherparser.cpp index 9cdf5211a67..1a2f5e55e87 100644 --- a/src/plugins/silversearcher/silversearcherparser.cpp +++ b/src/plugins/silversearcher/silversearcherparser.cpp @@ -3,8 +3,6 @@ #include "silversearcherparser.h" -#include - using namespace Utils; namespace SilverSearcher { @@ -96,28 +94,28 @@ static bool parseLineHits(QStringView *remainingInput, QList> *h return true; } -void parse(QPromise &promise, const QString &input, - ParserState *parserState, const std::optional ®Exp) +SearchResultItems parse(const QFuture &future, const QString &input, + const std::optional ®Exp, FilePath *lastFilePath) { - QTC_ASSERT(parserState, return); + QTC_ASSERT(lastFilePath, return {}); SearchResultItems items; QStringView remainingInput(input); while (true) { - if (promise.isCanceled()) - return; + if (future.isCanceled()) + return {}; if (remainingInput.isEmpty()) break; const QStringView filePathLine = nextLine(&remainingInput); if (filePathLine.isEmpty()) { - parserState->m_lastFilePath = {}; // Clear the parser state + *lastFilePath = {}; // Clear the parser state continue; } if (filePathLine.startsWith(':')) - parserState->m_lastFilePath = FilePath::fromPathPart(filePathLine.mid(1)); + *lastFilePath = FilePath::fromPathPart(filePathLine.mid(1)); while (true) { QStringView hitLine = nextLine(&remainingInput); @@ -133,7 +131,7 @@ void parse(QPromise &promise, const QString &input, break; SearchResultItem item; - item.setFilePath(parserState->m_lastFilePath); + item.setFilePath(*lastFilePath); item.setDisplayText(hitLine.toString()); item.setUseTextEditorFont(true); for (const QPair &hit : hits) { @@ -145,20 +143,15 @@ void parse(QPromise &promise, const QString &input, } } } - if (!items.isEmpty()) - promise.addResult(items); - - parserState->m_reportedResultsCount += items.count(); + return items; } SearchResultItems parse(const QString &input, const std::optional ®Exp) { - QPromise promise; + QPromise promise; promise.start(); - ParserState dummy; - SilverSearcher::parse(promise, input, &dummy, regExp); - promise.finish(); - return promise.future().resultCount() ? promise.future().result() : SearchResultItems(); + FilePath dummy; + return SilverSearcher::parse(promise.future(), input, regExp, &dummy); } } // namespace SilverSearcher diff --git a/src/plugins/silversearcher/silversearcherparser.h b/src/plugins/silversearcher/silversearcherparser.h index 1cc5ccb773c..67b3e124f42 100644 --- a/src/plugins/silversearcher/silversearcherparser.h +++ b/src/plugins/silversearcher/silversearcherparser.h @@ -5,23 +5,16 @@ #include -#include +#include #include namespace Utils { class FilePath; } namespace SilverSearcher { -class ParserState -{ -public: - Utils::FilePath m_lastFilePath; - int m_reportedResultsCount = 0; -}; - -void parse(QPromise &promise, const QString &input, - ParserState *parserState = nullptr, - const std::optional ®Exp = {}); +Utils::SearchResultItems parse(const QFuture &future, const QString &input, + const std::optional ®Exp, + Utils::FilePath *lastFilePath); Utils::SearchResultItems parse(const QString &input, const std::optional ®Exp = {}); From f10581ee31ad7a9b9f2e0632fce1eeb196cd2904 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Thu, 1 Jun 2023 21:42:18 +0200 Subject: [PATCH 106/141] GitGrep: Reuse searchInProcessOutput() Change-Id: I5e97f23c0e2a06ccd3d204977ac1abc986b84e5c Reviewed-by: Orgad Shaneh Reviewed-by: Reviewed-by: Qt CI Bot --- src/plugins/git/gitgrep.cpp | 292 ++++++++++++++---------------------- src/plugins/git/gitgrep.h | 5 +- 2 files changed, 112 insertions(+), 185 deletions(-) diff --git a/src/plugins/git/gitgrep.cpp b/src/plugins/git/gitgrep.cpp index fdb0f202e25..f6324f152de 100644 --- a/src/plugins/git/gitgrep.cpp +++ b/src/plugins/git/gitgrep.cpp @@ -21,12 +21,12 @@ #include #include -#include #include #include #include using namespace Core; +using namespace TextEditor; using namespace Utils; using namespace VcsBase; @@ -55,101 +55,93 @@ static QStringView nextLine(QStringView *remainingInput) return ret; } -class GitGrepRunner +struct Match { -public: - GitGrepRunner(const TextEditor::FileFindParameters ¶meters) - : m_parameters(parameters) - { - m_directory = FilePath::fromString(parameters.additionalParameters.toString()); - m_vcsBinary = GitClient::instance()->vcsBinary(); - m_environment = GitClient::instance()->processEnvironment(); - if (m_parameters.flags & FindRegularExpression) { - const QRegularExpression::PatternOptions patternOptions - = m_parameters.flags & FindCaseSensitively - ? QRegularExpression::NoPatternOption - : QRegularExpression::CaseInsensitiveOption; - m_regexp.setPattern(m_parameters.text); - m_regexp.setPatternOptions(patternOptions); - } + Match() = default; + Match(int start, int length) : + matchStart(start), matchLength(length) {} + + int matchStart = 0; + int matchLength = 0; + QStringList regexpCapturedTexts; +}; + +static void processLine(QStringView line, SearchResultItems *resultList, + const std::optional ®Exp, const QString &ref, + const FilePath &directory) +{ + if (line.isEmpty()) + return; + static const QLatin1String boldRed("\x1b[1;31m"); + static const QLatin1String resetColor("\x1b[m"); + SearchResultItem result; + const int lineSeparator = line.indexOf(QChar::Null); + QStringView filePath = line.left(lineSeparator); + if (!ref.isEmpty() && filePath.startsWith(ref)) + filePath = filePath.mid(ref.length()); + result.setFilePath(directory.pathAppended(filePath.toString())); + const int textSeparator = line.indexOf(QChar::Null, lineSeparator + 1); + const int lineNumber = line.mid(lineSeparator + 1, textSeparator - lineSeparator - 1).toInt(); + QString text = line.mid(textSeparator + 1).toString(); + QList matches; + while (true) { + const int matchStart = text.indexOf(boldRed); + if (matchStart == -1) + break; + const int matchTextStart = matchStart + boldRed.size(); + const int matchEnd = text.indexOf(resetColor, matchTextStart); + QTC_ASSERT(matchEnd != -1, break); + const int matchLength = matchEnd - matchTextStart; + Match match(matchStart, matchLength); + const QString matchText = text.mid(matchTextStart, matchLength); + if (regExp) + match.regexpCapturedTexts = regExp->match(matchText).capturedTexts(); + matches.append(match); + text = text.left(matchStart) + matchText + text.mid(matchEnd + resetColor.size()); } + result.setDisplayText(text); - struct Match - { - Match() = default; - Match(int start, int length) : - matchStart(start), matchLength(length) {} + for (const auto &match : std::as_const(matches)) { + result.setMainRange(lineNumber, match.matchStart, match.matchLength); + result.setUserData(match.regexpCapturedTexts); + result.setUseTextEditorFont(true); + resultList->append(result); + } +} - int matchStart = 0; - int matchLength = 0; - QStringList regexpCapturedTexts; - }; +static SearchResultItems parse(const QFuture &future, const QString &input, + const std::optional ®Exp, const QString &ref, + const FilePath &directory) +{ + SearchResultItems items; + QStringView remainingInput(input); + while (true) { + if (future.isCanceled()) + return {}; - void processLine(QStringView line, SearchResultItems *resultList) const - { + if (remainingInput.isEmpty()) + break; + + const QStringView line = nextLine(&remainingInput); if (line.isEmpty()) - return; - static const QLatin1String boldRed("\x1b[1;31m"); - static const QLatin1String resetColor("\x1b[m"); - SearchResultItem result; - const int lineSeparator = line.indexOf(QChar::Null); - QStringView filePath = line.left(lineSeparator); - if (!m_ref.isEmpty() && filePath.startsWith(m_ref)) - filePath = filePath.mid(m_ref.length()); - result.setFilePath(m_directory.pathAppended(filePath.toString())); - const int textSeparator = line.indexOf(QChar::Null, lineSeparator + 1); - const int lineNumber = line.mid(lineSeparator + 1, textSeparator - lineSeparator - 1).toInt(); - QString text = line.mid(textSeparator + 1).toString(); - QList matches; - while (true) { - const int matchStart = text.indexOf(boldRed); - if (matchStart == -1) - break; - const int matchTextStart = matchStart + boldRed.size(); - const int matchEnd = text.indexOf(resetColor, matchTextStart); - QTC_ASSERT(matchEnd != -1, break); - const int matchLength = matchEnd - matchTextStart; - Match match(matchStart, matchLength); - const QString matchText = text.mid(matchTextStart, matchLength); - if (m_parameters.flags & FindRegularExpression) - match.regexpCapturedTexts = m_regexp.match(matchText).capturedTexts(); - matches.append(match); - text = text.left(matchStart) + matchText + text.mid(matchEnd + resetColor.size()); - } - result.setDisplayText(text); + continue; - for (const auto &match : std::as_const(matches)) { - result.setMainRange(lineNumber, match.matchStart, match.matchLength); - result.setUserData(match.regexpCapturedTexts); - result.setUseTextEditorFont(true); - resultList->append(result); - } + processLine(line, &items, regExp, ref, directory); } + return items; +} - int read(QPromise &promise, const QString &input) - { - SearchResultItems items; - QStringView remainingInput(input); - while (true) { - if (promise.isCanceled()) - return 0; +static void runGitGrep(QPromise &promise, const FileFindParameters ¶meters) +{ + const FilePath directory = FilePath::fromString(parameters.additionalParameters.toString()); + const GitGrepParameters gitParameters + = parameters.searchEngineParameters.value(); + const QString ref = gitParameters.ref.isEmpty() ? QString() : gitParameters.ref + ':'; - if (remainingInput.isEmpty()) - break; + const auto setupProcess = [&](Process &process) { + const FilePath vcsBinary = GitClient::instance()->vcsBinary(); + const Environment environment = GitClient::instance()->processEnvironment(); - const QStringView line = nextLine(&remainingInput); - if (line.isEmpty()) - continue; - - processLine(line, &items); - } - if (!items.isEmpty()) - promise.addResult(items); - return items.count(); - } - - void operator()(QPromise &promise) - { QStringList arguments = { "-c", "color.grep.match=bold red", "-c", "color.grep=always", @@ -157,101 +149,41 @@ public: "-c", "color.grep.lineNumber=", "grep", "-zn", "--no-full-name" }; - if (!(m_parameters.flags & FindCaseSensitively)) + if (!(parameters.flags & FindCaseSensitively)) arguments << "-i"; - if (m_parameters.flags & FindWholeWords) + if (parameters.flags & FindWholeWords) arguments << "-w"; - if (m_parameters.flags & FindRegularExpression) + if (parameters.flags & FindRegularExpression) arguments << "-P"; else arguments << "-F"; - arguments << "-e" << m_parameters.text; - GitGrepParameters params = m_parameters.searchEngineParameters.value(); - if (params.recurseSubmodules) + arguments << "-e" << parameters.text; + if (gitParameters.recurseSubmodules) arguments << "--recurse-submodules"; - if (!params.ref.isEmpty()) { - arguments << params.ref; - m_ref = params.ref + ':'; + if (!gitParameters.ref.isEmpty()) { + arguments << gitParameters.ref; } const QStringList filterArgs = - m_parameters.nameFilters.isEmpty() ? QStringList("*") // needed for exclusion filters - : m_parameters.nameFilters; + parameters.nameFilters.isEmpty() ? QStringList("*") // needed for exclusion filters + : parameters.nameFilters; const QStringList exclusionArgs = - Utils::transform(m_parameters.exclusionFilters, [](const QString &filter) { - return QString(":!" + filter); - }); + Utils::transform(parameters.exclusionFilters, [](const QString &filter) { + return QString(":!" + filter); + }); arguments << "--" << filterArgs << exclusionArgs; - QEventLoop loop; + process.setEnvironment(environment); + process.setCommand({vcsBinary, arguments}); + process.setWorkingDirectory(directory); + }; - Process process; - process.setEnvironment(m_environment); - process.setCommand({m_vcsBinary, arguments}); - process.setWorkingDirectory(m_directory); - QStringList outputBuffer; - // The states transition exactly in this order: - enum State { BelowLimit, AboveLimit, Paused, Resumed }; - State state = BelowLimit; - int reportedResultsCount = 0; - process.setStdOutCallback([this, &process, &loop, &promise, &state, &reportedResultsCount, - &outputBuffer](const QString &output) { - if (promise.isCanceled()) { - process.close(); - loop.quit(); - return; - } - // The SearchResultWidget is going to pause the search anyway, so start buffering - // the output. - if (state == AboveLimit || state == Paused) { - outputBuffer.append(output); - } else { - reportedResultsCount += read(promise, output); - if (state == BelowLimit && reportedResultsCount > 200000) - state = AboveLimit; - } - }); - QObject::connect(&process, &Process::done, &loop, [&loop, &promise, &state] { - if (state == BelowLimit || state == Resumed || promise.isCanceled()) - loop.quit(); - }); + const auto outputParser = [&ref, &directory](const QFuture &future, const QString &input, + const std::optional ®Exp) { + return parse(future, input, regExp, ref, directory); + }; - process.start(); - if (process.state() == QProcess::NotRunning) - return; - - QFutureWatcher watcher; - QFuture future(promise.future()); - QObject::connect(&watcher, &QFutureWatcherBase::canceled, &loop, [&process, &loop] { - process.close(); - loop.quit(); - }); - QObject::connect(&watcher, &QFutureWatcherBase::paused, &loop, [&state] { state = Paused; }); - QObject::connect(&watcher, &QFutureWatcherBase::resumed, &loop, - [this, &process, &loop, &promise, &state, &outputBuffer] { - state = Resumed; - for (const QString &output : outputBuffer) { - if (promise.isCanceled()) { - process.close(); - loop.quit(); - } - read(promise, output); - } - outputBuffer.clear(); - if (process.state() == QProcess::NotRunning) - loop.quit(); - }); - watcher.setFuture(future); - loop.exec(QEventLoop::ExcludeUserInputEvents); - } - -private: - FilePath m_vcsBinary; - FilePath m_directory; - QString m_ref; - TextEditor::FileFindParameters m_parameters; - Environment m_environment; - QRegularExpression m_regexp; -}; + TextEditor::searchInProcessOutput(promise, parameters, setupProcess, outputParser); +} static bool isGitDirectory(const FilePath &path) { @@ -274,18 +206,16 @@ GitGrep::GitGrep(GitClient *client) m_treeLineEdit->setValidator(new QRegularExpressionValidator(refExpression, this)); layout->addWidget(m_treeLineEdit); // asynchronously check git version, add "recurse submodules" option if available - Utils::onResultReady(client->gitVersion(), - this, + Utils::onResultReady(client->gitVersion(), this, [this, pLayout = QPointer(layout)](unsigned version) { - if (version >= 0x021300 && pLayout) { - m_recurseSubmodules = new QCheckBox(Tr::tr("Recurse submodules")); - pLayout->addWidget(m_recurseSubmodules); - } - }); - TextEditor::FindInFiles *findInFiles = TextEditor::FindInFiles::instance(); + if (version >= 0x021300 && pLayout) { + m_recurseSubmodules = new QCheckBox(Tr::tr("Recurse submodules")); + pLayout->addWidget(m_recurseSubmodules); + } + }); + FindInFiles *findInFiles = FindInFiles::instance(); QTC_ASSERT(findInFiles, return); - connect(findInFiles, &TextEditor::FindInFiles::pathChanged, - m_widget, [this](const FilePath &path) { + connect(findInFiles, &FindInFiles::pathChanged, m_widget, [this](const FilePath &path) { setEnabled(isGitDirectory(path)); }); connect(this, &SearchEngine::enabledChanged, m_widget, &QWidget::setEnabled); @@ -334,14 +264,14 @@ void GitGrep::writeSettings(QSettings *settings) const settings->setValue(GitGrepRef, m_treeLineEdit->text()); } -QFuture GitGrep::executeSearch(const TextEditor::FileFindParameters ¶meters, - TextEditor::BaseFileFind * /*baseFileFind*/) +QFuture GitGrep::executeSearch(const FileFindParameters ¶meters, + BaseFileFind *) { - return Utils::asyncRun(GitGrepRunner(parameters)); + return Utils::asyncRun(runGitGrep, parameters); } IEditor *GitGrep::openEditor(const SearchResultItem &item, - const TextEditor::FileFindParameters ¶meters) + const FileFindParameters ¶meters) { const GitGrepParameters params = parameters.searchEngineParameters.value(); const QStringList &itemPath = item.path(); diff --git a/src/plugins/git/gitgrep.h b/src/plugins/git/gitgrep.h index 2fd114e36ec..fda6fe56ebd 100644 --- a/src/plugins/git/gitgrep.h +++ b/src/plugins/git/gitgrep.h @@ -9,10 +9,7 @@ QT_BEGIN_NAMESPACE class QCheckBox; QT_END_NAMESPACE -namespace Utils { -class FancyLineEdit; -class SearchResultItem; -} +namespace Utils { class FancyLineEdit; } namespace Git::Internal { From 59862702327104f9dd7e9b5fd879d65e4eb57ebd Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 1 Jun 2023 18:17:33 +0200 Subject: [PATCH 107/141] QMakeProjectManager: Remove compatibility reading For versions less then 4.12 (2019). Change-Id: I566189eafe6deb1ed29b2e004a38cdd4295ea9b0 Reviewed-by: Christian Kandeler --- src/plugins/qmakeprojectmanager/qmakestep.cpp | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/plugins/qmakeprojectmanager/qmakestep.cpp b/src/plugins/qmakeprojectmanager/qmakestep.cpp index c747f756581..0da8bebaad2 100644 --- a/src/plugins/qmakeprojectmanager/qmakestep.cpp +++ b/src/plugins/qmakeprojectmanager/qmakestep.cpp @@ -455,21 +455,6 @@ bool QMakeStep::fromMap(const QVariantMap &map) { m_forced = map.value(QMAKE_FORCED_KEY, false).toBool(); m_selectedAbis = map.value(QMAKE_SELECTED_ABIS_KEY).toStringList(); - - // Backwards compatibility with < Creator 4.12. - const QVariant separateDebugInfo - = map.value("QtProjectManager.QMakeBuildStep.SeparateDebugInfo"); - if (separateDebugInfo.isValid()) - qmakeBuildConfiguration()->forceSeparateDebugInfo(separateDebugInfo.toBool()); - const QVariant qmlDebugging - = map.value("QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary"); - if (qmlDebugging.isValid()) - qmakeBuildConfiguration()->forceQmlDebugging(qmlDebugging.toBool()); - const QVariant useQtQuickCompiler - = map.value("QtProjectManager.QMakeBuildStep.UseQtQuickCompiler"); - if (useQtQuickCompiler.isValid()) - qmakeBuildConfiguration()->forceQtQuickCompiler(useQtQuickCompiler.toBool()); - return BuildStep::fromMap(map); } From c8e1333f89ae10b3e2c571faeaf5792a077ffac9 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 1 Jun 2023 17:51:16 +0200 Subject: [PATCH 108/141] ProjectExplorer: Remove 4.11 compatibility code in buildsteplist Change-Id: Id0e65f17dcd4697e3c4d1f828a564b495e114ee4 Reviewed-by: Christian Kandeler --- src/plugins/projectexplorer/buildsteplist.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/plugins/projectexplorer/buildsteplist.cpp b/src/plugins/projectexplorer/buildsteplist.cpp index 8d6159541ef..0094bf0b683 100644 --- a/src/plugins/projectexplorer/buildsteplist.cpp +++ b/src/plugins/projectexplorer/buildsteplist.cpp @@ -43,16 +43,6 @@ QVariantMap BuildStepList::toMap() const { QVariantMap map; - { - // Only written for compatibility reasons within the 4.11 cycle - const char CONFIGURATION_ID_KEY[] = "ProjectExplorer.ProjectConfiguration.Id"; - const char DISPLAY_NAME_KEY[] = "ProjectExplorer.ProjectConfiguration.DisplayName"; - const char DEFAULT_DISPLAY_NAME_KEY[] = "ProjectExplorer.ProjectConfiguration.DefaultDisplayName"; - map.insert(QLatin1String(CONFIGURATION_ID_KEY), m_id.toSetting()); - map.insert(QLatin1String(DISPLAY_NAME_KEY), displayName()); - map.insert(QLatin1String(DEFAULT_DISPLAY_NAME_KEY), displayName()); - } - // Save build steps map.insert(QString::fromLatin1(STEPS_COUNT_KEY), m_steps.count()); for (int i = 0; i < m_steps.count(); ++i) From 5bacd9328eaef0a3ec8917df769ab6b7850dcc02 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 1 Jun 2023 11:15:16 +0200 Subject: [PATCH 109/141] Utils: Add a overload taking a AspecContainer for TextDisplay Change-Id: If6cc933e852b80c4ec6abcc2477db8852392ca69 Reviewed-by: Christian Stenger Reviewed-by: Qt CI Patch Build Bot --- src/libs/utils/aspects.cpp | 4 ++++ src/libs/utils/aspects.h | 1 + 2 files changed, 5 insertions(+) diff --git a/src/libs/utils/aspects.cpp b/src/libs/utils/aspects.cpp index 3dc5da0a4b4..57d358a7c1b 100644 --- a/src/libs/utils/aspects.cpp +++ b/src/libs/utils/aspects.cpp @@ -2346,6 +2346,10 @@ void IntegersAspect::setDefaultValue(const QList &value) A text display does not have a real value. */ +TextDisplay::TextDisplay(AspectContainer *container) + : BaseAspect(container) +{} + /*! Constructs a text display showing the \a message with an icon representing type \a type. diff --git a/src/libs/utils/aspects.h b/src/libs/utils/aspects.h index a0ebf5a045a..b99c28c0bef 100644 --- a/src/libs/utils/aspects.h +++ b/src/libs/utils/aspects.h @@ -610,6 +610,7 @@ class QTCREATOR_UTILS_EXPORT TextDisplay : public BaseAspect Q_OBJECT public: + explicit TextDisplay(AspectContainer *container); TextDisplay(const QString &message = {}, InfoLabel::InfoType type = InfoLabel::None); ~TextDisplay() override; From e759ce310fe6f30724f29b809bf0bcab1df88e1d Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Wed, 31 May 2023 19:10:05 +0200 Subject: [PATCH 110/141] Core: Use LayoutBuilder in PluginDialog Change-Id: I06b07234727fc46a717af89febae43af1cb67b9b Reviewed-by: Eike Ziller Reviewed-by: Reviewed-by: Qt CI Patch Build Bot --- src/plugins/coreplugin/plugindialog.cpp | 58 +++++++++---------- .../coreplugin/plugininstallwizard.cpp | 43 +++++--------- 2 files changed, 43 insertions(+), 58 deletions(-) diff --git a/src/plugins/coreplugin/plugindialog.cpp b/src/plugins/coreplugin/plugindialog.cpp index f6ea25e719c..24d8c8dff12 100644 --- a/src/plugins/coreplugin/plugindialog.cpp +++ b/src/plugins/coreplugin/plugindialog.cpp @@ -17,14 +17,11 @@ #include #include +#include -#include #include #include -#include -#include #include -#include using namespace Utils; @@ -35,30 +32,27 @@ PluginDialog::PluginDialog(QWidget *parent) : QDialog(parent), m_view(new ExtensionSystem::PluginView(this)) { - auto vl = new QVBoxLayout(this); - - auto filterLayout = new QHBoxLayout; - vl->addLayout(filterLayout); auto filterEdit = new Utils::FancyLineEdit(this); filterEdit->setFocus(); filterEdit->setFiltering(true); connect(filterEdit, &Utils::FancyLineEdit::filterChanged, m_view, &ExtensionSystem::PluginView::setFilter); - filterLayout->addWidget(filterEdit); - - vl->addWidget(m_view); - - m_detailsButton = new QPushButton(Tr::tr("Details"), this); - m_errorDetailsButton = new QPushButton(Tr::tr("Error Details"), this); - m_installButton = new QPushButton(Tr::tr("Install Plugin..."), this); - m_detailsButton->setEnabled(false); - m_errorDetailsButton->setEnabled(false); auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - buttonBox->addButton(m_detailsButton, QDialogButtonBox::ActionRole); - buttonBox->addButton(m_errorDetailsButton, QDialogButtonBox::ActionRole); - buttonBox->addButton(m_installButton, QDialogButtonBox::ActionRole); - vl->addWidget(buttonBox); + m_detailsButton = buttonBox->addButton(Tr::tr("Details"), QDialogButtonBox::ActionRole); + m_detailsButton->setEnabled(false); + m_errorDetailsButton = buttonBox->addButton(Tr::tr("Error Details"), + QDialogButtonBox::ActionRole); + m_errorDetailsButton->setEnabled(false); + m_installButton = buttonBox->addButton(Tr::tr("Install Plugin..."), + QDialogButtonBox::ActionRole); + + using namespace Layouting; + Column { + filterEdit, + m_view, + buttonBox, + }.attachTo(this); resize(650, 400); setWindowTitle(Tr::tr("Installed Plugins")); @@ -116,13 +110,16 @@ void PluginDialog::openDetails(ExtensionSystem::PluginSpec *spec) return; QDialog dialog(this); dialog.setWindowTitle(Tr::tr("Plugin Details of %1").arg(spec->name())); - auto layout = new QVBoxLayout; - dialog.setLayout(layout); auto details = new ExtensionSystem::PluginDetailsView(&dialog); - layout->addWidget(details); details->update(spec); QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Close, Qt::Horizontal, &dialog); - layout->addWidget(buttons); + + using namespace Layouting; + Column { + details, + buttons, + }.attachTo(&dialog); + connect(buttons, &QDialogButtonBox::accepted, &dialog, &QDialog::accept); connect(buttons, &QDialogButtonBox::rejected, &dialog, &QDialog::reject); dialog.resize(400, 500); @@ -136,13 +133,16 @@ void PluginDialog::openErrorDetails() return; QDialog dialog(this); dialog.setWindowTitle(Tr::tr("Plugin Errors of %1").arg(spec->name())); - auto layout = new QVBoxLayout; - dialog.setLayout(layout); auto errors = new ExtensionSystem::PluginErrorView(&dialog); - layout->addWidget(errors); errors->update(spec); QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Close, Qt::Horizontal, &dialog); - layout->addWidget(buttons); + + using namespace Layouting; + Column { + errors, + buttons, + }.attachTo(&dialog); + connect(buttons, &QDialogButtonBox::accepted, &dialog, &QDialog::accept); connect(buttons, &QDialogButtonBox::rejected, &dialog, &QDialog::reject); dialog.resize(500, 300); diff --git a/src/plugins/coreplugin/plugininstallwizard.cpp b/src/plugins/coreplugin/plugininstallwizard.cpp index c5694016d49..ac2dfd6c240 100644 --- a/src/plugins/coreplugin/plugininstallwizard.cpp +++ b/src/plugins/coreplugin/plugininstallwizard.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -33,7 +34,6 @@ #include #include #include -#include #include @@ -80,19 +80,15 @@ public: , m_data(data) { setTitle(Tr::tr("Source")); - auto vlayout = new QVBoxLayout; - setLayout(vlayout); auto label = new QLabel( "

" + Tr::tr("Choose source location. This can be a plugin library file or a zip file.") + "

"); label->setWordWrap(true); - vlayout->addWidget(label); auto chooser = new PathChooser; chooser->setExpectedKind(PathChooser::Any); - vlayout->addWidget(chooser); connect(chooser, &PathChooser::textChanged, this, [this, chooser] { m_data->sourcePath = chooser->filePath(); updateWarnings(); @@ -101,7 +97,8 @@ public: m_info = new InfoLabel; m_info->setType(InfoLabel::Error); m_info->setVisible(false); - vlayout->addWidget(m_info); + + Layouting::Column { label, chooser, m_info }.attachTo(this); } void updateWarnings() @@ -153,8 +150,6 @@ public: , m_data(data) { setTitle(Tr::tr("Check Archive")); - auto vlayout = new QVBoxLayout; - setLayout(vlayout); m_label = new InfoLabel; m_label->setElideMode(Qt::ElideNone); @@ -163,13 +158,11 @@ public: m_output = new QTextEdit; m_output->setReadOnly(true); - auto hlayout = new QHBoxLayout; - hlayout->addWidget(m_label, 1); - hlayout->addStretch(); - hlayout->addWidget(m_cancelButton); - - vlayout->addLayout(hlayout); - vlayout->addWidget(m_output); + using namespace Layouting; + Column { + Row { m_label, st, m_cancelButton }, + m_output, + }.attachTo(this); } void initializePage() final @@ -322,13 +315,9 @@ public: , m_data(data) { setTitle(Tr::tr("Install Location")); - auto vlayout = new QVBoxLayout; - setLayout(vlayout); auto label = new QLabel("

" + Tr::tr("Choose install location.") + "

"); label->setWordWrap(true); - vlayout->addWidget(label); - vlayout->addSpacing(10); auto localInstall = new QRadioButton(Tr::tr("User plugins")); localInstall->setChecked(!m_data->installIntoApplication); @@ -338,10 +327,6 @@ public: localLabel->setWordWrap(true); localLabel->setAttribute(Qt::WA_MacSmallSize, true); - vlayout->addWidget(localInstall); - vlayout->addWidget(localLabel); - vlayout->addSpacing(10); - auto appInstall = new QRadioButton( Tr::tr("%1 installation").arg(Constants::IDE_DISPLAY_NAME)); appInstall->setChecked(m_data->installIntoApplication); @@ -351,8 +336,11 @@ public: .arg(Constants::IDE_DISPLAY_NAME)); appLabel->setWordWrap(true); appLabel->setAttribute(Qt::WA_MacSmallSize, true); - vlayout->addWidget(appInstall); - vlayout->addWidget(appLabel); + + using namespace Layouting; + Column { + label, Space(10), localInstall, localLabel, Space(10), appInstall, appLabel, + }.attachTo(this); auto group = new QButtonGroup(this); group->addButton(localInstall); @@ -375,12 +363,9 @@ public: { setTitle(Tr::tr("Summary")); - auto vlayout = new QVBoxLayout; - setLayout(vlayout); - m_summaryLabel = new QLabel(this); m_summaryLabel->setWordWrap(true); - vlayout->addWidget(m_summaryLabel); + Layouting::Column { m_summaryLabel }.attachTo(this); } void initializePage() final From dc99f5ad6fb12b855fc5bf88cfb280b828aa8bb7 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Fri, 2 Jun 2023 16:43:48 +0200 Subject: [PATCH 111/141] Doc: Describe dragging and pinning the progress bar Task-number: QTCREATORBUG-28996 Change-Id: Iba9eb4b1f53645763c637221b9f11c3ff54d2855 Reviewed-by: Eike Ziller --- .../src/projects/creator-only/creator-projects-opening.qdoc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-opening.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-opening.qdoc index d06989e66fc..85d04903921 100644 --- a/doc/qtcreator/src/projects/creator-only/creator-projects-opening.qdoc +++ b/doc/qtcreator/src/projects/creator-only/creator-projects-opening.qdoc @@ -99,4 +99,7 @@ \image qtcreator-toggle-progress-bar.webp {Toggle Progress Details button} + You can drag the progress bar to another position. The position is saved for + later. Select the \inlineimage icons/pin.png + (\uicontrol Pin) button to pin the progress bar back to the toggle button. */ From e92a131644a1082b2e6cef832167ad7a81c444bc Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Fri, 2 Jun 2023 17:10:58 +0300 Subject: [PATCH 112/141] Terminal: Fix MSVC warning warning C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data Change-Id: I5d57843eba79f0eb023ea7e3c4149aa515430189 Reviewed-by: Marcus Tillmanns Reviewed-by: Qt CI Patch Build Bot --- src/plugins/terminal/terminalwidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/terminal/terminalwidget.cpp b/src/plugins/terminal/terminalwidget.cpp index 5027d390294..12a0521857c 100644 --- a/src/plugins/terminal/terminalwidget.cpp +++ b/src/plugins/terminal/terminalwidget.cpp @@ -72,7 +72,7 @@ static constexpr std::chrono::milliseconds minRefreshInterval = 1s / 30; TerminalWidget::TerminalWidget(QWidget *parent, const OpenTerminalParameters &openParameters) : QAbstractScrollArea(parent) - , m_context(Utils::Id("TerminalWidget_").withSuffix((size_t) this)) + , m_context(Utils::Id("TerminalWidget_").withSuffix(QString::number((uintptr_t) this))) , m_openParameters(openParameters) , m_lastFlush(std::chrono::system_clock::now()) , m_lastDoubleClick(std::chrono::system_clock::now()) From 980a95f7d6ae8ee53831aa4c8c9a7f517299ff21 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 5 Jun 2023 09:39:32 +0200 Subject: [PATCH 113/141] TextEditor: Fix missing include Amends 8da3575d7290be5002f06a363a622fd4ba70b803. Change-Id: I5696d83731cd25cc3abc58d7dc5359859918ac8e Reviewed-by: Orgad Shaneh --- src/plugins/texteditor/basefilefind.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/texteditor/basefilefind.cpp b/src/plugins/texteditor/basefilefind.cpp index 99f37d05eac..285d42fd3d9 100644 --- a/src/plugins/texteditor/basefilefind.cpp +++ b/src/plugins/texteditor/basefilefind.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include From 8b3f246285bd022b1a87673997ba571892c30da1 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 5 Jun 2023 08:03:11 +0200 Subject: [PATCH 114/141] AutoTest: Tweak postponing parse once more Postpone the parsing also if the build system is waiting for a parse. Change-Id: I56aaecfca05ea28a21c13747847b518d1eb8732f Reviewed-by: David Schulz --- src/plugins/autotest/testcodeparser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/autotest/testcodeparser.cpp b/src/plugins/autotest/testcodeparser.cpp index 8553702432f..66bbb256059 100644 --- a/src/plugins/autotest/testcodeparser.cpp +++ b/src/plugins/autotest/testcodeparser.cpp @@ -35,7 +35,7 @@ using namespace ProjectExplorer; static bool isProjectParsing() { const BuildSystem *bs = ProjectManager::startupBuildSystem(); - return bs && bs->isParsing(); + return bs && (bs->isParsing() || bs->isWaitingForParse()); } TestCodeParser::TestCodeParser() From e376355b189ea0c9b33bbeb606dda403713a0091 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Sat, 3 Jun 2023 12:44:28 +0200 Subject: [PATCH 115/141] CorePlugin: Reuse qScopeGuard instead of ExecuteOnDestruction Change-Id: I2b6f6319d82512fec9a407649d7514f93283770d Reviewed-by: Qt CI Patch Build Bot Reviewed-by: Reviewed-by: Eike Ziller Reviewed-by: Qt CI Bot --- src/plugins/coreplugin/editormanager/editormanager.cpp | 6 ++---- src/plugins/coreplugin/loggingviewer.cpp | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp index e7147e94cea..81262f5ebfe 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.cpp +++ b/src/plugins/coreplugin/editormanager/editormanager.cpp @@ -42,7 +42,6 @@ #include #include #include -#include #include #include #include @@ -70,6 +69,7 @@ #include #include #include +#include #include #include #include @@ -3325,9 +3325,7 @@ IEditor *EditorManager::openEditorWithContents(Id editorId, EditorManager::gotoOtherSplit(); QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - Utils::ExecuteOnDestruction appRestoreCursor(&QApplication::restoreOverrideCursor); - Q_UNUSED(appRestoreCursor) - + const auto cleanup = qScopeGuard(&QApplication::restoreOverrideCursor); const QString title = makeTitleUnique(titlePattern); diff --git a/src/plugins/coreplugin/loggingviewer.cpp b/src/plugins/coreplugin/loggingviewer.cpp index a81ed5936db..63fba41a4df 100644 --- a/src/plugins/coreplugin/loggingviewer.cpp +++ b/src/plugins/coreplugin/loggingviewer.cpp @@ -11,7 +11,6 @@ #include #include -#include #include #include #include @@ -33,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -591,7 +591,7 @@ void LoggingViewManagerWidget::saveLoggingsToFile() const { // should we just let it continue without temporarily disabling? const bool enabled = m_manager->isEnabled(); - Utils::ExecuteOnDestruction exec([this, enabled] { m_manager->setEnabled(enabled); }); + const auto cleanup = qScopeGuard([this, enabled] { m_manager->setEnabled(enabled); }); if (enabled) m_manager->setEnabled(false); const Utils::FilePath fp = Utils::FileUtils::getSaveFilePath(ICore::dialogParent(), From b14c07eed60b90309b017a0f1f2b2a5de4e1d9e7 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Sat, 3 Jun 2023 13:30:22 +0200 Subject: [PATCH 116/141] TextEditor: Reuse qScopeGuard instead of ExecuteOnDestruction Change-Id: I2ca7d4676bb4f34fbf59fd45bcd01d7857cb7e4e Reviewed-by: Qt CI Patch Build Bot Reviewed-by: David Schulz Reviewed-by: Qt CI Bot Reviewed-by: --- src/plugins/texteditor/basehoverhandler.cpp | 4 ++-- src/plugins/texteditor/codeassist/codeassistant.cpp | 6 +++--- src/plugins/texteditor/colorpreviewhoverhandler.cpp | 9 ++++----- src/plugins/texteditor/texteditor.cpp | 8 ++++---- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/plugins/texteditor/basehoverhandler.cpp b/src/plugins/texteditor/basehoverhandler.cpp index 9bb3d97f7d0..203ecc36e20 100644 --- a/src/plugins/texteditor/basehoverhandler.cpp +++ b/src/plugins/texteditor/basehoverhandler.cpp @@ -4,10 +4,10 @@ #include "basehoverhandler.h" #include "texteditor.h" -#include #include #include +#include #include namespace TextEditor { @@ -121,7 +121,7 @@ void BaseHoverHandler::process(TextEditorWidget *widget, int pos, ReportPriority void BaseHoverHandler::identifyMatch(TextEditorWidget *editorWidget, int pos, ReportPriority report) { - Utils::ExecuteOnDestruction reportPriority([this, report](){ report(priority()); }); + const auto cleanup = qScopeGuard([this, report] { report(priority()); }); QString tooltip = editorWidget->extraSelectionTooltip(pos); if (!tooltip.isEmpty()) diff --git a/src/plugins/texteditor/codeassist/codeassistant.cpp b/src/plugins/texteditor/codeassist/codeassistant.cpp index 430b7252cdf..0da6571da8f 100644 --- a/src/plugins/texteditor/codeassist/codeassistant.cpp +++ b/src/plugins/texteditor/codeassist/codeassistant.cpp @@ -18,13 +18,13 @@ #include #include #include -#include #include #include #include #include #include +#include #include using namespace TextEditor::Internal; @@ -158,7 +158,7 @@ void CodeAssistantPrivate::requestProposal(AssistReason reason, bool isUpdate) { // make sure to cleanup old proposals if we cannot find a new assistant - Utils::ExecuteOnDestruction earlyReturnContextClear([this] { destroyContext(); }); + auto cleanup = qScopeGuard([this] { destroyContext(); }); if (isWaitingForProposal()) cancelCurrentRequest(); @@ -179,7 +179,7 @@ void CodeAssistantPrivate::requestProposal(AssistReason reason, QTC_ASSERT(assistInterface, return); // We got an assist provider and interface so no need to reset the current context anymore - earlyReturnContextClear.reset({}); + cleanup.dismiss(); m_assistKind = kind; m_requestProvider = provider; diff --git a/src/plugins/texteditor/colorpreviewhoverhandler.cpp b/src/plugins/texteditor/colorpreviewhoverhandler.cpp index 181ba28e96f..1a66392c550 100644 --- a/src/plugins/texteditor/colorpreviewhoverhandler.cpp +++ b/src/plugins/texteditor/colorpreviewhoverhandler.cpp @@ -5,12 +5,12 @@ #include "texteditor.h" #include -#include #include #include -#include #include +#include +#include #include using namespace Core; @@ -333,10 +333,9 @@ static QColor colorFromFuncAndArgs(const QString &func, const QStringList &args) } void ColorPreviewHoverHandler::identifyMatch(TextEditorWidget *editorWidget, - int pos, - ReportPriority report) + int pos, ReportPriority report) { - Utils::ExecuteOnDestruction reportPriority([this, report](){ report(priority()); }); + const auto cleanup = qScopeGuard([this, report] { report(priority()); }); if (editorWidget->extraSelectionTooltip(pos).isEmpty()) { const QTextBlock tb = editorWidget->document()->findBlock(pos); diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp index ecb617aed70..2c8ff597015 100644 --- a/src/plugins/texteditor/texteditor.cpp +++ b/src/plugins/texteditor/texteditor.cpp @@ -50,7 +50,6 @@ #include #include #include -#include #include #include #include @@ -91,9 +90,10 @@ #include #include #include -#include +#include #include #include +#include #include #include #include @@ -1435,7 +1435,7 @@ void TextEditorWidgetPrivate::print(QPrinter *printer) return; doc = doc->clone(doc); - Utils::ExecuteOnDestruction docDeleter([doc]() { delete doc; }); + const auto cleanup = qScopeGuard([doc] { delete doc; }); QTextOption opt = doc->defaultTextOption(); opt.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); @@ -5284,7 +5284,7 @@ void TextEditorWidgetPrivate::paintTextMarks(QPainter &painter, const ExtraAreaP int yoffset = blockBoundingRect.top(); painter.save(); - Utils::ExecuteOnDestruction eod([&painter, size, yoffset, xoffset, overrideIcon]() { + const auto cleanup = qScopeGuard([&painter, size, yoffset, xoffset, overrideIcon] { if (!overrideIcon.isNull()) { const QRect r(xoffset, yoffset, size, size); overrideIcon.paint(&painter, r, Qt::AlignCenter); From 8d02d961278a3d0a31be758e43b211789f58527a Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Mon, 5 Jun 2023 09:13:03 +0200 Subject: [PATCH 117/141] Terminal: Fix esc button update Change-Id: I4862de654ab920faa46742b4a4433dff07ed0387 Reviewed-by: Reviewed-by: Christian Stenger --- src/plugins/terminal/terminalpane.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/terminal/terminalpane.cpp b/src/plugins/terminal/terminalpane.cpp index 7e9cae7539e..965e3ba651c 100644 --- a/src/plugins/terminal/terminalpane.cpp +++ b/src/plugins/terminal/terminalpane.cpp @@ -87,9 +87,10 @@ TerminalPane::TerminalPane(QObject *parent) updateEscButton(); - connect(m_escSettingButton, &QToolButton::toggled, this, [this] { + connect(m_escSettingButton, &QToolButton::toggled, this, [this, updateEscButton] { TerminalSettings::instance().sendEscapeToTerminal.setValue(m_escSettingButton->isChecked()); TerminalSettings::instance().writeSettings(ICore::settings()); + updateEscButton(); }); connect(&TerminalSettings::instance(), &TerminalSettings::applied, this, updateEscButton); From b7bd30aeb859b4ce271e1de7f027afe13208264d Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Sat, 3 Jun 2023 09:36:39 +0200 Subject: [PATCH 118/141] Tasking: Introduce ConcurrentCall It substitutes Utils::Async, but is Utils independent. The ConcurrentCall class is prepared to work with TaskTree. Provide the task tree adapter for the ConcurrentCall class. Register the task inside the Tasking namespace under the ConcurrentCallTask name. This class introduces the dependency to Qt::Concurrent, otherwise Tasking namespace is independent on Qt::Concurrent. Possibly, may be added into Qt::Concurrent lib, as a wrapper around the QtConcurrent::run() call. Change-Id: I4511ff0430e78346aa6a4fae1a9d5370fdd08506 Reviewed-by: Qt CI Bot Reviewed-by: Marcus Tillmanns Reviewed-by: --- src/libs/solutions/tasking/CMakeLists.txt | 3 +- src/libs/solutions/tasking/barrier.h | 2 +- src/libs/solutions/tasking/concurrentcall.h | 100 ++++++++++++++++++++ src/libs/solutions/tasking/tasking.qbs | 3 +- 4 files changed, 105 insertions(+), 3 deletions(-) create mode 100644 src/libs/solutions/tasking/concurrentcall.h diff --git a/src/libs/solutions/tasking/CMakeLists.txt b/src/libs/solutions/tasking/CMakeLists.txt index 5beed2fe5b4..52c994de8db 100644 --- a/src/libs/solutions/tasking/CMakeLists.txt +++ b/src/libs/solutions/tasking/CMakeLists.txt @@ -1,9 +1,10 @@ add_qtc_library(Tasking OBJECT # Never add dependencies to non-Qt libraries for this library - DEPENDS Qt::Core + DEPENDS Qt::Concurrent Qt::Core PUBLIC_DEFINES TASKING_LIBRARY SOURCES barrier.cpp barrier.h + concurrentcall.h tasking_global.h tasktree.cpp tasktree.h ) diff --git a/src/libs/solutions/tasking/barrier.h b/src/libs/solutions/tasking/barrier.h index 6939da5b365..6f1afe39b09 100644 --- a/src/libs/solutions/tasking/barrier.h +++ b/src/libs/solutions/tasking/barrier.h @@ -34,7 +34,7 @@ private: int m_current = -1; }; -class TASKING_EXPORT BarrierTaskAdapter : public Tasking::TaskAdapter +class TASKING_EXPORT BarrierTaskAdapter : public TaskAdapter { public: BarrierTaskAdapter() { connect(task(), &Barrier::done, this, &TaskInterface::done); } diff --git a/src/libs/solutions/tasking/concurrentcall.h b/src/libs/solutions/tasking/concurrentcall.h new file mode 100644 index 00000000000..d7799159447 --- /dev/null +++ b/src/libs/solutions/tasking/concurrentcall.h @@ -0,0 +1,100 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#pragma once + +#include "tasking_global.h" + +#include "tasktree.h" + +#include + +namespace Tasking { + +// This class introduces the dependency to Qt::Concurrent, otherwise Tasking namespace +// is independent on Qt::Concurrent. +// Possibly, it could be placed inside Qt::Concurrent library, as a wrapper around +// QtConcurrent::run() call. + +template +class ConcurrentCall +{ + Q_DISABLE_COPY_MOVE(ConcurrentCall) + +public: + ConcurrentCall() = default; + template + void setConcurrentCallData(Function &&function, Args &&...args) + { + return wrapConcurrent(std::forward(function), std::forward(args)...); + } + void setThreadPool(QThreadPool *pool) { m_threadPool = pool; } + ResultType result() const + { + return m_future.resultCount() ? m_future.result() : ResultType(); + } + QFuture future() const { return m_future; } + +private: + template + void wrapConcurrent(Function &&function, Args &&...args) + { + m_startHandler = [=] { + if (m_threadPool) + return QtConcurrent::run(m_threadPool, function, args...); + return QtConcurrent::run(function, args...); + }; + } + + template + void wrapConcurrent(std::reference_wrapper &&wrapper, Args &&...args) + { + m_startHandler = [=] { + if (m_threadPool) { + return QtConcurrent::run(m_threadPool, + std::forward(wrapper.get()), args...); + } + return QtConcurrent::run(std::forward(wrapper.get()), args...); + }; + } + + template + friend class ConcurrentCallTaskAdapter; + + std::function()> m_startHandler; + QThreadPool *m_threadPool = nullptr; + QFuture m_future; +}; + +template +class ConcurrentCallTaskAdapter : public TaskAdapter> +{ +public: + ~ConcurrentCallTaskAdapter() { + if (m_watcher) { + m_watcher->cancel(); + m_watcher->waitForFinished(); + } + } + + void start() { + if (!this->task()->m_startHandler) { + emit this->done(false); // TODO: Add runtime assert + return; + } + m_watcher.reset(new QFutureWatcher); + this->connect(m_watcher.get(), &QFutureWatcherBase::finished, this, [this] { + emit this->done(!m_watcher->isCanceled()); + m_watcher.release()->deleteLater(); + }); + this->task()->m_future = this->task()->m_startHandler(); + m_watcher->setFuture(this->task()->m_future); + } + +private: + std::unique_ptr> m_watcher; +}; + +} // namespace Tasking + +TASKING_DECLARE_TEMPLATE_TASK(ConcurrentCallTask, Tasking::ConcurrentCallTaskAdapter); diff --git a/src/libs/solutions/tasking/tasking.qbs b/src/libs/solutions/tasking/tasking.qbs index 8697b9c009b..0e78ed74f0a 100644 --- a/src/libs/solutions/tasking/tasking.qbs +++ b/src/libs/solutions/tasking/tasking.qbs @@ -1,11 +1,12 @@ QtcLibrary { name: "Tasking" - Depends { name: "Qt"; submodules: ["core"] } + Depends { name: "Qt"; submodules: ["concurrent", "core"] } cpp.defines: base.concat("TASKING_LIBRARY") files: [ "barrier.cpp", "barrier.h", + "concurrentcall.h", "tasking_global.h", "tasktree.cpp", "tasktree.h", From ebc185b1bb3759bb8a11606bb98335533e414fe0 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 1 Jun 2023 09:54:03 +0200 Subject: [PATCH 119/141] QmlProjectManager: Use FilePathAspect for device QML viewer overide Cosmetical. Change-Id: I480fd3163b45c3b2a19b7636cb79d6cb9b166825 Reviewed-by: Qt CI Bot Reviewed-by: Tim Jenssen --- src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp index 1cce1650ce0..756a0707d4a 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp +++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp @@ -61,7 +61,7 @@ private: FilePath qmlRuntimeFilePath() const; void createQtVersionAspect(); - StringAspect *m_qmlViewerAspect = nullptr; + FilePathAspect *m_qmlViewerAspect = nullptr; QmlMainFileAspect *m_qmlMainFileAspect = nullptr; QmlMultiLanguageAspect *m_multiLanguageAspect = nullptr; SelectionAspect *m_qtversionAspect = nullptr; @@ -71,10 +71,9 @@ private: QmlProjectRunConfiguration::QmlProjectRunConfiguration(Target *target, Id id) : RunConfiguration(target, id) { - m_qmlViewerAspect = addAspect(); + m_qmlViewerAspect = addAspect(); m_qmlViewerAspect->setLabelText(Tr::tr("Override device QML viewer:")); m_qmlViewerAspect->setPlaceHolderText(qmlRuntimeFilePath().toUserOutput()); - m_qmlViewerAspect->setDisplayStyle(StringAspect::PathChooserDisplay); m_qmlViewerAspect->setHistoryCompleter("QmlProjectManager.viewer.history"); m_qmlViewerAspect->setSettingsKey(Constants::QML_VIEWER_KEY); From 7b3c2c13a1aa6b66f5d383804b556a66ca857950 Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Tue, 6 Jun 2023 07:59:09 +0200 Subject: [PATCH 120/141] Terminal: Decode percent encoding Fixes: QTCREATORBUG-29254 Change-Id: I0d1712753f488dff9252d2fcf099c9aefb06ed0b Reviewed-by: Christian Stenger --- src/plugins/terminal/shellintegration.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/terminal/shellintegration.cpp b/src/plugins/terminal/shellintegration.cpp index d8e26f94ce5..d981dc7269e 100644 --- a/src/plugins/terminal/shellintegration.cpp +++ b/src/plugins/terminal/shellintegration.cpp @@ -85,7 +85,8 @@ void ShellIntegration::onOsc(int cmd, const VTermStringFragment &fragment) emit currentDirChanged(FilePath::fromUserInput(value.toString()).path()); } else if (cmd == 7) { - emit currentDirChanged(FilePath::fromUserInput(d).path()); + const QString decoded = QUrl::fromPercentEncoding(d.toUtf8()); + emit currentDirChanged(FilePath::fromUserInput(decoded).path()); } else if (cmd == 133) { qCDebug(integrationLog) << "OSC 133:" << data; } else if (cmd == 633 && command.length() == 1) { From 82966bc7baf480da14e6b5b03cc95a4a00cb0ec0 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 6 Jun 2023 08:14:45 +0200 Subject: [PATCH 121/141] Revert "ProjectExplorer: Remove 4.11 compatibility code in buildsteplist" This reverts commit c8e1333f89ae10b3e2c571faeaf5792a077ffac9. Contrary to the comment in the code this is apparently still in active use in the user file accessor. Change-Id: I5e5dddbe2a95c70bda92ce732688041787145055 Reviewed-by: Christian Stenger --- src/plugins/projectexplorer/buildsteplist.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/plugins/projectexplorer/buildsteplist.cpp b/src/plugins/projectexplorer/buildsteplist.cpp index 0094bf0b683..8d6159541ef 100644 --- a/src/plugins/projectexplorer/buildsteplist.cpp +++ b/src/plugins/projectexplorer/buildsteplist.cpp @@ -43,6 +43,16 @@ QVariantMap BuildStepList::toMap() const { QVariantMap map; + { + // Only written for compatibility reasons within the 4.11 cycle + const char CONFIGURATION_ID_KEY[] = "ProjectExplorer.ProjectConfiguration.Id"; + const char DISPLAY_NAME_KEY[] = "ProjectExplorer.ProjectConfiguration.DisplayName"; + const char DEFAULT_DISPLAY_NAME_KEY[] = "ProjectExplorer.ProjectConfiguration.DefaultDisplayName"; + map.insert(QLatin1String(CONFIGURATION_ID_KEY), m_id.toSetting()); + map.insert(QLatin1String(DISPLAY_NAME_KEY), displayName()); + map.insert(QLatin1String(DEFAULT_DISPLAY_NAME_KEY), displayName()); + } + // Save build steps map.insert(QString::fromLatin1(STEPS_COUNT_KEY), m_steps.count()); for (int i = 0; i < m_steps.count(); ++i) From cfa88ac1692a49a560a8e6c5b05b5e57767002cf Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 6 Jun 2023 09:00:27 +0200 Subject: [PATCH 122/141] QmlJS: Avoid deprecation warning de18b3ff370543b5b99bd068b871a2cd677cf9f3 deprecated the QCryptographicHash::addData(const char *data, qsizetype length) overload. Change-Id: I86444a9d7de3cafc596f508fc08c3a4c1f25142f Reviewed-by: Eike Ziller --- src/libs/qmljs/qmljsdocument.cpp | 53 ++++++++++++++++---------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/src/libs/qmljs/qmljsdocument.cpp b/src/libs/qmljs/qmljsdocument.cpp index 16b17b0faee..4b79bdafccc 100644 --- a/src/libs/qmljs/qmljsdocument.cpp +++ b/src/libs/qmljs/qmljsdocument.cpp @@ -369,61 +369,62 @@ LibraryInfo::LibraryInfo(const QmlDirParser &parser, const QByteArray &fingerpri QByteArray LibraryInfo::calculateFingerprint() const { QCryptographicHash hash(QCryptographicHash::Sha1); - hash.addData(reinterpret_cast(&_status), sizeof(_status)); + auto addData = [&hash](auto p, size_t len) { + hash.addData(QByteArrayView(reinterpret_cast(p), len)); + }; + + addData(&_status, sizeof(_status)); int len = _components.size(); - hash.addData(reinterpret_cast(&len), sizeof(len)); + addData(&len, sizeof(len)); for (const QmlDirParser::Component &component : _components) { len = component.fileName.size(); - hash.addData(reinterpret_cast(&len), sizeof(len)); - hash.addData(reinterpret_cast(component.fileName.constData()), - len * sizeofQChar); - hash.addData(reinterpret_cast(&component.majorVersion), sizeof(component.majorVersion)); - hash.addData(reinterpret_cast(&component.minorVersion), sizeof(component.minorVersion)); + addData(&len, sizeof(len)); + addData(component.fileName.constData(), len * sizeofQChar); + addData(&component.majorVersion, sizeof(component.majorVersion)); + addData(&component.minorVersion, sizeof(component.minorVersion)); len = component.typeName.size(); - hash.addData(reinterpret_cast(&len), sizeof(len)); - hash.addData(reinterpret_cast(component.typeName.constData()), - component.typeName.size() * sizeofQChar); + addData(&len, sizeof(len)); + addData(component.typeName.constData(), component.typeName.size() * sizeofQChar); int flags = (component.singleton ? (1 << 0) : 0) + (component.internal ? (1 << 1) : 0); - hash.addData(reinterpret_cast(&flags), sizeof(flags)); + addData(&flags, sizeof(flags)); } len = _plugins.size(); - hash.addData(reinterpret_cast(&len), sizeof(len)); + addData(&len, sizeof(len)); for (const QmlDirParser::Plugin &plugin : _plugins) { len = plugin.path.size(); - hash.addData(reinterpret_cast(&len), sizeof(len)); - hash.addData(reinterpret_cast(plugin.path.constData()), len * sizeofQChar); + addData(&len, sizeof(len)); + addData(plugin.path.constData(), len * sizeofQChar); len = plugin.name.size(); - hash.addData(reinterpret_cast(&len), sizeof(len)); - hash.addData(reinterpret_cast(plugin.name.constData()), len * sizeofQChar); + addData(&len, sizeof(len)); + addData(plugin.name.constData(), len * sizeofQChar); } len = _typeinfos.size(); - hash.addData(reinterpret_cast(&len), sizeof(len)); + addData(&len, sizeof(len)); for (const QString &typeinfo : _typeinfos) { len = typeinfo.size(); - hash.addData(reinterpret_cast(&len), sizeof(len)); - hash.addData(reinterpret_cast(typeinfo.constData()), - len * sizeofQChar); + addData(&len, sizeof(len)); + addData(typeinfo.constData(), len * sizeofQChar); } len = _metaObjects.size(); - hash.addData(reinterpret_cast(&len), sizeof(len)); + addData(&len, sizeof(len)); QList metaFingerprints; for (const LanguageUtils::FakeMetaObject::ConstPtr &metaObject : _metaObjects) metaFingerprints.append(metaObject->fingerprint()); std::sort(metaFingerprints.begin(), metaFingerprints.end()); for (const QByteArray &fp : std::as_const(metaFingerprints)) hash.addData(fp); - hash.addData(reinterpret_cast(&_dumpStatus), sizeof(_dumpStatus)); + addData(&_dumpStatus, sizeof(_dumpStatus)); len = _dumpError.size(); // localization dependent (avoid?) - hash.addData(reinterpret_cast(&len), sizeof(len)); - hash.addData(reinterpret_cast(_dumpError.constData()), len * sizeofQChar); + addData(&len, sizeof(len)); + addData(_dumpError.constData(), len * sizeofQChar); len = _moduleApis.size(); - hash.addData(reinterpret_cast(&len), sizeof(len)); + addData(&len, sizeof(len)); for (const ModuleApiInfo &moduleInfo : _moduleApis) moduleInfo.addToHash(hash); // make it order independent? len = _imports.size(); - hash.addData(reinterpret_cast(&len), sizeof(len)); + addData(&len, sizeof(len)); for (const QmlDirParser::Import &import : _imports) hash.addData(import.module.toUtf8()); // import order matters, keep order-dependent From f5d02f4bcb291b299408094f0ddbe6a298563520 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 6 Jun 2023 08:28:06 +0200 Subject: [PATCH 123/141] Utils: Fix compilation with recent Qt dev MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After an update of Qt dev the following code in Creator fails to compile with /data/dev/creator-out/src/libs/utils/aspects.cpp: In member function ‘void Utils::IntegersAspect::setValue(const QList&) /data/dev/creator-out/src/libs/utils/aspects.cpp:2323:35: error: no matching function for call to ‘transform(const QList&, )’ 2323 | BaseAspect::setValue(transform(value, &QVariant::fromValue)); Work around by using a lambda. Change-Id: Id5a844e7e5fe1846c4904dbad21472743439c4da Reviewed-by: Fabian Kosmale --- src/libs/utils/aspects.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/utils/aspects.cpp b/src/libs/utils/aspects.cpp index 57d358a7c1b..999385e1ca9 100644 --- a/src/libs/utils/aspects.cpp +++ b/src/libs/utils/aspects.cpp @@ -2320,7 +2320,7 @@ QList IntegersAspect::value() const void IntegersAspect::setValue(const QList &value) { - BaseAspect::setValue(transform(value, &QVariant::fromValue)); + BaseAspect::setValue(transform(value, [](int i) { return QVariant::fromValue(i); })); } QList IntegersAspect::defaultValue() const @@ -2331,7 +2331,7 @@ QList IntegersAspect::defaultValue() const void IntegersAspect::setDefaultValue(const QList &value) { - BaseAspect::setDefaultValue(transform(value, &QVariant::fromValue)); + BaseAspect::setDefaultValue(transform(value, [](int i) { return QVariant::fromValue(i); })); } From 73791080d43d79af1d88937d10ebbd6b3d9de8ad Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Thu, 1 Jun 2023 12:40:59 +0200 Subject: [PATCH 124/141] Core: Use LayoutBuilder in CommandMappingsPrivate Change-Id: I327e3eae887c0e4e1dfe600685e71c194f26ff75 Reviewed-by: Qt CI Patch Build Bot Reviewed-by: hjk Reviewed-by: --- .../actionmanager/commandmappings.cpp | 49 ++++++++----------- 1 file changed, 20 insertions(+), 29 deletions(-) diff --git a/src/plugins/coreplugin/actionmanager/commandmappings.cpp b/src/plugins/coreplugin/actionmanager/commandmappings.cpp index bfc62c3d184..15765698cbd 100644 --- a/src/plugins/coreplugin/actionmanager/commandmappings.cpp +++ b/src/plugins/coreplugin/actionmanager/commandmappings.cpp @@ -6,18 +6,17 @@ #include #include -#include #include +#include +#include #include #include #include -#include #include #include #include #include -#include Q_DECLARE_METATYPE(Core::Internal::ShortcutItem*) @@ -32,13 +31,10 @@ public: CommandMappingsPrivate(CommandMappings *parent) : q(parent) { - groupBox = new QGroupBox(parent); - groupBox->setTitle(::Core::Tr::tr("Command Mappings")); - - filterEdit = new FancyLineEdit(groupBox); + filterEdit = new FancyLineEdit; filterEdit->setFiltering(true); - commandList = new QTreeWidget(groupBox); + commandList = new QTreeWidget; commandList->setRootIsDecorated(false); commandList->setUniformRowHeights(true); commandList->setSortingEnabled(true); @@ -49,33 +45,28 @@ public: item->setText(1, ::Core::Tr::tr("Label")); item->setText(0, ::Core::Tr::tr("Command")); - defaultButton = new QPushButton(::Core::Tr::tr("Reset All"), groupBox); + defaultButton = new QPushButton(::Core::Tr::tr("Reset All")); defaultButton->setToolTip(::Core::Tr::tr("Reset all to default.")); - resetButton = new QPushButton(::Core::Tr::tr("Reset"), groupBox); + resetButton = new QPushButton(::Core::Tr::tr("Reset")); resetButton->setToolTip(::Core::Tr::tr("Reset to default.")); resetButton->setVisible(false); - importButton = new QPushButton(::Core::Tr::tr("Import..."), groupBox); - exportButton = new QPushButton(::Core::Tr::tr("Export..."), groupBox); + importButton = new QPushButton(::Core::Tr::tr("Import...")); + exportButton = new QPushButton(::Core::Tr::tr("Export...")); - auto hboxLayout1 = new QHBoxLayout(); - hboxLayout1->addWidget(defaultButton); - hboxLayout1->addWidget(resetButton); - hboxLayout1->addStretch(); - hboxLayout1->addWidget(importButton); - hboxLayout1->addWidget(exportButton); - - auto hboxLayout = new QHBoxLayout(); - hboxLayout->addWidget(filterEdit); - - auto vboxLayout1 = new QVBoxLayout(groupBox); - vboxLayout1->addLayout(hboxLayout); - vboxLayout1->addWidget(commandList); - vboxLayout1->addLayout(hboxLayout1); - - auto vboxLayout = new QVBoxLayout(parent); - vboxLayout->addWidget(groupBox); + using namespace Layouting; + Column { + Group { + title(::Core::Tr::tr("Command Mappings")), + bindTo(&groupBox), + Column { + filterEdit, + commandList, + Row { defaultButton, resetButton, st, importButton, exportButton }, + }, + }, + }.attachTo(parent); q->connect(exportButton, &QPushButton::clicked, q, &CommandMappings::exportAction); From 9694d9c6f6e8871841414b8616efeca592dbf491 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Fri, 2 Jun 2023 23:56:50 +0200 Subject: [PATCH 125/141] Tasking: Introduce NetworkQuery The NetworkQuery class is prepared to work with TaskTree. Provide the task tree adapter for the NetworkQuery class. Register the task inside the Tasking namespace under the NetworkQueryTask name. This class introduces the dependency to Qt::Network, otherwise Tasking namespace is independent on Qt::Network. Possibly, may be added into Qt::Network lib, as a wrapper around the QNetworkReply. Change-Id: I29f160c0bf128c567ce20f044540b2dd6f1e17c4 Reviewed-by: Qt CI Bot Reviewed-by: Marcus Tillmanns --- src/libs/solutions/tasking/CMakeLists.txt | 3 +- src/libs/solutions/tasking/networkquery.cpp | 38 ++++++++++++++ src/libs/solutions/tasking/networkquery.h | 55 +++++++++++++++++++++ src/libs/solutions/tasking/tasking.qbs | 4 +- tests/auto/solutions/tasking/CMakeLists.txt | 2 +- tests/auto/solutions/tasking/tasking.qbs | 1 + tests/manual/tasking/demo/CMakeLists.txt | 2 +- tests/manual/tasking/demo/demo.qbs | 2 +- 8 files changed, 102 insertions(+), 5 deletions(-) create mode 100644 src/libs/solutions/tasking/networkquery.cpp create mode 100644 src/libs/solutions/tasking/networkquery.h diff --git a/src/libs/solutions/tasking/CMakeLists.txt b/src/libs/solutions/tasking/CMakeLists.txt index 52c994de8db..f70c910e042 100644 --- a/src/libs/solutions/tasking/CMakeLists.txt +++ b/src/libs/solutions/tasking/CMakeLists.txt @@ -1,10 +1,11 @@ add_qtc_library(Tasking OBJECT # Never add dependencies to non-Qt libraries for this library - DEPENDS Qt::Concurrent Qt::Core + DEPENDS Qt::Concurrent Qt::Core Qt::Network PUBLIC_DEFINES TASKING_LIBRARY SOURCES barrier.cpp barrier.h concurrentcall.h + networkquery.cpp networkquery.h tasking_global.h tasktree.cpp tasktree.h ) diff --git a/src/libs/solutions/tasking/networkquery.cpp b/src/libs/solutions/tasking/networkquery.cpp new file mode 100644 index 00000000000..292d3c7d4aa --- /dev/null +++ b/src/libs/solutions/tasking/networkquery.cpp @@ -0,0 +1,38 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "networkquery.h" + +#include + +namespace Tasking { + +void NetworkQuery::start() +{ + if (m_reply) { + qWarning("The NetworkQuery is already running. Ignoring the call to start()."); + return; + } + if (!m_manager) { + qWarning("Can't start the NetworkQuery without the QNetworkAccessManager. " + "Stopping with an error."); + emit done(false); + return; + } + m_reply.reset(m_manager->get(m_request)); + connect(m_reply.get(), &QNetworkReply::finished, this, [this] { + disconnect(m_reply.get(), nullptr, this, nullptr); + emit done(m_reply->error() == QNetworkReply::NoError); + m_reply.release()->deleteLater(); + }); + if (m_reply->isRunning()) + emit started(); +} + +NetworkQuery::~NetworkQuery() +{ + if (m_reply) + m_reply->abort(); +} + +} // namespace Tasking diff --git a/src/libs/solutions/tasking/networkquery.h b/src/libs/solutions/tasking/networkquery.h new file mode 100644 index 00000000000..faf482df90d --- /dev/null +++ b/src/libs/solutions/tasking/networkquery.h @@ -0,0 +1,55 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#pragma once + +#include "tasking_global.h" + +#include "tasktree.h" + +#include +#include + +#include + +QT_BEGIN_NAMESPACE +class QNetworkAccessManager; +QT_END_NAMESPACE + +namespace Tasking { + +// This class introduces the dependency to Qt::Network, otherwise Tasking namespace +// is independent on Qt::Network. +// Possibly, it could be placed inside Qt::Network library, as a wrapper around QNetworkReply. + +class TASKING_EXPORT NetworkQuery final : public QObject +{ + Q_OBJECT + +public: + ~NetworkQuery(); + void setRequest(const QNetworkRequest &request) { m_request = request; } + void setNetworkAccessManager(QNetworkAccessManager *manager) { m_manager = manager; } + QNetworkReply *reply() const { return m_reply.get(); } + void start(); + +signals: + void started(); + void done(bool success); + +private: + QNetworkRequest m_request; + QNetworkAccessManager *m_manager = nullptr; + std::unique_ptr m_reply; +}; + +class TASKING_EXPORT NetworkQueryTaskAdapter : public TaskAdapter +{ +public: + NetworkQueryTaskAdapter() { connect(task(), &NetworkQuery::done, this, &TaskInterface::done); } + void start() final { task()->start(); } +}; + +} // namespace Tasking + +TASKING_DECLARE_TASK(NetworkQueryTask, Tasking::NetworkQueryTaskAdapter); diff --git a/src/libs/solutions/tasking/tasking.qbs b/src/libs/solutions/tasking/tasking.qbs index 0e78ed74f0a..fa0a5ebacc9 100644 --- a/src/libs/solutions/tasking/tasking.qbs +++ b/src/libs/solutions/tasking/tasking.qbs @@ -1,12 +1,14 @@ QtcLibrary { name: "Tasking" - Depends { name: "Qt"; submodules: ["concurrent", "core"] } + Depends { name: "Qt"; submodules: ["concurrent", "core", "network"] } cpp.defines: base.concat("TASKING_LIBRARY") files: [ "barrier.cpp", "barrier.h", "concurrentcall.h", + "networkquery.cpp", + "networkquery.h", "tasking_global.h", "tasktree.cpp", "tasktree.h", diff --git a/tests/auto/solutions/tasking/CMakeLists.txt b/tests/auto/solutions/tasking/CMakeLists.txt index a425250a5a9..f55c3b1c7b2 100644 --- a/tests/auto/solutions/tasking/CMakeLists.txt +++ b/tests/auto/solutions/tasking/CMakeLists.txt @@ -1,4 +1,4 @@ add_qtc_test(tst_solutions_tasking - DEPENDS Tasking + DEPENDS Tasking Qt::Network SOURCES tst_tasking.cpp ) diff --git a/tests/auto/solutions/tasking/tasking.qbs b/tests/auto/solutions/tasking/tasking.qbs index f099edb370c..d6ffa884920 100644 --- a/tests/auto/solutions/tasking/tasking.qbs +++ b/tests/auto/solutions/tasking/tasking.qbs @@ -1,6 +1,7 @@ QtcAutotest { name: "Tasking autotest" + Depends { name: "Qt"; submodules: ["network"] } Depends { name: "Tasking" } files: "tst_tasking.cpp" diff --git a/tests/manual/tasking/demo/CMakeLists.txt b/tests/manual/tasking/demo/CMakeLists.txt index bdd790cd898..7597e74d608 100644 --- a/tests/manual/tasking/demo/CMakeLists.txt +++ b/tests/manual/tasking/demo/CMakeLists.txt @@ -1,6 +1,6 @@ add_qtc_test(tst_tasking_demo MANUALTEST - DEPENDS Tasking Qt::Widgets + DEPENDS Tasking Qt::Widgets Qt::Network SOURCES demo.qrc main.cpp diff --git a/tests/manual/tasking/demo/demo.qbs b/tests/manual/tasking/demo/demo.qbs index 2a54143c415..9cf856bca21 100644 --- a/tests/manual/tasking/demo/demo.qbs +++ b/tests/manual/tasking/demo/demo.qbs @@ -4,7 +4,7 @@ QtcManualtest { name: "Tasking demo" type: ["application"] - Depends { name: "Qt"; submodules: ["widgets"] } + Depends { name: "Qt"; submodules: ["network", "widgets"] } Depends { name: "Tasking" } files: [ From c3344c740af03c892dab506afd629d3e5e266271 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Fri, 2 Jun 2023 22:56:30 +0200 Subject: [PATCH 126/141] Tasking: Import imagescaling example It's an initial copy of the qtbase/examples/qtconcurrent/imagescaling. The goal is to implement it using TaskTree and compare both implementations. Change-Id: I92953a70a3330ac679823060e75e5f39971ae444 Reviewed-by: Qt CI Bot Reviewed-by: Reviewed-by: Marcus Tillmanns Reviewed-by: Leena Miettinen Reviewed-by: hjk --- tests/manual/manual.qbs | 1 + tests/manual/tasking/CMakeLists.txt | 1 + .../tasking/imagescaling/CMakeLists.txt | 11 + .../tasking/imagescaling/downloaddialog.cpp | 41 +++ .../tasking/imagescaling/downloaddialog.h | 29 +++ .../tasking/imagescaling/downloaddialog.ui | 119 +++++++++ .../tasking/imagescaling/imagescaling.cpp | 236 ++++++++++++++++++ .../tasking/imagescaling/imagescaling.h | 54 ++++ .../tasking/imagescaling/imagescaling.qbs | 18 ++ tests/manual/tasking/imagescaling/main.cpp | 18 ++ 10 files changed, 528 insertions(+) create mode 100644 tests/manual/tasking/imagescaling/CMakeLists.txt create mode 100644 tests/manual/tasking/imagescaling/downloaddialog.cpp create mode 100644 tests/manual/tasking/imagescaling/downloaddialog.h create mode 100644 tests/manual/tasking/imagescaling/downloaddialog.ui create mode 100644 tests/manual/tasking/imagescaling/imagescaling.cpp create mode 100644 tests/manual/tasking/imagescaling/imagescaling.h create mode 100644 tests/manual/tasking/imagescaling/imagescaling.qbs create mode 100644 tests/manual/tasking/imagescaling/main.cpp diff --git a/tests/manual/manual.qbs b/tests/manual/manual.qbs index 66c480c7a62..fecd79518c5 100644 --- a/tests/manual/manual.qbs +++ b/tests/manual/manual.qbs @@ -15,6 +15,7 @@ Project { "shootout/shootout.qbs", "subdirfileiterator/subdirfileiterator.qbs", "tasking/demo/demo.qbs", + "tasking/demo/imagescaling.qbs", "widgets/widgets.qbs", ] } diff --git a/tests/manual/tasking/CMakeLists.txt b/tests/manual/tasking/CMakeLists.txt index a16f5f12201..a27004eb3ec 100644 --- a/tests/manual/tasking/CMakeLists.txt +++ b/tests/manual/tasking/CMakeLists.txt @@ -1 +1,2 @@ add_subdirectory(demo) +add_subdirectory(imagescaling) diff --git a/tests/manual/tasking/imagescaling/CMakeLists.txt b/tests/manual/tasking/imagescaling/CMakeLists.txt new file mode 100644 index 00000000000..cfa8121b922 --- /dev/null +++ b/tests/manual/tasking/imagescaling/CMakeLists.txt @@ -0,0 +1,11 @@ +add_qtc_test(tst_tasking_imagescaling + MANUALTEST + DEPENDS Tasking Qt::Concurrent Qt::Network Qt::Widgets + SOURCES + downloaddialog.cpp + downloaddialog.h + downloaddialog.ui + imagescaling.cpp + imagescaling.h + main.cpp +) diff --git a/tests/manual/tasking/imagescaling/downloaddialog.cpp b/tests/manual/tasking/imagescaling/downloaddialog.cpp new file mode 100644 index 00000000000..3547b880580 --- /dev/null +++ b/tests/manual/tasking/imagescaling/downloaddialog.cpp @@ -0,0 +1,41 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "downloaddialog.h" +#include "ui_downloaddialog.h" + +#include + +DownloadDialog::DownloadDialog(QWidget *parent) : QDialog(parent), ui(new Ui::DownloadDialog) +{ + ui->setupUi(this); + + ui->urlLineEdit->setPlaceholderText(tr("Enter the URL of an image to download")); + + connect(ui->addUrlButton, &QPushButton::clicked, this, [this] { + const auto text = ui->urlLineEdit->text(); + if (!text.isEmpty()) { + ui->urlListWidget->addItem(text); + ui->urlLineEdit->clear(); + } + }); + connect(ui->urlListWidget, &QListWidget::itemSelectionChanged, this, [this] { + ui->removeUrlButton->setEnabled(!ui->urlListWidget->selectedItems().empty()); + }); + connect(ui->clearUrlsButton, &QPushButton::clicked, ui->urlListWidget, &QListWidget::clear); + connect(ui->removeUrlButton, &QPushButton::clicked, this, + [this] { qDeleteAll(ui->urlListWidget->selectedItems()); }); +} + +DownloadDialog::~DownloadDialog() +{ + delete ui; +} + +QList DownloadDialog::getUrls() const +{ + QList urls; + for (auto row = 0; row < ui->urlListWidget->count(); ++row) + urls.push_back(QUrl(ui->urlListWidget->item(row)->text())); + return urls; +} diff --git a/tests/manual/tasking/imagescaling/downloaddialog.h b/tests/manual/tasking/imagescaling/downloaddialog.h new file mode 100644 index 00000000000..cc15d081893 --- /dev/null +++ b/tests/manual/tasking/imagescaling/downloaddialog.h @@ -0,0 +1,29 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef DOWNLOADDIALOG_H +#define DOWNLOADDIALOG_H + +#include + +QT_BEGIN_NAMESPACE +namespace Ui { +class DownloadDialog; +} +QT_END_NAMESPACE + +class DownloadDialog : public QDialog +{ + Q_OBJECT + +public: + explicit DownloadDialog(QWidget *parent = nullptr); + ~DownloadDialog(); + + QList getUrls() const; + +private: + Ui::DownloadDialog *ui; +}; + +#endif // DOWNLOADDIALOG_H diff --git a/tests/manual/tasking/imagescaling/downloaddialog.ui b/tests/manual/tasking/imagescaling/downloaddialog.ui new file mode 100644 index 00000000000..c85a0635681 --- /dev/null +++ b/tests/manual/tasking/imagescaling/downloaddialog.ui @@ -0,0 +1,119 @@ + + + DownloadDialog + + + + 0 + 0 + 489 + 333 + + + + Dialog + + + + + + + + + + + + + + + + + + + + Add URL + + + + + + + false + + + Remove URL + + + + + + + Clear + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + DownloadDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + DownloadDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/tests/manual/tasking/imagescaling/imagescaling.cpp b/tests/manual/tasking/imagescaling/imagescaling.cpp new file mode 100644 index 00000000000..f380ae9d908 --- /dev/null +++ b/tests/manual/tasking/imagescaling/imagescaling.cpp @@ -0,0 +1,236 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "imagescaling.h" +#include "downloaddialog.h" + +#include + +Images::Images(QWidget *parent) : QWidget(parent), downloadDialog(new DownloadDialog(this)) +{ + resize(800, 600); + + addUrlsButton = new QPushButton(tr("Add URLs")); +//! [1] + connect(addUrlsButton, &QPushButton::clicked, this, &Images::process); +//! [1] + + cancelButton = new QPushButton(tr("Cancel")); + cancelButton->setEnabled(false); +//! [2] + connect(cancelButton, &QPushButton::clicked, this, &Images::cancel); +//! [2] + + QHBoxLayout *buttonLayout = new QHBoxLayout(); + buttonLayout->addWidget(addUrlsButton); + buttonLayout->addWidget(cancelButton); + buttonLayout->addStretch(); + + statusBar = new QStatusBar(); + + imagesLayout = new QGridLayout(); + + mainLayout = new QVBoxLayout(); + mainLayout->addLayout(buttonLayout); + mainLayout->addLayout(imagesLayout); + mainLayout->addStretch(); + mainLayout->addWidget(statusBar); + setLayout(mainLayout); + +//! [6] + connect(&scalingWatcher, &QFutureWatcher>::finished, + this, &Images::scaleFinished); +//! [6] +} + +Images::~Images() +{ + cancel(); +} + +//! [3] +void Images::process() +{ + // Clean previous state + replies.clear(); + addUrlsButton->setEnabled(false); + + if (downloadDialog->exec() == QDialog::Accepted) { + + const auto urls = downloadDialog->getUrls(); + if (urls.empty()) + return; + + cancelButton->setEnabled(true); + + initLayout(urls.size()); + + downloadFuture = download(urls); + statusBar->showMessage(tr("Downloading...")); +//! [3] + + //! [4] + downloadFuture + .then([this](auto) { + cancelButton->setEnabled(false); + updateStatus(tr("Scaling...")); + //! [16] + scalingWatcher.setFuture(QtConcurrent::run(Images::scaled, + downloadFuture.results())); + //! [16] + }) + //! [4] + //! [5] + .onCanceled([this] { + updateStatus(tr("Download has been canceled.")); + }) + .onFailed([this](QNetworkReply::NetworkError error) { + updateStatus(tr("Download finished with error: %1").arg(error)); + // Abort all pending requests + abortDownload(); + }) + .onFailed([this](const std::exception &ex) { + updateStatus(tr(ex.what())); + }) + //! [5] + .then([this]() { + cancelButton->setEnabled(false); + addUrlsButton->setEnabled(true); + }); + } +} + +//! [7] +void Images::cancel() +{ + statusBar->showMessage(tr("Canceling...")); + + downloadFuture.cancel(); + abortDownload(); +} +//! [7] + +//! [15] +void Images::scaleFinished() +{ + const OptionalImages result = scalingWatcher.result(); + if (result.has_value()) { + const auto scaled = result.value(); + showImages(scaled); + updateStatus(tr("Finished")); + } else { + updateStatus(tr("Failed to extract image data.")); + } + addUrlsButton->setEnabled(true); +} +//! [15] + +//! [8] +QFuture Images::download(const QList &urls) +{ +//! [8] +//! [9] + QSharedPointer> promise(new QPromise()); + promise->start(); +//! [9] + + //! [10] + for (const auto &url : urls) { + QSharedPointer reply(qnam.get(QNetworkRequest(url))); + replies.push_back(reply); + //! [10] + + //! [11] + QtFuture::connect(reply.get(), &QNetworkReply::finished).then([=] { + if (promise->isCanceled()) { + if (!promise->future().isFinished()) + promise->finish(); + return; + } + + if (reply->error() != QNetworkReply::NoError) { + if (!promise->future().isFinished()) + throw reply->error(); + } + //! [12] + promise->addResult(reply->readAll()); + + // Report finished on the last download + if (promise->future().resultCount() == urls.size()) + promise->finish(); + //! [12] + }).onFailed([promise] (QNetworkReply::NetworkError error) { + promise->setException(std::make_exception_ptr(error)); + promise->finish(); + }).onFailed([promise] { + const auto ex = std::make_exception_ptr( + std::runtime_error("Unknown error occurred while downloading.")); + promise->setException(ex); + promise->finish(); + }); + } + //! [11] + +//! [13] + return promise->future(); +} +//! [13] + +//! [14] +Images::OptionalImages Images::scaled(const QList &data) +{ + QList scaled; + for (const auto &imgData : data) { + QImage image; + image.loadFromData(imgData); + if (image.isNull()) + return std::nullopt; + + scaled.push_back(image.scaled(100, 100, Qt::KeepAspectRatio)); + } + + return scaled; +} +//! [14] + +void Images::showImages(const QList &images) +{ + for (int i = 0; i < images.size(); ++i) { + labels[i]->setAlignment(Qt::AlignCenter); + labels[i]->setPixmap(QPixmap::fromImage(images[i])); + } +} + +void Images::initLayout(qsizetype count) +{ + // Clean old images + QLayoutItem *child; + while ((child = imagesLayout->takeAt(0)) != nullptr) { + child->widget()->setParent(nullptr); + delete child->widget(); + delete child; + } + labels.clear(); + + // Init the images layout for the new images + const auto dim = int(qSqrt(qreal(count))) + 1; + for (int i = 0; i < dim; ++i) { + for (int j = 0; j < dim; ++j) { + QLabel *imageLabel = new QLabel; + imageLabel->setFixedSize(100, 100); + imagesLayout->addWidget(imageLabel, i, j); + labels.append(imageLabel); + } + } +} + +void Images::updateStatus(const QString &msg) +{ + statusBar->showMessage(msg); +} + +void Images::abortDownload() +{ + for (auto reply : replies) + reply->abort(); +} diff --git a/tests/manual/tasking/imagescaling/imagescaling.h b/tests/manual/tasking/imagescaling/imagescaling.h new file mode 100644 index 00000000000..d66c9564d28 --- /dev/null +++ b/tests/manual/tasking/imagescaling/imagescaling.h @@ -0,0 +1,54 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef IMAGESCALING_H +#define IMAGESCALING_H + +#include +#include +#include +#include + +class DownloadDialog; +class Images : public QWidget +{ +Q_OBJECT +public: + Images(QWidget *parent = nullptr); + ~Images(); + + void initLayout(qsizetype count); + + QFuture download(const QList &urls); + void updateStatus(const QString &msg); + void showImages(const QList &images); + void abortDownload(); + +public slots: + void process(); + void cancel(); + +private slots: + void scaleFinished(); + +private: + //! [1] + using OptionalImages = std::optional>; + //! [1] + static OptionalImages scaled(const QList &data); + + QPushButton *addUrlsButton; + QPushButton *cancelButton; + QVBoxLayout *mainLayout; + QList labels; + QGridLayout *imagesLayout; + QStatusBar *statusBar; + DownloadDialog *downloadDialog; + + QNetworkAccessManager qnam; + QList> replies; + QFuture downloadFuture; + QFutureWatcher scalingWatcher; +}; + +#endif // IMAGESCALING_H diff --git a/tests/manual/tasking/imagescaling/imagescaling.qbs b/tests/manual/tasking/imagescaling/imagescaling.qbs new file mode 100644 index 00000000000..ea0698c7292 --- /dev/null +++ b/tests/manual/tasking/imagescaling/imagescaling.qbs @@ -0,0 +1,18 @@ +import qbs.FileInfo + +QtcManualtest { + name: "Tasking imagescaling" + type: ["application"] + + Depends { name: "Qt"; submodules: ["concurrent", "network", "widgets"] } + Depends { name: "Tasking" } + + files: [ + "downloaddialog.cpp", + "downloaddialog.h", + "downloaddialog.ui", + "imagescaling.cpp", + "imagescaling.h", + "main.cpp", + ] +} diff --git a/tests/manual/tasking/imagescaling/main.cpp b/tests/manual/tasking/imagescaling/main.cpp new file mode 100644 index 00000000000..a3ae6491f00 --- /dev/null +++ b/tests/manual/tasking/imagescaling/main.cpp @@ -0,0 +1,18 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "imagescaling.h" +#include + +int main(int argc, char *argv[]) +{ + QApplication app(argc,argv); + app.setOrganizationName("QtProject"); + app.setApplicationName(QObject::tr("Image Downloading and Scaling")); + + Images imageView; + imageView.setWindowTitle(QObject::tr("Image Downloading and Scaling")); + imageView.show(); + + return app.exec(); +} From 3f9704846b497119a06e16171e3baa2aa61c6a05 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Sat, 3 Jun 2023 10:45:09 +0200 Subject: [PATCH 127/141] ImageScaling: Get rid of doc example markers In order to more easily compare both implementations. Change-Id: I4ff48cb4d4e61be4e2c8834f63091f4d825db0be Reviewed-by: Marcus Tillmanns Reviewed-by: Qt CI Bot Reviewed-by: --- .../tasking/imagescaling/imagescaling.cpp | 32 ------------------- .../tasking/imagescaling/imagescaling.h | 2 -- 2 files changed, 34 deletions(-) diff --git a/tests/manual/tasking/imagescaling/imagescaling.cpp b/tests/manual/tasking/imagescaling/imagescaling.cpp index f380ae9d908..362a30287e6 100644 --- a/tests/manual/tasking/imagescaling/imagescaling.cpp +++ b/tests/manual/tasking/imagescaling/imagescaling.cpp @@ -11,15 +11,11 @@ Images::Images(QWidget *parent) : QWidget(parent), downloadDialog(new DownloadDi resize(800, 600); addUrlsButton = new QPushButton(tr("Add URLs")); -//! [1] connect(addUrlsButton, &QPushButton::clicked, this, &Images::process); -//! [1] cancelButton = new QPushButton(tr("Cancel")); cancelButton->setEnabled(false); -//! [2] connect(cancelButton, &QPushButton::clicked, this, &Images::cancel); -//! [2] QHBoxLayout *buttonLayout = new QHBoxLayout(); buttonLayout->addWidget(addUrlsButton); @@ -37,10 +33,8 @@ Images::Images(QWidget *parent) : QWidget(parent), downloadDialog(new DownloadDi mainLayout->addWidget(statusBar); setLayout(mainLayout); -//! [6] connect(&scalingWatcher, &QFutureWatcher>::finished, this, &Images::scaleFinished); -//! [6] } Images::~Images() @@ -48,7 +42,6 @@ Images::~Images() cancel(); } -//! [3] void Images::process() { // Clean previous state @@ -67,20 +60,14 @@ void Images::process() downloadFuture = download(urls); statusBar->showMessage(tr("Downloading...")); -//! [3] - //! [4] downloadFuture .then([this](auto) { cancelButton->setEnabled(false); updateStatus(tr("Scaling...")); - //! [16] scalingWatcher.setFuture(QtConcurrent::run(Images::scaled, downloadFuture.results())); - //! [16] }) - //! [4] - //! [5] .onCanceled([this] { updateStatus(tr("Download has been canceled.")); }) @@ -92,7 +79,6 @@ void Images::process() .onFailed([this](const std::exception &ex) { updateStatus(tr(ex.what())); }) - //! [5] .then([this]() { cancelButton->setEnabled(false); addUrlsButton->setEnabled(true); @@ -100,7 +86,6 @@ void Images::process() } } -//! [7] void Images::cancel() { statusBar->showMessage(tr("Canceling...")); @@ -108,9 +93,7 @@ void Images::cancel() downloadFuture.cancel(); abortDownload(); } -//! [7] -//! [15] void Images::scaleFinished() { const OptionalImages result = scalingWatcher.result(); @@ -123,24 +106,16 @@ void Images::scaleFinished() } addUrlsButton->setEnabled(true); } -//! [15] -//! [8] QFuture Images::download(const QList &urls) { -//! [8] -//! [9] QSharedPointer> promise(new QPromise()); promise->start(); -//! [9] - //! [10] for (const auto &url : urls) { QSharedPointer reply(qnam.get(QNetworkRequest(url))); replies.push_back(reply); - //! [10] - //! [11] QtFuture::connect(reply.get(), &QNetworkReply::finished).then([=] { if (promise->isCanceled()) { if (!promise->future().isFinished()) @@ -152,13 +127,11 @@ QFuture Images::download(const QList &urls) if (!promise->future().isFinished()) throw reply->error(); } - //! [12] promise->addResult(reply->readAll()); // Report finished on the last download if (promise->future().resultCount() == urls.size()) promise->finish(); - //! [12] }).onFailed([promise] (QNetworkReply::NetworkError error) { promise->setException(std::make_exception_ptr(error)); promise->finish(); @@ -169,14 +142,10 @@ QFuture Images::download(const QList &urls) promise->finish(); }); } - //! [11] -//! [13] return promise->future(); } -//! [13] -//! [14] Images::OptionalImages Images::scaled(const QList &data) { QList scaled; @@ -191,7 +160,6 @@ Images::OptionalImages Images::scaled(const QList &data) return scaled; } -//! [14] void Images::showImages(const QList &images) { diff --git a/tests/manual/tasking/imagescaling/imagescaling.h b/tests/manual/tasking/imagescaling/imagescaling.h index d66c9564d28..d3409e60a0f 100644 --- a/tests/manual/tasking/imagescaling/imagescaling.h +++ b/tests/manual/tasking/imagescaling/imagescaling.h @@ -32,9 +32,7 @@ private slots: void scaleFinished(); private: - //! [1] using OptionalImages = std::optional>; - //! [1] static OptionalImages scaled(const QList &data); QPushButton *addUrlsButton; From 6b04989fce21ce524e66662fe534c8c932995d6b Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Thu, 1 Jun 2023 19:12:52 +0200 Subject: [PATCH 128/141] Utils: Introduce customMargin(const QMargins &) And re-use it for normalMargin() and noMargin() Change-Id: Id779e2fa052ab35df3dd917d890ca7808dfb1a8c Reviewed-by: hjk Reviewed-by: Reviewed-by: Qt CI Patch Build Bot --- src/libs/utils/layoutbuilder.cpp | 20 +++++++++----------- src/libs/utils/layoutbuilder.h | 2 ++ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/libs/utils/layoutbuilder.cpp b/src/libs/utils/layoutbuilder.cpp index bea7faafd3b..94aa80f02cc 100644 --- a/src/libs/utils/layoutbuilder.cpp +++ b/src/libs/utils/layoutbuilder.cpp @@ -676,24 +676,22 @@ LayoutItem st() LayoutItem noMargin() { - LayoutItem item; - item.onAdd = [](LayoutBuilder &builder) { - if (auto layout = builder.stack.last().layout) - layout->setContentsMargins(0, 0, 0, 0); - else if (auto widget = builder.stack.last().widget) - widget->setContentsMargins(0, 0, 0, 0); - }; - return item; + return customMargin({}); } LayoutItem normalMargin() +{ + return customMargin({9, 9, 9, 9}); +} + +LayoutItem customMargin(const QMargins &margin) { LayoutItem item; - item.onAdd = [](LayoutBuilder &builder) { + item.onAdd = [margin](LayoutBuilder &builder) { if (auto layout = builder.stack.last().layout) - layout->setContentsMargins(9, 9, 9, 9); + layout->setContentsMargins(margin); else if (auto widget = builder.stack.last().widget) - widget->setContentsMargins(9, 9, 9, 9); + widget->setContentsMargins(margin); }; return item; } diff --git a/src/libs/utils/layoutbuilder.h b/src/libs/utils/layoutbuilder.h index 1f774ba1461..4a756139897 100644 --- a/src/libs/utils/layoutbuilder.h +++ b/src/libs/utils/layoutbuilder.h @@ -19,6 +19,7 @@ QT_BEGIN_NAMESPACE class QLayout; +class QMargins; class QObject; class QWidget; template T qobject_cast(QObject *object); @@ -202,6 +203,7 @@ QTCREATOR_UTILS_EXPORT LayoutItem empty(); QTCREATOR_UTILS_EXPORT LayoutItem hr(); QTCREATOR_UTILS_EXPORT LayoutItem noMargin(); QTCREATOR_UTILS_EXPORT LayoutItem normalMargin(); +QTCREATOR_UTILS_EXPORT LayoutItem customMargin(const QMargins &margin); QTCREATOR_UTILS_EXPORT LayoutItem withFormAlignment(); // "Setters" From 8b85ac30a49dec9a0b27af9a5c1d26b4a60470af Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Fri, 2 Jun 2023 15:15:48 +0200 Subject: [PATCH 129/141] Do not show Design Studio settings page in Qt Creator Change-Id: Iab2b8806f8041685440670fe741f25fb895afd99 Reviewed-by: Reviewed-by: Alessandro Portale Reviewed-by: Mahmoud Badri --- src/plugins/qmldesignerbase/qmldesignerbaseplugin.cpp | 7 ++++--- src/plugins/studiowelcome/examplecheckout.cpp | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/plugins/qmldesignerbase/qmldesignerbaseplugin.cpp b/src/plugins/qmldesignerbase/qmldesignerbaseplugin.cpp index c59fcbb2ea1..703c1cf7605 100644 --- a/src/plugins/qmldesignerbase/qmldesignerbaseplugin.cpp +++ b/src/plugins/qmldesignerbase/qmldesignerbaseplugin.cpp @@ -21,7 +21,7 @@ class QmlDesignerBasePlugin::Data public: DesignerSettings settings; StudioStyle *style = nullptr; - StudioConfigSettingsPage studioConfigSettingsPage; + std::unique_ptr studioConfigSettingsPage; Data() : settings(Core::ICore::settings()) @@ -54,13 +54,14 @@ QStyle *QmlDesignerBasePlugin::style() StudioConfigSettingsPage *QmlDesignerBasePlugin::studioConfigSettingsPage() { - return &global->d->studioConfigSettingsPage; + return global->d->studioConfigSettingsPage.get(); } bool QmlDesignerBasePlugin::initialize(const QStringList &, QString *) { d = std::make_unique(); - + if (Core::ICore::settings()->value("QML/Designer/StandAloneMode", false).toBool()) + d->studioConfigSettingsPage = std::make_unique(); return true; } diff --git a/src/plugins/studiowelcome/examplecheckout.cpp b/src/plugins/studiowelcome/examplecheckout.cpp index 61a8e429d68..b919bf29394 100644 --- a/src/plugins/studiowelcome/examplecheckout.cpp +++ b/src/plugins/studiowelcome/examplecheckout.cpp @@ -105,9 +105,10 @@ DataModelDownloader::DataModelDownloader(QObject * /* parent */) return; auto studioWelcomePlugin = qobject_cast(plugin); - - if (studioWelcomePlugin) { - QObject::connect(QmlDesigner::QmlDesignerBasePlugin::studioConfigSettingsPage(), + QmlDesigner::StudioConfigSettingsPage *settingsPage + = QmlDesigner::QmlDesignerBasePlugin::studioConfigSettingsPage(); + if (studioWelcomePlugin && settingsPage) { + QObject::connect(settingsPage, &QmlDesigner::StudioConfigSettingsPage::examplesDownloadPathChanged, this, &DataModelDownloader::targetPathMustChange); From 969f560c61438971b57b20ee38b6bcdb537ac1b2 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 6 Jun 2023 09:19:40 +0200 Subject: [PATCH 130/141] SilverSearcher: Fix missing include Amends 64d209c24bb618fee5e0d4ba427d656c3b71e5ff. Change-Id: Ib73302e98e4779e8d8f232852d45903a4055172a Reviewed-by: Jarek Kobus --- src/plugins/silversearcher/silversearcherparser.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/silversearcher/silversearcherparser.cpp b/src/plugins/silversearcher/silversearcherparser.cpp index 1a2f5e55e87..7880bd78eba 100644 --- a/src/plugins/silversearcher/silversearcherparser.cpp +++ b/src/plugins/silversearcher/silversearcherparser.cpp @@ -3,6 +3,8 @@ #include "silversearcherparser.h" +#include + using namespace Utils; namespace SilverSearcher { From d97d3f58ac976f05be0a43f2d807ce4f0240ab34 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Mon, 29 May 2023 20:16:19 +0200 Subject: [PATCH 131/141] TaskTree: Rename TaskItem into GroupItem Not all classes derived from TaskItem are tasks, but the common denominator is that all may be placed inside a group: thus GroupItem sounds more appropriate. Addresses the 10th point in the bugreport below. Task-number: QTCREATORBUG-28741 Change-Id: I94d728a8e39ec732810f2e5bbe6b9a76f3bc387c Reviewed-by: Qt CI Patch Build Bot Reviewed-by: Reviewed-by: Qt CI Bot Reviewed-by: hjk --- src/libs/solutions/tasking/tasktree.cpp | 81 ++++++++-------- src/libs/solutions/tasking/tasktree.h | 96 +++++++++---------- src/libs/utils/filestreamer.cpp | 22 ++--- src/plugins/autotest/testcodeparser.cpp | 2 +- src/plugins/autotest/testrunner.cpp | 2 +- .../clangtools/clangtoolruncontrol.cpp | 2 +- src/plugins/clangtools/clangtoolrunner.cpp | 6 +- src/plugins/clangtools/clangtoolrunner.h | 8 +- .../clangtools/documentclangtoolrunner.cpp | 2 +- .../coreplugin/locator/ilocatorfilter.cpp | 6 +- .../coreplugin/locator/ilocatorfilter.h | 8 +- src/plugins/coreplugin/locator/locator.cpp | 2 +- src/plugins/cppeditor/cppprojectupdater.cpp | 2 +- src/plugins/diffeditor/diffeditorplugin.cpp | 2 +- src/plugins/git/gitclient.cpp | 2 +- src/plugins/projectexplorer/extracompiler.cpp | 4 +- src/plugins/projectexplorer/extracompiler.h | 8 +- src/plugins/qmakeprojectmanager/qmakestep.cpp | 2 +- .../qnx/qnxdeployqtlibrariesdialog.cpp | 22 ++--- .../remotelinux/genericdirectuploadstep.cpp | 34 +++---- src/plugins/remotelinux/linuxdevicetester.cpp | 40 ++++---- src/plugins/remotelinux/linuxdevicetester.h | 4 +- src/plugins/remotelinux/rsyncdeploystep.cpp | 8 +- .../remotelinux/tarpackagedeploystep.cpp | 8 +- src/plugins/updateinfo/updateinfoplugin.cpp | 2 +- .../vcsbase/vcsbasediffeditorcontroller.cpp | 2 +- .../vcsbase/vcsbasediffeditorcontroller.h | 2 +- tests/auto/solutions/tasking/tst_tasking.cpp | 6 +- tests/auto/utils/async/tst_async.cpp | 2 +- .../tst_subdirfileiterator.cpp | 4 +- tests/manual/tasking/demo/main.cpp | 2 +- tests/manual/tasking/demo/taskwidget.cpp | 4 +- tests/manual/tasking/demo/taskwidget.h | 4 +- 33 files changed, 201 insertions(+), 200 deletions(-) diff --git a/src/libs/solutions/tasking/tasktree.cpp b/src/libs/solutions/tasking/tasktree.cpp index f9fe58375e8..2a4c7cefd98 100644 --- a/src/libs/solutions/tasking/tasktree.cpp +++ b/src/libs/solutions/tasking/tasktree.cpp @@ -43,11 +43,11 @@ private: }; /*! - \class Tasking::TaskItem + \class Tasking::GroupItem \inheaderfile solutions/tasking/tasktree.h \inmodule QtCreator \ingroup mainclasses - \brief The TaskItem class represents the basic element for composing nested tree structures. + \brief The GroupItem class represents the basic element for composing nested tree structures. */ /*! @@ -246,7 +246,7 @@ private: */ /*! - \typealias TaskItem::GroupSetupHandler + \typealias GroupItem::GroupSetupHandler Type alias for \c std::function. @@ -277,7 +277,7 @@ private: */ /*! - \typealias TaskItem::GroupEndHandler + \typealias GroupItem::GroupEndHandler Type alias for \c std::function\. @@ -290,13 +290,14 @@ private: */ /*! - \fn template TaskItem onGroupSetup(SetupHandler &&handler) + \fn template GroupItem onGroupSetup(SetupHandler &&handler) Constructs a group's element holding the group setup handler. The \a handler is invoked whenever the group starts. The passed \a handler is either of \c std::function or \c std::function - type. For more information on possible argument type, refer to \l {TaskItem::GroupSetupHandler}. + type. For more information on possible argument type, refer to + \l {GroupItem::GroupSetupHandler}. When the \a handler is invoked, none of the group's child tasks are running yet. @@ -304,7 +305,7 @@ private: after the storages are constructed, so that the \a handler may already perform some initial modifications to the active storages. - \sa TaskItem::GroupSetupHandler, onGroupDone, onGroupError + \sa GroupItem::GroupSetupHandler, onGroupDone, onGroupError */ /*! @@ -319,9 +320,9 @@ private: before the storages are destructed, so that the \a handler may still perform a last read of the active storages' data. - \sa TaskItem::GroupEndHandler, onGroupSetup, onGroupError + \sa GroupItem::GroupEndHandler, onGroupSetup, onGroupError */ -TaskItem onGroupDone(const TaskItem::GroupEndHandler &handler) +GroupItem onGroupDone(const GroupItem::GroupEndHandler &handler) { return Group::onGroupDone(handler); } @@ -338,9 +339,9 @@ TaskItem onGroupDone(const TaskItem::GroupEndHandler &handler) before the storages are destructed, so that the \a handler may still perform a last read of the active storages' data. - \sa TaskItem::GroupEndHandler, onGroupSetup, onGroupDone + \sa GroupItem::GroupEndHandler, onGroupSetup, onGroupDone */ -TaskItem onGroupError(const TaskItem::GroupEndHandler &handler) +GroupItem onGroupError(const GroupItem::GroupEndHandler &handler) { return Group::onGroupError(handler); } @@ -386,7 +387,7 @@ TaskItem onGroupError(const TaskItem::GroupEndHandler &handler) \sa sequential, parallel */ -TaskItem parallelLimit(int limit) +GroupItem parallelLimit(int limit) { return Group::parallelLimit(qMax(limit, 0)); } @@ -399,21 +400,21 @@ TaskItem parallelLimit(int limit) \sa stopOnError, continueOnError, stopOnDone, continueOnDone, stopOnFinished, finishAllAndDone, finishAllAndError, WorkflowPolicy */ -TaskItem workflowPolicy(WorkflowPolicy policy) +GroupItem workflowPolicy(WorkflowPolicy policy) { return Group::workflowPolicy(policy); } -const TaskItem sequential = parallelLimit(1); -const TaskItem parallel = parallelLimit(0); +const GroupItem sequential = parallelLimit(1); +const GroupItem parallel = parallelLimit(0); -const TaskItem stopOnError = workflowPolicy(WorkflowPolicy::StopOnError); -const TaskItem continueOnError = workflowPolicy(WorkflowPolicy::ContinueOnError); -const TaskItem stopOnDone = workflowPolicy(WorkflowPolicy::StopOnDone); -const TaskItem continueOnDone = workflowPolicy(WorkflowPolicy::ContinueOnDone); -const TaskItem stopOnFinished = workflowPolicy(WorkflowPolicy::StopOnFinished); -const TaskItem finishAllAndDone = workflowPolicy(WorkflowPolicy::FinishAllAndDone); -const TaskItem finishAllAndError = workflowPolicy(WorkflowPolicy::FinishAllAndError); +const GroupItem stopOnError = workflowPolicy(WorkflowPolicy::StopOnError); +const GroupItem continueOnError = workflowPolicy(WorkflowPolicy::ContinueOnError); +const GroupItem stopOnDone = workflowPolicy(WorkflowPolicy::StopOnDone); +const GroupItem continueOnDone = workflowPolicy(WorkflowPolicy::ContinueOnDone); +const GroupItem stopOnFinished = workflowPolicy(WorkflowPolicy::StopOnFinished); +const GroupItem finishAllAndDone = workflowPolicy(WorkflowPolicy::FinishAllAndDone); +const GroupItem finishAllAndError = workflowPolicy(WorkflowPolicy::FinishAllAndError); static TaskAction toTaskAction(bool success) { @@ -483,11 +484,11 @@ void TreeStorageBase::activateStorage(int id) const m_storageData->m_activeStorage = id; } -void TaskItem::addChildren(const QList &children) +void GroupItem::addChildren(const QList &children) { QTC_ASSERT(m_type == Type::Group, qWarning("Only Group may have children, skipping..."); return); - for (const TaskItem &child : children) { + for (const GroupItem &child : children) { switch (child.m_type) { case Type::Group: m_children.append(child); @@ -534,7 +535,7 @@ void TaskItem::addChildren(const QList &children) } } -void TaskItem::setTaskSetupHandler(const TaskSetupHandler &handler) +void GroupItem::setTaskSetupHandler(const TaskSetupHandler &handler) { if (!handler) { qWarning("Setting empty Setup Handler is no-op, skipping..."); @@ -545,7 +546,7 @@ void TaskItem::setTaskSetupHandler(const TaskSetupHandler &handler) m_taskHandler.m_setupHandler = handler; } -void TaskItem::setTaskDoneHandler(const TaskEndHandler &handler) +void GroupItem::setTaskDoneHandler(const TaskEndHandler &handler) { if (!handler) { qWarning("Setting empty Done Handler is no-op, skipping..."); @@ -556,7 +557,7 @@ void TaskItem::setTaskDoneHandler(const TaskEndHandler &handler) m_taskHandler.m_doneHandler = handler; } -void TaskItem::setTaskErrorHandler(const TaskEndHandler &handler) +void GroupItem::setTaskErrorHandler(const TaskEndHandler &handler) { if (!handler) { qWarning("Setting empty Error Handler is no-op, skipping..."); @@ -567,8 +568,8 @@ void TaskItem::setTaskErrorHandler(const TaskEndHandler &handler) m_taskHandler.m_errorHandler = handler; } -TaskItem TaskItem::withTimeout(const TaskItem &item, milliseconds timeout, - const GroupEndHandler &handler) +GroupItem GroupItem::withTimeout(const GroupItem &item, milliseconds timeout, + const GroupEndHandler &handler) { const TimeoutTask::EndHandler taskHandler = handler ? [handler](const milliseconds &) { handler(); } : TimeoutTask::EndHandler(); @@ -640,7 +641,7 @@ class TaskContainer Q_DISABLE_COPY_MOVE(TaskContainer) public: - TaskContainer(TaskTreePrivate *taskTreePrivate, const TaskItem &task, + TaskContainer(TaskTreePrivate *taskTreePrivate, const GroupItem &task, TaskNode *parentNode, TaskContainer *parentContainer) : m_constData(taskTreePrivate, task, parentNode, parentContainer, this) {} TaskAction start(); @@ -653,7 +654,7 @@ public: bool isStarting() const { return isRunning() && m_runtimeData->m_startGuard.isLocked(); } struct ConstData { - ConstData(TaskTreePrivate *taskTreePrivate, const TaskItem &task, TaskNode *parentNode, + ConstData(TaskTreePrivate *taskTreePrivate, const GroupItem &task, TaskNode *parentNode, TaskContainer *parentContainer, TaskContainer *thisContainer); ~ConstData() { qDeleteAll(m_children); } TaskTreePrivate * const m_taskTreePrivate = nullptr; @@ -662,7 +663,7 @@ public: const int m_parallelLimit = 1; const WorkflowPolicy m_workflowPolicy = WorkflowPolicy::StopOnError; - const TaskItem::GroupHandler m_groupHandler; + const GroupItem::GroupHandler m_groupHandler; const QList m_storageList; const QList m_children; const int m_taskCount = 0; @@ -693,7 +694,7 @@ class TaskNode Q_DISABLE_COPY_MOVE(TaskNode) public: - TaskNode(TaskTreePrivate *taskTreePrivate, const TaskItem &task, + TaskNode(TaskTreePrivate *taskTreePrivate, const GroupItem &task, TaskContainer *parentContainer) : m_taskHandler(task.taskHandler()) , m_container(taskTreePrivate, task, this, parentContainer) @@ -711,7 +712,7 @@ public: TaskTree *taskTree() const { return m_container.m_constData.m_taskTreePrivate->q; } private: - const TaskItem::TaskHandler m_taskHandler; + const GroupItem::TaskHandler m_taskHandler; TaskContainer m_container; std::unique_ptr m_task; }; @@ -831,16 +832,16 @@ ReturnType invokeHandler(TaskContainer *container, Handler &&handler, Args &&... } static QList createChildren(TaskTreePrivate *taskTreePrivate, TaskContainer *container, - const TaskItem &task) + const GroupItem &task) { QList result; - const QList &children = task.children(); - for (const TaskItem &child : children) + const QList &children = task.children(); + for (const GroupItem &child : children) result.append(new TaskNode(taskTreePrivate, child, container)); return result; } -TaskContainer::ConstData::ConstData(TaskTreePrivate *taskTreePrivate, const TaskItem &task, +TaskContainer::ConstData::ConstData(TaskTreePrivate *taskTreePrivate, const GroupItem &task, TaskNode *parentNode, TaskContainer *parentContainer, TaskContainer *thisContainer) : m_taskTreePrivate(taskTreePrivate) @@ -1035,7 +1036,7 @@ void TaskContainer::stop() void TaskContainer::invokeEndHandler() { - const TaskItem::GroupHandler &groupHandler = m_constData.m_groupHandler; + const GroupItem::GroupHandler &groupHandler = m_constData.m_groupHandler; if (m_runtimeData->m_successBit && groupHandler.m_doneHandler) invokeHandler(this, groupHandler.m_doneHandler); else if (!m_runtimeData->m_successBit && groupHandler.m_errorHandler) @@ -1539,7 +1540,7 @@ void TaskNode::invokeEndHandler(bool success) static QByteArray load(const QString &fileName) { ... } static void save(const QString &fileName, const QByteArray &array) { ... } - static TaskItem copyRecipe(const QString &source, const QString &destination) + static GroupItem copyRecipe(const QString &source, const QString &destination) { struct CopyStorage { // [1] custom inter-task struct QByteArray content; // [2] custom inter-task data diff --git a/src/libs/solutions/tasking/tasktree.h b/src/libs/solutions/tasking/tasktree.h index 647c680b5b0..dcd7b86ac18 100644 --- a/src/libs/solutions/tasking/tasktree.h +++ b/src/libs/solutions/tasking/tasktree.h @@ -123,7 +123,7 @@ enum class TaskAction }; Q_ENUM_NS(TaskAction); -class TASKING_EXPORT TaskItem +class TASKING_EXPORT GroupItem { public: // Internal, provided by QTC_DECLARE_CUSTOM_TASK @@ -156,7 +156,7 @@ public: std::optional m_workflowPolicy = {}; }; - QList children() const { return m_children; } + QList children() const { return m_children; } GroupData groupData() const { return m_groupData; } QList storageList() const { return m_storageList; } TaskHandler taskHandler() const { return m_taskHandler; } @@ -169,58 +169,58 @@ protected: TaskHandler }; - TaskItem() = default; - TaskItem(const GroupData &data) + GroupItem() = default; + GroupItem(const GroupData &data) : m_type(Type::GroupData) , m_groupData(data) {} - TaskItem(const TreeStorageBase &storage) + GroupItem(const TreeStorageBase &storage) : m_type(Type::Storage) , m_storageList{storage} {} - TaskItem(const TaskHandler &handler) + GroupItem(const TaskHandler &handler) : m_type(Type::TaskHandler) , m_taskHandler(handler) {} - void addChildren(const QList &children); + void addChildren(const QList &children); void setTaskSetupHandler(const TaskSetupHandler &handler); void setTaskDoneHandler(const TaskEndHandler &handler); void setTaskErrorHandler(const TaskEndHandler &handler); - static TaskItem groupHandler(const GroupHandler &handler) { return TaskItem({handler}); } - static TaskItem parallelLimit(int limit) { return TaskItem({{}, limit}); } - static TaskItem workflowPolicy(WorkflowPolicy policy) { return TaskItem({{}, {}, policy}); } - static TaskItem withTimeout(const TaskItem &item, std::chrono::milliseconds timeout, + static GroupItem groupHandler(const GroupHandler &handler) { return GroupItem({handler}); } + static GroupItem parallelLimit(int limit) { return GroupItem({{}, limit}); } + static GroupItem workflowPolicy(WorkflowPolicy policy) { return GroupItem({{}, {}, policy}); } + static GroupItem withTimeout(const GroupItem &item, std::chrono::milliseconds timeout, const GroupEndHandler &handler = {}); private: Type m_type = Type::Group; - QList m_children; + QList m_children; GroupData m_groupData; QList m_storageList; TaskHandler m_taskHandler; }; -class TASKING_EXPORT Group : public TaskItem +class TASKING_EXPORT Group : public GroupItem { public: - Group(const QList &children) { addChildren(children); } - Group(std::initializer_list children) { addChildren(children); } + Group(const QList &children) { addChildren(children); } + Group(std::initializer_list children) { addChildren(children); } // GroupData related: template - static TaskItem onGroupSetup(SetupHandler &&handler) { + static GroupItem onGroupSetup(SetupHandler &&handler) { return groupHandler({wrapGroupSetup(std::forward(handler))}); } - static TaskItem onGroupDone(const GroupEndHandler &handler) { + static GroupItem onGroupDone(const GroupEndHandler &handler) { return groupHandler({{}, handler}); } - static TaskItem onGroupError(const GroupEndHandler &handler) { + static GroupItem onGroupError(const GroupEndHandler &handler) { return groupHandler({{}, {}, handler}); } - using TaskItem::parallelLimit; // Default: 1 (sequential). 0 means unlimited (parallel). - using TaskItem::workflowPolicy; // Default: WorkflowPolicy::StopOnError. + using GroupItem::parallelLimit; // Default: 1 (sequential). 0 means unlimited (parallel). + using GroupItem::workflowPolicy; // Default: WorkflowPolicy::StopOnError. - TaskItem withTimeout(std::chrono::milliseconds timeout, - const GroupEndHandler &handler = {}) const { - return TaskItem::withTimeout(*this, timeout, handler); + GroupItem withTimeout(std::chrono::milliseconds timeout, + const GroupEndHandler &handler = {}) const { + return GroupItem::withTimeout(*this, timeout, handler); } private: @@ -244,31 +244,31 @@ private: }; template -static TaskItem onGroupSetup(SetupHandler &&handler) +static GroupItem onGroupSetup(SetupHandler &&handler) { return Group::onGroupSetup(std::forward(handler)); } -TASKING_EXPORT TaskItem onGroupDone(const TaskItem::GroupEndHandler &handler); -TASKING_EXPORT TaskItem onGroupError(const TaskItem::GroupEndHandler &handler); -TASKING_EXPORT TaskItem parallelLimit(int limit); -TASKING_EXPORT TaskItem workflowPolicy(WorkflowPolicy policy); +TASKING_EXPORT GroupItem onGroupDone(const GroupItem::GroupEndHandler &handler); +TASKING_EXPORT GroupItem onGroupError(const GroupItem::GroupEndHandler &handler); +TASKING_EXPORT GroupItem parallelLimit(int limit); +TASKING_EXPORT GroupItem workflowPolicy(WorkflowPolicy policy); -TASKING_EXPORT extern const TaskItem sequential; -TASKING_EXPORT extern const TaskItem parallel; +TASKING_EXPORT extern const GroupItem sequential; +TASKING_EXPORT extern const GroupItem parallel; -TASKING_EXPORT extern const TaskItem stopOnError; -TASKING_EXPORT extern const TaskItem continueOnError; -TASKING_EXPORT extern const TaskItem stopOnDone; -TASKING_EXPORT extern const TaskItem continueOnDone; -TASKING_EXPORT extern const TaskItem stopOnFinished; -TASKING_EXPORT extern const TaskItem finishAllAndDone; -TASKING_EXPORT extern const TaskItem finishAllAndError; +TASKING_EXPORT extern const GroupItem stopOnError; +TASKING_EXPORT extern const GroupItem continueOnError; +TASKING_EXPORT extern const GroupItem stopOnDone; +TASKING_EXPORT extern const GroupItem continueOnDone; +TASKING_EXPORT extern const GroupItem stopOnFinished; +TASKING_EXPORT extern const GroupItem finishAllAndDone; +TASKING_EXPORT extern const GroupItem finishAllAndError; -class TASKING_EXPORT Storage : public TaskItem +class TASKING_EXPORT Storage : public GroupItem { public: - Storage(const TreeStorageBase &storage) : TaskItem(storage) { } + Storage(const TreeStorageBase &storage) : GroupItem(storage) { } }; // Synchronous invocation. Similarly to Group - isn't counted as a task inside taskCount() @@ -281,7 +281,7 @@ public: private: template - static QList init(Function &&function) { + static QList init(Function &&function) { constexpr bool isInvocable = std::is_invocable_v>; static_assert(isInvocable, "Sync element: The synchronous function can't take any arguments."); @@ -310,17 +310,17 @@ private: }; template -class CustomTask : public TaskItem +class CustomTask : public GroupItem { public: using Task = typename Adapter::Type; using EndHandler = std::function; static Adapter *createAdapter() { return new Adapter; } - CustomTask() : TaskItem({&createAdapter}) {} + CustomTask() : GroupItem({&createAdapter}) {} template CustomTask(SetupFunction &&function, const EndHandler &done = {}, const EndHandler &error = {}) - : TaskItem({&createAdapter, wrapSetup(std::forward(function)), - wrapEnd(done), wrapEnd(error)}) {} + : GroupItem({&createAdapter, wrapSetup(std::forward(function)), + wrapEnd(done), wrapEnd(error)}) {} template CustomTask &onSetup(SetupFunction &&function) { @@ -336,14 +336,14 @@ public: return *this; } - TaskItem withTimeout(std::chrono::milliseconds timeout, - const GroupEndHandler &handler = {}) const { - return TaskItem::withTimeout(*this, timeout, handler); + GroupItem withTimeout(std::chrono::milliseconds timeout, + const GroupEndHandler &handler = {}) const { + return GroupItem::withTimeout(*this, timeout, handler); } private: template - static TaskItem::TaskSetupHandler wrapSetup(SetupFunction &&function) { + static GroupItem::TaskSetupHandler wrapSetup(SetupFunction &&function) { static constexpr bool isDynamic = std::is_same_v, typename Adapter::Type &>>; constexpr bool isVoid = std::is_same_vdeleteLater(); @@ -49,8 +49,8 @@ protected: std::unique_ptr m_taskTree; private: - virtual TaskItem remoteTask() = 0; - virtual TaskItem localTask() = 0; + virtual GroupItem remoteTask() = 0; + virtual GroupItem localTask() = 0; }; static void localRead(QPromise &promise, const FilePath &filePath) @@ -84,7 +84,7 @@ signals: void readyRead(const QByteArray &newData); private: - TaskItem remoteTask() final { + GroupItem remoteTask() final { const auto setup = [this](Process &process) { const QStringList args = {"if=" + m_filePath.path()}; const FilePath dd = m_filePath.withNewPath("dd"); @@ -96,7 +96,7 @@ private: }; return ProcessTask(setup); } - TaskItem localTask() final { + GroupItem localTask() final { const auto setup = [this](Async &async) { async.setConcurrentCallData(localRead, m_filePath); Async *asyncPtr = &async; @@ -251,7 +251,7 @@ signals: void started(); private: - TaskItem remoteTask() final { + GroupItem remoteTask() final { const auto setup = [this](Process &process) { m_writeBuffer = new WriteBuffer(false, &process); connect(m_writeBuffer, &WriteBuffer::writeRequested, &process, &Process::writeRaw); @@ -272,7 +272,7 @@ private: }; return ProcessTask(setup, finalize, finalize); } - TaskItem localTask() final { + GroupItem localTask() final { const auto setup = [this](Async &async) { m_writeBuffer = new WriteBuffer(isBuffered(), &async); async.setConcurrentCallData(localWrite, m_filePath, m_writeData, m_writeBuffer); @@ -390,7 +390,7 @@ public: StreamResult m_streamResult = StreamResult::FinishedWithError; std::unique_ptr m_taskTree; - TaskItem task() { + GroupItem task() { if (m_streamerMode == StreamMode::Reader) return readerTask(); if (m_streamerMode == StreamMode::Writer) @@ -399,7 +399,7 @@ public: } private: - TaskItem readerTask() { + GroupItem readerTask() { const auto setup = [this](FileStreamReader &reader) { m_readBuffer.clear(); reader.setFilePath(m_source); @@ -409,14 +409,14 @@ private: }; return FileStreamReaderTask(setup); } - TaskItem writerTask() { + GroupItem writerTask() { const auto setup = [this](FileStreamWriter &writer) { writer.setFilePath(m_destination); writer.setWriteData(m_writeBuffer); }; return FileStreamWriterTask(setup); } - TaskItem transferTask() { + GroupItem transferTask() { const auto setup = [this](Async &async) { async.setConcurrentCallData(transfer, m_source, m_destination); }; diff --git a/src/plugins/autotest/testcodeparser.cpp b/src/plugins/autotest/testcodeparser.cpp index 66bbb256059..e78be579651 100644 --- a/src/plugins/autotest/testcodeparser.cpp +++ b/src/plugins/autotest/testcodeparser.cpp @@ -360,7 +360,7 @@ void TestCodeParser::scanForTests(const QSet &filePaths, using namespace Tasking; - QList tasks{parallelLimit(std::max(QThread::idealThreadCount() / 4, 1))}; + QList tasks{parallelLimit(std::max(QThread::idealThreadCount() / 4, 1))}; for (const FilePath &file : filteredFiles) { const auto setup = [this, codeParsers, file](Async &async) { async.setConcurrentCallData(parseFileForTests, codeParsers, file); diff --git a/src/plugins/autotest/testrunner.cpp b/src/plugins/autotest/testrunner.cpp index 5c53d742e65..23912f15d98 100644 --- a/src/plugins/autotest/testrunner.cpp +++ b/src/plugins/autotest/testrunner.cpp @@ -347,7 +347,7 @@ void TestRunner::runTestsHelper() std::unique_ptr m_outputReader; }; - QList tasks{finishAllAndDone}; + QList tasks{finishAllAndDone}; for (ITestConfiguration *config : m_selectedTests) { QTC_ASSERT(config, continue); diff --git a/src/plugins/clangtools/clangtoolruncontrol.cpp b/src/plugins/clangtools/clangtoolruncontrol.cpp index 11353b04ae4..39de004ac89 100644 --- a/src/plugins/clangtools/clangtoolruncontrol.cpp +++ b/src/plugins/clangtools/clangtoolruncontrol.cpp @@ -183,7 +183,7 @@ void ClangToolRunWorker::start() m_filesAnalyzed.clear(); m_filesNotAnalyzed.clear(); - QList tasks{parallelLimit(qMax(1, m_runSettings.parallelJobs()))}; + QList tasks{parallelLimit(qMax(1, m_runSettings.parallelJobs()))}; for (const AnalyzeUnit &unit : std::as_const(unitsToProcess)) { if (!m_diagnosticConfig.isEnabled(tool) && !m_runSettings.hasConfigFileForSourceFile(unit.file)) { diff --git a/src/plugins/clangtools/clangtoolrunner.cpp b/src/plugins/clangtools/clangtoolrunner.cpp index 3e2c7a6c111..6681a9133dd 100644 --- a/src/plugins/clangtools/clangtoolrunner.cpp +++ b/src/plugins/clangtools/clangtoolrunner.cpp @@ -101,9 +101,9 @@ static FilePath createOutputFilePath(const FilePath &dirPath, const FilePath &fi return {}; } -TaskItem clangToolTask(const AnalyzeInputData &input, - const AnalyzeSetupHandler &setupHandler, - const AnalyzeOutputHandler &outputHandler) +GroupItem clangToolTask(const AnalyzeInputData &input, + const AnalyzeSetupHandler &setupHandler, + const AnalyzeOutputHandler &outputHandler) { struct ClangToolStorage { QString name; diff --git a/src/plugins/clangtools/clangtoolrunner.h b/src/plugins/clangtools/clangtoolrunner.h index 3a0f59f3417..a8d1204c224 100644 --- a/src/plugins/clangtools/clangtoolrunner.h +++ b/src/plugins/clangtools/clangtoolrunner.h @@ -10,7 +10,7 @@ #include -namespace Tasking { class TaskItem; } +namespace Tasking { class GroupItem; } namespace ClangTools { namespace Internal { @@ -50,9 +50,9 @@ struct AnalyzeOutputData using AnalyzeSetupHandler = std::function; using AnalyzeOutputHandler = std::function; -Tasking::TaskItem clangToolTask(const AnalyzeInputData &input, - const AnalyzeSetupHandler &setupHandler, - const AnalyzeOutputHandler &outputHandler); +Tasking::GroupItem clangToolTask(const AnalyzeInputData &input, + const AnalyzeSetupHandler &setupHandler, + const AnalyzeOutputHandler &outputHandler); } // namespace Internal } // namespace ClangTools diff --git a/src/plugins/clangtools/documentclangtoolrunner.cpp b/src/plugins/clangtools/documentclangtoolrunner.cpp index 3de2c6d55cf..93cd27bac38 100644 --- a/src/plugins/clangtools/documentclangtoolrunner.cpp +++ b/src/plugins/clangtools/documentclangtoolrunner.cpp @@ -190,7 +190,7 @@ void DocumentClangToolRunner::run() vfso().update(); const ClangDiagnosticConfig config = diagnosticConfig(runSettings.diagnosticConfigId()); const Environment env = projectBuildEnvironment(project); - QList tasks{parallel}; + QList tasks{parallel}; const auto addClangTool = [this, &runSettings, &config, &env, &tasks](ClangToolType tool) { if (!toolEnabled(tool, config, runSettings)) return; diff --git a/src/plugins/coreplugin/locator/ilocatorfilter.cpp b/src/plugins/coreplugin/locator/ilocatorfilter.cpp index 3a84a0b548b..0a4665361d2 100644 --- a/src/plugins/coreplugin/locator/ilocatorfilter.cpp +++ b/src/plugins/coreplugin/locator/ilocatorfilter.cpp @@ -450,7 +450,7 @@ void LocatorMatcher::start() collectorStorage->m_collector = nullptr; }; - QList parallelTasks {parallelLimit(d->m_parallelLimit)}; + QList parallelTasks {parallelLimit(d->m_parallelLimit)}; const auto onSetup = [this, collectorStorage](const TreeStorage &storage, int index) { @@ -597,7 +597,7 @@ QString ILocatorFilter::shortcutString() const \internal Sets the refresh recipe for refreshing cached data. */ -void ILocatorFilter::setRefreshRecipe(const std::optional &recipe) +void ILocatorFilter::setRefreshRecipe(const std::optional &recipe) { m_refreshRecipe = recipe; } @@ -606,7 +606,7 @@ void ILocatorFilter::setRefreshRecipe(const std::optional &recipe) Returns the refresh recipe for refreshing cached data. By default, the locator filter has no recipe set, so that it won't be refreshed. */ -std::optional ILocatorFilter::refreshRecipe() const +std::optional ILocatorFilter::refreshRecipe() const { return m_refreshRecipe; } diff --git a/src/plugins/coreplugin/locator/ilocatorfilter.h b/src/plugins/coreplugin/locator/ilocatorfilter.h index b008c12bb5c..fbc68bc647c 100644 --- a/src/plugins/coreplugin/locator/ilocatorfilter.h +++ b/src/plugins/coreplugin/locator/ilocatorfilter.h @@ -139,7 +139,7 @@ class CORE_EXPORT LocatorMatcherTask final public: // The main task. Initial data (searchTerm) should be taken from storage.input(). // Results reporting is done via the storage.reportOutput(). - Tasking::TaskItem task = Tasking::Group{}; + Tasking::GroupItem task = Tasking::Group{}; // When constructing the task, don't place the storage inside the task above. Tasking::TreeStorage storage; @@ -270,8 +270,8 @@ protected: virtual void saveState(QJsonObject &object) const; virtual void restoreState(const QJsonObject &object); - void setRefreshRecipe(const std::optional &recipe); - std::optional refreshRecipe() const; + void setRefreshRecipe(const std::optional &recipe); + std::optional refreshRecipe() const; static bool isOldSetting(const QByteArray &state); @@ -289,7 +289,7 @@ private: QString m_description; QString m_defaultShortcut; std::optional m_defaultSearchText; - std::optional m_refreshRecipe; + std::optional m_refreshRecipe; QKeySequence m_defaultKeySequence; bool m_defaultIncludedByDefault = false; bool m_includedByDefault = m_defaultIncludedByDefault; diff --git a/src/plugins/coreplugin/locator/locator.cpp b/src/plugins/coreplugin/locator/locator.cpp index 2deaef9fe09..cefce35a5b1 100644 --- a/src/plugins/coreplugin/locator/locator.cpp +++ b/src/plugins/coreplugin/locator/locator.cpp @@ -381,7 +381,7 @@ void Locator::refresh(const QList &filters) m_refreshingFilters = Utils::filteredUnique(m_refreshingFilters + filters); using namespace Tasking; - QList tasks{parallel}; + QList tasks{parallel}; for (ILocatorFilter *filter : std::as_const(m_refreshingFilters)) { const auto task = filter->refreshRecipe(); if (!task.has_value()) diff --git a/src/plugins/cppeditor/cppprojectupdater.cpp b/src/plugins/cppeditor/cppprojectupdater.cpp index c92d091396e..e4b57c90c5a 100644 --- a/src/plugins/cppeditor/cppprojectupdater.cpp +++ b/src/plugins/cppeditor/cppprojectupdater.cpp @@ -64,7 +64,7 @@ void CppProjectUpdater::update(const ProjectUpdateInfo &projectUpdateInfo, if (async.isResultAvailable()) storage->projectInfo = async.result(); }; - QList tasks{parallel}; + QList tasks{parallel}; tasks.append(AsyncTask(setupInfoGenerator, onInfoGeneratorDone)); for (QPointer compiler : compilers) { if (compiler && compiler->isDirty()) diff --git a/src/plugins/diffeditor/diffeditorplugin.cpp b/src/plugins/diffeditor/diffeditorplugin.cpp index 99ceef2f0ab..867217d86d8 100644 --- a/src/plugins/diffeditor/diffeditorplugin.cpp +++ b/src/plugins/diffeditor/diffeditorplugin.cpp @@ -128,7 +128,7 @@ DiffFilesController::DiffFilesController(IDocument *document) outputList->resize(inputList.size()); using namespace std::placeholders; - QList tasks {parallel, finishAllAndDone}; + QList tasks {parallel, finishAllAndDone}; for (int i = 0; i < inputList.size(); ++i) { tasks.append(AsyncTask(std::bind(setupDiff, _1, inputList.at(i)), std::bind(onDiffDone, _1, i))); diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 935b56291ff..4f2bdc4912a 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -441,7 +441,7 @@ ShowController::ShowController(IDocument *document, const QString &id) }; using namespace std::placeholders; - QList tasks {parallel, continueOnDone, onGroupError(onFollowsError)}; + QList tasks {parallel, continueOnDone, onGroupError(onFollowsError)}; for (int i = 0, total = parents.size(); i < total; ++i) { tasks.append(ProcessTask(std::bind(setupFollow, _1, parents.at(i)), std::bind(onFollowDone, _1, i))); diff --git a/src/plugins/projectexplorer/extracompiler.cpp b/src/plugins/projectexplorer/extracompiler.cpp index 67bb4a63fc3..bbd34a798fa 100644 --- a/src/plugins/projectexplorer/extracompiler.cpp +++ b/src/plugins/projectexplorer/extracompiler.cpp @@ -137,7 +137,7 @@ QThreadPool *ExtraCompiler::extraCompilerThreadPool() return s_extraCompilerThreadPool(); } -TaskItem ExtraCompiler::compileFileItem() +GroupItem ExtraCompiler::compileFileItem() { return taskItemImpl(fromFileProvider()); } @@ -326,7 +326,7 @@ ProcessExtraCompiler::ProcessExtraCompiler(const Project *project, const FilePat ExtraCompiler(project, source, targets, parent) { } -TaskItem ProcessExtraCompiler::taskItemImpl(const ContentProvider &provider) +GroupItem ProcessExtraCompiler::taskItemImpl(const ContentProvider &provider) { const auto setupTask = [=](Async &async) { async.setThreadPool(extraCompilerThreadPool()); diff --git a/src/plugins/projectexplorer/extracompiler.h b/src/plugins/projectexplorer/extracompiler.h index 1dbda0e4242..82bd9070f25 100644 --- a/src/plugins/projectexplorer/extracompiler.h +++ b/src/plugins/projectexplorer/extracompiler.h @@ -24,7 +24,7 @@ class QPromise; class QThreadPool; QT_END_NAMESPACE -namespace Tasking { class TaskItem; } +namespace Tasking { class GroupItem; } namespace Utils { class Process; } namespace ProjectExplorer { @@ -49,7 +49,7 @@ public: Utils::FilePaths targets() const; void forEachTarget(std::function func) const; - Tasking::TaskItem compileFileItem(); + Tasking::GroupItem compileFileItem(); void compileFile(); bool isDirty() const; void block(); @@ -75,7 +75,7 @@ private: void compileContent(const QByteArray &content); void compileImpl(const ContentProvider &provider); void compileIfDirty(); - virtual Tasking::TaskItem taskItemImpl(const ContentProvider &provider) = 0; + virtual Tasking::GroupItem taskItemImpl(const ContentProvider &provider) = 0; const std::unique_ptr d; }; @@ -101,7 +101,7 @@ protected: virtual Tasks parseIssues(const QByteArray &stdErr); private: - Tasking::TaskItem taskItemImpl(const ContentProvider &provider) final; + Tasking::GroupItem taskItemImpl(const ContentProvider &provider) final; void runInThread(QPromise &promise, const Utils::FilePath &cmd, const Utils::FilePath &workDir, const QStringList &args, const ContentProvider &provider, diff --git a/src/plugins/qmakeprojectmanager/qmakestep.cpp b/src/plugins/qmakeprojectmanager/qmakestep.cpp index 0da8bebaad2..27e29e497e8 100644 --- a/src/plugins/qmakeprojectmanager/qmakestep.cpp +++ b/src/plugins/qmakeprojectmanager/qmakestep.cpp @@ -330,7 +330,7 @@ void QMakeStep::doRun() emit buildConfiguration()->buildDirectoryInitialized(); }; - QList processList = {ProcessTask(setupQMake, onProcessDone, onProcessError)}; + QList processList = {ProcessTask(setupQMake, onProcessDone, onProcessError)}; if (m_runMakeQmake) processList << ProcessTask(setupMakeQMake, onProcessDone, onProcessError); processList << onGroupDone(onDone); diff --git a/src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp b/src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp index a5cc9cdad86..d9eb88273e6 100644 --- a/src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp +++ b/src/plugins/qnx/qnxdeployqtlibrariesdialog.cpp @@ -90,11 +90,11 @@ public: private: Group deployRecipe(); - TaskItem checkDirTask(); - TaskItem removeDirTask(); - TaskItem uploadTask(); - TaskItem chmodTask(const DeployableFile &file); - TaskItem chmodTree(); + GroupItem checkDirTask(); + GroupItem removeDirTask(); + GroupItem uploadTask(); + GroupItem chmodTask(const DeployableFile &file); + GroupItem chmodTree(); enum class CheckResult { RemoveDir, SkipRemoveDir, Abort }; CheckResult m_checkResult = CheckResult::Abort; @@ -117,7 +117,7 @@ QList collectFilesToUpload(const DeployableFile &deployable) return collected; } -TaskItem QnxDeployQtLibrariesDialogPrivate::checkDirTask() +GroupItem QnxDeployQtLibrariesDialogPrivate::checkDirTask() { const auto setupHandler = [this](Process &process) { m_deployLogWindow->appendPlainText(Tr::tr("Checking existence of \"%1\"") @@ -145,7 +145,7 @@ TaskItem QnxDeployQtLibrariesDialogPrivate::checkDirTask() return ProcessTask(setupHandler, doneHandler, errorHandler); } -TaskItem QnxDeployQtLibrariesDialogPrivate::removeDirTask() +GroupItem QnxDeployQtLibrariesDialogPrivate::removeDirTask() { const auto setupHandler = [this](Process &process) { if (m_checkResult != CheckResult::RemoveDir) @@ -162,7 +162,7 @@ TaskItem QnxDeployQtLibrariesDialogPrivate::removeDirTask() return ProcessTask(setupHandler, {}, errorHandler); } -TaskItem QnxDeployQtLibrariesDialogPrivate::uploadTask() +GroupItem QnxDeployQtLibrariesDialogPrivate::uploadTask() { const auto setupHandler = [this](FileTransfer &transfer) { if (m_deployableFiles.isEmpty()) { @@ -196,7 +196,7 @@ TaskItem QnxDeployQtLibrariesDialogPrivate::uploadTask() return FileTransferTask(setupHandler, {}, errorHandler); } -TaskItem QnxDeployQtLibrariesDialogPrivate::chmodTask(const DeployableFile &file) +GroupItem QnxDeployQtLibrariesDialogPrivate::chmodTask(const DeployableFile &file) { const auto setupHandler = [=](Process &process) { process.setCommand({m_device->filePath("chmod"), @@ -215,7 +215,7 @@ TaskItem QnxDeployQtLibrariesDialogPrivate::chmodTask(const DeployableFile &file return ProcessTask(setupHandler, {}, errorHandler); } -TaskItem QnxDeployQtLibrariesDialogPrivate::chmodTree() +GroupItem QnxDeployQtLibrariesDialogPrivate::chmodTree() { const auto setupChmodHandler = [=](TaskTree &tree) { QList filesToChmod; @@ -223,7 +223,7 @@ TaskItem QnxDeployQtLibrariesDialogPrivate::chmodTree() if (file.isExecutable()) filesToChmod << file; } - QList chmodList{finishAllAndDone, parallelLimit(MaxConcurrentStatCalls)}; + QList chmodList{finishAllAndDone, parallelLimit(MaxConcurrentStatCalls)}; for (const DeployableFile &file : std::as_const(filesToChmod)) { QTC_ASSERT(file.isValid(), continue); chmodList.append(chmodTask(file)); diff --git a/src/plugins/remotelinux/genericdirectuploadstep.cpp b/src/plugins/remotelinux/genericdirectuploadstep.cpp index 6074eaabaaf..714404ec5b7 100644 --- a/src/plugins/remotelinux/genericdirectuploadstep.cpp +++ b/src/plugins/remotelinux/genericdirectuploadstep.cpp @@ -75,13 +75,13 @@ public: using FilesToStat = std::function(UploadStorage *)>; using StatEndHandler = std::function; - TaskItem statTask(UploadStorage *storage, const DeployableFile &file, - StatEndHandler statEndHandler); - TaskItem statTree(const TreeStorage &storage, FilesToStat filesToStat, - StatEndHandler statEndHandler); - TaskItem uploadTask(const TreeStorage &storage); - TaskItem chmodTask(const DeployableFile &file); - TaskItem chmodTree(const TreeStorage &storage); + GroupItem statTask(UploadStorage *storage, const DeployableFile &file, + StatEndHandler statEndHandler); + GroupItem statTree(const TreeStorage &storage, FilesToStat filesToStat, + StatEndHandler statEndHandler); + GroupItem uploadTask(const TreeStorage &storage); + GroupItem chmodTask(const DeployableFile &file); + GroupItem chmodTree(const TreeStorage &storage); IncrementalDeployment m_incremental = IncrementalDeployment::NotSupported; bool m_ignoreMissingFiles = false; @@ -156,9 +156,9 @@ QDateTime GenericDirectUploadStep::timestampFromStat(const DeployableFile &file, return QDateTime::fromSecsSinceEpoch(secsSinceEpoch); } -TaskItem GenericDirectUploadStep::statTask(UploadStorage *storage, - const DeployableFile &file, - StatEndHandler statEndHandler) +GroupItem GenericDirectUploadStep::statTask(UploadStorage *storage, + const DeployableFile &file, + StatEndHandler statEndHandler) { const auto setupHandler = [=](Process &process) { // We'd like to use --format=%Y, but it's not supported by busybox. @@ -173,13 +173,13 @@ TaskItem GenericDirectUploadStep::statTask(UploadStorage *storage, return ProcessTask(setupHandler, endHandler, endHandler); } -TaskItem GenericDirectUploadStep::statTree(const TreeStorage &storage, - FilesToStat filesToStat, StatEndHandler statEndHandler) +GroupItem GenericDirectUploadStep::statTree(const TreeStorage &storage, + FilesToStat filesToStat, StatEndHandler statEndHandler) { const auto setupHandler = [=](TaskTree &tree) { UploadStorage *storagePtr = storage.activeStorage(); const QList files = filesToStat(storagePtr); - QList statList{finishAllAndDone, parallelLimit(MaxConcurrentStatCalls)}; + QList statList{finishAllAndDone, parallelLimit(MaxConcurrentStatCalls)}; for (const DeployableFile &file : std::as_const(files)) { QTC_ASSERT(file.isValid(), continue); statList.append(statTask(storagePtr, file, statEndHandler)); @@ -189,7 +189,7 @@ TaskItem GenericDirectUploadStep::statTree(const TreeStorage &sto return TaskTreeTask(setupHandler); } -TaskItem GenericDirectUploadStep::uploadTask(const TreeStorage &storage) +GroupItem GenericDirectUploadStep::uploadTask(const TreeStorage &storage) { const auto setupHandler = [this, storage](FileTransfer &transfer) { if (storage->filesToUpload.isEmpty()) { @@ -229,7 +229,7 @@ TaskItem GenericDirectUploadStep::uploadTask(const TreeStorage &s return FileTransferTask(setupHandler, {}, errorHandler); } -TaskItem GenericDirectUploadStep::chmodTask(const DeployableFile &file) +GroupItem GenericDirectUploadStep::chmodTask(const DeployableFile &file) { const auto setupHandler = [=](Process &process) { process.setCommand({deviceConfiguration()->filePath("chmod"), @@ -248,7 +248,7 @@ TaskItem GenericDirectUploadStep::chmodTask(const DeployableFile &file) return ProcessTask(setupHandler, {}, errorHandler); } -TaskItem GenericDirectUploadStep::chmodTree(const TreeStorage &storage) +GroupItem GenericDirectUploadStep::chmodTree(const TreeStorage &storage) { const auto setupChmodHandler = [=](TaskTree &tree) { QList filesToChmod; @@ -256,7 +256,7 @@ TaskItem GenericDirectUploadStep::chmodTree(const TreeStorage &st if (file.isExecutable()) filesToChmod << file; } - QList chmodList{finishAllAndDone, parallelLimit(MaxConcurrentStatCalls)}; + QList chmodList{finishAllAndDone, parallelLimit(MaxConcurrentStatCalls)}; for (const DeployableFile &file : std::as_const(filesToChmod)) { QTC_ASSERT(file.isValid(), continue); chmodList.append(chmodTask(file)); diff --git a/src/plugins/remotelinux/linuxdevicetester.cpp b/src/plugins/remotelinux/linuxdevicetester.cpp index 37aea361123..5392fb4245c 100644 --- a/src/plugins/remotelinux/linuxdevicetester.cpp +++ b/src/plugins/remotelinux/linuxdevicetester.cpp @@ -34,20 +34,20 @@ public: QStringList commandsToTest() const; - TaskItem echoTask(const QString &contents) const; - TaskItem unameTask() const; - TaskItem gathererTask() const; - TaskItem transferTask(FileTransferMethod method, - const TreeStorage &storage) const; - TaskItem transferTasks() const; - TaskItem commandTask(const QString &commandName) const; - TaskItem commandTasks() const; + GroupItem echoTask(const QString &contents) const; + GroupItem unameTask() const; + GroupItem gathererTask() const; + GroupItem transferTask(FileTransferMethod method, + const TreeStorage &storage) const; + GroupItem transferTasks() const; + GroupItem commandTask(const QString &commandName) const; + GroupItem commandTasks() const; GenericLinuxDeviceTester *q = nullptr; IDevice::Ptr m_device; std::unique_ptr m_taskTree; QStringList m_extraCommands; - QList m_extraTests; + QList m_extraTests; }; QStringList GenericLinuxDeviceTesterPrivate::commandsToTest() const @@ -90,7 +90,7 @@ QStringList GenericLinuxDeviceTesterPrivate::commandsToTest() const return commands; } -TaskItem GenericLinuxDeviceTesterPrivate::echoTask(const QString &contents) const +GroupItem GenericLinuxDeviceTesterPrivate::echoTask(const QString &contents) const { const auto setup = [this, contents](Process &process) { emit q->progressMessage(Tr::tr("Sending echo to device...")); @@ -114,7 +114,7 @@ TaskItem GenericLinuxDeviceTesterPrivate::echoTask(const QString &contents) cons return ProcessTask(setup, done, error); } -TaskItem GenericLinuxDeviceTesterPrivate::unameTask() const +GroupItem GenericLinuxDeviceTesterPrivate::unameTask() const { const auto setup = [this](Process &process) { emit q->progressMessage(Tr::tr("Checking kernel version...")); @@ -136,7 +136,7 @@ TaskItem GenericLinuxDeviceTesterPrivate::unameTask() const }; } -TaskItem GenericLinuxDeviceTesterPrivate::gathererTask() const +GroupItem GenericLinuxDeviceTesterPrivate::gathererTask() const { const auto setup = [this](DeviceUsedPortsGatherer &gatherer) { emit q->progressMessage(Tr::tr("Checking if specified ports are available...")); @@ -164,8 +164,8 @@ TaskItem GenericLinuxDeviceTesterPrivate::gathererTask() const }; } -TaskItem GenericLinuxDeviceTesterPrivate::transferTask(FileTransferMethod method, - const TreeStorage &storage) const +GroupItem GenericLinuxDeviceTesterPrivate::transferTask(FileTransferMethod method, + const TreeStorage &storage) const { const auto setup = [this, method](FileTransfer &transfer) { emit q->progressMessage(Tr::tr("Checking whether \"%1\" works...") @@ -216,7 +216,7 @@ TaskItem GenericLinuxDeviceTesterPrivate::transferTask(FileTransferMethod method return FileTransferTestTask(setup, done, error); } -TaskItem GenericLinuxDeviceTesterPrivate::transferTasks() const +GroupItem GenericLinuxDeviceTesterPrivate::transferTasks() const { TreeStorage storage; return Group { @@ -231,7 +231,7 @@ TaskItem GenericLinuxDeviceTesterPrivate::transferTasks() const }; } -TaskItem GenericLinuxDeviceTesterPrivate::commandTask(const QString &commandName) const +GroupItem GenericLinuxDeviceTesterPrivate::commandTask(const QString &commandName) const { const auto setup = [this, commandName](Process &process) { emit q->progressMessage(Tr::tr("%1...").arg(commandName)); @@ -252,9 +252,9 @@ TaskItem GenericLinuxDeviceTesterPrivate::commandTask(const QString &commandName return ProcessTask(setup, done, error); } -TaskItem GenericLinuxDeviceTesterPrivate::commandTasks() const +GroupItem GenericLinuxDeviceTesterPrivate::commandTasks() const { - QList tasks {continueOnError}; + QList tasks {continueOnError}; tasks.append(onGroupSetup([this] { emit q->progressMessage(Tr::tr("Checking if required commands are available...")); })); @@ -279,7 +279,7 @@ void GenericLinuxDeviceTester::setExtraCommandsToTest(const QStringList &extraCo d->m_extraCommands = extraCommands; } -void GenericLinuxDeviceTester::setExtraTests(const QList &extraTests) +void GenericLinuxDeviceTester::setExtraTests(const QList &extraTests) { d->m_extraTests = extraTests; } @@ -295,7 +295,7 @@ void GenericLinuxDeviceTester::testDevice(const IDevice::Ptr &deviceConfiguratio d->m_taskTree.release()->deleteLater(); }; - QList taskItems = { + QList taskItems = { d->echoTask("Hello"), // No quoting necessary d->echoTask("Hello Remote World!"), // Checks quoting, too. d->unameTask(), diff --git a/src/plugins/remotelinux/linuxdevicetester.h b/src/plugins/remotelinux/linuxdevicetester.h index 3fda1ecb3a2..787d22fd109 100644 --- a/src/plugins/remotelinux/linuxdevicetester.h +++ b/src/plugins/remotelinux/linuxdevicetester.h @@ -7,7 +7,7 @@ #include -namespace Tasking { class TaskItem; } +namespace Tasking { class GroupItem; } namespace RemoteLinux { @@ -22,7 +22,7 @@ public: ~GenericLinuxDeviceTester() override; void setExtraCommandsToTest(const QStringList &extraCommands); - void setExtraTests(const QList &extraTests); + void setExtraTests(const QList &extraTests); void testDevice(const ProjectExplorer::IDevice::Ptr &deviceConfiguration) override; void stopTest() override; diff --git a/src/plugins/remotelinux/rsyncdeploystep.cpp b/src/plugins/remotelinux/rsyncdeploystep.cpp index 84eb47b8cc1..317b08bb77c 100644 --- a/src/plugins/remotelinux/rsyncdeploystep.cpp +++ b/src/plugins/remotelinux/rsyncdeploystep.cpp @@ -35,8 +35,8 @@ public: private: bool isDeploymentNecessary() const final; Group deployRecipe() final; - TaskItem mkdirTask(); - TaskItem transferTask(); + GroupItem mkdirTask(); + GroupItem transferTask(); mutable FilesToTransfer m_files; bool m_ignoreMissingFiles = false; @@ -85,7 +85,7 @@ bool RsyncDeployStep::isDeploymentNecessary() const return !m_files.empty(); } -TaskItem RsyncDeployStep::mkdirTask() +GroupItem RsyncDeployStep::mkdirTask() { const auto setupHandler = [this](Process &process) { QStringList remoteDirs; @@ -113,7 +113,7 @@ TaskItem RsyncDeployStep::mkdirTask() return ProcessTask(setupHandler, {}, errorHandler); } -TaskItem RsyncDeployStep::transferTask() +GroupItem RsyncDeployStep::transferTask() { const auto setupHandler = [this](FileTransfer &transfer) { transfer.setTransferMethod(FileTransferMethod::Rsync); diff --git a/src/plugins/remotelinux/tarpackagedeploystep.cpp b/src/plugins/remotelinux/tarpackagedeploystep.cpp index 6b50ca4dced..6deaea90662 100644 --- a/src/plugins/remotelinux/tarpackagedeploystep.cpp +++ b/src/plugins/remotelinux/tarpackagedeploystep.cpp @@ -55,8 +55,8 @@ private: QString remoteFilePath() const; bool isDeploymentNecessary() const final; Group deployRecipe() final; - TaskItem uploadTask(); - TaskItem installTask(); + GroupItem uploadTask(); + GroupItem installTask(); FilePath m_packageFilePath; }; @@ -71,7 +71,7 @@ bool TarPackageDeployStep::isDeploymentNecessary() const return hasLocalFileChanged(DeployableFile(m_packageFilePath, {})); } -TaskItem TarPackageDeployStep::uploadTask() +GroupItem TarPackageDeployStep::uploadTask() { const auto setupHandler = [this](FileTransfer &transfer) { const FilesToTransfer files {{m_packageFilePath, @@ -90,7 +90,7 @@ TaskItem TarPackageDeployStep::uploadTask() return FileTransferTask(setupHandler, doneHandler, errorHandler); } -TaskItem TarPackageDeployStep::installTask() +GroupItem TarPackageDeployStep::installTask() { const auto setupHandler = [this](Process &process) { const QString cmdLine = QLatin1String("cd / && tar xvf ") + remoteFilePath() diff --git a/src/plugins/updateinfo/updateinfoplugin.cpp b/src/plugins/updateinfo/updateinfoplugin.cpp index 749cbbbec64..4891d9e8fdf 100644 --- a/src/plugins/updateinfo/updateinfoplugin.cpp +++ b/src/plugins/updateinfo/updateinfoplugin.cpp @@ -135,7 +135,7 @@ void UpdateInfoPlugin::startCheckForUpdates() d->m_updateOutput = process.cleanedStdOut(); }; - QList tasks { ProcessTask(setupUpdate, updateDone) }; + QList tasks { ProcessTask(setupUpdate, updateDone) }; if (d->m_settings.checkForQtVersions) { const auto setupPackages = [doSetup](Process &process) { doSetup(process, {"se", "qt[.]qt[0-9][.][0-9]+$", "-g", "*=false,ifw.package.*=true"}); diff --git a/src/plugins/vcsbase/vcsbasediffeditorcontroller.cpp b/src/plugins/vcsbase/vcsbasediffeditorcontroller.cpp index 696e96b2916..b60abaeb5f5 100644 --- a/src/plugins/vcsbase/vcsbasediffeditorcontroller.cpp +++ b/src/plugins/vcsbase/vcsbasediffeditorcontroller.cpp @@ -45,7 +45,7 @@ TreeStorage VcsBaseDiffEditorController::inputStorage() const return d->m_inputStorage; } -TaskItem VcsBaseDiffEditorController::postProcessTask() +GroupItem VcsBaseDiffEditorController::postProcessTask() { const auto setupDiffProcessor = [this](Async> &async) { const QString *storage = inputStorage().activeStorage(); diff --git a/src/plugins/vcsbase/vcsbasediffeditorcontroller.h b/src/plugins/vcsbase/vcsbasediffeditorcontroller.h index 63976bc26cb..e4b88805065 100644 --- a/src/plugins/vcsbase/vcsbasediffeditorcontroller.h +++ b/src/plugins/vcsbase/vcsbasediffeditorcontroller.h @@ -29,7 +29,7 @@ public: protected: Tasking::TreeStorage inputStorage() const; - Tasking::TaskItem postProcessTask(); + Tasking::GroupItem postProcessTask(); void setupCommand(Utils::Process &process, const QStringList &args) const; diff --git a/tests/auto/solutions/tasking/tst_tasking.cpp b/tests/auto/solutions/tasking/tst_tasking.cpp index 294bea71b7e..69d87e8188e 100644 --- a/tests/auto/solutions/tasking/tst_tasking.cpp +++ b/tests/auto/solutions/tasking/tst_tasking.cpp @@ -197,8 +197,8 @@ public: TASKING_DECLARE_TASK(TickAndDoneTask, TickAndDoneTaskAdapter); template -TaskItem createBarrierAdvance(const TreeStorage &storage, - const SharedBarrierType &barrier, int taskId) +GroupItem createBarrierAdvance(const TreeStorage &storage, + const SharedBarrierType &barrier, int taskId) { return TickAndDoneTask([storage, barrier, taskId](TickAndDone &tickAndDone) { tickAndDone.setInterval(1ms); @@ -253,7 +253,7 @@ void tst_Tasking::testTree_data() }; const auto createTask = [storage, setupTask, setupDone, setupError]( - int taskId, bool successTask, milliseconds timeout = 0ms) -> TaskItem { + int taskId, bool successTask, milliseconds timeout = 0ms) -> GroupItem { if (successTask) return TestTask(setupTask(taskId, timeout), setupDone(taskId), setupError(taskId)); const Group root { diff --git a/tests/auto/utils/async/tst_async.cpp b/tests/auto/utils/async/tst_async.cpp index 5d4a81dc961..0e8bc1e2b03 100644 --- a/tests/auto/utils/async/tst_async.cpp +++ b/tests/auto/utils/async/tst_async.cpp @@ -500,7 +500,7 @@ void tst_Async::mapReduce_data() using SetupHandler = std::function &task, int input)>; using DoneHandler = std::function; - const auto createTask = [=](const TaskItem &executeMode, + const auto createTask = [=](const GroupItem &executeMode, const SetupHandler &setupHandler, const DoneHandler &doneHandler) { return Group { diff --git a/tests/manual/subdirfileiterator/tst_subdirfileiterator.cpp b/tests/manual/subdirfileiterator/tst_subdirfileiterator.cpp index 882a9993a26..50bbd222c9a 100644 --- a/tests/manual/subdirfileiterator/tst_subdirfileiterator.cpp +++ b/tests/manual/subdirfileiterator/tst_subdirfileiterator.cpp @@ -128,7 +128,7 @@ private slots: async.setConcurrentCallData(generate, parentPath, templateFile, s_treeDepth); }; }; - QList tasks {parallel}; + QList tasks {parallel}; for (int i = 0; i < tasksCount; ++i) { const QString dirName = QString("%1%2").arg(s_dirPrefix).arg(i); QVERIFY(parentDir.mkdir(dirName)); @@ -153,7 +153,7 @@ private slots: async.setConcurrentCallData(removeTree, parentPath); }; }; - QList tasks {parallel}; + QList tasks {parallel}; const int tasksCount = QThread::idealThreadCount(); for (int i = 0; i < tasksCount; ++i) { const QString dirName = QString("%1%2").arg(s_dirPrefix).arg(i); diff --git a/tests/manual/tasking/demo/main.cpp b/tests/manual/tasking/demo/main.cpp index c4b885efe2f..807def8e454 100644 --- a/tests/manual/tasking/demo/main.cpp +++ b/tests/manual/tasking/demo/main.cpp @@ -163,7 +163,7 @@ int main(int argc, char *argv[]) std::unique_ptr taskTree; - const auto createTask = [](TaskWidget *widget) -> TaskItem { + const auto createTask = [](TaskWidget *widget) -> GroupItem { const auto setupTask = [](TaskWidget *widget) { return [widget](milliseconds &taskObject) { taskObject = milliseconds{widget->busyTime() * 1000}; diff --git a/tests/manual/tasking/demo/taskwidget.cpp b/tests/manual/tasking/demo/taskwidget.cpp index 6bc68db1a1b..97d3d2b9ef7 100644 --- a/tests/manual/tasking/demo/taskwidget.cpp +++ b/tests/manual/tasking/demo/taskwidget.cpp @@ -158,7 +158,7 @@ void GroupWidget::updateExecuteMode() m_executeCombo->setCurrentIndex(m_executeCombo->findData((int)m_executeMode)); } -TaskItem GroupWidget::executeMode() const +GroupItem GroupWidget::executeMode() const { return m_executeMode == ExecuteMode::Sequential ? sequential : parallel; } @@ -174,7 +174,7 @@ void GroupWidget::updateWorkflowPolicy() m_workflowCombo->setCurrentIndex(m_workflowCombo->findData((int)m_workflowPolicy)); } -TaskItem GroupWidget::workflowPolicy() const +GroupItem GroupWidget::workflowPolicy() const { return Tasking::workflowPolicy(m_workflowPolicy); } diff --git a/tests/manual/tasking/demo/taskwidget.h b/tests/manual/tasking/demo/taskwidget.h index 3ce210eb0d4..a737e315a4e 100644 --- a/tests/manual/tasking/demo/taskwidget.h +++ b/tests/manual/tasking/demo/taskwidget.h @@ -62,10 +62,10 @@ public: GroupWidget(); void setExecuteMode(ExecuteMode mode); - Tasking::TaskItem executeMode() const; + Tasking::GroupItem executeMode() const; void setWorkflowPolicy(Tasking::WorkflowPolicy policy); - Tasking::TaskItem workflowPolicy() const; + Tasking::GroupItem workflowPolicy() const; private: void updateExecuteMode(); From 0a1073f7cdcef6303ca01afd472838af5a6530b7 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Fri, 2 Jun 2023 11:22:47 +0200 Subject: [PATCH 132/141] ClangCodeModel: Restart clangd on changes in VCS repository This should prevent the index from becoming stale after e.g. a git checkout. Change-Id: I94d364d3f2ec38889564c7859ca95ccb2de3019d Reviewed-by: Christian Stenger Reviewed-by: Reviewed-by: Qt CI Bot Reviewed-by: Qt CI Patch Build Bot --- .../clangmodelmanagersupport.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp index 42e77c11a34..a14fb81b901 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -686,6 +687,7 @@ void ClangModelManagerSupport::claimNonProjectSources(ClangdClient *client) // for the respective project to force re-parsing of open documents and re-indexing. // While this is not 100% bullet-proof, chances are good that in a typical session-based // workflow, e.g. a git branch switch will hit at least one open file. +// We also look for repository changes explicitly. void ClangModelManagerSupport::watchForExternalChanges() { connect(DocumentManager::instance(), &DocumentManager::filesChangedExternally, @@ -709,6 +711,23 @@ void ClangModelManagerSupport::watchForExternalChanges() return; } }); + + connect(VcsManager::instance(), &VcsManager::repositoryChanged, + this, [this](const FilePath &repoDir) { + if (sessionModeEnabled()) { + if (ClangdClient * const client = clientForProject(nullptr)) + scheduleClientRestart(client); + return; + } + for (const Project * const project : ProjectManager::projects()) { + const FilePath &projectDir = project->projectDirectory(); + if (repoDir == projectDir || repoDir.isChildOf(projectDir) + || projectDir.isChildOf(repoDir)) { + if (ClangdClient * const client = clientForProject(project)) + scheduleClientRestart(client); + } + } + }); } // If Qt Creator changes a file that is not open (e.g. as part of a quickfix), we have to From b3e51d62428efa807d7d41919fcf7595421fc3db Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Mon, 5 Jun 2023 11:19:13 +0200 Subject: [PATCH 133/141] ProjectExplorer: Fix build progress icon alignment The build progress warnings/error icons were not vertically centered. That was noticeable with the "Relaxed" toobar style. Fixes: QTCREATORBUG-29252 Change-Id: I921ccc936c3233b2b2f80979aaae2b09709dbcff Reviewed-by: Eike Ziller --- src/plugins/projectexplorer/buildprogress.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/projectexplorer/buildprogress.cpp b/src/plugins/projectexplorer/buildprogress.cpp index a78b8a1b79d..7166ab474d9 100644 --- a/src/plugins/projectexplorer/buildprogress.cpp +++ b/src/plugins/projectexplorer/buildprogress.cpp @@ -60,8 +60,8 @@ BuildProgress::BuildProgress(TaskWindow *taskWindow, Qt::Orientation orientation m_errorLabel->setProperty("_q_custom_style_disabled", QVariant(true)); m_warningLabel->setProperty("_q_custom_style_disabled", QVariant(true)); - m_errorIcon->setAlignment(Qt::AlignRight); - m_warningIcon->setAlignment(Qt::AlignRight); + m_errorIcon->setAlignment(Qt::AlignRight | Qt::AlignVCenter); + m_warningIcon->setAlignment(Qt::AlignRight | Qt::AlignVCenter); m_errorIcon->setPixmap(Utils::Icons::CRITICAL_TOOLBAR.pixmap()); m_warningIcon->setPixmap(Utils::Icons::WARNING_TOOLBAR.pixmap()); From beaf86f9deb219565da0c1b92e727d3138cf6526 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Tue, 6 Jun 2023 09:23:14 +0200 Subject: [PATCH 134/141] Python: filepathify python project path for saving Change-Id: Ibcea9de6c8844cb826b61aa40357890153923854 Reviewed-by: hjk --- src/plugins/python/pythonproject.cpp | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/plugins/python/pythonproject.cpp b/src/plugins/python/pythonproject.cpp index a29847ac7bc..86afde46e8b 100644 --- a/src/plugins/python/pythonproject.cpp +++ b/src/plugins/python/pythonproject.cpp @@ -52,12 +52,12 @@ public: QString name() const override { return QLatin1String("python"); } bool saveRawFileList(const QStringList &rawFileList); - bool saveRawList(const QStringList &rawList, const QString &fileName); + bool saveRawList(const QStringList &rawList, const FilePath &filePath); void parse(); QStringList processEntries(const QStringList &paths, QHash *map = nullptr) const; - bool writePyProjectFile(const QString &fileName, QString &content, + bool writePyProjectFile(const FilePath &filePath, QString &content, const QStringList &rawList, QString *errorMessage); void triggerParsing() final; @@ -268,25 +268,24 @@ void PythonBuildSystem::triggerParsing() bool PythonBuildSystem::saveRawFileList(const QStringList &rawFileList) { - const bool result = saveRawList(rawFileList, projectFilePath().toString()); + const bool result = saveRawList(rawFileList, projectFilePath()); // refresh(PythonProject::Files); return result; } -bool PythonBuildSystem::saveRawList(const QStringList &rawList, const QString &fileName) +bool PythonBuildSystem::saveRawList(const QStringList &rawList, const FilePath &filePath) { - const FilePath filePath = FilePath::fromString(fileName); - FileChangeBlocker changeGuarg(filePath); + const FileChangeBlocker changeGuarg(filePath); bool result = false; // New project file - if (fileName.endsWith(".pyproject")) { + if (filePath.endsWith(".pyproject")) { FileSaver saver(filePath, QIODevice::ReadOnly | QIODevice::Text); if (!saver.hasError()) { QString content = QTextStream(saver.file()).readAll(); if (saver.finalize(ICore::dialogParent())) { QString errorMessage; - result = writePyProjectFile(fileName, content, rawList, &errorMessage); + result = writePyProjectFile(filePath, content, rawList, &errorMessage); if (!errorMessage.isEmpty()) MessageManager::writeDisrupting(errorMessage); } @@ -305,13 +304,13 @@ bool PythonBuildSystem::saveRawList(const QStringList &rawList, const QString &f return result; } -bool PythonBuildSystem::writePyProjectFile(const QString &fileName, QString &content, - const QStringList &rawList, QString *errorMessage) +bool PythonBuildSystem::writePyProjectFile(const FilePath &filePath, QString &content, + const QStringList &rawList, QString *errorMessage) { - QFile file(fileName); + QFile file(filePath.toString()); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { - *errorMessage = Tr::tr("Unable to open \"%1\" for reading: %2") - .arg(fileName, file.errorString()); + *errorMessage = Tr::tr("Unable to open \"%1\" for writing: %2") + .arg(filePath.toUserOutput(), file.errorString()); return false; } From d617b046c6d2405f2adddbfb0381fc2dc9ee4060 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Tue, 6 Jun 2023 09:34:24 +0200 Subject: [PATCH 135/141] Python: support remote file paths when loading projects Change-Id: I94f709275d3b226685439ac55d58b029d3323d12 Reviewed-by: hjk --- src/plugins/python/pythonproject.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/plugins/python/pythonproject.cpp b/src/plugins/python/pythonproject.cpp index 86afde46e8b..e9d503037d0 100644 --- a/src/plugins/python/pythonproject.cpp +++ b/src/plugins/python/pythonproject.cpp @@ -90,14 +90,13 @@ private: static QJsonObject readObjJson(const FilePath &projectFile, QString *errorMessage) { - QFile file(projectFile.toString()); - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - *errorMessage = Tr::tr("Unable to open \"%1\" for reading: %2") - .arg(projectFile.toUserOutput(), file.errorString()); - return QJsonObject(); + const expected_str fileContentsResult = projectFile.fileContents(); + if (!fileContentsResult) { + *errorMessage = fileContentsResult.error(); + return {}; } - const QByteArray content = file.readAll(); + const QByteArray content = *fileContentsResult; // This assumes the project file is formed with only one field called // 'files' that has a list associated of the files to include in the project. From a81c9b497a8a0f58f0920d1f4039d82cea4430b9 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 6 Jun 2023 13:43:13 +0200 Subject: [PATCH 136/141] Tests: Fix qbs build Change-Id: Ia4a54bab4208c5cdf1c7ce67f5caab84aa1583ef Reviewed-by: Christian Stenger --- tests/manual/manual.qbs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/manual/manual.qbs b/tests/manual/manual.qbs index fecd79518c5..35d08815d26 100644 --- a/tests/manual/manual.qbs +++ b/tests/manual/manual.qbs @@ -15,7 +15,7 @@ Project { "shootout/shootout.qbs", "subdirfileiterator/subdirfileiterator.qbs", "tasking/demo/demo.qbs", - "tasking/demo/imagescaling.qbs", + "tasking/imagescaling/imagescaling.qbs", "widgets/widgets.qbs", ] } From 9cc9ec2aec1a6de499737cdd1f021384e320a997 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20L=C3=B6hning?= Date: Thu, 20 Apr 2023 23:54:17 +0200 Subject: [PATCH 137/141] SquishTests: Remove workaround for fixed bug Task-number: QTCREATORBUG-28985 Change-Id: Ib69ccd0f967484a9858ddebdf08a376035e42e90 Reviewed-by: Christian Stenger --- tests/system/suite_QMLS/tst_QMLS04/test.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/tests/system/suite_QMLS/tst_QMLS04/test.py b/tests/system/suite_QMLS/tst_QMLS04/test.py index 2c96939151d..435d993cb2a 100644 --- a/tests/system/suite_QMLS/tst_QMLS04/test.py +++ b/tests/system/suite_QMLS/tst_QMLS04/test.py @@ -48,12 +48,10 @@ def main(): pass # open MyComponent.qml file for verification docOpened = openDocument(myCompTE) - # Work around QTCREATORBUG-28985 - test.xverify(docOpened, "Was MyComponent.qml properly generated in project explorer?") - saveAndExit() - return - # The workaround will be removed in master branch - # Following dead code left in intentionally to still allow merging forward changes in it. + if not test.verify(docOpened, "Was MyComponent.qml properly generated in project explorer?"): + test.fatal("Could not open MyComponent.qml.") + saveAndExit() + return editorArea = waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget") codeText = str(editorArea.plainText) # there should be Text item in new file From 1348f0cfe07866bc61df1aa23e7ad54d278299de Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Tue, 6 Jun 2023 11:07:40 +0200 Subject: [PATCH 138/141] Doc: Fix description of Add Class Member refactoring action The developer must enter the data type of the member only if automatic detection fails. Change-Id: I51c1f36aeb34fb6560701cbd30a5748be5f1cde0 Reviewed-by: Reviewed-by: Christian Kandeler --- doc/qtcreator/src/editors/creator-quick-fixes.qdoc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/qtcreator/src/editors/creator-quick-fixes.qdoc b/doc/qtcreator/src/editors/creator-quick-fixes.qdoc index 57bb973bb28..0f6e7fd58af 100644 --- a/doc/qtcreator/src/editors/creator-quick-fixes.qdoc +++ b/doc/qtcreator/src/editors/creator-quick-fixes.qdoc @@ -482,8 +482,9 @@ \row \li Add Class Member \li Adds a member declaration for the class member being - initialized if it is not yet declared. You must enter - the data type of the member. + initialized if it is not yet declared. If \QC cannot + automatically detect the data type of the member, you + must add it. \li Identifier \row \li Create Implementations for Member Functions From 9b6ff3fb36ac796f0c4e9f5af3d361fb1460fca7 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 1 Jun 2023 14:30:06 +0200 Subject: [PATCH 139/141] Vcs: Use PagedSettings for common settings Also restrict the Reset VCS Cache button to the second column, as it was earlier. Change-Id: I291fdceb11df4ecdfdc0887fd521288d0b4544f3 Reviewed-by: Christian Stenger Reviewed-by: --- src/plugins/vcsbase/commonvcssettings.cpp | 103 ++++++++------------ src/plugins/vcsbase/commonvcssettings.h | 21 +--- src/plugins/vcsbase/vcsbaseplugin.cpp | 2 +- src/plugins/vcsbase/vcsbasesubmiteditor.cpp | 20 ++-- src/plugins/vcsbase/vcsplugin.cpp | 14 +-- src/plugins/vcsbase/vcsplugin.h | 5 - 6 files changed, 54 insertions(+), 111 deletions(-) diff --git a/src/plugins/vcsbase/commonvcssettings.cpp b/src/plugins/vcsbase/commonvcssettings.cpp index d286164b5b9..e0c4ba4af62 100644 --- a/src/plugins/vcsbase/commonvcssettings.cpp +++ b/src/plugins/vcsbase/commonvcssettings.cpp @@ -6,18 +6,13 @@ #include "vcsbaseconstants.h" #include "vcsbasetr.h" -#include -#include #include -#include #include #include #include -#include -#include - +using namespace Core; using namespace Utils; namespace VcsBase::Internal { @@ -33,10 +28,24 @@ static QString sshPasswordPromptDefault() return QLatin1String("ssh-askpass"); } +static CommonVcsSettings *s_instance; + +CommonVcsSettings &commonSettings() +{ + return *s_instance; +} + CommonVcsSettings::CommonVcsSettings() { + s_instance = this; + setSettingsGroup("VCS"); - setAutoApply(false); + setId(Constants::VCS_COMMON_SETTINGS_ID); + setDisplayName(Tr::tr("General")); + setCategory(Constants::VCS_SETTINGS_CATEGORY); + // The following act as blueprint for other pages in the same category: + setDisplayCategory(Tr::tr("Version Control")); + setCategoryIconPath(":/vcsbase/images/settingscategory_vcs.png"); nickNameMailMap.setSettingsKey("NickNameMailMap"); nickNameMailMap.setExpectedKind(PathChooser::File); @@ -76,69 +85,37 @@ CommonVcsSettings::CommonVcsSettings() lineWrapWidth.setSettingsKey("LineWrapWidth"); lineWrapWidth.setSuffix(Tr::tr(" characters")); lineWrapWidth.setDefaultValue(72); -} - -// CommonSettingsWidget - -class CommonSettingsWidget final : public Core::IOptionsPageWidget -{ -public: - CommonSettingsWidget(CommonOptionsPage *page) - { - CommonVcsSettings &s = page->settings(); - - auto cacheResetButton = new QPushButton(Tr::tr("Reset VCS Cache")); - cacheResetButton->setToolTip(Tr::tr("Reset information about which " - "version control system handles which directory.")); - - auto updatePath = [&s] { - Environment env; - env.appendToPath(Core::VcsManager::additionalToolsPath()); - s.sshPasswordPrompt.setEnvironment(env); - }; + setLayouter([this] { using namespace Layouting; - Column { - Row { s.lineWrap, s.lineWrapWidth, st }, + return Column { + Row { lineWrap, lineWrapWidth, st }, Form { - s.submitMessageCheckScript, br, - s.nickNameMailMap, br, - s.nickNameFieldListFile, br, - s.sshPasswordPrompt, br, - {}, cacheResetButton + submitMessageCheckScript, br, + nickNameMailMap, br, + nickNameFieldListFile, br, + sshPasswordPrompt, br, + empty, + PushButton { + text(Tr::tr("Reset VCS Cache")), + tooltip(Tr::tr("Reset information about which " + "version control system handles which directory.")), + onClicked(&VcsManager::clearVersionControlCache) + } } - }.attachTo(this); + }; + }); - updatePath(); + auto updatePath = [this] { + Environment env; + env.appendToPath(VcsManager::additionalToolsPath()); + sshPasswordPrompt.setEnvironment(env); + }; - connect(Core::VcsManager::instance(), &Core::VcsManager::configurationChanged, - this, updatePath); - connect(cacheResetButton, &QPushButton::clicked, - Core::VcsManager::instance(), &Core::VcsManager::clearVersionControlCache); + updatePath(); + connect(VcsManager::instance(), &VcsManager::configurationChanged, this, updatePath); - setOnApply([&s] { - if (s.isDirty()) { - s.apply(); - s.writeSettings(Core::ICore::settings()); - emit s.settingsChanged(); - } - }); - } -}; - -// CommonOptionsPage - -CommonOptionsPage::CommonOptionsPage() -{ - m_settings.readSettings(Core::ICore::settings()); - - setId(Constants::VCS_COMMON_SETTINGS_ID); - setDisplayName(Tr::tr("General")); - setCategory(Constants::VCS_SETTINGS_CATEGORY); - // The following act as blueprint for other pages in the same category: - setDisplayCategory(Tr::tr("Version Control")); - setCategoryIconPath(":/vcsbase/images/settingscategory_vcs.png"); - setWidgetCreator([this] { return new CommonSettingsWidget(this); }); + readSettings(); } } // VcsBase::Internal diff --git a/src/plugins/vcsbase/commonvcssettings.h b/src/plugins/vcsbase/commonvcssettings.h index a5005f252a5..0f591b27111 100644 --- a/src/plugins/vcsbase/commonvcssettings.h +++ b/src/plugins/vcsbase/commonvcssettings.h @@ -4,15 +4,12 @@ #pragma once #include - -#include +#include namespace VcsBase::Internal { -class CommonVcsSettings : public Utils::AspectContainer +class CommonVcsSettings : public Core::PagedSettings { - Q_OBJECT - public: CommonVcsSettings(); @@ -26,20 +23,8 @@ public: Utils::BoolAspect lineWrap{this}; Utils::IntegerAspect lineWrapWidth{this}; - -signals: - void settingsChanged(); }; -class CommonOptionsPage final : public Core::IOptionsPage -{ -public: - CommonOptionsPage(); - - CommonVcsSettings &settings() { return m_settings; } - -private: - CommonVcsSettings m_settings; -}; +CommonVcsSettings &commonSettings(); } // VcsBase::Internal diff --git a/src/plugins/vcsbase/vcsbaseplugin.cpp b/src/plugins/vcsbase/vcsbaseplugin.cpp index b72657cdb3c..b73f97dd79c 100644 --- a/src/plugins/vcsbase/vcsbaseplugin.cpp +++ b/src/plugins/vcsbase/vcsbaseplugin.cpp @@ -750,7 +750,7 @@ FilePath source(IDocument *document) void setProcessEnvironment(Environment *e) { - const QString prompt = Internal::VcsPlugin::instance()->settings().sshPasswordPrompt.value(); + const QString prompt = Internal::commonSettings().sshPasswordPrompt().path(); if (!prompt.isEmpty()) e->set("SSH_ASKPASS", prompt); } diff --git a/src/plugins/vcsbase/vcsbasesubmiteditor.cpp b/src/plugins/vcsbase/vcsbasesubmiteditor.cpp index 5ddab0da77f..03eaa49c857 100644 --- a/src/plugins/vcsbase/vcsbasesubmiteditor.cpp +++ b/src/plugins/vcsbase/vcsbasesubmiteditor.cpp @@ -103,11 +103,6 @@ namespace VcsBase { using namespace Internal; using namespace Utils; -static inline QString submitMessageCheckScript() -{ - return VcsPlugin::instance()->settings().submitMessageCheckScript.value(); -} - class VcsBaseSubmitEditorPrivate { public: @@ -176,15 +171,15 @@ void VcsBaseSubmitEditor::setParameters(const VcsBaseSubmitEditorParameters &par connect(descriptionEdit, &QTextEdit::textChanged, this, &VcsBaseSubmitEditor::fileContentsChanged); - const CommonVcsSettings &settings = VcsPlugin::instance()->settings(); + const CommonVcsSettings &settings = commonSettings(); // Add additional context menu settings - if (!settings.submitMessageCheckScript.value().isEmpty() + if (!settings.submitMessageCheckScript().isEmpty() || !settings.nickNameMailMap.value().isEmpty()) { auto sep = new QAction(this); sep->setSeparator(true); d->m_widget->addDescriptionEditContextMenuAction(sep); // Run check action - if (!settings.submitMessageCheckScript.value().isEmpty()) { + if (!settings.submitMessageCheckScript().isEmpty()) { auto checkAction = new QAction(Tr::tr("Check Message"), this); connect(checkAction, &QAction::triggered, this, &VcsBaseSubmitEditor::slotCheckSubmitMessage); @@ -203,7 +198,7 @@ void VcsBaseSubmitEditor::setParameters(const VcsBaseSubmitEditorParameters &par // wrapping. etc slotUpdateEditorSettings(); - connect(VcsPlugin::instance(), &VcsPlugin::settingsChanged, + connect(&settings, &CommonVcsSettings::changed, this, &VcsBaseSubmitEditor::slotUpdateEditorSettings); connect(Core::EditorManager::instance(), &Core::EditorManager::currentEditorChanged, this, [this] { @@ -229,9 +224,8 @@ VcsBaseSubmitEditor::~VcsBaseSubmitEditor() void VcsBaseSubmitEditor::slotUpdateEditorSettings() { - const CommonVcsSettings &s = VcsPlugin::instance()->settings(); - setLineWrapWidth(s.lineWrapWidth()); - setLineWrap(s.lineWrap()); + setLineWrapWidth(commonSettings().lineWrapWidth()); + setLineWrap(commonSettings().lineWrap()); } // Return a trimmed list of non-empty field texts @@ -527,7 +521,7 @@ void VcsBaseSubmitEditor::slotCheckSubmitMessage() bool VcsBaseSubmitEditor::checkSubmitMessage(QString *errorMessage) const { - const QString checkScript = submitMessageCheckScript(); + const QString checkScript = commonSettings().submitMessageCheckScript.value(); if (checkScript.isEmpty()) return true; QApplication::setOverrideCursor(Qt::WaitCursor); diff --git a/src/plugins/vcsbase/vcsplugin.cpp b/src/plugins/vcsbase/vcsplugin.cpp index 0596f406b8b..c61c8e0bec0 100644 --- a/src/plugins/vcsbase/vcsplugin.cpp +++ b/src/plugins/vcsbase/vcsplugin.cpp @@ -40,7 +40,7 @@ public: explicit VcsPluginPrivate(VcsPlugin *plugin) : q(plugin) { - QObject::connect(&m_settingsPage.settings(), &CommonVcsSettings::settingsChanged, + QObject::connect(&m_settings, &AspectContainer::changed, [this] { slotSettingsChanged(); }); slotSettingsChanged(); } @@ -57,7 +57,7 @@ public: void populateNickNameModel() { QString errorMessage; - if (!NickNameDialog::populateModelFromMailCapFile(m_settingsPage.settings().nickNameMailMap.filePath(), + if (!NickNameDialog::populateModelFromMailCapFile(m_settings.nickNameMailMap(), m_nickNameModel, &errorMessage)) { qWarning("%s", qPrintable(errorMessage)); @@ -71,7 +71,7 @@ public: } VcsPlugin *q; - CommonOptionsPage m_settingsPage; + CommonVcsSettings m_settings; QStandardItemModel *m_nickNameModel = nullptr; }; @@ -101,9 +101,6 @@ void VcsPlugin::initialize() return result; }); - connect(&d->m_settingsPage.settings(), &CommonVcsSettings::settingsChanged, - this, &VcsPlugin::settingsChanged); - JsonWizardFactory::registerPageFactory(new Internal::VcsConfigurationPageFactory); JsonWizardFactory::registerPageFactory(new Internal::VcsCommandPageFactory); @@ -146,11 +143,6 @@ VcsPlugin *VcsPlugin::instance() return m_instance; } -CommonVcsSettings &VcsPlugin::settings() const -{ - return d->m_settingsPage.settings(); -} - /* Delayed creation/update of the nick name model. */ QStandardItemModel *VcsPlugin::nickNameModel() { diff --git a/src/plugins/vcsbase/vcsplugin.h b/src/plugins/vcsbase/vcsplugin.h index 6d4b35c11fd..44be10b23e0 100644 --- a/src/plugins/vcsbase/vcsplugin.h +++ b/src/plugins/vcsbase/vcsplugin.h @@ -15,8 +15,6 @@ class VcsBaseSubmitEditor; namespace Internal { -class CommonVcsSettings; - class VcsPlugin : public ExtensionSystem::IPlugin { Q_OBJECT @@ -30,15 +28,12 @@ public: static VcsPlugin *instance(); - CommonVcsSettings &settings() const; - // Model of user nick names used for the submit // editor. Stored centrally here to achieve delayed // initialization and updating on settings change. QStandardItemModel *nickNameModel(); signals: - void settingsChanged(); void submitEditorAboutToClose(VcsBase::VcsBaseSubmitEditor *e, bool *result); private: From 1c2cf83c697d66069c6b51d614caea79d74e04eb Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 31 May 2023 17:11:05 +0200 Subject: [PATCH 140/141] QmlDesigner: Inline assetexportdialog.ui Change-Id: Ie22beaf507fcf146bcd3c5d228cafa33941425d8 Reviewed-by: Alessandro Portale --- src/plugins/qmldesigner/CMakeLists.txt | 2 +- .../assetexporterplugin/assetexportdialog.cpp | 120 +++++++++++------- .../assetexporterplugin/assetexportdialog.h | 22 ++-- .../assetexporterplugin/assetexportdialog.ui | 81 ------------ 4 files changed, 90 insertions(+), 135 deletions(-) delete mode 100644 src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.ui diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt index 8cffad60f1e..30c93baca78 100644 --- a/src/plugins/qmldesigner/CMakeLists.txt +++ b/src/plugins/qmldesigner/CMakeLists.txt @@ -1096,7 +1096,7 @@ extend_qtc_plugin(assetexporterplugin extend_qtc_plugin(assetexporterplugin SOURCES_PREFIX assetexporterplugin SOURCES - assetexportdialog.h assetexportdialog.cpp assetexportdialog.ui + assetexportdialog.h assetexportdialog.cpp assetexporter.h assetexporter.cpp assetexporterplugin.h assetexporterplugin.cpp assetexporterview.h assetexporterview.cpp diff --git a/src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.cpp b/src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.cpp index e9b5ab7082b..64845068970 100644 --- a/src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.cpp +++ b/src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.cpp @@ -1,19 +1,24 @@ // Copyright (C) 2020 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + #include "assetexportdialog.h" -#include "ui_assetexportdialog.h" +#include "../qmldesignertr.h" #include "assetexportpluginconstants.h" #include "filepathmodel.h" #include #include + #include #include #include #include -#include + +#include +#include #include +#include #include #include @@ -22,13 +27,21 @@ #include #include #include +#include +#include +#include +#include #include #include -namespace { -static void addFormattedMessage(Utils::OutputFormatter *formatter, const QString &str, - Utils::OutputFormat format) { +using namespace ProjectExplorer; +using namespace Utils; + +namespace QmlDesigner { + +static void addFormattedMessage(OutputFormatter *formatter, const QString &str, OutputFormat format) +{ if (!formatter) return; @@ -42,79 +55,81 @@ static void addFormattedMessage(Utils::OutputFormatter *formatter, const QString if (isAtBottom) scroll->setValue(scroll->maximum()); } -} -using namespace ProjectExplorer; - -namespace QmlDesigner { -AssetExportDialog::AssetExportDialog(const Utils::FilePath &exportPath, +AssetExportDialog::AssetExportDialog(const FilePath &exportPath, AssetExporter &assetExporter, FilePathModel &model, QWidget *parent) : QDialog(parent), m_assetExporter(assetExporter), m_filePathModel(model), - m_ui(new Ui::AssetExportDialog), m_filesView(new QListView), m_exportLogs(new QPlainTextEdit), m_outputFormatter(new Utils::OutputFormatter()) { - m_ui->setupUi(this); + resize(768, 480); + setWindowTitle(Tr::tr("Export Components")); - m_ui->exportPath->setExpectedKind(Utils::PathChooser::Kind::SaveFile); - m_ui->exportPath->setFilePath( + m_stackedWidget = new QStackedWidget; + + m_exportProgress = new QProgressBar; + m_exportProgress->setRange(0,0); + + auto optionsWidget = new QWidget; + + auto advancedOptions = new DetailsWidget; + advancedOptions->setSummaryText(tr("Advanced Options")); + advancedOptions->setWidget(optionsWidget); + + m_buttonBox = new QDialogButtonBox; + m_buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Close); + + m_exportPath = new PathChooser; + m_exportPath->setExpectedKind(PathChooser::Kind::SaveFile); + m_exportPath->setFilePath( exportPath.pathAppended( ProjectExplorer::ProjectManager::startupProject()->displayName() + ".metadata" )); - m_ui->exportPath->setPromptDialogTitle(tr("Choose Export File")); - m_ui->exportPath->setPromptDialogFilter(tr("Metadata file (*.metadata)")); - m_ui->exportPath->lineEdit()->setReadOnly(true); - m_ui->exportPath->addButton(tr("Open"), this, [this]() { - Core::FileUtils::showInGraphicalShell(Core::ICore::dialogParent(), m_ui->exportPath->filePath()); + m_exportPath->setPromptDialogTitle(tr("Choose Export File")); + m_exportPath->setPromptDialogFilter(tr("Metadata file (*.metadata)")); + m_exportPath->lineEdit()->setReadOnly(true); + m_exportPath->addButton(tr("Open"), this, [this]() { + Core::FileUtils::showInGraphicalShell(Core::ICore::dialogParent(), m_exportPath->filePath()); }); - auto optionsWidget = new QWidget; - m_ui->advancedOptions->setSummaryText(tr("Advanced Options")); - m_ui->advancedOptions->setWidget(optionsWidget); - auto optionsLayout = new QHBoxLayout(optionsWidget); - optionsLayout->setContentsMargins(8, 8, 8, 8); - m_exportAssetsCheck = new QCheckBox(tr("Export assets"), this); m_exportAssetsCheck->setChecked(true); - optionsLayout->addWidget(m_exportAssetsCheck); m_perComponentExportCheck = new QCheckBox(tr("Export components separately"), this); m_perComponentExportCheck->setChecked(false); - optionsLayout->addWidget(m_perComponentExportCheck); - optionsLayout->addStretch(); - m_ui->buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(false); + m_buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(false); - m_ui->stackedWidget->addWidget(m_filesView); + m_stackedWidget->addWidget(m_filesView); m_filesView->setModel(&m_filePathModel); m_exportLogs->setReadOnly(true); m_outputFormatter->setPlainTextEdit(m_exportLogs); - m_ui->stackedWidget->addWidget(m_exportLogs); + m_stackedWidget->addWidget(m_exportLogs); switchView(false); - connect(m_ui->buttonBox->button(QDialogButtonBox::Cancel), &QPushButton::clicked, [this]() { - m_ui->buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(false); + connect(m_buttonBox->button(QDialogButtonBox::Cancel), &QPushButton::clicked, [this]() { + m_buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(false); m_assetExporter.cancel(); }); - m_exportBtn = m_ui->buttonBox->addButton(tr("Export"), QDialogButtonBox::AcceptRole); + m_exportBtn = m_buttonBox->addButton(tr("Export"), QDialogButtonBox::AcceptRole); m_exportBtn->setEnabled(false); connect(m_exportBtn, &QPushButton::clicked, this, &AssetExportDialog::onExport); connect(&m_filePathModel, &FilePathModel::modelReset, this, [this]() { - m_ui->exportProgress->setRange(0, 1000); - m_ui->exportProgress->setValue(0); + m_exportProgress->setRange(0, 1000); + m_exportProgress->setValue(0); m_exportBtn->setEnabled(true); }); - connect(m_ui->buttonBox->button(QDialogButtonBox::Close), &QPushButton::clicked, [this]() { + connect(m_buttonBox->button(QDialogButtonBox::Close), &QPushButton::clicked, [this]() { close(); }); - m_ui->buttonBox->button(QDialogButtonBox::Close)->setVisible(false); + m_buttonBox->button(QDialogButtonBox::Close)->setVisible(false); connect(&m_assetExporter, &AssetExporter::stateChanged, this, &AssetExportDialog::onExportStateChanged); @@ -123,7 +138,22 @@ AssetExportDialog::AssetExportDialog(const Utils::FilePath &exportPath, connect(TaskHub::instance(), &TaskHub::taskAdded, this, &AssetExportDialog::onTaskAdded); - m_ui->exportProgress->setRange(0,0); + using namespace Layouting; + + Column { + m_exportAssetsCheck, + m_perComponentExportCheck, + st, + noMargin(), + }.attachTo(optionsWidget); + + Column { + Form { Tr::tr("Export path:"), m_exportPath }, + advancedOptions, + m_stackedWidget, + m_exportProgress, + m_buttonBox, + }.attachTo(this); } AssetExportDialog::~AssetExportDialog() @@ -139,7 +169,7 @@ void AssetExportDialog::onExport() TaskHub::clearTasks(Constants::TASK_CATEGORY_ASSET_EXPORT); m_exportLogs->clear(); - Utils::FilePath selectedPath = m_ui->exportPath->filePath(); + Utils::FilePath selectedPath = m_exportPath->filePath(); Utils::FilePath exportPath = m_perComponentExportCheck->isChecked() ? (selectedPath.isDir() ? selectedPath : selectedPath.parentDir()) : selectedPath; @@ -154,28 +184,28 @@ void AssetExportDialog::onExportStateChanged(AssetExporter::ParsingState newStat switch (newState) { case AssetExporter::ParsingState::ExportingDone: m_exportBtn->setVisible(false); - m_ui->buttonBox->button(QDialogButtonBox::Close)->setVisible(true); + m_buttonBox->button(QDialogButtonBox::Close)->setVisible(true); break; default: break; } m_exportBtn->setEnabled(newState == AssetExporter::ParsingState::ExportingDone); - m_ui->buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(m_assetExporter.isBusy()); + m_buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(m_assetExporter.isBusy()); } void AssetExportDialog::updateExportProgress(double value) { value = std::max(0.0, std::min(1.0, value)); - m_ui->exportProgress->setValue(std::round(value * 1000)); + m_exportProgress->setValue(std::round(value * 1000)); } void AssetExportDialog::switchView(bool showExportView) { if (showExportView) - m_ui->stackedWidget->setCurrentWidget(m_exportLogs); + m_stackedWidget->setCurrentWidget(m_exportLogs); else - m_ui->stackedWidget->setCurrentWidget(m_filesView); + m_stackedWidget->setCurrentWidget(m_filesView); } void AssetExportDialog::onTaskAdded(const ProjectExplorer::Task &task) diff --git a/src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.h b/src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.h index dacab052d41..bf277f82bbe 100644 --- a/src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.h +++ b/src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.h @@ -1,25 +1,28 @@ // Copyright (C) 2020 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + #pragma once + #include "assetexporter.h" +#include + #include #include -#include "utils/fileutils.h" - -#include - QT_BEGIN_NAMESPACE class QPushButton; class QCheckBox; +class QDialogButtonBox; class QListView; class QPlainTextEdit; +class QProgressBar; +class QStackedWidget; QT_END_NAMESPACE - namespace Utils { class OutputFormatter; +class PathChooser; } namespace ProjectExplorer { @@ -27,7 +30,7 @@ class Task; } namespace QmlDesigner { -namespace Ui { class AssetExportDialog; } + class FilePathModel; class AssetExportDialog : public QDialog @@ -49,13 +52,16 @@ private: private: AssetExporter &m_assetExporter; FilePathModel &m_filePathModel; - std::unique_ptr m_ui; QPushButton *m_exportBtn = nullptr; QCheckBox *m_exportAssetsCheck = nullptr; QCheckBox *m_perComponentExportCheck = nullptr; QListView *m_filesView = nullptr; QPlainTextEdit *m_exportLogs = nullptr; Utils::OutputFormatter *m_outputFormatter = nullptr; + Utils::PathChooser *m_exportPath = nullptr; + QDialogButtonBox *m_buttonBox = nullptr; + QStackedWidget *m_stackedWidget = nullptr; + QProgressBar *m_exportProgress = nullptr; }; -} +} // QmlDesigner diff --git a/src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.ui b/src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.ui deleted file mode 100644 index fa807588676..00000000000 --- a/src/plugins/qmldesigner/assetexporterplugin/assetexportdialog.ui +++ /dev/null @@ -1,81 +0,0 @@ - - - QmlDesigner::AssetExportDialog - - - - 0 - 0 - 768 - 480 - - - - Export Components - - - - - - - 0 - 0 - - - - Export path: - - - - - - - - - - 1000 - - - 0 - - - - - - - - 0 - 8 - - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Close - - - - - - - - - - - Utils::PathChooser - QWidget -
utils/pathchooser.h
- 1 -
- - Utils::DetailsWidget - QWidget -
utils/detailswidget.h
- 1 -
-
- - -
From 414e15617725df3e64364ff40c1970994c7a9fa0 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Tue, 6 Jun 2023 13:28:02 +0200 Subject: [PATCH 141/141] Markdown: Set focus to text editor at start Take two. Amends d9e3d32a80497fbef98073b06f1eaf9bf5811587 Change-Id: Ib3680df9ea7954e00326be2aee71ed2862a74a6e Reviewed-by: Reviewed-by: Christian Stenger --- src/plugins/texteditor/markdowneditor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/texteditor/markdowneditor.cpp b/src/plugins/texteditor/markdowneditor.cpp index 9c89636df8e..90ca41283ec 100644 --- a/src/plugins/texteditor/markdowneditor.cpp +++ b/src/plugins/texteditor/markdowneditor.cpp @@ -30,7 +30,7 @@ const char MARKDOWNVIEWER_MIME_TYPE[] = "text/markdown"; const char MARKDOWNVIEWER_TEXTEDITOR_RIGHT[] = "Markdown.TextEditorRight"; const char MARKDOWNVIEWER_SHOW_EDITOR[] = "Markdown.ShowEditor"; const char MARKDOWNVIEWER_SHOW_PREVIEW[] = "Markdown.ShowPreview"; -const bool kTextEditorRightDefault = true; +const bool kTextEditorRightDefault = false; const bool kShowEditorDefault = true; const bool kShowPreviewDefault = true; @@ -67,8 +67,8 @@ public: context->setContext(Core::Context(MARKDOWNVIEWER_TEXT_CONTEXT)); Core::ICore::addContextObject(context); + m_splitter->addWidget(m_textEditorWidget); // sets splitter->focusWidget() on non-Windows m_splitter->addWidget(m_previewWidget); - m_splitter->addWidget(m_textEditorWidget); setContext(Core::Context(MARKDOWNVIEWER_ID));